@hasna/infinity 0.1.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 (112) hide show
  1. package/LICENSE +3 -0
  2. package/README.md +331 -0
  3. package/dist/cli.js +2965 -0
  4. package/dist/http-api.js +6448 -0
  5. package/dist/index.js +28536 -0
  6. package/dist/migrate.js +346 -0
  7. package/dist/self-hosted-migrate.js +2064 -0
  8. package/dist/self-hosted.js +13180 -0
  9. package/dist/types/authcapsules/codewith-local.d.ts +109 -0
  10. package/dist/types/authcapsules/infinity-agent-policy.d.ts +57 -0
  11. package/dist/types/authcapsules/os-isolated-runner.d.ts +87 -0
  12. package/dist/types/authority/authority.d.ts +342 -0
  13. package/dist/types/authority/effect-journal.d.ts +205 -0
  14. package/dist/types/authority/mutation-journal.d.ts +163 -0
  15. package/dist/types/authority/mutation-tuple.d.ts +26 -0
  16. package/dist/types/authority/state.d.ts +75 -0
  17. package/dist/types/authority/store.d.ts +15 -0
  18. package/dist/types/brokers/checkpoint/archive.d.ts +21 -0
  19. package/dist/types/brokers/checkpoint/bundle.d.ts +22 -0
  20. package/dist/types/brokers/checkpoint/bytes.d.ts +4 -0
  21. package/dist/types/brokers/checkpoint/clean-verifier-finalization.d.ts +62 -0
  22. package/dist/types/brokers/checkpoint/clean-verifier.d.ts +145 -0
  23. package/dist/types/brokers/checkpoint/final-trust-authority.d.ts +55 -0
  24. package/dist/types/brokers/checkpoint/idempotency.d.ts +25 -0
  25. package/dist/types/brokers/checkpoint/journaled-store.d.ts +9 -0
  26. package/dist/types/brokers/checkpoint/manifest-signature.d.ts +135 -0
  27. package/dist/types/brokers/checkpoint/manifest.d.ts +57 -0
  28. package/dist/types/brokers/checkpoint/s3-store.d.ts +215 -0
  29. package/dist/types/brokers/checkpoint/seal-authority.d.ts +86 -0
  30. package/dist/types/brokers/checkpoint/service.d.ts +198 -0
  31. package/dist/types/brokers/checkpoint/signing-message.d.ts +22 -0
  32. package/dist/types/brokers/checkpoint/store.d.ts +76 -0
  33. package/dist/types/brokers/checkpoint/verifier-cleanup-authority.d.ts +108 -0
  34. package/dist/types/brokers/checkpoint/verifier-cleanup.d.ts +391 -0
  35. package/dist/types/brokers/checkpoint/verifier.d.ts +225 -0
  36. package/dist/types/brokers/composition.d.ts +86 -0
  37. package/dist/types/brokers/git/github-app.d.ts +216 -0
  38. package/dist/types/brokers/git/promotion.d.ts +418 -0
  39. package/dist/types/brokers/persistence/contracts.d.ts +77 -0
  40. package/dist/types/brokers/persistence/memory.d.ts +5 -0
  41. package/dist/types/brokers/persistence/migration.d.ts +6 -0
  42. package/dist/types/brokers/persistence/postgres.d.ts +74 -0
  43. package/dist/types/cli/main.d.ts +2 -0
  44. package/dist/types/cli/operation-journal.d.ts +47 -0
  45. package/dist/types/cli/run.d.ts +15 -0
  46. package/dist/types/client/operator-client.d.ts +100 -0
  47. package/dist/types/contracts/dtos.d.ts +198 -0
  48. package/dist/types/contracts/events.d.ts +45 -0
  49. package/dist/types/contracts/fence.d.ts +39 -0
  50. package/dist/types/contracts/operations.d.ts +91 -0
  51. package/dist/types/contracts/runspec.d.ts +75 -0
  52. package/dist/types/contracts/validators.d.ts +8 -0
  53. package/dist/types/core/clock.d.ts +12 -0
  54. package/dist/types/core/errors.d.ts +18 -0
  55. package/dist/types/core/ids.d.ts +10 -0
  56. package/dist/types/core/int64.d.ts +7 -0
  57. package/dist/types/core/strict-json.d.ts +8 -0
  58. package/dist/types/core/validation.d.ts +25 -0
  59. package/dist/types/golden/disposable-task.d.ts +108 -0
  60. package/dist/types/golden/source-pins.d.ts +77 -0
  61. package/dist/types/http/api.d.ts +52 -0
  62. package/dist/types/http/bearer-auth.d.ts +8 -0
  63. package/dist/types/http/main.d.ts +3 -0
  64. package/dist/types/http/self-hosted-main.d.ts +17 -0
  65. package/dist/types/index.d.ts +65 -0
  66. package/dist/types/mcp/schema.d.ts +7 -0
  67. package/dist/types/node-agent/agent.d.ts +174 -0
  68. package/dist/types/node-agent/contracts.d.ts +119 -0
  69. package/dist/types/node-agent/macos-service.d.ts +33 -0
  70. package/dist/types/node-agent/service-cli.d.ts +26 -0
  71. package/dist/types/persistence/composition.d.ts +49 -0
  72. package/dist/types/persistence/migrate-main.d.ts +2 -0
  73. package/dist/types/persistence/migrations.d.ts +30 -0
  74. package/dist/types/persistence/postgres-accounts-operation.d.ts +26 -0
  75. package/dist/types/persistence/postgres-authority.d.ts +69 -0
  76. package/dist/types/persistence/postgres-external-mutation-journal.d.ts +22 -0
  77. package/dist/types/persistence/postgres-json.d.ts +1 -0
  78. package/dist/types/persistence/postgres-mutation-journal.d.ts +31 -0
  79. package/dist/types/persistence/postgres-reconciler.d.ts +34 -0
  80. package/dist/types/persistence/postgres-sandbox-dispatch-authority.d.ts +9 -0
  81. package/dist/types/persistence/self-hosted-migrate-main.d.ts +2 -0
  82. package/dist/types/ports/accounts-operation.d.ts +336 -0
  83. package/dist/types/ports/accounts.d.ts +293 -0
  84. package/dist/types/ports/sandbox-dispatch-authority.d.ts +154 -0
  85. package/dist/types/ports/sandboxes.d.ts +40 -0
  86. package/dist/types/providers/sandbox-dispatch.d.ts +143 -0
  87. package/dist/types/runtime/config.d.ts +61 -0
  88. package/dist/types/runtime/postgres.d.ts +18 -0
  89. package/dist/types/runtime/provider-activation.d.ts +45 -0
  90. package/dist/types/runtime/server.d.ts +68 -0
  91. package/dist/types/testing/accounts-fake.d.ts +31 -0
  92. package/dist/types/testing/fakes.d.ts +2 -0
  93. package/dist/types/testing/node-control-plane-fake.d.ts +20 -0
  94. package/dist/types/testing/reference.d.ts +27 -0
  95. package/dist/types/testing/sandboxes-fake.d.ts +22 -0
  96. package/evidence/provider-live-daytona-v3.json +1 -0
  97. package/evidence/provider-live-e2b-v3.json +1 -0
  98. package/evidence/provider-production-route-daytona-v1.json +1 -0
  99. package/evidence/provider-production-route-e2b-v1.json +1 -0
  100. package/migrations/0001_authority.sql +689 -0
  101. package/migrations/0002_effect_step_global_owner.sql +2 -0
  102. package/migrations/0003_effect_journal_observed_head.sql +34 -0
  103. package/migrations/0004_authority_mutation_journal_binding.sql +15 -0
  104. package/migrations/20260710_checkpoint_broker_v1.sql +163 -0
  105. package/migrations/20260711_accounts_operation_v1.sql +137 -0
  106. package/migrations/20260711_checkpoint_trust_v2.sql +17 -0
  107. package/migrations/20260711_verifier_cleanup_v2.sql +169 -0
  108. package/migrations/20260711_z_accounts_claim_authority_v2.sql +172 -0
  109. package/migrations/20260711_zz_sandbox_dispatch_authority_v1.sql +143 -0
  110. package/migrations/20260712_sandbox_dispatch_authority_v2.sql +58 -0
  111. package/migrations/external-journal/0001_external_authority_mutation_journal.sql +175 -0
  112. package/package.json +47 -0
