@cello-protocol/daemon 0.0.168 → 0.0.169

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 (80) hide show
  1. package/dist/daemon.d.ts.map +1 -1
  2. package/dist/daemon.js +115 -265
  3. package/dist/daemon.js.map +1 -1
  4. package/dist/document-amendment-store.d.ts +94 -46
  5. package/dist/document-amendment-store.d.ts.map +1 -1
  6. package/dist/document-amendment-store.js +217 -102
  7. package/dist/document-amendment-store.js.map +1 -1
  8. package/dist/document-delivery-transport.d.ts +41 -52
  9. package/dist/document-delivery-transport.d.ts.map +1 -1
  10. package/dist/document-delivery-transport.js +6 -156
  11. package/dist/document-delivery-transport.js.map +1 -1
  12. package/dist/document-frame-router.d.ts +13 -17
  13. package/dist/document-frame-router.d.ts.map +1 -1
  14. package/dist/document-frame-router.js +21 -93
  15. package/dist/document-frame-router.js.map +1 -1
  16. package/dist/document-handlers.d.ts +1 -1
  17. package/dist/document-handlers.d.ts.map +1 -1
  18. package/dist/document-handlers.js +462 -511
  19. package/dist/document-handlers.js.map +1 -1
  20. package/dist/document-handshake.d.ts +4 -1
  21. package/dist/document-handshake.d.ts.map +1 -1
  22. package/dist/document-handshake.js +3 -1
  23. package/dist/document-handshake.js.map +1 -1
  24. package/dist/document-inbound.d.ts +18 -5
  25. package/dist/document-inbound.d.ts.map +1 -1
  26. package/dist/document-inbound.js +94 -110
  27. package/dist/document-inbound.js.map +1 -1
  28. package/dist/document-layer.d.ts +28 -67
  29. package/dist/document-layer.d.ts.map +1 -1
  30. package/dist/document-layer.js +655 -565
  31. package/dist/document-layer.js.map +1 -1
  32. package/dist/document-lifecycle.d.ts +11 -157
  33. package/dist/document-lifecycle.d.ts.map +1 -1
  34. package/dist/document-lifecycle.js +26 -568
  35. package/dist/document-lifecycle.js.map +1 -1
  36. package/dist/document-publish.d.ts +13 -0
  37. package/dist/document-publish.d.ts.map +1 -1
  38. package/dist/document-publish.js +19 -11
  39. package/dist/document-publish.js.map +1 -1
  40. package/dist/document-reconcile-engine.d.ts +66 -0
  41. package/dist/document-reconcile-engine.d.ts.map +1 -0
  42. package/dist/document-reconcile-engine.js +225 -0
  43. package/dist/document-reconcile-engine.js.map +1 -0
  44. package/dist/document-reconcile-scheduler.d.ts +91 -0
  45. package/dist/document-reconcile-scheduler.d.ts.map +1 -0
  46. package/dist/document-reconcile-scheduler.js +153 -0
  47. package/dist/document-reconcile-scheduler.js.map +1 -0
  48. package/dist/document-rejection.d.ts +2 -0
  49. package/dist/document-rejection.d.ts.map +1 -1
  50. package/dist/document-rejection.js +5 -1
  51. package/dist/document-rejection.js.map +1 -1
  52. package/dist/document-store.d.ts +18 -247
  53. package/dist/document-store.d.ts.map +1 -1
  54. package/dist/document-store.js +95 -827
  55. package/dist/document-store.js.map +1 -1
  56. package/dist/initiate-session-handler.d.ts +5 -0
  57. package/dist/initiate-session-handler.d.ts.map +1 -1
  58. package/dist/initiate-session-handler.js +1 -0
  59. package/dist/initiate-session-handler.js.map +1 -1
  60. package/package.json +5 -5
  61. package/dist/delivery-sweep-bound.d.ts +0 -79
  62. package/dist/delivery-sweep-bound.d.ts.map +0 -1
  63. package/dist/delivery-sweep-bound.js +0 -109
  64. package/dist/delivery-sweep-bound.js.map +0 -1
  65. package/dist/document-ack-inbound.d.ts +0 -71
  66. package/dist/document-ack-inbound.d.ts.map +0 -1
  67. package/dist/document-ack-inbound.js +0 -210
  68. package/dist/document-ack-inbound.js.map +0 -1
  69. package/dist/document-control-notifier.d.ts +0 -124
  70. package/dist/document-control-notifier.d.ts.map +0 -1
  71. package/dist/document-control-notifier.js +0 -176
  72. package/dist/document-control-notifier.js.map +0 -1
  73. package/dist/document-delivery.d.ts +0 -250
  74. package/dist/document-delivery.d.ts.map +0 -1
  75. package/dist/document-delivery.js +0 -608
  76. package/dist/document-delivery.js.map +0 -1
  77. package/dist/document-join-store.d.ts +0 -80
  78. package/dist/document-join-store.d.ts.map +0 -1
  79. package/dist/document-join-store.js +0 -197
  80. package/dist/document-join-store.js.map +0 -1
