@sekiban/dcb-runtime 0.2.0

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 (153) hide show
  1. package/LICENSE +86 -0
  2. package/README.md +13 -0
  3. package/dist/allocator/AllocatorDurableObject.d.ts +36 -0
  4. package/dist/allocator/AllocatorDurableObject.js +658 -0
  5. package/dist/allocator/IssuanceLedger.d.ts +188 -0
  6. package/dist/allocator/IssuanceLedger.js +608 -0
  7. package/dist/allocator/IssuanceReconciler.d.ts +41 -0
  8. package/dist/allocator/IssuanceReconciler.js +191 -0
  9. package/dist/allocator/OrderClock.d.ts +41 -0
  10. package/dist/allocator/OrderClock.js +92 -0
  11. package/dist/allocator/SortableUniqueId.d.ts +46 -0
  12. package/dist/allocator/SortableUniqueId.js +156 -0
  13. package/dist/allocator/types.d.ts +52 -0
  14. package/dist/allocator/types.js +1 -0
  15. package/dist/bootstrap/BootstrapCoordinatorDurableObject.d.ts +28 -0
  16. package/dist/bootstrap/BootstrapCoordinatorDurableObject.js +357 -0
  17. package/dist/bootstrap/BootstrapStoreAdapter.d.ts +51 -0
  18. package/dist/bootstrap/BootstrapStoreAdapter.js +162 -0
  19. package/dist/bootstrap/OperatorBootstrap.d.ts +20 -0
  20. package/dist/bootstrap/OperatorBootstrap.js +104 -0
  21. package/dist/bootstrap/manifest.d.ts +9 -0
  22. package/dist/bootstrap/manifest.js +115 -0
  23. package/dist/bootstrap/types.d.ts +75 -0
  24. package/dist/bootstrap/types.js +1 -0
  25. package/dist/cli/OperatorRepairCli.d.ts +11 -0
  26. package/dist/cli/OperatorRepairCli.js +108 -0
  27. package/dist/cloudflare.d.ts +164 -0
  28. package/dist/cloudflare.js +19487 -0
  29. package/dist/commit/CommitWorker.d.ts +101 -0
  30. package/dist/commit/CommitWorker.js +921 -0
  31. package/dist/commit/types.d.ts +25 -0
  32. package/dist/commit/types.js +13 -0
  33. package/dist/completeness/GlobalCompletenessReconciler.d.ts +77 -0
  34. package/dist/completeness/GlobalCompletenessReconciler.js +572 -0
  35. package/dist/completeness/types.d.ts +85 -0
  36. package/dist/completeness/types.js +6 -0
  37. package/dist/composition.d.ts +123 -0
  38. package/dist/composition.js +237 -0
  39. package/dist/cosmos.d.ts +11 -0
  40. package/dist/cosmos.js +1411 -0
  41. package/dist/d1-mv.d.ts +8 -0
  42. package/dist/d1-mv.js +2001 -0
  43. package/dist/d1.d.ts +16 -0
  44. package/dist/d1.js +3418 -0
  45. package/dist/diagnostics/G60DurableHop.d.ts +99 -0
  46. package/dist/diagnostics/G60DurableHop.js +248 -0
  47. package/dist/diagnostics/G65Admission.d.ts +23 -0
  48. package/dist/diagnostics/G65Admission.js +43 -0
  49. package/dist/diagnostics/G65DirectRing.d.ts +33 -0
  50. package/dist/diagnostics/G65DirectRing.js +85 -0
  51. package/dist/diagnostics/G69AdmissionAttempt.d.ts +43 -0
  52. package/dist/diagnostics/G69AdmissionAttempt.js +22 -0
  53. package/dist/downstream/DeliveryCore.d.ts +127 -0
  54. package/dist/downstream/DeliveryCore.js +304 -0
  55. package/dist/downstream/Doorbell.d.ts +43 -0
  56. package/dist/downstream/Doorbell.js +137 -0
  57. package/dist/downstream/DownstreamAdapter.d.ts +52 -0
  58. package/dist/downstream/DownstreamAdapter.js +299 -0
  59. package/dist/downstream/ExclusionLookup.d.ts +36 -0
  60. package/dist/downstream/ExclusionLookup.js +50 -0
  61. package/dist/downstream/InconsistencyDetector.d.ts +27 -0
  62. package/dist/downstream/InconsistencyDetector.js +82 -0
  63. package/dist/downstream/OutboxDrain.d.ts +35 -0
  64. package/dist/downstream/OutboxDrain.js +126 -0
  65. package/dist/downstream/types.d.ts +77 -0
  66. package/dist/downstream/types.js +64 -0
  67. package/dist/eventIdentity.d.ts +30 -0
  68. package/dist/eventIdentity.js +49 -0
  69. package/dist/eventRecord.d.ts +26 -0
  70. package/dist/eventRecord.js +53 -0
  71. package/dist/g42-probe.d.ts +9 -0
  72. package/dist/g42-probe.js +9 -0
  73. package/dist/http/SerializedQueryWorker.d.ts +58 -0
  74. package/dist/http/SerializedQueryWorker.js +497 -0
  75. package/dist/http/commitResponse.d.ts +46 -0
  76. package/dist/http/commitResponse.js +80 -0
  77. package/dist/http/testServiceId.d.ts +17 -0
  78. package/dist/http/testServiceId.js +14 -0
  79. package/dist/index.d.ts +112 -0
  80. package/dist/index.js +19926 -0
  81. package/dist/journal/JournalDurableObject.d.ts +30 -0
  82. package/dist/journal/JournalDurableObject.js +481 -0
  83. package/dist/journal/JournalFirstTouchProbe.d.ts +190 -0
  84. package/dist/journal/JournalFirstTouchProbe.js +375 -0
  85. package/dist/journal/types.d.ts +116 -0
  86. package/dist/journal/types.js +52 -0
  87. package/dist/mv/MaterializedViewCatchUp.d.ts +60 -0
  88. package/dist/mv/MaterializedViewCatchUp.js +353 -0
  89. package/dist/mv/MaterializedViewRuntime.d.ts +80 -0
  90. package/dist/mv/MaterializedViewRuntime.js +328 -0
  91. package/dist/mv/MaterializedViewStore.d.ts +257 -0
  92. package/dist/mv/MaterializedViewStore.js +875 -0
  93. package/dist/mv/UnsafeWindowMaterializedView.d.ts +112 -0
  94. package/dist/mv/UnsafeWindowMaterializedView.js +495 -0
  95. package/dist/mv/index.d.ts +8 -0
  96. package/dist/mv/index.js +2357 -0
  97. package/dist/projection/LiveProjectionWorker.d.ts +86 -0
  98. package/dist/projection/LiveProjectionWorker.js +240 -0
  99. package/dist/projection/ProjectionRuntime.d.ts +113 -0
  100. package/dist/projection/ProjectionRuntime.js +346 -0
  101. package/dist/projection/ProjectorRegistry.d.ts +51 -0
  102. package/dist/projection/ProjectorRegistry.js +116 -0
  103. package/dist/query/ProjectionQueryStore.d.ts +102 -0
  104. package/dist/query/ProjectionQueryStore.js +185 -0
  105. package/dist/query/QueryRegistry.d.ts +22 -0
  106. package/dist/query/QueryRegistry.js +36 -0
  107. package/dist/read/SerializedReadWorker.d.ts +36 -0
  108. package/dist/read/SerializedReadWorker.js +225 -0
  109. package/dist/repair/RepairWorker.d.ts +72 -0
  110. package/dist/repair/RepairWorker.js +461 -0
  111. package/dist/safeWindow.d.ts +20 -0
  112. package/dist/safeWindow.js +36 -0
  113. package/dist/scope/ControlRouteScope.d.ts +22 -0
  114. package/dist/scope/ControlRouteScope.js +36 -0
  115. package/dist/scope/ScopeName.d.ts +34 -0
  116. package/dist/scope/ScopeName.js +67 -0
  117. package/dist/service/ServiceIdentityProvider.d.ts +35 -0
  118. package/dist/service/ServiceIdentityProvider.js +56 -0
  119. package/dist/store/CosmosEventStore.d.ts +126 -0
  120. package/dist/store/CosmosEventStore.js +950 -0
  121. package/dist/store/D1EventStore.d.ts +111 -0
  122. package/dist/store/D1EventStore.js +1111 -0
  123. package/dist/store/PostgresEventStore.d.ts +35 -0
  124. package/dist/store/PostgresEventStore.js +811 -0
  125. package/dist/store/provider.d.ts +25 -0
  126. package/dist/store/provider.js +32 -0
  127. package/dist/store/types.d.ts +205 -0
  128. package/dist/store/types.js +18 -0
  129. package/dist/tag/EventDigest.d.ts +40 -0
  130. package/dist/tag/EventDigest.js +158 -0
  131. package/dist/tag/TagDurableObject.d.ts +286 -0
  132. package/dist/tag/TagDurableObject.js +4071 -0
  133. package/dist/tag/TagSqlMeasurement.d.ts +26 -0
  134. package/dist/tag/TagSqlMeasurement.js +44 -0
  135. package/dist/tag/TagSqlSchema.d.ts +29 -0
  136. package/dist/tag/TagSqlSchema.js +211 -0
  137. package/dist/tag/types.d.ts +173 -0
  138. package/dist/tag/types.js +3 -0
  139. package/dist/tagstate/TagStateDurableObject.d.ts +57 -0
  140. package/dist/tagstate/TagStateDurableObject.js +499 -0
  141. package/dist/trace/AttributionRatio.d.ts +12 -0
  142. package/dist/trace/AttributionRatio.js +68 -0
  143. package/dist/trace/CloudflareTracing.d.ts +7 -0
  144. package/dist/trace/CloudflareTracing.js +9 -0
  145. package/dist/trace/CommitTrace.d.ts +405 -0
  146. package/dist/trace/CommitTrace.js +1008 -0
  147. package/dist/trace/CommitTraceConsoleSink.d.ts +68 -0
  148. package/dist/trace/CommitTraceConsoleSink.js +114 -0
  149. package/dist/trace/CommitTraceVerifier.d.ts +22 -0
  150. package/dist/trace/CommitTraceVerifier.js +295 -0
  151. package/dist/trace/ObservationStream.d.ts +118 -0
  152. package/dist/trace/ObservationStream.js +148 -0
  153. package/package.json +71 -0