@@ -0,0 +1,689 @@
1
+ CREATE SCHEMA IF NOT EXISTS infinity;
2
+
3
+ CREATE TABLE infinity.authority_epochs (
4
+ authority_epoch bigint PRIMARY KEY CHECK (authority_epoch > 0),
5
+ state text NOT NULL CHECK (state IN ('recovery_pending', 'reconciled', 'unknown_requires_review')),
6
+ activation_receipt_digest text NOT NULL CHECK (activation_receipt_digest ~ '^sha256:[0-9a-f]{64}$'),
7
+ activated_at timestamptz NOT NULL,
8
+ is_current boolean NOT NULL DEFAULT false
9
+ );
10
+ CREATE UNIQUE INDEX authority_epochs_one_current ON infinity.authority_epochs ((is_current)) WHERE is_current;
11
+
12
+ CREATE TABLE infinity.authority_runtime_meta (
13
+ singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
14
+ next_queue_sequence bigint NOT NULL CHECK (next_queue_sequence > 0),
15
+ next_commit_sequence bigint NOT NULL CHECK (next_commit_sequence > 0),
16
+ journal_acknowledged_through bigint NOT NULL CHECK (journal_acknowledged_through >= 0),
17
+ budget_limit_units bigint NOT NULL CHECK (budget_limit_units >= 0),
18
+ budget_reserved_units bigint NOT NULL CHECK (budget_reserved_units >= 0),
19
+ budget_charged_units bigint NOT NULL CHECK (budget_charged_units >= 0),
20
+ budget_released_units bigint NOT NULL CHECK (budget_released_units >= 0)
21
+ );
22
+
23
+ CREATE TABLE infinity.authority_mutation_change_buffer (
24
+ change_id bigint GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
25
+ commit_sequence bigint NOT NULL CHECK (commit_sequence > 0),
26
+ table_name text NOT NULL CHECK (table_name ~ '^[a-z][a-z0-9_]*$'),
27
+ mutation_kind text NOT NULL CHECK (mutation_kind IN ('INSERT','UPDATE','DELETE')),
28
+ row_record jsonb NOT NULL,
29
+ captured_at timestamptz NOT NULL
30
+ );
31
+ CREATE INDEX authority_mutation_change_sequence ON infinity.authority_mutation_change_buffer (commit_sequence, change_id);
32
+
33
+ CREATE TABLE infinity.authority_mutation_envelopes (
34
+ commit_sequence bigint PRIMARY KEY CHECK (commit_sequence > 0),
35
+ operation_id text NOT NULL UNIQUE,
36
+ operation_digest text NOT NULL CHECK (operation_digest ~ '^sha256:[0-9a-f]{64}$'),
37
+ envelope_digest text NOT NULL UNIQUE CHECK (envelope_digest ~ '^sha256:[0-9a-f]{64}$'),
38
+ envelope_record jsonb NOT NULL,
39
+ created_at timestamptz NOT NULL
40
+ );
41
+
42
+ CREATE TABLE infinity.authority_mutation_acknowledgements (
43
+ commit_sequence bigint PRIMARY KEY REFERENCES infinity.authority_mutation_envelopes(commit_sequence),
44
+ frontier_digest text NOT NULL UNIQUE CHECK (frontier_digest ~ '^sha256:[0-9a-f]{64}$'),
45
+ acknowledgement_digest text NOT NULL UNIQUE CHECK (acknowledgement_digest ~ '^sha256:[0-9a-f]{64}$'),
46
+ restore_domain_id text NOT NULL CHECK (restore_domain_id ~ '^[A-Za-z0-9][A-Za-z0-9:_-]{0,95}$'),
47
+ signer_principal text NOT NULL CHECK (signer_principal ~ '^[A-Za-z0-9][A-Za-z0-9:_-]{0,95}$'),
48
+ signing_key_id text NOT NULL CHECK (signing_key_id ~ '^[A-Za-z0-9][A-Za-z0-9:_-]{0,95}$'),
49
+ signature text NOT NULL CHECK (signature ~ '^[A-Za-z0-9_-]{80,128}$'),
50
+ acknowledgement_record jsonb NOT NULL,
51
+ acknowledged_at timestamptz NOT NULL
52
+ );
53
+
54
+ ALTER TABLE infinity.authority_mutation_change_buffer
55
+ ADD CONSTRAINT authority_mutation_change_envelope_fk
56
+ FOREIGN KEY (commit_sequence) REFERENCES infinity.authority_mutation_envelopes(commit_sequence)
57
+ DEFERRABLE INITIALLY DEFERRED;
58
+
59
+ CREATE TABLE infinity.routes (
60
+ route_lineage_id text PRIMARY KEY,
61
+ route_id text NOT NULL,
62
+ route_epoch bigint NOT NULL CHECK (route_epoch > 0),
63
+ state text NOT NULL CHECK (state IN ('active','draining','inactive')),
64
+ UNIQUE (route_lineage_id, route_epoch),
65
+ UNIQUE (route_lineage_id, route_id, route_epoch)
66
+ );
67
+
68
+ CREATE TABLE infinity.run_specs (
69
+ id text PRIMARY KEY,
70
+ digest text NOT NULL UNIQUE CHECK (digest ~ '^sha256:[0-9a-f]{64}$'),
71
+ schema_version text NOT NULL,
72
+ canonical_spec jsonb NOT NULL,
73
+ created_at timestamptz NOT NULL,
74
+ UNIQUE (id, digest)
75
+ );
76
+
77
+ CREATE TABLE infinity.runs (
78
+ id text PRIMARY KEY,
79
+ run_spec_id text NOT NULL REFERENCES infinity.run_specs(id),
80
+ run_spec_digest text NOT NULL CHECK (run_spec_digest ~ '^sha256:[0-9a-f]{64}$'),
81
+ route_lineage_id text NOT NULL,
82
+ route_id text NOT NULL,
83
+ route_epoch bigint NOT NULL CHECK (route_epoch > 0),
84
+ admitted_authority_epoch bigint NOT NULL REFERENCES infinity.authority_epochs(authority_epoch) CHECK (admitted_authority_epoch > 0),
85
+ logical_work_key text NOT NULL,
86
+ owner_principal text NOT NULL,
87
+ project_id text NOT NULL,
88
+ repository_id text NOT NULL,
89
+ current_attempt_id text NOT NULL,
90
+ state text NOT NULL CHECK (state IN ('admitted','active','cancel_requested','finalizing','succeeded','failed','canceled','lost_uncheckpointed','discarded_uncheckpointed')),
91
+ terminal_outcome text,
92
+ revision integer NOT NULL CHECK (revision > 0),
93
+ next_event_sequence integer NOT NULL CHECK (next_event_sequence > 0),
94
+ created_at timestamptz NOT NULL,
95
+ updated_at timestamptz NOT NULL,
96
+ CHECK (updated_at >= created_at),
97
+ CHECK (
98
+ (state IN ('admitted','active','cancel_requested','finalizing') AND terminal_outcome IS NULL)
99
+ OR (state = 'succeeded' AND terminal_outcome = 'succeeded')
100
+ OR (state = 'failed' AND terminal_outcome IN ('failed_permanent','policy_denied','budget_exhausted'))
101
+ OR (state = 'canceled' AND terminal_outcome = 'canceled')
102
+ OR (state = 'lost_uncheckpointed' AND terminal_outcome = 'lost_uncheckpointed')
103
+ OR (state = 'discarded_uncheckpointed' AND terminal_outcome = 'discarded_uncheckpointed')
104
+ ),
105
+ FOREIGN KEY (run_spec_id, run_spec_digest) REFERENCES infinity.run_specs(id, digest),
106
+ FOREIGN KEY (route_lineage_id, route_id, route_epoch) REFERENCES infinity.routes(route_lineage_id, route_id, route_epoch),
107
+ UNIQUE (route_lineage_id, logical_work_key),
108
+ UNIQUE (id, route_lineage_id, logical_work_key, run_spec_digest)
109
+ );
110
+
111
+ CREATE TABLE infinity.attempts (
112
+ id text PRIMARY KEY,
113
+ run_id text NOT NULL REFERENCES infinity.runs(id) DEFERRABLE INITIALLY DEFERRED,
114
+ attempt_number integer NOT NULL CHECK (attempt_number > 0),
115
+ phase text NOT NULL CHECK (phase IN ('queued','lane_leased','sandbox_allocating','running','checkpointed','verifying','finalizing','terminal')),
116
+ outcome text CHECK (outcome IS NULL OR outcome IN ('succeeded','failed_retryable','failed_permanent','canceled','lost_uncheckpointed','discarded_uncheckpointed','policy_denied','budget_exhausted')),
117
+ pending_outcome text CHECK (pending_outcome IS NULL OR pending_outcome IN ('succeeded','failed_retryable','failed_permanent','canceled','lost_uncheckpointed','discarded_uncheckpointed','policy_denied','budget_exhausted')),
118
+ runner_principal text,
119
+ attempt_lease_id text,
120
+ lease_epoch bigint CHECK (lease_epoch > 0),
121
+ lease_holder_principal text,
122
+ lease_expires_at timestamptz,
123
+ cancellation_state text NOT NULL CHECK (cancellation_state IN ('none','requested','fenced','cleanup_pending','complete')),
124
+ retry_cause text,
125
+ terminal_reason text,
126
+ revision integer NOT NULL CHECK (revision > 0),
127
+ created_at timestamptz NOT NULL,
128
+ updated_at timestamptz NOT NULL,
129
+ UNIQUE (run_id, attempt_number),
130
+ UNIQUE (id, run_id),
131
+ CHECK (updated_at >= created_at),
132
+ CHECK ((attempt_lease_id IS NULL AND lease_epoch IS NULL AND lease_holder_principal IS NULL AND lease_expires_at IS NULL)
133
+ OR (attempt_lease_id IS NOT NULL AND lease_epoch IS NOT NULL AND lease_holder_principal IS NOT NULL AND lease_expires_at IS NOT NULL)),
134
+ CHECK ((attempt_lease_id IS NULL AND runner_principal IS NULL)
135
+ OR (attempt_lease_id IS NOT NULL AND runner_principal IS NOT NULL)),
136
+ CHECK (phase <> 'queued' OR attempt_lease_id IS NULL),
137
+ CHECK (phase IN ('queued','terminal') OR attempt_lease_id IS NOT NULL),
138
+ CHECK ((phase = 'terminal') = (outcome IS NOT NULL)),
139
+ CHECK (phase = 'finalizing' OR pending_outcome IS NULL),
140
+ CHECK (phase <> 'terminal' OR pending_outcome IS NULL),
141
+ CHECK (phase <> 'terminal' OR attempt_lease_id IS NOT NULL OR outcome = 'policy_denied')
142
+ );
143
+ CREATE UNIQUE INDEX attempts_one_nonterminal_per_run ON infinity.attempts (run_id) WHERE phase <> 'terminal';
144
+
145
+ ALTER TABLE infinity.runs
146
+ ADD CONSTRAINT runs_current_attempt_fk FOREIGN KEY (current_attempt_id, id) REFERENCES infinity.attempts(id, run_id) DEFERRABLE INITIALLY DEFERRED;
147
+
148
+ CREATE TABLE infinity.attempt_lease_grants (
149
+ attempt_lease_id text PRIMARY KEY,
150
+ attempt_id text NOT NULL REFERENCES infinity.attempts(id),
151
+ run_id text NOT NULL REFERENCES infinity.runs(id),
152
+ lease_epoch bigint NOT NULL CHECK (lease_epoch > 0),
153
+ lease_holder_principal text NOT NULL,
154
+ audience text NOT NULL,
155
+ issued_at timestamptz NOT NULL,
156
+ lease_expires_at timestamptz NOT NULL CHECK (lease_expires_at > issued_at),
157
+ grant_digest text NOT NULL CHECK (grant_digest ~ '^sha256:[0-9a-f]{64}$'),
158
+ kind text NOT NULL CHECK (kind IN ('worker','cancel_recovery')),
159
+ UNIQUE (attempt_id, lease_epoch),
160
+ UNIQUE (attempt_lease_id, attempt_id, lease_epoch),
161
+ FOREIGN KEY (attempt_id, run_id) REFERENCES infinity.attempts(id, run_id)
162
+ );
163
+
164
+ CREATE TABLE infinity.attempt_lease_events (
165
+ id text PRIMARY KEY,
166
+ attempt_lease_id text NOT NULL,
167
+ attempt_id text NOT NULL REFERENCES infinity.attempts(id),
168
+ lease_epoch bigint NOT NULL CHECK (lease_epoch > 0),
169
+ kind text NOT NULL CHECK (kind IN ('granted','renewed','fenced','released','expired')),
170
+ actor_principal text NOT NULL,
171
+ database_time timestamptz NOT NULL,
172
+ detail_digest text NOT NULL CHECK (detail_digest ~ '^sha256:[0-9a-f]{64}$'),
173
+ UNIQUE (attempt_id, lease_epoch, kind, database_time),
174
+ FOREIGN KEY (attempt_lease_id, attempt_id, lease_epoch)
175
+ REFERENCES infinity.attempt_lease_grants(attempt_lease_id, attempt_id, lease_epoch)
176
+ );
177
+
178
+ CREATE TABLE infinity.queue_entries (
179
+ attempt_id text PRIMARY KEY REFERENCES infinity.attempts(id),
180
+ run_id text NOT NULL REFERENCES infinity.runs(id),
181
+ project_id text NOT NULL,
182
+ lane_pool_id text NOT NULL,
183
+ enqueue_sequence bigint NOT NULL UNIQUE CHECK (enqueue_sequence > 0),
184
+ admitted_at timestamptz NOT NULL,
185
+ state text NOT NULL CHECK (state IN ('queued','reserved','removed')),
186
+ FOREIGN KEY (attempt_id, run_id) REFERENCES infinity.attempts(id, run_id)
187
+ );
188
+
189
+ CREATE TABLE infinity.budget_reservations (
190
+ run_id text PRIMARY KEY REFERENCES infinity.runs(id),
191
+ ceiling_units bigint NOT NULL CHECK (ceiling_units >= 0),
192
+ charged_units bigint NOT NULL CHECK (charged_units >= 0),
193
+ state text NOT NULL CHECK (state IN ('reserved','settled','released')),
194
+ CHECK (charged_units <= ceiling_units)
195
+ );
196
+
197
+ CREATE TABLE infinity.admission_keys (
198
+ route_lineage_id text NOT NULL,
199
+ logical_work_key text NOT NULL,
200
+ run_spec_digest text NOT NULL CHECK (run_spec_digest ~ '^sha256:[0-9a-f]{64}$'),
201
+ run_id text NOT NULL REFERENCES infinity.runs(id),
202
+ disposition text NOT NULL CHECK (disposition IN ('admitted','tombstone')),
203
+ created_at timestamptz NOT NULL,
204
+ PRIMARY KEY (route_lineage_id, logical_work_key),
205
+ FOREIGN KEY (run_id, route_lineage_id, logical_work_key, run_spec_digest)
206
+ REFERENCES infinity.runs(id, route_lineage_id, logical_work_key, run_spec_digest)
207
+ );
208
+
209
+ CREATE TABLE infinity.idempotency_records (
210
+ operation_id text PRIMARY KEY,
211
+ actor_principal text NOT NULL,
212
+ command text NOT NULL,
213
+ scope text NOT NULL,
214
+ idempotency_key text NOT NULL,
215
+ request_hash text NOT NULL CHECK (request_hash ~ '^sha256:[0-9a-f]{64}$'),
216
+ source_namespace text NOT NULL,
217
+ request_execution_epoch bigint NOT NULL CHECK (request_execution_epoch > 0),
218
+ request_execution_holder text NOT NULL,
219
+ request_execution_expires_at timestamptz NOT NULL,
220
+ state text NOT NULL CHECK (state IN ('in_flight','committed','aborted')),
221
+ result jsonb,
222
+ created_at timestamptz NOT NULL,
223
+ updated_at timestamptz NOT NULL,
224
+ UNIQUE (actor_principal, command, scope, idempotency_key)
225
+ );
226
+
227
+ ALTER TABLE infinity.authority_mutation_envelopes
228
+ ADD CONSTRAINT authority_mutation_envelope_operation_fk
229
+ FOREIGN KEY (operation_id) REFERENCES infinity.idempotency_records(operation_id)
230
+ DEFERRABLE INITIALLY DEFERRED;
231
+
232
+ CREATE TABLE infinity.event_stream_heads (
233
+ aggregate_type text NOT NULL,
234
+ aggregate_id text NOT NULL,
235
+ sequence integer NOT NULL CHECK (sequence > 0),
236
+ digest text NOT NULL CHECK (digest ~ '^sha256:[0-9a-f]{64}$'),
237
+ PRIMARY KEY (aggregate_type, aggregate_id)
238
+ );
239
+
240
+ CREATE TABLE infinity.events (
241
+ event_id text PRIMARY KEY,
242
+ authority_commit_sequence bigint NOT NULL UNIQUE CHECK (authority_commit_sequence > 0),
243
+ operation_id text NOT NULL,
244
+ operation_digest text NOT NULL CHECK (operation_digest ~ '^sha256:[0-9a-f]{64}$'),
245
+ aggregate_type text NOT NULL,
246
+ aggregate_id text NOT NULL,
247
+ aggregate_sequence integer NOT NULL CHECK (aggregate_sequence > 0),
248
+ run_id text,
249
+ run_sequence integer,
250
+ actor_principal text NOT NULL,
251
+ authority_epoch bigint NOT NULL CHECK (authority_epoch > 0),
252
+ route_lineage_id text,
253
+ route_id text,
254
+ route_epoch bigint CHECK (route_epoch > 0),
255
+ attempt_id text,
256
+ attempt_lease_id text,
257
+ lease_epoch bigint CHECK (lease_epoch > 0),
258
+ lease_holder_principal text,
259
+ audience text,
260
+ resource_lease_id text,
261
+ resource_id text,
262
+ resource_lifecycle_generation bigint CHECK (resource_lifecycle_generation > 0),
263
+ operation_executor_principal text,
264
+ event_schema text NOT NULL,
265
+ event_type text NOT NULL,
266
+ event_digest text NOT NULL UNIQUE CHECK (event_digest ~ '^sha256:[0-9a-f]{64}$'),
267
+ prior_event_digest text CHECK (prior_event_digest IS NULL OR prior_event_digest ~ '^sha256:[0-9a-f]{64}$'),
268
+ payload jsonb NOT NULL,
269
+ payload_digest text NOT NULL CHECK (payload_digest ~ '^sha256:[0-9a-f]{64}$'),
270
+ event_record jsonb NOT NULL,
271
+ database_time timestamptz NOT NULL,
272
+ UNIQUE (aggregate_type, aggregate_id, aggregate_sequence),
273
+ UNIQUE (run_id, run_sequence),
274
+ UNIQUE (event_id, authority_commit_sequence, event_digest),
275
+ CHECK ((route_lineage_id IS NULL AND route_id IS NULL AND route_epoch IS NULL)
276
+ OR (route_lineage_id IS NOT NULL AND route_id IS NOT NULL AND route_epoch IS NOT NULL)),
277
+ CHECK ((attempt_lease_id IS NULL AND lease_epoch IS NULL AND lease_holder_principal IS NULL AND audience IS NULL)
278
+ OR (attempt_lease_id IS NOT NULL AND lease_epoch IS NOT NULL AND lease_holder_principal IS NOT NULL AND audience IS NOT NULL)),
279
+ CHECK ((resource_lease_id IS NULL AND resource_id IS NULL AND resource_lifecycle_generation IS NULL)
280
+ OR (resource_lease_id IS NOT NULL AND resource_id IS NOT NULL AND resource_lifecycle_generation IS NOT NULL))
281
+ );
282
+
283
+ CREATE TABLE infinity.outbox (
284
+ id text PRIMARY KEY,
285
+ event_id text NOT NULL REFERENCES infinity.events(event_id),
286
+ destination text NOT NULL,
287
+ projection_version text NOT NULL,
288
+ outbox_identity_digest text NOT NULL UNIQUE CHECK (outbox_identity_digest ~ '^sha256:[0-9a-f]{64}$'),
289
+ payload_digest text NOT NULL CHECK (payload_digest ~ '^sha256:[0-9a-f]{64}$'),
290
+ state text NOT NULL CHECK (state IN ('held','pending','leased','delivered','blocked')),
291
+ authority_commit_sequence bigint NOT NULL CHECK (authority_commit_sequence > 0),
292
+ lease_owner text,
293
+ lease_expires_at timestamptz,
294
+ created_at timestamptz NOT NULL,
295
+ CHECK ((lease_owner IS NULL) = (lease_expires_at IS NULL)),
296
+ UNIQUE (event_id, destination, projection_version),
297
+ FOREIGN KEY (event_id, authority_commit_sequence, payload_digest)
298
+ REFERENCES infinity.events(event_id, authority_commit_sequence, event_digest)
299
+ );
300
+
301
+ CREATE TABLE infinity.external_operations (
302
+ id text NOT NULL,
303
+ operation_step_id text NOT NULL,
304
+ operation_execution_epoch bigint NOT NULL CHECK (operation_execution_epoch > 0),
305
+ provider_idempotency_token text NOT NULL,
306
+ state text NOT NULL CHECK (state IN ('planned','intent_committed','prepared','dispatched','succeeded','failed_effect','failed_no_effect','unknown','suppressed','quarantined')),
307
+ fence_digest text NOT NULL CHECK (fence_digest ~ '^sha256:[0-9a-f]{64}$'),
308
+ operation_record jsonb NOT NULL,
309
+ revision integer NOT NULL CHECK (revision > 0),
310
+ updated_at timestamptz NOT NULL,
311
+ PRIMARY KEY (id, operation_execution_epoch)
312
+ );
313
+
314
+ CREATE TABLE infinity.effect_operation_steps (
315
+ operation_id text NOT NULL,
316
+ operation_step_id text NOT NULL,
317
+ step_ordinal integer NOT NULL CHECK (step_ordinal > 0),
318
+ operation_step_digest text NOT NULL CHECK (operation_step_digest ~ '^sha256:[0-9a-f]{64}$'),
319
+ step_record jsonb NOT NULL,
320
+ PRIMARY KEY (operation_id, operation_step_id),
321
+ UNIQUE (operation_id, step_ordinal)
322
+ );
323
+
324
+ CREATE TABLE infinity.effect_journal_records (
325
+ operation_id text NOT NULL,
326
+ operation_step_id text NOT NULL,
327
+ operation_execution_epoch bigint NOT NULL CHECK (operation_execution_epoch > 0),
328
+ record_kind text NOT NULL CHECK (record_kind IN ('DISPATCHED','OUTCOME')),
329
+ outcome_kind text CHECK (outcome_kind IS NULL OR outcome_kind IN ('succeeded','failed_effect','failed_no_effect','reconciliation_blocked')),
330
+ outcome_receipt_digest text CHECK (outcome_receipt_digest IS NULL OR outcome_receipt_digest ~ '^sha256:[0-9a-f]{64}$'),
331
+ operation_digest text NOT NULL CHECK (operation_digest ~ '^sha256:[0-9a-f]{64}$'),
332
+ operation_step_digest text NOT NULL CHECK (operation_step_digest ~ '^sha256:[0-9a-f]{64}$'),
333
+ request_digest text NOT NULL CHECK (request_digest ~ '^sha256:[0-9a-f]{64}$'),
334
+ target_digest text NOT NULL CHECK (target_digest ~ '^sha256:[0-9a-f]{64}$'),
335
+ resource_id text NOT NULL,
336
+ resource_lifecycle_generation bigint NOT NULL CHECK (resource_lifecycle_generation > 0),
337
+ predecessor_receipt_digest text CHECK (predecessor_receipt_digest IS NULL OR predecessor_receipt_digest ~ '^sha256:[0-9a-f]{64}$'),
338
+ provider_idempotency_token text NOT NULL,
339
+ journal_sequence bigint NOT NULL UNIQUE CHECK (journal_sequence > 0),
340
+ prior_frontier_digest text CHECK (prior_frontier_digest IS NULL OR prior_frontier_digest ~ '^sha256:[0-9a-f]{64}$'),
341
+ record_digest text NOT NULL CHECK (record_digest ~ '^sha256:[0-9a-f]{64}$'),
342
+ frontier_digest text NOT NULL UNIQUE CHECK (frontier_digest ~ '^sha256:[0-9a-f]{64}$'),
343
+ signer_principal text NOT NULL,
344
+ signing_key_id text NOT NULL,
345
+ signature text NOT NULL,
346
+ anchor_record jsonb NOT NULL,
347
+ created_at timestamptz NOT NULL,
348
+ PRIMARY KEY (operation_id, operation_step_id, operation_execution_epoch, record_kind),
349
+ FOREIGN KEY (operation_id, operation_step_id) REFERENCES infinity.effect_operation_steps(operation_id, operation_step_id),
350
+ CHECK ((record_kind = 'DISPATCHED' AND outcome_kind IS NULL AND outcome_receipt_digest IS NULL)
351
+ OR (record_kind = 'OUTCOME' AND outcome_kind IS NOT NULL AND outcome_receipt_digest IS NOT NULL))
352
+ );
353
+
354
+ CREATE TABLE infinity.effect_journal_frontier (
355
+ singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
356
+ journal_sequence bigint NOT NULL CHECK (journal_sequence >= 0),
357
+ frontier_digest text CHECK (frontier_digest IS NULL OR frontier_digest ~ '^sha256:[0-9a-f]{64}$'),
358
+ updated_at timestamptz NOT NULL,
359
+ CHECK ((journal_sequence = 0) = (frontier_digest IS NULL))
360
+ );
361
+
362
+ CREATE OR REPLACE FUNCTION infinity.reject_immutable_mutation() RETURNS trigger
363
+ LANGUAGE plpgsql AS $$
364
+ BEGIN
365
+ RAISE EXCEPTION 'immutable Infinity record cannot be updated or deleted' USING ERRCODE = '55000';
366
+ END;
367
+ $$;
368
+
369
+ CREATE OR REPLACE FUNCTION infinity.capture_authority_mutation_change() RETURNS trigger
370
+ LANGUAGE plpgsql SECURITY DEFINER
371
+ SET search_path = pg_catalog, infinity AS $$
372
+ DECLARE
373
+ sequence_text text;
374
+ image jsonb;
375
+ BEGIN
376
+ IF TG_TABLE_NAME = 'authority_runtime_meta' AND TG_OP = 'UPDATE'
377
+ AND (to_jsonb(NEW) - 'journal_acknowledged_through') = (to_jsonb(OLD) - 'journal_acknowledged_through') THEN
378
+ RETURN NEW;
379
+ END IF;
380
+ sequence_text := NULLIF(current_setting('infinity.authority_commit_sequence', true), '');
381
+ IF sequence_text IS NULL OR sequence_text !~ '^[1-9][0-9]*$' THEN
382
+ RAISE EXCEPTION 'authority mutation lacks a committed sequence context' USING ERRCODE = '55000';
383
+ END IF;
384
+ IF TG_OP = 'DELETE' THEN image := to_jsonb(OLD); ELSE image := to_jsonb(NEW); END IF;
385
+ INSERT INTO infinity.authority_mutation_change_buffer
386
+ (commit_sequence, table_name, mutation_kind, row_record, captured_at)
387
+ VALUES (sequence_text::bigint, TG_TABLE_NAME, TG_OP, image, clock_timestamp());
388
+ IF TG_OP = 'DELETE' THEN RETURN OLD; ELSE RETURN NEW; END IF;
389
+ END;
390
+ $$;
391
+
392
+ CREATE OR REPLACE FUNCTION infinity.validate_authority_mutation_envelope() RETURNS trigger
393
+ LANGUAGE plpgsql SECURITY DEFINER
394
+ SET search_path = pg_catalog, infinity AS $$
395
+ DECLARE
396
+ mismatch boolean;
397
+ BEGIN
398
+ IF NEW.envelope_record->>'schema_version' IS DISTINCT FROM 'infinity.authority-mutation-reconstruction/v1'
399
+ OR (NEW.envelope_record->>'commit_sequence')::bigint IS DISTINCT FROM NEW.commit_sequence
400
+ OR NEW.envelope_record->>'operation_id' IS DISTINCT FROM NEW.operation_id
401
+ OR NEW.envelope_record->>'operation_digest' IS DISTINCT FROM NEW.operation_digest
402
+ OR jsonb_typeof(NEW.envelope_record->'changes') IS DISTINCT FROM 'array' THEN
403
+ RAISE EXCEPTION 'authority mutation envelope columns differ from reconstruction record' USING ERRCODE = '23514';
404
+ END IF;
405
+ IF NOT EXISTS (
406
+ SELECT 1 FROM infinity.authority_runtime_meta
407
+ WHERE singleton
408
+ AND next_commit_sequence = NEW.commit_sequence + 1
409
+ AND journal_acknowledged_through = NEW.commit_sequence - 1
410
+ ) THEN
411
+ RAISE EXCEPTION 'authority mutation envelope does not extend the local contiguous frontier' USING ERRCODE = '23514';
412
+ END IF;
413
+ IF NOT EXISTS (
414
+ SELECT 1 FROM infinity.idempotency_records
415
+ WHERE operation_id = NEW.operation_id AND request_hash = NEW.operation_digest AND state = 'committed'
416
+ ) THEN
417
+ RAISE EXCEPTION 'authority mutation envelope lacks its committed idempotency record' USING ERRCODE = '23514';
418
+ END IF;
419
+ WITH buffered AS (
420
+ SELECT row_number() OVER (ORDER BY change_id) AS ordinal, table_name, mutation_kind, row_record
421
+ FROM infinity.authority_mutation_change_buffer WHERE commit_sequence = NEW.commit_sequence
422
+ ), encoded AS (
423
+ SELECT ordinality AS ordinal, value
424
+ FROM jsonb_array_elements(NEW.envelope_record->'changes') WITH ORDINALITY AS item(value, ordinality)
425
+ )
426
+ SELECT EXISTS (
427
+ SELECT 1 FROM buffered FULL JOIN encoded USING (ordinal)
428
+ WHERE buffered.ordinal IS NULL OR encoded.ordinal IS NULL
429
+ OR (encoded.value->>'change_ordinal')::bigint IS DISTINCT FROM buffered.ordinal
430
+ OR encoded.value->>'table_name' IS DISTINCT FROM buffered.table_name
431
+ OR encoded.value->>'mutation_kind' IS DISTINCT FROM buffered.mutation_kind
432
+ OR encoded.value->'row' IS DISTINCT FROM buffered.row_record
433
+ ) INTO mismatch;
434
+ IF mismatch OR NOT EXISTS (
435
+ SELECT 1 FROM infinity.authority_mutation_change_buffer WHERE commit_sequence = NEW.commit_sequence
436
+ ) THEN
437
+ RAISE EXCEPTION 'authority mutation envelope changes differ from captured row images' USING ERRCODE = '23514';
438
+ END IF;
439
+ RETURN NEW;
440
+ END;
441
+ $$;
442
+
443
+ CREATE OR REPLACE FUNCTION infinity.validate_authority_mutation_acknowledgement() RETURNS trigger
444
+ LANGUAGE plpgsql SECURITY DEFINER
445
+ SET search_path = pg_catalog, infinity AS $$
446
+ BEGIN
447
+ IF NEW.acknowledgement_record->>'ack_schema_version' IS DISTINCT FROM 'infinity.authority-mutation-journal-ack/v1'
448
+ OR (NEW.acknowledgement_record->>'acknowledged_through')::bigint IS DISTINCT FROM NEW.commit_sequence
449
+ OR NEW.acknowledgement_record->>'frontier_digest' IS DISTINCT FROM NEW.frontier_digest
450
+ OR NEW.acknowledgement_record->>'restore_domain_id' IS DISTINCT FROM NEW.restore_domain_id
451
+ OR NEW.acknowledgement_record->'encrypted_at_rest' IS DISTINCT FROM 'true'::jsonb THEN
452
+ RAISE EXCEPTION 'authority mutation acknowledgement columns differ from signed record' USING ERRCODE = '23514';
453
+ END IF;
454
+ IF NEW.acknowledgement_record->>'signer_principal' IS DISTINCT FROM NEW.signer_principal
455
+ OR NEW.acknowledgement_record->>'signing_key_id' IS DISTINCT FROM NEW.signing_key_id
456
+ OR NEW.acknowledgement_record->>'signature' IS DISTINCT FROM NEW.signature THEN
457
+ RAISE EXCEPTION 'authority mutation acknowledgement columns differ from signed record' USING ERRCODE = '23514';
458
+ END IF;
459
+ RETURN NEW;
460
+ END;
461
+ $$;
462
+
463
+ CREATE OR REPLACE FUNCTION infinity.validate_authority_ack_frontier_update() RETURNS trigger
464
+ LANGUAGE plpgsql SECURITY DEFINER
465
+ SET search_path = pg_catalog, infinity AS $$
466
+ BEGIN
467
+ IF NEW.journal_acknowledged_through = OLD.journal_acknowledged_through THEN
468
+ RETURN NEW;
469
+ END IF;
470
+ IF (to_jsonb(NEW) - 'journal_acknowledged_through') IS DISTINCT FROM (to_jsonb(OLD) - 'journal_acknowledged_through')
471
+ OR NEW.journal_acknowledged_through <> OLD.journal_acknowledged_through + 1
472
+ OR NEW.journal_acknowledged_through >= NEW.next_commit_sequence
473
+ OR NOT EXISTS (
474
+ SELECT 1 FROM infinity.authority_mutation_acknowledgements
475
+ WHERE commit_sequence = NEW.journal_acknowledged_through
476
+ AND (acknowledgement_record->>'acknowledged_through')::bigint = NEW.journal_acknowledged_through
477
+ AND acknowledgement_record->>'frontier_digest' = frontier_digest
478
+ ) THEN
479
+ RAISE EXCEPTION 'authority mutation acknowledgement frontier update lacks the exact next signed record' USING ERRCODE = '23514';
480
+ END IF;
481
+ RETURN NEW;
482
+ END;
483
+ $$;
484
+
485
+ CREATE OR REPLACE FUNCTION infinity.validate_outbox_write() RETURNS trigger
486
+ LANGUAGE plpgsql SECURITY DEFINER
487
+ SET search_path = pg_catalog, infinity AS $$
488
+ DECLARE
489
+ acknowledged bigint;
490
+ BEGIN
491
+ IF TG_OP = 'INSERT' THEN
492
+ IF NEW.state <> 'held' OR NEW.lease_owner IS NOT NULL OR NEW.lease_expires_at IS NOT NULL THEN
493
+ RAISE EXCEPTION 'new outbox records must begin held behind the journal barrier' USING ERRCODE = '23514';
494
+ END IF;
495
+ RETURN NEW;
496
+ END IF;
497
+ IF (to_jsonb(NEW) - 'state' - 'lease_owner' - 'lease_expires_at')
498
+ IS DISTINCT FROM (to_jsonb(OLD) - 'state' - 'lease_owner' - 'lease_expires_at') THEN
499
+ RAISE EXCEPTION 'immutable outbox authority binding cannot change' USING ERRCODE = '23514';
500
+ END IF;
501
+ IF NEW.state <> 'held' THEN
502
+ SELECT journal_acknowledged_through INTO acknowledged
503
+ FROM infinity.authority_runtime_meta WHERE singleton;
504
+ IF acknowledged IS NULL OR acknowledged < NEW.authority_commit_sequence THEN
505
+ RAISE EXCEPTION 'outbox record cannot cross an unacknowledged authority frontier' USING ERRCODE = '23514';
506
+ END IF;
507
+ END IF;
508
+ IF OLD.state = 'held' AND NEW.state = 'pending'
509
+ AND NEW.lease_owner IS NULL AND NEW.lease_expires_at IS NULL THEN
510
+ RETURN NEW;
511
+ ELSIF OLD.state = 'pending' AND NEW.state = 'leased'
512
+ AND OLD.lease_owner IS NULL AND OLD.lease_expires_at IS NULL
513
+ AND NEW.lease_owner IS NOT NULL AND NEW.lease_expires_at > clock_timestamp() THEN
514
+ RETURN NEW;
515
+ ELSIF OLD.state = 'leased' AND NEW.state = 'leased'
516
+ AND OLD.lease_expires_at <= clock_timestamp()
517
+ AND NEW.lease_owner IS NOT NULL AND NEW.lease_expires_at > clock_timestamp() THEN
518
+ RETURN NEW;
519
+ ELSIF OLD.state = 'leased' AND NEW.state = 'delivered'
520
+ AND OLD.lease_expires_at > clock_timestamp()
521
+ AND NEW.lease_owner IS NULL AND NEW.lease_expires_at IS NULL THEN
522
+ RETURN NEW;
523
+ ELSIF OLD.state = 'leased' AND NEW.state = 'pending'
524
+ AND OLD.lease_expires_at <= clock_timestamp()
525
+ AND NEW.lease_owner IS NULL AND NEW.lease_expires_at IS NULL THEN
526
+ RETURN NEW;
527
+ ELSIF OLD.state IN ('pending', 'leased') AND NEW.state = 'blocked'
528
+ AND NEW.lease_owner IS NULL AND NEW.lease_expires_at IS NULL THEN
529
+ RETURN NEW;
530
+ END IF;
531
+ RAISE EXCEPTION 'invalid outbox state or lease transition' USING ERRCODE = '23514';
532
+ END;
533
+ $$;
534
+
535
+ CREATE OR REPLACE FUNCTION infinity.validate_effect_journal_insert() RETURNS trigger
536
+ LANGUAGE plpgsql AS $$
537
+ DECLARE
538
+ current_sequence bigint;
539
+ current_digest text;
540
+ dispatched infinity.effect_journal_records%ROWTYPE;
541
+ prior_outcome infinity.effect_journal_records%ROWTYPE;
542
+ BEGIN
543
+ SELECT journal_sequence, frontier_digest INTO current_sequence, current_digest
544
+ FROM infinity.effect_journal_frontier WHERE singleton FOR UPDATE;
545
+ IF NEW.journal_sequence <> current_sequence + 1 OR NEW.prior_frontier_digest IS DISTINCT FROM current_digest THEN
546
+ RAISE EXCEPTION 'effect journal record does not extend contiguous frontier' USING ERRCODE = '23514';
547
+ END IF;
548
+ IF NEW.anchor_record->>'record_digest' IS DISTINCT FROM NEW.record_digest
549
+ OR NEW.anchor_record->>'frontier_digest' IS DISTINCT FROM NEW.frontier_digest
550
+ OR NEW.anchor_record->>'signer_principal' IS DISTINCT FROM NEW.signer_principal
551
+ OR NEW.anchor_record->>'signing_key_id' IS DISTINCT FROM NEW.signing_key_id
552
+ OR NEW.anchor_record->'record'->>'operation_id' IS DISTINCT FROM NEW.operation_id
553
+ OR NEW.anchor_record->'record'->>'operation_step_id' IS DISTINCT FROM NEW.operation_step_id
554
+ OR (NEW.anchor_record->'record'->>'operation_execution_epoch')::bigint IS DISTINCT FROM NEW.operation_execution_epoch
555
+ OR NEW.anchor_record->'record'->>'record_kind' IS DISTINCT FROM NEW.record_kind
556
+ OR NEW.anchor_record->'record'->>'operation_digest' IS DISTINCT FROM NEW.operation_digest
557
+ OR NEW.anchor_record->'record'->>'operation_step_digest' IS DISTINCT FROM NEW.operation_step_digest
558
+ OR NEW.anchor_record->'record'->>'request_digest' IS DISTINCT FROM NEW.request_digest
559
+ OR NEW.anchor_record->'record'->>'target_digest' IS DISTINCT FROM NEW.target_digest
560
+ OR NEW.anchor_record->'record'->>'resource_id' IS DISTINCT FROM NEW.resource_id
561
+ OR (NEW.anchor_record->'record'->>'resource_lifecycle_generation')::bigint IS DISTINCT FROM NEW.resource_lifecycle_generation
562
+ OR NEW.anchor_record->'record'->>'predecessor_receipt_digest' IS DISTINCT FROM NEW.predecessor_receipt_digest
563
+ OR NEW.anchor_record->'record'->>'provider_idempotency_token' IS DISTINCT FROM NEW.provider_idempotency_token THEN
564
+ RAISE EXCEPTION 'effect journal columns differ from signed anchor envelope' USING ERRCODE = '23514';
565
+ END IF;
566
+ IF NEW.record_kind = 'OUTCOME' THEN
567
+ SELECT * INTO dispatched FROM infinity.effect_journal_records
568
+ WHERE operation_id = NEW.operation_id AND operation_step_id = NEW.operation_step_id
569
+ AND operation_execution_epoch = NEW.operation_execution_epoch AND record_kind = 'DISPATCHED';
570
+ IF NOT FOUND OR dispatched.anchor_record->'record'->'fence' <> NEW.anchor_record->'record'->'fence'
571
+ OR dispatched.operation_digest <> NEW.operation_digest
572
+ OR dispatched.operation_step_digest <> NEW.operation_step_digest
573
+ OR dispatched.request_digest <> NEW.request_digest
574
+ OR dispatched.target_digest <> NEW.target_digest
575
+ OR dispatched.resource_id <> NEW.resource_id
576
+ OR dispatched.resource_lifecycle_generation <> NEW.resource_lifecycle_generation
577
+ OR dispatched.predecessor_receipt_digest IS DISTINCT FROM NEW.predecessor_receipt_digest
578
+ OR dispatched.provider_idempotency_token <> NEW.provider_idempotency_token THEN
579
+ RAISE EXCEPTION 'OUTCOME requires the matching immutable DISPATCHED fence' USING ERRCODE = '23514';
580
+ END IF;
581
+ ELSE
582
+ IF NEW.operation_execution_epoch = 1 THEN
583
+ NULL;
584
+ ELSE
585
+ SELECT * INTO prior_outcome FROM infinity.effect_journal_records
586
+ WHERE operation_id = NEW.operation_id AND operation_step_id = NEW.operation_step_id
587
+ AND operation_execution_epoch = NEW.operation_execution_epoch - 1 AND record_kind = 'OUTCOME';
588
+ IF NOT FOUND OR prior_outcome.outcome_kind <> 'failed_no_effect'
589
+ OR prior_outcome.operation_digest <> NEW.operation_digest
590
+ OR prior_outcome.operation_step_digest <> NEW.operation_step_digest
591
+ OR prior_outcome.request_digest <> NEW.request_digest
592
+ OR prior_outcome.target_digest <> NEW.target_digest
593
+ OR prior_outcome.resource_id <> NEW.resource_id
594
+ OR prior_outcome.resource_lifecycle_generation <> NEW.resource_lifecycle_generation
595
+ OR prior_outcome.predecessor_receipt_digest IS DISTINCT FROM NEW.predecessor_receipt_digest
596
+ OR prior_outcome.provider_idempotency_token <> NEW.provider_idempotency_token THEN
597
+ RAISE EXCEPTION 'higher execution epoch lacks stable failed_no_effect predecessor' USING ERRCODE = '23514';
598
+ END IF;
599
+ END IF;
600
+ END IF;
601
+ RETURN NEW;
602
+ END;
603
+ $$;
604
+
605
+ CREATE TRIGGER run_specs_immutable BEFORE UPDATE OR DELETE ON infinity.run_specs
606
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
607
+ CREATE TRIGGER admission_keys_immutable BEFORE UPDATE OR DELETE ON infinity.admission_keys
608
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
609
+ CREATE TRIGGER attempt_lease_grants_immutable BEFORE UPDATE OR DELETE ON infinity.attempt_lease_grants
610
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
611
+ CREATE TRIGGER attempt_lease_events_immutable BEFORE UPDATE OR DELETE ON infinity.attempt_lease_events
612
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
613
+ CREATE TRIGGER events_immutable BEFORE UPDATE OR DELETE ON infinity.events
614
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
615
+ CREATE TRIGGER effect_operation_steps_immutable BEFORE UPDATE OR DELETE ON infinity.effect_operation_steps
616
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
617
+ CREATE TRIGGER effect_journal_records_immutable BEFORE UPDATE OR DELETE ON infinity.effect_journal_records
618
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
619
+ CREATE TRIGGER effect_journal_insert_guard BEFORE INSERT ON infinity.effect_journal_records
620
+ FOR EACH ROW EXECUTE FUNCTION infinity.validate_effect_journal_insert();
621
+ CREATE TRIGGER authority_mutation_envelope_insert_guard BEFORE INSERT ON infinity.authority_mutation_envelopes
622
+ FOR EACH ROW EXECUTE FUNCTION infinity.validate_authority_mutation_envelope();
623
+ CREATE TRIGGER authority_mutation_acknowledgement_insert_guard BEFORE INSERT ON infinity.authority_mutation_acknowledgements
624
+ FOR EACH ROW EXECUTE FUNCTION infinity.validate_authority_mutation_acknowledgement();
625
+ CREATE TRIGGER authority_ack_frontier_update_guard BEFORE UPDATE ON infinity.authority_runtime_meta
626
+ FOR EACH ROW EXECUTE FUNCTION infinity.validate_authority_ack_frontier_update();
627
+ CREATE TRIGGER outbox_write_guard BEFORE INSERT OR UPDATE ON infinity.outbox
628
+ FOR EACH ROW EXECUTE FUNCTION infinity.validate_outbox_write();
629
+
630
+ CREATE TRIGGER run_specs_mutation_capture AFTER INSERT ON infinity.run_specs
631
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
632
+ CREATE TRIGGER runs_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.runs
633
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
634
+ CREATE TRIGGER attempts_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.attempts
635
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
636
+ CREATE TRIGGER attempt_lease_grants_mutation_capture AFTER INSERT ON infinity.attempt_lease_grants
637
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
638
+ CREATE TRIGGER attempt_lease_events_mutation_capture AFTER INSERT ON infinity.attempt_lease_events
639
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
640
+ CREATE TRIGGER queue_entries_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.queue_entries
641
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
642
+ CREATE TRIGGER budget_reservations_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.budget_reservations
643
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
644
+ CREATE TRIGGER admission_keys_mutation_capture AFTER INSERT ON infinity.admission_keys
645
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
646
+ CREATE TRIGGER idempotency_records_mutation_capture AFTER INSERT OR UPDATE ON infinity.idempotency_records
647
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
648
+ CREATE TRIGGER event_stream_heads_mutation_capture AFTER INSERT OR UPDATE ON infinity.event_stream_heads
649
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
650
+ CREATE TRIGGER events_mutation_capture AFTER INSERT ON infinity.events
651
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
652
+ CREATE TRIGGER outbox_mutation_capture AFTER INSERT ON infinity.outbox
653
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
654
+ CREATE TRIGGER external_operations_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.external_operations
655
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
656
+ CREATE TRIGGER authority_runtime_meta_mutation_capture AFTER UPDATE ON infinity.authority_runtime_meta
657
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
658
+
659
+ CREATE TRIGGER authority_mutation_change_buffer_immutable BEFORE UPDATE OR DELETE ON infinity.authority_mutation_change_buffer
660
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
661
+ CREATE TRIGGER authority_mutation_envelopes_immutable BEFORE UPDATE OR DELETE ON infinity.authority_mutation_envelopes
662
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
663
+ CREATE TRIGGER authority_mutation_acknowledgements_immutable BEFORE UPDATE OR DELETE ON infinity.authority_mutation_acknowledgements
664
+ FOR EACH ROW EXECUTE FUNCTION infinity.reject_immutable_mutation();
665
+
666
+ INSERT INTO infinity.authority_epochs (
667
+ authority_epoch, state, activation_receipt_digest, activated_at, is_current
668
+ ) VALUES (
669
+ 1, 'reconciled', 'sha256:0000000000000000000000000000000000000000000000000000000000000000', clock_timestamp(), true
670
+ ) ON CONFLICT (authority_epoch) DO NOTHING;
671
+
672
+ INSERT INTO infinity.authority_runtime_meta (
673
+ singleton, next_queue_sequence, next_commit_sequence, journal_acknowledged_through,
674
+ budget_limit_units, budget_reserved_units, budget_charged_units, budget_released_units
675
+ ) VALUES (true, 1, 1, 0, 1000000, 0, 0, 0)
676
+ ON CONFLICT (singleton) DO NOTHING;
677
+
678
+ INSERT INTO infinity.routes (route_lineage_id, route_id, route_epoch, state)
679
+ VALUES ('route-lineage-direct', 'route-direct', 1, 'active')
680
+ ON CONFLICT (route_lineage_id) DO NOTHING;
681
+
682
+ INSERT INTO infinity.effect_journal_frontier (singleton, journal_sequence, frontier_digest, updated_at)
683
+ VALUES (true, 0, NULL, clock_timestamp())
684
+ ON CONFLICT (singleton) DO NOTHING;
685
+
686
+ CREATE TRIGGER authority_epochs_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.authority_epochs
687
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();
688
+ CREATE TRIGGER routes_mutation_capture AFTER INSERT OR UPDATE OR DELETE ON infinity.routes
689
+ FOR EACH ROW EXECUTE FUNCTION infinity.capture_authority_mutation_change();