@enbox/agent 0.5.9 → 0.5.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/browser.mjs +9 -9
  2. package/dist/browser.mjs.map +4 -4
  3. package/dist/esm/dwn-api.js.map +1 -1
  4. package/dist/esm/dwn-record-upgrade.js +1 -1
  5. package/dist/esm/dwn-record-upgrade.js.map +1 -1
  6. package/dist/esm/index.js +4 -0
  7. package/dist/esm/index.js.map +1 -1
  8. package/dist/esm/sync-closure-resolver.js +855 -0
  9. package/dist/esm/sync-closure-resolver.js.map +1 -0
  10. package/dist/esm/sync-closure-types.js +189 -0
  11. package/dist/esm/sync-closure-types.js.map +1 -0
  12. package/dist/esm/sync-engine-level.js +977 -224
  13. package/dist/esm/sync-engine-level.js.map +1 -1
  14. package/dist/esm/sync-messages.js +19 -5
  15. package/dist/esm/sync-messages.js.map +1 -1
  16. package/dist/esm/sync-replication-ledger.js +220 -0
  17. package/dist/esm/sync-replication-ledger.js.map +1 -0
  18. package/dist/esm/types/sync.js +54 -1
  19. package/dist/esm/types/sync.js.map +1 -1
  20. package/dist/types/dwn-api.d.ts.map +1 -1
  21. package/dist/types/index.d.ts +5 -0
  22. package/dist/types/index.d.ts.map +1 -1
  23. package/dist/types/sync-closure-resolver.d.ts +19 -0
  24. package/dist/types/sync-closure-resolver.d.ts.map +1 -0
  25. package/dist/types/sync-closure-types.d.ts +122 -0
  26. package/dist/types/sync-closure-types.d.ts.map +1 -0
  27. package/dist/types/sync-engine-level.d.ts +137 -11
  28. package/dist/types/sync-engine-level.d.ts.map +1 -1
  29. package/dist/types/sync-messages.d.ts +6 -1
  30. package/dist/types/sync-messages.d.ts.map +1 -1
  31. package/dist/types/sync-replication-ledger.d.ts +72 -0
  32. package/dist/types/sync-replication-ledger.d.ts.map +1 -0
  33. package/dist/types/types/sync.d.ts +188 -0
  34. package/dist/types/types/sync.d.ts.map +1 -1
  35. package/package.json +3 -3
  36. package/src/dwn-api.ts +2 -1
  37. package/src/dwn-record-upgrade.ts +1 -1
  38. package/src/index.ts +5 -0
  39. package/src/sync-closure-resolver.ts +919 -0
  40. package/src/sync-closure-types.ts +270 -0
  41. package/src/sync-engine-level.ts +1062 -255
  42. package/src/sync-messages.ts +21 -6
  43. package/src/sync-replication-ledger.ts +197 -0
  44. package/src/types/sync.ts +202 -0
@@ -5,6 +5,11 @@ export type * from './types/identity-vault.js';
5
5
  export type * from './types/key-manager.js';
6
6
  export type * from './types/permissions.js';
7
7
  export type * from './types/sync.js';
8
+ export { computeScopeId, MAX_PENDING_TOKENS } from './types/sync.js';
9
+ export { ReplicationLedger } from './sync-replication-ledger.js';
10
+ export { ClosureFailureCode, createClosureContext } from './sync-closure-types.js';
11
+ export type { ClosureDependencyEdge, ClosureEvaluationContext, ClosureResult } from './sync-closure-types.js';
12
+ export { evaluateClosure, evaluateClosureBatch } from './sync-closure-resolver.js';
8
13
  export type * from './types/vc.js';
9
14
  export * from './agent-did-resolver-cache.js';
10
15
  export * from './anonymous-dwn-api.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,kBAAkB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,wBAAwB,CAAC;AAC5C,mBAAmB,wBAAwB,CAAC;AAC5C,mBAAmB,iBAAiB,CAAC;AACrC,mBAAmB,eAAe,CAAC;AAEnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AAItC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,mBAAmB,kBAAkB,CAAC;AACtC,cAAc,gBAAgB,CAAC;AAC/B,mBAAmB,qBAAqB,CAAC;AACzC,mBAAmB,2BAA2B,CAAC;AAC/C,mBAAmB,wBAAwB,CAAC;AAC5C,mBAAmB,wBAAwB,CAAC;AAC5C,mBAAmB,iBAAiB,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACnF,YAAY,EAAE,qBAAqB,EAAE,wBAAwB,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAC9G,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AACnF,mBAAmB,eAAe,CAAC;AAEnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,cAAc,CAAC;AAC7B,cAAc,cAAc,CAAC;AAC7B,cAAc,yBAAyB,CAAC;AACxC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AAItC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,YAAY,CAAC;AAC3B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { SyncScope } from './types/sync.js';