@@ -0,0 +1,26 @@
1
+ /**
2
+ * G43's structural measurement harness. It is deliberately opt-in and holds
3
+ * no durable state: a test starts it immediately before a real Tag DO handler
4
+ * request and completes it only after response serialization. Every SQL
5
+ * cursor obtained through the handler is retained until final consumption, so
6
+ * counters are summed over the complete statement universe rather than a
7
+ * hand-selected query.
8
+ */
9
+ export interface G43MeasuredCursor {
10
+ readonly query: string;
11
+ readonly rowsRead: number;
12
+ readonly rowsWritten: number;
13
+ }
14
+ export interface G43SqlMeasurementSnapshot {
15
+ readonly statements: readonly string[];
16
+ readonly cursors: readonly G43MeasuredCursor[];
17
+ readonly rowsRead: number;
18
+ readonly rowsWritten: number;
19
+ }
20
+ export declare class G43SqlMeasurement {
21
+ private readonly statements;
22
+ private readonly cursors;
23
+ private completed;
24
+ instrument(sql: SqlStorage): SqlStorage;
25
+ complete(): G43SqlMeasurementSnapshot;
26
+ }
@@ -0,0 +1,44 @@
1
+ export class G43SqlMeasurement {
2
+ statements = [];
3
+ cursors = [];
4
+ completed = false;
5
+ instrument(sql) {
6
+ return new Proxy(sql, {
7
+ get: (target, property, receiver) => {
8
+ if (property === "exec") {
9
+ return (query, ...bindings) => {
10
+ if (this.completed)
11
+ throw new Error("G43 SQL measurement cannot observe a completed handler");
12
+ const cursor = target.exec(query, ...bindings);
13
+ this.statements.push(query);
14
+ this.cursors.push({
15
+ query,
16
+ cursor: cursor,
17
+ });
18
+ return cursor;
19
+ };
20
+ }
21
+ const value = Reflect.get(target, property, receiver);
22
+ return typeof value === "function" ? value.bind(target) : value;
23
+ },
24
+ });
25
+ }
26
+ complete() {
27
+ if (this.completed)
28
+ throw new Error("G43 SQL measurement is already complete");
29
+ this.completed = true;
30
+ const cursors = this.cursors.map(({ query, cursor }) => {
31
+ // SqlStorage cursor counters are only final after full enumeration. This
32
+ // consumes even write/no-row cursors, and makes an omitted statement
33
+ // impossible to hide behind a partial cursor read.
34
+ cursor.toArray();
35
+ return { query, rowsRead: cursor.rowsRead, rowsWritten: cursor.rowsWritten };
36
+ });
37
+ return Object.freeze({
38
+ statements: Object.freeze([...this.statements]),
39
+ cursors: Object.freeze(cursors),
40
+ rowsRead: cursors.reduce((sum, cursor) => sum + cursor.rowsRead, 0),
41
+ rowsWritten: cursors.reduce((sum, cursor) => sum + cursor.rowsWritten, 0),
42
+ });
43
+ }
44
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * SDT-G43's tag-local authority is intentionally a normal SQLite schema, not
3
+ * a serialized application record hidden behind a KV key. These statements
4
+ * are kept literal so schema review and `sqlite_master` introspection see the
5
+ * exact primary keys, uniqueness constraints, foreign keys, and indexes.
6
+ *
7
+ * Existing TAG_KEY records are deliberately not migrated. This repository is
8
+ * still in development and the operator ruling for G43 is to reset those test
9
+ * records rather than introduce a mixed-format or rollback protocol.
10
+ */
11
+ export declare const TAG_SQL_SCHEMA_DDL = "\n PRAGMA foreign_keys = ON;\n\n CREATE TABLE IF NOT EXISTS tag_identity (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n tag TEXT NOT NULL UNIQUE,\n created_at TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS tag_control (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n schema_version INTEGER NOT NULL CHECK (schema_version = 3),\n head_suid TEXT NOT NULL,\n clock_offset_ms INTEGER NOT NULL,\n clock_now_ms INTEGER,\n version INTEGER NOT NULL,\n repair_owner TEXT,\n repair_lease_until INTEGER,\n highest_repair_epoch INTEGER NOT NULL,\n repair_scope_version INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT\n );\n\n CREATE TABLE IF NOT EXISTS tag_reservation (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n attempt_id TEXT NOT NULL,\n epoch INTEGER NOT NULL,\n reservation_token TEXT NOT NULL UNIQUE,\n expected_head TEXT NOT NULL,\n expires_at INTEGER NOT NULL,\n alarm_due_at INTEGER NOT NULL,\n FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT\n );\n CREATE INDEX IF NOT EXISTS tag_reservation_due_idx ON tag_reservation(alarm_due_at);\n\n CREATE TABLE IF NOT EXISTS tag_epoch (\n attempt_id TEXT PRIMARY KEY,\n highest_epoch INTEGER NOT NULL,\n sealed_epoch INTEGER,\n confirmation_epoch INTEGER\n );\n\n CREATE TABLE IF NOT EXISTS tag_tombstone (\n attempt_id TEXT PRIMARY KEY,\n epoch INTEGER NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS tag_event (\n service_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n attempt_id TEXT NOT NULL,\n suid TEXT NOT NULL,\n payload TEXT NOT NULL,\n event_tags_json TEXT NOT NULL,\n allocator_lineage_id TEXT NOT NULL,\n event_type TEXT NOT NULL,\n provenance TEXT NOT NULL CHECK (provenance = 'g32'),\n timestamp TEXT NOT NULL,\n event_json TEXT NOT NULL,\n PRIMARY KEY (service_id, event_id),\n UNIQUE (suid)\n );\n CREATE INDEX IF NOT EXISTS tag_event_suid_idx ON tag_event(suid);\n CREATE INDEX IF NOT EXISTS tag_event_attempt_idx ON tag_event(attempt_id, event_id);\n\n CREATE TABLE IF NOT EXISTS tag_head (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n service_id TEXT NOT NULL,\n head_suid TEXT NOT NULL,\n FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT\n );\n\n CREATE TABLE IF NOT EXISTS tag_committed_membership (\n service_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n tag TEXT NOT NULL,\n committed_at TEXT NOT NULL,\n PRIMARY KEY (service_id, event_id, tag),\n FOREIGN KEY (service_id, event_id)\n REFERENCES tag_event(service_id, event_id) ON DELETE RESTRICT,\n FOREIGN KEY (tag) REFERENCES tag_identity(tag) ON DELETE RESTRICT\n );\n CREATE INDEX IF NOT EXISTS tag_committed_membership_tag_idx\n ON tag_committed_membership(tag, service_id, event_id);\n\n CREATE TABLE IF NOT EXISTS tag_outbox_obligation (\n obligation_sequence INTEGER PRIMARY KEY AUTOINCREMENT,\n service_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n attempt_id TEXT NOT NULL,\n suid TEXT NOT NULL,\n payload TEXT NOT NULL,\n allocator_lineage_id TEXT NOT NULL,\n event_type TEXT NOT NULL,\n provenance TEXT NOT NULL CHECK (provenance = 'g32'),\n timestamp TEXT NOT NULL,\n canonical_bytes BLOB NOT NULL,\n event_digest TEXT NOT NULL,\n declared_tag_set_json TEXT NOT NULL,\n local_committed_membership_json TEXT NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('pending', 'acknowledged', 'poison')),\n next_attempt_at INTEGER NOT NULL,\n attempt_count INTEGER NOT NULL DEFAULT 0,\n enqueued_at INTEGER,\n acknowledged_at INTEGER,\n last_error TEXT,\n UNIQUE (service_id, event_id, attempt_id),\n FOREIGN KEY (service_id, event_id)\n REFERENCES tag_event(service_id, event_id) ON DELETE RESTRICT\n );\n CREATE INDEX IF NOT EXISTS tag_outbox_obligation_due_idx\n ON tag_outbox_obligation(status, next_attempt_at, obligation_sequence);\n\n CREATE TABLE IF NOT EXISTS tag_source_partition_registration (\n service_id TEXT NOT NULL,\n partition_tag TEXT NOT NULL,\n last_obligation_sequence INTEGER NOT NULL,\n status TEXT NOT NULL CHECK (status IN ('pending', 'registered')),\n next_attempt_at INTEGER,\n attempt_count INTEGER NOT NULL DEFAULT 0,\n last_error TEXT,\n PRIMARY KEY (service_id, partition_tag)\n );\n CREATE INDEX IF NOT EXISTS tag_source_partition_registration_due_idx\n ON tag_source_partition_registration(status, next_attempt_at, service_id, partition_tag);\n\n CREATE TABLE IF NOT EXISTS tag_commit_receipt (\n attempt_id TEXT NOT NULL,\n epoch INTEGER NOT NULL,\n committed_at TEXT NOT NULL,\n committed_event_count INTEGER NOT NULL,\n head_suid TEXT NOT NULL,\n reservation_confirmed INTEGER NOT NULL CHECK (reservation_confirmed IN (0, 1)),\n PRIMARY KEY (attempt_id, epoch)\n );\n\n CREATE TABLE IF NOT EXISTS tag_fence (\n reason TEXT NOT NULL,\n attempt_id TEXT NOT NULL,\n epoch INTEGER NOT NULL,\n PRIMARY KEY (reason, attempt_id)\n );\n\n CREATE TABLE IF NOT EXISTS tag_cleared_fence (\n reason TEXT NOT NULL,\n attempt_id TEXT NOT NULL,\n epoch INTEGER NOT NULL,\n PRIMARY KEY (reason, attempt_id)\n );\n\n CREATE TABLE IF NOT EXISTS tag_bootstrap_admission (\n singleton INTEGER PRIMARY KEY CHECK (singleton = 1),\n import_id TEXT NOT NULL,\n lease_epoch INTEGER NOT NULL,\n manifest_digest TEXT NOT NULL,\n target_service_id TEXT NOT NULL,\n closed INTEGER NOT NULL CHECK (closed IN (0, 1)),\n FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT\n );\n\n CREATE TABLE IF NOT EXISTS tag_repair_scope (\n attempt_id TEXT NOT NULL,\n event_id TEXT NOT NULL,\n item_json TEXT NOT NULL,\n PRIMARY KEY (attempt_id, event_id)\n );\n";
12
+ /**
13
+ * Packet-owned AC8 range seam. The query text and index identity are exported
14
+ * so the measurement checker can prove exactly what was explained and what
15
+ * returned rows were compared against; no "equivalent" plan is accepted.
16
+ */
17
+ export declare const TAG_READ_AFTER_INDEX = "tag_event_suid_idx";
18
+ export declare const TAG_READ_AFTER_SQL = "\n SELECT event_json\n FROM tag_event INDEXED BY tag_event_suid_idx\n WHERE suid > ?\n ORDER BY suid ASC\n LIMIT ?\n";
19
+ /**
20
+ * SDT-G46's frozen-frontier form of the same G43 range index seam. It is not
21
+ * a second source path: a caller supplies the immutable `through` that the
22
+ * first `g43TagStateIncrementalCatchUp` page obtained from `readHeadFacts`.
23
+ */
24
+ export declare const TAG_READ_AFTER_THROUGH_SQL = "\n SELECT event_json\n FROM tag_event INDEXED BY tag_event_suid_idx\n WHERE suid > ? AND suid <= ?\n ORDER BY suid ASC\n LIMIT ?\n";
25
+ export declare function initializeTagSqlSchema(sql: SqlStorage): void;
26
+ /** A SQL-backed tag object always exposes this capability at runtime. */
27
+ export declare function hasTagSqlStorage(storage: DurableObjectStorage): storage is DurableObjectStorage & {
28
+ sql: SqlStorage;
29
+ };
@@ -0,0 +1,211 @@
1
+ /**
2
+ * SDT-G43's tag-local authority is intentionally a normal SQLite schema, not
3
+ * a serialized application record hidden behind a KV key. These statements
4
+ * are kept literal so schema review and `sqlite_master` introspection see the
5
+ * exact primary keys, uniqueness constraints, foreign keys, and indexes.
6
+ *
7
+ * Existing TAG_KEY records are deliberately not migrated. This repository is
8
+ * still in development and the operator ruling for G43 is to reset those test
9
+ * records rather than introduce a mixed-format or rollback protocol.
10
+ */
11
+ export const TAG_SQL_SCHEMA_DDL = `
12
+ PRAGMA foreign_keys = ON;
13
+
14
+ CREATE TABLE IF NOT EXISTS tag_identity (
15
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
16
+ tag TEXT NOT NULL UNIQUE,
17
+ created_at TEXT NOT NULL
18
+ );
19
+
20
+ CREATE TABLE IF NOT EXISTS tag_control (
21
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
22
+ schema_version INTEGER NOT NULL CHECK (schema_version = 3),
23
+ head_suid TEXT NOT NULL,
24
+ clock_offset_ms INTEGER NOT NULL,
25
+ clock_now_ms INTEGER,
26
+ version INTEGER NOT NULL,
27
+ repair_owner TEXT,
28
+ repair_lease_until INTEGER,
29
+ highest_repair_epoch INTEGER NOT NULL,
30
+ repair_scope_version INTEGER NOT NULL,
31
+ created_at TEXT NOT NULL,
32
+ updated_at TEXT NOT NULL,
33
+ FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT
34
+ );
35
+
36
+ CREATE TABLE IF NOT EXISTS tag_reservation (
37
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
38
+ attempt_id TEXT NOT NULL,
39
+ epoch INTEGER NOT NULL,
40
+ reservation_token TEXT NOT NULL UNIQUE,
41
+ expected_head TEXT NOT NULL,
42
+ expires_at INTEGER NOT NULL,
43
+ alarm_due_at INTEGER NOT NULL,
44
+ FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT
45
+ );
46
+ CREATE INDEX IF NOT EXISTS tag_reservation_due_idx ON tag_reservation(alarm_due_at);
47
+
48
+ CREATE TABLE IF NOT EXISTS tag_epoch (
49
+ attempt_id TEXT PRIMARY KEY,
50
+ highest_epoch INTEGER NOT NULL,
51
+ sealed_epoch INTEGER,
52
+ confirmation_epoch INTEGER
53
+ );
54
+
55
+ CREATE TABLE IF NOT EXISTS tag_tombstone (
56
+ attempt_id TEXT PRIMARY KEY,
57
+ epoch INTEGER NOT NULL
58
+ );
59
+
60
+ CREATE TABLE IF NOT EXISTS tag_event (
61
+ service_id TEXT NOT NULL,
62
+ event_id TEXT NOT NULL,
63
+ attempt_id TEXT NOT NULL,
64
+ suid TEXT NOT NULL,
65
+ payload TEXT NOT NULL,
66
+ event_tags_json TEXT NOT NULL,
67
+ allocator_lineage_id TEXT NOT NULL,
68
+ event_type TEXT NOT NULL,
69
+ provenance TEXT NOT NULL CHECK (provenance = 'g32'),
70
+ timestamp TEXT NOT NULL,
71
+ event_json TEXT NOT NULL,
72
+ PRIMARY KEY (service_id, event_id),
73
+ UNIQUE (suid)
74
+ );
75
+ CREATE INDEX IF NOT EXISTS tag_event_suid_idx ON tag_event(suid);
76
+ CREATE INDEX IF NOT EXISTS tag_event_attempt_idx ON tag_event(attempt_id, event_id);
77
+
78
+ CREATE TABLE IF NOT EXISTS tag_head (
79
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
80
+ service_id TEXT NOT NULL,
81
+ head_suid TEXT NOT NULL,
82
+ FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT
83
+ );
84
+
85
+ CREATE TABLE IF NOT EXISTS tag_committed_membership (
86
+ service_id TEXT NOT NULL,
87
+ event_id TEXT NOT NULL,
88
+ tag TEXT NOT NULL,
89
+ committed_at TEXT NOT NULL,
90
+ PRIMARY KEY (service_id, event_id, tag),
91
+ FOREIGN KEY (service_id, event_id)
92
+ REFERENCES tag_event(service_id, event_id) ON DELETE RESTRICT,
93
+ FOREIGN KEY (tag) REFERENCES tag_identity(tag) ON DELETE RESTRICT
94
+ );
95
+ CREATE INDEX IF NOT EXISTS tag_committed_membership_tag_idx
96
+ ON tag_committed_membership(tag, service_id, event_id);
97
+
98
+ CREATE TABLE IF NOT EXISTS tag_outbox_obligation (
99
+ obligation_sequence INTEGER PRIMARY KEY AUTOINCREMENT,
100
+ service_id TEXT NOT NULL,
101
+ event_id TEXT NOT NULL,
102
+ attempt_id TEXT NOT NULL,
103
+ suid TEXT NOT NULL,
104
+ payload TEXT NOT NULL,
105
+ allocator_lineage_id TEXT NOT NULL,
106
+ event_type TEXT NOT NULL,
107
+ provenance TEXT NOT NULL CHECK (provenance = 'g32'),
108
+ timestamp TEXT NOT NULL,
109
+ canonical_bytes BLOB NOT NULL,
110
+ event_digest TEXT NOT NULL,
111
+ declared_tag_set_json TEXT NOT NULL,
112
+ local_committed_membership_json TEXT NOT NULL,
113
+ status TEXT NOT NULL CHECK (status IN ('pending', 'acknowledged', 'poison')),
114
+ next_attempt_at INTEGER NOT NULL,
115
+ attempt_count INTEGER NOT NULL DEFAULT 0,
116
+ enqueued_at INTEGER,
117
+ acknowledged_at INTEGER,
118
+ last_error TEXT,
119
+ UNIQUE (service_id, event_id, attempt_id),
120
+ FOREIGN KEY (service_id, event_id)
121
+ REFERENCES tag_event(service_id, event_id) ON DELETE RESTRICT
122
+ );
123
+ CREATE INDEX IF NOT EXISTS tag_outbox_obligation_due_idx
124
+ ON tag_outbox_obligation(status, next_attempt_at, obligation_sequence);
125
+
126
+ CREATE TABLE IF NOT EXISTS tag_source_partition_registration (
127
+ service_id TEXT NOT NULL,
128
+ partition_tag TEXT NOT NULL,
129
+ last_obligation_sequence INTEGER NOT NULL,
130
+ status TEXT NOT NULL CHECK (status IN ('pending', 'registered')),
131
+ next_attempt_at INTEGER,
132
+ attempt_count INTEGER NOT NULL DEFAULT 0,
133
+ last_error TEXT,
134
+ PRIMARY KEY (service_id, partition_tag)
135
+ );
136
+ CREATE INDEX IF NOT EXISTS tag_source_partition_registration_due_idx
137
+ ON tag_source_partition_registration(status, next_attempt_at, service_id, partition_tag);
138
+
139
+ CREATE TABLE IF NOT EXISTS tag_commit_receipt (
140
+ attempt_id TEXT NOT NULL,
141
+ epoch INTEGER NOT NULL,
142
+ committed_at TEXT NOT NULL,
143
+ committed_event_count INTEGER NOT NULL,
144
+ head_suid TEXT NOT NULL,
145
+ reservation_confirmed INTEGER NOT NULL CHECK (reservation_confirmed IN (0, 1)),
146
+ PRIMARY KEY (attempt_id, epoch)
147
+ );
148
+
149
+ CREATE TABLE IF NOT EXISTS tag_fence (
150
+ reason TEXT NOT NULL,
151
+ attempt_id TEXT NOT NULL,
152
+ epoch INTEGER NOT NULL,
153
+ PRIMARY KEY (reason, attempt_id)
154
+ );
155
+
156
+ CREATE TABLE IF NOT EXISTS tag_cleared_fence (
157
+ reason TEXT NOT NULL,
158
+ attempt_id TEXT NOT NULL,
159
+ epoch INTEGER NOT NULL,
160
+ PRIMARY KEY (reason, attempt_id)
161
+ );
162
+
163
+ CREATE TABLE IF NOT EXISTS tag_bootstrap_admission (
164
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
165
+ import_id TEXT NOT NULL,
166
+ lease_epoch INTEGER NOT NULL,
167
+ manifest_digest TEXT NOT NULL,
168
+ target_service_id TEXT NOT NULL,
169
+ closed INTEGER NOT NULL CHECK (closed IN (0, 1)),
170
+ FOREIGN KEY (singleton) REFERENCES tag_identity(singleton) ON DELETE RESTRICT
171
+ );
172
+
173
+ CREATE TABLE IF NOT EXISTS tag_repair_scope (
174
+ attempt_id TEXT NOT NULL,
175
+ event_id TEXT NOT NULL,
176
+ item_json TEXT NOT NULL,
177
+ PRIMARY KEY (attempt_id, event_id)
178
+ );
179
+ `;
180
+ /**
181
+ * Packet-owned AC8 range seam. The query text and index identity are exported
182
+ * so the measurement checker can prove exactly what was explained and what
183
+ * returned rows were compared against; no "equivalent" plan is accepted.
184
+ */
185
+ export const TAG_READ_AFTER_INDEX = "tag_event_suid_idx";
186
+ export const TAG_READ_AFTER_SQL = `
187
+ SELECT event_json
188
+ FROM tag_event INDEXED BY tag_event_suid_idx
189
+ WHERE suid > ?
190
+ ORDER BY suid ASC
191
+ LIMIT ?
192
+ `;
193
+ /**
194
+ * SDT-G46's frozen-frontier form of the same G43 range index seam. It is not
195
+ * a second source path: a caller supplies the immutable `through` that the
196
+ * first `g43TagStateIncrementalCatchUp` page obtained from `readHeadFacts`.
197
+ */
198
+ export const TAG_READ_AFTER_THROUGH_SQL = `
199
+ SELECT event_json
200
+ FROM tag_event INDEXED BY tag_event_suid_idx
201
+ WHERE suid > ? AND suid <= ?
202
+ ORDER BY suid ASC
203
+ LIMIT ?
204
+ `;
205
+ export function initializeTagSqlSchema(sql) {
206
+ sql.exec(TAG_SQL_SCHEMA_DDL);
207
+ }
208
+ /** A SQL-backed tag object always exposes this capability at runtime. */
209
+ export function hasTagSqlStorage(storage) {
210
+ return typeof storage.sql?.exec === "function";
211
+ }
@@ -0,0 +1,173 @@
1
+ export declare const RESERVATION_WINDOW_MS = 30000;
2
+ export declare const PARTIAL_WRITE_FENCE_REASON = "partial_write";
3
+ export declare const SEGMENT_ROTATION_FENCE_REASON = "segment_rotation";
4
+ export interface TagEpoch {
5
+ attemptId: string;
6
+ epoch: number;
7
+ }
8
+ /**
9
+ * §3.1 consistency-entry spelling. F-001 preserves `lastSortedUniqueId`
10
+ * only for the §5.3 tag-state response, not for this request entry.
11
+ */
12
+ export interface TagConsistencyEntry {
13
+ tag: string;
14
+ lastSortableUniqueId: string | null;
15
+ }
16
+ export interface TagReservation {
17
+ attemptId: string;
18
+ epoch: number;
19
+ token: string;
20
+ expectedHead: string;
21
+ expiresAt: number;
22
+ alarmDueAt: number;
23
+ }
24
+ export interface TagEvent {
25
+ attemptId: string;
26
+ eventId: string;
27
+ suid: string;
28
+ payload: string;
29
+ eventTags: string[];
30
+ eventType: string;
31
+ provenance: "g32";
32
+ timestamp: string;
33
+ /** Internal allocator lineage belongs to the sidecar/outbox path. */
34
+ allocatorLineageId: string;
35
+ }
36
+ /**
37
+ * The single internal source-read request for TagStateDO. It is dispatched
38
+ * directly between Durable Objects through TagDurableObject's private
39
+ * adapter, never through the public Worker router. `through` is omitted only
40
+ * by the first page; the Tag DO then freezes it from scalar, identity-checked
41
+ * head facts.
42
+ */
43
+ export interface G43TagStateIncrementalRequest {
44
+ readonly tag: string;
45
+ readonly cursor: string;
46
+ readonly limit: number;
47
+ readonly through?: string;
48
+ }
49
+ /** A bounded page from the sole TagState event-source seam. */
50
+ export interface G43TagStateIncrementalPage {
51
+ readonly events: readonly TagEvent[];
52
+ readonly lastSortableUniqueId: string;
53
+ readonly through: string;
54
+ /** Non-null only when this cursor has consumed the frozen frontier. */
55
+ readonly completeThrough: string | null;
56
+ }
57
+ export interface TagOutboxRow {
58
+ attemptId: string;
59
+ eventId: string;
60
+ suid: string;
61
+ payload: string;
62
+ allocatorLineageId: string;
63
+ eventType: string;
64
+ provenance: "g32";
65
+ timestamp: string;
66
+ }
67
+ /**
68
+ * Separate from the immutable outbox row so an append remains a commit-path
69
+ * write only. A drain records its first queue-attempt clock fact and delivery
70
+ * acknowledgement here.
71
+ */
72
+ export interface TagOutboxDelivery extends TagOutboxRow {
73
+ enqueuedAt: number;
74
+ deliveredAt: number | null;
75
+ }
76
+ export interface TagFence {
77
+ reason: string;
78
+ attemptId: string;
79
+ epoch: number;
80
+ }
81
+ /** Bootstrap is intentionally separate from V1 append/reservation state. */
82
+ export interface TagBootstrapAdmission {
83
+ importId: string;
84
+ leaseEpoch: number;
85
+ manifestDigest: string;
86
+ targetServiceId: string;
87
+ closed: boolean;
88
+ }
89
+ /**
90
+ * SDT-G6 repair authority is deliberately held by the Tag DO rather than by
91
+ * a Journal observation. A scope item is the exact candidate that a repair
92
+ * lease is permitted to touch.
93
+ */
94
+ export interface RepairScopeItem {
95
+ attemptId: string;
96
+ eventId: string;
97
+ suid: string;
98
+ payload: string;
99
+ eventTags: string[];
100
+ allocatorLineageId: string;
101
+ eventType: string;
102
+ provenance: "g32";
103
+ timestamp: string;
104
+ }
105
+ export type RepairBranch = "ROLLED_FORWARD" | "EXCLUDED_AUDITED" | "FAILED_CLOSED";
106
+ /** Durable fact written by the Tag DO after it has made a branch decision. */
107
+ export interface RepairResolution {
108
+ attemptId: string;
109
+ eventId: string;
110
+ suid: string;
111
+ branch: RepairBranch;
112
+ epoch: number;
113
+ owner: string;
114
+ recordedAt: string;
115
+ }
116
+ /** An audit is intentionally separate from the original commit outcome. */
117
+ export interface RepairAudit {
118
+ attemptId: string;
119
+ eventId: string;
120
+ suid: string;
121
+ branch: Exclude<RepairBranch, "FAILED_CLOSED">;
122
+ actor: string;
123
+ epoch: number;
124
+ owner: string;
125
+ recordedAt: string;
126
+ }
127
+ export interface RepairFacts {
128
+ resolutions: RepairResolution[];
129
+ audits: RepairAudit[];
130
+ }
131
+ /**
132
+ * The per-tag durable authority. Its `head` is read from SQLite inside every
133
+ * consistency comparison; there is no in-memory cache of the head.
134
+ */
135
+ export interface TagRecord {
136
+ /** G32 is a fresh namespace; earlier durable Tag record shapes are rejected. */
137
+ schemaVersion: 3;
138
+ tag: string;
139
+ head: string;
140
+ activeReservation: TagReservation | null;
141
+ alarmDueAt: number | null;
142
+ events: TagEvent[];
143
+ outbox: TagOutboxRow[];
144
+ highestEpoch: TagEpoch[];
145
+ sealedEpoch: TagEpoch[];
146
+ tombstones: TagEpoch[];
147
+ confirmations: TagEpoch[];
148
+ fences: TagFence[];
149
+ clearedFences: TagFence[];
150
+ bootstrapAdmission: TagBootstrapAdmission | null;
151
+ /** SDT-G6 repair fencing-token lease. */
152
+ repairOwner: string | null;
153
+ repairLeaseUntil: number | null;
154
+ highestRepairEpoch: number;
155
+ /** Durable, set-based authorization scope for the currently held lease. */
156
+ repairScope: RepairScopeItem[];
157
+ repairScopeVersion: number;
158
+ clockOffsetMs: number;
159
+ clockNowMs: number | null;
160
+ version: number;
161
+ createdAt: string;
162
+ updatedAt: string;
163
+ }
164
+ /**
165
+ * The immutable scalar facts needed by the commit response. This is
166
+ * intentionally distinct from TagRecord: a caller that only needs the head
167
+ * must not hydrate or validate the tag's event history to obtain it.
168
+ */
169
+ export interface TagHeadFacts {
170
+ head: string;
171
+ version: number;
172
+ updatedAt: string;
173
+ }
@@ -0,0 +1,3 @@
1
+ export const RESERVATION_WINDOW_MS = 30_000;
2
+ export const PARTIAL_WRITE_FENCE_REASON = "partial_write";
3
+ export const SEGMENT_ROTATION_FENCE_REASON = "segment_rotation";
@@ -0,0 +1,57 @@
1
+ import { type ProjectorRegistry } from "../projection/ProjectorRegistry";
2
+ /** The fixed bounded source page used by both normal delta and replay. */
3
+ export declare const TAG_STATE_SOURCE_PAGE_LIMIT = 64;
4
+ export declare function configureTagStateProjectorRegistry(registry: ProjectorRegistry | undefined): void;
5
+ export interface TagStateObjectIdentity {
6
+ readonly serviceId: string;
7
+ readonly tag: string;
8
+ readonly projectorId: string;
9
+ }
10
+ export interface TagStateReadSuccess {
11
+ readonly kind: "ready";
12
+ readonly payload: string;
13
+ readonly version: number;
14
+ readonly lastSortedUniqueId: string;
15
+ readonly projectorVersion: string;
16
+ }
17
+ interface TagStateDurableObjectEnv {
18
+ readonly TAG: DurableObjectNamespace;
19
+ }
20
+ /**
21
+ * TagState cache and resumable replay owner. The only event source is the
22
+ * existing G43 Tag RPC; this object deliberately has neither a full-record
23
+ * fetch route nor a second source-query implementation.
24
+ */
25
+ export declare class TagStateDurableObject implements DurableObject {
26
+ private readonly ctx;
27
+ private readonly env;
28
+ private g46CheckpointFault;
29
+ private g46SourceNamespace;
30
+ /**
31
+ * Installed by the entrypoint when it composes the deployed domain. There
32
+ * is deliberately no default/test-registry fallback here: a DO isolate
33
+ * which was not built from that composition must return the typed registry
34
+ * failure rather than fold with a different projector authority.
35
+ */
36
+ private readonly registry;
37
+ constructor(ctx: DurableObjectState, env: TagStateDurableObjectEnv, registry?: ProjectorRegistry);
38
+ /** Test-only fault seam for the two durable checkpoint boundaries. */
39
+ setG46CheckpointFaultForTest(fault: "before-checkpoint" | "after-checkpoint" | undefined): void;
40
+ /** Test-only source seam; production always resolves `env.TAG`. */
41
+ setG46SourceNamespaceForTest(namespace: DurableObjectNamespace | undefined): void;
42
+ fetch(request: Request): Promise<Response>;
43
+ private read;
44
+ private beginDeltaOrRespondReady;
45
+ private continueRebuild;
46
+ private foldAndCheckpoint;
47
+ private success;
48
+ private readSource;
49
+ private assertSourcePage;
50
+ private resolveProjector;
51
+ private ensureIdentity;
52
+ private readCache;
53
+ private beginRebuild;
54
+ private sql;
55
+ private transaction;
56
+ }
57
+ export {};