@@ -1,72 +1,120 @@
1
1
  /**
2
- * DOD-MP-AMEND-1 (daemon half) — the append-only amendment store.
2
+ * SYNC-P1 (daemon half) — the fork-tolerant entry store.
3
3
  *
4
- * One row per epoch per document, holding the amendment AS RECEIVED the wire bytes, never a
5
- * re-encode. The bytes are the truth: `chain` decodes them on read, so what replay consumes is
6
- * exactly what was signed, and a codec asymmetry can never silently rewrite an agreed record
7
- * (the class of defect TRACE-1 found in the proposal codec).
4
+ * One row per ENTRY (keyed by entry hash never by an epoch slot), holding the entry AS
5
+ * RECEIVED — the wire bytes, never a re-encode. The bytes are the truth: `chain` decodes them on
6
+ * read, so what the fold consumes is exactly what was signed, and a codec asymmetry can never
7
+ * silently rewrite an agreed record (the class of defect TRACE-1 found in the proposal codec).
8
8
  *
9
- * The store owns persistence and chain SHAPE:
10
- * - **Contiguity** epoch N appends only onto N-1 rows. An out-of-order arrival is refused by
11
- * name, not buffered; amendment-lag buffering is DOD-MP-INBOUND-N-1's design, and until it
12
- * lands the honest behaviour is a loud refusal the sender retries.
13
- * - **Fork refusal** a different amendment at an occupied epoch is `document_amendment_conflict`,
14
- * first record kept. Two rivals for one epoch is a governance fork; absorbing either silently
15
- * would have two holders replay different arrangements with no error anywhere.
16
- * - **Idempotent redelivery** — the same bytes again is `recorded: false`, not an error and not a
17
- * second row.
9
+ * The store owns persistence and ANCESTRY CLOSURE:
10
+ * - **Held until whole (R14)** an entry lands in `document_entries` only when every parent has
11
+ * landed. Otherwise it waits in `document_entries_pending`: recorded, never applied, never in a
12
+ * watermark, promoted the moment its ancestry completes cascade included. The invariant this
13
+ * buys: everything in `document_entries` has its FULL ancestry there too.
14
+ * - **Fork tolerance** two entries claiming the same epoch or the same author seq are BOTH
15
+ * stored. Ruling on conflicts is the causal fold's job (`deriveDocumentState`), not the
16
+ * store's; the old chain-gap and epoch-conflict refusals are gone WITH the epoch spine.
17
+ * - **Idempotent redelivery** — the same bytes again is `recorded: false`, not an error and not
18
+ * a second row.
19
+ * - **Watermarks** — per author, the highest CONTIGUOUS seq with its head hash(es). Two heads at
20
+ * one seq is an equivocation made visible for the exchange to resolve, never silently picked.
18
21
  *
19
- * What the store does NOT judge: signatures, policy, subject semantics. `deriveArrangement`
20
- * (protocol-types) rules on those at every consumption, and the inbound path rules BEFORE
21
- * appending. A row in this table is a claim to be replayed, not an admitted fact.
22
+ * What the store does NOT judge: signatures, policy, subject semantics. The fold rules on those
23
+ * at every consumption, and the inbound path rules BEFORE appending. A row in these tables is a
24
+ * claim to be folded, not an admitted fact.
22
25
  */
23
26
  import { type DocumentAmendmentEnvelope } from "@cello-protocol/protocol-types";
24
27
  import type { DaemonDatabase } from "./sqlcipher-db.js";
25
28
  import type { Logger } from "./types.js";
26
29
  /**
27
- * Shared with `DocumentStore`, which also execs this (the :353 shared-definition precedent there):
28
- * every epoch producer already holds a DocumentStore, and `currentDocumentEpoch` reads this table
29
- * through it so the table must exist whichever module constructs first. Keep the two consumers
30
- * on THIS one string.
30
+ * The PRE-PIVOT table, epoch-keyed. Still created because `DocumentStore` execs this too and the
31
+ * pre-pivot readers live until P4 deletes them (SYNC-D2); the entry store neither reads nor
32
+ * writes it. Rows predating the pivot stay untouched old-shape bytes are not decodable by the
33
+ * v2 codec and are not migrated (no compatibility owed; essentially no documents exist).
34
+ */
35
+ /**
36
+ * Shared with `DocumentStore` (the :352 shared-definition precedent): its membership walk and
37
+ * epoch read consume `document_entries`, so the tables must exist whichever module constructs
38
+ * first. Keep both consumers on THIS string.
31
39
  */
32
- export declare const DOCUMENT_AMENDMENTS_CREATE_SQL = "\n CREATE TABLE IF NOT EXISTS document_amendments (\n owner_agent_id TEXT NOT NULL,\n document_id TEXT NOT NULL,\n epoch_id INTEGER NOT NULL,\n amendment_hash TEXT NOT NULL,\n received_bytes BLOB NOT NULL,\n recorded_at INTEGER NOT NULL,\n PRIMARY KEY (owner_agent_id, document_id, epoch_id)\n );\n";
33
- export interface MembershipVerdict {
34
- state: "holder" | "removed" | "untouched";
35
- epochId: number | null;
36
- }
37
40
  /**
38
- * The last membership event naming this agent in an ordered chain ONE implementation, because
39
- * two walks (the inbound refusal's and the publish gate's) disagreeing about whether someone was
40
- * removed is two daemons disagreeing about the arrangement.
41
+ * D7 the epoch spine is deleted. A database born before that carries a NOT NULL `epoch_id`
42
+ * with no default, which would refuse every insert from this build. Dropped in place (SQLite
43
+ * ≥3.35 / SQLCipher 4.5); a fresh database never has it.
41
44
  */
