@sekiban/dcb-runtime 0.2.0 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/README.md +32 -1
  2. package/dist/allocator/AllocatorDurableObject.js +25 -2
  3. package/dist/bootstrap/BootstrapCoordinatorDurableObject.d.ts +2 -0
  4. package/dist/bootstrap/BootstrapCoordinatorDurableObject.js +64 -1
  5. package/dist/bootstrap/OperatorBootstrap.d.ts +5 -1
  6. package/dist/bootstrap/OperatorBootstrap.js +17 -10
  7. package/dist/bootstrap/types.d.ts +6 -0
  8. package/dist/cli/OperatorRepairCli.d.ts +6 -1
  9. package/dist/cli/OperatorRepairCli.js +26 -6
  10. package/dist/cloudflare.d.ts +5 -0
  11. package/dist/cloudflare.js +1567 -465
  12. package/dist/commit/CommitWorker.d.ts +19 -0
  13. package/dist/commit/CommitWorker.js +176 -27
  14. package/dist/completeness/IncidentLifecycle.d.ts +75 -0
  15. package/dist/completeness/IncidentLifecycle.js +503 -0
  16. package/dist/completeness/types.d.ts +67 -0
  17. package/dist/cosmos.d.ts +34 -4
  18. package/dist/cosmos.js +214 -49
  19. package/dist/downstream/OutboxDrain.d.ts +4 -1
  20. package/dist/downstream/OutboxDrain.js +24 -2
  21. package/dist/generated/cosmos-layout.d.ts +87 -0
  22. package/dist/generated/cosmos-layout.js +99 -0
  23. package/dist/http/ConfiguredBearer.d.ts +12 -0
  24. package/dist/http/ConfiguredBearer.js +33 -0
  25. package/dist/http/IncidentMaintenance.d.ts +8 -0
  26. package/dist/http/IncidentMaintenance.js +124 -0
  27. package/dist/http/SerializedQueryWorker.js +37 -0
  28. package/dist/index.d.ts +13 -0
  29. package/dist/index.js +1627 -465
  30. package/dist/read/SerializedReadWorker.d.ts +3 -0
  31. package/dist/read/SerializedReadWorker.js +3 -3
  32. package/dist/shard/ShardRotation.d.ts +48 -0
  33. package/dist/shard/ShardRotation.js +120 -0
  34. package/dist/store/CosmosEventStore.js +56 -46
  35. package/dist/store/PostgresEventStore.d.ts +20 -0
  36. package/dist/store/PostgresEventStore.js +53 -0
  37. package/dist/store/provider.d.ts +4 -0
  38. package/dist/tag/TagDurableObject.js +66 -14
  39. package/dist/tag/TagSqlSchema.d.ts +6 -1
  40. package/dist/tag/TagSqlSchema.js +15 -0
  41. package/dist/tag/types.d.ts +9 -0
  42. package/dist/trace/CommitTrace.d.ts +3 -3
  43. package/dist/trace/CommitTraceVerifier.js +1 -1
  44. package/package.json +6 -15
@@ -926,10 +926,10 @@ var systemOrderClock = Object.freeze({
926
926
  }
927
927
  });
928
928
  var ORDER_SUID_LIMIT = DOTNET_MAX_TICKS + 1n;
929
- function asOrderClockError(error10) {
930
- if (error10 instanceof OrderClockReadError) return error10;
931
- const detail = error10 instanceof Error ? error10.message : "SortableUniqueId allocation failed";
932
- return new OrderClockReadError(detail, { cause: error10 });
929
+ function asOrderClockError(error11) {
930
+ if (error11 instanceof OrderClockReadError) return error11;
931
+ const detail = error11 instanceof Error ? error11.message : "SortableUniqueId allocation failed";
932
+ return new OrderClockReadError(detail, { cause: error11 });
933
933
  }
934
934
  function allocateOrderRange(watermark, count, clockTick, options = {}) {
935
935
  if (!Number.isSafeInteger(count) || count <= 0) {
@@ -958,9 +958,9 @@ function allocateOrderRange(watermark, count, clockTick, options = {}) {
958
958
  watermark: suids.at(-1),
959
959
  suids: Object.freeze(suids)
960
960
  });
961
- } catch (error10) {
962
- if (error10 instanceof SortableUniqueIdError) throw error10;
963
- throw asOrderClockError(error10);
961
+ } catch (error11) {
962
+ if (error11 instanceof SortableUniqueIdError) throw error11;
963
+ throw asOrderClockError(error11);
964
964
  }
965
965
  }
