# Enterprise Source Synchronization 0.1.0 This original companion specifies a locally owned register of source declarations, purpose-qualified record-to-subject mappings, intake receipts and snapshot coverage. It records metadata and protected evidence references. It does not acquire source bytes or apply business facts. A board ABOUT a Project is an aboutness claim, not board IS Project and not permission to create a Project. ## Identity and boundaries SyncRegister has one registerId (at most 160 characters, reserving room for derived occurrence IDs), one Dimension, one bootstrap administrator and one protected evidence namespace. The immutable local SQLite journal is its master; the derived state, archive and native projection are views. Changing bootstrap identity requires a new register. No tenant, Company, Project, Person, Dataset or source record is created as a business subject here. Target catalogue entries are host-supplied references to separately governed subjects. SourceInstance declares a product reference, exact tenant/environment and source-instance generation. Its ID and declaration cannot be edited. Another installation of a connector does not necessarily mean another source instance; installation/credential lifecycle is external. The reference rejects duplicate declared product/tenant/environment/generation tuples. It cannot discover undisclosed aliases or prove source continuity. AcquisitionScope is an immutable, locally identified interpretation of an unpartitioned stream: source ID, resource, scheme/version, source object kind, source-query projection, filter, principal visibility, adapter interpretation and schema evidence. Its fingerprint excludes the local scope ID. Equal fingerprints cannot be registered twice. Mapping revisions and per-round source positions are not acquisition-scope components. Partition/global states and unknown schema properties are refused. The protected evidence references are compared literally; a re-wrapped reference yields a new fingerprint even if an external operator believes its meaning unchanged. A qualified source lineage is the exact tuple (SourceInstance ID, source-instance generation, resource, scheme, schemeVersion, lexical key, record generation). There is no number conversion, case folding, Unicode normalization or same-as inference. `01` differs from `1`; tenants and resource namespaces qualify `42`. Record generation and synchronization epoch are different: token expiry changes progress context, not automatically record identity. Unknown record generation is non-joinable, never an implicit generation 1. RecordKey may carry unknown generation and no evidence; it is then accepted only as an unpinned occurrence with continuity-unknown. Known generation requires an evidence declaration based on source incarnation, source non-reuse guarantee or steward attestation. Source attribution must name the declared SourceInstance; steward attestation must name the admitted actor and requires mapping permission. These are host-verified declarations, not cryptographic source authentication. ## Aboutness mapping and history RecordSubjectMapping has immutable ID, complete known lineage, target subject/kind, purpose, issuer, validity interval, evidence and optional correction predecessor. The creating actor must be the issuer. Mapping admission requires a trusted target catalogue match and an allowed (sourceKind, targetKind, purpose) pair; arbitrary kinds are governed values rather than Identity's four-kind enum. Source kind comes from the trusted scope interpretation. A proposed mapping can activate, dispute or retract; active can dispute/retract; disputed can activate/retract; retraction is terminal. Every activation checks uniqueness across all mapping IDs and revisions for complete lineage plus purpose. Changing a target, key, generation, purpose, kind or issuer requires a new mapping ID. A replacement that declares corrects must name an earlier claim in the same scope, purpose and known lineage, and cannot activate until that predecessor is retracted. A different-key claim needs independent retirement and new admission without a misleading correction edge. Any current map grantee for the claim scope/purpose may transition it; issuer attribution remains immutable. A zero-active interval is allowed. The first release exposes separate guarded transitions, not an atomic replace convenience API. At no point can two claims for one lineage/purpose be active. Renames of source content do not edit the mapping. At first batch admission, each record gets a derived mapping outcome. A pin can use only a mapping declared in that same acquisition scope and purpose. Another scope with the same qualified lineage does not inherit its mapping, even if only the filter changed; its outcome is unmapped. Global lineage/purpose uniqueness still reserves an active claim across scopes. To move governance, a steward with current map grants for both scopes explicitly retracts the old claim and activates a separately proposed new one. Cross-scope corrects is refused; host evidence records the migration instead. Historical pins are unchanged. A pin names mapping ID/state revision, target catalogue revision and current policy revision. The mapping validity window is checked against connector-declared observedAt. The state revision is selected at receipt time, not reconstructed from sourceEventTime. A later retraction or correction does not repin historical occurrences. Within the same immutable scope, a catalogue reclassification or observedAt outside the mapping validity window suspends new pins with active-pin-suspended, while the old active claim still reserves uniqueness until steward action. A changed source-kind interpretation requires a new scope; until a mapping in that receiving scope is activated, its outcome is unmapped, never an inherited suspended pin. Unknowns yield continuity-unknown; known lineages without an active claim yield unmapped. Disputed claims confer no operative pin. This is a narrow combination of fixed mapping validity and append-only receipt knowledge. It is not a universal bitemporal mapping engine: future-effective state transitions, assignment closure revisions, retroactive repinning and historical reprocessing are deferred. historical_cut reports the journal known by a host receipt timestamp; within one second sequence remains the ordering key. ## Permission and host trust Bootstrap administration can declare sources/scopes, replace versioned host catalogue/policy, open/close epochs and advance fences. It does not automatically receive intake, mapping or ordinary receipt-read permission. Mapping/round identifiers are register-global, not secret per-scope namespaces. A foreign scope/purpose ID collision and a foreign active-lineage reservation produce uniform DENIED without diagnostic detail. They can still reveal that an identifier or lineage is unavailable compared with a fresh successful proposal. Hosts allocate collision-resistant IDs and coordinate namespace stewardship. Receipt IDs expose register-wide sequence/activity; no concealment guarantee is made. There is no ordinary API for head/fence discovery: a trusted coordinator supplies current preconditions across purposes in a shared epoch. A current exact Grant binds actor, scope, purpose, a subset of intake/map/read/attest-coverage, and a half-open validity interval. No wildcard, group inheritance, delegation chain or real IAM integration ships. Authentication, source/steward verification, policy-issuer competence and current time are trusted host inputs. A grant and a source's semantic priority remain distinct. Unauthorized/revoked calls return the same not-accepted shape before receipt lookup and append no canonical event. Host denial telemetry is external. Write-only callers get a minimal receipt ID/status for their own successful commit or exact own retry. A different current writer colliding with the same scope/epoch-wide key receives no receipt, and a compact restricted diagnostic may be retained within the separate diagnostic budgets. It can still infer one bit that the key is unavailable by comparing refusal with success for a fresh key. No timing side-channel or zero-knowledge claim is made. Recovery under a replacement principal needs current read permission or an operator lookup; write-only recovery rights do not transfer automatically. read_receipt checks current read grant and purpose. Full archives, offline history validation, historical_cut and assess_rounds are privileged host functions, not partial disclosure APIs. Native exports must remain subject to current host disclosure; copying them does not enforce a later revocation. Errors for authorized malformed inputs and privileged diagnostics are not public-safe responses. No real addresses, tokens or credentials occur in fixtures. A secret disguised as a permitted identifier is not detected by this schema; the host is responsible for classification and safe input. ## Atomic intake and replay The first release supports one local SQLite database with rollback journal and FULL synchronous mode. BEGIN IMMEDIATE serializes writers. Each retained event is one immutable journal entry with sequence, previous digest, actor, host receipt time, accepted command or compact conflict observation, minimal result, full-derived-state outcomeDigest and event digest. The bootstrap, archive and native snapshot carry buildId: SHA-256 over the exact UTF-8 source file bytes, a NUL separator and exact schema file bytes. The chain root binds configuration and buildId. Replay requires that exact installed build and verifies the result and complete state digest after every event; changed code/schema cannot silently reinterpret stored outcomes. The reports record tested Python, SQLite and dependency versions. requirements.txt pins jsonschema only; there is no complete runtime or transitive dependency lock. Other environments need validation; recording a version is not pinning its executable bytes. Build hashes establish integrity, not trusted authorship. Replaying the journal derives configuration, mappings, epochs, receipts and conflicts. The database journal, not a replaceable query index, is the master. A hash chain proves internal byte consistency only; it cannot prove authenticity or that a coherent copy is current. SyncEpoch belongs to one scope. Only one epoch per scope can be open. It begins with fence 1, no head and progress 0. A trusted administration command advances the fence independently of progress and is journaled. An incoming new batch needs the exact current fence and expected head inside the same write transaction. Tokens are opaque protected references; neither token text nor source wall clock is sorted to find the head. Local progress sequence orders receipts. Batch identity is (scopeId, epochId, batchKey), independent of writer and mapping revisions. The host/extractor must preserve that key across retry. The reference does not deduplicate arbitrarily repaginated deliveries under new keys. Client content includes ordered input descriptors, purpose, round/page declarations and token evidence. attemptId, expectedHead, fence and computed mapping outcomes are outside content identity. The first implementation has no optional expected-mapping-revision input. Admission order is: authenticate/authorize; validate closed input; refuse a closed/wrong epoch; look up the key; return the original own acknowledgement for identical content; retain a conflict for a different principal or changed content; only for a new key evaluate head/fence and first-admission guards. Identical retry after later progress, fence change or mapping correction short-circuits stale preconditions, never readmits or repins the batch and creates no canonical event. Loading the store does recompute historical derived state under its exact build and checks every outcomeDigest. It still requires current intake permission. After epoch close, COMMIT uniformly refuses; separate authorized READ may recover history. The single local transaction persists original content and the digest of its complete resulting state. Replay reconstructs and verifies derived occurrences, durable quarantine descriptors, received/accepted/quarantined counts, receipt and new head. A receipt is the destination acknowledgement for this local metadata register. It is not confirmation by an independent external business destination. Conservation is received = accepted + quarantined. There is no accept-loss option. Zero records requires empty=true. A rejection descriptor names a protected evidence reference, reason and retry obligation. The reference does not parse or quarantine arbitrary raw source bytes: an upstream adapter classifies each descriptor, while the whole input envelope itself must validate. Quarantine obligations remain open in 0.1.0; automated resolution, erasure and retention execution are deferred. Reingestion is a new batch and does not erase old quarantine. RecordOccurrence identity is receipt ID plus input ordinal. Repeated identical records within one page retain distinct occurrences and order. Content-reference spelling is part of retry identity. A reissued locator changes the body and conflicts, even if it points to the same external bytes. Digests bind submitted descriptors and do not prove external payload/token acquisition, retention, authenticity, encryption or privacy. Their external evidence store must be managed by the host; no fetch, fsync or token-access check is performed against it. Only the committing attemptId and retained conflict attemptIds enter this journal. A rejected authorized commit retains only its qualified key, attempt, preconditions, supplied digest and conflict reason, never its full rejected payload or record descriptors. Replaying this internal observation independently verifies the conflict against prior state; clients cannot submit internal observations. At most 32 conflicts total and 4 per actor/scope/epoch are retained. Diagnostic budget exhaustion, the 128-event limit or insufficient archive space yields the same refusal with no event or head change. Full denial/attempt telemetry and capacity monitoring belong outside this finite reference. A digest collision with unequal canonical content is refused without a diagnostic. Exact-retry attempts, failed-before-commit attempts, denied calls and invalid envelopes remain external telemetry. There is no crash-durable running ExtractionAttempt object. Fault tests exercise a process exiting before and after SQLite COMMIT, not storage hardware/power-loss certification. Storage that lies about flush or locking remains outside the guarantee. Multi-host fencing, distributed exactly-once, external effects and cross-register transactions are not implemented. ## Occurrence time, corrections and competing facts observedAt is connector-declared acquisition time. sourceEventTime is nullable and never invented from observedAt or host time. recordedAt/committedAt come from the trusted host; journal sequence disambiguates equal host timestamps. The host receipt clock cannot move backwards along the journal, but no ordering across source clocks is asserted. An occurrence correction references an earlier retained occurrence of the same known lineage, scope and purpose. In addition to intake, it needs current map and read grants and declared source-or-steward attribution; foreign-scope/purpose and nonexistent targets receive the same refusal without a canonical event. Source-or-steward attribution is then checked; source attribution names SourceInstance, steward attribution names the admitted actor. It creates a new occurrence and retains the old one. The reference does not adjudicate which competing source value is true. It retains both evidence references and routes fact selection to separately governed authority; no EFA or EAP adapter executes automatically. Source-deleted, removed-from-scope and inaccessible are source-availability observations, never business-subject retirement. ## Snapshot coverage and comparison SnapshotRound declares one scope/epoch/purpose, consistency kind/evidence, whether visibility is covered by the source guarantee, and optional earlier round plus not-earlier evidence. For a round declaring source-snapshot consistency or visibilityCovered=true, opening it, admitting a new terminal page, and sealing without errors each require current attest-coverage as well as intake. Revocation is rechecked at each of those admissions; an exact committed batch retry still returns only its original acknowledgement under the existing intake retry rule. Nonterminal pages may be supplied by intake-only actors. An intake actor may seal with explicit nonempty error evidence, which always makes complete=false and cannot support absence. This records host-authorized attestation; it does not verify external completeness. Intake-only writers may declare best-effort with visibilityCovered=false. The earlier round must already be sealed in the same scope. Pages commit in contiguous zero-based order; no page can follow terminal=true. A nonterminal page can advance local progress but cannot complete a round. A round must be sealed, including error evidence for a partial result, before its epoch closes. It cannot accept pages after sealing. If its writer loses permission, an administrator must explicitly grant an operator (including itself) intake for that scope/purpose to seal an orphaned round with error evidence. Admin has no implicit intake. Hosts must reserve capacity for closure; no special over-budget recovery or rollover exists. The reference's complete flag is deliberately a strong key-accounting condition: a terminal page exists, no error or quarantine remains in the round, and all retained items are snapshot-read with known generations. It does not certify actual source completeness. Best-effort may be fully accounted yet cannot support absence comparison. A host must establish actual consistency and visibility before declaring them. assess_rounds validates the complete restricted archive first. It requires two complete rounds, increasing local seal sequence, identical scope/purpose, source-snapshot consistency in both, visibilityCovered in both and the later round's explicit earlier-round/not-earlier witness. Opaque LSN/token values are not compared. Different epochs alone do not break comparison. Changed source-instance generation, filter, principal visibility or interpretation changes the scope and breaks it. Unknown order, missing pages or inadequate key coverage returns insufficient-context. For a known lineage present in the earlier round and not the later, an explicit intervening deletion/removal/inaccessibility observation is reported separately. Otherwise the result is only not-observed-in-comparable-rounds with steward-review-only action and an empty effects list. Same principal does not prove unchanged per-object visibility. No absence result deletes data, retracts a mapping, chooses a fact or retires a subject. Cross-register/foreign-archive round comparison is not implemented. ## Export, versions and operational limits Archives preserve bootstrap, buildId, complete journal, exact derived state, root and version. validate_archive recomputes history and rejects edited outcomes, missing evidence, changed state, unsupported versions or a different executable/schema build. Derived state is compared by canonical bytes, including exact boolean versus integer types. Earlier unreleased 0.1.0 candidate builds are not interchangeable; they remain frozen historical evidence and need their exact original code/schema to inspect. No automatic migration is provided. inspect_import returns a historical-only report or an explicit LossReport. It does not create a writable database. resume_archive always refuses. Original epoch states remain unchanged as historical evidence; the archive wrapper is non-resumable. Upgrade/downgrade transformations, origin-host handover and writable restoration are deferred, not silently approximated. A normal process restart can reopen the same locally owned database. The host must establish that it is the current owned store. A crash before bootstrap commits may leave an uninitialized file. An empty store is explicitly refused and preserved; do not overwrite it automatically. An operator inspects the file and establishes a new owned path/baseline if initialization never completed. Other corrupt/partial store errors remain host recovery events. The reference cannot detect a coherent old backup or two cloned databases and has no live ownership token service. Another host starts a new local register/epoch and fresh acquisition baseline; it does not continue from an imported token. Fresh-source/baseline truth remains external because this reference has no network connector. Budgets: 128 retained journal entries; 256 input records/descriptors per batch; 256 catalogue targets/pairs/grants; 32 round-error references; one complete archive at most 512 KiB of the reference's canonical JSON encoding. A new retained event is refused before persistence if its archive would exceed the budget; no-event exact retries and uniform refusals remain available at the event limit. Conflict diagnostics also have the separate bounds described above. Generated journal entries are schema-checked before persistence. These are demonstration limits, not enterprise throughput targets. The journal is replayed on each operation and hashes the growing state at every event; this can be quadratic work per call under a database lock. The earlier candidate 2,000-event/8-MiB limits are withdrawn. benchmark.py records a synthetic run near both new limits, with large state present early and two process writers. Its timings are observations, not an SLA or certification under every host load. SQLite busy/lock errors can still occur and are host operational errors, not authorization refusals. Large-scale indexing/partitioning needs a separately reviewed implementation. Canonical encoding uses Python sorted-key, compact, UTF-8 JSON with ordered arrays; floats, duplicate JSON keys, non-string keys, C0/DEL/C1 control characters and unpaired surrogates are refused. JSON text bytes must be UTF-8 without BOM. Raw transport has a separate 8 MiB UTF-8 byte limit, including whitespace and escape spelling; the parsed canonical value remains limited to 512 KiB. Whitespace and key order within that transport budget are accepted and canonicalized. Excessive JSON nesting returns a structured import refusal; no unbounded parser support is promised. Stored journal/bootstrap blobs must already use exact canonical encoding. All lexical schema patterns require absolute end of string, so a trailing newline cannot pass. Other Unicode characters, including format/zero-width characters, remain distinct lexical values; viewers must escape ambiguous display safely. It is explicitly not RFC 8785/JCS. IDs are restricted URNs, lexical source keys remain exact bounded strings. Supplied SHA-256 values are declarations; no payload is fetched to confirm them. Schema version, object revision, journal sequence, epoch and source/record generation are independent values. ## Native binding and release posture The native V3 binding is one SyncRegister object and a restricted sync.register.snapshot fact pointing to this exact companion/version and carrying its closed journal snapshot. The snapshot omits redundant derived state; installed replay reconstructs the exact complete archive. sync.schema.json closes this native value at the root, with command and journal definitions in $defs. The native fact profile rejects extra envelope fields and requires exact authority types. One aggregate projection has an explicit owner, boundary and calculation rule. Its fact ID is determined by journal root; exporting the same cut at a later capture time can change envelope bytes but cannot create a new fact identity. Keep the first stored fact; the native writer rejects duplicate IDs. Only strict journal extensions supersede a trusted predecessor. That predecessor must already have been validated by the host, including its provenance. Generic business fact resolution must not treat this register snapshot as a Project field. Native outer validation and installed companion replay must both run; outer validity alone does not establish nested semantics, authenticity or current state. This file currently describes an implementation candidate. Executed test reports and native acceptance state what was run. Separate frozen Claude/Grok audits are tracked in review.json and review.md; this candidate text alone makes no audit-acceptance claim. Published lifecycle, research assurance, implementation evidence and broader-contour completion remain separate. A source synchronization package is not a Company model or a production connector deployment. ## Deterministic availability evidence Absence assessment uses only availability occurrences from the compared scope and purpose. When multiple observations concern one lineage between the seals, the latest is selected by (receipt sequence, input ordinal), never dictionary or lexical key order. Canonical JSON export/import therefore preserves this result. Source-event clocks are not used to reorder host-admitted observations. Shared-round coordination: an intake grantee may append nonterminal pages to an attested round or close it with nonempty error evidence, always incomplete. Page slots are shared, so one writer can displace another writer's planned page. The current attester must inspect and verify the entire admitted page set before terminal admission and an error-free seal, including pages supplied by other writers. The host coordinates contributors, source completeness and recovery; the reference neither reserves page ownership nor proves that the attester actually performed this review. Current attestation gates prevent intake-only successful completion, not interference by an authorized contributor.