2
+ import type { ClosureEvaluationContext, ClosureResult } from './sync-closure-types.js';
3
+ import type { GenericMessage, MessageStore } from '@enbox/dwn-sdk-js';
4
+ /**
5
+ * Evaluates closure completeness for a single operation (closure root).
6
+ *
7
+ * Uses BFS traversal with deduplication and depth limiting. Shared caching
8
+ * across evaluation batches via {@link ClosureEvaluationContext}.
9
+ *
10
+ * The resolver queries the local MessageStore directly (bypassing auth)
11
+ * because it needs to verify dependency presence, not access-control the
12
+ * syncing agent's own local store.
13
+ */
14
+ export declare function evaluateClosure(message: GenericMessage, messageStore: MessageStore, scope: SyncScope, context: ClosureEvaluationContext): Promise<ClosureResult>;
15
+ /**
16
+ * Evaluate closure for a batch of messages. Shares caching across all roots.
17
+ */
18
+ export declare function evaluateClosureBatch(messages: GenericMessage[], messageStore: MessageStore, scope: SyncScope, tenantDid: string, maxDepth?: number): Promise<ClosureResult[]>;
19
+ //# sourceMappingURL=sync-closure-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-closure-resolver.d.ts","sourceRoot":"","sources":["../../src/sync-closure-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AACjD,OAAO,KAAK,EAEV,wBAAwB,EACxB,aAAa,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAyZtE;;;;;;;;;GASG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,EACvB,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,SAAS,EAChB,OAAO,EAAE,wBAAwB,GAChC,OAAO,CAAC,aAAa,CAAC,CA8FxB;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,cAAc,EAAE,EAC1B,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,SAAS,EAChB,SAAS,EAAE,MAAM,EACjB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,aAAa,EAAE,CAAC,CAU1B"}
@@ -0,0 +1,122 @@
1
+ import type { GenericMessage } from '@enbox/dwn-sdk-js';
2
+ /**
3
+ * Typed failure codes for closure resolution. Each code maps to a specific
4
+ * dependency class from the closure RFC.
5
+ */
6
+ export declare enum ClosureFailureCode {
7
+ /** Class 1: The ProtocolsConfigure for the protocol could not be found. */
8
+ ProtocolMetadataMissing = "ClosureProtocolMetadataMissing",
9
+ /** Class 2: The initialWrite for a non-initial RecordsWrite is missing. */
10
+ InitialWriteMissing = "ClosureInitialWriteMissing",
11
+ /** Class 2: A parent record in the parentId chain is missing. */
12
+ ParentChainMissing = "ClosureParentChainMissing",
13
+ /** Class 2: A context ancestor record is missing. */
14
+ ContextChainMissing = "ClosureContextChainMissing",
15
+ /** Class 3: A permission grant referenced by permissionGrantId is missing. */
16
+ GrantMissing = "ClosureGrantMissing",
17
+ /** Class 3: The grant exists but is not yet active at the message's timestamp. */
18
+ GrantNotYetActive = "ClosureGrantNotYetActive",
19
+ /** Class 3: The grant exists but has expired at the message's timestamp. */
20
+ GrantExpired = "ClosureGrantExpired",
21
+ /** Class 3: A revocation record that affects a referenced grant is missing. */
22
+ GrantRevocationMissing = "ClosureGrantRevocationMissing",
23
+ /** Class 4: A squash floor or visibility-floor record is missing. */
24
+ VisibilityFloorMissing = "ClosureVisibilityFloorMissing",
25
+ /** Class 5: An encryption/key-delivery dependency is missing. */
26
+ EncryptionDependencyMissing = "ClosureEncryptionDependencyMissing",
27
+ /** Class 6: A cross-protocol $ref dependency is missing. */
28
+ CrossProtocolReferenceMissing = "ClosureCrossProtocolReferenceMissing",
29
+ /** A dependency exists but the syncing principal is not authorized to fetch it. */
30
+ DependencyForbidden = "ClosureDependencyForbidden",
31
+ /** Traversal depth exceeded the configured maximum (default 32). */
32
+ DepthExceeded = "ClosureDepthExceeded"
33
+ }
34
+ /**
35
+ * A single dependency edge in the closure graph — identifies what is needed
36
+ * and why. Used for diagnostics, deduplication, and fetch queue management.
37
+ */
38
+ export type ClosureDependencyEdge = {
39
+ /** The dependency class that produced this edge. */
40
+ dependencyClass: 1 | 2 | 3 | 4 | 5 | 6;
41
+ /** Human-readable label for the dependency (e.g., "initialWrite", "grant", "protocolsConfigure"). */
42
+ label: string;
43
+ /**
44
+ * The identifier used to look up this dependency. Typically a `messageCid`
45
+ * or `recordId` depending on the dependency class.
46
+ */
47
+ identifier: string;
48
+ /** The type of identifier — determines the fetch strategy. */
49
+ identifierType: 'messageCid' | 'recordId' | 'protocol' | 'grantId' | 'filter';
50
+ /**
51
+ * When `identifierType` is `'filter'`, this carries the full query filter
52
+ * as a structured object. Used for dependencies that require multi-field
53
+ * queries (e.g., cross-protocol role records queried by protocol +
54
+ * protocolPath + recipient + contextId prefix).
55
+ */
56
+ filter?: Record<string, unknown>;
57
+ };
58
+ /**
59
+ * Result of closure evaluation for a single operation (closure root).
60
+ */
61
+ export type ClosureResult = {
62
+ /** Whether all hard dependencies are satisfied. */
63
+ complete: boolean;
64
+ /** The closure root's messageCid. */
65
+ rootMessageCid: string;
66
+ /** All dependency edges that were evaluated. */
67
+ edges: ClosureDependencyEdge[];
68
+ /**
69
+ * If incomplete, the first unsatisfied dependency. Used for diagnostics
70
+ * and determines the failure code for repair transitions.
71
+ */
72
+ failure?: {
73
+ code: ClosureFailureCode;
74
+ edge: ClosureDependencyEdge;
75
+ detail: string;
76
+ };
77
+ /** Total number of dependency hops traversed. */
78
+ depth: number;
79
+ };
80
+ /**
81
+ * Shared context for a batch of closure evaluations. Caches protocol
82
+ * definitions, grant records, and previously resolved operations to avoid
83
+ * redundant queries across closure roots in the same evaluation pass.
84
+ */
85
+ export type ClosureEvaluationContext = {
86
+ /** Tenant DID for this evaluation batch. */
87
+ tenantDid: string;
88
+ /** Cached ProtocolsConfigure definitions keyed by protocol URI. */
89
+ protocolCache: Map<string, any>;
90
+ /** Cached grant records keyed by grantId. */
91
+ grantCache: Map<string, GenericMessage | null>;
92
+ /**
93
+ * Set of dependency identifiers already known to be locally present.
94
+ * Keyed by `${identifierType}:${identifier}` to prevent cross-namespace
95
+ * collisions (e.g., a recordId and a grantId with the same string value).
96
+ */
97
+ satisfiedDeps: Set<string>;
98
+ /**
99
+ * Set of dependency identifiers already known to be missing/unfetchable.
100
+ * Same composite key format as `satisfiedDeps`.
101
+ */
102
+ missingDeps: Set<string>;
103
+ /** Maximum traversal depth. Default 32. */
104
+ maxDepth: number;
105
+ };
106
+ /**
107
+ * Create a fresh evaluation context for a batch of closure evaluations.
108
+ */
109
+ export declare function createClosureContext(tenantDid: string, maxDepth?: number): ClosureEvaluationContext;
110
+ /**
111
+ * Invalidate cached entries that may be affected by a newly processed message.
112
+ * Called after `processRawMessage` succeeds to ensure subsequent closure
113
+ * evaluations see the updated state.
114
+ *
115
+ * - `ProtocolsConfigure` → clears protocolCache for that protocol URI
116
+ * - Permissions grant write → clears grantCache for that recordId
117
+ * - Permissions revocation → clears grantCache for the parent grantId
118
+ * - Any Records message → clears satisfiedDeps/missingDeps for that recordId
119
+ * (the message may have changed what's locally present)
120
+ */
121
+ export declare function invalidateClosureCache(context: ClosureEvaluationContext, message: GenericMessage): void;
122
+ //# sourceMappingURL=sync-closure-types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-closure-types.d.ts","sourceRoot":"","sources":["../../src/sync-closure-types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMxD;;;GAGG;AACH,oBAAY,kBAAkB;IAC5B,2EAA2E;IAC3E,uBAAuB,mCAAmC;IAC1D,2EAA2E;IAC3E,mBAAmB,+BAA+B;IAClD,iEAAiE;IACjE,kBAAkB,8BAA8B;IAChD,qDAAqD;IACrD,mBAAmB,+BAA+B;IAClD,8EAA8E;IAC9E,YAAY,wBAAwB;IACpC,kFAAkF;IAClF,iBAAiB,6BAA6B;IAC9C,4EAA4E;IAC5E,YAAY,wBAAwB;IACpC,+EAA+E;IAC/E,sBAAsB,kCAAkC;IACxD,qEAAqE;IACrE,sBAAsB,kCAAkC;IACxD,iEAAiE;IACjE,2BAA2B,uCAAuC;IAClE,4DAA4D;IAC5D,6BAA6B,yCAAyC;IACtE,mFAAmF;IACnF,mBAAmB,+BAA+B;IAClD,oEAAoE;IACpE,aAAa,yBAAyB;CACvC;AAMD;;;GAGG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,oDAAoD;IACpD,eAAe,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACvC,qGAAqG;IACrG,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,cAAc,EAAE,YAAY,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;IAC9E;;;;;OAKG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAMF;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,mDAAmD;IACnD,QAAQ,EAAE,OAAO,CAAC;IAClB,qCAAqC;IACrC,cAAc,EAAE,MAAM,CAAC;IACvB,gDAAgD;IAChD,KAAK,EAAE,qBAAqB,EAAE,CAAC;IAC/B;;;OAGG;IACH,OAAO,CAAC,EAAE;QACR,IAAI,EAAE,kBAAkB,CAAC;QACzB,IAAI,EAAE,qBAAqB,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,iDAAiD;IACjD,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAMF;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,4CAA4C;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,aAAa,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC,6CAA6C;IAC7C,UAAU,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAC,CAAC;IAC/C;;;;OAIG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B;;;OAGG;IACH,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACzB,2CAA2C;IAC3C,QAAQ,EAAE,MAAM,CAAC;CAClB,CAAC;AAEF;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,wBAAwB,CASnG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,wBAAwB,EACjC,OAAO,EAAE,cAAc,GACtB,IAAI,CAmHN"}
@@ -1,7 +1,7 @@
1
1
  import type { AbstractLevel } from 'abstract-level';