42
- export declare function walkMembership(chain: readonly DocumentAmendmentEnvelope[], agentId: string): MembershipVerdict;
45
+ type ColumnDropper = {
46
+ exec(sql: string): void;
47
+ prepare(sql: string): {
48
+ all(...a: unknown[]): unknown[];
49
+ };
50
+ };
51
+ /**
52
+ * Drop columns a previous milestone left behind, birth-gated: only what the table actually still
53
+ * has is touched, so this is safe on a database created yesterday and on one created before the
54
+ * column existed. Dead schema is not free — it is the design a future author reads and rebuilds.
55
+ */
56
+ export declare function dropLegacyColumns(db: ColumnDropper, table: string, columns: readonly string[]): void;
57
+ export declare function dropLegacyEpochColumn(db: ColumnDropper, table: string): void;
58
+ export declare const DOCUMENT_ENTRIES_CREATE_SQL = "\n CREATE TABLE IF NOT EXISTS document_entries (\n owner_agent_id TEXT NOT NULL,\n document_id TEXT NOT NULL,\n entry_hash TEXT NOT NULL,\n author_agent_id TEXT NOT NULL,\n author_seq INTEGER NOT NULL,\n received_bytes BLOB NOT NULL,\n recorded_at INTEGER NOT NULL,\n PRIMARY KEY (owner_agent_id, document_id, entry_hash)\n );\n CREATE INDEX IF NOT EXISTS idx_document_entries_author\n ON document_entries (owner_agent_id, document_id, author_agent_id, author_seq);\n CREATE TABLE IF NOT EXISTS document_entries_pending (\n owner_agent_id TEXT NOT NULL,\n document_id TEXT NOT NULL,\n entry_hash TEXT NOT NULL,\n author_agent_id TEXT NOT NULL,\n received_bytes BLOB NOT NULL,\n recorded_at INTEGER NOT NULL,\n PRIMARY KEY (owner_agent_id, document_id, entry_hash)\n );\n";
43
59
  export interface AmendmentAppendResult {
44
- /** False on an idempotent redelivery — the row already existed with the same hash. */
60
+ /** False on an idempotent redelivery — the entry (or its pending row) already existed. */
45
61
  recorded: boolean;
46
- epochId: number;
47
- /** Hex of the amendment's TBS hash. */
48
- amendmentHash: string;
62
+ /** True when the entry is waiting on missing parents (R14) — recorded but not yet applied. */
63
+ held: boolean;
64
+ /** Hex of the entry's TBS hash. */
65
+ entryHash: string;
66
+ /** Previously-held entries this arrival completed, now applied — envelopes included, so the
67
+ * caller can run the same post-apply surfacing it runs for a direct arrival (review F2: the
68
+ * held path silently dropped removal notices and lifecycle completion). */
69
+ promoted: PromotedEntry[];
70
+ }
71
+ export interface PromotedEntry {
72
+ entryHash: string;
73
+ envelope: DocumentAmendmentEnvelope;
74
+ }
75
+ export interface PendingEntry {
76
+ entryHash: string;
77
+ /** The parents not yet held — the exchange asks for exactly these. */
78
+ missingParents: string[];
79
+ recordedAtMs: number;
80
+ }
81
+ /**
82
+ * Ceiling on HELD entries per (document, author). An honest author's pending set is a short gap
83
+ * awaiting one delivery; a hostile known author fabricating parents could otherwise grow the
84
+ * pending table without bound (review F4).
85
+ */
86
+ export declare const MAX_PENDING_PER_AUTHOR = 64;
87
+ export interface AuthorWatermark {
88
+ /** Highest CONTIGUOUS seq held from this author. */
89
+ seq: number;
90
+ /** Entry hash(es) at that seq — more than one is an equivocation, visible by design. */
91
+ headHashes: string[];
49
92
  }
