mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-11-05 15:58:19 +00:00
Use document views in file processing and history
Replace broad entry inputs with the information used by file processing, history, and JSON comparison. Separate customisation content and save-base results from database-document models, and keep content fields out of logical-deletion Metadata while preserving the parent revision. Record the accepted design, compatibility boundaries, and verification. Requires Commonlib commit 751b29a74340da57122b8ab11b80d00c40272120. The registry dependency remains at 0.2.3 pending publication and adoption.
This commit is contained in:
1 parent
0fe7d82f46
commit
80ce481575
17 files changed
+1036
-159
No files matched your search
@@ -0,0 +1,149 @@
|
||||
---
|
||||
date: 2026-11-03
|
||||
commonlib-version: "0.2.3"
|
||||
self-hosted-livesync-version: "1.0.44"
|
||||
status: accepted-unreleased
|
||||
---
|
||||
|
||||
# Architectural Decision Record: Separate Document Representations and Operation Contracts
|
||||
|
||||
## Status
|
||||
|
||||
Accepted, with an unreleased local implementation. The investigated baseline
|
||||
is Self-hosted LiveSync `1.0.44` with Commonlib `0.2.3`. Implementation review
|
||||
also examined Commonlib `0.3.0`; the original baseline is retained. The
|
||||
[design document](../design_docs/document_and_chunk_type_contracts.md#implementation-decisions-and-remaining-work)
|
||||
records the selected API surface, compatibility staging, and remaining work.
|
||||
|
||||
The review reproduced a difference between direct and path reads of the
|
||||
oldest inline format. Its repair was explicitly approved: path reads retain
|
||||
the inline body until the existing legacy reconstruction runs. DFM path and
|
||||
ID admission policies also remain distinct, and existing content-interpretation
|
||||
rules retain differing `type` and `datatype` inputs.
|
||||
|
||||
The proposal complements the accepted
|
||||
[Commonlib package boundary](2026_07_common_library_package_boundary.md).
|
||||
It does not replace the current [data-structure reference](../datastructure.md),
|
||||
[Chunk retrieval contract](../design_docs/chunk_retrieval_and_waiting.md), or
|
||||
[revision-provenance contract](../specs_conflict_resolution.md).
|
||||
|
||||
## Context
|
||||
|
||||
The document types combine persisted file formats, compatibility formats,
|
||||
save inputs, reconstructed content, and PouchDB response information through
|
||||
overlapping unions and intersections. Several names are structurally
|
||||
equivalent. `LoadedEntry` can describe a Metadata-only result with placeholder
|
||||
content, while `SavingEntry` inherits fields which the save operation has not
|
||||
yet produced.
|
||||
|
||||
Functions which only inspect paths or deletion markers require complete entry
|
||||
types. Other boundaries declare content which their callers do not provide.
|
||||
Type assertions bridge those mismatches without explaining the actual
|
||||
preconditions and results of the operation.
|
||||
|
||||
DFM defines its own current `MetaEntry` and `ReadyEntry`. Its array-content
|
||||
guarantee differs from the broader Commonlib `LoadedEntry`, and the return
|
||||
types do not express the relationship between `metaOnly` and content
|
||||
availability. Replacing one name with another would change those guarantees.
|
||||
|
||||
Some guards claim a complete document after checking only a discriminator,
|
||||
property presence, or an ID prefix. Other apparently weak checks preserve an
|
||||
intentional compatibility contract: the Chunk response classifier accepts ID
|
||||
and content without requiring a `leaf` discriminator. A uniform strict
|
||||
validator would change accepted behaviour.
|
||||
|
||||
The [design document](../design_docs/document_and_chunk_type_contracts.md)
|
||||
records the pinned source evidence, current relationships, function matrix,
|
||||
and verification requirements.
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. Share information views and distinguish operation contracts
|
||||
|
||||
Keep small interfaces for shared identity, path, file attributes, and deletion
|
||||
state. Functions accept those views when that information is sufficient.
|
||||
Use unions for document alternatives and composed types for complete operation
|
||||
inputs and results. Do not convert every object type alias to an interface.
|
||||
|
||||
Separate save inputs and content reconstruction results from stored-document
|
||||
variants. A content-bearing value may satisfy a Metadata information view,
|
||||
but that view does not establish that the whole value is suitable for storage.
|
||||
Keep explicit construction of persisted Metadata and separate Chunk content.
|
||||
|
||||
Distinguish an identified value from a revision-bearing response, a logical
|
||||
deletion from a tombstone, and a decoded application value from raw transport
|
||||
input. Document unions state their store or transport scope; they do not
|
||||
implicitly grant replication or reflection eligibility.
|
||||
|
||||
### 2. Align Commonlib, DFM, and consumer boundaries
|
||||
|
||||
Commonlib owns canonical shared types, validators, normalisation, reconstruction,
|
||||
and the DFM contracts. DFM and Self-hosted LiveSync use those definitions rather
|
||||
than maintaining parallel domain models. Product-specific projections remain
|
||||
with their owning consumer.
|
||||
|
||||
Retain DFM's current array-content guarantee and distinguish Metadata selection
|
||||
from content callbacks. Express the relationship between a read mode and its
|
||||
result. Keep compatibility names or adapters where they preserve an existing
|
||||
contract; do not widen guarantees merely to collapse names.
|
||||
|
||||
Preserve current-state re-reading in ordinary reflection and the explicit
|
||||
selected-revision contract in history restoration. Check every maintained
|
||||
service handler before narrowing a shared callback.
|
||||
|
||||
### 3. Validate only what the resulting type promises
|
||||
|
||||
Use shared validators with detailed failures, Boolean guards, and assertion
|
||||
wrappers as appropriate. A discriminator-only guard operates on an already
|
||||
validated union; validation of unknown input establishes every property which
|
||||
its result promises.
|
||||
|
||||
Keep decoding and compatibility normalisation as value-producing operations.
|
||||
Successful reconstruction produces the content result. A shape assertion
|
||||
cannot certify that content was fetched, persisted, or matched to the Vault.
|
||||
Revision freshness, ancestry, provenance, and destructive-operation authority
|
||||
remain with the existing authoritative checks and rechecks.
|
||||
|
||||
Preserve accepted legacy and minimal retrieval inputs. Any stricter acceptance
|
||||
rule or canonicalisation with observable effects is a separate behavioural
|
||||
decision, not an incidental consequence of a type refactor.
|
||||
|
||||
### 4. Migrate through the package boundary
|
||||
|
||||
Implement shared contracts in the Commonlib repository, validate its exact
|
||||
packed artefact, and update the consumer's exact dependency before integrating
|
||||
the corresponding Self-hosted LiveSync changes. Retain the agreed public and
|
||||
compatibility contracts during migration. This decision adds no persistent
|
||||
state, wire-format change, automatic repair, or database migration.
|
||||
|
||||
## Alternatives considered
|
||||
|
||||
| Alternative | Assessment |
|
||||
| --- | --- |
|
||||
| Rename or convert declarations without changing contracts | Leaves placeholder content, redundant save fields, and overstated predicates in place. |
|
||||
| Retain one entry hierarchy for every processing stage | Continues to make save inputs and loaded content appear to be stored-document variants. |
|
||||
| Give every helper a complete document union | Requires unrelated fields and encourages casts at information-only boundaries. |
|
||||
| Use one strict assertion for every incoming document | Conflates raw and decoded shapes, rejects supported compatibility inputs, and mishandles body-less tombstones. |
|
||||
| Keep DFM's domain model independent | Preserves duplicated definitions without a distinct domain ownership reason. |
|
||||
| Replace authoritative reads with validated or branded snapshots | Cannot preserve current-leaf, provenance, or concurrent-storage guarantees after state changes. |
|
||||
|
||||
## Consequences and follow-ups
|
||||
|
||||
Callers can state whether they supply a reference, Metadata, save content,
|
||||
or reconstructed content. Invalid assumptions become visible in declarations
|
||||
and focused contract tests. This does not itself establish an end-user defect
|
||||
or eliminate the need for runtime validation and recovery checks.
|
||||
|
||||
More explicit types require adapters at the compatibility boundaries and
|
||||
coordinated package and consumer changes. The design document records the
|
||||
implemented information views, legacy correction, static content exclusion,
|
||||
and DFM read methods. Old entry aliases, the broad document union, and the
|
||||
Chunk write/event adapter remain compatibility boundaries. A complete
|
||||
store-specific union and Chunk hierarchy migration remain follow-ups.
|
||||
|
||||
Before changing production behaviour, add the relevant regression and
|
||||
compatibility cases and establish their baseline outcomes. Validate save
|
||||
ordering, accepted legacy inputs, empty content, tombstones, DFM callbacks,
|
||||
and revision/provenance behaviour. Update this status and the supporting
|
||||
references when the decision is accepted, implemented, or published; preserve
|
||||
the investigated baseline and any remaining follow-ups.
|
||||
Reference in new issue
Block a user