2
2
  import type { GenericMessage } from '@enbox/dwn-sdk-js';
3
3
  import type { EnboxPlatformAgent } from './types/agent.js';
4
- import type { StartSyncParams, SyncConnectivityState, SyncEngine, SyncIdentityOptions } from './types/sync.js';
4
+ import type { StartSyncParams, SyncConnectivityState, SyncEngine, SyncEventListener, SyncIdentityOptions } from './types/sync.js';
5
5
  export type SyncEngineLevelParams = {
6
6
  agent?: EnboxPlatformAgent;
7
7
  dataPath?: string;
@@ -22,6 +22,26 @@ export declare class SyncEngineLevel implements SyncEngine {
22
22
  private _db;
23
23
  private _syncIntervalId?;
24
24
  private _syncLock;
25
+ /**
26
+ * Durable replication ledger — persists per-link checkpoint state.
27
+ * Used by live sync to track pull/push progression independently per link.
28
+ * Poll-mode sync still uses the legacy `getCursor`/`setCursor` path.
29
+ * Lazily initialized on first use to avoid sublevel() calls on mock dbs.
30
+ */
31
+ private _ledger?;
32
+ /**
33
+ * In-memory cache of active links, keyed by `{did}^{dwnUrl}^{protocol}`.
34
+ * Populated from the ledger on `startLiveSync`, used by subscription handlers
35
+ * to avoid async ledger lookups on every event.
36
+ */
37
+ private _activeLinks;
38
+ /**
39
+ * Per-link in-memory delivery-order tracking for the pull path. Keyed by
40
+ * the same link key as `_activeLinks`. Not persisted — on crash, replay
41
+ * restarts from `contiguousAppliedToken` and idempotent apply handles
42
+ * re-delivered events.
43
+ */
44
+ private _linkRuntimes;
25
45
  /**
26
46
  * Hex-encoded default hashes for empty subtrees at each depth, keyed by depth.
27
47
  * Lazily initialized on first use. Used by `walkTreeDiff` to detect empty subtrees
@@ -30,6 +50,13 @@ export declare class SyncEngineLevel implements SyncEngine {
30
50
  private _defaultHashHex?;
31
51
  /** Current sync mode, set by `startSync`. */
32
52
  private _syncMode;
53
+ /**
54
+ * Monotonic session generation counter. Incremented on every teardown.
55
+ * Async operations (repair, retry timers) capture the generation at start
56
+ * and bail if it has changed — this prevents stale work from mutating
57
+ * state after teardown or mode switch.
58
+ */
59
+ private _syncGeneration;
33
60
  /** Active live pull subscriptions (remote -> local via MessagesSubscribe). */
34
61
  private _liveSubscriptions;
35
62
  /** Active local EventLog subscriptions for push-on-write (local -> remote). */
@@ -38,8 +65,27 @@ export declare class SyncEngineLevel implements SyncEngine {
38
65
  private _connectivityState;
39
66
  /** Debounce timer for batched push-on-write. */
40
67
  private _pushDebounceTimer?;
41
- /** Pending message CIDs to push, accumulated during the debounce window. */
68
+ /** Registered event listeners for observability. */
69
+ private _eventListeners;
70
+ /** Entry in the pending push queue — a message CID with its local EventLog token. */
42
71
  private _pendingPushCids;
72
+ /**
73
+ * CIDs recently received via pull subscription, keyed by `cid|dwnUrl` to
74
+ * scope suppression per remote endpoint. A message pulled from Provider A
75
+ * is only suppressed for push back to Provider A — it still fans out to
76
+ * Provider B and C. TTL: 60 seconds. Cap: 10,000 entries.
77
+ */
78
+ private _recentlyPulledCids;
79
+ /** TTL for echo-loop suppression entries (60 seconds). */
80
+ private static readonly ECHO_SUPPRESS_TTL_MS;
81
+ /**
82
+ * Per-tenant closure evaluation contexts for the current live sync session.
83
+ * Caches ProtocolsConfigure and grant lookups across events for the same
84
+ * tenant. Keyed by tenantDid to prevent cross-tenant cache pollution.
85
+ */
86
+ private _closureContexts;
87
+ /** Maximum entries in the echo-loop suppression cache. */
88
+ private static readonly ECHO_SUPPRESS_MAX_ENTRIES;
43
89
  /** Count of consecutive SMT sync failures (for backoff in poll mode). */
44
90
  private _consecutiveFailures;
45
91
  /** Maximum consecutive failures before entering backoff. */
@@ -47,6 +93,8 @@ export declare class SyncEngineLevel implements SyncEngine {
47
93
  /** Backoff multiplier for consecutive failures (caps at 4x the configured interval). */
48
94
  private static readonly MAX_BACKOFF_MULTIPLIER;
49
95
  constructor({ agent, dataPath, db }: SyncEngineLevelParams);
96
+ /** Lazy accessor for the replication ledger. */
97
+ private get ledger();
50
98
  /**
51
99
  * Retrieves the `EnboxPlatformAgent` execution context.
52
100
  *
@@ -56,6 +104,9 @@ export declare class SyncEngineLevel implements SyncEngine {
56
104
  get agent(): EnboxPlatformAgent;
57
105
  set agent(agent: EnboxPlatformAgent);
58
106
  get connectivityState(): SyncConnectivityState;
107
+ on(listener: SyncEventListener): () => void;
108
+ /** Emit a sync event to all registered listeners. */
109
+ private emitEvent;
59
110
  clear(): Promise<void>;
60
111
  close(): Promise<void>;
61
112
  registerIdentity({ did, options }: {
@@ -84,6 +135,73 @@ export declare class SyncEngineLevel implements SyncEngine {
84
135
  * 4. Schedules an infrequent SMT integrity check at `interval`.
85
136
  */
86
137
  private startLiveSync;
138
+ /**
139
+ * Get or create the runtime state for a link.
140
+ */
141
+ private getOrCreateRuntime;
142
+ /**
143
+ * Drain contiguously committed ordinals from the runtime state, advancing
144
+ * the link's pull checkpoint for each drained entry. Returns the number of
145
+ * entries drained (0 if the next ordinal is not yet committed).
146
+ */
147
+ private drainCommittedPull;
148
+ /** Maximum consecutive repair attempts before falling back to degraded_poll. */
149
+ private static readonly MAX_REPAIR_ATTEMPTS;
150
+ /** Per-link degraded-poll interval timers. */
151
+ private _degradedPollTimers;
152
+ /** Per-link repair attempt counters. */
153
+ private _repairAttempts;
154
+ /** Per-link active repair promises — prevents concurrent repair for the same link. */
155
+ private _activeRepairs;
156
+ /** Per-link retry timers for failed repairs below max attempts. */
157
+ private _repairRetryTimers;
158
+ /** Backoff schedule for repair retries (milliseconds). */
159
+ private static readonly REPAIR_BACKOFF_MS;
160
+ /**
161
+ * Per-link repair context — stores ProgressGap metadata for use during
162
+ * repair. The `resumeToken` (from `gapInfo.latestAvailable`) is used as
163
+ * the post-repair checkpoint so the reopened subscription replays from
164
+ * a valid boundary instead of starting live-only.
165
+ */
166
+ private _repairContext;
167
+ /**
168
+ * Central helper for transitioning a link to `repairing`. Encapsulates:
169
+ * - status change
170
+ * - optional gap context storage
171
+ * - repair kick-off with retry scheduling on failure
172
+ *
173
+ * All code paths that set `repairing` should go through this helper to
174
+ * guarantee a future retry path.
175
+ */
176
+ private transitionToRepairing;
177
+ /**
178
+ * Schedule a retry for a failed repair. Uses exponential backoff.
179
+ * No-op if the link is already in `degraded_poll` (timer loop owns retries)
180
+ * or if a retry is already scheduled.
181
+ */
182
+ private scheduleRepairRetry;
183
+ /**
184
+ * Repair a single link. Deduplicates concurrent calls via `_activeRepairs`.
185
+ * If repair is already running for this link, returns the existing promise.
186
+ */
187
+ private repairLink;
188
+ /**
189
+ * Internal repair implementation. Runs SMT set reconciliation for a single
190
+ * link, then attempts to re-establish live subscriptions. If repair succeeds,
191
+ * transitions to `live`. If it fails, throws so callers (degraded_poll timer,
192
+ * startup) can handle retry scheduling.
193
+ */
194
+ private doRepairLink;
195
+ /**
196
+ * Close pull and push subscriptions for a specific link.
197
+ */
198
+ private closeLinkSubscriptions;
199
+ /**
200
+ * Transition a link to `degraded_poll` and start a per-link polling timer.
201
+ * The timer runs SMT reconciliation at a reduced frequency (30s with jitter)
202
+ * and attempts to re-establish live subscriptions after each successful repair.
203
+ */
204
+ private enterDegradedPoll;
87
205
  /**
88
206
  * Tears down all live subscriptions and push listeners.
89
207
  */
@@ -103,6 +221,12 @@ export declare class SyncEngineLevel implements SyncEngine {
103
221
  */
104
222
  private flushPendingPushes;
105
223
  private buildCursorKey;
224
+ /**
225
+ * Retrieves a stored progress token. Handles migration from old string cursors:
226
+ * if the stored value is a bare string (pre-ProgressToken format), it is treated
227
+ * as absent — the sync engine will do a full SMT reconciliation on first startup
228
+ * after upgrade, which is correct and safe.
229
+ */
106
230
  private getCursor;
107
231
  private setCursor;
108
232
  /**
@@ -147,13 +271,6 @@ export declare class SyncEngineLevel implements SyncEngine {
147
271
  * Returns a hex-encoded root hash string.
148
272
  */
149
273
  private getRemoteRoot;
150
- /**
151
- * Walks the local and remote SMTs in parallel, recursing into subtrees whose
152
- * hashes differ, until reaching `MAX_DIFF_DEPTH` where leaves are enumerated.
153
- *
154
- * Returns the sets of messageCids that exist only locally or only remotely.
155
- */
156
- private walkTreeDiff;
157
274
  /**
158
275
  * Compute the diff between local and remote in a single HTTP round-trip.
159
276
  *
@@ -184,7 +301,6 @@ export declare class SyncEngineLevel implements SyncEngine {
184
301
  * In remote mode: constructs a signed MessagesSync message and routes through RPC.
185
302
  */
186
303
  private getLocalSubtreeHash;
187
- private getRemoteSubtreeHash;
188
304
  /**
189
305
  * Get all leaf messageCids under a given prefix from the local DWN.
190
306
  *
@@ -192,7 +308,6 @@ export declare class SyncEngineLevel implements SyncEngine {
192
308
  * In remote mode: constructs a signed MessagesSync message and routes through RPC.
193
309
  */
194
310
  private getLocalLeaves;
195
- private getRemoteLeaves;
196
311
  /**
197
312
  * Fetches missing messages from the remote DWN and processes them locally
198
313
  * in dependency order (topological sort).
@@ -202,6 +317,17 @@ export declare class SyncEngineLevel implements SyncEngine {
202
317
  * Only `messageCids` that were NOT prefetched are fetched individually.
203
318
  */
204
319
  private pullMessages;
320
+ /**
321
+ * Evicts expired entries from the echo-loop suppression cache.
322
+ * Also enforces the size cap by evicting oldest entries first.
323
+ */
324
+ private evictExpiredEchoEntries;
325
+ /**
326
+ * Checks whether a CID was recently pulled from a specific remote endpoint
327
+ * and should not be pushed back to that same endpoint (echo-loop suppression).
328
+ * Does not suppress pushes to other endpoints — multi-provider fan-out works.
329
+ */
330
+ private isRecentlyPulled;
205
331
  /**
206
332
  * Reads missing messages from the local DWN and pushes them to the remote DWN
207
333
  * in dependency order (topological sort).
@@ -1 +1 @@
1
- {"version":3,"file":"sync-engine-level.d.ts","sourceRoot":"","sources":["../../src/sync-engine-level.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sync-engine-level.d.ts","sourceRoot":"","sources":["../../src/sync-engine-level.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAGpD,OAAO,KAAK,EAAE,cAAc,EAAkI,MAAM,mBAAmB,CAAC;AASxL,OAAO,KAAK,EAAc,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAoC,eAAe,EAAE,qBAAqB,EAAE,UAAU,EAAa,iBAAiB,EAAE,mBAAmB,EAAuB,MAAM,iBAAiB,CAAC;AAapM,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,CAAC,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,EAAE,CAAC,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC,CAAC;CAClD,CAAC;AA0HF,qBAAa,eAAgB,YAAW,UAAU;IAChD;;;;;OAKG;IACH,OAAO,CAAC,MAAM,CAAC,CAAqB;IAEpC;;OAEG;IACH,OAAO,CAAC,eAAe,CAAiB;IAExC,OAAO,CAAC,GAAG,CAA8C;IACzD,OAAO,CAAC,eAAe,CAAC,CAAiC;IACzD,OAAO,CAAC,SAAS,CAAS;IAE1B;;;;;OAKG;IACH,OAAO,CAAC,OAAO,CAAC,CAAoB;IAEpC;;;;OAIG;IACH,OAAO,CAAC,YAAY,CAAgD;IAEpE;;;;;OAKG;IACH,OAAO,CAAC,aAAa,CAA4C;IAEjE;;;;OAIG;IACH,OAAO,CAAC,eAAe,CAAC,CAAsB;IAM9C,6CAA6C;IAC7C,OAAO,CAAC,SAAS,CAAoB;IAErC;;;;;OAKG;IACH,OAAO,CAAC,eAAe,CAAK;IAE5B,8EAA8E;IAC9E,OAAO,CAAC,kBAAkB,CAA0B;IAEpD,+EAA+E;IAC/E,OAAO,CAAC,mBAAmB,CAA2B;IAEtD,2DAA2D;IAC3D,OAAO,CAAC,kBAAkB,CAAoC;IAE9D,gDAAgD;IAChD,OAAO,CAAC,kBAAkB,CAAC,CAAgC;IAE3D,oDAAoD;IACpD,OAAO,CAAC,eAAe,CAAqC;IAE5D,qFAAqF;IACrF,OAAO,CAAC,gBAAgB,CAGT;IAEf;;;;;OAKG;IACH,OAAO,CAAC,mBAAmB,CAAkC;IAE7D,0DAA0D;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAAU;IAEtD;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAoD;IAE5E,0DAA0D;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,yBAAyB,CAAU;IAE3D,yEAAyE;IACzE,OAAO,CAAC,oBAAoB,CAAK;IAEjC,4DAA4D;IAC5D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,wBAAwB,CAAK;IAErD,wFAAwF;IACxF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,sBAAsB,CAAK;gBAEvC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,EAAE,qBAAqB;IAM1D,gDAAgD;IAChD,OAAO,KAAK,MAAM,GAKjB;IAED;;;;;OAKG;IACH,IAAI,KAAK,IAAI,kBAAkB,CAM9B;IAED,IAAI,KAAK,CAAC,KAAK,EAAE,kBAAkB,EAGlC;IAED,IAAI,iBAAiB,IAAI,qBAAqB,CAkB7C;IAEM,EAAE,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI;IAKlD,qDAAqD;IACrD,OAAO,CAAC,SAAS;IAUJ,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAItB,gBAAgB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,mBAAmB,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcjG,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU9C,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,mBAAmB,GAAG,SAAS,CAAC;IAkBzE,qBAAqB,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,mBAAmB,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAcrG,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA6GhD,SAAS,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAuB9D;;;OAGG;IACU,QAAQ,CAAC,OAAO,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;YAwB9C,aAAa;IA6C3B;;;;;;OAMG;YACW,aAAa;IA8F3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IA2B1B,gFAAgF;IAChF,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAK;IAEhD,8CAA8C;IAC9C,OAAO,CAAC,mBAAmB,CAA0D;IAErF,wCAAwC;IACxC,OAAO,CAAC,eAAe,CAAkC;IAEzD,sFAAsF;IACtF,OAAO,CAAC,cAAc,CAAyC;IAE/D,mEAAmE;IACnE,OAAO,CAAC,kBAAkB,CAAyD;IAEnF,0DAA0D;IAC1D,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,iBAAiB,CAA0B;IAEnE;;;;;OAKG;IACH,OAAO,CAAC,cAAc,CAA2D;IAEjF;;;;;;;;OAQG;YACW,qBAAqB;IAiCnC;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAqC3B;;;OAGG;IACH,OAAO,CAAC,UAAU;IAWlB;;;;;OAKG;YACW,YAAY;IAgI1B;;OAEG;YACW,sBAAsB;IAsBpC;;;;OAIG;YACW,iBAAiB;IA6D/B;;OAEG;YACW,gBAAgB;IA4D9B;;;OAGG;YACW,wBAAwB;IAiUtC;;;OAGG;YACW,yBAAyB;IAgHvC;;OAEG;YACW,kBAAkB;IA8FhC,OAAO,CAAC,cAAc;IAKtB;;;;;OAKG;YACW,SAAS;YA0BT,SAAS;IASvB;;;;OAIG;IACH,OAAO,CAAC,iBAAiB;IA6BzB;;;OAGG;YACW,iBAAiB;IAa/B;;;;OAIG;IACH,OAAO,CAAC,MAAM,CAAC,cAAc;IAQ7B;;;;;;;;;OASG;IACH,OAAO,KAAK,UAAU,GAKrB;IAED;;;;;;;OAOG;YACW,YAAY;IA0B1B;;;OAGG;YACW,aAAa;IA8B3B;;;;;;;;;;;;OAYG;YACW,cAAc;IAoD5B;;;;;;;OAOG;YACW,yBAAyB;IA6CvC;;;;;OAKG;YACW,mBAAmB;IA6BjC;;;;;OAKG;YACW,cAAc;IAgC5B;;;;;;;OAOG;YACW,YAAY;IAmB1B;;;OAGG;IACH,OAAO,CAAC,uBAAuB;IAsB/B;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAWxB;;;OAGG;YACW,YAAY;IAkB1B;;;OAGG;WACW,eAAe,CAAC,CAAC,SAAS;QAAE,OAAO,EAAE,cAAc,CAAA;KAAE,EACjE,QAAQ,EAAE,CAAC,EAAE,GACZ,CAAC,EAAE;IAIN;;OAEG;YACW,cAAc;IAsC5B;;;OAGG;YACW,wBAAwB;CAcvC"}
@@ -1,5 +1,6 @@
1
1
  import type { EnboxPlatformAgent } from './types/agent.js';
2
2
  import type { PermissionsApi } from './types/permissions.js';
3
+ import type { PushResult } from './types/sync.js';
3
4
  import type { GenericMessage, MessagesSyncDiffEntry, UnionMessageReply } from '@enbox/dwn-sdk-js';
4
5
  /** Entry type for fetched messages with optional data stream and retry buffer. */
5
6
  export type SyncMessageEntry = {
@@ -56,6 +57,10 @@ export declare function fetchRemoteMessages({ did, dwnUrl, delegateDid, protocol
56
57
  * Messages are fetched first, then sorted in dependency order (topological sort)
57
58
  * so that initial writes come before updates, and ProtocolsConfigures come before
58
59
  * records that reference those protocols.
60
+ *
61
+ * Returns a {@link PushResult} with per-CID outcome tracking instead of throwing
62
+ * on the first failure. Callers use this to advance the push checkpoint
63
+ * incrementally — only up to the highest contiguous success.
59
64
  */
60
65
  export declare function pushMessages({ did, dwnUrl, delegateDid, protocol, messageCids, agent, permissionsApi }: {
61
66
  did: string;
@@ -65,7 +70,7 @@ export declare function pushMessages({ did, dwnUrl, delegateDid, protocol, messa
65
70
  messageCids: string[];
66
71
  agent: EnboxPlatformAgent;
67
72
  permissionsApi: PermissionsApi;
68
- }): Promise<void>;
73
+ }): Promise<PushResult>;
69
74
  /**
70
75
  * Reads a message from the local DWN by its CID using MessagesRead.
71
76
  */
@@ -1 +1 @@
1
- {"version":3,"file":"sync-messages.d.ts","sourceRoot":"","sources":["../../src/sync-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAqB,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAWrH,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACxC,8FAA8F;IAC9F,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAS9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5E;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACzH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gGAAgG;IAChG,UAAU,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACrC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFhB;AA4DD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACpH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoE9B;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC7G,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAiChB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC1G,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAmCxC"}
1
+ {"version":3,"file":"sync-messages.d.ts","sourceRoot":"","sources":["../../src/sync-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAqB,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAWrH,kFAAkF;AAClF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,cAAc,CAAC;IACxB,UAAU,CAAC,EAAE,cAAc,CAAC,UAAU,CAAC,CAAC;IACxC,8FAA8F;IAC9F,YAAY,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAS9E;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAM5E;AAED;;;;;;;;GAQG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACzH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,gGAAgG;IAChG,UAAU,CAAC,EAAE,qBAAqB,EAAE,CAAC;IACrC,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,IAAI,CAAC,CAoFhB;AA4DD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IACpH,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAoE9B;AAED;;;;;;;;;GASG;AACH,wBAAsB,YAAY,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC7G,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,UAAU,CAAC,CA2CtB;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE;IAC1G,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,kBAAkB,CAAC;IAC1B,cAAc,EAAE,cAAc,CAAC;CAChC,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAmCxC"}
@@ -0,0 +1,72 @@
1
+ import type { AbstractLevel } from 'abstract-level';
2
+ import type { ProgressToken } from '@enbox/dwn-sdk-js';
3
+ import type { DirectionCheckpoint, LinkStatus, ReplicationLinkState, SyncScope } from './types/sync.js';
4
+ /**
5
+ * Durable replication ledger — persists {@link ReplicationLinkState} for each
6
+ * sync link in a LevelDB sublevel. Provides CRUD operations and replication
7
+ * checkpoint helpers.
8
+ *
9
+ * Key format: `{tenantDid}^{remoteEndpoint}^{scopeId}`
10
+ *
11
+ * Each link tracks independent pull and push {@link DirectionCheckpoint}s.
12
+ * The ledger does not own subscriptions or timers — it is a passive state
13
+ * store called by the sync engine.
14
+ */
15
+ export declare class ReplicationLedger {
16
+ private readonly db;
17
+ private sublevel;
18
+ constructor(db: AbstractLevel<string | Buffer | Uint8Array>);
19
+ /** Build the compound key for a link. */
20
+ private static buildKey;
21
+ /**
22
+ * Get-or-create a link. If the link does not exist, it is created with
23
+ * `initializing` status and empty checkpoints.
24
+ */
25
+ getOrCreateLink(params: {
26
+ tenantDid: string;
27
+ remoteEndpoint: string;
28
+ scope: SyncScope;
29
+ delegateDid?: string;
30
+ protocol?: string;
31
+ }): Promise<ReplicationLinkState>;
32
+ /** Persist the current state of a link. */
33
+ saveLink(link: ReplicationLinkState): Promise<void>;
34
+ /** Delete a link. */
35
+ deleteLink(tenantDid: string, remoteEndpoint: string, scopeId: string): Promise<void>;
36
+ /** List all links for a tenant. */
37
+ getLinksForTenant(tenantDid: string): Promise<ReplicationLinkState[]>;
38
+ /** List all links. */
39
+ getAllLinks(): Promise<ReplicationLinkState[]>;
40
+ /** Transition a link to a new status and persist. */
41
+ setStatus(link: ReplicationLinkState, status: LinkStatus): Promise<void>;
42
+ /**
43
+ * Compare two tokens by position (BigInt numeric comparison).
44
+ * Returns negative if a < b, zero if equal, positive if a > b.
45
+ * Caller must verify streamId and epoch match before calling.
46
+ */
47
+ static comparePosition(a: ProgressToken, b: ProgressToken): number;
48
+ /**
49
+ * Check whether a token belongs to the same domain (streamId + epoch) as
50
+ * the checkpoint's current baseline. Returns `true` if domains match or if
51
+ * the checkpoint has no baseline yet.
52
+ */
53
+ static validateTokenDomain(checkpoint: DirectionCheckpoint, token: ProgressToken): boolean;
54
+ /**
55
+ * Update `receivedToken` to the highest seen token (for observability).
56
+ * Does NOT advance `contiguousAppliedToken` — that is owned by the engine's
57
+ * delivery-order tracking.
58
+ */
59
+ static setReceivedToken(checkpoint: DirectionCheckpoint, token: ProgressToken): void;
60
+ /**
61
+ * Commit a token as the new contiguous applied baseline. The caller (engine)
62
+ * must have already verified that all earlier delivered tokens for this link
63
+ * are durably committed before calling this.
64
+ */
65
+ static commitContiguousToken(checkpoint: DirectionCheckpoint, token: ProgressToken): void;
66
+ /**
67
+ * Reset a replication checkpoint (e.g., after repair or domain change).
68
+ * Clears all state.
69
+ */
70
+ static resetCheckpoint(checkpoint: DirectionCheckpoint, token?: ProgressToken): void;
71
+ }
72
+ //# sourceMappingURL=sync-replication-ledger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync-replication-ledger.d.ts","sourceRoot":"","sources":["../../src/sync-replication-ledger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,mBAAmB,EAAE,UAAU,EAAE,oBAAoB,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAOxG;;;;;;;;;;GAUG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,EAAE,CAA8C;IACjE,OAAO,CAAC,QAAQ,CAAC;gBAEL,EAAE,EAAE,aAAa,CAAC,MAAM,GAAG,MAAM,GAAG,UAAU,CAAC;IAS3D,yCAAyC;IACzC,OAAO,CAAC,MAAM,CAAC,QAAQ;IAYvB;;;OAGG;IACU,eAAe,CAAC,MAAM,EAAE;QACnC,SAAS,EAAG,MAAM,CAAC;QACnB,cAAc,EAAG,MAAM,CAAC;QACxB,KAAK,EAAG,SAAS,CAAC;QAClB,WAAW,CAAC,EAAG,MAAM,CAAC;QACtB,QAAQ,CAAC,EAAG,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAoCjC,2CAA2C;IAC9B,QAAQ,CAAC,IAAI,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMhE,qBAAqB;IACR,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKlG,mCAAmC;IACtB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAWlF,sBAAsB;IACT,WAAW,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAY3D,qDAAqD;IACxC,SAAS,CAAC,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IASrF;;;;OAIG;WACW,eAAe,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,MAAM;IAOzE;;;;OAIG;WACW,mBAAmB,CAAC,UAAU,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO;IAMjG;;;;OAIG;WACW,gBAAgB,CAAC,UAAU,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI;IAS3F;;;;OAIG;WACW,qBAAqB,CAAC,UAAU,EAAE,mBAAmB,EAAE,KAAK,EAAE,aAAa,GAAG,IAAI;IAIhG;;;OAGG;WACW,eAAe,CAAC,UAAU,EAAE,mBAAmB,EAAE,KAAK,CAAC,EAAE,aAAa,GAAG,IAAI;CAI5F"}