50
93
  export declare class DocumentAmendmentStore {
51
94
  #private;
52
95
  constructor(db: DaemonDatabase, logger: Logger);
53
96
  /**
54
- * Append one amendment from its wire bytes. Decodes first — malformed bytes refuse with the
55
- * decoder's named reason and nothing is stored.
97
+ * Append one entry from its wire bytes. Decodes first — malformed bytes refuse with the
98
+ * decoder's named reason and nothing is stored. An entry with missing parents is HELD; an
99
+ * arrival that completes held ancestry promotes the whole cascade.
56
100
  */
57
101
  append(ownerAgentId: string, documentId: string, receivedBytes: Uint8Array, nowMs: number): AmendmentAppendResult;
58
- /** The ordered chain, decoded from the stored received bytes. */
102
+ /** Every applied entry, decoded from the stored received bytes. The set is ancestry-closed. */
59
103
  chain(ownerAgentId: string, documentId: string): DocumentAmendmentEnvelope[];
104
+ /** Held entries and exactly which parents they still wait on (R37's receiver-side record). */
105
+ pending(ownerAgentId: string, documentId: string): PendingEntry[];
106
+ /**
107
+ * This author's applied entries with seq strictly beyond `afterSeq`, as WIRE BYTES in seq
108
+ * order — what a reconcile reply carries to a peer whose watermark for this author is behind
109
+ * ours (R10 step 2/3). Forked seqs both ship: the peer's fold rules on them like ours did.
110
+ */
111
+ entriesByAuthorAfter(ownerAgentId: string, documentId: string, authorAgentId: string, afterSeq: number): Uint8Array[];
60
112
  /**
61
- * DOD-MP-REMOVE-1 this agent's LAST membership event in the recorded chain.
62
- * "holder" = admitted (or never touched by any membership amendment genesis membership is
63
- * the CALLER's fact, not this table's); "removed" = the last event naming them was
64
- * remove_holder, with the epoch it happened at, so a refusal can name the removal rather than
65
- * a generic condition. Reads the recorded chain only — validity was ruled before append
66
- * (the standing invariant).
113
+ * Per-author position: the highest CONTIGUOUS seq held and the head hash(es) at it. A held
114
+ * (pending) entry is not counted a gap ends the walk (R13: report contiguous, never highest
115
+ * received).
67
116
  */
68
- membershipOf(ownerAgentId: string, documentId: string, agentId: string): MembershipVerdict;
69
- /** The highest recorded epoch, or 0 — genesis — when no amendment exists. */
70
- currentEpoch(ownerAgentId: string, documentId: string): number;
117
+ watermarks(ownerAgentId: string, documentId: string): Map<string, AuthorWatermark>;
71
118
  }
119
+ export {};
72
120
  //# sourceMappingURL=document-amendment-store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"document-amendment-store.d.ts","sourceRoot":"","sources":["../src/document-amendment-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;GAKG;AACH,eAAO,MAAM,8BAA8B,oWAU1C,CAAC;AAEF,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,QAAQ,GAAG,SAAS,GAAG,WAAW,CAAC;IAC1C,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,yBAAyB,EAAE,EAC3C,OAAO,EAAE,MAAM,GACd,iBAAiB,CAcnB;AAED,MAAM,WAAW,qBAAqB;IACpC,sFAAsF;IACtF,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,uCAAuC;IACvC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,sBAAsB;;gBAIrB,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM;IAM9C;;;OAGG;IACH,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,UAAU,EACzB,KAAK,EAAE,MAAM,GACZ,qBAAqB;IAmExB,iEAAiE;IACjE,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,yBAAyB,EAAE;IAW5E;;;;;;;OAOG;IACH,YAAY,CACV,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,iBAAiB;IAIpB,6EAA6E;IAC7E,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM;CAS/D"}