966
966
  function diagnosticAllocatedAt(ticks) {
@@ -978,7 +978,7 @@ function diagnosticAllocatedAt(ticks) {
978
978
  var commit_trace_manifest_default = {
979
979
  schemaVersion: 2,
980
980
  name: "commit-trace-manifest",
981
- description: "Authority for the sdt.commit span manifests. means/19 links to RENDERED-VIEWS.md; it does not duplicate these tables.",
981
+ description: "Repository-owned authority for the sdt.commit span manifests. The generated views are kept in RENDERED-VIEWS.md; the manifest does not duplicate those tables.",
982
982
  remoteInvocationUniverse: [
983
983
  "S16"
984
984
  ],
@@ -3391,9 +3391,9 @@ var commit_trace_manifest_default = {
3391
3391
 
3392
3392
  // src/trace/AttributionRatio.ts
3393
3393
  function failure(code, message) {
3394
- const error10 = new Error(`${code}:${message}`);
3395
- error10.name = "CommitTraceAttributionError";
3396
- throw error10;
3394
+ const error11 = new Error(`${code}:${message}`);
3395
+ error11.name = "CommitTraceAttributionError";
3396
+ throw error11;
3397
3397
  }
3398
3398
  function clip(interval, root) {
3399
3399
  const start = Math.max(interval[0], root[0]);
@@ -3706,8 +3706,8 @@ var CommitTrace = class {
3706
3706
  unattributed,
3707
3707
  attributionGatePassed: unattributed.unattributedRatio <= 0.05
3708
3708
  });
3709
- } catch (error10) {
3710
- this.noteObservationFailure(error10);
3709
+ } catch (error11) {
3710
+ this.noteObservationFailure(error11);
3711
3711
  return Object.freeze({
3712
3712
  ...base,
3713
3713
  runtimeVerification: this.observationVerification()
@@ -3774,9 +3774,9 @@ var CommitTrace = class {
3774
3774
  throw new Error(`Commit trace root ${rowId} is not active`);
3775
3775
  }
3776
3776
  attributes = this.attributesFor(row, options);
3777
- } catch (error10) {
3778
- if (!this.isFailOpen()) throw error10;
3779
- this.noteObservationFailure(error10);
3777
+ } catch (error11) {
3778
+ if (!this.isFailOpen()) throw error11;
3779
+ this.noteObservationFailure(error11);
3780
3780
  return callback(disabledChild());
3781
3781
  }
3782
3782
  const execute = async (native2) => {
@@ -3902,8 +3902,8 @@ var CommitTrace = class {
3902
3902
  for (const [key, value] of Object.entries(attributes)) {
3903
3903
  try {
3904
3904
  native.setAttribute(key, value);
3905
- } catch (error10) {
3906
- this.noteObservationFailure(error10);
3905
+ } catch (error11) {
3906
+ this.noteObservationFailure(error11);
3907
3907
  }
3908
3908
  }
3909
3909
  }
@@ -3920,8 +3920,8 @@ var CommitTrace = class {
3920
3920
  now() {
3921
3921
  try {
3922
3922
  return this.clock().now();
3923
- } catch (error10) {
3924
- this.noteObservationFailure(error10);
3923
+ } catch (error11) {
3924
+ this.noteObservationFailure(error11);
3925
3925
  return Date.now();
3926
3926
  }
3927
3927
  }
@@ -3929,8 +3929,8 @@ var CommitTrace = class {
3929
3929
  let beforeVerification;
3930
3930
  try {
3931
3931
  beforeVerification = this.snapshot();
3932
- } catch (error10) {
3933
- this.noteObservationFailure(error10);
3932
+ } catch (error11) {
3933
+ this.noteObservationFailure(error11);
3934
3934
  return;
3935
3935
  }
3936
3936
  if (this.options.runtimeVerifier !== void 0) {
@@ -3941,15 +3941,15 @@ var CommitTrace = class {
3941
3941
  this.options.runtimeVerifier.verify(beforeVerification);
3942
3942
  this.runtimeVerification = Object.freeze({ passed: true });
3943
3943
  }
3944
- } catch (error10) {
3945
- const code = typeof error10 === "object" && error10 !== null && "code" in error10 && typeof error10.code === "string" ? error10.code : "runtime-verifier-error";
3944
+ } catch (error11) {
3945
+ const code = typeof error11 === "object" && error11 !== null && "code" in error11 && typeof error11.code === "string" ? error11.code : "runtime-verifier-error";
3946
3946
  this.runtimeVerification = Object.freeze({ passed: false, code });
3947
3947
  }
3948
3948
  }
3949
3949
  try {
3950
3950
  this.options.sink?.record(this.snapshot());
3951
- } catch (error10) {
3952
- this.noteObservationFailure(error10);
3951
+ } catch (error11) {
3952
+ this.noteObservationFailure(error11);
3953
3953
  }
3954
3954
  }
3955
3955
  /**
@@ -3961,8 +3961,8 @@ var CommitTrace = class {
3961
3961
  async scheduleDetachedObservation() {
3962
3962
  try {
3963
3963
  await this.options.scheduleDetachedObservation?.();
3964
- } catch (error10) {
3965
- this.noteObservationFailure(error10);
3964
+ } catch (error11) {
3965
+ this.noteObservationFailure(error11);
3966
3966
  }
3967
3967
  }
3968
3968
  isFailOpen() {
@@ -3971,9 +3971,9 @@ var CommitTrace = class {
3971
3971
  observationVerification() {
3972
3972
  return Object.freeze({ passed: false, code: this.observationFailureCode ?? "trace-observation-error" });
3973
3973
  }
3974
- noteObservationFailure(error10) {
3974
+ noteObservationFailure(error11) {
3975
3975
  if (this.observationFailureCode !== void 0) return;
3976
- this.observationFailureCode = typeof error10 === "object" && error10 !== null && "code" in error10 && typeof error10.code === "string" ? error10.code : "trace-observation-error";
3976
+ this.observationFailureCode = typeof error11 === "object" && error11 !== null && "code" in error11 && typeof error11.code === "string" ? error11.code : "trace-observation-error";
3977
3977
  this.runtimeVerification = this.observationVerification();
3978
3978
  }
3979
3979
  /**
@@ -3994,9 +3994,9 @@ var CommitTrace = class {
3994
3994
  return callback(void 0);
3995
3995
  }
3996
3996
  return await result2;
3997
- } catch (error10) {
3998
- if (callbackStarted) throw error10;
3999
- this.noteObservationFailure(error10);
3997
+ } catch (error11) {
3998
+ if (callbackStarted) throw error11;
3999
+ this.noteObservationFailure(error11);
4000
4000
  return callback(void 0);
4001
4001
  }
4002
4002
  }
@@ -4085,8 +4085,8 @@ async function enterNativeSpanFailOpen(nativeTracing, name, callback) {
4085
4085
  const result2 = nativeTracing.enterSpan(name, wrapped);
4086
4086
  if (!callbackStarted) return callback(void 0);
4087
4087
  return await result2;
4088
- } catch (error10) {
4089
- if (callbackStarted) throw error10;
4088
+ } catch (error11) {
4089
+ if (callbackStarted) throw error11;
4090
4090
  return callback(void 0);
4091
4091
  }
4092
4092
  }
@@ -4118,9 +4118,9 @@ async function enterNativeCommitSpan(nativeTracing, name, input, callback) {
4118
4118
  if (response3 !== void 0 && input.face !== "reconcile-root") setNativeAttribute(span, "http.status", response3.status);
4119
4119
  }
4120
4120
  return result2;
4121
- } catch (error10) {
4121
+ } catch (error11) {
4122
4122
  setNativeAttribute(span, "outcome", "exception");
4123
- throw error10;
4123
+ throw error11;
4124
4124
  }
4125
4125
  });
4126
4126
  }
@@ -4159,9 +4159,9 @@ async function enterNativeActorHandleSpan(nativeTracing, input, resolveIdentity,
4159
4159
  if (response3 !== void 0) setNativeAttribute(span, "http.status", response3.status);
4160
4160
  }
4161
4161
  return result2;
4162
- } catch (error10) {
4162
+ } catch (error11) {
4163
4163
  if (identity2 !== void 0) setNativeAttribute(span, "outcome", "exception");
4164
- throw error10;
4164
+ throw error11;
4165
4165
  } finally {
4166
4166
  input.observation?.finish();
4167
4167
  }
@@ -4289,6 +4289,8 @@ var ATTEMPT_KEY_PREFIX2 = "attempt:";
4289
4289
  var ROLLBACK_WARNING_WINDOW_MS = 1000n;
4290
4290
  var AllocationTransactionFault = class extends Error {
4291
4291
  };
4292
+ var ImportSeedRequiredError = class extends Error {
4293
+ };
4292
4294
  function json(body, status = 200) {
4293
4295
  return new Response(JSON.stringify(body), {
4294
4296
  status,
@@ -4328,7 +4330,17 @@ function seedFrom(value) {
4328
4330
  } catch {
4329
4331
  return { error: "highWatermark must be an allocator SUID" };
4330
4332
  }
4331
- return { value: { importId: value.importId, leaseEpoch: value.leaseEpoch, highWatermark: value.highWatermark } };
4333
+ let storeMaximum;
4334
+ if (value.storeMaximum !== void 0) {
4335
+ if (!isNonEmptyString2(value.storeMaximum)) return { error: "storeMaximum must be an allocator SUID" };
4336
+ try {
4337
+ decodeSuid(value.storeMaximum);
4338
+ } catch {
4339
+ return { error: "storeMaximum must be an allocator SUID" };
4340
+ }
4341
+ storeMaximum = value.storeMaximum;
4342
+ }
4343
+ return { value: { importId: value.importId, leaseEpoch: value.leaseEpoch, highWatermark: value.highWatermark, ...storeMaximum !== void 0 ? { storeMaximum } : {} } };
4332
4344
  }
4333
4345
  function newAllocatorLineageId() {
4334
4346
  return crypto.randomUUID();
@@ -4383,7 +4395,8 @@ function allocateFrom(value) {
4383
4395
  faultInjection,
4384
4396
  ...serviceId !== void 0 ? { serviceId } : {},
4385
4397
  ...bootstrapCommandId !== void 0 ? { bootstrapCommandId } : {},
4386
- ...bootstrapEpoch !== void 0 ? { bootstrapEpoch } : {}
4398
+ ...bootstrapEpoch !== void 0 ? { bootstrapEpoch } : {},
4399
+ ...value.requiresImportSeed === true ? { requiresImportSeed: true } : {}
4387
4400
  }
4388
4401
  };
4389
4402
  }
@@ -4768,11 +4781,12 @@ var AllocatorDurableObject = class {
4768
4781
  };
4769
4782
  }
4770
4783
  const state = persistedState === void 0 ? currentState(lineage) : { ...persistedState, allocatorLineageId: lineage, schemaVersion: 5, bootstrapSeed: persistedState.bootstrapSeed ?? null, lastRollbackWarningFingerprint: persistedState.lastRollbackWarningFingerprint ?? null };
4784
+ if (input.requiresImportSeed === true && state.bootstrapSeed === null) throw new ImportSeedRequiredError();
4771
4785
  let clockTick;
4772
4786
  try {
4773
4787
  clockTick = this.orderClock.tick();
4774
- } catch (error10) {
4775
- throw error10 instanceof OrderClockReadError ? error10 : new OrderClockReadError("Order clock failed before allocation write", { cause: error10 });
4788
+ } catch (error11) {
4789
+ throw error11 instanceof OrderClockReadError ? error11 : new OrderClockReadError("Order clock failed before allocation write", { cause: error11 });
4776
4790
  }
4777
4791
  const range = allocateOrderRange(state.allocatedWatermark, input.candidates.length, clockTick);
4778
4792
  const rollback = range.observedTicks !== null && range.physicalTicks < range.observedTicks;
@@ -4846,6 +4860,9 @@ var AllocatorDurableObject = class {
4846
4860
  }
4847
4861
  return json(result2.vector, result2.created ? 201 : 200);
4848
4862
  } catch (failure3) {
4863
+ if (failure3 instanceof ImportSeedRequiredError) {
4864
+ return error(409, "allocator_seed_required", "commit before import seed");
4865
+ }
4849
4866
  if (failure3 instanceof AllocationTransactionFault) {
4850
4867
  return error(
4851
4868
  503,
@@ -4886,7 +4903,10 @@ var AllocatorDurableObject = class {
4886
4903
  return { status: 409, body: { code: "allocator_seed_rejected", error: "allocator already seeded" } };
4887
4904
  }
4888
4905
  if (state.allocatedWatermark !== null) return { status: 409, body: { code: "allocator_seed_rejected", error: "allocator already allocating" } };
4889
- const updated = { ...state, allocatedWatermark: input.highWatermark, bootstrapSeed: input };
4906
+ if (input.storeMaximum !== void 0 && input.highWatermark < input.storeMaximum) {
4907
+ return { status: 409, body: { code: "allocator_seed_below_store_max", error: "seed below store maximum" } };
4908
+ }
4909
+ const updated = { ...state, allocatedWatermark: input.highWatermark, bootstrapSeed: { importId: input.importId, leaseEpoch: input.leaseEpoch, highWatermark: input.highWatermark } };
4890
4910
  await txn.put(STATE_KEY, updated);
4891
4911
  return { status: 201, body: updated };
4892
4912
  });
@@ -4911,7 +4931,7 @@ var isPlainRecord = (value) => {
4911
4931
  return prototype === Object.prototype || prototype === null;
4912
4932
  };
4913
4933
  function assertJsonValue(value, boundary = "value") {
4914
- const active = /* @__PURE__ */ new WeakSet();
4934
+ const active2 = /* @__PURE__ */ new WeakSet();
4915
4935
  const visit = (candidate, path) => {
4916
4936
  if (candidate === null || typeof candidate === "string" || typeof candidate === "boolean") {
4917
4937
  return candidate;
@@ -4923,10 +4943,10 @@ function assertJsonValue(value, boundary = "value") {
4923
4943
  if (typeof candidate !== "object") {
4924
4944
  throw new JsonValidationError(`Value at ${path} is not JSON serializable`, boundary, path);
4925
4945
  }
4926
- if (active.has(candidate)) {
4946
+ if (active2.has(candidate)) {
4927
4947
  throw new JsonValidationError(`Cyclic JSON value at ${path}`, boundary, path);
4928
4948
  }
4929
- active.add(candidate);
4949
+ active2.add(candidate);
4930
4950
  try {
4931
4951
  if (Array.isArray(candidate)) {
4932
4952
  return candidate.map((item, index) => visit(item, `${path}[${index}]`));
@@ -4940,7 +4960,7 @@ function assertJsonValue(value, boundary = "value") {
4940
4960
  }
4941
4961
  return result2;
4942
4962
  } finally {
4943
- active.delete(candidate);
4963
+ active2.delete(candidate);
4944
4964
  }
4945
4965
  };
4946
4966
  return visit(value, "$");
@@ -5035,16 +5055,16 @@ function createUuidV7(nowMs = Date.now()) {
5035
5055
  if (typeof globalThis.crypto?.getRandomValues !== "function") {
5036
5056
  throw new Error("crypto.getRandomValues is required for UUIDv7");
5037
5057
  }
5038
- const bytes = new Uint8Array(16);
5039
- globalThis.crypto.getRandomValues(bytes);
5058
+ const bytes2 = new Uint8Array(16);
5059
+ globalThis.crypto.getRandomValues(bytes2);
5040
5060
  let time = BigInt(nowMs);
5041
5061
  for (let index = 5; index >= 0; index -= 1) {
5042
- bytes[index] = Number(time & 0xffn);
5062
+ bytes2[index] = Number(time & 0xffn);
5043
5063
  time >>= 8n;
5044
5064
  }
5045
- bytes[6] = bytes[6] & 15 | 112;
5046
- bytes[8] = bytes[8] & 63 | 128;
5047
- const hex = [...bytes].map((value) => value.toString(16).padStart(2, "0")).join("");
5065
+ bytes2[6] = bytes2[6] & 15 | 112;
5066
+ bytes2[8] = bytes2[8] & 63 | 128;
5067
+ const hex = [...bytes2].map((value) => value.toString(16).padStart(2, "0")).join("");
5048
5068
  return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
5049
5069
  }
5050
5070
  function isRfc4122Uuid(value) {
@@ -5160,7 +5180,7 @@ var epoch = (value) => typeof value === "number" && Number.isSafeInteger(value)
5160
5180
  var response = (body, status = 200) => new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json; charset=utf-8" } });
5161
5181
  var reject = (code, message, status = 409) => response({ code, error: message }, status);
5162
5182
  function empty(serviceId) {
5163
- return { schemaVersion: 1, status: "EMPTY", importId: null, targetServiceId: serviceId, allocatorLineageId: null, source: null, digest: null, manifest: null, progress: {}, leaseEpoch: 0, leaseUntil: null, failure: null, readyAt: null, normalInFlight: 0, normalCommands: {}, releasedCommands: {}, verifiedImportId: null, verifiedLeaseEpoch: null, storeCompletion: null };
5183
+ return { schemaVersion: 1, status: "EMPTY", importId: null, targetServiceId: serviceId, allocatorLineageId: null, source: null, digest: null, manifest: null, progress: {}, leaseEpoch: 0, leaseUntil: null, failure: null, readyAt: null, normalInFlight: 0, normalCommands: {}, releasedCommands: {}, writePermits: {}, verifiedImportId: null, verifiedLeaseEpoch: null, storeCompletion: null };
5164
5184
  }
5165
5185
  function expired(control) {
5166
5186
  return control.leaseUntil !== null && control.leaseUntil <= Date.now();
@@ -5171,12 +5191,22 @@ function commands(control) {
5171
5191
  function released(control) {
5172
5192
  return { ...control.releasedCommands ?? {} };
5173
5193
  }
5194
+ function permits(control) {
5195
+ return { ...control.writePermits ?? {} };
5196
+ }
5174
5197
  function fault(body, point) {
5175
5198
  return object(body) && body.faultAt === point;
5176
5199
  }
5177
5200
  function encodedBytes(value) {
5178
5201
  return new TextEncoder().encode(JSON.stringify(value)).byteLength;
5179
5202
  }
5203
+ async function readBody(request) {
5204
+ try {
5205
+ return await request.json();
5206
+ } catch {
5207
+ return void 0;
5208
+ }
5209
+ }
5180
5210
  var BootstrapCoordinatorDurableObject = class {
5181
5211
  constructor(ctx, env, nativeTracing = noOpNativeTracing) {
5182
5212
  this.ctx = ctx;
@@ -5198,6 +5228,8 @@ var BootstrapCoordinatorDurableObject = class {
5198
5228
  if (request.method === "POST" && url.pathname === "/command/admit") return this.traceCommand(request, serviceId, activation2, observation, "admit");
5199
5229
  if (request.method === "POST" && url.pathname === "/command/finalize") return this.traceCommand(request, serviceId, activation2, observation, "finalize");
5200
5230
  if (request.method === "POST" && url.pathname === "/command/release") return this.traceCommand(request, serviceId, activation2, observation, "release");
5231
+ if (request.method === "POST" && url.pathname === "/command/permit") return this.permit(serviceId, await readBody(request));
5232
+ if (request.method === "POST" && url.pathname === "/command/permit-release") return this.permitRelease(serviceId, await readBody(request));
5201
5233
  let body;
5202
5234
  try {
5203
5235
  body = await request.json();
@@ -5254,6 +5286,7 @@ var BootstrapCoordinatorDurableObject = class {
5254
5286
  const control = await txn.get(CONTROL) ?? empty(serviceId);
5255
5287
  if (control.status === "READY") return { error: "bootstrap_ready_permanent" };
5256
5288
  if (control.status !== "EMPTY") return control.importId === importId && control.digest === dump.manifest.contentDigest ? { control } : { error: "bootstrap_plan_conflict" };
5289
+ if (Object.keys(permits(control)).length !== 0) return { error: "bootstrap_write_permit_active" };
5257
5290
  if (control.normalInFlight !== 0 || Object.keys(commands(control)).length !== 0) return { error: "bootstrap_normal_command_in_flight" };
5258
5291
  const next = { ...control, status: "PLANNED", importId, allocatorLineageId: dump.manifest.target.allocatorLineageId, source: dump.manifest.source, digest: dump.manifest.contentDigest, manifest: dump.manifest, leaseEpoch: control.leaseEpoch + 1, leaseUntil: Date.now() + 3e4, failure: null, progress: {}, verifiedImportId: null, verifiedLeaseEpoch: null, storeCompletion: null };
5259
5292
  await txn.put(CONTROL, next);
@@ -5266,17 +5299,17 @@ var BootstrapCoordinatorDurableObject = class {
5266
5299
  chunks(events) {
5267
5300
  const chunks = [];
5268
5301
  let current = [];
5269
- let bytes = 0;
5302
+ let bytes2 = 0;
5270
5303
  for (const event of events) {
5271
5304
  const eventBytes = encodedBytes(event);
5272
5305
  if (eventBytes > MAX_CHUNK_BYTES) throw new Error("bootstrap event exceeds encoded chunk bound");
5273
- if (current.length === MAX_CHUNK_EVENTS || bytes + eventBytes > MAX_CHUNK_BYTES) {
5306
+ if (current.length === MAX_CHUNK_EVENTS || bytes2 + eventBytes > MAX_CHUNK_BYTES) {
5274
5307
  chunks.push(current);
5275
5308
  current = [];
5276
- bytes = 0;
5309
+ bytes2 = 0;
5277
5310
  }
5278
5311
  current.push(event);
5279
- bytes += eventBytes;
5312
+ bytes2 += eventBytes;
5280
5313
  }
5281
5314
  if (current.length > 0) chunks.push(current);
5282
5315
  return chunks;
@@ -5422,6 +5455,45 @@ var BootstrapCoordinatorDurableObject = class {
5422
5455
  const control = await this.control(serviceId);
5423
5456
  return control.status === "EMPTY" || control.status === "READY" ? response({ admitted: true, leaseEpoch: control.leaseEpoch, route: body.route }) : reject("bootstrap_route_rejected", `${body.route} is unavailable during bootstrap`);
5424
5457
  }
5458
+ async permit(serviceId, body) {
5459
+ if (!object(body) || !string(body.commandId) || !string(body.digest)) return reject("bootstrap_permit_invalid", "commandId and digest are required", 400);
5460
+ const commandId = body.commandId;
5461
+ const digest = body.digest;
5462
+ const result2 = await this.ctx.storage.transaction(async (txn) => {
5463
+ const control = await txn.get(CONTROL) ?? empty(serviceId);
5464
+ const active2 = permits(control);
5465
+ if (active2[commandId] !== void 0) {
5466
+ return active2[commandId] === digest ? { control } : { digestMismatch: true };
5467
+ }
5468
+ if (control.status !== "EMPTY" && control.status !== "READY") return { rejected: true };
5469
+ const updated = { ...control, writePermits: { ...active2, [commandId]: digest } };
5470
+ await txn.put(CONTROL, updated);
5471
+ return { control: updated };
5472
+ });
5473
+ if ("digestMismatch" in result2) return reject("bootstrap_permit_digest_mismatch", "bootstrap permit digest does not match the held permit");
5474
+ if ("rejected" in result2) return reject("bootstrap_command_rejected", "bootstrap epoch rejects normal durable mutation");
5475
+ return response({ leaseEpoch: result2.control.leaseEpoch, admitted: true });
5476
+ }
5477
+ async permitRelease(serviceId, body) {
5478
+ if (!object(body) || !string(body.commandId)) return reject("bootstrap_permit_invalid", "commandId is required", 400);
5479
+ const commandId = body.commandId;
5480
+ const digest = string(body.digest) ? body.digest : void 0;
5481
+ const result2 = await this.ctx.storage.transaction(async (txn) => {
5482
+ const control = await txn.get(CONTROL) ?? empty(serviceId);
5483
+ const active2 = permits(control);
5484
+ if (active2[commandId] !== void 0 && digest !== void 0 && active2[commandId] !== digest) {
5485
+ return { digestMismatch: true };
5486
+ }
5487
+ if (active2[commandId] === void 0) return { control };
5488
+ const next = { ...active2 };
5489
+ delete next[commandId];
5490
+ const updated = { ...control, writePermits: next };
5491
+ await txn.put(CONTROL, updated);
5492
+ return { control: updated };
5493
+ });
5494
+ if ("digestMismatch" in result2) return reject("bootstrap_permit_digest_mismatch", "bootstrap permit digest does not match the held permit");
5495
+ return response({ leaseEpoch: result2.control.leaseEpoch, admitted: true });
5496
+ }
5425
5497
  async command(serviceId, body, action, observation) {
5426
5498
  if (!object(body) || !string(body.commandId)) return reject("bootstrap_command_invalid", "commandId is required", 400);
5427
5499
  const commandId = body.commandId;
@@ -5487,13 +5559,13 @@ function byteCompare(left, right) {
5487
5559
  }
5488
5560
  function concat(parts) {
5489
5561
  const length = parts.reduce((total, part) => total + part.byteLength, 0);
5490
- const bytes = new Uint8Array(length);
5562
+ const bytes2 = new Uint8Array(length);
5491
5563
  let offset = 0;
5492
5564
  for (const part of parts) {
5493
- bytes.set(part, offset);
5565
+ bytes2.set(part, offset);
5494
5566
  offset += part.byteLength;
5495
5567
  }
5496
- return bytes;
5568
+ return bytes2;
5497
5569
  }
5498
5570
  function lengthPrefix(length) {
5499
5571
  if (!Number.isSafeInteger(length) || length < 0 || length > 4294967295) {
@@ -5522,8 +5594,8 @@ function requiredUtf8(input, name) {
5522
5594
  function tagSetBytes(tags) {
5523
5595
  const canonical2 = canonicalDeclaredTagSet(tags);
5524
5596
  return concat(canonical2.map((tag) => {
5525
- const bytes = utf8(tag);
5526
- return concat([lengthPrefix(bytes.byteLength), bytes]);
5597
+ const bytes2 = utf8(tag);
5598
+ return concat([lengthPrefix(bytes2.byteLength), bytes2]);
5527
5599
  }));
5528
5600
  }
5529
5601
  function canonicalDeclaredTagSet(tags) {
@@ -5593,16 +5665,16 @@ function eventDigestBytes(input) {
5593
5665
  ]);
5594
5666
  }
5595
5667
  async function eventDigestHex(input) {
5596
- const bytes = eventDigestBytes(input);
5597
- const source = bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
5668
+ const bytes2 = eventDigestBytes(input);
5669
+ const source = bytes2.buffer.slice(bytes2.byteOffset, bytes2.byteOffset + bytes2.byteLength);
5598
5670
  const digest = await crypto.subtle.digest("SHA-256", source);
5599
5671
  return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
5600
5672
  }
5601
5673
 
5602
5674
  // src/bootstrap/BootstrapStoreAdapter.ts
5603
- function arrayBufferBase64(bytes) {
5675
+ function arrayBufferBase64(bytes2) {
5604
5676
  let binary = "";
5605
- for (const byte of bytes) binary += String.fromCharCode(byte);
5677
+ for (const byte of bytes2) binary += String.fromCharCode(byte);
5606
5678
  return btoa(binary);
5607
5679
  }
5608
5680
  var BootstrapIdentityConflictError = class extends Error {
@@ -5742,6 +5814,34 @@ function createBootstrapStoreAdapter(provider, store, identityGuard) {
5742
5814
  return new BootstrapStoreAdapter(provider, store, identityGuard);
5743
5815
  }
5744
5816
 
5817
+ // src/http/ConfiguredBearer.ts
5818
+ async function sha256(value) {
5819
+ const encoded = new TextEncoder().encode(value);
5820
+ return new Uint8Array(await crypto.subtle.digest("SHA-256", encoded));
5821
+ }
5822
+ function digestsMatch(expected, supplied) {
5823
+ let difference = expected.length ^ supplied.length;
5824
+ const length = Math.max(expected.length, supplied.length);
5825
+ for (let index = 0; index < length; index += 1) {
5826
+ difference |= (expected[index] ?? 0) ^ (supplied[index] ?? 0);
5827
+ }
5828
+ return difference === 0;
5829
+ }
5830
+ async function checkConfiguredBearer(request, binding, options) {
5831
+ if (typeof binding !== "string" || binding.trim().length === 0) {
5832
+ return "unconfigured";
5833
+ }
5834
+ const effectiveToken = options?.tokenNormalization === "trim" ? binding.trim() : binding;
5835
+ const supplied = request.headers.get("authorization");
5836
+ if (supplied === null) return "missing";
5837
+ const expected = `Bearer ${effectiveToken}`;
5838
+ const [expectedDigest, suppliedDigest] = await Promise.all([
5839
+ sha256(expected),
5840
+ sha256(supplied)
5841
+ ]);
5842
+ return digestsMatch(expectedDigest, suppliedDigest) ? "authorized" : "invalid";
5843
+ }
5844
+
5745
5845
  // src/bootstrap/OperatorBootstrap.ts
5746
5846
  function json2(body, status = 200) {
5747
5847
  return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json; charset=utf-8" } });
@@ -5749,15 +5849,17 @@ function json2(body, status = 200) {
5749
5849
  function object2(value) {
5750
5850
  return typeof value === "object" && value !== null && !Array.isArray(value);
5751
5851
  }
5752
- function bearer(request, token) {
5753
- const supplied = request.headers.get("authorization");
5754
- if (supplied === null) return json2({ code: "not_found", error: "not found" }, 404);
5755
- if (supplied !== `Bearer ${token}`) return json2({ code: "operator_auth_required", error: "valid bearer required" }, 403);
5852
+ async function authenticateOperatorBootstrap(request, binding) {
5853
+ const decision = await checkConfiguredBearer(request, binding);
5854
+ if (decision === "unconfigured" || decision === "missing") {
5855
+ return json2({ code: "not_found", error: "not found" }, 404);
5856
+ }
5857
+ if (decision === "invalid") {
5858
+ return json2({ code: "operator_auth_required", error: "valid bearer required" }, 403);
5859
+ }
5756
5860
  return void 0;
5757
5861
  }
5758
- async function handleOperatorBootstrap(request, env, storeProvider, hooks = {}) {
5759
- const denied = bearer(request, env.REPAIR_OPERATOR_TOKEN);
5760
- if (denied !== void 0) return denied;
5862
+ async function handleAuthorizedOperatorBootstrap(request, env, storeProvider, hooks = {}) {
5761
5863
  const url = new URL(request.url);
5762
5864
  const match = url.pathname.match(/^\/operator\/bootstrap\/([^/]+)\/(plan|import|status|abort|export)$/);
5763
5865
  if (match === null) return json2({ code: "not_found", error: "not found" }, 404);
@@ -6656,14 +6758,21 @@ function testFaultFromRequest(request) {
6656
6758
  const value = request.headers.get("x-sdt-g6-test-fault");
6657
6759
  return value === "after-lease-before-prepare" || value === "after-prepare-before-apply" || value === "after-apply-before-observation" || value === "after-verify-before-audit" || value === "after-audit-before-clear" || value === "after-clear-before-final-observation" ? value : void 0;
6658
6760
  }
6659
- async function handleOperatorRepair(request, env, nativeTracing = noOpNativeTracing, serviceIdentityProvider) {
6660
- if (request.method !== "POST") {
6661
- return error2(404, "operator_repair_route_not_found", "Operator repair requires POST");
6761
+ function nonPostOperatorRepairResponse(request) {
6762
+ if (request.method === "POST") return void 0;
6763
+ return error2(404, "operator_repair_route_not_found", "Operator repair requires POST");
6764
+ }
6765
+ async function authenticateOperatorRepair(request, binding) {
6766
+ const decision = await checkConfiguredBearer(request, binding);
6767
+ if (decision === "unconfigured") {
6768
+ return error2(404, "operator_repair_route_not_found", "Operator repair route not found");
6662
6769
  }
6663
- const token = env.REPAIR_OPERATOR_TOKEN;
6664
- if (!isNonEmptyString3(token) || request.headers.get("authorization") !== `Bearer ${token}`) {
6770
+ if (decision === "missing" || decision === "invalid") {
6665
6771
  return error2(401, "operator_auth_required", "A valid operator repair bearer token is required");
6666
6772
  }
6773
+ return void 0;
6774
+ }
6775
+ async function handleAuthorizedOperatorRepair(request, env, nativeTracing = noOpNativeTracing, serviceIdentityProvider) {
6667
6776
  let body;
6668
6777
  try {
6669
6778
  body = await request.json();
@@ -6713,6 +6822,22 @@ var COMMIT_TEST_FAULTS = [
6713
6822
  var INITIAL_OWNER_EPOCH = 0;
6714
6823
  var MAX_WRITE_ATTEMPTS = 2;
6715
6824
  var OUTCOME_UNDETERMINED_ERROR = "Commit outcome is undetermined; reread tag heads and event/query state before retrying because blind retry may create duplicate events.";
6825
+ function commitPermitDigest(allTags, candidates) {
6826
+ const normalized = JSON.stringify({
6827
+ tags: [...allTags].sort(),
6828
+ events: candidates.map((candidate) => ({
6829
+ eventId: candidate.eventId,
6830
+ payload: candidate.payload,
6831
+ tags: [...candidate.tags].sort()
6832
+ })).sort((left, right) => left.eventId < right.eventId ? -1 : left.eventId > right.eventId ? 1 : 0)
6833
+ });
6834
+ let hash = 2166136261;
6835
+ for (let index = 0; index < normalized.length; index += 1) {
6836
+ hash ^= normalized.charCodeAt(index);
6837
+ hash = Math.imul(hash, 16777619) >>> 0;
6838
+ }
6839
+ return `fnv1a32:${hash.toString(16).padStart(8, "0")}`;
6840
+ }
6716
6841
  var GLOBAL_ADMISSION_HEADER = "x-sdt-global-admission";
6717
6842
  var runtimeCommitTraceVerifier = {
6718
6843
  verify(snapshot) {
@@ -6766,19 +6891,19 @@ var CommitPayloadAdmissionError = class extends Error {
6766
6891
  code;
6767
6892
  };
6768
6893
  function decodeBase64Utf8Json(value) {
6769
- let bytes;
6894
+ let bytes2;
6770
6895
  try {
6771
6896
  const binary = atob(value);
6772
- bytes = Uint8Array.from(binary, (character) => character.charCodeAt(0));
6897
+ bytes2 = Uint8Array.from(binary, (character) => character.charCodeAt(0));
6773
6898
  } catch {
6774
6899
  throw new CommitPayloadAdmissionError("invalid_payload_utf8", "Payload base64 could not be decoded");
6775
6900
  }
6776
- if (bytes[0] === 239 && bytes[1] === 187 && bytes[2] === 191) {
6901
+ if (bytes2[0] === 239 && bytes2[1] === 187 && bytes2[2] === 191) {
6777
6902
  throw new CommitPayloadAdmissionError("invalid_payload_utf8", "Payload must not start with a UTF-8 BOM");
6778
6903
  }
6779
6904
  let text;
6780
6905
  try {
6781
- text = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
6906
+ text = new TextDecoder("utf-8", { fatal: true }).decode(bytes2);
6782
6907
  } catch {
6783
6908
  throw new CommitPayloadAdmissionError("invalid_payload_utf8", "Payload must be valid UTF-8 JSON text");
6784
6909
  }
@@ -6824,9 +6949,9 @@ function assertExactMemberPaths(actual, registered, path = "$") {
6824
6949
  }
6825
6950
  }
6826
6951
  function encodeBase64Utf8(value) {
6827
- const bytes = new TextEncoder().encode(value);
6952
+ const bytes2 = new TextEncoder().encode(value);
6828
6953
  let binary = "";
6829
- for (const byte of bytes) binary += String.fromCharCode(byte);
6954
+ for (const byte of bytes2) binary += String.fromCharCode(byte);
6830
6955
  return btoa(binary);
6831
6956
  }
6832
6957
  function faultFromRequest(request) {
@@ -7085,25 +7210,43 @@ var CommitWorker = class {
7085
7210
  return responseWithAttempt(error3(409, "bootstrap_command_rejected", "Bootstrap admission could not be released"), attemptId, fault2 !== void 0);
7086
7211
  }
7087
7212
  await this.retiredJournalMilestone("S04", traceState?.scope);
7213
+ const permitDigest = commitPermitDigest(input.allTags, candidates);
7214
+ let permitHeld = false;
7215
+ const releasePermit = async () => {
7216
+ if (!permitHeld) return;
7217
+ permitHeld = false;
7218
+ await this.bootstrapPermitRelease(attemptId, permitDigest);
7219
+ };
7220
+ const permit = await this.bootstrapPermitAcquire(attemptId, permitDigest);
7221
+ if (!permit.ok) {
7222
+ if (permit.code === "bootstrap_permit_digest_mismatch") {
7223
+ return responseWithAttempt(error3(409, "bootstrap_permit_digest_mismatch", "Bootstrap write permit digest does not match"), attemptId, fault2 !== void 0);
7224
+ }
7225
+ return responseWithAttempt(error3(409, "bootstrap_command_rejected", "Bootstrap is importing; commit is unavailable"), attemptId, fault2 !== void 0);
7226
+ }
7227
+ permitHeld = this.env.BOOTSTRAP !== void 0;
7088
7228
  const reservations = await this.acquireReservations(input, attemptId, fault2, traceState?.scope);
7089
7229
  await this.retiredJournalMilestone("S05a", traceState?.scope, 0);
7090
7230
  if (reservations.failure !== void 0) {
7091
- return this.finishReservationFailure(
7231
+ const failure3 = await this.finishReservationFailure(
7092
7232
  [...reservations.successes.keys()],
7093
7233
  attemptId,
7094
7234
  reservations.failure,
7095
7235
  fault2,
7096
7236
  traceState?.scope
7097
7237
  );
7238
+ if (failure3.resolved) await releasePermit();
7239
+ return failure3.response;
7098
7240
  }
7099
7241
  if (fault2 === "after-reservations-before-allocation") {
7100
- await this.cancelReservations([...reservations.successes.keys()], attemptId, fault2, traceState?.scope);
7242
+ const cleanup = await this.cancelReservations([...reservations.successes.keys()], attemptId, fault2, traceState?.scope);
7243
+ if (cleanup.failedTags.length === 0) await releasePermit();
7101
7244
  return this.noApplicationOutcome(attemptId, true);
7102
7245
  }
7103
7246
  await this.hooks.beforeBootstrapAllocation?.();
7104
7247
  const allocation = await this.allocate(candidates, attemptId, fault2, bootstrapEpoch, traceState?.scope);
7105
7248
  if (allocation === void 0) {
7106
- return this.finishReservationFailure(
7249
+ const failure3 = await this.finishReservationFailure(
7107
7250
  [...reservations.successes.keys()],
7108
7251
  attemptId,
7109
7252
  {
@@ -7114,10 +7257,13 @@ var CommitWorker = class {
7114
7257
  fault2,
7115
7258
  traceState?.scope
7116
7259
  );
7260
+ if (failure3.resolved) await releasePermit();
7261
+ return failure3.response;
7117
7262
  }
7118
7263
  const allocatedCandidates = this.withAllocatedSuids(candidates, allocation);
7119
7264
  if (allocatedCandidates === void 0) {
7120
- await this.cancelReservations([...reservations.successes.keys()], attemptId, fault2, traceState?.scope);
7265
+ const cleanup = await this.cancelReservations([...reservations.successes.keys()], attemptId, fault2, traceState?.scope);
7266
+ if (cleanup.failedTags.length === 0) await releasePermit();
7121
7267
  return this.noApplicationOutcome(attemptId, fault2 !== void 0);
7122
7268
  }
7123
7269
  for (const candidate of allocatedCandidates) {
@@ -7132,15 +7278,18 @@ var CommitWorker = class {
7132
7278
  }
7133
7279
  await this.retiredJournalMilestone("S05b", traceState?.scope, 1);
7134
7280
  if (fault2 === "journal-cas-after-allocator") {
7135
- await this.cancelReservations(input.allTags, attemptId, fault2, traceState?.scope);
7281
+ const cleanup = await this.cancelReservations(input.allTags, attemptId, fault2, traceState?.scope);
7282
+ if (cleanup.failedTags.length === 0) await releasePermit();
7136
7283
  return this.noApplicationOutcome(attemptId, true);
7137
7284
  }
7138
7285
  await this.retiredJournalMilestone("S05c", traceState?.scope, 2);
7139
7286
  await this.hooks.beforeBootstrapFinalization?.();
7140
7287
  if (await this.bootstrapCommand("finalize", attemptId, bootstrapEpoch, traceState?.scope, "S10") === void 0) {
7141
- await this.cancelReservations(input.allTags, attemptId, fault2, traceState?.scope);
7288
+ const cleanup = await this.cancelReservations(input.allTags, attemptId, fault2, traceState?.scope);
7289
+ if (cleanup.failedTags.length === 0) await releasePermit();
7142
7290
  return responseWithAttempt(error3(409, "bootstrap_command_rejected", "Bootstrap fencing epoch changed before commit write"), attemptId, fault2 !== void 0);
7143
7291
  }
7292
+ await this.hooks.beforeAuthoritativeAppend?.();
7144
7293
  const writes = await this.appendAllTags(
7145
7294
  input,
7146
7295
  allocatedCandidates,
@@ -7156,6 +7305,7 @@ var CommitWorker = class {
7156
7305
  return this.noApplicationOutcome(attemptId, true);
7157
7306
  }
7158
7307
  if (writes.committedTags.size === 0 && writes.registrationUnavailableTags.length === writes.pendingTags.length) {
7308
+ await releasePermit();
7159
7309
  return responseWithAttempt(
7160
7310
  error3(
7161
7311
  503,
@@ -7167,20 +7317,25 @@ var CommitWorker = class {
7167
7317
  fault2 !== void 0
7168
7318
  );
7169
7319
  }
7320
+ await releasePermit();
7170
7321
  return this.partialWriteOutcome(input, allocatedCandidates, writes, attemptId, fault2 !== void 0);
7171
7322
  }
7323
+ await this.hooks.afterAppendBeforeResponse?.();
7172
7324
  await this.retiredJournalMilestone("S05d", traceState?.scope, 3);
7173
7325
  if (fault2 === "sealing-after-cas") {
7326
+ await releasePermit();
7174
7327
  return this.noApplicationOutcome(attemptId, true);
7175
7328
  }
7176
7329
  try {
7177
- const success = await this.successResponse(input, allocatedCandidates, attemptId, startedAt, fault2, traceState?.scope);
7330
+ const success = await this.successResponse(input, allocatedCandidates, attemptId, startedAt, fault2, traceState?.scope, writes);
7331
+ await releasePermit();
7178
7332
  return responseWithAttempt(
7179
7333
  withGlobalAdmission(json4(success, 200), writes.globalAdmission),
7180
7334
  attemptId,
7181
7335
  fault2 !== void 0
7182
7336
  );
7183
7337
  } catch {
7338
+ await releasePermit();
7184
7339
  return responseWithAttempt(
7185
7340
  error3(500, "internal_error", "Committed records could not be read while preparing the response"),
7186
7341
  attemptId,
@@ -7227,6 +7382,51 @@ var CommitWorker = class {
7227
7382
  const result2 = traceScope === void 0 || rowId === void 0 ? await invoke() : await traceScope.span(rowId, {}, invoke);
7228
7383
  return result2.leaseEpoch;
7229
7384
  }
7385
+ /**
7386
+ * SDT-G36 bootstrap write permit. Deliberately untraced: it must not add
7387
+ * `sdt.commit/v2` rows or new trace identities. Only a bootstrap barrier,
7388
+ * never commit-outcome authority. No JOURNAL, no alarm, no lease expiry.
7389
+ */
7390
+ bootstrapStub() {
7391
+ if (this.env.BOOTSTRAP === void 0) return void 0;
7392
+ return this.env.BOOTSTRAP.get(scopeIdFor(this.env.BOOTSTRAP, {
7393
+ serviceId: this.serviceId,
7394
+ doClass: "bootstrap",
7395
+ identity: "coordinator"
7396
+ }));
7397
+ }
7398
+ async bootstrapPermitAcquire(commandId, digest) {
7399
+ const stub = this.bootstrapStub();
7400
+ if (stub === void 0) return { ok: true };
7401
+ try {
7402
+ const url = new URL(`https://commit-worker.internal/command/permit`);
7403
+ url.searchParams.set("__serviceId", this.serviceId);
7404
+ const response3 = await stub.fetch(new Request(url, {
7405
+ method: "POST",
7406
+ headers: { "content-type": "application/json" },
7407
+ body: JSON.stringify({ commandId, digest })
7408
+ }));
7409
+ if (response3.ok) return { ok: true };
7410
+ const body = await response3.clone().json().catch(() => void 0);
7411
+ return { ok: false, code: typeof body?.code === "string" ? body.code : void 0 };
7412
+ } catch {
7413
+ return { ok: false };
7414
+ }
7415
+ }
7416
+ async bootstrapPermitRelease(commandId, digest) {
7417
+ const stub = this.bootstrapStub();
7418
+ if (stub === void 0) return;
7419
+ try {
7420
+ const url = new URL(`https://commit-worker.internal/command/permit-release`);
7421
+ url.searchParams.set("__serviceId", this.serviceId);
7422
+ await stub.fetch(new Request(url, {
7423
+ method: "POST",
7424
+ headers: { "content-type": "application/json" },
7425
+ body: JSON.stringify({ commandId, digest })
7426
+ }));
7427
+ } catch {
7428
+ }
7429
+ }
7230
7430
  async postJson(stub, path, body, traceScope, rowId, traceOptions = {}) {
7231
7431
  const invoke = async () => {
7232
7432
  const response3 = await stub.fetch(
@@ -7372,6 +7572,7 @@ var CommitWorker = class {
7372
7572
  let pending = [...input.allTags];
7373
7573
  const committedTags = /* @__PURE__ */ new Set();
7374
7574
  const lastFailureCodeByTag = /* @__PURE__ */ new Map();
7575
+ const tagWriteFacts = /* @__PURE__ */ new Map();
7375
7576
  let globalAdmission = "admitted";
7376
7577
  for (let attempt = 0; attempt < MAX_WRITE_ATTEMPTS && pending.length > 0; attempt += 1) {
7377
7578
  const append = (stageScope) => Promise.allSettled(
@@ -7398,12 +7599,26 @@ var CommitWorker = class {
7398
7599
  retryIndex: attempt,
7399
7600
  attemptId
7400
7601
  });
7401
- const body = response3.status === 503 ? await response3.clone().json().catch(() => void 0) : void 0;
7602
+ const success = response3.status >= 200 && response3.status < 300;
7603
+ let appendVersion;
7604
+ let appendUpdatedAt;
7605
+ let code;
7606
+ try {
7607
+ const parsed = await response3.clone().json();
7608
+ if (isObject5(parsed)) {
7609
+ if (typeof parsed.version === "number" && Number.isSafeInteger(parsed.version)) appendVersion = parsed.version;
7610
+ if (typeof parsed.updatedAt === "string" && parsed.updatedAt.length > 0) appendUpdatedAt = parsed.updatedAt;
7611
+ if (typeof parsed.code === "string") code = parsed.code;
7612
+ }
7613
+ } catch {
7614
+ }
7402
7615
  return {
7403
7616
  tag,
7404
- success: response3.status >= 200 && response3.status < 300,
7617
+ success,
7405
7618
  globalAdmission: readGlobalAdmission(response3),
7406
- code: isObject5(body) && typeof body.code === "string" ? body.code : void 0
7619
+ code,
7620
+ appendVersion,
7621
+ appendUpdatedAt
7407
7622
  };
7408
7623
  })
7409
7624
  );
@@ -7415,6 +7630,9 @@ var CommitWorker = class {
7415
7630
  committedTags.add(tag);
7416
7631
  lastFailureCodeByTag.delete(tag);
7417
7632
  globalAdmission = mergeGlobalAdmission(globalAdmission, result2.value.globalAdmission);
7633
+ if (result2.value.appendVersion !== void 0 && result2.value.appendUpdatedAt !== void 0) {
7634
+ tagWriteFacts.set(tag, { version: result2.value.appendVersion, updatedAt: result2.value.appendUpdatedAt });
7635
+ }
7418
7636
  } else {
7419
7637
  lastFailureCodeByTag.set(
7420
7638
  tag,
@@ -7431,7 +7649,8 @@ var CommitWorker = class {
7431
7649
  registrationUnavailableTags: pending.filter(
7432
7650
  (tag) => lastFailureCodeByTag.get(tag) === "partition_registration_unavailable"
7433
7651
  ),
7434
- globalAdmission
7652
+ globalAdmission,
7653
+ tagWriteFacts
7435
7654
  };
7436
7655
  }
7437
7656
  /**
@@ -7464,10 +7683,13 @@ var CommitWorker = class {
7464
7683
  if (traceScope !== void 0) {
7465
7684
  await traceScope.span("S17", {}, async () => void 0);
7466
7685
  }
7467
- await this.cancelReservations(tags, attemptId, fault2, traceScope);
7686
+ const cleanup = await this.cancelReservations(tags, attemptId, fault2, traceScope);
7468
7687
  await this.retiredJournalMilestone("S05e", traceScope, 4);
7469
7688
  const response3 = failure3.outcome === "REFUSED" ? error3(400, "consistency_conflict", "serialized commit was refused by a consistency reservation") : failure3.failureCause === "reservation-timeout" ? error3(504, "timeout", "serialized commit timed out") : error3(500, "internal_error", "serialized commit failed before writing requested records");
7470
- return responseWithAttempt(response3, attemptId, fault2 !== void 0);
7689
+ return {
7690
+ response: responseWithAttempt(response3, attemptId, fault2 !== void 0),
7691
+ resolved: cleanup.failedTags.length === 0
7692
+ };
7471
7693
  }
7472
7694
  /**
7473
7695
  * Persist the local partial-write fact for each tag whose append did not
@@ -7504,22 +7726,25 @@ var CommitWorker = class {
7504
7726
  }
7505
7727
  }, 500), attemptId, exposeAttempt);
7506
7728
  }
7507
- async successResponse(input, candidates, attemptId, startedAt, fault2, traceScope) {
7508
- const readStates = (stageScope) => Promise.all(input.allTags.map(async (tag, memberIndex) => {
7729
+ async successResponse(input, candidates, attemptId, startedAt, fault2, traceScope, writes) {
7730
+ const assemble = async (stageScope) => {
7509
7731
  if (fault2 === "tag-state-unavailable") {
7510
7732
  throw new Error("Test fault made the committed tag state unavailable");
7511
7733
  }
7512
- const response3 = await this.tagRequest(tag, "/head-facts", void 0, stageScope?.fork(), stageScope === void 0 ? void 0 : "S14", { memberIndex, attemptId });
7513
- if (response3.status !== 200) {
7514
- throw new Error("Committed tag state was unavailable while preparing the response");
7515
- }
7516
- const body = await response3.json();
7517
- if (typeof body.version !== "number" || typeof body.updatedAt !== "string" || typeof body.head !== "string") {
7518
- throw new Error("Committed tag state was malformed while preparing the response");
7734
+ const results = [];
7735
+ for (const [memberIndex, tag] of input.allTags.entries()) {
7736
+ const read = () => {
7737
+ const fact = writes?.tagWriteFacts.get(tag);
7738
+ if (fact === void 0) {
7739
+ throw new Error("Committed tag state was unavailable while preparing the response");
7740
+ }
7741
+ return { tag, version: fact.version, writtenAt: fact.updatedAt };
7742
+ };
7743
+ results.push(stageScope === void 0 ? read() : await stageScope.fork().span("S14", { tag, memberIndex, attemptId }, async () => read()));
7519
7744
  }
7520
- return { tag, version: body.version, writtenAt: body.updatedAt };
7521
- }));
7522
- const tagWriteResults = traceScope === void 0 ? await readStates() : await traceScope.span("S13", {}, async (stage) => readStates(stage));
7745
+ return results;
7746
+ };
7747
+ const tagWriteResults = traceScope === void 0 ? await assemble() : await traceScope.span("S13", {}, async (stage) => assemble(stage));
7523
7748
  return {
7524
7749
  writtenEvents: candidates.map((candidate) => ({
7525
7750
  payload: encodeBase64Utf8(candidate.payload),
@@ -7911,15 +8136,15 @@ function observePostAdmission(observer, message, source, input) {
7911
8136
  observedAt: Date.now()
7912
8137
  });
7913
8138
  }
7914
- function errorText(error10) {
7915
- if (error10 instanceof Error && error10.message.length > 0) return error10.message;
7916
- return String(error10);
8139
+ function errorText(error11) {
8140
+ if (error11 instanceof Error && error11.message.length > 0) return error11.message;
8141
+ return String(error11);
7917
8142
  }
7918
8143
  function deliveryCorrelationId(message, source, supplied) {
7919
8144
  return supplied ?? `${source}:${message.serviceId}:${message.eventId}:${message.attemptId}`;
7920
8145
  }
7921
- function defaultFailureClass(error10) {
7922
- const candidate = error10;
8146
+ function defaultFailureClass(error11) {
8147
+ const candidate = error11;
7923
8148
  if (candidate.failureClass === "duplicate-race") return "duplicate-race";
7924
8149
  if (candidate.failureClass === "nonretryable-definition-poison") return "nonretryable-definition-poison";
7925
8150
  if (candidate.failureClass === "retryable-transient") return "retryable-transient";
@@ -7978,8 +8203,8 @@ async function applyViewHandlers(views, message, storedEvent, arrivedAt, source,
7978
8203
  result: { id: view.id, status, durationMs: Math.max(0, performance.now() - viewStartedAt) },
7979
8204
  failure: void 0
7980
8205
  };
7981
- } catch (error10) {
7982
- const failureClass = view.classifyError?.(error10) ?? defaultFailureClass(error10);
8206
+ } catch (error11) {
8207
+ const failureClass = view.classifyError?.(error11) ?? defaultFailureClass(error11);
7983
8208
  observePostAdmission(observer, message, source, {
7984
8209
  stage: "unsafe-view-apply",
7985
8210
  boundary: "end",
@@ -7991,10 +8216,10 @@ async function applyViewHandlers(views, message, storedEvent, arrivedAt, source,
7991
8216
  id: view.id,
7992
8217
  status: "failed",
7993
8218
  failureClass,
7994
- error: errorText(error10),
8219
+ error: errorText(error11),
7995
8220
  durationMs: Math.max(0, performance.now() - viewStartedAt)
7996
8221
  },
7997
- failure: { phase: "view", class: failureClass, viewId: view.id, error: errorText(error10) }
8222
+ failure: { phase: "view", class: failureClass, viewId: view.id, error: errorText(error11) }
7998
8223
  };
7999
8224
  }
8000
8225
  }));
@@ -8024,15 +8249,15 @@ async function processDeliveryCore(message, source, env, options = {}) {
8024
8249
  // settled; this is the durable post-batch observation boundary.
8025
8250
  observedAt: Date.now()
8026
8251
  });
8027
- } catch (error10) {
8028
- const failures2 = [{ phase: "recordDelivery", class: "retryable-transient", error: errorText(error10) }];
8252
+ } catch (error11) {
8253
+ const failures2 = [{ phase: "recordDelivery", class: "retryable-transient", error: errorText(error11) }];
8029
8254
  return result(source, message, "stored", arrivedAt, false, [], failures2, options.correlationId, startedAt);
8030
8255
  }
8031
8256
  if (outcome.outcome !== "stored") {
8032
8257
  try {
8033
8258
  await store.projectDeliveryIncidents?.(message.serviceId);
8034
- } catch (error10) {
8035
- const failures2 = [{ phase: "detector", class: "retryable-transient", error: errorText(error10) }];
8259
+ } catch (error11) {
8260
+ const failures2 = [{ phase: "detector", class: "retryable-transient", error: errorText(error11) }];
8036
8261
  return result(source, message, outcome.outcome, arrivedAt, false, [], failures2, options.correlationId, startedAt);
8037
8262
  }
8038
8263
  return result(source, message, outcome.outcome, arrivedAt, false, [], [], options.correlationId, startedAt);
@@ -8061,20 +8286,20 @@ async function processDeliveryCore(message, source, env, options = {}) {
8061
8286
  boundary: "end",
8062
8287
  outcome: "available"
8063
8288
  });
8064
- } catch (error10) {
8289
+ } catch (error11) {
8065
8290
  observePostAdmission(options.durableHopObserver, message, source, {
8066
8291
  stage: "post-record-delivery-global-receipt-readback",
8067
8292
  boundary: "end",
8068
8293
  outcome: "error"
8069
8294
  });
8070
- failures.push({ phase: "recordDelivery", class: "retryable-transient", error: errorText(error10) });
8295
+ failures.push({ phase: "recordDelivery", class: "retryable-transient", error: errorText(error11) });
8071
8296
  return result(source, message, "stored", arrivedAt, false, [], failures, options.correlationId, startedAt);
8072
8297
  }
8073
8298
  if (options.afterGlobalReceipt !== void 0) {
8074
8299
  try {
8075
8300
  await options.afterGlobalReceipt({ message, receipt, arrivedAt, source });
8076
- } catch (error10) {
8077
- failures.push({ phase: "drain", class: "retryable-transient", error: errorText(error10) });
8301
+ } catch (error11) {
8302
+ failures.push({ phase: "drain", class: "retryable-transient", error: errorText(error11) });
8078
8303
  }
8079
8304
  }
8080
8305
  }
@@ -8091,8 +8316,8 @@ async function processDeliveryCore(message, source, env, options = {}) {
8091
8316
  if (options.beforeViews !== void 0) {
8092
8317
  try {
8093
8318
  await options.beforeViews({ message, event: storedEvent, arrivedAt, source });
8094
- } catch (error10) {
8095
- failures.push({ phase: "completeness", class: "retryable-transient", error: errorText(error10) });
8319
+ } catch (error11) {
8320
+ failures.push({ phase: "completeness", class: "retryable-transient", error: errorText(error11) });
8096
8321
  return result(source, message, "stored", arrivedAt, false, viewResults, failures, options.correlationId, startedAt);
8097
8322
  }
8098
8323
  }
@@ -8112,14 +8337,14 @@ async function processDeliveryCore(message, source, env, options = {}) {
8112
8337
  boundary: "end",
8113
8338
  outcome: "applied"
8114
8339
  });
8115
- } catch (error10) {
8340
+ } catch (error11) {
8116
8341
  observePostAdmission(options.durableHopObserver, message, source, {
8117
8342
  stage: "detector",
8118
8343
  boundary: "end",
8119
8344
  outcome: "error"
8120
8345
  });
8121
8346
  try {
8122
- await options.onDetectorFailure?.({ message, arrivedAt, source, error: error10 });
8347
+ await options.onDetectorFailure?.({ message, arrivedAt, source, error: error11 });
8123
8348
  } catch (healthError) {
8124
8349
  failures.push({
8125
8350
  phase: "detector",
@@ -8127,7 +8352,7 @@ async function processDeliveryCore(message, source, env, options = {}) {
8127
8352
  error: `detector_health_record_failed:${errorText(healthError)}`
8128
8353
  });
8129
8354
  }
8130
- failures.push({ phase: "detector", class: "retryable-transient", error: errorText(error10) });
8355
+ failures.push({ phase: "detector", class: "retryable-transient", error: errorText(error11) });
8131
8356
  return result(source, message, "stored", arrivedAt, false, [], failures, options.correlationId, startedAt);
8132
8357
  }
8133
8358
  const views = gatedViews;
@@ -8144,16 +8369,16 @@ async function processDeliveryCore(message, source, env, options = {}) {
8144
8369
  if (options.onStored !== void 0) {
8145
8370
  try {
8146
8371
  await options.onStored({ message, event: storedEvent, arrivedAt, source });
8147
- } catch (error10) {
8148
- failures.push({ phase: "view", class: "retryable-transient", viewId: "legacy-onStored", error: errorText(error10) });
8372
+ } catch (error11) {
8373
+ failures.push({ phase: "view", class: "retryable-transient", viewId: "legacy-onStored", error: errorText(error11) });
8149
8374
  }
8150
8375
  }
8151
8376
  const preliminary = result(source, message, "stored", arrivedAt, detectorApplied, viewResults, failures, options.correlationId, startedAt);
8152
8377
  if (options.afterDelivery !== void 0 && failures.every((failure3) => failure3.class === "duplicate-race")) {
8153
8378
  try {
8154
8379
  await options.afterDelivery({ message, event: storedEvent, arrivedAt, source, result: preliminary });
8155
- } catch (error10) {
8156
- failures.push({ phase: "drain", class: "retryable-transient", error: errorText(error10) });
8380
+ } catch (error11) {
8381
+ failures.push({ phase: "drain", class: "retryable-transient", error: errorText(error11) });
8157
8382
  }
8158
8383
  }
8159
8384
  return result(source, message, "stored", arrivedAt, detectorApplied, viewResults, failures, options.correlationId, startedAt);
@@ -8175,8 +8400,8 @@ function asNumber(value, name) {
8175
8400
  if (!Number.isSafeInteger(number) || number < 0) throw new Error(`G44 ${name} must be a non-negative safe integer`);
8176
8401
  return number;
8177
8402
  }
8178
- function errorText2(error10) {
8179
- return error10 instanceof Error && error10.message.length > 0 ? error10.message : String(error10);
8403
+ function errorText2(error11) {
8404
+ return error11 instanceof Error && error11.message.length > 0 ? error11.message : String(error11);
8180
8405
  }
8181
8406
  function settledFrontierFromCursor(cursorJson) {
8182
8407
  const cursor = settledCursorFromJson(cursorJson);
@@ -8280,8 +8505,8 @@ var GlobalCompletenessReconciler = class {
8280
8505
  let snapshots;
8281
8506
  try {
8282
8507
  snapshots = await this.snapshotPartitions(serviceId);
8283
- } catch (error10) {
8284
- const message = errorText2(error10);
8508
+ } catch (error11) {
8509
+ const message = errorText2(error11);
8285
8510
  await this.appendFinding(serviceId, {
8286
8511
  identity: scannerFailureIdentity(serviceId),
8287
8512
  type: "GLOBAL_ARRAY_SCANNER_FAILURE",
@@ -8323,7 +8548,7 @@ var GlobalCompletenessReconciler = class {
8323
8548
  let joined;
8324
8549
  try {
8325
8550
  joined = this.options.globalReceiptMatcher === void 0 ? await this.globalReceiptMatches(snapshot.serviceId, snapshot.tag, obligation) : await this.options.globalReceiptMatcher(snapshot.serviceId, snapshot.tag, obligation);
8326
- } catch (error10) {
8551
+ } catch (error11) {
8327
8552
  await this.appendFinding(snapshot.serviceId, {
8328
8553
  identity: `GLOBAL_RECEIPT_UNAVAILABLE|${snapshot.serviceId}|${snapshot.tag}|${obligation.obligationSequence}|${obligation.eventId}|${obligation.eventDigest}`,
8329
8554
  type: "GLOBAL_ARRAY_RECEIPT_UNAVAILABLE",
@@ -8332,7 +8557,7 @@ var GlobalCompletenessReconciler = class {
8332
8557
  eventId: obligation.eventId,
8333
8558
  eventDigest: obligation.eventDigest
8334
8559
  }, nowMs).catch(() => void 0);
8335
- throw error10;
8560
+ throw error11;
8336
8561
  }
8337
8562
  if (!joined) {
8338
8563
  await this.appendObligationFinding(snapshot.serviceId, snapshot.tag, obligation, nowMs);
@@ -8351,8 +8576,8 @@ var GlobalCompletenessReconciler = class {
8351
8576
  if (afterSequence !== snapshot.upperBoundSequence) {
8352
8577
  throw new Error(`source_partition_range_incomplete:${snapshot.tag}`);
8353
8578
  }
8354
- } catch (error10) {
8355
- if (errorText2(error10).startsWith("source_")) {
8579
+ } catch (error11) {
8580
+ if (errorText2(error11).startsWith("source_")) {
8356
8581
  await this.appendFinding(snapshot.serviceId, {
8357
8582
  identity: sourceUnavailableIdentity(snapshot.serviceId, snapshot.tag),
8358
8583
  type: "GLOBAL_ARRAY_SOURCE_PARTITION_UNAVAILABLE",
@@ -8362,7 +8587,7 @@ var GlobalCompletenessReconciler = class {
8362
8587
  eventDigest: null
8363
8588
  }, nowMs).catch(() => void 0);
8364
8589
  }
8365
- throw error10;
8590
+ throw error11;
8366
8591
  }
8367
8592
  }
8368
8593
  const endSnapshots = await this.snapshotPartitions(serviceId);
@@ -8381,8 +8606,8 @@ var GlobalCompletenessReconciler = class {
8381
8606
  }
8382
8607
  await this.writeHealth(serviceId, "HEALTHY", JSON.stringify(cursor), nowMs, null, nowMs);
8383
8608
  return { kind: "FULL", partitions: snapshots, scannedObligations: scanned };
8384
- } catch (error10) {
8385
- const message = errorText2(error10);
8609
+ } catch (error11) {
8610
+ const message = errorText2(error11);
8386
8611
  const health = message.startsWith("source_") ? "UNKNOWN" : "FAILED";
8387
8612
  if (health === "FAILED") {
8388
8613
  await this.appendFinding(serviceId, {
@@ -8524,8 +8749,8 @@ var GlobalCompletenessReconciler = class {
8524
8749
  * without applying views. It shares the scanner's single health/finding
8525
8750
  * authority rather than creating a second incident workflow.
8526
8751
  */
8527
- async recordDetectorFailure(serviceId, error10, nowMs) {
8528
- const message = `detector_failure:${errorText2(error10).slice(0, 256)}`;
8752
+ async recordDetectorFailure(serviceId, error11, nowMs) {
8753
+ const message = `detector_failure:${errorText2(error11).slice(0, 256)}`;
8529
8754
  await this.appendFinding(serviceId, {
8530
8755
  identity: `GLOBAL_DETECTOR_FAILURE|${serviceId}`,
8531
8756
  type: "GLOBAL_ARRAY_DETECTOR_FAILURE",
@@ -8664,7 +8889,7 @@ var GlobalCompletenessReconciler = class {
8664
8889
  nowMs
8665
8890
  ).run();
8666
8891
  }
8667
- async writeHealth(serviceId, status, cursor, lastFullScanAt, error10, nowMs) {
8892
+ async writeHealth(serviceId, status, cursor, lastFullScanAt, error11, nowMs) {
8668
8893
  await this.database.prepare(
8669
8894
  `INSERT INTO serialized_dcb_completeness_scanner_health
8670
8895
  (service_id, scanner_version, status, cursor_json, last_full_scan_at, last_error, updated_at)
@@ -8676,7 +8901,7 @@ var GlobalCompletenessReconciler = class {
8676
8901
  last_full_scan_at = COALESCE(excluded.last_full_scan_at, serialized_dcb_completeness_scanner_health.last_full_scan_at),
8677
8902
  last_error = excluded.last_error,
8678
8903
  updated_at = excluded.updated_at`
8679
- ).bind(serviceId, this.scannerVersion, status, cursor, lastFullScanAt, error10, nowMs).run();
8904
+ ).bind(serviceId, this.scannerVersion, status, cursor, lastFullScanAt, error11, nowMs).run();
8680
8905
  }
8681
8906
  };
8682
8907
  function globalReceiptAcknowledgement(message, receivedAt) {
@@ -8768,7 +8993,7 @@ function sourceAcknowledgementOptions(env, options) {
8768
8993
  if (decision.kind !== "SETTLED") {
8769
8994
  throw new Error(`global_completeness_${decision.kind}:${decision.health.status}`);
8770
8995
  }
8771
- } catch (error10) {
8996
+ } catch (error11) {
8772
8997
  if (!completed) {
8773
8998
  observeG60PostAdmission(options.durableHopObserver, {
8774
8999
  stage: "completeness-coverage",
@@ -8783,7 +9008,7 @@ function sourceAcknowledgementOptions(env, options) {
8783
9008
  observedAt: Date.now()
8784
9009
  });
8785
9010
  }
8786
- throw error10;
9011
+ throw error11;
8787
9012
  }
8788
9013
  } : options.beforeViews;
8789
9014
  const observedSourceAcknowledgement = sourceAcknowledgement === void 0 ? void 0 : async (input) => {
@@ -8791,14 +9016,14 @@ function sourceAcknowledgementOptions(env, options) {
8791
9016
  try {
8792
9017
  await sourceAcknowledgement(input);
8793
9018
  observeSourceSubstep(options.durableHopObserver, { ...input, boundary: "end", outcome: "acknowledged" });
8794
- } catch (error10) {
9019
+ } catch (error11) {
8795
9020
  observeSourceSubstep(options.durableHopObserver, { ...input, boundary: "end", outcome: "error" });
8796
- throw error10;
9021
+ throw error11;
8797
9022
  }
8798
9023
  };
8799
- const detectorFailure = hasG44Authority ? async ({ message, arrivedAt, error: error10, source }) => {
8800
- await options.onDetectorFailure?.({ message, arrivedAt, error: error10, source });
8801
- await new GlobalCompletenessReconciler(env.D1, env.TAG).recordDetectorFailure(message.serviceId, error10, arrivedAt);
9024
+ const detectorFailure = hasG44Authority ? async ({ message, arrivedAt, error: error11, source }) => {
9025
+ await options.onDetectorFailure?.({ message, arrivedAt, error: error11, source });
9026
+ await new GlobalCompletenessReconciler(env.D1, env.TAG).recordDetectorFailure(message.serviceId, error11, arrivedAt);
8802
9027
  } : options.onDetectorFailure;
8803
9028
  return {
8804
9029
  ...options,
@@ -8813,9 +9038,9 @@ function sharedStore(env, provider) {
8813
9038
  async function admitBootstrapRoute(env, serviceId, route) {
8814
9039
  if (env.BOOTSTRAP === void 0) {
8815
9040
  if (env.G38_DOORBELL_DELIVERY_ROLE === "receiver") {
8816
- const error10 = new Error(`bootstrap_route_binding_missing:${route}`);
8817
- error10.name = "BootstrapRouteBindingMissingError";
8818
- throw error10;
9041
+ const error11 = new Error(`bootstrap_route_binding_missing:${route}`);
9042
+ error11.name = "BootstrapRouteBindingMissingError";
9043
+ throw error11;
8819
9044
  }
8820
9045
  return;
8821
9046
  }
@@ -8904,10 +9129,10 @@ async function handleDownstreamQueue(batch, env, options = {}) {
8904
9129
  if (outcome.outcome === "stored" && !outcome.failures.some((failure3) => failure3.phase === "recordDelivery")) {
8905
9130
  try {
8906
9131
  options.afterStoredQueueDelivery?.({ message: queued.body, result: outcome });
8907
- } catch (error10) {
9132
+ } catch (error11) {
8908
9133
  console.warn("safe_lane_kick", {
8909
9134
  status: "failed-to-schedule",
8910
- error: error10 instanceof Error ? error10.message : String(error10),
9135
+ error: error11 instanceof Error ? error11.message : String(error11),
8911
9136
  serviceId: queued.body.serviceId,
8912
9137
  eventId: queued.body.eventId,
8913
9138
  attemptId: queued.body.attemptId
@@ -8929,6 +9154,36 @@ async function stabilizeDownstream(env, options = {}, serviceId, serviceIdentity
8929
9154
  });
8930
9155
  }
8931
9156
 
9157
+ // src/scope/ControlRouteScope.ts
9158
+ function response2(status, code, error11) {
9159
+ return new Response(JSON.stringify({ code, error: error11 }), {
9160
+ status,
9161
+ headers: { "content-type": "application/json; charset=utf-8" }
9162
+ });
9163
+ }
9164
+ function scopeIdentityMissingResponse() {
9165
+ return response2(503, "scope.identity_missing", "A deployment service identity is required for this scope");
9166
+ }
9167
+ function enforceControlRouteScope(input) {
9168
+ let actual;
9169
+ try {
9170
+ actual = input.provider.forRequest(input.request, input.requestOptions).serviceId;
9171
+ } catch (caught) {
9172
+ if (caught instanceof ServiceIdentityMissingError) {
9173
+ console.error({ schema: "sdt.scope/v1", code: "scope.identity_missing", route: input.route });
9174
+ return { response: scopeIdentityMissingResponse() };
9175
+ }
9176
+ throw caught;
9177
+ }
9178
+ if (input.pathServiceId !== actual) {
9179
+ console.warn({ schema: "sdt.scope/v1", code: "scope.mismatch", route: input.route });
9180
+ return {
9181
+ response: response2(403, "scope.mismatch", "The path service identity is not authorized for this deployment")
9182
+ };
9183
+ }
9184
+ return { serviceId: actual };
9185
+ }
9186
+
8932
9187
  // src/downstream/OutboxDrain.ts
8933
9188
  function json5(body, status = 200) {
8934
9189
  return new Response(JSON.stringify(body), {
@@ -9025,15 +9280,32 @@ async function handleOutboxDrainRequest(request, env, options = {}) {
9025
9280
  if (!isDrainRequest(body)) {
9026
9281
  return json5({ error: "serviceId and unique non-empty tags are required", code: "invalid_outbox_drain_request" }, 400);
9027
9282
  }
9283
+ const requestedServiceId = body.serviceId;
9284
+ const tags = body.tags;
9285
+ const provider = options.serviceIdentityProvider ?? envServiceIdentity(env);
9286
+ let authority;
9287
+ try {
9288
+ authority = provider.forRequest(request).serviceId;
9289
+ } catch (caught) {
9290
+ if (caught instanceof ServiceIdentityMissingError) return scopeIdentityMissingResponse();
9291
+ throw caught;
9292
+ }
9293
+ if (requestedServiceId !== authority) {
9294
+ console.warn({ schema: "sdt.scope/v1", code: "scope.mismatch", route: "outbox-drain" });
9295
+ return json5({
9296
+ code: "scope.mismatch",
9297
+ error: "The request service identity is not authorized for this deployment"
9298
+ }, 403);
9299
+ }
9028
9300
  try {
9029
9301
  const results = [];
9030
- for (const tag of body.tags) {
9031
- results.push(await drainTagOutbox({ serviceId: body.serviceId, tag }, env, systemPipelineClock, options));
9302
+ for (const tag of tags) {
9303
+ results.push(await drainTagOutbox({ serviceId: authority, tag }, env, systemPipelineClock, options));
9032
9304
  }
9033
9305
  return json5({ results });
9034
- } catch (error10) {
9306
+ } catch (error11) {
9035
9307
  return json5({
9036
- error: error10 instanceof Error ? error10.message : "Outbox drain failed",
9308
+ error: error11 instanceof Error ? error11.message : "Outbox drain failed",
9037
9309
  code: "outbox_drain_failed"
9038
9310
  }, 503);
9039
9311
  }
@@ -9783,9 +10055,9 @@ function isNonEmptyString7(value) {
9783
10055
  return typeof value === "string" && value.length > 0;
9784
10056
  }
9785
10057
  function base64Json(value) {
9786
- const bytes = new TextEncoder().encode(JSON.stringify(value));
10058
+ const bytes2 = new TextEncoder().encode(JSON.stringify(value));
9787
10059
  let binary = "";
9788
- for (const byte of bytes) {
10060
+ for (const byte of bytes2) {
9789
10061
  binary += String.fromCharCode(byte);
9790
10062
  }
9791
10063
  return btoa(binary);
@@ -9963,9 +10235,9 @@ function decodeStoredJson(value) {
9963
10235
  }
9964
10236
  }
9965
10237
  function jsonBytes(value) {
9966
- const bytes = new TextEncoder().encode(JSON.stringify(value));
10238
+ const bytes2 = new TextEncoder().encode(JSON.stringify(value));
9967
10239
  let binary = "";
9968
- for (const byte of bytes) binary += String.fromCharCode(byte);
10240
+ for (const byte of bytes2) binary += String.fromCharCode(byte);
9969
10241
  return btoa(binary);
9970
10242
  }
9971
10243
  function isRuntimeBridgedProjector(definition) {
@@ -10158,8 +10430,8 @@ function asNumber2(value, name) {
10158
10430
  if (!Number.isSafeInteger(number)) throw new Error(`D1 ${name} was not a safe integer`);
10159
10431
  return number;
10160
10432
  }
10161
- function errorText3(error10) {
10162
- return (error10 instanceof Error ? error10.message : String(error10)).slice(0, 256);
10433
+ function errorText3(error11) {
10434
+ return (error11 instanceof Error ? error11.message : String(error11)).slice(0, 256);
10163
10435
  }
10164
10436
  function sortedUnique2(values) {
10165
10437
  return [...new Set(values)].sort((left, right) => binaryCompare(left, right));
@@ -10346,8 +10618,8 @@ var D1EventStore = class {
10346
10618
  let failure3;
10347
10619
  try {
10348
10620
  result2 = await this.recordDeliveryCore(message, arrivedAt, deliverySource, mutationAttemptId);
10349
- } catch (error10) {
10350
- failure3 = { error: error10 };
10621
+ } catch (error11) {
10622
+ failure3 = { error: error11 };
10351
10623
  }
10352
10624
  const retryReason = failure3 === void 0 ? null : errorText3(failure3.error);
10353
10625
  const suppressDiagnostic = failure3?.error instanceof D1IdentityConflictError && failure3.error.beforeMutation;
@@ -10918,8 +11190,8 @@ var D1EventStore = class {
10918
11190
  if (replay === null || replay === void 0) return finish({ kind: "miss" });
10919
11191
  const event = await this.eventById(serviceId, asString3(replay.event_id, "replay.event_id"));
10920
11192
  return event === void 0 ? finish({ kind: "unknown", reason: "replay-event-row-disappeared" }) : finish({ kind: "replay", event });
10921
- } catch (error10) {
10922
- return finish({ kind: "unknown", reason: errorText3(error10) });
11193
+ } catch (error11) {
11194
+ return finish({ kind: "unknown", reason: errorText3(error11) });
10923
11195
  }
10924
11196
  }
10925
11197
  /**
@@ -11394,8 +11666,8 @@ var D1EventStore = class {
11394
11666
  try {
11395
11667
  try {
11396
11668
  await this.options.beforeG69AdmissionAttempt?.();
11397
- } catch (error10) {
11398
- await appendFailedDiagnostic(errorText3(error10));
11669
+ } catch (error11) {
11670
+ await appendFailedDiagnostic(errorText3(error11));
11399
11671
  return;
11400
11672
  }
11401
11673
  const afterObservedAt = Date.now();
@@ -11469,15 +11741,15 @@ function integer(row, key) {
11469
11741
  function operationId() {
11470
11742
  return `mv-unsafe-${crypto.randomUUID()}`;
11471
11743
  }
11472
- function errorFrom(error10) {
11473
- const value = String(error10);
11744
+ function errorFrom(error11) {
11745
+ const value = String(error11);
11474
11746
  if (value.includes("mv_unsafe_receipts") && (value.includes("UNIQUE") || value.includes("constraint"))) {
11475
- return new UnsafeWindowMaterializedViewError("UNSAFE_DUPLICATE_RACE", false, "Concurrent unsafe receipt was committed by another delivery", { cause: error10 });
11747
+ return new UnsafeWindowMaterializedViewError("UNSAFE_DUPLICATE_RACE", false, "Concurrent unsafe receipt was committed by another delivery", { cause: error11 });
11476
11748
  }
11477
- if (value.includes("unsafe_row_cas")) return new UnsafeWindowMaterializedViewError("UNSAFE_ROW_CAS_MISMATCH", true, "Unsafe row version changed before atomic apply", { cause: error10 });
11478
- if (value.includes("unsafe_suid_contradiction")) return new UnsafeWindowMaterializedViewError("UNSAFE_SUID_CONTRADICTION", false, "Unsafe same-SUID payload contradiction", { cause: error10 });
11479
- if (value.includes("unsafe_safe_ahead")) return new UnsafeWindowMaterializedViewError("UNSAFE_SAFE_AHEAD", false, "Safe head already covers unsafe event", { cause: error10 });
11480
- if (value.includes("unsafe_behind_frontier")) return new UnsafeWindowMaterializedViewError("UNSAFE_BEHIND_FRONTIER", false, "Unsafe reads are fail-closed pending rebuild", { cause: error10 });
11749
+ if (value.includes("unsafe_row_cas")) return new UnsafeWindowMaterializedViewError("UNSAFE_ROW_CAS_MISMATCH", true, "Unsafe row version changed before atomic apply", { cause: error11 });
11750
+ if (value.includes("unsafe_suid_contradiction")) return new UnsafeWindowMaterializedViewError("UNSAFE_SUID_CONTRADICTION", false, "Unsafe same-SUID payload contradiction", { cause: error11 });
11751
+ if (value.includes("unsafe_safe_ahead")) return new UnsafeWindowMaterializedViewError("UNSAFE_SAFE_AHEAD", false, "Safe head already covers unsafe event", { cause: error11 });
11752
+ if (value.includes("unsafe_behind_frontier")) return new UnsafeWindowMaterializedViewError("UNSAFE_BEHIND_FRONTIER", false, "Unsafe reads are fail-closed pending rebuild", { cause: error11 });
11481
11753
  return void 0;
11482
11754
  }
11483
11755
  var UnsafeWindowMaterializedViewStore = class {
@@ -11610,8 +11882,8 @@ var UnsafeWindowMaterializedViewStore = class {
11610
11882
  await this.options.beforeApplyBatch?.(input, statements);
11611
11883
  try {
11612
11884
  await this.database.batch(statements);
11613
- } catch (error10) {
11614
- const text = String(error10);
11885
+ } catch (error11) {
11886
+ const text = String(error11);
11615
11887
  const guardFailure = text.includes("mv_atomic_guards") || text.includes("checkpoint_match") || text.includes("mv_unsafe_receipts") && (text.includes("UNIQUE") || text.includes("constraint"));
11616
11888
  if (guardFailure) {
11617
11889
  const receipt = await this.database.prepare(
@@ -11619,16 +11891,16 @@ var UnsafeWindowMaterializedViewStore = class {
11619
11891
  ).bind(input.serviceId, input.viewId, input.eventId).first();
11620
11892
  if (receipt !== null && receipt !== void 0) {
11621
11893
  if (string2(receipt, "suid") !== input.suid) {
11622
- throw new UnsafeWindowMaterializedViewError("UNSAFE_SUID_CONTRADICTION", false, "Duplicate event identity has a contradictory SUID", { cause: error10 });
11894
+ throw new UnsafeWindowMaterializedViewError("UNSAFE_SUID_CONTRADICTION", false, "Duplicate event identity has a contradictory SUID", { cause: error11 });
11623
11895
  }
11624
11896
  if (this.options.beforeApplyBatch !== void 0) {
11625
- throw new UnsafeWindowMaterializedViewError("UNSAFE_DUPLICATE_RACE", false, "Concurrent unsafe receipt was committed by another delivery", { cause: error10 });
11897
+ throw new UnsafeWindowMaterializedViewError("UNSAFE_DUPLICATE_RACE", false, "Concurrent unsafe receipt was committed by another delivery", { cause: error11 });
11626
11898
  }
11627
11899
  return { outcome: "no-change", duplicate: true };
11628
11900
  }
11629
11901
  return this.apply(input, true);
11630
11902
  }
11631
- throw error10;
11903
+ throw error11;
11632
11904
  }
11633
11905
  const result2 = { outcome: "applied", duplicate: false };
11634
11906
  await this.options.afterApplyBatch?.(input, result2);
@@ -11761,13 +12033,13 @@ var UnsafeWindowMaterializedViewStore = class {
11761
12033
  await this.options.beforeApplyBatch?.(input, statements);
11762
12034
  try {
11763
12035
  await this.database.batch(statements);
11764
- } catch (error10) {
11765
- if (sameSuidContradiction) throw new UnsafeWindowMaterializedViewError("UNSAFE_SUID_CONTRADICTION", false, "Unsafe same-SUID payload contradiction", { cause: error10 });
11766
- if (rowCasMismatch) throw new UnsafeWindowMaterializedViewError("UNSAFE_ROW_CAS_MISMATCH", true, "Unsafe row version changed before atomic apply", { cause: error10 });
11767
- if (safeAhead) throw new UnsafeWindowMaterializedViewError("UNSAFE_SAFE_AHEAD", false, "Safe head already covers unsafe event", { cause: error10 });
11768
- const typed = errorFrom(error10);
12036
+ } catch (error11) {
12037
+ if (sameSuidContradiction) throw new UnsafeWindowMaterializedViewError("UNSAFE_SUID_CONTRADICTION", false, "Unsafe same-SUID payload contradiction", { cause: error11 });
12038
+ if (rowCasMismatch) throw new UnsafeWindowMaterializedViewError("UNSAFE_ROW_CAS_MISMATCH", true, "Unsafe row version changed before atomic apply", { cause: error11 });
12039
+ if (safeAhead) throw new UnsafeWindowMaterializedViewError("UNSAFE_SAFE_AHEAD", false, "Safe head already covers unsafe event", { cause: error11 });
12040
+ const typed = errorFrom(error11);
11769
12041
  if (typed !== void 0) throw typed;
11770
- throw error10;
12042
+ throw error11;
11771
12043
  }
11772
12044
  const result2 = { outcome, duplicate: false };
11773
12045
  await this.options.afterApplyBatch?.(input, result2);
@@ -11834,8 +12106,8 @@ var UnsafeWindowMaterializedViewStore = class {
11834
12106
  this.database.prepare(`UPDATE mv_unsafe_kicks SET lease_owner = ?, lease_until = ?, dirty = 0 WHERE service_id = ? AND view_id = ?`).bind(owner, nowMs + leaseMs, serviceId, viewId),
11835
12107
  this.database.prepare("DELETE FROM mv_atomic_guards WHERE operation_id = ?").bind(operation2)
11836
12108
  ]);
11837
- } catch (error10) {
11838
- throw new UnsafeWindowMaterializedViewError("UNSAFE_KICK_LEASE_HELD", true, "Unsafe kick is held by another lease owner", { cause: error10 });
12109
+ } catch (error11) {
12110
+ throw new UnsafeWindowMaterializedViewError("UNSAFE_KICK_LEASE_HELD", true, "Unsafe kick is held by another lease owner", { cause: error11 });
11839
12111
  }
11840
12112
  const row = await this.database.prepare(`SELECT target_suid, dirty FROM mv_unsafe_kicks WHERE service_id = ? AND view_id = ?`).bind(serviceId, viewId).first();
11841
12113
  return row === null || row === void 0 ? void 0 : { targetSuid: string2(row, "target_suid"), dirty: integer(row, "dirty") === 1 };
@@ -11909,9 +12181,9 @@ var UnsafeWindowMaterializedViewStore = class {
11909
12181
  try {
11910
12182
  await this.database.batch(statements);
11911
12183
  return true;
11912
- } catch (error10) {
11913
- if (String(error10).includes("mv_atomic_guards") || String(error10).includes("checkpoint_match")) return false;
11914
- throw error10;
12184
+ } catch (error11) {
12185
+ if (String(error11).includes("mv_atomic_guards") || String(error11).includes("checkpoint_match")) return false;
12186
+ throw error11;
11915
12187
  }
11916
12188
  }
11917
12189
  /**
@@ -12077,12 +12349,12 @@ function indexValue(row, type) {
12077
12349
  function operationId2() {
12078
12350
  return `mv-${crypto.randomUUID()}`;
12079
12351
  }
12080
- function isCasFailure(error10) {
12081
- const message = String(error10);
12352
+ function isCasFailure(error11) {
12353
+ const message = String(error11);
12082
12354
  return message.includes("mv_atomic_guards.checkpoint_match") || message.includes("MV_CAS_MISMATCH");
12083
12355
  }
12084
- function isPatchFailure(error10) {
12085
- return String(error10).includes("CHECK constraint failed: checkpoint_match");
12356
+ function isPatchFailure(error11) {
12357
+ return String(error11).includes("CHECK constraint failed: checkpoint_match");
12086
12358
  }
12087
12359
  var D1MaterializedViewStore = class {
12088
12360
  constructor(database) {
@@ -12118,8 +12390,8 @@ var D1MaterializedViewStore = class {
12118
12390
  VALUES (?, ?, ?, ?)`
12119
12391
  ).bind(input.serviceId, input.viewId, generation, input.updatedAt)
12120
12392
  ]);
12121
- } catch (error10) {
12122
- throw new MaterializedViewStoreError("create-active", "MV_INSTANCE_EXISTS", `Active materialized view already exists: ${String(error10)}`, { cause: error10 });
12393
+ } catch (error11) {
12394
+ throw new MaterializedViewStoreError("create-active", "MV_INSTANCE_EXISTS", `Active materialized view already exists: ${String(error11)}`, { cause: error11 });
12123
12395
  }
12124
12396
  return this.readInstance(input.serviceId, input.viewId, generation);
12125
12397
  }
@@ -12140,8 +12412,8 @@ var D1MaterializedViewStore = class {
12140
12412
  input.definitionVersion,
12141
12413
  input.updatedAt
12142
12414
  ).run();
12143
- } catch (error10) {
12144
- throw new MaterializedViewStoreError("create-candidate", "MV_INSTANCE_EXISTS", `Candidate generation already exists: ${String(error10)}`, { cause: error10 });
12415
+ } catch (error11) {
12416
+ throw new MaterializedViewStoreError("create-candidate", "MV_INSTANCE_EXISTS", `Candidate generation already exists: ${String(error11)}`, { cause: error11 });
12145
12417
  }
12146
12418
  return this.readInstance(input.serviceId, input.viewId, input.generation);
12147
12419
  }
@@ -12279,10 +12551,10 @@ var D1MaterializedViewStore = class {
12279
12551
  */
12280
12552
  async readListPage(serviceId, viewId, options = {}) {
12281
12553
  this.ready("initialize");
12282
- const active = await this.readActive(serviceId, viewId);
12283
- if (active === void 0) return { rows: [], totalCount: 0, readHead: "" };
12284
- const selected = options.generation ?? active.generation;
12285
- const selectedInstance = selected === active.generation ? active : await this.readInstance(serviceId, viewId, selected);
12554
+ const active2 = await this.readActive(serviceId, viewId);
12555
+ if (active2 === void 0) return { rows: [], totalCount: 0, readHead: "" };
12556
+ const selected = options.generation ?? active2.generation;
12557
+ const selectedInstance = selected === active2.generation ? active2 : await this.readInstance(serviceId, viewId, selected);
12286
12558
  if (selectedInstance === void 0) {
12287
12559
  throw new MaterializedViewStoreError("initialize", "MV_INSTANCE_MISSING", "Requested materialized-view generation is unavailable");
12288
12560
  }
@@ -12799,10 +13071,10 @@ var D1MaterializedViewStore = class {
12799
13071
  ).bind(operation2, `${operation2}:%`));
12800
13072
  try {
12801
13073
  await this.database.batch(statements);
12802
- } catch (error10) {
12803
- if (isPatchFailure(error10)) throw new MaterializedViewPatchError();
12804
- if (isCasFailure(error10)) throw new MaterializedViewCasError();
12805
- throw new MaterializedViewStoreError("apply", "MV_STORE_OPERATION_FAILED", `Materialized-view atomic apply failed: ${String(error10)}`, { cause: error10 });
13074
+ } catch (error11) {
13075
+ if (isPatchFailure(error11)) throw new MaterializedViewPatchError();
13076
+ if (isCasFailure(error11)) throw new MaterializedViewCasError();
13077
+ throw new MaterializedViewStoreError("apply", "MV_STORE_OPERATION_FAILED", `Materialized-view atomic apply failed: ${String(error11)}`, { cause: error11 });
12806
13078
  }
12807
13079
  const instance = await this.readInstance(input.serviceId, input.viewId, input.generation);
12808
13080
  if (instance === void 0) throw new MaterializedViewStoreError("apply", "MV_INSTANCE_MISSING", "Materialized-view instance disappeared after apply");
@@ -12907,13 +13179,13 @@ var D1MaterializedViewStore = class {
12907
13179
  ];
12908
13180
  try {
12909
13181
  await this.database.batch(statements);
12910
- } catch (error10) {
12911
- if (isCasFailure(error10)) throw new MaterializedViewPromotionCasError();
12912
- throw new MaterializedViewStoreError("promote", "MV_STORE_OPERATION_FAILED", `Materialized-view promotion failed: ${String(error10)}`, { cause: error10 });
13182
+ } catch (error11) {
13183
+ if (isCasFailure(error11)) throw new MaterializedViewPromotionCasError();
13184
+ throw new MaterializedViewStoreError("promote", "MV_STORE_OPERATION_FAILED", `Materialized-view promotion failed: ${String(error11)}`, { cause: error11 });
12913
13185
  }
12914
- const active = await this.readActive(input.serviceId, input.viewId);
12915
- if (active === void 0) throw new MaterializedViewStoreError("promote", "MV_INSTANCE_MISSING", "Active generation disappeared after promotion");
12916
- return active;
13186
+ const active2 = await this.readActive(input.serviceId, input.viewId);
13187
+ if (active2 === void 0) throw new MaterializedViewStoreError("promote", "MV_INSTANCE_MISSING", "Active generation disappeared after promotion");
13188
+ return active2;
12917
13189
  }
12918
13190
  /** Short aliases make the port convenient for runtime composition and tests. */
12919
13191
  apply = this.applyMutationsAndAdvanceCheckpoint.bind(this);
@@ -12922,8 +13194,8 @@ var D1MaterializedViewStore = class {
12922
13194
  let value;
12923
13195
  try {
12924
13196
  value = assertJsonValue(JSON.parse(asString4(row.value_json, "value_json")), "state-persistence");
12925
- } catch (error10) {
12926
- throw new MaterializedViewStoreError("initialize", "MV_VALUE_INVALID", `Materialized-view row JSON was invalid: ${String(error10)}`, { cause: error10 });
13197
+ } catch (error11) {
13198
+ throw new MaterializedViewStoreError("initialize", "MV_VALUE_INVALID", `Materialized-view row JSON was invalid: ${String(error11)}`, { cause: error11 });
12927
13199
  }
12928
13200
  return {
12929
13201
  serviceId: asString4(row.service_id, "service_id"),
@@ -13047,8 +13319,8 @@ function stateFromCheckpoint(projector, checkpoint) {
13047
13319
  if (checkpoint === void 0) return projector.initialState();
13048
13320
  try {
13049
13321
  return projector.deserializeState(checkpoint.stateJson);
13050
- } catch (error10) {
13051
- throw new ProjectionCheckpointCorruption(error10);
13322
+ } catch (error11) {
13323
+ throw new ProjectionCheckpointCorruption(error11);
13052
13324
  }
13053
13325
  }
13054
13326
  function projectionEventFromStored(event) {
@@ -13279,8 +13551,8 @@ async function admitBootstrapRoute2(env, serviceId) {
13279
13551
  })).fetch(new Request(url, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ route: "projection-rebuild" }) }));
13280
13552
  if (!admitted.ok) throw new Error("bootstrap_route_rejected:projection-rebuild");
13281
13553
  }
13282
- function boundedErrorReason(error10) {
13283
- const value = error10 instanceof Error ? error10.message : String(error10);
13554
+ function boundedErrorReason(error11) {
13555
+ const value = error11 instanceof Error ? error11.message : String(error11);
13284
13556
  return value.length > 256 ? `${value.slice(0, 253)}...` : value;
13285
13557
  }
13286
13558
  async function notifyObserver(observer, callback, input) {
@@ -13293,7 +13565,7 @@ async function notifyObserver(observer, callback, input) {
13293
13565
  } catch {
13294
13566
  }
13295
13567
  }
13296
- async function notifyOutcomes(observer, serviceId, projectorIds, attemptedAt, results, maximumSuid, env, error10) {
13568
+ async function notifyOutcomes(observer, serviceId, projectorIds, attemptedAt, results, maximumSuid, env, error11) {
13297
13569
  if (observer?.onOutcome === void 0) return;
13298
13570
  const byProjector = /* @__PURE__ */ new Map();
13299
13571
  for (const result2 of results) {
@@ -13306,9 +13578,9 @@ async function notifyOutcomes(observer, serviceId, projectorIds, attemptedAt, re
13306
13578
  let outcome = "invoked-but-no-work";
13307
13579
  let reason = null;
13308
13580
  let advancedSourceEvents = 0;
13309
- if (error10 !== void 0) {
13581
+ if (error11 !== void 0) {
13310
13582
  outcome = "invoked-and-threw";
13311
- reason = boundedErrorReason(error10);
13583
+ reason = boundedErrorReason(error11);
13312
13584
  } else {
13313
13585
  advancedSourceEvents = projectorResults.reduce((total, result2) => total + result2.advancedSourceEvents, 0);
13314
13586
  if (advancedSourceEvents > 0) {
@@ -13410,9 +13682,9 @@ async function pollLiveProjections(env, options = {}) {
13410
13682
  const results = await runtime.pollRegistered(serviceId, attemptedAt, options.maximumSuid);
13411
13683
  await notifyOutcomes(options.observer, serviceId, projectorIds, attemptedAt, results, options.maximumSuid, env);
13412
13684
  return results;
13413
- } catch (error10) {
13414
- await notifyOutcomes(options.observer, serviceId, projectorIds, attemptedAt, [], options.maximumSuid, env, error10);
13415
- throw error10;
13685
+ } catch (error11) {
13686
+ await notifyOutcomes(options.observer, serviceId, projectorIds, attemptedAt, [], options.maximumSuid, env, error11);
13687
+ throw error11;
13416
13688
  }
13417
13689
  }
13418
13690
  async function handleProjectionLag(request, env, registry = DEPLOYED_PROJECTOR_REGISTRY, storeProvider, serviceIdentityProvider) {
@@ -13664,6 +13936,33 @@ function parseRequest(value) {
13664
13936
  }
13665
13937
  };
13666
13938
  }
13939
+ var QUERY_PARAMS_UNSUPPORTED_MESSAGE = "The selected query does not support these parameters.";
13940
+ var LIST_QUERY_PARAM_KEYS = /* @__PURE__ */ new Set(["PageNumber", "PageSize", "NewestFirst", "consistency"]);
13941
+ function unsupportedQueryParams(endpoint, queryParams) {
13942
+ if (endpoint === "query") {
13943
+ if (isObject9(queryParams) && Object.keys(queryParams).length === 0) {
13944
+ return void 0;
13945
+ }
13946
+ return {
13947
+ status: 400,
13948
+ code: "query_params_unsupported",
13949
+ error: QUERY_PARAMS_UNSUPPORTED_MESSAGE
13950
+ };
13951
+ }
13952
+ if (!isObject9(queryParams)) {
13953
+ return void 0;
13954
+ }
13955
+ for (const key of Object.keys(queryParams)) {
13956
+ if (!LIST_QUERY_PARAM_KEYS.has(key)) {
13957
+ return {
13958
+ status: 400,
13959
+ code: "query_params_unsupported",
13960
+ error: QUERY_PARAMS_UNSUPPORTED_MESSAGE
13961
+ };
13962
+ }
13963
+ }
13964
+ return void 0;
13965
+ }
13667
13966
  function paginationFrom(value) {
13668
13967
  if (!isObject9(value)) {
13669
13968
  return { error: "list-query queryParamsJson must contain an object" };
@@ -13844,6 +14143,10 @@ async function handleSerializedQuery(request, env, options = {}) {
13844
14143
  if (definition === void 0 || definition.endpoint !== endpoint) {
13845
14144
  return error6(400, "validation_error", "queryType is not mapped for this endpoint");
13846
14145
  }
14146
+ const unsupported = unsupportedQueryParams(endpoint, parsed.value.queryParams);
14147
+ if (unsupported !== void 0) {
14148
+ return error6(unsupported.status, unsupported.code, unsupported.error);
14149
+ }
13847
14150
  if (!definition.enabled || (options.projectors ?? DEPLOYED_PROJECTOR_REGISTRY).resolve(definition.tagProjector) === void 0) {
13848
14151
  return error6(503, "projection_unavailable", "The mapped query projection is unavailable");
13849
14152
  }
@@ -14230,10 +14533,10 @@ var SerializedReadWorker = class {
14230
14533
  });
14231
14534
  }
14232
14535
  async ensureWindowDeterminate() {
14233
- if (this.storeProvider === void 0 || this.storeProvider.isConfigured?.(this.env) === false) {
14234
- return;
14235
- }
14236
14536
  try {
14537
+ if (this.storeProvider === void 0 || this.storeProvider.isConfigured?.(this.env) === false) {
14538
+ return;
14539
+ }
14237
14540
  const store = this.storeProvider.create(this.env);
14238
14541
  await store.initialize();
14239
14542
  const nowMs = Date.now();
@@ -14274,13 +14577,662 @@ async function handleSerializedRead(request, env, registry = DEPLOYED_PROJECTOR_
14274
14577
  }), registry, storeProvider).handle(request);
14275
14578
  }
14276
14579
 
14580
+ // src/completeness/IncidentLifecycle.ts
14581
+ var MAX_IDENTITY_BYTES = 256;
14582
+ var MAX_LONG_TEXT_BYTES = 2048;
14583
+ var SHA256_DIGEST = /^sha256:[0-9a-f]{64}$/;
14584
+ var IncidentLifecycleError = class extends Error {
14585
+ code;
14586
+ status;
14587
+ constructor(code, status, message) {
14588
+ super(message);
14589
+ this.name = "IncidentLifecycleError";
14590
+ this.code = code;
14591
+ this.status = status;
14592
+ }
14593
+ };
14594
+ function isObject11(value) {
14595
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14596
+ }
14597
+ function hasOnlyKeys(value, keys) {
14598
+ const allowed = new Set(keys);
14599
+ return Object.keys(value).every((key) => allowed.has(key));
14600
+ }
14601
+ function bytes(value) {
14602
+ return new TextEncoder().encode(value).byteLength;
14603
+ }
14604
+ function boundedString(value, name, maximum, required = true) {
14605
+ if (typeof value !== "string") {
14606
+ throw new IncidentLifecycleError("incident_invalid_request", 400, `${name} must be a string`);
14607
+ }
14608
+ const normalized = value.trim();
14609
+ if (required && normalized.length === 0) {
14610
+ throw new IncidentLifecycleError("incident_invalid_request", 400, `${name} must be non-empty`);
14611
+ }
14612
+ if (bytes(normalized) > maximum) {
14613
+ throw new IncidentLifecycleError("incident_invalid_request", 400, `${name} is too long`);
14614
+ }
14615
+ return normalized.length === 0 ? null : normalized;
14616
+ }
14617
+ function normalizeIncidentIdentity(value) {
14618
+ const identity2 = boundedString(value, "incidentIdentity", MAX_IDENTITY_BYTES);
14619
+ if (identity2 === null) {
14620
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "incidentIdentity must be non-empty");
14621
+ }
14622
+ return identity2;
14623
+ }
14624
+ function safeInteger(value, name) {
14625
+ if (typeof value !== "number" || !Number.isSafeInteger(value)) {
14626
+ throw new IncidentLifecycleError("incident_invalid_request", 400, `${name} must be a safe integer`);
14627
+ }
14628
+ return value;
14629
+ }
14630
+ function normalizeCorrection(value) {
14631
+ if (!isObject11(value) || !hasOnlyKeys(value, ["kind", "reference", "digest"])) {
14632
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "correction has unknown or missing keys");
14633
+ }
14634
+ if (value.kind !== "event" && value.kind !== "receipt") {
14635
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "correction.kind must be event or receipt");
14636
+ }
14637
+ const reference = boundedString(value.reference, "correction.reference", MAX_LONG_TEXT_BYTES);
14638
+ const digest = boundedString(value.digest, "correction.digest", MAX_IDENTITY_BYTES);
14639
+ if (reference === null || digest === null || !SHA256_DIGEST.test(digest)) {
14640
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "correction.digest must be lowercase sha256");
14641
+ }
14642
+ return { kind: value.kind, reference, digest };
14643
+ }
14644
+ function normalizeRequest(value) {
14645
+ if (!isObject11(value) || !hasOnlyKeys(value, ["action", "incidentIdentity", "transitionKey", "expectedVersion", "reason", "ownerId", "deadlineAt", "correction", "resolution"])) {
14646
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "transition has unknown keys");
14647
+ }
14648
+ const action = value.action;
14649
+ if (typeof action !== "string" || !["ACKNOWLEDGE", "UPDATE_ASSIGNMENT", "RECORD_CORRECTION", "CLOSE", "REOPEN"].includes(action)) {
14650
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "transition action is invalid");
14651
+ }
14652
+ const actionKeys = action === "RECORD_CORRECTION" ? ["action", "incidentIdentity", "transitionKey", "expectedVersion", "reason", "correction"] : action === "CLOSE" ? ["action", "incidentIdentity", "transitionKey", "expectedVersion", "reason", "resolution"] : ["action", "incidentIdentity", "transitionKey", "expectedVersion", "reason", "ownerId", "deadlineAt"];
14653
+ if (!hasOnlyKeys(value, actionKeys)) {
14654
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "transition has keys not valid for its action");
14655
+ }
14656
+ const base = {
14657
+ incidentIdentity: normalizeIncidentIdentity(value.incidentIdentity),
14658
+ transitionKey: boundedString(value.transitionKey, "transitionKey", MAX_IDENTITY_BYTES),
14659
+ expectedVersion: safeInteger(value.expectedVersion, "expectedVersion"),
14660
+ reason: boundedString(value.reason, "reason", MAX_LONG_TEXT_BYTES)
14661
+ };
14662
+ if (base.expectedVersion < 0) {
14663
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "expectedVersion must not be negative");
14664
+ }
14665
+ if (action === "ACKNOWLEDGE" || action === "UPDATE_ASSIGNMENT" || action === "REOPEN") {
14666
+ const ownerId = boundedString(value.ownerId, "ownerId", MAX_IDENTITY_BYTES);
14667
+ const deadlineAt = safeInteger(value.deadlineAt, "deadlineAt");
14668
+ if (ownerId === null) throw new IncidentLifecycleError("incident_invalid_request", 400, "ownerId must be non-empty");
14669
+ return { ...base, action, ownerId, deadlineAt };
14670
+ }
14671
+ if (action === "RECORD_CORRECTION") {
14672
+ return { ...base, action, correction: normalizeCorrection(value.correction) };
14673
+ }
14674
+ if (!isObject11(value.resolution) || !hasOnlyKeys(value.resolution, ["kind", "explanation"])) {
14675
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "resolution has unknown or missing keys");
14676
+ }
14677
+ if (value.resolution.kind === "CORRECTED") {
14678
+ if (value.resolution.explanation !== void 0) {
14679
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "CORRECTED resolution has unknown keys");
14680
+ }
14681
+ return { ...base, action, resolution: { kind: "CORRECTED" } };
14682
+ }
14683
+ if (value.resolution.kind === "ACCEPTED_AS_IS") {
14684
+ const explanation = boundedString(value.resolution.explanation, "resolution.explanation", MAX_LONG_TEXT_BYTES);
14685
+ if (explanation === null) throw new IncidentLifecycleError("incident_invalid_request", 400, "resolution.explanation is required");
14686
+ return { ...base, action, resolution: { kind: "ACCEPTED_AS_IS", explanation } };
14687
+ }
14688
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "resolution.kind is invalid");
14689
+ }
14690
+ function canonicalize(value) {
14691
+ if (Array.isArray(value)) return value.map(canonicalize);
14692
+ if (!isObject11(value)) return value;
14693
+ return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalize(value[key])]));
14694
+ }
14695
+ async function digestFor(request, actorId) {
14696
+ const envelope = canonicalize({ action: request, actor: actorId });
14697
+ const encoded = new TextEncoder().encode(JSON.stringify(envelope));
14698
+ const digest = await crypto.subtle.digest("SHA-256", encoded);
14699
+ return `sha256:${Array.from(new Uint8Array(digest), (byte) => byte.toString(16).padStart(2, "0")).join("")}`;
14700
+ }
14701
+ function projectionFromRow(row, finding2) {
14702
+ if (row === null) {
14703
+ return {
14704
+ serviceId: finding2.service_id,
14705
+ incidentIdentity: finding2.incident_identity,
14706
+ lifecycleState: "OPEN",
14707
+ ownerId: null,
14708
+ deadlineAt: null,
14709
+ correction: null,
14710
+ closeResolution: null,
14711
+ closeReason: null,
14712
+ version: 0,
14713
+ lastTransitionKey: "",
14714
+ updatedAt: finding2.last_observed_at
14715
+ };
14716
+ }
14717
+ return {
14718
+ serviceId: row.service_id,
14719
+ incidentIdentity: row.incident_identity,
14720
+ lifecycleState: row.lifecycle_state,
14721
+ ownerId: row.owner_id,
14722
+ deadlineAt: row.deadline_at,
14723
+ correction: row.correction_kind === null ? null : {
14724
+ kind: row.correction_kind,
14725
+ reference: row.correction_reference,
14726
+ digest: row.correction_digest
14727
+ },
14728
+ closeResolution: row.close_resolution,
14729
+ closeReason: row.close_reason,
14730
+ version: row.version,
14731
+ lastTransitionKey: row.last_transition_key,
14732
+ updatedAt: row.updated_at
14733
+ };
14734
+ }
14735
+ function findingFromRow(row) {
14736
+ return {
14737
+ serviceId: row.service_id,
14738
+ incidentIdentity: row.incident_identity,
14739
+ incidentType: row.incident_type,
14740
+ partitionTag: row.partition_tag,
14741
+ obligationSequence: row.obligation_sequence,
14742
+ eventId: row.event_id,
14743
+ eventDigest: row.event_digest,
14744
+ state: row.finding_state,
14745
+ firstObservedAt: row.first_observed_at,
14746
+ lastObservedAt: row.last_observed_at
14747
+ };
14748
+ }
14749
+ function transitionFromRow(row) {
14750
+ const before = projectionFromAudit(row, "before");
14751
+ const after = projectionFromAudit(row, "after");
14752
+ return {
14753
+ transitionId: row.transition_id,
14754
+ serviceId: row.service_id,
14755
+ incidentIdentity: row.incident_identity,
14756
+ transitionKey: row.transition_key,
14757
+ requestDigest: row.request_digest,
14758
+ action: row.action,
14759
+ fromState: row.from_state,
14760
+ toState: row.to_state,
14761
+ fromVersion: row.from_version,
14762
+ toVersion: row.to_version,
14763
+ actorId: row.actor_id,
14764
+ before,
14765
+ after,
14766
+ reason: row.reason,
14767
+ occurredAt: row.occurred_at
14768
+ };
14769
+ }
14770
+ function projectionFromAudit(row, prefix) {
14771
+ const state = prefix === "before" ? row.from_state : row.to_state;
14772
+ const version = prefix === "before" ? row.from_version : row.to_version;
14773
+ const ownerId = row[`${prefix}_owner_id`];
14774
+ const correctionKind = row[`${prefix}_correction_kind`];
14775
+ return {
14776
+ serviceId: row.service_id,
14777
+ incidentIdentity: row.incident_identity,
14778
+ lifecycleState: state,
14779
+ ownerId,
14780
+ deadlineAt: row[`${prefix}_deadline_at`],
14781
+ correction: correctionKind === null ? null : {
14782
+ kind: correctionKind,
14783
+ reference: row[`${prefix}_correction_reference`],
14784
+ digest: row[`${prefix}_correction_digest`]
14785
+ },
14786
+ closeResolution: row[`${prefix}_close_resolution`],
14787
+ closeReason: row[`${prefix}_close_reason`],
14788
+ version,
14789
+ lastTransitionKey: prefix === "after" ? row.transition_key : "",
14790
+ updatedAt: row.occurred_at
14791
+ };
14792
+ }
14793
+ function active(state) {
14794
+ return state !== "CLOSED";
14795
+ }
14796
+ function compareItems(left, right) {
14797
+ if (left.overdue !== right.overdue) return left.overdue ? -1 : 1;
14798
+ if (left.unowned !== right.unowned) return left.unowned ? -1 : 1;
14799
+ if (left.finding.lastObservedAt !== right.finding.lastObservedAt) return right.finding.lastObservedAt - left.finding.lastObservedAt;
14800
+ return left.finding.incidentIdentity < right.finding.incidentIdentity ? -1 : left.finding.incidentIdentity > right.finding.incidentIdentity ? 1 : 0;
14801
+ }
14802
+ var IncidentLifecycle = class {
14803
+ constructor(database, now2 = () => Date.now()) {
14804
+ this.database = database;
14805
+ this.now = now2;
14806
+ }
14807
+ database;
14808
+ now;
14809
+ static parseTransition(value) {
14810
+ return normalizeRequest(value);
14811
+ }
14812
+ async finding(serviceId, incidentIdentity) {
14813
+ const row = await this.database.prepare(
14814
+ `SELECT service_id, incident_identity, incident_type, partition_tag,
14815
+ obligation_sequence, event_id, event_digest, state AS finding_state,
14816
+ first_observed_at, last_observed_at
14817
+ FROM serialized_dcb_completeness_findings
14818
+ WHERE service_id = ? AND incident_identity = ?`
14819
+ ).bind(serviceId, incidentIdentity).first();
14820
+ if (row === null || row === void 0) {
14821
+ throw new IncidentLifecycleError("incident_not_found", 404, "The completeness incident was not found");
14822
+ }
14823
+ return row;
14824
+ }
14825
+ async lifecycle(serviceId, incidentIdentity) {
14826
+ const row = await this.database.prepare(
14827
+ `SELECT service_id, incident_identity, lifecycle_state, owner_id, deadline_at,
14828
+ correction_kind, correction_reference, correction_digest,
14829
+ close_resolution, close_reason, version, last_transition_key, updated_at
14830
+ FROM serialized_dcb_incident_lifecycles
14831
+ WHERE service_id = ? AND incident_identity = ?`
14832
+ ).bind(serviceId, incidentIdentity).first();
14833
+ return row === void 0 ? null : row;
14834
+ }
14835
+ async transitions(serviceId, incidentIdentity) {
14836
+ const result2 = await this.database.prepare(
14837
+ `SELECT * FROM serialized_dcb_incident_transitions
14838
+ WHERE service_id = ? AND incident_identity = ?
14839
+ ORDER BY transition_id ASC`
14840
+ ).bind(serviceId, incidentIdentity).all();
14841
+ return result2.results.map(transitionFromRow);
14842
+ }
14843
+ async closeTime(serviceId, incidentIdentity) {
14844
+ const row = await this.database.prepare(
14845
+ `SELECT occurred_at FROM serialized_dcb_incident_transitions
14846
+ WHERE service_id = ? AND incident_identity = ? AND to_state = 'CLOSED'
14847
+ ORDER BY transition_id DESC LIMIT 1`
14848
+ ).bind(serviceId, incidentIdentity).first();
14849
+ return row?.occurred_at ?? null;
14850
+ }
14851
+ async item(finding2, row, at) {
14852
+ const lifecycle = projectionFromRow(row, finding2);
14853
+ const closeTime = lifecycle.lifecycleState === "OPEN" && row === null ? null : await this.closeTime(finding2.service_id, finding2.incident_identity);
14854
+ const observedAfterClose = closeTime !== null && finding2.last_observed_at > closeTime;
14855
+ const overdue = active(lifecycle.lifecycleState) && lifecycle.deadlineAt !== null && lifecycle.deadlineAt < at;
14856
+ return {
14857
+ finding: findingFromRow(finding2),
14858
+ lifecycle,
14859
+ overdue,
14860
+ unowned: lifecycle.ownerId === null,
14861
+ observedAfterClose
14862
+ };
14863
+ }
14864
+ async list(serviceId, filters = {}, at = this.now()) {
14865
+ const rows = await this.database.prepare(
14866
+ `SELECT service_id, incident_identity, incident_type, partition_tag,
14867
+ obligation_sequence, event_id, event_digest, state AS finding_state,
14868
+ first_observed_at, last_observed_at
14869
+ FROM serialized_dcb_completeness_findings
14870
+ WHERE service_id = ?`
14871
+ ).bind(serviceId).all();
14872
+ const items = [];
14873
+ for (const finding2 of rows.results) {
14874
+ const item = await this.item(finding2, await this.lifecycle(serviceId, finding2.incident_identity), at);
14875
+ if (filters.state !== void 0 && item.lifecycle.lifecycleState !== filters.state) continue;
14876
+ if (filters.owner !== void 0 && item.lifecycle.ownerId !== filters.owner) continue;
14877
+ if (filters.unowned === true && !item.unowned) continue;
14878
+ if (filters.overdue === true && !item.overdue) continue;
14879
+ if (filters.observedAfterClose === true && !item.observedAfterClose) continue;
14880
+ items.push(item);
14881
+ }
14882
+ items.sort(compareItems);
14883
+ const byState = {
14884
+ OPEN: 0,
14885
+ ACKNOWLEDGED: 0,
14886
+ CORRECTION_RECORDED: 0,
14887
+ CLOSED: 0,
14888
+ REOPENED: 0
14889
+ };
14890
+ for (const item of items) byState[item.lifecycle.lifecycleState] += 1;
14891
+ return {
14892
+ items,
14893
+ summary: {
14894
+ total: items.length,
14895
+ byState,
14896
+ unowned: items.filter((item) => item.unowned).length,
14897
+ overdue: items.filter((item) => item.overdue).length,
14898
+ observedAfterClose: items.filter((item) => item.observedAfterClose).length
14899
+ }
14900
+ };
14901
+ }
14902
+ async detail(serviceId, incidentIdentity, at = this.now()) {
14903
+ const finding2 = await this.finding(serviceId, incidentIdentity);
14904
+ const lifecycle = await this.lifecycle(serviceId, incidentIdentity);
14905
+ const item = await this.item(finding2, lifecycle, at);
14906
+ return {
14907
+ finding: item.finding,
14908
+ lifecycle: item.lifecycle,
14909
+ flags: { overdue: item.overdue, unowned: item.unowned, observedAfterClose: item.observedAfterClose },
14910
+ transitions: await this.transitions(serviceId, incidentIdentity)
14911
+ };
14912
+ }
14913
+ async transition(serviceId, value, actor) {
14914
+ const request = normalizeRequest(value);
14915
+ let actorId;
14916
+ try {
14917
+ actorId = boundedString(actor, "x-sdt-maintainer", MAX_IDENTITY_BYTES);
14918
+ } catch (caught) {
14919
+ if (caught instanceof IncidentLifecycleError && caught.code === "incident_invalid_request") {
14920
+ throw new IncidentLifecycleError("incident_invalid_actor", 400, caught.message);
14921
+ }
14922
+ throw caught;
14923
+ }
14924
+ if (actorId === null) throw new IncidentLifecycleError("incident_invalid_actor", 400, "x-sdt-maintainer must be non-empty");
14925
+ const finding2 = await this.finding(serviceId, request.incidentIdentity);
14926
+ const digest = await digestFor(request, actorId);
14927
+ const existing = await this.database.prepare(
14928
+ `SELECT * FROM serialized_dcb_incident_transitions
14929
+ WHERE service_id = ? AND incident_identity = ? AND transition_key = ?`
14930
+ ).bind(serviceId, request.incidentIdentity, request.transitionKey).first();
14931
+ if (existing !== null && existing !== void 0) {
14932
+ if (existing.request_digest !== digest) {
14933
+ throw new IncidentLifecycleError("incident_idempotency_conflict", 409, "The transition key was already used with different content");
14934
+ }
14935
+ return { projection: transitionFromRow(existing).after, transition: transitionFromRow(existing), idempotent: true };
14936
+ }
14937
+ const priorRow = await this.lifecycle(serviceId, request.incidentIdentity);
14938
+ const before = projectionFromRow(priorRow, finding2);
14939
+ if (before.version !== request.expectedVersion) {
14940
+ throw new IncidentLifecycleError("incident_version_conflict", 409, "The incident version is stale");
14941
+ }
14942
+ const at = this.now();
14943
+ const after = this.nextProjection(before, request, at);
14944
+ const newVersion = before.version + 1;
14945
+ const occurredAt = at;
14946
+ const seed = this.database.prepare(
14947
+ `INSERT INTO serialized_dcb_incident_lifecycles
14948
+ (service_id, incident_identity, lifecycle_state, version, last_transition_key, updated_at)
14949
+ VALUES (?, ?, 'OPEN', 0, '', ?)
14950
+ ON CONFLICT (service_id, incident_identity) DO NOTHING`
14951
+ ).bind(serviceId, request.incidentIdentity, occurredAt);
14952
+ const update = this.database.prepare(
14953
+ `UPDATE serialized_dcb_incident_lifecycles
14954
+ SET lifecycle_state = ?, owner_id = ?, deadline_at = ?,
14955
+ correction_kind = ?, correction_reference = ?, correction_digest = ?,
14956
+ close_resolution = ?, close_reason = ?, version = ?,
14957
+ last_transition_key = ?, updated_at = ?
14958
+ WHERE service_id = ? AND incident_identity = ? AND version = ?
14959
+ AND last_transition_key <> ?`
14960
+ ).bind(
14961
+ after.lifecycleState,
14962
+ after.ownerId,
14963
+ after.deadlineAt,
14964
+ after.correction?.kind ?? null,
14965
+ after.correction?.reference ?? null,
14966
+ after.correction?.digest ?? null,
14967
+ after.closeResolution,
14968
+ after.closeReason,
14969
+ newVersion,
14970
+ request.transitionKey,
14971
+ occurredAt,
14972
+ serviceId,
14973
+ request.incidentIdentity,
14974
+ before.version,
14975
+ request.transitionKey
14976
+ );
14977
+ const audit = this.database.prepare(
14978
+ `INSERT INTO serialized_dcb_incident_transitions
14979
+ (service_id, incident_identity, transition_key, request_digest, action,
14980
+ from_state, to_state, from_version, to_version, actor_id,
14981
+ before_owner_id, before_deadline_at, before_correction_kind,
14982
+ before_correction_reference, before_correction_digest, before_close_resolution,
14983
+ before_close_reason, after_owner_id, after_deadline_at, after_correction_kind,
14984
+ after_correction_reference, after_correction_digest, after_close_resolution,
14985
+ after_close_reason, reason, occurred_at)
14986
+ SELECT ?, ?, ?, ?, ?, ?, lifecycle_state, ?, version, ?,
14987
+ ?, ?, ?, ?, ?, ?, ?, owner_id, deadline_at, correction_kind,
14988
+ correction_reference, correction_digest, close_resolution, close_reason, ?, ?
14989
+ FROM serialized_dcb_incident_lifecycles
14990
+ WHERE service_id = ? AND incident_identity = ? AND version = ? AND last_transition_key = ?`
14991
+ ).bind(
14992
+ serviceId,
14993
+ request.incidentIdentity,
14994
+ request.transitionKey,
14995
+ digest,
14996
+ request.action,
14997
+ before.lifecycleState,
14998
+ before.version,
14999
+ actorId,
15000
+ before.ownerId,
15001
+ before.deadlineAt,
15002
+ before.correction?.kind ?? null,
15003
+ before.correction?.reference ?? null,
15004
+ before.correction?.digest ?? null,
15005
+ before.closeResolution,
15006
+ before.closeReason,
15007
+ request.reason,
15008
+ occurredAt,
15009
+ serviceId,
15010
+ request.incidentIdentity,
15011
+ newVersion,
15012
+ request.transitionKey
15013
+ );
15014
+ await this.database.batch([seed, update, audit]);
15015
+ const inserted = await this.database.prepare(
15016
+ `SELECT * FROM serialized_dcb_incident_transitions
15017
+ WHERE service_id = ? AND incident_identity = ? AND transition_key = ?`
15018
+ ).bind(serviceId, request.incidentIdentity, request.transitionKey).first();
15019
+ if (inserted === null || inserted === void 0) {
15020
+ const competing = await this.database.prepare(
15021
+ `SELECT * FROM serialized_dcb_incident_transitions
15022
+ WHERE service_id = ? AND incident_identity = ? AND transition_key = ?`
15023
+ ).bind(serviceId, request.incidentIdentity, request.transitionKey).first();
15024
+ if (competing !== null && competing !== void 0 && competing.request_digest !== digest) {
15025
+ throw new IncidentLifecycleError("incident_idempotency_conflict", 409, "The transition key was already used with different content");
15026
+ }
15027
+ if (competing !== null && competing !== void 0) {
15028
+ const transition2 = transitionFromRow(competing);
15029
+ return { projection: transition2.after, transition: transition2, idempotent: true };
15030
+ }
15031
+ throw new IncidentLifecycleError("incident_version_conflict", 409, "The incident version is stale");
15032
+ }
15033
+ const transition = transitionFromRow(inserted);
15034
+ return { projection: transition.after, transition, idempotent: false };
15035
+ }
15036
+ nextProjection(before, request, at) {
15037
+ const laterDeadline = (deadlineAt2) => {
15038
+ if (deadlineAt2 <= at) throw new IncidentLifecycleError("incident_invalid_deadline", 400, "deadlineAt must be in the future");
15039
+ return deadlineAt2;
15040
+ };
15041
+ let lifecycleState;
15042
+ let ownerId = before.ownerId;
15043
+ let deadlineAt = before.deadlineAt;
15044
+ let correction = before.correction;
15045
+ let closeResolution = before.closeResolution;
15046
+ let closeReason = before.closeReason;
15047
+ if (request.action === "ACKNOWLEDGE") {
15048
+ if (before.lifecycleState !== "OPEN" && before.lifecycleState !== "REOPENED") {
15049
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "The incident cannot be acknowledged from its current state");
15050
+ }
15051
+ lifecycleState = "ACKNOWLEDGED";
15052
+ ownerId = request.ownerId;
15053
+ deadlineAt = laterDeadline(request.deadlineAt);
15054
+ correction = null;
15055
+ closeResolution = null;
15056
+ closeReason = null;
15057
+ } else if (request.action === "UPDATE_ASSIGNMENT") {
15058
+ if (before.lifecycleState !== "ACKNOWLEDGED" && before.lifecycleState !== "CORRECTION_RECORDED") {
15059
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "The incident cannot be reassigned from its current state");
15060
+ }
15061
+ lifecycleState = before.lifecycleState;
15062
+ ownerId = request.ownerId;
15063
+ deadlineAt = laterDeadline(request.deadlineAt);
15064
+ } else if (request.action === "RECORD_CORRECTION") {
15065
+ if (before.lifecycleState !== "ACKNOWLEDGED") {
15066
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "The incident must be acknowledged before correction evidence");
15067
+ }
15068
+ lifecycleState = "CORRECTION_RECORDED";
15069
+ correction = request.correction;
15070
+ } else if (request.action === "CLOSE") {
15071
+ if (before.ownerId === null || before.deadlineAt === null) {
15072
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "The incident must have an owner and deadline before closure");
15073
+ }
15074
+ if (request.resolution.kind === "CORRECTED") {
15075
+ if (before.lifecycleState !== "CORRECTION_RECORDED") {
15076
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "A corrected closure requires recorded correction evidence");
15077
+ }
15078
+ lifecycleState = "CLOSED";
15079
+ closeResolution = "CORRECTED";
15080
+ closeReason = request.reason;
15081
+ } else {
15082
+ if (before.lifecycleState !== "ACKNOWLEDGED") {
15083
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "Accepted-as-is closure requires an acknowledged incident");
15084
+ }
15085
+ lifecycleState = "CLOSED";
15086
+ closeResolution = "ACCEPTED_AS_IS";
15087
+ closeReason = request.resolution.explanation;
15088
+ correction = null;
15089
+ }
15090
+ } else {
15091
+ if (before.lifecycleState !== "CLOSED") {
15092
+ throw new IncidentLifecycleError("incident_invalid_transition", 409, "Only a closed incident can be reopened");
15093
+ }
15094
+ lifecycleState = "REOPENED";
15095
+ ownerId = request.ownerId;
15096
+ deadlineAt = laterDeadline(request.deadlineAt);
15097
+ correction = null;
15098
+ closeResolution = null;
15099
+ closeReason = null;
15100
+ }
15101
+ return {
15102
+ ...before,
15103
+ lifecycleState,
15104
+ ownerId,
15105
+ deadlineAt,
15106
+ correction,
15107
+ closeResolution,
15108
+ closeReason,
15109
+ version: before.version + 1,
15110
+ lastTransitionKey: request.transitionKey,
15111
+ updatedAt: at
15112
+ };
15113
+ }
15114
+ };
15115
+
15116
+ // src/http/IncidentMaintenance.ts
15117
+ function json10(body, status = 200) {
15118
+ return new Response(JSON.stringify(body), {
15119
+ status,
15120
+ headers: { "content-type": "application/json; charset=utf-8" }
15121
+ });
15122
+ }
15123
+ function error8(status, code, message) {
15124
+ return json10({ error: message, code }, status);
15125
+ }
15126
+ function boolFilter(value, name) {
15127
+ if (value === null) return void 0;
15128
+ if (value === "true") return true;
15129
+ if (value === "false") return false;
15130
+ throw new IncidentLifecycleError("incident_invalid_filter", 400, `${name} must be true or false`);
15131
+ }
15132
+ function parseFilters(url) {
15133
+ const allowed = /* @__PURE__ */ new Set(["state", "owner", "unowned", "overdue", "observedAfterClose"]);
15134
+ let unknown = false;
15135
+ url.searchParams.forEach((_value, key) => {
15136
+ if (!allowed.has(key)) unknown = true;
15137
+ });
15138
+ if (unknown) throw new IncidentLifecycleError("incident_invalid_filter", 400, "Unknown incident list filter");
15139
+ const state = url.searchParams.get("state");
15140
+ if (state !== null && !["OPEN", "ACKNOWLEDGED", "CORRECTION_RECORDED", "CLOSED", "REOPENED"].includes(state)) {
15141
+ throw new IncidentLifecycleError("incident_invalid_filter", 400, "state is invalid");
15142
+ }
15143
+ const owner = url.searchParams.get("owner");
15144
+ if (owner !== null) {
15145
+ const normalizedOwner = owner.trim();
15146
+ if (normalizedOwner.length === 0) {
15147
+ throw new IncidentLifecycleError("incident_invalid_filter", 400, "owner must be non-empty");
15148
+ }
15149
+ if (new TextEncoder().encode(normalizedOwner).byteLength > 256) {
15150
+ throw new IncidentLifecycleError("incident_invalid_filter", 400, "owner is too long");
15151
+ }
15152
+ }
15153
+ const unowned = boolFilter(url.searchParams.get("unowned"), "unowned");
15154
+ const overdue = boolFilter(url.searchParams.get("overdue"), "overdue");
15155
+ const observedAfterClose = boolFilter(url.searchParams.get("observedAfterClose"), "observedAfterClose");
15156
+ return {
15157
+ ...state === null ? {} : { state },
15158
+ ...owner === null ? {} : { owner: owner.trim() },
15159
+ ...unowned === void 0 ? {} : { unowned },
15160
+ ...overdue === void 0 ? {} : { overdue },
15161
+ ...observedAfterClose === void 0 ? {} : { observedAfterClose }
15162
+ };
15163
+ }
15164
+ function incidentIdentityFromPath(pathname) {
15165
+ const encoded = pathname.slice("/maintenance/incidents/".length);
15166
+ if (encoded.length === 0 || encoded.includes("/")) {
15167
+ throw new IncidentLifecycleError("incident_route_not_found", 404, "Incident route not found");
15168
+ }
15169
+ try {
15170
+ return normalizeIncidentIdentity(decodeURIComponent(encoded));
15171
+ } catch {
15172
+ throw new IncidentLifecycleError("incident_invalid_request", 400, "Incident identity must be URI encoded");
15173
+ }
15174
+ }
15175
+ function isIncidentMaintenancePath(pathname) {
15176
+ return pathname === "/maintenance/incidents" || pathname.startsWith("/maintenance/incidents/");
15177
+ }
15178
+ async function handleIncidentMaintenance(request, env, serviceIdentityProvider) {
15179
+ const decision = await checkConfiguredBearer(request, env.INCIDENT_MAINTAINER_TOKEN, {
15180
+ tokenNormalization: "trim"
15181
+ });
15182
+ if (decision === "unconfigured") {
15183
+ return error8(503, "incident_maintenance_unavailable", "Incident maintenance is not configured");
15184
+ }
15185
+ if (decision === "missing" || decision === "invalid") {
15186
+ return error8(401, "incident_auth_required", "A valid incident maintenance bearer token is required");
15187
+ }
15188
+ let serviceId;
15189
+ try {
15190
+ serviceId = requestServiceIdentity(request, serviceIdentityProvider, {
15191
+ allowG11Verification: env.G11_VERIFICATION_ENABLED === "true"
15192
+ });
15193
+ } catch {
15194
+ return error8(503, "scope.identity_missing", "A deployment service identity is required for this scope");
15195
+ }
15196
+ if (env.D1 === void 0) {
15197
+ return error8(503, "incident_maintenance_unavailable", "Incident maintenance storage is unavailable");
15198
+ }
15199
+ const lifecycle = new IncidentLifecycle(env.D1);
15200
+ const url = new URL(request.url);
15201
+ try {
15202
+ if (request.method === "GET" && url.pathname === "/maintenance/incidents") {
15203
+ return json10(await lifecycle.list(serviceId, parseFilters(url)));
15204
+ }
15205
+ if (request.method === "GET" && url.pathname.startsWith("/maintenance/incidents/")) {
15206
+ return json10(await lifecycle.detail(serviceId, incidentIdentityFromPath(url.pathname)));
15207
+ }
15208
+ if (request.method === "POST" && url.pathname === "/maintenance/incidents/transitions") {
15209
+ let body;
15210
+ try {
15211
+ body = await request.json();
15212
+ } catch {
15213
+ return error8(400, "incident_invalid_request", "Transition request must be JSON");
15214
+ }
15215
+ const requestValue = IncidentLifecycle.parseTransition(body);
15216
+ const actor = request.headers.get("x-sdt-maintainer");
15217
+ if (actor === null) {
15218
+ return error8(400, "incident_invalid_actor", "x-sdt-maintainer is required");
15219
+ }
15220
+ return json10(await lifecycle.transition(serviceId, requestValue, actor));
15221
+ }
15222
+ return error8(404, "incident_route_not_found", "Incident maintenance route not found");
15223
+ } catch (caught) {
15224
+ if (caught instanceof IncidentLifecycleError) return error8(caught.status, caught.code, caught.message);
15225
+ return error8(500, "incident_maintenance_failed", "Incident maintenance could not complete the request");
15226
+ }
15227
+ }
15228
+
14277
15229
  // src/downstream/Doorbell.ts
14278
15230
  var MAX_SERVICE_BINDING_INVOCATIONS_PER_REQUEST = 32;
14279
- function classifyDirectDoorbellFailure(error10) {
14280
- const structured = typeof error10 === "object" && error10 !== null ? error10 : {};
15231
+ function classifyDirectDoorbellFailure(error11) {
15232
+ const structured = typeof error11 === "object" && error11 !== null ? error11 : {};
14281
15233
  const status = typeof structured.status === "number" ? structured.status : typeof structured.statusCode === "number" ? structured.statusCode : void 0;
14282
15234
  if (status !== void 0 && (status < 200 || status >= 300)) return "non-2xx";
14283
- const value = String(error10).toLowerCase();
15235
+ const value = String(error11).toLowerCase();
14284
15236
  const code = `${String(structured.code ?? "")} ${String(structured.name ?? "")}`.toLowerCase();
14285
15237
  if (value.includes("timeout") || value.includes("deadline") || code.includes("timeout")) return "timeout";
14286
15238
  if (value.includes("cancel") || value.includes("abort") || code.includes("abort")) return "cancel";
@@ -14523,6 +15475,7 @@ var TAG_SQL_SCHEMA_DDL = `
14523
15475
  committed_event_count INTEGER NOT NULL,
14524
15476
  head_suid TEXT NOT NULL,
14525
15477
  reservation_confirmed INTEGER NOT NULL CHECK (reservation_confirmed IN (0, 1)),
15478
+ written_version INTEGER NOT NULL,
14526
15479
  PRIMARY KEY (attempt_id, epoch)
14527
15480
  );
14528
15481
 
@@ -14573,6 +15526,12 @@ var TAG_READ_AFTER_THROUGH_SQL = `
14573
15526
  `;
14574
15527
  function initializeTagSqlSchema(sql) {
14575
15528
  sql.exec(TAG_SQL_SCHEMA_DDL);
15529
+ ensureTagCommitReceiptWrittenVersion(sql);
15530
+ }
15531
+ function ensureTagCommitReceiptWrittenVersion(sql) {
15532
+ const columns = sql.exec("SELECT name FROM pragma_table_info('tag_commit_receipt')").toArray();
15533
+ if (columns.some((column) => column.name === "written_version")) return;
15534
+ sql.exec("ALTER TABLE tag_commit_receipt ADD COLUMN written_version INTEGER");
14576
15535
  }
14577
15536
  function hasTagSqlStorage(storage) {
14578
15537
  return typeof storage.sql?.exec === "function";
@@ -14699,14 +15658,14 @@ var TagIdentityConflict = class extends Error {
14699
15658
  this.name = "TagIdentityConflict";
14700
15659
  }
14701
15660
  };
14702
- function json10(body, status = 200) {
15661
+ function json11(body, status = 200) {
14703
15662
  return new Response(JSON.stringify(body), {
14704
15663
  status,
14705
15664
  headers: { "content-type": "application/json; charset=utf-8" }
14706
15665
  });
14707
15666
  }
14708
- function error8(status, code, message, retryable = false) {
14709
- return json10(retryable ? { error: message, code, retryable: true } : { error: message, code }, status);
15667
+ function error9(status, code, message, retryable = false) {
15668
+ return json11(retryable ? { error: message, code, retryable: true } : { error: message, code }, status);
14710
15669
  }
14711
15670
  function withGlobalAdmission2(response3, status) {
14712
15671
  response3.headers.set(G65_GLOBAL_ADMISSION_HEADER, status);
@@ -14725,7 +15684,7 @@ function repairRejected(reason, status = 409) {
14725
15684
  body: { code: "repair_operation_rejected", error: reason, reason }
14726
15685
  };
14727
15686
  }
14728
- function isObject11(value) {
15687
+ function isObject12(value) {
14729
15688
  return typeof value === "object" && value !== null && !Array.isArray(value);
14730
15689
  }
14731
15690
  function isNonEmptyString11(value) {
@@ -14770,8 +15729,8 @@ function sqlJson(value, column) {
14770
15729
  throw new Error(`Tag SQL column ${column} is not valid JSON`);
14771
15730
  }
14772
15731
  }
14773
- function copyArrayBuffer(bytes) {
14774
- return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
15732
+ function copyArrayBuffer(bytes2) {
15733
+ return bytes2.buffer.slice(bytes2.byteOffset, bytes2.byteOffset + bytes2.byteLength);
14775
15734
  }
14776
15735
  function arrayBufferBase642(value) {
14777
15736
  let binary = "";
@@ -14782,7 +15741,7 @@ function nowIso() {
14782
15741
  return (/* @__PURE__ */ new Date()).toISOString();
14783
15742
  }
14784
15743
  function epochFrom(value) {
14785
- if (!isObject11(value) || !isNonEmptyString11(value.attemptId) || !isEpoch(value.epoch)) {
15744
+ if (!isObject12(value) || !isNonEmptyString11(value.attemptId) || !isEpoch(value.epoch)) {
14786
15745
  return { error: "attemptId and a non-negative safe-integer epoch are required" };
14787
15746
  }
14788
15747
  return { value: { attemptId: value.attemptId, epoch: value.epoch } };
@@ -14802,7 +15761,7 @@ function consistencyTagsFrom(value) {
14802
15761
  }
14803
15762
  const entries = [];
14804
15763
  for (const rawEntry of value) {
14805
- if (!isObject11(rawEntry) || !isNonEmptyString11(rawEntry.tag)) {
15764
+ if (!isObject12(rawEntry) || !isNonEmptyString11(rawEntry.tag)) {
14806
15765
  return { error: "each consistency tag needs a non-empty tag" };
14807
15766
  }
14808
15767
  if (!("lastSortableUniqueId" in rawEntry)) {
@@ -14830,7 +15789,7 @@ function consistencyTagsFrom(value) {
14830
15789
  }
14831
15790
  function acquireFrom(value, tag) {
14832
15791
  const epoch2 = epochFrom(value);
14833
- if (epoch2.value === void 0 || !isObject11(value)) {
15792
+ if (epoch2.value === void 0 || !isObject12(value)) {
14834
15793
  return { error: epoch2.error ?? "Invalid acquire request" };
14835
15794
  }
14836
15795
  const eventTags = stringArrayFrom(value.eventTags, "eventTags");
@@ -14853,7 +15812,7 @@ function acquireFrom(value, tag) {
14853
15812
  }
14854
15813
  function reservationFrom(value) {
14855
15814
  const epoch2 = epochFrom(value);
14856
- if (epoch2.value === void 0 || !isObject11(value)) {
15815
+ if (epoch2.value === void 0 || !isObject12(value)) {
14857
15816
  return { error: epoch2.error ?? "Invalid reservation request" };
14858
15817
  }
14859
15818
  if (value.reservationToken !== void 0 && !isNonEmptyString11(value.reservationToken)) {
@@ -14872,7 +15831,7 @@ function reservationFrom(value) {
14872
15831
  }
14873
15832
  function appendFrom(value, tag) {
14874
15833
  const reservation = reservationFrom(value);
14875
- if (reservation.value === void 0 || !isObject11(value) || !Array.isArray(value.candidates)) {
15834
+ if (reservation.value === void 0 || !isObject12(value) || !Array.isArray(value.candidates)) {
14876
15835
  return { error: reservation.error ?? "candidates must be an array" };
14877
15836
  }
14878
15837
  if (value.candidates.length === 0) {
@@ -14880,7 +15839,7 @@ function appendFrom(value, tag) {
14880
15839
  }
14881
15840
  const candidates = [];
14882
15841
  for (const rawCandidate of value.candidates) {
14883
- if (!isObject11(rawCandidate) || !isNonEmptyString11(rawCandidate.eventId) || !isNonEmptyString11(rawCandidate.suid) || typeof rawCandidate.payload !== "string") {
15842
+ if (!isObject12(rawCandidate) || !isNonEmptyString11(rawCandidate.eventId) || !isNonEmptyString11(rawCandidate.suid) || typeof rawCandidate.payload !== "string") {
14884
15843
  return { error: "each candidate needs eventId, suid, and payload" };
14885
15844
  }
14886
15845
  const eventTags = stringArrayFrom(rawCandidate.eventTags, "candidate eventTags");
@@ -14894,8 +15853,8 @@ function appendFrom(value, tag) {
14894
15853
  assertSortableUniqueId(rawCandidate.suid);
14895
15854
  if (!isUuidV7(rawCandidate.eventId)) return { error: "candidate eventId must be a UUID v7" };
14896
15855
  JSON.parse(rawCandidate.payload);
14897
- } catch (error10) {
14898
- return { error: error10 instanceof Error ? error10.message : "candidate identity or payload is invalid" };
15856
+ } catch (error11) {
15857
+ return { error: error11 instanceof Error ? error11.message : "candidate identity or payload is invalid" };
14899
15858
  }
14900
15859
  if (rawCandidate.provenance !== "g32") return { error: "candidate provenance must be g32" };
14901
15860
  if (!isNonEmptyString11(rawCandidate.allocatorLineageId)) return { error: "candidate allocatorLineageId is required" };
@@ -14929,10 +15888,10 @@ function appendFrom(value, tag) {
14929
15888
  return { value: { ...reservation.value, candidates: ordered, faultInjection } };
14930
15889
  }
14931
15890
  function bootstrapAppendFrom(value, tag) {
14932
- if (!isObject11(value) || !isNonEmptyString11(value.importId) || !isEpoch(value.leaseEpoch) || !isNonEmptyString11(value.manifestDigest) || !isNonEmptyString11(value.targetServiceId) || !Array.isArray(value.candidates) || value.candidates.length === 0) return { error: "bootstrap identity and candidates are required" };
15891
+ if (!isObject12(value) || !isNonEmptyString11(value.importId) || !isEpoch(value.leaseEpoch) || !isNonEmptyString11(value.manifestDigest) || !isNonEmptyString11(value.targetServiceId) || !Array.isArray(value.candidates) || value.candidates.length === 0) return { error: "bootstrap identity and candidates are required" };
14933
15892
  const candidates = [];
14934
15893
  for (const candidate of value.candidates) {
14935
- if (!isObject11(candidate) || !isNonEmptyString11(candidate.eventId) || !isNonEmptyString11(candidate.suid) || typeof candidate.payload !== "string") return { error: "bootstrap candidate is invalid" };
15894
+ if (!isObject12(candidate) || !isNonEmptyString11(candidate.eventId) || !isNonEmptyString11(candidate.suid) || typeof candidate.payload !== "string") return { error: "bootstrap candidate is invalid" };
14936
15895
  const tags = stringArrayFrom(candidate.eventTags, "bootstrap candidate eventTags");
14937
15896
  if (tags.value === void 0 || !tags.value.includes(tag) || !isNonEmptyString11(candidate.allocatorLineageId)) return { error: "bootstrap candidate must include this tag and lineage" };
14938
15897
  let eventType;
@@ -14942,8 +15901,8 @@ function bootstrapAppendFrom(value, tag) {
14942
15901
  assertSortableUniqueId(candidate.suid);
14943
15902
  if (!isRfc4122Uuid(candidate.eventId)) return { error: "bootstrap candidate eventId must be an RFC 4122 UUID" };
14944
15903
  JSON.parse(candidate.payload);
14945
- } catch (error10) {
14946
- return { error: error10 instanceof Error ? error10.message : "bootstrap candidate identity or payload is invalid" };
15904
+ } catch (error11) {
15905
+ return { error: error11 instanceof Error ? error11.message : "bootstrap candidate identity or payload is invalid" };
14947
15906
  }
14948
15907
  if (candidate.provenance !== "g32") return { error: "bootstrap candidate provenance must be g32" };
14949
15908
  if (!isNonEmptyString11(candidate.timestamp) || !CANONICAL_UTC_TIMESTAMP_PATTERN.test(candidate.timestamp)) return { error: "bootstrap candidate timestamp must be canonical UTC" };
@@ -14955,13 +15914,13 @@ function bootstrapAppendFrom(value, tag) {
14955
15914
  }
14956
15915
  function fenceFrom(value) {
14957
15916
  const epoch2 = epochFrom(value);
14958
- if (epoch2.value === void 0 || !isObject11(value) || !isNonEmptyString11(value.reason)) {
15917
+ if (epoch2.value === void 0 || !isObject12(value) || !isNonEmptyString11(value.reason)) {
14959
15918
  return { error: epoch2.error ?? "reason is required" };
14960
15919
  }
14961
15920
  return { value: { ...epoch2.value, reason: value.reason } };
14962
15921
  }
14963
15922
  function repairScopeItemFrom(value, tag) {
14964
- if (!isObject11(value) || !isNonEmptyString11(value.attemptId) || !isNonEmptyString11(value.eventId) || !isNonEmptyString11(value.suid) || typeof value.payload !== "string" || !isNonEmptyString11(value.allocatorLineageId) || !isNonEmptyString11(value.eventType) || value.provenance !== "g32" || !isNonEmptyString11(value.timestamp)) {
15923
+ if (!isObject12(value) || !isNonEmptyString11(value.attemptId) || !isNonEmptyString11(value.eventId) || !isNonEmptyString11(value.suid) || typeof value.payload !== "string" || !isNonEmptyString11(value.allocatorLineageId) || !isNonEmptyString11(value.eventType) || value.provenance !== "g32" || !isNonEmptyString11(value.timestamp)) {
14965
15924
  return { error: "each repair scope item needs attemptId, eventId, suid, and payload" };
14966
15925
  }
14967
15926
  const eventTags = stringArrayFrom(value.eventTags, "repair eventTags");
@@ -15009,13 +15968,13 @@ function repairScopeFrom(value, tag) {
15009
15968
  return { value: sortRepairScope(scope) };
15010
15969
  }
15011
15970
  function repairLeaseFrom(value) {
15012
- if (!isObject11(value) || !isNonEmptyString11(value.owner) || !isEpoch(value.epoch)) {
15971
+ if (!isObject12(value) || !isNonEmptyString11(value.owner) || !isEpoch(value.epoch)) {
15013
15972
  return { error: "repair owner and non-negative safe-integer epoch are required" };
15014
15973
  }
15015
15974
  return { value: { owner: value.owner, epoch: value.epoch } };
15016
15975
  }
15017
15976
  function repairAcquireFrom(value, tag) {
15018
- if (!isObject11(value) || !isNonEmptyString11(value.owner)) {
15977
+ if (!isObject12(value) || !isNonEmptyString11(value.owner)) {
15019
15978
  return { error: "repair owner is required" };
15020
15979
  }
15021
15980
  const leaseMs = value.leaseMs ?? DEFAULT_REPAIR_LEASE_MS;
@@ -15027,7 +15986,7 @@ function repairAcquireFrom(value, tag) {
15027
15986
  }
15028
15987
  function repairScopeUnionFrom(value, tag) {
15029
15988
  const lease = repairLeaseFrom(value);
15030
- if (lease.value === void 0 || !isObject11(value)) {
15989
+ if (lease.value === void 0 || !isObject12(value)) {
15031
15990
  return { error: lease.error };
15032
15991
  }
15033
15992
  const scope = repairScopeFrom(value.scope, tag);
@@ -15035,7 +15994,7 @@ function repairScopeUnionFrom(value, tag) {
15035
15994
  }
15036
15995
  function repairApplyFrom(value, tag) {
15037
15996
  const lease = repairLeaseFrom(value);
15038
- if (lease.value === void 0 || !isObject11(value)) {
15997
+ if (lease.value === void 0 || !isObject12(value)) {
15039
15998
  return { error: lease.error };
15040
15999
  }
15041
16000
  const item = repairScopeItemFrom(value.item, tag);
@@ -15043,20 +16002,20 @@ function repairApplyFrom(value, tag) {
15043
16002
  }
15044
16003
  function repairAuditFrom(value, tag) {
15045
16004
  const apply = repairApplyFrom(value, tag);
15046
- if (apply.value === void 0 || !isObject11(value) || !isNonEmptyString11(value.actor)) {
16005
+ if (apply.value === void 0 || !isObject12(value) || !isNonEmptyString11(value.actor)) {
15047
16006
  return { error: apply.error ?? "audit actor is required" };
15048
16007
  }
15049
16008
  return { value: { ...apply.value, actor: value.actor } };
15050
16009
  }
15051
16010
  function repairClearFrom(value) {
15052
16011
  const lease = repairLeaseFrom(value);
15053
- if (lease.value === void 0 || !isObject11(value) || !isNonEmptyString11(value.attemptId) || !isNonNegativeInteger4(value.scopeVersion)) {
16012
+ if (lease.value === void 0 || !isObject12(value) || !isNonEmptyString11(value.attemptId) || !isNonNegativeInteger4(value.scopeVersion)) {
15054
16013
  return { error: lease.error ?? "attemptId and scopeVersion are required" };
15055
16014
  }
15056
16015
  return { value: { ...lease.value, attemptId: value.attemptId, scopeVersion: value.scopeVersion } };
15057
16016
  }
15058
16017
  function outboxPendingFrom(value) {
15059
- if (!isObject11(value)) {
16018
+ if (!isObject12(value)) {
15060
16019
  return { error: "outbox pending request must be an object" };
15061
16020
  }
15062
16021
  const nowMs = value.nowMs ?? Date.now();
@@ -15074,22 +16033,22 @@ function outboxPendingFrom(value) {
15074
16033
  return { value: { nowMs, limit, force } };
15075
16034
  }
15076
16035
  function outboxMarkFrom(value) {
15077
- if (!isObject11(value) || !Array.isArray(value.deliveries) || value.deliveries.length === 0) {
16036
+ if (!isObject12(value) || !Array.isArray(value.deliveries) || value.deliveries.length === 0) {
15078
16037
  return { error: "deliveries must be a non-empty array" };
15079
16038
  }
15080
16039
  const deliveries = [];
15081
16040
  for (const raw of value.deliveries) {
15082
- if (!isObject11(raw) || !isNonEmptyString11(raw.attemptId) || !isNonEmptyString11(raw.eventId) || !isNonEmptyString11(raw.suid) || typeof raw.payload !== "string" || !isSafeInteger(raw.enqueuedAt)) {
16041
+ if (!isObject12(raw) || !isNonEmptyString11(raw.attemptId) || !isNonEmptyString11(raw.eventId) || !isNonEmptyString11(raw.suid) || typeof raw.payload !== "string" || !isSafeInteger(raw.enqueuedAt)) {
15083
16042
  return { error: "each delivery needs attemptId, eventId, suid, payload, and enqueuedAt" };
15084
16043
  }
15085
16044
  if (!isNonEmptyString11(raw.eventType) || raw.provenance !== "g32" || !isNonEmptyString11(raw.timestamp) || !isNonEmptyString11(raw.allocatorLineageId)) return { error: "delivery must carry the complete G32 identity" };
15086
- if (!isObject11(raw.completeness)) {
16045
+ if (!isObject12(raw.completeness)) {
15087
16046
  return { error: "delivery must carry a readable global receipt/membership join proof" };
15088
16047
  }
15089
16048
  const completeness = raw.completeness;
15090
16049
  const obligationSequence = completeness.obligationSequence;
15091
16050
  const memberships = completeness.localCommittedMembership;
15092
- if (!isNonEmptyString11(completeness.eventDigest) || !isSafeInteger(obligationSequence) || obligationSequence < 1 || !Array.isArray(memberships) || memberships.length !== 1 || !isObject11(memberships[0]) || memberships[0].eventId !== raw.eventId || typeof memberships[0].tag !== "string") {
16051
+ if (!isNonEmptyString11(completeness.eventDigest) || !isSafeInteger(obligationSequence) || obligationSequence < 1 || !Array.isArray(memberships) || memberships.length !== 1 || !isObject12(memberships[0]) || memberships[0].eventId !== raw.eventId || typeof memberships[0].tag !== "string") {
15093
16052
  return { error: "delivery must carry a readable global receipt/membership join proof" };
15094
16053
  }
15095
16054
  const membership = memberships[0];
@@ -15128,7 +16087,7 @@ function outboxMarkFrom(value) {
15128
16087
  return { value: { deliveries, nowMs } };
15129
16088
  }
15130
16089
  function g44SourceScanFrom(value) {
15131
- if (!isObject11(value) || !isNonEmptyString11(value.serviceId) || !isNonEmptyString11(value.tag) || !isSafeInteger(value.upperBoundSequence) || value.upperBoundSequence < 0 || !isSafeInteger(value.afterSequence) || value.afterSequence < 0 || !isSafeInteger(value.limit) || value.limit < 1 || value.limit > 256) {
16090
+ if (!isObject12(value) || !isNonEmptyString11(value.serviceId) || !isNonEmptyString11(value.tag) || !isSafeInteger(value.upperBoundSequence) || value.upperBoundSequence < 0 || !isSafeInteger(value.afterSequence) || value.afterSequence < 0 || !isSafeInteger(value.limit) || value.limit < 1 || value.limit > 256) {
15132
16091
  return { error: "source scan needs serviceId, tag, and a bounded compound cursor" };
15133
16092
  }
15134
16093
  return {
@@ -15142,7 +16101,7 @@ function g44SourceScanFrom(value) {
15142
16101
  };
15143
16102
  }
15144
16103
  function g46TagStateSourceFrom(value) {
15145
- if (!isObject11(value) || !isNonEmptyString11(value.tag) || typeof value.cursor !== "string" || !isSafeInteger(value.limit) || value.limit < 1 || value.limit > 256 || value.through !== void 0 && typeof value.through !== "string") {
16104
+ if (!isObject12(value) || !isNonEmptyString11(value.tag) || typeof value.cursor !== "string" || !isSafeInteger(value.limit) || value.limit < 1 || value.limit > 256 || value.through !== void 0 && typeof value.through !== "string") {
15146
16105
  return { error: "G46 source read needs tag, cursor, optional through, and a bounded limit" };
15147
16106
  }
15148
16107
  try {
@@ -15316,8 +16275,8 @@ function logicalNow(record) {
15316
16275
  return record.clockNowMs ?? Date.now() + record.clockOffsetMs;
15317
16276
  }
15318
16277
  function expireReservation(record) {
15319
- const active = record.activeReservation;
15320
- if (active === null || active.expiresAt > logicalNow(record)) {
16278
+ const active2 = record.activeReservation;
16279
+ if (active2 === null || active2.expiresAt > logicalNow(record)) {
15321
16280
  return { record, expired: false };
15322
16281
  }
15323
16282
  return {
@@ -15435,7 +16394,7 @@ var TagDurableObject = class {
15435
16394
  const url = new URL(request.url);
15436
16395
  const tag = url.searchParams.get("__tag");
15437
16396
  if (!isNonEmptyString11(tag)) {
15438
- return error8(400, "tag_identity_required", "Tag identity is required");
16397
+ return error9(400, "tag_identity_required", "Tag identity is required");
15439
16398
  }
15440
16399
  const serviceId = url.searchParams.get("__serviceId");
15441
16400
  if (request.method === "GET" && url.pathname === "/head-facts") {
@@ -15443,10 +16402,10 @@ var TagDurableObject = class {
15443
16402
  observation.markFirstStorageRead();
15444
16403
  try {
15445
16404
  const facts = this.readHeadFacts(tag);
15446
- return facts === void 0 ? error8(404, "tag_not_found", "Tag has no durable state yet") : json10(facts);
16405
+ return facts === void 0 ? error9(404, "tag_not_found", "Tag has no durable state yet") : json11(facts);
15447
16406
  } catch (caught) {
15448
16407
  if (caught instanceof TagIdentityConflict) {
15449
- return error8(409, "tag_identity_conflict", "Tag Durable Object identity changed");
16408
+ return error9(409, "tag_identity_conflict", "Tag Durable Object identity changed");
15450
16409
  }
15451
16410
  throw caught;
15452
16411
  }
@@ -15457,9 +16416,9 @@ var TagDurableObject = class {
15457
16416
  observation.markFirstStorageRead();
15458
16417
  const record = this.readStoredRecord(tag);
15459
16418
  if (record === void 0) {
15460
- return error8(404, "tag_not_found", "Tag has no durable state yet");
16419
+ return error9(404, "tag_not_found", "Tag has no durable state yet");
15461
16420
  }
15462
- return record.tag === tag ? json10(requireG32TagRecord(record)) : error8(409, "tag_identity_conflict", "Tag Durable Object identity changed");
16421
+ return record.tag === tag ? json11(requireG32TagRecord(record)) : error9(409, "tag_identity_conflict", "Tag Durable Object identity changed");
15463
16422
  });
15464
16423
  }
15465
16424
  if (request.method === "GET" && url.pathname === "/repair/facts") {
@@ -15467,7 +16426,7 @@ var TagDurableObject = class {
15467
16426
  }
15468
16427
  if (request.method === "POST" && url.pathname === "/debug/alarm") {
15469
16428
  const record = await this.runAlarm();
15470
- return record === void 0 ? error8(404, "tag_not_found", "Tag has no durable state yet") : json10(record);
16429
+ return record === void 0 ? error9(404, "tag_not_found", "Tag has no durable state yet") : json11(record);
15471
16430
  }
15472
16431
  if (request.method === "POST" && url.pathname === "/acquire") {
15473
16432
  return this.traceCommitActor(request, tag, serviceId, activation2, observation, (body2) => this.acquire(tag, body2, observation));
@@ -15490,37 +16449,37 @@ var TagDurableObject = class {
15490
16449
  }
15491
16450
  const body = await this.jsonBody(request);
15492
16451
  if (body === void 0) {
15493
- return error8(400, "malformed_tag_request", "Request body must be JSON");
16452
+ return error9(400, "malformed_tag_request", "Request body must be JSON");
15494
16453
  }
15495
16454
  if (request.method === "POST" && url.pathname === "/__internal/g46/tag-state-incremental") {
15496
16455
  if (request.headers.get("x-sdt-g46-source-read") !== "1") {
15497
- return error8(403, "g46_source_read_forbidden", "G46 source reads require the TagState adapter");
16456
+ return error9(403, "g46_source_read_forbidden", "G46 source reads require the TagState adapter");
15498
16457
  }
15499
16458
  const parsed = g46TagStateSourceFrom(body);
15500
16459
  if (parsed.value === void 0 || parsed.value.tag !== tag) {
15501
- return error8(400, "g46_source_read_invalid", parsed.error ?? "G46 source read is invalid");
16460
+ return error9(400, "g46_source_read_invalid", parsed.error ?? "G46 source read is invalid");
15502
16461
  }
15503
16462
  try {
15504
- return json10(await this.g43TagStateIncrementalCatchUp(parsed.value));
16463
+ return json11(await this.g43TagStateIncrementalCatchUp(parsed.value));
15505
16464
  } catch (caught) {
15506
16465
  if (caught instanceof TagIdentityConflict) {
15507
- return error8(409, "tag_identity_conflict", "Tag Durable Object identity changed");
16466
+ return error9(409, "tag_identity_conflict", "Tag Durable Object identity changed");
15508
16467
  }
15509
- return error8(503, "g46_source_read_unavailable", caught instanceof Error ? caught.message : "G46 source read is unavailable");
16468
+ return error9(503, "g46_source_read_unavailable", caught instanceof Error ? caught.message : "G46 source read is unavailable");
15510
16469
  }
15511
16470
  }
15512
16471
  if (request.method === "POST" && url.pathname === "/__internal/g44/source-obligations") {
15513
16472
  if (request.headers.get("x-sdt-g44-source-scan") !== "1") {
15514
- return error8(403, "g44_source_scan_forbidden", "G44 source scan requires the internal scanner seam");
16473
+ return error9(403, "g44_source_scan_forbidden", "G44 source scan requires the internal scanner seam");
15515
16474
  }
15516
16475
  const parsed = g44SourceScanFrom(body);
15517
16476
  if (parsed.value === void 0 || parsed.value.tag !== tag || parsed.value.serviceId !== serviceId) {
15518
- return error8(400, "g44_source_scan_invalid", parsed.error ?? "G44 source scan identity is invalid");
16477
+ return error9(400, "g44_source_scan_invalid", parsed.error ?? "G44 source scan identity is invalid");
15519
16478
  }
15520
16479
  try {
15521
- return json10(await this.g44ReadSourceObligations(parsed.value));
16480
+ return json11(await this.g44ReadSourceObligations(parsed.value));
15522
16481
  } catch (failure3) {
15523
- return error8(503, "g44_source_scan_unavailable", failure3 instanceof Error ? failure3.message : "G44 source scan is unavailable");
16482
+ return error9(503, "g44_source_scan_unavailable", failure3 instanceof Error ? failure3.message : "G44 source scan is unavailable");
15524
16483
  }
15525
16484
  }
15526
16485
  if (request.method === "POST" && url.pathname === "/bootstrap/admit") {
@@ -15567,7 +16526,7 @@ var TagDurableObject = class {
15567
16526
  }
15568
16527
  if (request.method === "POST" && url.pathname === "/__internal/g77/inspect-target") {
15569
16528
  if (!isNonEmptyString11(serviceId)) {
15570
- return error8(400, "service_identity_required", "Service identity is required");
16529
+ return error9(400, "service_identity_required", "Service identity is required");
15571
16530
  }
15572
16531
  return this.inspectG77Target(serviceId, tag, body);
15573
16532
  }
@@ -15575,28 +16534,28 @@ var TagDurableObject = class {
15575
16534
  return this.fenceAbsentG77Target(tag, body);
15576
16535
  }
15577
16536
  if (request.method === "POST" && url.pathname === "/__internal/g77/capabilities") {
15578
- return json10({ inspectTarget: true, fenceAbsentTarget: true });
16537
+ return json11({ inspectTarget: true, fenceAbsentTarget: true });
15579
16538
  }
15580
- return error8(404, "tag_route_not_found", "Tag route was not found");
16539
+ return error9(404, "tag_route_not_found", "Tag route was not found");
15581
16540
  }
15582
16541
  /** Identity-bound installed/absent inspection for G77 issuance reconciliation. */
15583
16542
  inspectG77Target(serviceId, tag, body) {
15584
- if (!isObject11(body) || !isNonEmptyString11(body.eventId) || !isNonEmptyString11(body.suid)) {
15585
- return error8(400, "invalid_inspect_target", "eventId and suid are required");
16543
+ if (!isObject12(body) || !isNonEmptyString11(body.eventId) || !isNonEmptyString11(body.suid)) {
16544
+ return error9(400, "invalid_inspect_target", "eventId and suid are required");
15586
16545
  }
15587
16546
  const pinnedWriterEpoch = isNonNegativeInteger4(body.pinnedWriterEpoch) ? body.pinnedWriterEpoch : 0;
15588
16547
  const attemptId = isNonEmptyString11(body.attemptId) ? body.attemptId : void 0;
15589
16548
  const sql = this.sqlStorage();
15590
- if (sql === void 0) return error8(503, "tag_sql_unavailable", "Tag SQL storage is unavailable");
16549
+ if (sql === void 0) return error9(503, "tag_sql_unavailable", "Tag SQL storage is unavailable");
15591
16550
  const identity2 = sql.exec("SELECT tag FROM tag_identity WHERE singleton = 1").toArray()[0];
15592
16551
  if (identity2 === void 0) {
15593
16552
  if (attemptId !== void 0) {
15594
- return json10({ inspectionStatus: "absent-never-contacted" });
16553
+ return json11({ inspectionStatus: "absent-never-contacted" });
15595
16554
  }
15596
- return error8(409, "target_not_terminal", "Target is not terminal under pinned writer authority");
16555
+ return error9(409, "target_not_terminal", "Target is not terminal under pinned writer authority");
15597
16556
  }
15598
16557
  if (sqlString(identity2.tag, "tag_identity.tag") !== tag) {
15599
- return error8(409, "tag_identity_mismatch", "Tag identity does not match the inspected tag");
16558
+ return error9(409, "tag_identity_mismatch", "Tag identity does not match the inspected tag");
15600
16559
  }
15601
16560
  const event = sql.exec(`
15602
16561
  SELECT attempt_id, event_id, suid FROM tag_event
@@ -15609,41 +16568,41 @@ var TagDurableObject = class {
15609
16568
  `, serviceId, body.eventId).toArray()[0];
15610
16569
  if (obligation !== void 0) {
15611
16570
  const obligationDigest = sqlString(obligation.event_digest, "tag_outbox_obligation.event_digest");
15612
- return json10({
16571
+ return json11({
15613
16572
  terminalStatus: "installed-and-covered",
15614
16573
  eventId: body.eventId,
15615
16574
  obligationDigest
15616
16575
  });
15617
16576
  }
15618
- return error8(409, "target_not_terminal", "Target append is in flight under pinned writer authority");
16577
+ return error9(409, "target_not_terminal", "Target append is in flight under pinned writer authority");
15619
16578
  }
15620
16579
  if (attemptId !== void 0) {
15621
16580
  const tombstone = sql.exec("SELECT epoch FROM tag_tombstone WHERE attempt_id = ?", attemptId).toArray()[0];
15622
16581
  const tombstoneEpoch = tombstone === void 0 ? void 0 : sqlNumber(tombstone.epoch, "tag_tombstone.epoch");
15623
16582
  if (tombstoneEpoch !== void 0 && pinnedWriterEpoch <= tombstoneEpoch) {
15624
- return json10({ terminalStatus: "absent-and-irrevocably-fenced", tombstoneEpoch });
16583
+ return json11({ terminalStatus: "absent-and-irrevocably-fenced", tombstoneEpoch });
15625
16584
  }
15626
16585
  const reservation = sql.exec("SELECT attempt_id, expires_at FROM tag_reservation WHERE singleton = 1").toArray()[0];
15627
16586
  if (reservation !== void 0 && sqlString(reservation.attempt_id, "tag_reservation.attempt_id") === attemptId) {
15628
- return error8(409, "target_not_terminal", "Active reservation holds writer authority");
16587
+ return error9(409, "target_not_terminal", "Active reservation holds writer authority");
15629
16588
  }
15630
16589
  const epoch2 = sql.exec("SELECT attempt_id FROM tag_epoch WHERE attempt_id = ?", attemptId).toArray()[0];
15631
16590
  if (epoch2 !== void 0) {
15632
- return json10({ inspectionStatus: "absent-but-unfenced" });
16591
+ return json11({ inspectionStatus: "absent-but-unfenced" });
15633
16592
  }
15634
- return json10({ inspectionStatus: "absent-never-contacted" });
16593
+ return json11({ inspectionStatus: "absent-never-contacted" });
15635
16594
  }
15636
- return error8(409, "target_not_terminal", "Target is not terminal under pinned writer authority");
16595
+ return error9(409, "target_not_terminal", "Target is not terminal under pinned writer authority");
15637
16596
  }
15638
16597
  /** Reconciler-only fence for never-contacted targets; creates durable tombstone state. */
15639
16598
  async fenceAbsentG77Target(tag, body) {
15640
16599
  const parsed = reservationFrom(body);
15641
16600
  if (parsed.value === void 0) {
15642
- return error8(400, "invalid_fence_target", parsed.error ?? "attemptId and epoch are required");
16601
+ return error9(400, "invalid_fence_target", parsed.error ?? "attemptId and epoch are required");
15643
16602
  }
15644
16603
  this.ensureSqlTag(tag);
15645
16604
  const result2 = await this.cancelSql(tag, { ...parsed.value, forceTombstone: true });
15646
- return result2.status >= 200 && result2.status < 300 ? json10(result2.body) : error8(result2.status, "fence_target_rejected", "Absent target fence was rejected");
16605
+ return result2.status >= 200 && result2.status < 300 ? json11(result2.body) : error9(result2.status, "fence_target_rejected", "Absent target fence was rejected");
15647
16606
  }
15648
16607
  async alarm() {
15649
16608
  this.activation.beginHandler();
@@ -15990,21 +16949,21 @@ var TagDurableObject = class {
15990
16949
  const result2 = await authority;
15991
16950
  g44GlobalArrayAuthorityResultByD1.set(database, result2);
15992
16951
  return result2;
15993
- } catch (error10) {
16952
+ } catch (error11) {
15994
16953
  if (g44GlobalArrayAuthorityByD1.get(database) === authority) {
15995
16954
  g44GlobalArrayAuthorityByD1.delete(database);
15996
16955
  }
15997
- throw error10;
16956
+ throw error11;
15998
16957
  }
15999
16958
  }
16000
16959
  async readG44GlobalArrayAuthority(database) {
16001
16960
  try {
16002
16961
  await database.prepare('SELECT "EventDigest" FROM dcb_events WHERE 1 = 0').all();
16003
16962
  return true;
16004
- } catch (error10) {
16005
- const message = error10 instanceof Error ? error10.message : String(error10);
16963
+ } catch (error11) {
16964
+ const message = error11 instanceof Error ? error11.message : String(error11);
16006
16965
  if (/no such (?:table|column):\s*(?:dcb_events|EventDigest)/i.test(message)) return false;
16007
- throw error10;
16966
+ throw error11;
16008
16967
  }
16009
16968
  }
16010
16969
  async traceCommitActor(request, tag, serviceId, activation2, observation, callback) {
@@ -16014,10 +16973,10 @@ var TagDurableObject = class {
16014
16973
  { actorClass: "TAG", actorKey: `tag:${serviceId}:${tag}`, activation: activation2, observation },
16015
16974
  async () => {
16016
16975
  body = await this.jsonBody(request);
16017
- const attemptId = isObject11(body) && isNonEmptyString11(body.attemptId) ? body.attemptId : void 0;
16976
+ const attemptId = isObject12(body) && isNonEmptyString11(body.attemptId) ? body.attemptId : void 0;
16018
16977
  return attemptId === void 0 || !isNonEmptyString11(serviceId) ? void 0 : { attemptId, serviceId };
16019
16978
  },
16020
- async () => body === void 0 ? error8(400, "malformed_tag_request", "Request body must be JSON") : callback(body)
16979
+ async () => body === void 0 ? error9(400, "malformed_tag_request", "Request body must be JSON") : callback(body)
16021
16980
  );
16022
16981
  }
16023
16982
  /**
@@ -16231,6 +17190,7 @@ var TagDurableObject = class {
16231
17190
  ensureSqlTag(tag) {
16232
17191
  const sql = this.sqlStorage();
16233
17192
  if (sql === void 0) throw new Error("Tag SQL storage is unavailable");
17193
+ ensureTagCommitReceiptWrittenVersion(sql);
16234
17194
  const existing = sql.exec("SELECT tag FROM tag_identity WHERE singleton = 1").toArray()[0];
16235
17195
  if (existing !== void 0) {
16236
17196
  if (sqlString(existing.tag, "tag_identity.tag") !== tag) throw new Error("Tag Durable Object identity changed");
@@ -16343,17 +17303,18 @@ var TagDurableObject = class {
16343
17303
  sql.exec("UPDATE tag_control SET head_suid = ?, version = ?, updated_at = ? WHERE singleton = 1", head, version, committedAt);
16344
17304
  sql.exec("UPDATE tag_head SET service_id = ?, head_suid = ? WHERE singleton = 1", serviceId, head);
16345
17305
  }
16346
- writeCommittedSqlReceipt(sql, input, committedAt, eventCount, head, confirmsReservation) {
17306
+ writeCommittedSqlReceipt(sql, input, committedAt, eventCount, head, confirmsReservation, writtenVersion) {
16347
17307
  sql.exec(`
16348
17308
  INSERT INTO tag_commit_receipt
16349
- (attempt_id, epoch, committed_at, committed_event_count, head_suid, reservation_confirmed)
16350
- VALUES (?, ?, ?, ?, ?, ?)
17309
+ (attempt_id, epoch, committed_at, committed_event_count, head_suid, reservation_confirmed, written_version)
17310
+ VALUES (?, ?, ?, ?, ?, ?, ?)
16351
17311
  ON CONFLICT(attempt_id, epoch) DO UPDATE SET
16352
17312
  committed_at = excluded.committed_at,
16353
17313
  committed_event_count = excluded.committed_event_count,
16354
17314
  head_suid = excluded.head_suid,
16355
- reservation_confirmed = excluded.reservation_confirmed
16356
- `, input.attemptId, input.epoch, committedAt, eventCount, head, confirmsReservation ? 1 : 0);
17315
+ reservation_confirmed = excluded.reservation_confirmed,
17316
+ written_version = excluded.written_version
17317
+ `, input.attemptId, input.epoch, committedAt, eventCount, head, confirmsReservation ? 1 : 0, writtenVersion);
16357
17318
  }
16358
17319
  /**
16359
17320
  * The normal append path deliberately probes only the indexed rows it needs
@@ -16395,11 +17356,29 @@ var TagDurableObject = class {
16395
17356
  return { event, obligation, exact };
16396
17357
  });
16397
17358
  if (existingCandidates.every(({ exact }) => exact)) {
16398
- return { status: 200, body: { status: "duplicate", version } };
17359
+ const receipts = sql.exec(`
17360
+ SELECT epoch, committed_at, written_version, head_suid FROM tag_commit_receipt
17361
+ WHERE attempt_id = ?
17362
+ `, input.attemptId).toArray();
17363
+ const sameEpoch = receipts.find((row) => sqlNumber(row.epoch, "tag_commit_receipt.epoch") === input.epoch);
17364
+ const replayHead = input.candidates.at(-1)?.suid;
17365
+ const byHead = replayHead === void 0 ? [] : receipts.filter((row) => sqlString(row.head_suid, "tag_commit_receipt.head_suid") === replayHead);
17366
+ const receipt = sameEpoch ?? (byHead.length === 1 ? byHead[0] : void 0) ?? (receipts.length === 1 ? receipts[0] : void 0);
17367
+ if (receipt === void 0) {
17368
+ await this.rearmScheduler(txn);
17369
+ return { ...rejected("duplicate_receipt_missing"), body: { ...rejected("duplicate_receipt_missing").body, version } };
17370
+ }
17371
+ const storedAt = sqlNullableString(receipt.committed_at, "tag_commit_receipt.committed_at");
17372
+ const storedVersion = sqlNullableNumber(receipt.written_version, "tag_commit_receipt.written_version");
17373
+ if (storedAt === null || storedVersion === null) {
17374
+ await this.rearmScheduler(txn);
17375
+ return { ...rejected("duplicate_receipt_unknown"), body: { ...rejected("duplicate_receipt_unknown").body, version } };
17376
+ }
17377
+ return { status: 200, body: { status: "duplicate", version: storedVersion, updatedAt: storedAt } };
16399
17378
  }
16400
- const active = sql.exec("SELECT * FROM tag_reservation WHERE singleton = 1").toArray()[0];
17379
+ const active2 = sql.exec("SELECT * FROM tag_reservation WHERE singleton = 1").toArray()[0];
16401
17380
  const now2 = sqlNullableNumber(control.clock_now_ms, "tag_control.clock_now_ms") ?? Date.now() + sqlNumber(control.clock_offset_ms, "tag_control.clock_offset_ms");
16402
- let reservation = active;
17381
+ let reservation = active2;
16403
17382
  if (reservation !== void 0 && sqlNumber(reservation.expires_at, "tag_reservation.expires_at") <= now2) {
16404
17383
  sql.exec("DELETE FROM tag_reservation WHERE singleton = 1");
16405
17384
  version += 1;
@@ -16492,7 +17471,7 @@ var TagDurableObject = class {
16492
17471
  if (input.faultInjection === "after-append-before-confirm") {
16493
17472
  throw new AppendTransactionFault("Simulated interruption before atomic commit receipt");
16494
17473
  }
16495
- this.writeCommittedSqlReceipt(sql, input, committedAt, events.length, head, confirmsReservation);
17474
+ this.writeCommittedSqlReceipt(sql, input, committedAt, events.length, head, confirmsReservation, version + 1);
16496
17475
  if (confirmsReservation) sql.exec("DELETE FROM tag_reservation WHERE singleton = 1");
16497
17476
  await this.rearmScheduler(txn);
16498
17477
  return {
@@ -16500,7 +17479,8 @@ var TagDurableObject = class {
16500
17479
  body: {
16501
17480
  status: "appended",
16502
17481
  fenceGate: { checked: true, activeFenceCount: 0 },
16503
- version: version + 1
17482
+ version: version + 1,
17483
+ updatedAt: committedAt
16504
17484
  },
16505
17485
  hopFacts
16506
17486
  };
@@ -16901,18 +17881,20 @@ var TagDurableObject = class {
16901
17881
  );
16902
17882
  this.upsertSourcePartitionRegistration(sql, eventServiceId, record.tag, outbox.eventId);
16903
17883
  }
17884
+ ensureTagCommitReceiptWrittenVersion(sql);
16904
17885
  for (const confirmation of record.confirmations) {
16905
17886
  sql.exec(
16906
17887
  `
16907
17888
  INSERT OR IGNORE INTO tag_commit_receipt
16908
- (attempt_id, epoch, committed_at, committed_event_count, head_suid, reservation_confirmed)
16909
- VALUES (?, ?, ?, ?, ?, 1)
17889
+ (attempt_id, epoch, committed_at, committed_event_count, head_suid, reservation_confirmed, written_version)
17890
+ VALUES (?, ?, ?, ?, ?, 1, ?)
16910
17891
  `,
16911
17892
  confirmation.attemptId,
16912
17893
  confirmation.epoch,
16913
17894
  record.updatedAt,
16914
17895
  record.events.filter((event) => event.attemptId === confirmation.attemptId).length,
16915
- record.head
17896
+ record.head,
17897
+ record.version
16916
17898
  );
16917
17899
  }
16918
17900
  }
@@ -16961,13 +17943,13 @@ var TagDurableObject = class {
16961
17943
  async acquire(tag, body, observation) {
16962
17944
  const parsed = acquireFrom(body, tag);
16963
17945
  if (parsed.value === void 0) {
16964
- return error8(400, "invalid_tag_acquire", parsed.error ?? "Invalid acquire request");
17946
+ return error9(400, "invalid_tag_acquire", parsed.error ?? "Invalid acquire request");
16965
17947
  }
16966
17948
  const input = parsed.value;
16967
17949
  observation?.markFirstStorageRead();
16968
17950
  if (this.sqlStorage() !== void 0) {
16969
17951
  const result3 = await this.acquireSql(tag, input);
16970
- return json10(result3.body, result3.status);
17952
+ return json11(result3.body, result3.status);
16971
17953
  }
16972
17954
  const result2 = await this.ctx.storage.transaction(async (txn) => {
16973
17955
  const loaded = await this.recordFor(txn, tag);
@@ -17002,9 +17984,9 @@ var TagDurableObject = class {
17002
17984
  body: { ...rejected("consistency_head_mismatch").body, version: record.version }
17003
17985
  };
17004
17986
  }
17005
- const active = record.activeReservation;
17006
- if (active !== null) {
17007
- if (active.attemptId === input.attemptId && active.epoch === input.epoch) {
17987
+ const active2 = record.activeReservation;
17988
+ if (active2 !== null) {
17989
+ if (active2.attemptId === input.attemptId && active2.epoch === input.epoch) {
17008
17990
  return {
17009
17991
  status: 200,
17010
17992
  body: {
@@ -17049,18 +18031,18 @@ var TagDurableObject = class {
17049
18031
  body: { status: "reserved", reservation, fenceGate, version: updated.version }
17050
18032
  };
17051
18033
  });
17052
- return json10(result2.body, result2.status);
18034
+ return json11(result2.body, result2.status);
17053
18035
  }
17054
18036
  async cancel(tag, body, observation) {
17055
18037
  const parsed = reservationFrom(body);
17056
18038
  if (parsed.value === void 0) {
17057
- return error8(400, "invalid_tag_cancel", parsed.error ?? "Invalid cancel request");
18039
+ return error9(400, "invalid_tag_cancel", parsed.error ?? "Invalid cancel request");
17058
18040
  }
17059
18041
  const input = parsed.value;
17060
18042
  observation?.markFirstStorageRead();
17061
18043
  if (this.sqlStorage() !== void 0) {
17062
18044
  const result3 = await this.cancelSql(tag, input);
17063
- return json10(result3.body, result3.status);
18045
+ return json11(result3.body, result3.status);
17064
18046
  }
17065
18047
  const result2 = await this.ctx.storage.transaction(async (txn) => {
17066
18048
  const loaded = await this.recordFor(txn, tag);
@@ -17095,8 +18077,8 @@ var TagDurableObject = class {
17095
18077
  record = await this.commitExpiryIfNeeded(txn, expiry);
17096
18078
  return { ...rejected(epochError), body: { ...rejected(epochError).body, version: record.version } };
17097
18079
  }
17098
- const active = record.activeReservation;
17099
- if (active === null || active.attemptId !== input.attemptId || active.epoch !== input.epoch || active.token !== input.reservationToken) {
18080
+ const active2 = record.activeReservation;
18081
+ if (active2 === null || active2.attemptId !== input.attemptId || active2.epoch !== input.epoch || active2.token !== input.reservationToken) {
17100
18082
  record = await this.commitExpiryIfNeeded(txn, expiry);
17101
18083
  return {
17102
18084
  ...rejected("reservation_token_required"),
@@ -17111,12 +18093,12 @@ var TagDurableObject = class {
17111
18093
  });
17112
18094
  return { status: 200, body: { status: "cancelled", idempotent: false, version: updated.version } };
17113
18095
  });
17114
- return json10(result2.body, result2.status);
18096
+ return json11(result2.body, result2.status);
17115
18097
  }
17116
18098
  async seal(tag, body, observation) {
17117
18099
  const parsed = epochFrom(body);
17118
18100
  if (parsed.value === void 0) {
17119
- return error8(400, "invalid_tag_seal", parsed.error ?? "Invalid seal request");
18101
+ return error9(400, "invalid_tag_seal", parsed.error ?? "Invalid seal request");
17120
18102
  }
17121
18103
  const input = parsed.value;
17122
18104
  observation?.markFirstStorageRead();
@@ -17151,7 +18133,7 @@ var TagDurableObject = class {
17151
18133
  });
17152
18134
  return { status: 200, body: { status: "sealed", highestEpoch: input.epoch, version: updated.version } };
17153
18135
  });
17154
- return json10(result2.body, result2.status);
18136
+ return json11(result2.body, result2.status);
17155
18137
  }
17156
18138
  /**
17157
18139
  * Coordinator-only import admission. This is deliberately not a flag on
@@ -17160,8 +18142,8 @@ var TagDurableObject = class {
17160
18142
  */
17161
18143
  async bootstrapAppend(tag, body, serviceId) {
17162
18144
  const parsed = bootstrapAppendFrom(body, tag);
17163
- if (parsed.value === void 0) return error8(400, "invalid_bootstrap_admission", parsed.error ?? "Invalid bootstrap admission");
17164
- if (serviceId !== parsed.value.targetServiceId) return error8(409, "bootstrap_service_scope_mismatch", "Bootstrap target service does not match tag scope");
18145
+ if (parsed.value === void 0) return error9(400, "invalid_bootstrap_admission", parsed.error ?? "Invalid bootstrap admission");
18146
+ if (serviceId !== parsed.value.targetServiceId) return error9(409, "bootstrap_service_scope_mismatch", "Bootstrap target service does not match tag scope");
17165
18147
  const input = parsed.value;
17166
18148
  const result2 = await this.ctx.storage.transaction(async (txn) => {
17167
18149
  const loaded = await this.recordFor(txn, tag);
@@ -17182,10 +18164,10 @@ var TagDurableObject = class {
17182
18164
  );
17183
18165
  return { status: 201, body: { status: "bootstrap_admitted", version: updated.version } };
17184
18166
  });
17185
- return json10(result2.body, result2.status);
18167
+ return json11(result2.body, result2.status);
17186
18168
  }
17187
18169
  async closeBootstrap(tag, body) {
17188
- if (!isObject11(body) || !isNonEmptyString11(body.importId) || !isEpoch(body.leaseEpoch)) return error8(400, "invalid_bootstrap_close", "bootstrap importId and leaseEpoch are required");
18170
+ if (!isObject12(body) || !isNonEmptyString11(body.importId) || !isEpoch(body.leaseEpoch)) return error9(400, "invalid_bootstrap_close", "bootstrap importId and leaseEpoch are required");
17189
18171
  const result2 = await this.ctx.storage.transaction(async (txn) => {
17190
18172
  const loaded = await this.recordFor(txn, tag);
17191
18173
  const record = loaded.record;
@@ -17195,7 +18177,7 @@ var TagDurableObject = class {
17195
18177
  const updated = await this.commit(txn, record, { bootstrapAdmission: { ...admission, closed: true } });
17196
18178
  return { status: 200, body: { status: "closed", version: updated.version } };
17197
18179
  });
17198
- return json10(result2.body, result2.status);
18180
+ return json11(result2.body, result2.status);
17199
18181
  }
17200
18182
  directDoorbellPreflight(domainDeliveryClass) {
17201
18183
  const domainClass = domainDeliveryClass === void 0 ? void 0 : readDomainDeliveryClass({ DOMAIN_DELIVERY_CLASS: domainDeliveryClass });
@@ -17214,7 +18196,7 @@ var TagDurableObject = class {
17214
18196
  async append(tag, body, serviceId, domainDeliveryClass, observation) {
17215
18197
  const parsed = appendFrom(body, tag);
17216
18198
  if (parsed.value === void 0) {
17217
- return error8(400, "invalid_tag_append", parsed.error ?? "Invalid append request");
18199
+ return error9(400, "invalid_tag_append", parsed.error ?? "Invalid append request");
17218
18200
  }
17219
18201
  const input = parsed.value;
17220
18202
  try {
@@ -17252,7 +18234,7 @@ var TagDurableObject = class {
17252
18234
  if ((result3.status === 201 || result3.status === 200) && serviceId !== null && serviceId.length > 0 && sourcePartitionRegistration !== "unconfigured") {
17253
18235
  this.scheduleSourcePartitionWatermark(tag, serviceId);
17254
18236
  }
17255
- const response4 = json10(result3.body, result3.status);
18237
+ const response4 = json11(result3.body, result3.status);
17256
18238
  if (result3.status === 201 && serviceId !== null && serviceId.length > 0 && this.env.AUTO_DRAIN_OUTBOX === "true" && (this.env.DOWNSTREAM_QUEUE !== void 0 || doorbellPreflight.status === "ready" && this.env.DOWNSTREAM_DOORBELL !== void 0)) {
17257
18239
  const directRows = doorbellPreflight.status === "ready" && this.env.DOWNSTREAM_DOORBELL !== void 0 ? await this.directDeliveryBeforeResponse(tag, serviceId) : void 0;
17258
18240
  if (sourcePartitionRegistration !== "unconfigured" || sourcePartitionWasRegistered) {
@@ -17269,7 +18251,19 @@ var TagDurableObject = class {
17269
18251
  const loaded = await this.recordFor(txn, tag);
17270
18252
  let record = loaded.record;
17271
18253
  if (batchIsExactDuplicate(record, input)) {
17272
- return { status: 200, body: { status: "duplicate", version: record.version } };
18254
+ const receipts = record.writeReceipts ?? {};
18255
+ const sameEpoch = receipts[`${input.attemptId}:${input.epoch}`];
18256
+ const forAttempt = Object.entries(receipts).filter(([key]) => key.startsWith(`${input.attemptId}:`));
18257
+ const replayHead = input.candidates.at(-1)?.suid;
18258
+ const byHead = replayHead === void 0 ? [] : forAttempt.filter(([, value]) => value.headSuid === replayHead);
18259
+ const receipt = sameEpoch ?? (byHead.length === 1 ? byHead[0]?.[1] : void 0) ?? (forAttempt.length === 1 ? forAttempt[0]?.[1] : void 0);
18260
+ if (receipt === void 0) {
18261
+ return {
18262
+ ...rejected("duplicate_receipt_unknown"),
18263
+ body: { ...rejected("duplicate_receipt_unknown").body, version: record.version }
18264
+ };
18265
+ }
18266
+ return { status: 200, body: { status: "duplicate", version: receipt.version, updatedAt: receipt.updatedAt } };
17273
18267
  }
17274
18268
  const expiry = expireReservation(record);
17275
18269
  record = expiry.record;
@@ -17282,9 +18276,9 @@ var TagDurableObject = class {
17282
18276
  await this.commitExpiryIfNeeded(txn, expiry);
17283
18277
  return fenceGateRejected();
17284
18278
  }
17285
- const active = record.activeReservation;
17286
- const confirmsReservation = active !== null && active.attemptId === input.attemptId && active.epoch === input.epoch && active.token === input.reservationToken;
17287
- if (active !== null && (active.attemptId !== input.attemptId || active.epoch !== input.epoch || active.token !== input.reservationToken)) {
18279
+ const active2 = record.activeReservation;
18280
+ const confirmsReservation = active2 !== null && active2.attemptId === input.attemptId && active2.epoch === input.epoch && active2.token === input.reservationToken;
18281
+ if (active2 !== null && (active2.attemptId !== input.attemptId || active2.epoch !== input.epoch || active2.token !== input.reservationToken)) {
17288
18282
  record = await this.commitExpiryIfNeeded(txn, expiry);
17289
18283
  return {
17290
18284
  ...rejected("reservation_token_required"),
@@ -17346,13 +18340,20 @@ var TagDurableObject = class {
17346
18340
  alarmDueAt: null,
17347
18341
  confirmations: confirmsReservation ? withMaxEpoch(record.confirmations, input.attemptId, input.epoch) : record.confirmations
17348
18342
  });
17349
- await this.write(txn, updated, serviceId ?? "");
18343
+ const recorded = {
18344
+ ...updated,
18345
+ writeReceipts: {
18346
+ ...record.writeReceipts ?? {},
18347
+ [`${input.attemptId}:${input.epoch}`]: { version: updated.version, updatedAt: updated.updatedAt, headSuid: updated.head }
18348
+ }
18349
+ };
18350
+ await this.write(txn, recorded, serviceId ?? "");
17350
18351
  return {
17351
18352
  status: 201,
17352
- body: { status: "appended", fenceGate, version: updated.version }
18353
+ body: { status: "appended", fenceGate, version: recorded.version, updatedAt: recorded.updatedAt }
17353
18354
  };
17354
18355
  });
17355
- const response3 = json10(result2.body, result2.status);
18356
+ const response3 = json11(result2.body, result2.status);
17356
18357
  if (result2.status === 201 && serviceId !== null && serviceId.length > 0 && this.env.AUTO_DRAIN_OUTBOX === "true" && (this.env.DOWNSTREAM_QUEUE !== void 0 || doorbellPreflight.status === "ready" && this.env.DOWNSTREAM_DOORBELL !== void 0)) {
17357
18358
  const directRows = doorbellPreflight.status === "ready" && this.env.DOWNSTREAM_DOORBELL !== void 0 ? await this.directDeliveryBeforeResponse(tag, serviceId) : void 0;
17358
18359
  withGlobalAdmission2(
@@ -17364,16 +18365,16 @@ var TagDurableObject = class {
17364
18365
  return response3;
17365
18366
  } catch (failure3) {
17366
18367
  if (failure3 instanceof PartitionRegistrationUnavailableError) {
17367
- return error8(503, "partition_registration_unavailable", "Source partition registration is unavailable; retry the commit.", true);
18368
+ return error9(503, "partition_registration_unavailable", "Source partition registration is unavailable; retry the commit.", true);
17368
18369
  }
17369
18370
  if (failure3 instanceof AppendTransactionFault) {
17370
- return error8(
18371
+ return error9(
17371
18372
  503,
17372
18373
  "simulated_append_crash",
17373
18374
  "Simulated interruption before atomic append and confirmation commit"
17374
18375
  );
17375
18376
  }
17376
- return error8(500, "tag_append_failure", "Tag append could not be persisted");
18377
+ return error9(500, "tag_append_failure", "Tag append could not be persisted");
17377
18378
  }
17378
18379
  }
17379
18380
  /**
@@ -17489,7 +18490,7 @@ var TagDurableObject = class {
17489
18490
  let timer;
17490
18491
  const operationResult = Promise.resolve().then(operation2).then(
17491
18492
  (value) => ({ status: "completed", value }),
17492
- (error10) => ({ status: "failed", error: error10 })
18493
+ (error11) => ({ status: "failed", error: error11 })
17493
18494
  );
17494
18495
  const timeout = new Promise((resolve) => {
17495
18496
  timer = setTimeout(() => resolve({ status: "timeout" }), budgetMs);
@@ -17540,14 +18541,14 @@ var TagDurableObject = class {
17540
18541
  envelopeBytes,
17541
18542
  status: "success"
17542
18543
  });
17543
- } catch (error10) {
18544
+ } catch (error11) {
17544
18545
  console.warn("direct_doorbell_status", {
17545
18546
  status: "queued-degraded",
17546
18547
  reason: "direct_doorbell_delivery_failed",
17547
18548
  correlationId,
17548
18549
  envelopeBytes,
17549
- failureKind: classifyDirectDoorbellFailure(error10),
17550
- error: String(error10)
18550
+ failureKind: classifyDirectDoorbellFailure(error11),
18551
+ error: String(error11)
17551
18552
  });
17552
18553
  }
17553
18554
  }
@@ -17608,7 +18609,7 @@ var TagDurableObject = class {
17608
18609
  async confirm(tag, body) {
17609
18610
  const parsed = reservationFrom(body);
17610
18611
  if (parsed.value === void 0) {
17611
- return error8(400, "invalid_tag_confirm", parsed.error ?? "Invalid confirm request");
18612
+ return error9(400, "invalid_tag_confirm", parsed.error ?? "Invalid confirm request");
17612
18613
  }
17613
18614
  const input = parsed.value;
17614
18615
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -17624,8 +18625,8 @@ var TagDurableObject = class {
17624
18625
  record = await this.commitExpiryIfNeeded(txn, expiry);
17625
18626
  return { ...rejected(epochError), body: { ...rejected(epochError).body, version: record.version } };
17626
18627
  }
17627
- const active = record.activeReservation;
17628
- if (active !== null && active.attemptId === input.attemptId && active.epoch === input.epoch && active.token === input.reservationToken) {
18628
+ const active2 = record.activeReservation;
18629
+ if (active2 !== null && active2.attemptId === input.attemptId && active2.epoch === input.epoch && active2.token === input.reservationToken) {
17629
18630
  record = await this.commitExpiryIfNeeded(txn, expiry);
17630
18631
  return {
17631
18632
  ...rejected("append_required_for_confirmation"),
@@ -17638,12 +18639,12 @@ var TagDurableObject = class {
17638
18639
  body: { ...rejected("confirmation_not_found").body, version: record.version }
17639
18640
  };
17640
18641
  });
17641
- return json10(result2.body, result2.status);
18642
+ return json11(result2.body, result2.status);
17642
18643
  }
17643
18644
  async installFence(tag, body) {
17644
18645
  const parsed = fenceFrom(body);
17645
18646
  if (parsed.value === void 0) {
17646
- return error8(400, "invalid_tag_fence", parsed.error ?? "Invalid fence request");
18647
+ return error9(400, "invalid_tag_fence", parsed.error ?? "Invalid fence request");
17647
18648
  }
17648
18649
  const input = parsed.value;
17649
18650
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -17680,12 +18681,12 @@ var TagDurableObject = class {
17680
18681
  });
17681
18682
  return { status: 201, body: { status: "fence-installed", idempotent: false, version: updated.version } };
17682
18683
  });
17683
- return json10(result2.body, result2.status);
18684
+ return json11(result2.body, result2.status);
17684
18685
  }
17685
18686
  async clearFence(tag, body) {
17686
18687
  const parsed = fenceFrom(body);
17687
18688
  if (parsed.value === void 0) {
17688
- return error8(400, "invalid_tag_fence", parsed.error ?? "Invalid fence request");
18689
+ return error9(400, "invalid_tag_fence", parsed.error ?? "Invalid fence request");
17689
18690
  }
17690
18691
  const input = parsed.value;
17691
18692
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -17711,7 +18712,7 @@ var TagDurableObject = class {
17711
18712
  });
17712
18713
  return { status: 200, body: { status: "fence-cleared", idempotent: false, version: updated.version } };
17713
18714
  });
17714
- return json10(result2.body, result2.status);
18715
+ return json11(result2.body, result2.status);
17715
18716
  }
17716
18717
  /**
17717
18718
  * Returns Tag-side repair facts only. Journal observations are deliberately
@@ -17747,7 +18748,7 @@ var TagDurableObject = class {
17747
18748
  }
17748
18749
  };
17749
18750
  });
17750
- return json10(result2.body, result2.status);
18751
+ return json11(result2.body, result2.status);
17751
18752
  }
17752
18753
  /**
17753
18754
  * Internal outbox handoff: enqueuedAt is persisted before any Queue send so
@@ -17757,10 +18758,10 @@ var TagDurableObject = class {
17757
18758
  async pendingOutbox(tag, serviceId, body) {
17758
18759
  const parsed = outboxPendingFrom(body);
17759
18760
  if (parsed.value === void 0) {
17760
- return error8(400, "invalid_outbox_pending", parsed.error ?? "Invalid outbox pending request");
18761
+ return error9(400, "invalid_outbox_pending", parsed.error ?? "Invalid outbox pending request");
17761
18762
  }
17762
18763
  if (!isNonEmptyString11(serviceId)) {
17763
- return error8(400, "outbox_service_identity_required", "Outbox delivery requires a service identity");
18764
+ return error9(400, "outbox_service_identity_required", "Outbox delivery requires a service identity");
17764
18765
  }
17765
18766
  const input = parsed.value;
17766
18767
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -17836,7 +18837,7 @@ var TagDurableObject = class {
17836
18837
  }
17837
18838
  return { status: 200, body: { rows } };
17838
18839
  });
17839
- return json10(result2.body, result2.status);
18840
+ return json11(result2.body, result2.status);
17840
18841
  }
17841
18842
  /**
17842
18843
  * Source-side obligation scanner. It deliberately does not call the Queue,
@@ -17906,7 +18907,7 @@ var TagDurableObject = class {
17906
18907
  }
17907
18908
  };
17908
18909
  });
17909
- return json10(result2.body, result2.status);
18910
+ return json11(result2.body, result2.status);
17910
18911
  }
17911
18912
  /** Record a retry or terminal poison disposition without changing the source event. */
17912
18913
  async recordOutboxFailure(tag, delivery, failure3) {
@@ -17960,16 +18961,16 @@ var TagDurableObject = class {
17960
18961
  async markOutboxDelivered(tag, body) {
17961
18962
  const parsed = outboxMarkFrom(body);
17962
18963
  if (parsed.value === void 0) {
17963
- return error8(400, "invalid_outbox_delivery_mark", parsed.error ?? "Invalid outbox delivery mark");
18964
+ return error9(400, "invalid_outbox_delivery_mark", parsed.error ?? "Invalid outbox delivery mark");
17964
18965
  }
17965
18966
  const input = parsed.value;
17966
18967
  try {
17967
18968
  const joined = await Promise.all(input.deliveries.map((delivery) => this.globalReceiptMatches(delivery)));
17968
18969
  if (joined.some((value) => !value)) {
17969
- return error8(409, "outbox_global_receipt_unverified", "Global receipt and membership must be read back before source acknowledgement");
18970
+ return error9(409, "outbox_global_receipt_unverified", "Global receipt and membership must be read back before source acknowledgement");
17970
18971
  }
17971
18972
  } catch {
17972
- return error8(503, "outbox_global_receipt_unavailable", "Global receipt verification is unavailable");
18973
+ return error9(503, "outbox_global_receipt_unavailable", "Global receipt verification is unavailable");
17973
18974
  }
17974
18975
  const result2 = await this.ctx.storage.transaction(async (txn) => {
17975
18976
  if (this.sqlStorage() !== void 0) {
@@ -18008,7 +19009,7 @@ var TagDurableObject = class {
18008
19009
  }
18009
19010
  return { status: 200, body: { marked, idempotent: marked === 0 } };
18010
19011
  });
18011
- return json10(result2.body, result2.status);
19012
+ return json11(result2.body, result2.status);
18012
19013
  }
18013
19014
  /**
18014
19015
  * The delivery handoff reads its universe from `tag_outbox_obligation`.
@@ -18147,7 +19148,7 @@ var TagDurableObject = class {
18147
19148
  async acquireRepairLease(tag, body) {
18148
19149
  const parsed = repairAcquireFrom(body, tag);
18149
19150
  if (parsed.value === void 0) {
18150
- return error8(400, "invalid_repair_acquire", parsed.error ?? "Invalid repair acquire request");
19151
+ return error9(400, "invalid_repair_acquire", parsed.error ?? "Invalid repair acquire request");
18151
19152
  }
18152
19153
  const input = parsed.value;
18153
19154
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -18193,12 +19194,12 @@ var TagDurableObject = class {
18193
19194
  }
18194
19195
  };
18195
19196
  });
18196
- return json10(result2.body, result2.status);
19197
+ return json11(result2.body, result2.status);
18197
19198
  }
18198
19199
  async renewRepairLease(tag, body) {
18199
19200
  const parsed = repairLeaseFrom(body);
18200
19201
  if (parsed.value === void 0) {
18201
- return error8(400, "invalid_repair_renew", parsed.error ?? "Invalid repair renew request");
19202
+ return error9(400, "invalid_repair_renew", parsed.error ?? "Invalid repair renew request");
18202
19203
  }
18203
19204
  const input = parsed.value;
18204
19205
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -18222,12 +19223,12 @@ var TagDurableObject = class {
18222
19223
  }
18223
19224
  };
18224
19225
  });
18225
- return json10(result2.body, result2.status);
19226
+ return json11(result2.body, result2.status);
18226
19227
  }
18227
19228
  async unionRepairScope(tag, body) {
18228
19229
  const parsed = repairScopeUnionFrom(body, tag);
18229
19230
  if (parsed.value === void 0) {
18230
- return error8(400, "invalid_repair_scope_union", parsed.error ?? "Invalid repair scope union request");
19231
+ return error9(400, "invalid_repair_scope_union", parsed.error ?? "Invalid repair scope union request");
18231
19232
  }
18232
19233
  const input = parsed.value;
18233
19234
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -18263,12 +19264,12 @@ var TagDurableObject = class {
18263
19264
  body: { status: "repair-scope-unioned", scopeVersion: updated.repairScopeVersion, scope: updated.repairScope }
18264
19265
  };
18265
19266
  });
18266
- return json10(result2.body, result2.status);
19267
+ return json11(result2.body, result2.status);
18267
19268
  }
18268
19269
  async applyRepair(tag, body) {
18269
19270
  const parsed = repairApplyFrom(body, tag);
18270
19271
  if (parsed.value === void 0) {
18271
- return error8(400, "invalid_repair_apply", parsed.error ?? "Invalid repair apply request");
19272
+ return error9(400, "invalid_repair_apply", parsed.error ?? "Invalid repair apply request");
18272
19273
  }
18273
19274
  const input = parsed.value;
18274
19275
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -18349,12 +19350,12 @@ var TagDurableObject = class {
18349
19350
  body: { status: branch, idempotent: false, head: (updatedRecord ?? record).head, version: (updatedRecord ?? record).version }
18350
19351
  };
18351
19352
  });
18352
- return json10(result2.body, result2.status);
19353
+ return json11(result2.body, result2.status);
18353
19354
  }
18354
19355
  async auditRepair(tag, body) {
18355
19356
  const parsed = repairAuditFrom(body, tag);
18356
19357
  if (parsed.value === void 0) {
18357
- return error8(400, "invalid_repair_audit", parsed.error ?? "Invalid repair audit request");
19358
+ return error9(400, "invalid_repair_audit", parsed.error ?? "Invalid repair audit request");
18358
19359
  }
18359
19360
  const input = parsed.value;
18360
19361
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -18391,12 +19392,12 @@ var TagDurableObject = class {
18391
19392
  await txn.put(REPAIR_FACTS_KEY, { ...facts, audits: [...facts.audits, audit] });
18392
19393
  return { status: 200, body: { status: "repair-audited", idempotent: false, branch: audit.branch } };
18393
19394
  });
18394
- return json10(result2.body, result2.status);
19395
+ return json11(result2.body, result2.status);
18395
19396
  }
18396
19397
  async clearRepairFence(tag, body) {
18397
19398
  const parsed = repairClearFrom(body);
18398
19399
  if (parsed.value === void 0) {
18399
- return error8(400, "invalid_repair_clear", parsed.error ?? "Invalid repair clear request");
19400
+ return error9(400, "invalid_repair_clear", parsed.error ?? "Invalid repair clear request");
18400
19401
  }
18401
19402
  const input = parsed.value;
18402
19403
  const result2 = await this.ctx.storage.transaction(async (txn) => {
@@ -18427,16 +19428,16 @@ var TagDurableObject = class {
18427
19428
  });
18428
19429
  return { status: 200, body: { status: "repair-fence-cleared", idempotent: false, version: updated.version } };
18429
19430
  });
18430
- return json10(result2.body, result2.status);
19431
+ return json11(result2.body, result2.status);
18431
19432
  }
18432
19433
  async setClockOffset(tag, body) {
18433
- if (!isObject11(body)) {
18434
- return error8(400, "invalid_tag_clock", "offsetMs or nowMs must be a safe integer");
19434
+ if (!isObject12(body)) {
19435
+ return error9(400, "invalid_tag_clock", "offsetMs or nowMs must be a safe integer");
18435
19436
  }
18436
19437
  const nowMs = body.nowMs;
18437
19438
  const offsetMs = body.offsetMs;
18438
19439
  if (!isSafeInteger(nowMs) && !isSafeInteger(offsetMs)) {
18439
- return error8(400, "invalid_tag_clock", "offsetMs or nowMs must be a safe integer");
19440
+ return error9(400, "invalid_tag_clock", "offsetMs or nowMs must be a safe integer");
18440
19441
  }
18441
19442
  const result2 = await this.ctx.storage.transaction(async (txn) => {
18442
19443
  const loaded = await this.recordFor(txn, tag);
@@ -18454,7 +19455,7 @@ var TagDurableObject = class {
18454
19455
  }
18455
19456
  };
18456
19457
  });
18457
- return json10(result2.body, result2.status);
19458
+ return json11(result2.body, result2.status);
18458
19459
  }
18459
19460
  async runAlarm() {
18460
19461
  const due = await this.ctx.storage.transaction(async (txn) => {
@@ -18573,16 +19574,16 @@ var TagStateCheckpointFault = class extends Error {
18573
19574
  this.name = "TagStateCheckpointFault";
18574
19575
  }
18575
19576
  };
18576
- function json11(body, status = 200) {
19577
+ function json12(body, status = 200) {
18577
19578
  return new Response(JSON.stringify(body), {
18578
19579
  status,
18579
19580
  headers: { "content-type": "application/json; charset=utf-8" }
18580
19581
  });
18581
19582
  }
18582
- function error9(status, code, message) {
18583
- return json11({ code, error: message }, status);
19583
+ function error10(status, code, message) {
19584
+ return json12({ code, error: message }, status);
18584
19585
  }
18585
- function isObject12(value) {
19586
+ function isObject13(value) {
18586
19587
  return typeof value === "object" && value !== null && !Array.isArray(value);
18587
19588
  }
18588
19589
  function isNonEmptyString12(value) {
@@ -18597,7 +19598,7 @@ function sqlNullableString2(value, column) {
18597
19598
  return sqlString2(value, column);
18598
19599
  }
18599
19600
  function parseIdentity(value) {
18600
- if (!isObject12(value) || !isNonEmptyString12(value.serviceId) || !isNonEmptyString12(value.tag) || !isNonEmptyString12(value.projectorId)) {
19601
+ if (!isObject13(value) || !isNonEmptyString12(value.serviceId) || !isNonEmptyString12(value.tag) || !isNonEmptyString12(value.projectorId)) {
18601
19602
  return void 0;
18602
19603
  }
18603
19604
  return { serviceId: value.serviceId, tag: value.tag, projectorId: value.projectorId };
@@ -18659,17 +19660,17 @@ var TagStateDurableObject = class {
18659
19660
  async fetch(request) {
18660
19661
  const url = new URL(request.url);
18661
19662
  if (request.method !== "POST" || url.pathname !== "/read") {
18662
- return error9(404, "tag_state_route_not_found", "TagState route was not found");
19663
+ return error10(404, "tag_state_route_not_found", "TagState route was not found");
18663
19664
  }
18664
19665
  let body;
18665
19666
  try {
18666
19667
  body = await request.json();
18667
19668
  } catch {
18668
- return error9(400, "tag_state_validation_error", "TagState request must be JSON");
19669
+ return error10(400, "tag_state_validation_error", "TagState request must be JSON");
18669
19670
  }
18670
19671
  const identity2 = parseIdentity(body);
18671
19672
  if (identity2 === void 0) {
18672
- return error9(400, "tag_state_validation_error", "TagState identity requires serviceId, tag, and projectorId");
19673
+ return error10(400, "tag_state_validation_error", "TagState identity requires serviceId, tag, and projectorId");
18673
19674
  }
18674
19675
  return await this.read(identity2);
18675
19676
  }
@@ -18691,16 +19692,16 @@ var TagStateDurableObject = class {
18691
19692
  return await this.continueRebuild(identity2, projector, cache);
18692
19693
  } catch (caught) {
18693
19694
  if (caught instanceof TagStateIdentityConflict) {
18694
- return error9(409, "tag_state_identity_conflict", "TagState Durable Object identity changed");
19695
+ return error10(409, "tag_state_identity_conflict", "TagState Durable Object identity changed");
18695
19696
  }
18696
19697
  if (caught instanceof TagStateUnknownProjector) {
18697
- return error9(404, "tag_state_unknown_projector", "TagState projector is not registered");
19698
+ return error10(404, "tag_state_unknown_projector", "TagState projector is not registered");
18698
19699
  }
18699
19700
  if (caught instanceof TagStateRegistryFailure) {
18700
- return error9(503, "tag_state_projector_registry_failure", "TagState projector registry is unavailable");
19701
+ return error10(503, "tag_state_projector_registry_failure", "TagState projector registry is unavailable");
18701
19702
  }
18702
19703
  if (caught instanceof TagStateSourceFailure) {
18703
- return error9(caught.status, "tag_state_source_frontier_failure", "TagState source frontier could not be read");
19704
+ return error10(caught.status, "tag_state_source_frontier_failure", "TagState source frontier could not be read");
18704
19705
  }
18705
19706
  if (caught instanceof TagStateCacheCorruption) {
18706
19707
  try {
@@ -18708,21 +19709,21 @@ var TagStateDurableObject = class {
18708
19709
  this.beginRebuild(projector, "cache-corrupt");
18709
19710
  } catch (rebuildFailure) {
18710
19711
  if (rebuildFailure instanceof TagStateRegistryFailure) {
18711
- return error9(503, "tag_state_projector_registry_failure", "TagState projector registry is unavailable");
19712
+ return error10(503, "tag_state_projector_registry_failure", "TagState projector registry is unavailable");
18712
19713
  }
18713
19714
  }
18714
- return error9(409, "tag_state_cache_corrupt", "TagState cache is corrupt and is rebuilding");
19715
+ return error10(409, "tag_state_cache_corrupt", "TagState cache is corrupt and is rebuilding");
18715
19716
  }
18716
19717
  if (caught instanceof TagStateCheckpointFault) {
18717
- return error9(503, "tag_state_rebuild_interrupted", "TagState replay checkpoint was interrupted");
19718
+ return error10(503, "tag_state_rebuild_interrupted", "TagState replay checkpoint was interrupted");
18718
19719
  }
18719
- return error9(503, "tag_state_unavailable", "TagState cache is unavailable");
19720
+ return error10(503, "tag_state_unavailable", "TagState cache is unavailable");
18720
19721
  }
18721
19722
  }
18722
19723
  async beginDeltaOrRespondReady(identity2, projector, cache) {
18723
19724
  const page = await this.readSource(identity2, cache.lastSuid, void 0);
18724
19725
  if (page.events.length === 0 && page.completeThrough !== null) {
18725
- return json11(this.success(projector, cache.stateJson, cache.lastSuid));
19726
+ return json12(this.success(projector, cache.stateJson, cache.lastSuid));
18726
19727
  }
18727
19728
  const rebuild = this.beginRebuild(projector, "normal-delta", {
18728
19729
  cursor: cache.lastSuid,
@@ -18771,9 +19772,9 @@ var TagStateDurableObject = class {
18771
19772
  });
18772
19773
  if (this.g46CheckpointFault === "after-checkpoint") throw new TagStateCheckpointFault();
18773
19774
  if (!complete) {
18774
- return error9(503, "tag_state_rebuild_in_progress", "TagState replay is rebuilding to its frozen frontier");
19775
+ return error10(503, "tag_state_rebuild_in_progress", "TagState replay is rebuilding to its frozen frontier");
18775
19776
  }
18776
- return json11(this.success(projector, accumulatorJson, page.completeThrough));
19777
+ return json12(this.success(projector, accumulatorJson, page.completeThrough));
18777
19778
  }
18778
19779
  success(projector, stateJson, lastSortedUniqueId) {
18779
19780
  try {
@@ -18830,7 +19831,7 @@ var TagStateDurableObject = class {
18830
19831
  }
18831
19832
  }
18832
19833
  assertSourcePage(cursor, expectedThrough, page) {
18833
- if (!isObject12(page) || !Array.isArray(page.events) || typeof page.lastSortableUniqueId !== "string" || typeof page.through !== "string" || page.completeThrough !== null && typeof page.completeThrough !== "string") {
19834
+ if (!isObject13(page) || !Array.isArray(page.events) || typeof page.lastSortableUniqueId !== "string" || typeof page.through !== "string" || page.completeThrough !== null && typeof page.completeThrough !== "string") {
18834
19835
  throw new TagStateSourceFailure(503, new Error("TagState source response was malformed"));
18835
19836
  }
18836
19837
  if (expectedThrough !== void 0 && expectedThrough !== null && page.through !== expectedThrough) {
@@ -19029,12 +20030,12 @@ function encodedCommitSnapshotLogBytes(record) {
19029
20030
  function assertCommitSnapshotLogSize(record) {
19030
20031
  const encodedBytes2 = encodedCommitSnapshotLogBytes(record);
19031
20032
  if (encodedBytes2 > COMMIT_SNAPSHOT_LOG_BYTE_BUDGET) {
19032
- const error10 = new Error(
20033
+ const error11 = new Error(
19033
20034
  `Commit snapshot log is ${encodedBytes2} bytes; budget is ${COMMIT_SNAPSHOT_LOG_BYTE_BUDGET} bytes`
19034
20035
  );
19035
- error10.code = "commit-snapshot-log-size";
19036
- error10.encodedBytes = encodedBytes2;
19037
- throw error10;
20036
+ error11.code = "commit-snapshot-log-size";
20037
+ error11.encodedBytes = encodedBytes2;
20038
+ throw error11;
19038
20039
  }
19039
20040
  return encodedBytes2;
19040
20041
  }
@@ -19053,8 +20054,8 @@ function createCommitTraceConsoleSink(options = {}) {
19053
20054
  if (record === void 0) return;
19054
20055
  try {
19055
20056
  assertCommitSnapshotLogSize(record);
19056
- } catch (error10) {
19057
- const encodedBytes2 = typeof error10 === "object" && error10 !== null && "encodedBytes" in error10 && typeof error10.encodedBytes === "number" ? error10.encodedBytes : encodedCommitSnapshotLogBytes(record);
20057
+ } catch (error11) {
20058
+ const encodedBytes2 = typeof error11 === "object" && error11 !== null && "encodedBytes" in error11 && typeof error11.encodedBytes === "number" ? error11.encodedBytes : encodedCommitSnapshotLogBytes(record);
19058
20059
  reportRejectedSize(Object.freeze({
19059
20060
  schema: COMMIT_SNAPSHOT_LOG_SCHEMA,
19060
20061
  event: "commit.snapshot-size-rejected",
@@ -19063,43 +20064,13 @@ function createCommitTraceConsoleSink(options = {}) {
19063
20064
  encodedBytes: encodedBytes2,
19064
20065
  byteBudget: COMMIT_SNAPSHOT_LOG_BYTE_BUDGET
19065
20066
  }));
19066
- throw error10;
20067
+ throw error11;
19067
20068
  }
19068
20069
  log(record);
19069
20070
  }
19070
20071
  });
19071
20072
  }
19072
20073
 
19073
- // src/scope/ControlRouteScope.ts
19074
- function response2(status, code, error10) {
19075
- return new Response(JSON.stringify({ code, error: error10 }), {
19076
- status,
19077
- headers: { "content-type": "application/json; charset=utf-8" }
19078
- });
19079
- }
19080
- function scopeIdentityMissingResponse() {
19081
- return response2(503, "scope.identity_missing", "A deployment service identity is required for this scope");
19082
- }
19083
- function enforceControlRouteScope(input) {
19084
- let actual;
19085
- try {
19086
- actual = input.provider.forRequest(input.request, input.requestOptions).serviceId;
19087
- } catch (caught) {
19088
- if (caught instanceof ServiceIdentityMissingError) {
19089
- console.error({ schema: "sdt.scope/v1", code: "scope.identity_missing", route: input.route });
19090
- return { response: scopeIdentityMissingResponse() };
19091
- }
19092
- throw caught;
19093
- }
19094
- if (input.pathServiceId !== actual) {
19095
- console.warn({ schema: "sdt.scope/v1", code: "scope.mismatch", route: input.route });
19096
- return {
19097
- response: response2(403, "scope.mismatch", "The path service identity is not authorized for this deployment")
19098
- };
19099
- }
19100
- return { serviceId: actual };
19101
- }
19102
-
19103
20074
  // src/diagnostics/G65DirectRing.ts
19104
20075
  var G65_DIRECT_RING_BUDGET_MS = 100;
19105
20076
  var G65_DIRECT_RING_CLOCK_ORIGIN = "Date.now epoch ms";
@@ -19165,7 +20136,7 @@ async function markG65DirectApplyStarted(database, message, observedAt) {
19165
20136
  WHERE service_id = ? AND event_id = ? AND attempt_id = ?
19166
20137
  `).bind(observedAt, message.serviceId, message.eventId, message.attemptId).run();
19167
20138
  }
19168
- async function markG65DirectApplyFinished(database, message, observedAt, outcome, error10) {
20139
+ async function markG65DirectApplyFinished(database, message, observedAt, outcome, error11) {
19169
20140
  validateTimestamp(observedAt, "apply finish");
19170
20141
  if (outcome.length === 0) throw new Error("G65 direct apply outcome must be non-empty");
19171
20142
  await database.prepare(`
@@ -19177,13 +20148,109 @@ async function markG65DirectApplyFinished(database, message, observedAt, outcome
19177
20148
  `).bind(
19178
20149
  observedAt,
19179
20150
  outcome,
19180
- error10 ?? null,
20151
+ error11 ?? null,
19181
20152
  message.serviceId,
19182
20153
  message.eventId,
19183
20154
  message.attemptId
19184
20155
  ).run();
19185
20156
  }
19186
20157
 
20158
+ // src/shard/ShardRotation.ts
20159
+ var ShardRotationError = class extends Error {
20160
+ diagnostic;
20161
+ constructor(diagnostic) {
20162
+ super(diagnostic.code);
20163
+ this.name = "ShardRotationError";
20164
+ this.diagnostic = diagnostic;
20165
+ }
20166
+ };
20167
+ function fail(code, path, reason) {
20168
+ throw new ShardRotationError({ code, path, reason });
20169
+ }
20170
+ function createRotationState(active2) {
20171
+ if (typeof active2 !== "string" || active2.length === 0) fail("ACTIVE_COUNT", "active", "active-missing");
20172
+ return { sealed: [], active: active2, ledger: [] };
20173
+ }
20174
+ function assertStrictlyBefore(lastD1_1, firstD1_2) {
20175
+ assertSortableUniqueId(lastD1_1);
20176
+ assertSortableUniqueId(firstD1_2);
20177
+ if (compareSortableUniqueId(lastD1_1, firstD1_2) >= 0) {
20178
+ fail("ORDER_INVARIANT", "last(D1-1)<first(D1-2)", "order-invariant");
20179
+ }
20180
+ }
20181
+ function maxSortableUniqueId(values) {
20182
+ if (values.length === 0) fail("SEAL_MAX_MISSING", "d1-1", "seal-max-missing");
20183
+ let max = assertSortableUniqueId(values[0]).value;
20184
+ for (let i = 1; i < values.length; i += 1) {
20185
+ const next = assertSortableUniqueId(values[i]).value;
20186
+ if (next > max) max = next;
20187
+ }
20188
+ return max;
20189
+ }
20190
+ function rotateAppend(state, sealedId, shardSuids, nextActiveId) {
20191
+ if (sealedId !== state.active) fail("UNKNOWN_SHARD", sealedId, "unknown-shard");
20192
+ if (typeof nextActiveId !== "string" || nextActiveId.length === 0 || nextActiveId === sealedId) {
20193
+ fail("ACTIVE_COUNT", "active", "active-count");
20194
+ }
20195
+ if (state.sealed.some((entry) => entry.id === nextActiveId)) {
20196
+ fail("ACTIVE_COUNT", nextActiveId, "active-already-sealed");
20197
+ }
20198
+ if (state.sealed.some((entry) => entry.id === sealedId)) fail("IDENTITY_SWAP", sealedId, "identity-swap");
20199
+ const lastSuid = maxSortableUniqueId(shardSuids);
20200
+ return {
20201
+ sealed: [...state.sealed, { id: sealedId, lastSuid }],
20202
+ active: nextActiveId,
20203
+ ledger: state.ledger
20204
+ };
20205
+ }
20206
+ function replaceSealedIdentity(state, index, nextId) {
20207
+ if (index < 0 || index >= state.sealed.length) fail("UNKNOWN_SHARD", "sealed", "unknown-shard");
20208
+ fail("IDENTITY_SWAP", state.sealed[index].id, `identity-swap:${nextId}`);
20209
+ }
20210
+ function refuseSealedWrite(state, shardId) {
20211
+ if (state.sealed.some((entry) => entry.id === shardId)) fail("SEALED_WRITE", shardId, "sealed-write");
20212
+ }
20213
+ function admitActiveWrite(state, shardId, firstOrNextSuid) {
20214
+ assertSortableUniqueId(firstOrNextSuid);
20215
+ refuseSealedWrite(state, shardId);
20216
+ if (shardId !== state.active) fail("UNKNOWN_SHARD", shardId, "unknown-shard");
20217
+ if (state.sealed.length === 0) return;
20218
+ const previous = state.sealed[state.sealed.length - 1];
20219
+ assertStrictlyBefore(previous.lastSuid, firstOrNextSuid);
20220
+ }
20221
+ function recordLateArrival(state, sealedShardId, suid) {
20222
+ assertSortableUniqueId(suid);
20223
+ const sealed = state.sealed.find((entry) => entry.id === sealedShardId);
20224
+ if (sealed === void 0) fail("UNKNOWN_SHARD", sealedShardId, "unknown-shard");
20225
+ if (compareSortableUniqueId(suid, sealed.lastSuid) > 0) {
20226
+ fail("ORDER_INVARIANT", sealedShardId, "not-late-arrival");
20227
+ }
20228
+ return {
20229
+ ...state,
20230
+ ledger: [...state.ledger, { shardId: sealed.id, suid, reason: "sealed-range" }]
20231
+ };
20232
+ }
20233
+ var SILENT_MERGE_TOKENS = [
20234
+ ["merge", "Ledger", "Into", "Sealed"],
20235
+ ["merge", "OnRead", "Sealed"],
20236
+ ["silent", "Merge", "Ledger"],
20237
+ ["ledger", ".concat(", "sealed"],
20238
+ ["sealed", ".concat(", "ledger"]
20239
+ ];
20240
+ function assertNoSilentLedgerMerge(source) {
20241
+ const lowered = source.toLowerCase();
20242
+ for (const token of SILENT_MERGE_TOKENS) {
20243
+ const needle = token.join("").toLowerCase();
20244
+ if (lowered.includes(needle)) fail("SILENT_MERGE", "ledger", "silent-merge");
20245
+ }
20246
+ }
20247
+ function refuseSilentLedgerMerge() {
20248
+ fail("SILENT_MERGE", "ledger", "silent-merge");
20249
+ }
20250
+ function refuseSafeWindowSeal() {
20251
+ fail("SAFEWINDOW_SEAL", "safe-window", "safewindow-seal");
20252
+ }
20253
+
19187
20254
  // src/cloudflare.ts
19188
20255
  function cloudflareCommitTraceProvider(request, env) {
19189
20256
  const versionId = env.WORKER_VERSION?.id;
@@ -19224,6 +20291,22 @@ function createCloudflareOnlyRuntimeWorker(options = {}) {
19224
20291
  const storeProvider = createD1StoreProvider();
19225
20292
  return {
19226
20293
  async fetch(request, env, ctx) {
20294
+ const url = new URL(request.url);
20295
+ if (isIncidentMaintenancePath(url.pathname)) {
20296
+ return handleIncidentMaintenance(request, env, options.serviceIdentityProvider ?? envServiceIdentity(env));
20297
+ }
20298
+ const operatorRepair = url.pathname === "/operator/repair";
20299
+ const operatorBootstrap = url.pathname.startsWith("/operator/bootstrap/");
20300
+ if (operatorRepair) {
20301
+ const methodDenied = nonPostOperatorRepairResponse(request);
20302
+ if (methodDenied !== void 0) return methodDenied;
20303
+ const denied = await authenticateOperatorRepair(request, env.REPAIR_OPERATOR_TOKEN);
20304
+ if (denied !== void 0) return denied;
20305
+ }
20306
+ if (operatorBootstrap) {
20307
+ const denied = await authenticateOperatorBootstrap(request, env.REPAIR_OPERATOR_TOKEN);
20308
+ if (denied !== void 0) return denied;
20309
+ }
19227
20310
  const serviceIdentity = options.serviceIdentityProvider ?? envServiceIdentity(env);
19228
20311
  const requestIdentityOptions = { allowG11Verification: env.G11_VERIFICATION_ENABLED === "true" };
19229
20312
  let requestServiceId;
@@ -19233,7 +20316,6 @@ function createCloudflareOnlyRuntimeWorker(options = {}) {
19233
20316
  return scopeIdentityMissingResponse();
19234
20317
  }
19235
20318
  const durableHopObserver = createG60DurableHopObserver(env.D1, (promise) => ctx.waitUntil(promise));
19236
- const url = new URL(request.url);
19237
20319
  if (url.pathname === "/api/sekiban/serialized/commit") {
19238
20320
  return handleSerializedCommit(request, env, {
19239
20321
  domainDeliveryClass: options.config?.deliveryClass,
@@ -19277,19 +20359,26 @@ function createCloudflareOnlyRuntimeWorker(options = {}) {
19277
20359
  serviceIdentityProvider: serviceIdentity
19278
20360
  });
19279
20361
  }
19280
- if (url.pathname === "/operator/repair") {
19281
- return handleOperatorRepair(request, env, cloudflareTracing(ctx), serviceIdentity);
20362
+ if (operatorRepair) {
20363
+ return handleAuthorizedOperatorRepair(request, env, cloudflareTracing(ctx), serviceIdentity);
19282
20364
  }
19283
- if (url.pathname.startsWith("/operator/bootstrap/")) {
19284
- return handleOperatorBootstrap(request, env, storeProvider, {
20365
+ if (operatorBootstrap) {
20366
+ return handleAuthorizedOperatorBootstrap(request, env, storeProvider, {
19285
20367
  afterVerifyBeforeReady: options.afterBootstrapVerify === void 0 ? void 0 : ({ serviceId }) => options.afterBootstrapVerify({ serviceId, env })
19286
20368
  });
19287
20369
  }
19288
20370
  if (url.pathname === "/internal/downstream/drain" && request.method === "POST") {
19289
20371
  if (durableHopObserver === void 0) {
19290
- return handleOutboxDrainRequest(request, env, { acknowledgement: "global-receipt" });
20372
+ return handleOutboxDrainRequest(request, env, {
20373
+ acknowledgement: "global-receipt",
20374
+ serviceIdentityProvider: serviceIdentity
20375
+ });
19291
20376
  }
19292
- return handleOutboxDrainRequest(request, env, { acknowledgement: "global-receipt", durableHopObserver });
20377
+ return handleOutboxDrainRequest(request, env, {
20378
+ acknowledgement: "global-receipt",
20379
+ durableHopObserver,
20380
+ serviceIdentityProvider: serviceIdentity
20381
+ });
19293
20382
  }
19294
20383
  if (url.pathname === "/internal/projection/lag") {
19295
20384
  return handleProjectionLag(request, env, composition.projectors, storeProvider, serviceIdentity);
@@ -19440,14 +20529,20 @@ export {
19440
20529
  MAX_SERVICE_BINDING_INVOCATIONS_PER_REQUEST,
19441
20530
  ScopeNameError,
19442
20531
  ServiceIdentityMissingError,
20532
+ ShardRotationError,
19443
20533
  TEST_SERVICE_ID_HEADER,
19444
20534
  TagDurableObject2 as TagDurableObject,
19445
20535
  TagStateDurableObject2 as TagStateDurableObject,
20536
+ admitActiveWrite,
20537
+ assertNoSilentLedgerMerge,
20538
+ assertStrictlyBefore,
19446
20539
  buildScopeName,
20540
+ checkConfiguredBearer,
19447
20541
  classifyDirectDoorbellFailure,
19448
20542
  cleanupG42JournalProbeTrial,
19449
20543
  createCloudflareOnlyRuntimeWorker,
19450
20544
  createG60DurableHopObserver,
20545
+ createRotationState,
19451
20546
  cloudflare_default as default,
19452
20547
  deliveryCorrelationId,
19453
20548
  downstreamEnvelopeBytes,
@@ -19460,6 +20555,7 @@ export {
19460
20555
  isScopeServiceId,
19461
20556
  markG65DirectApplyFinished,
19462
20557
  markG65DirectApplyStarted,
20558
+ maxSortableUniqueId,
19463
20559
  measureG42JournalProbeTrial,
19464
20560
  observeFaultBarrier,
19465
20561
  observeG60UnsafeWriter,
@@ -19477,8 +20573,14 @@ export {
19477
20573
  recordDurableUnsafeWriterBoundary,
19478
20574
  recordFirstUnsafeVisibleRead,
19479
20575
  recordG65DirectRing,
20576
+ recordLateArrival,
20577
+ refuseSafeWindowSeal,
20578
+ refuseSealedWrite,
20579
+ refuseSilentLedgerMerge,
20580
+ replaceSealedIdentity,
19480
20581
  requestServiceIdentity,
19481
20582
  requireServiceIdentity,
20583
+ rotateAppend,
19482
20584
  runG42JournalProbeTrial,
19483
20585
  scheduledLiveProjectionMaximumSuid,
19484
20586
  scopeIdFor,