1
+ {"version":3,"file":"document-amendment-store.d.ts","sourceRoot":"","sources":["../src/document-amendment-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,EAGL,KAAK,yBAAyB,EAC/B,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACxD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;GAKG;AACH;;;;GAIG;AACH;;;;GAIG;AACH,KAAK,aAAa,GAAG;IAAE,IAAI,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAAA;KAAE,CAAA;CAAE,CAAC;AAE5G;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAOpG;AAED,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAE5E;AAED,eAAO,MAAM,2BAA2B,63BAsBvC,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,0FAA0F;IAC1F,QAAQ,EAAE,OAAO,CAAC;IAClB,8FAA8F;IAC9F,IAAI,EAAE,OAAO,CAAC;IACd,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB;;gFAE4E;IAC5E,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,yBAAyB,CAAC;CACrC;AAED,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAEzC,MAAM,WAAW,eAAe;IAC9B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,wFAAwF;IACxF,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,qBAAa,sBAAsB;;gBAIrB,EAAE,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM;IAW9C;;;;OAIG;IACH,MAAM,CACJ,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,UAAU,EACzB,KAAK,EAAE,MAAM,GACZ,qBAAqB;IA0DxB,+FAA+F;IAC/F,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,yBAAyB,EAAE;IAW5E,8FAA8F;IAC9F,OAAO,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,YAAY,EAAE;IAwBjE;;;;OAIG;IACH,oBAAoB,CAClB,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,EAClB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACf,UAAU,EAAE;IAaf;;;;OAIG;IACH,UAAU,CAAC,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,GAAG,CAAC,MAAM,EAAE,eAAe,CAAC;CAqInF"}
@@ -1,76 +1,90 @@
1
1
  /**
2
- * DOD-MP-AMEND-1 (daemon half) — the append-only amendment store.
2
+ * SYNC-P1 (daemon half) — the fork-tolerant entry store.
3
3
  *
4
- * One row per epoch per document, holding the amendment AS RECEIVED the wire bytes, never a
5
- * re-encode. The bytes are the truth: `chain` decodes them on read, so what replay consumes is
6
- * exactly what was signed, and a codec asymmetry can never silently rewrite an agreed record
7
- * (the class of defect TRACE-1 found in the proposal codec).
4
+ * One row per ENTRY (keyed by entry hash never by an epoch slot), holding the entry AS
5
+ * RECEIVED — the wire bytes, never a re-encode. The bytes are the truth: `chain` decodes them on
6
+ * read, so what the fold consumes is exactly what was signed, and a codec asymmetry can never
7
+ * silently rewrite an agreed record (the class of defect TRACE-1 found in the proposal codec).
8
8
  *
9
- * The store owns persistence and chain SHAPE:
10
- * - **Contiguity** epoch N appends only onto N-1 rows. An out-of-order arrival is refused by
11
- * name, not buffered; amendment-lag buffering is DOD-MP-INBOUND-N-1's design, and until it
12
- * lands the honest behaviour is a loud refusal the sender retries.
13
- * - **Fork refusal** a different amendment at an occupied epoch is `document_amendment_conflict`,
14
- * first record kept. Two rivals for one epoch is a governance fork; absorbing either silently
15
- * would have two holders replay different arrangements with no error anywhere.
16
- * - **Idempotent redelivery** — the same bytes again is `recorded: false`, not an error and not a
17
- * second row.
9
+ * The store owns persistence and ANCESTRY CLOSURE:
10
+ * - **Held until whole (R14)** an entry lands in `document_entries` only when every parent has
11
+ * landed. Otherwise it waits in `document_entries_pending`: recorded, never applied, never in a
12
+ * watermark, promoted the moment its ancestry completes cascade included. The invariant this
13
+ * buys: everything in `document_entries` has its FULL ancestry there too.
14
+ * - **Fork tolerance** two entries claiming the same epoch or the same author seq are BOTH
15
+ * stored. Ruling on conflicts is the causal fold's job (`deriveDocumentState`), not the
16
+ * store's; the old chain-gap and epoch-conflict refusals are gone WITH the epoch spine.
17
+ * - **Idempotent redelivery** — the same bytes again is `recorded: false`, not an error and not
18
+ * a second row.
19
+ * - **Watermarks** — per author, the highest CONTIGUOUS seq with its head hash(es). Two heads at
20
+ * one seq is an equivocation made visible for the exchange to resolve, never silently picked.
18
21
  *
19
- * What the store does NOT judge: signatures, policy, subject semantics. `deriveArrangement`
20
- * (protocol-types) rules on those at every consumption, and the inbound path rules BEFORE
21
- * appending. A row in this table is a claim to be replayed, not an admitted fact.
22
+ * What the store does NOT judge: signatures, policy, subject semantics. The fold rules on those
23
+ * at every consumption, and the inbound path rules BEFORE appending. A row in these tables is a
24
+ * claim to be folded, not an admitted fact.
22
25
  */
23
26
  import { decodeDocumentAmendment, documentAmendmentHash, } from "@cello-protocol/protocol-types";
24
27
  /**
25
- * Shared with `DocumentStore`, which also execs this (the :353 shared-definition precedent there):
26
- * every epoch producer already holds a DocumentStore, and `currentDocumentEpoch` reads this table
27
- * through it so the table must exist whichever module constructs first. Keep the two consumers
28
- * on THIS one string.
28
+ * Drop columns a previous milestone left behind, birth-gated: only what the table actually still
29
+ * has is touched, so this is safe on a database created yesterday and on one created before the
30
+ * column existed. Dead schema is not free it is the design a future author reads and rebuilds.
29
31
  */
30
- export const DOCUMENT_AMENDMENTS_CREATE_SQL = `
31
- CREATE TABLE IF NOT EXISTS document_amendments (
32
+ export function dropLegacyColumns(db, table, columns) {
33
+ const held = new Set(db.prepare(`PRAGMA table_info(${table})`).all().map((c) => c.name));
34
+ for (const column of columns) {
35
+ if (held.has(column))
36
+ db.exec(`ALTER TABLE ${table} DROP COLUMN ${column}`);
37
+ }
38
+ }
39
+ export function dropLegacyEpochColumn(db, table) {
40
+ dropLegacyColumns(db, table, ["epoch_id"]);
41
+ }
42
+ export const DOCUMENT_ENTRIES_CREATE_SQL = `
43
+ CREATE TABLE IF NOT EXISTS document_entries (
44
+ owner_agent_id TEXT NOT NULL,
45
+ document_id TEXT NOT NULL,
46
+ entry_hash TEXT NOT NULL,
47
+ author_agent_id TEXT NOT NULL,
48
+ author_seq INTEGER NOT NULL,
49
+ received_bytes BLOB NOT NULL,
50
+ recorded_at INTEGER NOT NULL,
51
+ PRIMARY KEY (owner_agent_id, document_id, entry_hash)
52
+ );
53
+ CREATE INDEX IF NOT EXISTS idx_document_entries_author
54
+ ON document_entries (owner_agent_id, document_id, author_agent_id, author_seq);
55
+ CREATE TABLE IF NOT EXISTS document_entries_pending (
32
56
  owner_agent_id TEXT NOT NULL,
33
57
  document_id TEXT NOT NULL,
34
- epoch_id INTEGER NOT NULL,
35
- amendment_hash TEXT NOT NULL,
58
+ entry_hash TEXT NOT NULL,
59
+ author_agent_id TEXT NOT NULL,
36
60
  received_bytes BLOB NOT NULL,
37
61
  recorded_at INTEGER NOT NULL,
38
- PRIMARY KEY (owner_agent_id, document_id, epoch_id)
62
+ PRIMARY KEY (owner_agent_id, document_id, entry_hash)
39
63
  );
40
64
  `;
41
65
  /**
42
- * The last membership event naming this agent in an ordered chain ONE implementation, because
43
- * two walks (the inbound refusal's and the publish gate's) disagreeing about whether someone was
44
- * removed is two daemons disagreeing about the arrangement.
66
+ * Ceiling on HELD entries per (document, author). An honest author's pending set is a short gap
67
+ * awaiting one delivery; a hostile known author fabricating parents could otherwise grow the
68
+ * pending table without bound (review F4).
45
69
  */
46
- export function walkMembership(chain, agentId) {
47
- let state = "untouched";
48
- let epochId = null;
49
- for (const env of chain) {
50
- if (env.body.subject_agent_id !== agentId)
51
- continue;
52
- if (env.body.kind === "add_holder") {
53
- state = "holder";
54
- epochId = env.body.epoch_id;
55
- }
56
- else if (env.body.kind === "remove_holder") {
57
- state = "removed";
58
- epochId = env.body.epoch_id;
59
- }
60
- }
61
- return { state, epochId };
62
- }
70
+ export const MAX_PENDING_PER_AUTHOR = 64;
63
71
  export class DocumentAmendmentStore {
64
72
  #db;
65
73
  #logger;
66
74
  constructor(db, logger) {
67
75
  this.#db = db;
68
76
  this.#logger = logger;
69
- this.#db.exec(DOCUMENT_AMENDMENTS_CREATE_SQL);
77
+ // D7/D9 residue sweep (review F5/F6): the epoch-keyed legacy table and the withdrawals
78
+ // table have no reader or writer left — never born on a fresh database, dropped in place
79
+ // on one that predates the pivot.
80
+ this.#db.exec(`DROP TABLE IF EXISTS document_amendments`);
81
+ this.#db.exec(DOCUMENT_ENTRIES_CREATE_SQL);
82
+ dropLegacyEpochColumn(this.#db, "document_entries");
70
83
  }
71
84
  /**
72
- * Append one amendment from its wire bytes. Decodes first — malformed bytes refuse with the
73
- * decoder's named reason and nothing is stored.
85
+ * Append one entry from its wire bytes. Decodes first — malformed bytes refuse with the
86
+ * decoder's named reason and nothing is stored. An entry with missing parents is HELD; an
87
+ * arrival that completes held ancestry promotes the whole cascade.
74
88
  */
75
89
  append(ownerAgentId, documentId, receivedBytes, nowMs) {
76
90
  const env = decodeDocumentAmendment(receivedBytes);
@@ -78,74 +92,175 @@ export class DocumentAmendmentStore {
78
92
  throw new Error(`document_amendment_wrong_document: the bytes name ${env.body.document_id}, appending ` +
79
93
  `under ${documentId}`);
80
94
  }
81
- const epochId = env.body.epoch_id;
82
95
  const hash = Buffer.from(documentAmendmentHash(env.body)).toString("hex");
83
- const existing = this.#db
84
- .prepare(`SELECT amendment_hash FROM document_amendments
85
- WHERE owner_agent_id = ? AND document_id = ? AND epoch_id = ?`)
86
- .get(ownerAgentId, documentId, epochId);
87
- if (existing) {
88
- if (existing.amendment_hash === hash) {
89
- return { recorded: false, epochId, amendmentHash: hash };
96
+ if (this.#hasEntry(ownerAgentId, documentId, hash)) {
97
+ return { recorded: false, held: false, entryHash: hash, promoted: [] };
98
+ }
99
+ if (this.#hasPending(ownerAgentId, documentId, hash)) {
100
+ return { recorded: false, held: true, entryHash: hash, promoted: [] };
101
+ }
102
+ const missing = env.body.parents.filter((p) => !this.#hasEntry(ownerAgentId, documentId, p));
103
+ if (missing.length > 0) {
104
+ const author = env.body.author_agent_id;
105
+ const backlog = this.#db
106
+ .prepare(`SELECT COUNT(*) AS n FROM document_entries_pending
107
+ WHERE owner_agent_id = ? AND document_id = ? AND author_agent_id = ?`)
108
+ .get(ownerAgentId, documentId, author);
109
+ if (backlog.n >= MAX_PENDING_PER_AUTHOR) {
110
+ throw new Error(`document_pending_cap: ${author} already has ${backlog.n} entries held awaiting ` +
111
+ `parents — the ceiling is ${MAX_PENDING_PER_AUTHOR}, and an honest gap is never ` +
112
+ `this deep; deliver the missing ancestry first`);
90
113
  }
91
- this.#logger.error("document.amendment.conflict", {
114
+ this.#db
115
+ .prepare(`INSERT INTO document_entries_pending
116
+ (owner_agent_id, document_id, entry_hash, author_agent_id, received_bytes, recorded_at)
117
+ VALUES (?, ?, ?, ?, ?, ?)`)
118
+ .run(ownerAgentId, documentId, hash, author, Buffer.from(receivedBytes), nowMs);
119
+ this.#logger.info("document.entry.held", {
92
120
  documentId,
93
- epochId,
94
- storedHash: existing.amendment_hash,
95
- rivalHash: hash,
121
+ entryHash: hash,
122
+ author: env.body.author_agent_id,
123
+ authorSeq: env.body.author_seq,
124
+ kind: env.body.kind,
125
+ missingParents: missing,
96
126
  });
97
- throw new Error(`document_amendment_conflict: epoch ${epochId} of ${documentId} already holds ` +
98
- `${existing.amendment_hash} and a rival amendment ${hash} arrived — a governance fork, ` +
99
- `refused with the first record kept`);
100
- }
101
- const prior = this.currentEpoch(ownerAgentId, documentId);
102
- if (epochId !== prior + 1) {
103
- throw new Error(`document_amendment_chain_gap: epoch ${epochId} cannot append onto epoch ${prior} — ` +
104
- `amendments land contiguously, and an out-of-order arrival is retried by its sender, ` +
105
- `never buffered silently`);
127
+ return { recorded: true, held: true, entryHash: hash, promoted: [] };
106
128
  }
107
- this.#db
108
- .prepare(`INSERT INTO document_amendments
109
- (owner_agent_id, document_id, epoch_id, amendment_hash, received_bytes, recorded_at)
110
- VALUES (?, ?, ?, ?, ?, ?)`)
111
- .run(ownerAgentId, documentId, epochId, hash,
112
- // Copied — the caller may reuse or zero its buffer after we return.
113
- Buffer.from(receivedBytes), nowMs);
114
- this.#logger.info("document.amendment.recorded", {
115
- documentId,
116
- epochId,
117
- amendmentHash: hash,
118
- kind: env.body.kind,
119
- });
120
- return { recorded: true, epochId, amendmentHash: hash };
129
+ this.#insertEntry(ownerAgentId, documentId, hash, env, receivedBytes, nowMs);
130
+ const promoted = this.#promoteReady(ownerAgentId, documentId, nowMs);
131
+ return { recorded: true, held: false, entryHash: hash, promoted };
121
132
  }
122
- /** The ordered chain, decoded from the stored received bytes. */
133
+ /** Every applied entry, decoded from the stored received bytes. The set is ancestry-closed. */
123
134
  chain(ownerAgentId, documentId) {
124
135
  const rows = this.#db
125
- .prepare(`SELECT received_bytes FROM document_amendments
136
+ .prepare(`SELECT received_bytes FROM document_entries
126
137
  WHERE owner_agent_id = ? AND document_id = ?
127
- ORDER BY epoch_id ASC`)
138
+ ORDER BY author_seq ASC, entry_hash ASC`)
128
139
  .all(ownerAgentId, documentId);
129
140
  return rows.map((r) => decodeDocumentAmendment(new Uint8Array(r.received_bytes)));
130
141
  }
142
+ /** Held entries and exactly which parents they still wait on (R37's receiver-side record). */
143
+ pending(ownerAgentId, documentId) {
144
+ const rows = this.#db
145
+ .prepare(`SELECT entry_hash, received_bytes, recorded_at FROM document_entries_pending
146
+ WHERE owner_agent_id = ? AND document_id = ?
147
+ ORDER BY recorded_at ASC, entry_hash ASC`)
148
+ .all(ownerAgentId, documentId);
149
+ return rows.map((r) => {
150
+ const env = decodeDocumentAmendment(new Uint8Array(r.received_bytes));
151
+ return {
152
+ entryHash: r.entry_hash,
153
+ missingParents: env.body.parents.filter((p) => !this.#hasEntry(ownerAgentId, documentId, p)),
154
+ recordedAtMs: r.recorded_at,
155
+ };
156
+ });
157
+ }
158
+ /**
159
+ * This author's applied entries with seq strictly beyond `afterSeq`, as WIRE BYTES in seq
160
+ * order — what a reconcile reply carries to a peer whose watermark for this author is behind
161
+ * ours (R10 step 2/3). Forked seqs both ship: the peer's fold rules on them like ours did.
162
+ */
163
+ entriesByAuthorAfter(ownerAgentId, documentId, authorAgentId, afterSeq) {
164
+ const rows = this.#db
165
+ .prepare(`SELECT received_bytes FROM document_entries
166
+ WHERE owner_agent_id = ? AND document_id = ? AND author_agent_id = ? AND author_seq > ?
167
+ ORDER BY author_seq ASC, entry_hash ASC`)
168
+ .all(ownerAgentId, documentId, authorAgentId, afterSeq);
169
+ return rows.map((r) => new Uint8Array(r.received_bytes));
170
+ }
131
171
  /**
132
- * DOD-MP-REMOVE-1 this agent's LAST membership event in the recorded chain.
133
- * "holder" = admitted (or never touched by any membership amendment genesis membership is
134
- * the CALLER's fact, not this table's); "removed" = the last event naming them was
135
- * remove_holder, with the epoch it happened at, so a refusal can name the removal rather than
136
- * a generic condition. Reads the recorded chain only — validity was ruled before append
137
- * (the standing invariant).
172
+ * Per-author position: the highest CONTIGUOUS seq held and the head hash(es) at it. A held
173
+ * (pending) entry is not counted a gap ends the walk (R13: report contiguous, never highest
174
+ * received).
138
175
  */
139
- membershipOf(ownerAgentId, documentId, agentId) {
140
- return walkMembership(this.chain(ownerAgentId, documentId), agentId);
176
+ watermarks(ownerAgentId, documentId) {
177
+ const rows = this.#db
178
+ .prepare(`SELECT author_agent_id, author_seq, entry_hash FROM document_entries
179
+ WHERE owner_agent_id = ? AND document_id = ?
180
+ ORDER BY author_agent_id ASC, author_seq ASC, entry_hash ASC`)
181
+ .all(ownerAgentId, documentId);
182
+ const byAuthor = new Map();
183
+ for (const r of rows) {
184
+ let seqs = byAuthor.get(r.author_agent_id);
185
+ if (!seqs) {
186
+ seqs = new Map();
187
+ byAuthor.set(r.author_agent_id, seqs);
188
+ }
189
+ const at = seqs.get(r.author_seq);
190
+ if (at)
191
+ at.push(r.entry_hash);
192
+ else
193
+ seqs.set(r.author_seq, [r.entry_hash]);
194
+ }
195
+ const out = new Map();
196
+ for (const [author, seqs] of byAuthor) {
197
+ let seq = 0;
198
+ while (seqs.has(seq + 1))
199
+ seq++;
200
+ if (seq === 0)
201
+ continue;
202
+ out.set(author, { seq, headHashes: seqs.get(seq) });
203
+ }
204
+ return out;
205
+ }
206
+ #hasEntry(ownerAgentId, documentId, hash) {
207
+ return (this.#db
208
+ .prepare(`SELECT 1 FROM document_entries
209
+ WHERE owner_agent_id = ? AND document_id = ? AND entry_hash = ?`)
210
+ .get(ownerAgentId, documentId, hash) !== undefined);
211
+ }
212
+ #hasPending(ownerAgentId, documentId, hash) {
213
+ return (this.#db
214
+ .prepare(`SELECT 1 FROM document_entries_pending
215
+ WHERE owner_agent_id = ? AND document_id = ? AND entry_hash = ?`)
216
+ .get(ownerAgentId, documentId, hash) !== undefined);
141
217
  }
142
- /** The highest recorded epoch, or 0 — genesis — when no amendment exists. */
143
- currentEpoch(ownerAgentId, documentId) {
144
- const r = this.#db
145
- .prepare(`SELECT MAX(epoch_id) AS max_epoch FROM document_amendments
146
- WHERE owner_agent_id = ? AND document_id = ?`)
147
- .get(ownerAgentId, documentId);
148
- return r?.max_epoch ?? 0;
218
+ #insertEntry(ownerAgentId, documentId, hash, env, bytes, nowMs) {
219
+ this.#db
220
+ .prepare(`INSERT INTO document_entries
221
+ (owner_agent_id, document_id, entry_hash, author_agent_id, author_seq,
222
+ received_bytes, recorded_at)
223
+ VALUES (?, ?, ?, ?, ?, ?, ?)`)
224
+ .run(ownerAgentId, documentId, hash, env.body.author_agent_id, env.body.author_seq,
225
+ // Copied — the caller may reuse or zero its buffer after we return.
226
+ Buffer.from(bytes), nowMs);
227
+ this.#logger.info("document.entry.recorded", {
228
+ documentId,
229
+ entryHash: hash,
230
+ author: env.body.author_agent_id,
231
+ authorSeq: env.body.author_seq,
232
+ kind: env.body.kind,
233
+ });
234
+ }
235
+ /** Move every pending entry whose ancestry is now complete — repeated until a pass moves none. */
236
+ #promoteReady(ownerAgentId, documentId, nowMs) {
237
+ const promoted = [];
238
+ for (;;) {
239
+ const rows = this.#db
240
+ .prepare(`SELECT entry_hash, received_bytes FROM document_entries_pending
241
+ WHERE owner_agent_id = ? AND document_id = ?`)
242
+ .all(ownerAgentId, documentId);
243
+ let movedThisPass = false;
244
+ for (const row of rows) {
245
+ const env = decodeDocumentAmendment(new Uint8Array(row.received_bytes));
246
+ const ready = env.body.parents.every((p) => this.#hasEntry(ownerAgentId, documentId, p));
247
+ if (!ready)
248
+ continue;
249
+ this.#insertEntry(ownerAgentId, documentId, row.entry_hash, env, new Uint8Array(row.received_bytes), nowMs);
250
+ this.#db
251
+ .prepare(`DELETE FROM document_entries_pending
252
+ WHERE owner_agent_id = ? AND document_id = ? AND entry_hash = ?`)
253
+ .run(ownerAgentId, documentId, row.entry_hash);
254
+ this.#logger.info("document.entry.promoted", {
255
+ documentId,
256
+ entryHash: row.entry_hash,
257
+ });
258
+ promoted.push({ entryHash: row.entry_hash, envelope: env });
259
+ movedThisPass = true;
260
+ }
261
+ if (!movedThisPass)
262
+ return promoted;
263
+ }
149
264
  }
150
265
  }
151
266
  //# sourceMappingURL=document-amendment-store.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"document-amendment-store.js","sourceRoot":"","sources":["../src/document-amendment-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"document-amendment-store.js","sourceRoot":"","sources":["../src/document-amendment-store.ts"],"names":[],"mappings":"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"}