@lunora/codegen 1.0.0-alpha.335 → 1.0.0-alpha.337

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 (91) hide show
  1. package/dist/index.d.mts +26 -1
  2. package/dist/index.d.ts +26 -1
  3. package/dist/index.mjs +1 -1
  4. package/dist/packem_shared/{AGENTS_FILENAME-8zoeGNsB.mjs → AGENTS_FILENAME-isdHqPIt.mjs} +1 -1
  5. package/dist/packem_shared/CONTAINERS_FILENAME-mK4cZpcz.mjs +1 -0
  6. package/dist/packem_shared/{DEFAULT_TARGET-CDksdcYc.mjs → DEFAULT_TARGET-3OLdJhTj.mjs} +1 -1
  7. package/dist/packem_shared/{FLAGS_FILENAME-Cwq0B2Nl.mjs → FLAGS_FILENAME-BQk3SX8D.mjs} +1 -1
  8. package/dist/packem_shared/GENERATED_HEADER-BXK9A_wP.mjs +1 -0
  9. package/dist/packem_shared/LUNORA_ERROR_CODES-CIAJQeKB.mjs +1 -0
  10. package/dist/packem_shared/{MUTATORS_FILENAME-DZFH7a9G.mjs → MUTATORS_FILENAME-Cy9h3EVW.mjs} +1 -1
  11. package/dist/packem_shared/{NOTIFY_FILENAME-DZIt-rb0.mjs → NOTIFY_FILENAME-9to_l_Kh.mjs} +1 -1
  12. package/dist/packem_shared/{OPENRPC_VERSION-CeEGdAZ9.mjs → OPENRPC_VERSION-l4HD4osw.mjs} +1 -1
  13. package/dist/packem_shared/{QUEUES_FILENAME-EvfCmmv6.mjs → QUEUES_FILENAME-Civ-7SiI.mjs} +1 -1
  14. package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-6cfIWExE.mjs +31 -0
  15. package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs +2 -0
  16. package/dist/packem_shared/{SHAPES_FILENAME-Ciu5tx7B.mjs → SHAPES_FILENAME-DVJbfDZ8.mjs} +1 -1
  17. package/dist/packem_shared/SchemaSnapshotParseError-H9eQX4ui.mjs +18 -0
  18. package/dist/packem_shared/{WORKFLOWS_FILENAME-C5tz9gMh.mjs → WORKFLOWS_FILENAME-kXq07aGl.mjs} +1 -1
  19. package/dist/packem_shared/{attribution-RI-H1KPm.mjs → attribution-CG8-kUcl.mjs} +1 -1
  20. package/dist/packem_shared/{buildOpenApiDocument-BBao-3vL.mjs → buildOpenApiDocument-DWdj2jvW.mjs} +1 -1
  21. package/dist/packem_shared/capabilitiesUsedBy-C-7D7vlH.mjs +1 -0
  22. package/dist/packem_shared/chain-74gjwZMP.mjs +1 -0
  23. package/dist/packem_shared/{classify-procedure-call-C5JY2w5V.mjs → classify-procedure-call-BkaeM9Ej.mjs} +1 -1
  24. package/dist/packem_shared/{context-property-calls-M6Oo1xQT.mjs → context-property-calls-dFjpeIlP.mjs} +1 -1
  25. package/dist/packem_shared/{context-root-DQd48e1F.mjs → context-root-CNR6TAsP.mjs} +1 -1
  26. package/dist/packem_shared/{createCodegenProject-C-fKC9h4.mjs → createCodegenProject-R4so-yTU.mjs} +1 -1
  27. package/dist/packem_shared/{database-calls-BNoSJRFy.mjs → database-calls-UPlhi3Ks.mjs} +1 -1
  28. package/dist/packem_shared/discoverAuthApiCalls-CScPrUD-.mjs +1 -0
  29. package/dist/packem_shared/discoverCrons-B1_NUt19.mjs +1 -0
  30. package/dist/packem_shared/{discoverFunctions-CJu5EH_G.mjs → discoverFunctions-DkPOc8b9.mjs} +1 -1
  31. package/dist/packem_shared/{discoverHttpRoutes-MrMxIY66.mjs → discoverHttpRoutes-DCDgDIYv.mjs} +1 -1
  32. package/dist/packem_shared/discoverHyperdriveCalls-CL-d0IVo.mjs +1 -0
  33. package/dist/packem_shared/{discoverInserts-Boh6WAYw.mjs → discoverInserts-BcoTjXqI.mjs} +1 -1
  34. package/dist/packem_shared/discoverMaskProcedures-Bw-BOIbA.mjs +1 -0
  35. package/dist/packem_shared/{discoverMigrations-BMdGxHeq.mjs → discoverMigrations-BWxx8Wv9.mjs} +1 -1
  36. package/dist/packem_shared/{discoverNondeterministicCalls-c9xenrIN.mjs → discoverNondeterministicCalls-3INW8oqs.mjs} +1 -1
  37. package/dist/packem_shared/{discoverQueries-o_00HnBB.mjs → discoverQueries-CxQRVuIV.mjs} +1 -1
  38. package/dist/packem_shared/discoverR2sqlCalls-B4oeTYEM.mjs +1 -0
  39. package/dist/packem_shared/{discoverRlsMetadata-C7J8dgVz.mjs → discoverRlsMetadata-D0B4nCmG.mjs} +1 -1
  40. package/dist/packem_shared/{discoverRlsProcedures-Di3VEk-D.mjs → discoverRlsProcedures-Cl6UKT7L.mjs} +1 -1
  41. package/dist/packem_shared/{discoverSandboxUsage-CrhZZJZS.mjs → discoverSandboxUsage--Z1vx7GM.mjs} +1 -1
  42. package/dist/packem_shared/discoverSchema-Cwt-DQgh.mjs +1 -0
  43. package/dist/packem_shared/{discoverStorageRulesMetadata-BFCmbsIN.mjs → discoverStorageRulesMetadata-CitX6ziW.mjs} +1 -1
  44. package/dist/packem_shared/{emitAgents-CR2_X_ov.mjs → emitAgents--VDKoet4.mjs} +1 -1
  45. package/dist/packem_shared/{emitApi-CDgIPAG2.mjs → emitApi-c14__tie.mjs} +24 -24
  46. package/dist/packem_shared/{emitApp-DuJW6LKD.mjs → emitApp-BL16wvE9.mjs} +1 -1
  47. package/dist/packem_shared/{emitCrons-BQW2lviZ.mjs → emitCrons-lc-hnJYn.mjs} +1 -1
  48. package/dist/packem_shared/{emitDataModel-BskFt9Wv.mjs → emitDataModel-CuFqq97x.mjs} +1 -1
  49. package/dist/packem_shared/{emitDrizzleSchema-DitcRZ1a.mjs → emitDrizzleSchema-bct1OuH5.mjs} +1 -1
  50. package/dist/packem_shared/{emitFunctions-Cd0Tuw73.mjs → emitFunctions-CkBPtGDF.mjs} +71 -65
  51. package/dist/packem_shared/{emitServer-D1vA5_X1.mjs → emitServer-CGUhLmlG.mjs} +1 -1
  52. package/dist/packem_shared/emitShard-fpKA7Svs.mjs +1 -0
  53. package/dist/packem_shared/{exported-procedure-chains-Bol_VtzO.mjs → exported-procedure-chains-D1WlRfqJ.mjs} +1 -1
  54. package/dist/packem_shared/{fingerprintSchemaSources-BdFj8vPc.mjs → fingerprintSchemaSources-BKXkgkj4.mjs} +1 -1
  55. package/dist/packem_shared/{handler-reference-8w_VU4XY.mjs → handler-reference-CClSR4bi.mjs} +1 -1
  56. package/dist/packem_shared/index-CN8FVvr-.mjs +1 -0
  57. package/dist/packem_shared/{isTestPath-Cdv_LoVU.mjs → isTestPath-C3QumE88.mjs} +1 -1
  58. package/dist/packem_shared/loadProjectConfig-B7RmxIeD.mjs +1 -0
  59. package/dist/packem_shared/{modules-DDIIcM7P.mjs → modules-l-Db0C4S.mjs} +1 -1
  60. package/dist/packem_shared/parse-validator-iVTounLK.mjs +1 -0
  61. package/dist/packem_shared/property-name-7cBlgK_O.mjs +1 -0
  62. package/dist/packem_shared/{qualifiers-DEdXn5wP.mjs → qualifiers-Bl5fSmav.mjs} +1 -1
  63. package/dist/packem_shared/readServiceBindings-BA49C6aN.mjs +1 -0
  64. package/dist/packem_shared/{server-DAvi_bv_.mjs → server-B6VhYK7m.mjs} +1 -1
  65. package/dist/packem_shared/{shard-CsfiXxV0.mjs → shard-BCqz_05A.mjs} +267 -142
  66. package/dist/packem_shared/{shard-runtime-BpoCV-aM.mjs → shard-runtime-ByYXjCKY.mjs} +10 -8
  67. package/dist/packem_shared/shared-8vTRkL2-.mjs +13 -0
  68. package/dist/packem_shared/{unwrap-handler-return-Bfz7lH0C.mjs → unwrap-handler-return-CGdJGvGh.mjs} +1 -1
  69. package/dist/sdk/index.mjs +15 -15
  70. package/package.json +9 -9
  71. package/dist/packem_shared/CONTAINERS_FILENAME-QiNt84QA.mjs +0 -1
  72. package/dist/packem_shared/GENERATED_HEADER-Ck_WOHzE.mjs +0 -1
  73. package/dist/packem_shared/LUNORA_ERROR_CODES-C2s0xWQD.mjs +0 -1
  74. package/dist/packem_shared/SCHEMA_SNAPSHOT_FILENAME-V7LYutDl.mjs +0 -31
  75. package/dist/packem_shared/SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs +0 -2
  76. package/dist/packem_shared/SchemaSnapshotParseError-BRJT7c2k.mjs +0 -18
  77. package/dist/packem_shared/capabilitiesUsedBy-BC7ldWJI.mjs +0 -1
  78. package/dist/packem_shared/chain-C9qZxjM_.mjs +0 -1
  79. package/dist/packem_shared/discoverAuthApiCalls-GPzUN_-_.mjs +0 -1
  80. package/dist/packem_shared/discoverCrons-C1fKEf4g.mjs +0 -1
  81. package/dist/packem_shared/discoverHyperdriveCalls-VVJGsgxj.mjs +0 -1
  82. package/dist/packem_shared/discoverMaskProcedures-D3Tu8Q8Y.mjs +0 -1
  83. package/dist/packem_shared/discoverR2sqlCalls-D_H1v-UD.mjs +0 -1
  84. package/dist/packem_shared/discoverSchema-Bdmw34_P.mjs +0 -1
  85. package/dist/packem_shared/emitShard-DtfjUgjj.mjs +0 -1
  86. package/dist/packem_shared/index-BMMBKqsT.mjs +0 -1
  87. package/dist/packem_shared/loadProjectConfig-B0uxUGF-.mjs +0 -1
  88. package/dist/packem_shared/parse-validator-BqDQLzDZ.mjs +0 -1
  89. package/dist/packem_shared/project-config-file-CBY6llht.mjs +0 -1
  90. package/dist/packem_shared/readServiceBindings-4xlUucKw.mjs +0 -1
  91. package/dist/packem_shared/shared-DnCokNcE.mjs +0 -13
@@ -1,4 +1,4 @@
1
- import{LunoraError as de}from"@lunora/errors";import{serializeSchemaSnapshot as Ht,hashSchemaSnapshot as Vt}from"./SCHEMA_SNAPSHOT_VERSION-C0oHwiJZ.mjs";import{isHyperdriveGlobalTable as Kt,isD1GlobalTable as Gt}from"./isD1GlobalTable-udvHAAzD.mjs";import{r as Qt}from"./json-data-Chfs2Cz5.mjs";import{r as E,e as Jt,a as zt,b as Yt,c as Xt,d as Zt,f as er,g as tr,h as rr,i as nr,j as ar,k as sr,l as or,m as ir,n as dr,o as cr,p as lr,q as ur}from"./shard-runtime-BpoCV-aM.mjs";import{u as Y,i as hr,a as pr,I as mr,c as gr,G as fr,d as br}from"./shared-DnCokNcE.mjs";import{p as wr}from"./platform-8oj7iXQy.mjs";import{i as yr}from"./schema-BgM8A3XV.mjs";const h=(n,e)=>`((): (() => ${e}) => { let cached: ${e} | undefined; return () => (cached ??= JSON.parse(${JSON.stringify(JSON.stringify(n))}) as ${e}); })()`,ce=["categories","description","facing","level","remediation","title"],vr=n=>{const e={};return{advisoryRows:n.map(a=>{let r=e[a.name];return r||(r=Object.fromEntries(ce.filter(o=>o in a).map(o=>[o,a[o]])),e[a.name]=r),Object.fromEntries(Object.entries(a).filter(([o,d])=>!ce.includes(o)||JSON.stringify(d)!==JSON.stringify(r[o])))}),advisoryRules:e}},kr=` /**
1
+ import{LunoraError as he}from"@lunora/errors";import{serializeSchemaSnapshot as Jt,hashSchemaSnapshot as Yt}from"./SCHEMA_SNAPSHOT_VERSION-C7Um0EnM.mjs";import{isHyperdriveGlobalTable as zt,isD1GlobalTable as Xt}from"./isD1GlobalTable-udvHAAzD.mjs";import{r as Zt}from"./json-data-Chfs2Cz5.mjs";import{r as $,e as er,a as tr,b as rr,c as nr,d as ar,f as sr,g as or,h as ir,i as dr,j as cr,k as lr,l as ur,m as hr,n as pr,o as mr,p as gr,q as fr}from"./shard-runtime-ByYXjCKY.mjs";import{u as re,h as br,s as wr,a as yr,I as vr,c as kr,G as Sr,d as Rr}from"./shared-8vTRkL2-.mjs";import{p as xr}from"./platform-8oj7iXQy.mjs";import{i as Ar}from"./schema-BgM8A3XV.mjs";const u=(n,t)=>`((): (() => ${t}) => { let cached: ${t} | undefined; return () => (cached ??= JSON.parse(${JSON.stringify(JSON.stringify(n))}) as ${t}); })()`,pe=["categories","description","facing","level","remediation","title"],Or=n=>{const t={};return{advisoryRows:n.map(a=>{let r=t[a.name];return r||(r=Object.fromEntries(pe.filter(o=>o in a).map(o=>[o,a[o]])),t[a.name]=r),Object.fromEntries(Object.entries(a).filter(([o,d])=>!pe.includes(o)||JSON.stringify(d)!==JSON.stringify(r[o])))}),advisoryRules:t}},Dr=` /**
2
2
  * The bare writer every admin/maintenance entry point writes through.
3
3
  *
4
4
  * Admin and maintenance writes go through the SAME reactive-cache hooks as a
@@ -30,7 +30,7 @@ import{LunoraError as de}from"@lunora/errors";import{serializeSchemaSnapshot as
30
30
  schema: schema as unknown as SchemaLike,
31
31
  sql: this.sql as SqlExec,
32
32
  });
33
- }`,g=(n="")=>` const writer = this.adminWriter(${n});`,Sr=`${kr}
33
+ }`,w=(n="")=>` const writer = this.adminWriter(${n});`,Tr=`${Dr}
34
34
 
35
35
  protected override async runShardDataMigration(args: RunShardMigrationArgs): Promise<MigrationRunResult> {
36
36
  this.ensureMigrated();
@@ -47,21 +47,27 @@ import{LunoraError as de}from"@lunora/errors";import{serializeSchemaSnapshot as
47
47
  throw new LunoraError("MIGRATION_NOT_FOUND", \`data migration "\${args.id}" is not registered\`, { status: 404 });
48
48
  }
49
49
 
50
- ${g()}
51
-
52
- return runDataMigration({
53
- ...(args.batchSize === undefined ? {} : { batchSize: args.batchSize }),
54
- ...(args.direction === undefined ? {} : { direction: args.direction }),
55
- ...(args.dryRun === undefined ? {} : { dryRun: args.dryRun }),
56
- ...(args.maxBatches === undefined ? {} : { maxBatches: args.maxBatches }),
57
- migration: migration as unknown as DataMigrationLike,
58
- // Flush after each batch so live migrationStatus subscribers see
59
- // progress mid-run (the base method records the reserved state
60
- // table the raw-SQL progress write is invisible to the tracker).
61
- onBatch: () => this.flushMigrationProgress(),
62
- sql: this.sql as SqlExec,
63
- writer,
64
- });
50
+ ${w()}
51
+
52
+ try {
53
+ return await runDataMigration({
54
+ ...(args.batchSize === undefined ? {} : { batchSize: args.batchSize }),
55
+ ...(args.direction === undefined ? {} : { direction: args.direction }),
56
+ ...(args.dryRun === undefined ? {} : { dryRun: args.dryRun }),
57
+ ...(args.maxBatches === undefined ? {} : { maxBatches: args.maxBatches }),
58
+ migration: migration as unknown as DataMigrationLike,
59
+ // Flush after each batch so live migrationStatus subscribers see
60
+ // progress mid-run (the base method records the reserved state
61
+ // table the raw-SQL progress write is invisible to the tracker).
62
+ onBatch: () => this.flushMigrationProgress(),
63
+ sql: this.sql as SqlExec,
64
+ writer,
65
+ });
66
+ } finally {
67
+ // The de-dup that unblocks a deferred UNIQUE index runs through here;
68
+ // let the next call rebuild it now instead of after the retry interval.
69
+ this.migrationRetryAt = 0;
70
+ }
65
71
  }
66
72
 
67
73
  protected override async runShardWrite(args: RunShardWriteArgs, headroom?: TransactionHeadroomTracker): Promise<RunShardWriteResult> {
@@ -80,7 +86,7 @@ ${g()}
80
86
 
81
87
  this.ensureMigrated();
82
88
 
83
- ${g("headroom ?? this.transactionHeadroom()")}
89
+ ${w("headroom ?? this.transactionHeadroom()")}
84
90
 
85
91
  if (args.op === "insert") {
86
92
  const id = await writer.insert(args.table, args.doc ?? {});
@@ -135,7 +141,7 @@ ${g("headroom ?? this.transactionHeadroom()")}
135
141
  protected override async runShardExport(args: RunShardExportArgs): Promise<ExportRow[]> {
136
142
  this.ensureMigrated();
137
143
 
138
- ${g()}
144
+ ${w()}
139
145
 
140
146
  const rows: ExportRow[] = [];
141
147
 
@@ -152,7 +158,7 @@ ${g()}
152
158
  protected override async runShardImport(args: RunShardImportArgs): Promise<ImportShardResult> {
153
159
  this.ensureMigrated();
154
160
 
155
- ${g()}
161
+ ${w()}
156
162
 
157
163
  // \`importShardRows\` inserts with \`allowExplicitId\`, so a source
158
164
  // database's \`_id\`s carry across verbatim and every foreign key
@@ -163,7 +169,7 @@ ${g()}
163
169
  protected override async runShardRankBefore(args: RunShardRankBeforeArgs): Promise<{ before: number; total: number }> {
164
170
  this.ensureMigrated();
165
171
 
166
- ${g()}
172
+ ${w()}
167
173
 
168
174
  // \`rankBefore\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
169
175
  // but the shard writer from \`createShardCtxDb\` always defines it.
@@ -181,7 +187,7 @@ ${g()}
181
187
  protected override async runShardFindRelated(args: RunShardFindRelatedArgs): Promise<RelatedPage> {
182
188
  this.ensureMigrated();
183
189
 
184
- ${g()}
190
+ ${w()}
185
191
 
186
192
  // \`related\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
187
193
  // but the shard writer from \`createShardCtxDb\` always defines it — it
@@ -199,7 +205,7 @@ ${g()}
199
205
  protected override async runShardRankPage(args: RunShardRankPageArgs): Promise<ShardRankPageResult> {
200
206
  this.ensureMigrated();
201
207
 
202
- ${g()}
208
+ ${w()}
203
209
 
204
210
  // \`rankPageRows\` is optional on \`DatabaseWriterLike\` (the D1 twin omits it),
205
211
  // but the shard writer from \`createShardCtxDb\` always defines it. The sort
@@ -220,21 +226,21 @@ ${g()}
220
226
  protected override async runShardApplyCdc(args: RunShardApplyCdcArgs): Promise<{ applied: number }> {
221
227
  this.ensureMigrated();
222
228
 
223
- ${g()}
229
+ ${w()}
224
230
 
225
231
  await applyCdcChanges(writer, args.changes);
226
232
 
227
233
  return { applied: args.changes.length };
228
- }`,Rr=({actionOnlyBuild:n,actionOnlyFields:e,agentsBuild:t,agentsContextField:a,containersBuild:r,containersContextField:o,databaseOptions:d,everyContextBuild:f,everyContextField:v,facadeBlock:l,globalDatabaseLine:b,lazyFunctions:c=!1,notifyBuild:L,ormContextField:S,paymentsBuild:R,paymentsContextField:I,queuesBuild:P,queuesContextField:k,topicsBuild:N,topicsContextField:i,vectorsBuild:w,vectorsContextField:M,workflowsBuild:$,workflowsContextField:q})=>{const x=e.length>0,F=S===""?"{ db }":"{ db, orm: bindOrm(facade) }",U=S===""?"":`
229
- orm: databaseContext.orm,`,O=S===""?"":`
230
- orm: { configurable: true, enumerable: true, value: mutationDatabase.orm, writable: true },`,u=x?`
234
+ }`,_r=({actionOnlyBuild:n,actionOnlyFields:t,agentsBuild:e,agentsContextField:a,containersBuild:r,containersContextField:o,databaseOptions:d,everyContextBuild:m,everyContextField:g,facadeBlock:h,globalDatabaseLine:x,hasSensitiveArgs:S=!1,lazyFunctions:f=!1,notifyBuild:c,ormContextField:y,paymentsBuild:M,paymentsContextField:A,queuesBuild:q,queuesContextField:F,topicsBuild:R,topicsContextField:U,vectorsBuild:i,vectorsContextField:v,workflowsBuild:E,workflowsContextField:B})=>{const I=t.length>0,C=y===""?"{ db }":"{ db, orm: bindOrm(facade) }",j=y===""?"":`
235
+ orm: databaseContext.orm,`,W=y===""?"":`
236
+ orm: { configurable: true, enumerable: true, value: mutationDatabase.orm, writable: true },`,O=I?`
231
237
  // ActionCtx-only helpers (external, non-deterministic I/O): constructed
232
238
  // and attached only for an \`action\` so query/mutation ctx never carry them.
233
239
  if (isAction) {
234
- ${n.replaceAll(/^(?=.)/gmu," ")}${e.map(p=>` ctx.${p} = ${p};`).join(`
240
+ ${n.replaceAll(/^(?=.)/gmu," ")}${t.map(p=>` ctx.${p} = ${p};`).join(`
235
241
  `)}
236
242
  }
237
- `:"";return` private buildCtx(options: { bookmarks?: DispatchBookmark | undefined; functionPath?: string | undefined; headroom?: TransactionHeadroomTracker | undefined; identity?: SubscriptionIdentity | undefined; kind?: "query" | undefined; onRead?: ((table: string, idOrScan?: string) => void) | undefined; onReadRange?: ((range: KeyRange) => void) | undefined; scope?: QueryReadScope | undefined; trusted?: boolean | undefined } = {}): unknown {
243
+ `:"";return` private buildCtx(options: { bookmarks?: DispatchBookmark | undefined; functionPath?: string | undefined; headroom?: TransactionHeadroomTracker | undefined; identity?: SubscriptionIdentity | undefined; kind?: "query" | undefined; onRead?: ((table: string, idOrScan?: string) => void) | undefined; onReadRange?: ((range: KeyRange) => void) | undefined; scope?: QueryReadScope | undefined; sensitive?: SensitiveScope | undefined; trusted?: boolean | undefined } = {}): unknown {
238
244
  const env = (this.env ?? {}) as Record<string, unknown>;
239
245
  // The caller context this ctx runs under, resolved ONCE on one
240
246
  // discriminant. When the caller threads an explicit identity
@@ -261,7 +267,7 @@ ${n.replaceAll(/^(?=.)/gmu," ")}${e.map(p=>` ctx.${p} = ${p};`
261
267
  };
262
268
  })();
263
269
  const { identity, ip, userId } = caller;
264
- ${w}${f}${r}${$}${P}${N}${t}
270
+ ${i}${m}${r}${E}${q}${R}${e}
265
271
  // Which dispatch this ctx belongs to. Drives the two deferral facades
266
272
  // below and the \`ctx.run*\` caller guard; a ctx built for an
267
273
  // admin/lifecycle path has no registered function, and so no kind. An
@@ -357,7 +363,7 @@ ${w}${f}${r}${$}${P}${N}${t}
357
363
  // dispatch's wide-event handle.
358
364
  const observability = config.observability?.(env);
359
365
  const logFunctionPath = options.functionPath ?? "";
360
- const log = this.makeLogger(logFunctionPath, observability);
366
+ const log = this.makeLogger(logFunctionPath, observability, undefined, options.sensitive);
361
367
  const traceAnchor = this.resolveDispatchAnchor(Boolean(options.identity));
362
368
 
363
369
  // \`ctx.span\`: the handle onto the DISPATCH's own span — the wide-event
@@ -365,9 +371,9 @@ ${w}${f}${r}${$}${P}${N}${t}
365
371
  // and are folded into the one span it already emits, instead of
366
372
  // becoming N separate log lines. Shares \`traceAnchor\` with \`ctx.trace\`
367
373
  // so both write to the same trace.
368
- const span = this.makeDispatchSpan(traceAnchor, observability);
374
+ const span = this.makeDispatchSpan(traceAnchor, observability, options.sensitive);
369
375
 
370
- ${b} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
376
+ ${x} // \`ctx.db\`, wrapped in automatic instrumentation: by default this
371
377
  // adds aggregate counters (call count, total time, per-operation
372
378
  // breakdown) to the wide event rather than a span per call, so a
373
379
  // handler making hundreds of queries stays readable. See
@@ -375,20 +381,20 @@ ${b} // \`ctx.db\`, wrapped in automatic instrumentation: by default
375
381
  // Schema triggers close over this DB's scheduler, so a composed
376
382
  // mutation must rebuild its DB and table/ORM views with its own queue.
377
383
  const makeDatabaseContext = (scheduler: SchedulerLike) => {
378
- const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${d}), logFunctionPath, traceAnchor, observability);
379
- ${l} return ${F};
384
+ const db: DatabaseWriterLike = this.instrumentDb(createShardCtxDb(${d}), logFunctionPath, traceAnchor, observability, options.sensitive);
385
+ ${h} return ${C};
380
386
  };
381
387
  const databaseContext = makeDatabaseContext(scheduler);
382
388
  const db = databaseContext.db;
383
- ${R}
389
+ ${M}
384
390
 
385
391
  // \`ctx.trace\` / \`ctx.metrics\`: spans and measurements to the same sink.
386
392
  // The trace anchor is threaded explicitly for the same reason \`identity\`
387
393
  // is — a deferred caller (a subscription re-run) must not inherit the
388
394
  // writing mutation's trace from the shared per-request field.
389
- const trace = this.makeTracer(logFunctionPath, observability, traceAnchor);
390
- const metrics = this.makeMetrics(logFunctionPath, observability);
391
- ${L}
395
+ const trace = this.makeTracer(logFunctionPath, observability, traceAnchor, options.sensitive);
396
+ const metrics = this.makeMetrics(logFunctionPath, observability, options.sensitive);
397
+ ${c}
392
398
  // \`ctx.now\`: the wall-clock instant (epoch ms) this function began,
393
399
  // captured ONCE so the whole handler body sees a single stable value.
394
400
  // A \`query\` handler is re-run by every live subscription that reads it,
@@ -418,7 +424,7 @@ ${L}
418
424
  // \`traceparent\` propagation, so time spent in a downstream service
419
425
  // is visible and its spans join this trace. Degrades to the bare
420
426
  // global when no sink is configured.
421
- fetch: this.makeFetch(logFunctionPath, traceAnchor, observability),
427
+ fetch: this.makeFetch(logFunctionPath, traceAnchor, observability, options.sensitive),
422
428
  // A GETTER, not a plain field, so the reactive cache can tell a
423
429
  // handler that reads the caller's address from the majority that
424
430
  // never do. \`ctx.ip\` is per-request state the memo must be keyed
@@ -439,25 +445,32 @@ ${L}
439
445
  // to the handler so code that signs its own URLs (a copy-in
440
446
  // \`createStorage\`) can fall back to it too. \`undefined\` for a
441
447
  // query and for a deferred dispatch, for the reasons given there.
442
- origin: requestOrigin,${U}
448
+ origin: requestOrigin,${j}
443
449
  scheduler,
444
450
  span,
445
451
  storage: contextStorage,
446
- trace,${M}${v}${I}${o}${q}${k}${i}${a}
452
+ trace,${v}${g}${A}${o}${B}${F}${U}${a}${S?`
453
+ [Symbol.for("lunora.admitSensitiveArgs")]: (args: Record<string, unknown>, names: ReadonlySet<string>): void => this.admitSensitiveValues(options.sensitive, args, names),`:""}
447
454
  };
448
- ${x?` const isAction = contextKind === "action";
449
- `:""}${u}
450
- ${c?` const captureScope = (): (() => void) => {
455
+ ${I?` const isAction = contextKind === "action";
456
+ `:""}${O}
457
+ ${f?` const captureScope = (): (() => void) => {
451
458
  const requestScope = this.captureRequestScope();
452
459
  return () => this.restoreRequestScope(requestScope);
453
460
  };
454
461
 
455
462
  `:""} const installRun = (target: Record<string, unknown>, kind: typeof contextKind): void => {
456
- target.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => dispatchRun("action", reference.__lunoraRef, fnArgs, target, kind${c?", undefined, captureScope":""});
463
+ target.runAction = (reference: FunctionReference, fnArgs: Record<string, unknown>) => {
464
+ // The callee runs inside this invocation, so its marked arguments are scrubbed here too.
465
+ this.admitSensitiveArgs(options.sensitive, reference.__lunoraRef, fnArgs);
466
+
467
+ return dispatchRun("action", reference.__lunoraRef, fnArgs, target, kind${f?", undefined, captureScope":""});
468
+ };
457
469
  // The composed mutation runs under the SAME wrapper the top-level RPC
458
470
  // uses, so "do the transactional work in a mutation and call it from the
459
471
  // action" — the recipe the docs give for atomicity — actually is atomic.
460
472
  target.runMutation = (reference: FunctionReference, fnArgs: Record<string, unknown>) => {
473
+ this.admitSensitiveArgs(options.sensitive, reference.__lunoraRef, fnArgs);
461
474
  // An action can start sibling mutations concurrently. Each owns its
462
475
  // context and deferral queues; only calls from an admitted mutation
463
476
  // inherit that mutation's transaction.
@@ -469,7 +482,7 @@ ${c?` const captureScope = (): (() => void) => {
469
482
 
470
483
  return Object.defineProperties({}, {
471
484
  ...Object.getOwnPropertyDescriptors(target),
472
- db: { configurable: true, enumerable: true, value: mutationDatabase.db, writable: true },${O}
485
+ db: { configurable: true, enumerable: true, value: mutationDatabase.db, writable: true },${W}
473
486
  scheduler: { configurable: true, enumerable: true, value: mutationScheduler, writable: true },
474
487
  storage: { configurable: true, enumerable: true, value: withDeferredDeletes(storage), writable: true },
475
488
  });
@@ -479,7 +492,7 @@ ${c?` const captureScope = (): (() => void) => {
479
492
  installRun(mutationCtx, kind);
480
493
  }
481
494
 
482
- return dispatchRun("mutation", reference.__lunoraRef, fnArgs, mutationCtx, kind, async (work) => this.runMutationTransaction(mutationCtx, work)${c?", captureScope":""});
495
+ return dispatchRun("mutation", reference.__lunoraRef, fnArgs, mutationCtx, kind, async (work) => this.runMutationTransaction(mutationCtx, work)${f?", captureScope":""});
483
496
  };
484
497
  // \`ctx.runQuery(ref, args, { untracked: true })\` runs the sub-query on
485
498
  // its OWN query context, built without the subscription's read-footprint
@@ -494,18 +507,21 @@ ${c?` const captureScope = (): (() => void) => {
494
507
  // to the shared per-request fields, which a concurrent RPC may have
495
508
  // re-set, and an RLS-scoped sub-query would then read as the wrong user
496
509
  // from the wrong address. A tracked call runs on \`queryContext()\` below.
497
- target.runQuery = (reference: FunctionReference, fnArgs: Record<string, unknown>, runOptions?: { untracked?: boolean }) =>
498
- dispatchRun(
510
+ target.runQuery = (reference: FunctionReference, fnArgs: Record<string, unknown>, runOptions?: { untracked?: boolean }) => {
511
+ this.admitSensitiveArgs(options.sensitive, reference.__lunoraRef, fnArgs);
512
+
513
+ return dispatchRun(
499
514
  "query",
500
515
  reference.__lunoraRef,
501
516
  fnArgs,
502
517
  runOptions?.untracked === true
503
- ? this.buildCtx({ bookmarks: options.bookmarks, functionPath: options.functionPath, headroom: options.headroom, identity: caller, kind: "query", scope: options.scope })
518
+ ? this.buildCtx({ bookmarks: options.bookmarks, functionPath: options.functionPath, headroom: options.headroom, identity: caller, kind: "query", scope: options.scope, sensitive: options.sensitive })
504
519
  : queryContext(),
505
- kind,${c?`
520
+ kind,${f?`
506
521
  undefined,
507
522
  captureScope,`:""}
508
523
  );
524
+ };
509
525
  };
510
526
 
511
527
  // A query composed from a mutation or action runs on a QUERY view of
@@ -526,7 +542,7 @@ ${c?` const captureScope = (): (() => void) => {
526
542
 
527
543
  if (queryView === undefined) {
528
544
  const descriptors: PropertyDescriptorMap = Object.getOwnPropertyDescriptors(ctx);
529
- ${e.map(p=>` delete descriptors.${p};
545
+ ${t.map(p=>` delete descriptors.${p};
530
546
  `).join("")} // Writable and configurable, like the plain fields they replace.
531
547
  const field = (value: unknown): PropertyDescriptor => ({ configurable: true, enumerable: true, value, writable: true });
532
548
 
@@ -545,7 +561,7 @@ ${e.map(p=>` delete descriptors.${p};
545
561
  installRun(ctx, contextKind);
546
562
 
547
563
  return ctx;
548
- }`},le=`// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
564
+ }`},me=`// Bound in-process \`ctx.run*\` composition depth so a self- or cyclically-
549
565
  // referencing call fails loudly with a clear error instead of overflowing the
550
566
  // stack. Tracked across the awaited handler chain (one DO invocation is
551
567
  // single-threaded), so the counter reflects true nesting depth.
@@ -611,7 +627,7 @@ const dispatchRun = async (
611
627
  } finally {
612
628
  runDepth -= 1;
613
629
  }
614
- };`,xr=n=>n?le.replace(" runTransactional?: (work: () => Promise<unknown>) => Promise<unknown>,",` runTransactional?: (work: () => Promise<unknown>) => Promise<unknown>,
630
+ };`,Er=n=>n?me.replace(" runTransactional?: (work: () => Promise<unknown>) => Promise<unknown>,",` runTransactional?: (work: () => Promise<unknown>) => Promise<unknown>,
615
631
  captureScope?: () => () => void,`).replace(` try {
616
632
  // A mutation composed from an action`,` try {
617
633
  let loaded = getLoadedFunction(functionPath);
@@ -632,7 +648,20 @@ const dispatchRun = async (
632
648
 
633
649
  const loadedFunction = loaded;
634
650
 
635
- // A mutation composed from an action`).replaceAll("registered.handler","loadedFunction.handler"):le,Or=` public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker, scope?: QueryReadScope, bookmarks?: DispatchBookmark): Promise<unknown> {
651
+ // A mutation composed from an action`).replaceAll("registered.handler","loadedFunction.handler"):me,Ir=` public override async handleRpc(functionPath: string, args: Record<string, unknown>, headroom?: TransactionHeadroomTracker, scope?: QueryReadScope, bookmarks?: DispatchBookmark, sensitive?: SensitiveScope): Promise<unknown> {
652
+ // A dispatch that did not come through the shard's \`/rpc\` (a scheduled call,
653
+ // a lifecycle hook, an admin run) has no scope of its own, so it opens one here
654
+ // and releases it when the handler settles.
655
+ if (sensitive === undefined) {
656
+ const own = this.openSensitiveScope(functionPath, args);
657
+
658
+ try {
659
+ return await this.handleRpc(functionPath, args, headroom, scope, bookmarks, own);
660
+ } finally {
661
+ own.clear();
662
+ }
663
+ }
664
+
636
665
  __PREPARE_FUNCTION__ const registered = LUNORA_FUNCTIONS[functionPath];
637
666
 
638
667
  // Internal functions are reachable server-side only: via \`ctx.run*\`
@@ -643,7 +672,7 @@ __PREPARE_FUNCTION__ const registered = LUNORA_FUNCTIONS[functionPath
643
672
  throw new LunoraError("FUNCTION_NOT_FOUND", \`function not registered: \${functionPath}\`);
644
673
  }
645
674
 
646
- this.ensureMigrated();
675
+ this.ensureServable();
647
676
 
648
677
  // \`headroom\`, when the caller supplied one, is threaded straight
649
678
  // through to \`buildCtx\` — bypassing its \`this.transactionHeadroom()\`
@@ -659,7 +688,7 @@ __PREPARE_FUNCTION__ const registered = LUNORA_FUNCTIONS[functionPath
659
688
  // our dep set — and ours out of theirs. A dispatch with no scope (a
660
689
  // mutation, an action, a cache-less shard) builds unbound hooks that
661
690
  // stamp no deps.
662
- const ctx = this.buildCtx({ bookmarks, functionPath, headroom, scope, trusted: registered.lifecycle === "init" });
691
+ const ctx = this.buildCtx({ bookmarks, functionPath, headroom, scope, sensitive, trusted: registered.lifecycle === "init" });
663
692
 
664
693
  // A mutation's writes must commit all-or-nothing, so its dispatch runs
665
694
  // under \`runMutationTransaction\` — the ONE place that opens the span,
@@ -816,14 +845,14 @@ __COMMITTED_CATCH__ } finally {
816
845
  // \`ctx.scheduler\` call that reached the buffer in the first place.
817
846
  protected override scheduleOutboxScheduler(): SchedulerLike | undefined {
818
847
  return config.scheduler?.((this.env ?? {}) as Record<string, unknown>) as SchedulerLike | undefined;
819
- }`,Ar=` protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): Promise<{ ranges?: Map<string, KeyRange[]>; result: unknown; tables: Set<string> } | null> {
848
+ }`,Cr=` protected override async executeSubscription(functionPath: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): Promise<{ ranges?: Map<string, KeyRange[]>; result: unknown; tables: Set<string> } | null> {
820
849
  const registered = LUNORA_FUNCTIONS[functionPath];
821
850
 
822
851
  if (!registered || registered.kind !== "query" || registered.visibility === "internal") {
823
852
  return null;
824
853
  }
825
854
 
826
- __PREPARE_FUNCTION__ this.ensureMigrated();
855
+ __PREPARE_FUNCTION__ this.ensureServable();
827
856
 
828
857
  const footprint = createReadFootprint();
829
858
  // Identity is threaded EXPLICITLY from the (deferred/interleaved)
@@ -846,7 +875,7 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
846
875
  return null;
847
876
  }
848
877
 
849
- this.ensureMigrated();
878
+ this.ensureServable();
850
879
 
851
880
  return {
852
881
  ...(registered.durable ? { durable: registered.durable as { ttlMs?: number } } : {}),
@@ -857,7 +886,7 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
857
886
  // \`ctx.auth\` stream as nobody — or as a concurrent RPC's caller.
858
887
  iterator: (signal) => (registered.handler as (context: unknown, args: Record<string, unknown>, signal: AbortSignal) => AsyncIterable<unknown>)(this.buildCtx({ functionPath, identity }), args, signal),
859
888
  };
860
- }`,Dr=` } catch (error) {
889
+ }`,Lr=` } catch (error) {
861
890
  // The write committed before this failed. Mark the error so the caller can tell
862
891
  // a durable write from a rollback: the rethrow still reaches the caller unchanged.
863
892
  if (typeof error === "object" && error !== null) {
@@ -865,13 +894,13 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
865
894
  }
866
895
 
867
896
  throw error;
868
- `,Tr=(n,e=!1)=>{const t=e?` const registeredBeforeLoad = LUNORA_FUNCTIONS[functionPath];
897
+ `,Pr=(n,t=!1)=>{const e=t?` const registeredBeforeLoad = LUNORA_FUNCTIONS[functionPath];
869
898
 
870
899
  if (registeredBeforeLoad?.visibility === "internal" && !this.isSystemDispatch()) {
871
900
  throw new LunoraError("FUNCTION_NOT_FOUND", "function not registered: " + functionPath);
872
901
  }
873
902
 
874
- `:"",a=e?` const requestScope = this.captureRequestScope();
903
+ `:"",a=t?` const requestScope = this.captureRequestScope();
875
904
  const preparation = this.prepareFunction(functionPath, "rpc");
876
905
 
877
906
  if (preparation !== undefined) {
@@ -882,21 +911,33 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
882
911
  }
883
912
  }
884
913
 
885
- `:"";return Or.replace("__COMMITTED_CATCH__",n?Dr:"").replace("__PREPARE_FUNCTION__",`${t}${a}`)},Cr=n=>{const e={};for(const t of n.tables){const a={};for(const[r,o]of Object.entries(t.shape)){const d=Y(o);d.kind==="id"&&d.tableName!==void 0&&(a[r]=d.tableName)}Object.keys(a).length>0&&(e[t.name]=a)}return e},_r=n=>{const e={};for(const t of n.tables){const a=[];for(const[r,o]of Object.entries(t.shape))Y(o).kind==="storage"&&a.push(r);a.length>0&&(e[t.name]=a)}return e},Er=n=>{const e={};for(const t of n.tables){const a=[...t.indexes.map(r=>({fields:[...r.fields],name:r.name,type:"index",...r.unique===!0?{unique:!0}:{}})),...t.searchIndexes.map(r=>({fields:[r.field,...r.filterFields??[]],name:r.name,type:"search"})),...(t.geoIndexes??[]).map(r=>({fields:[r.field],name:r.name,type:"geo"})),...t.rankIndexes.map(r=>({fields:r.sortBy.map(o=>o.field),name:r.name,type:"rank"})),...t.vectorIndexes.map(r=>({fields:r.field===void 0?[]:[r.field],name:r.name,type:"vector"}))];a.length>0&&(e[t.name]=a)}return e},Lr=n=>{const e=[];for(const t of n.tables)!t.ttl||t.shardMode==="global"||e.push({...t.ttl.after===void 0?{}:{after:t.ttl.after},field:t.ttl.field,...t.softDelete?{softDeleteField:t.softDelete.field}:{},table:t.name});return e},Ir=n=>{if(n.kind!=="union"||n.members===void 0||n.members.length===0)return;const e=[];for(const t of n.members){if(t.kind!=="literal"||t.literalValue===void 0)return;try{const a=JSON.parse(t.literalValue);if(typeof a!="string")return;e.push(a)}catch{return}}return e},Pr=(n,e,t)=>{const a=Y(e),r={name:n,optional:hr(e),type:a.kind};if(a.kind==="id"&&a.tableName!==void 0){r.ref=a.tableName;const d=t.get(n);d!==void 0&&(r.onDelete=d)}a.kind==="storage"&&(r.isStorage=!0,a.bucket!==void 0&&(r.bucket=a.bucket));const o=Ir(a);return o!==void 0&&(r.enumValues=o),a.column?.notNull===!1&&(r.nullable=!0),r},Nr=n=>{const e={};for(const t of n.tables){const a=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"},...t.commitOrdered===!0?[{name:"_commitSeq",optional:!1,type:"number"}]:[]],r=new Map(t.relations.flatMap(o=>o.kind==="one"?[[o.field,o.onDelete]]:[]));for(const[o,d]of Object.entries(t.shape))a.push(Pr(o,d,r));e[t.name]=a}return e},Mr=({hasMutators:n,hasShapes:e,rlsData:t})=>{const a=e?`
886
- protected override resolveShape(name: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): { columns?: readonly string[]; effectiveWhere?: WhereInput; global?: boolean; table: string } | undefined {
914
+ `:"";return Ir.replace("__COMMITTED_CATCH__",n?Lr:"").replace("__PREPARE_FUNCTION__",`${e}${a}`)},Nr=n=>{const t={};for(const e of n.tables){const a={};for(const[r,o]of Object.entries(e.shape)){const d=re(o);d.kind==="id"&&d.tableName!==void 0&&(a[r]=d.tableName)}Object.keys(a).length>0&&(t[e.name]=a)}return t},$r=n=>{const t={};for(const e of n.tables){const a=[];for(const[r,o]of Object.entries(e.shape))re(o).kind==="storage"&&a.push(r);a.length>0&&(t[e.name]=a)}return t},Mr=n=>{const t={};for(const e of n.tables){const a=[...e.indexes.map(r=>({fields:[...r.fields],name:r.name,type:"index",...r.unique===!0?{unique:!0}:{}})),...e.searchIndexes.map(r=>({fields:[r.field,...r.filterFields??[]],name:r.name,type:"search"})),...(e.geoIndexes??[]).map(r=>({fields:[r.field],name:r.name,type:"geo"})),...e.rankIndexes.map(r=>({fields:r.sortBy.map(o=>o.field),name:r.name,type:"rank"})),...e.vectorIndexes.map(r=>({fields:r.field===void 0?[]:[r.field],name:r.name,type:"vector"}))];a.length>0&&(t[e.name]=a)}return t},qr=n=>{const t=[];for(const e of n.tables)!e.ttl||e.shardMode==="global"||t.push({...e.ttl.after===void 0?{}:{after:e.ttl.after},field:e.ttl.field,...e.softDelete?{softDeleteField:e.softDelete.field}:{},table:e.name});return t},Fr=n=>{if(n.kind!=="union"||n.members===void 0||n.members.length===0)return;const t=[];for(const e of n.members){if(e.kind!=="literal"||e.literalValue===void 0)return;try{const a=JSON.parse(e.literalValue);if(typeof a!="string")return;t.push(a)}catch{return}}return t},Ur=(n,t,e)=>{const a=re(t),r={name:n,optional:br(t),type:a.kind};if(a.kind==="id"&&a.tableName!==void 0){r.ref=a.tableName;const d=e.get(n);d!==void 0&&(r.onDelete=d)}a.kind==="storage"&&(r.isStorage=!0,a.bucket!==void 0&&(r.bucket=a.bucket));const o=Fr(a);return o!==void 0&&(r.enumValues=o),a.column?.notNull===!1&&(r.nullable=!0),r},Br=n=>{const t={};for(const e of n.tables){const a=[{name:"_id",optional:!1,pk:!0,type:"id"},{name:"_creationTime",optional:!1,type:"number"},...e.commitOrdered===!0?[{name:"_commitSeq",optional:!1,type:"number"}]:[]],r=new Map(e.relations.flatMap(o=>o.kind==="one"?[[o.field,o.onDelete]]:[]));for(const[o,d]of Object.entries(e.shape))a.push(Ur(o,d,r));t[e.name]=a}return t},jr=({hasMutators:n,hasSensitiveShapes:t,hasShapes:e,rlsData:a})=>{const r="{ columns?: readonly string[]; effectiveWhere?: WhereInput; global?: boolean; table: string } | undefined",o=t?` protected override resolveShape(name: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): ${r} {
915
+ const sensitive = this.openSensitiveScope(\`__shape__:\${name}\`, args);
916
+
917
+ try {
918
+ return this.resolveShapeWithScope(name, args, identity, sensitive);
919
+ } catch (error) {
920
+ throw this.maskSensitiveError(error, sensitive);
921
+ } finally {
922
+ sensitive.clear();
923
+ }
924
+ }
925
+
926
+ private resolveShapeWithScope(name: string, args: Record<string, unknown>, identity: SubscriptionIdentity | undefined, sensitive: SensitiveScope): ${r} {`:` protected override resolveShape(name: string, args: Record<string, unknown>, identity?: SubscriptionIdentity): ${r} {`,m=e?`
927
+ ${o}
887
928
  const shape = LUNORA_SHAPES[name];
888
929
 
889
930
  if (!shape) {
890
931
  return undefined;
891
932
  }
892
933
 
893
- this.ensureMigrated();
934
+ this.ensureServable();
894
935
 
895
936
  // Trusted ctx from the socket's OWN verified identity — the client
896
937
  // supplies only the shape name + args; \`compileWhere\` validates the
897
938
  // args then runs the shape's \`where(ctx, args)\` under that identity,
898
939
  // so which rows replicate is a server decision (reads-as-permissions).
899
- const ctx = this.buildCtx({ functionPath: \`__shape__:\${name}\`, identity });
940
+ const ctx = this.buildCtx({ functionPath: \`__shape__:\${name}\`, identity${t?", sensitive":""} });
900
941
  // \`ownerField\` resolves an \`owner: true\` shape: only here is the table's
901
942
  // \`.ownedBy(field)\` column in scope, so the DO hands it to the shape
902
943
  // rather than every shape restating the ownership check in its \`where\`.
@@ -945,14 +986,14 @@ __PREPARE_FUNCTION__ this.ensureMigrated();
945
986
 
946
987
  return { ...(shape.columns === undefined ? {} : { columns: shape.columns }), effectiveWhere, global: isGlobal, table: shape.table };
947
988
  }
948
- `:"",r=e?[...new Set(t.policies.filter(l=>l.on==="read"&&l.table!=="").map(l=>l.table))].toSorted((l,b)=>l.localeCompare(b)):[],o=r.length>0?`
989
+ `:"",g=e?[...new Set(a.policies.filter(c=>c.on==="read"&&c.table!=="").map(c=>c.table))].toSorted((c,y)=>c.localeCompare(y)):[],h=g.length>0?`
949
990
  /** Refuses to boot a shape that would replicate around the read policies its table is governed by (\`defineShape({ use })\` is how a shape opts in; \`use: []\` acknowledges an ungoverned one). */
950
- assertShapesDeclareReadPolicies(LUNORA_SHAPES, ${JSON.stringify(r)}, (schema as unknown as { rlsMode?: string }).rlsMode === "required");
991
+ assertShapesDeclareReadPolicies(LUNORA_SHAPES, ${JSON.stringify(g)}, (schema as unknown as { rlsMode?: string }).rlsMode === "required");
951
992
  `:"";return{customMutatorOverride:n?`
952
993
  protected override isCustomMutator(functionPath: string): boolean {
953
994
  return LUNORA_MUTATOR_PATHS.has(functionPath);
954
995
  }
955
- `:"",shapeGuardImport:e?"assertShapeShardable, ":"",shapeReadPolicyAssertion:o,shapeReadPolicyImport:o===""?"":"assertShapesDeclareReadPolicies, ",shapeResolveOverride:a}},$r=(n,e)=>n?`
996
+ `:"",shapeGuardImport:e?"assertShapeShardable, ":"",shapeReadPolicyAssertion:h,shapeReadPolicyImport:h===""?"":"assertShapesDeclareReadPolicies, ",shapeResolveOverride:m}},Wr=(n,t)=>n?`
956
997
  protected override async readGlobalShapeRows(resolved: { columns?: readonly string[]; effectiveWhere?: WhereInput; global?: boolean; table: string }, identity?: SubscriptionIdentity): Promise<Array<{ doc: Record<string, unknown>; id: string }>> {
957
998
  const env = this.env as Record<string, unknown>;
958
999
  // A shape read performs no writes, so the widened request only needs
@@ -972,7 +1013,7 @@ assertShapesDeclareReadPolicies(LUNORA_SHAPES, ${JSON.stringify(r)}, (schema as
972
1013
  ...(identity?.identity === undefined ? {} : { identity: identity.identity }),
973
1014
  ...(identity?.userId === undefined ? {} : { userId: identity.userId }),
974
1015
  };
975
- const globalDb: DatabaseWriterLike = ${e}?.(env, globalRequest) ?? globalDbStub;
1016
+ const globalDb: DatabaseWriterLike = ${t}?.(env, globalRequest) ?? globalDbStub;
976
1017
  const rows: Array<{ doc: Record<string, unknown>; id: string }> = [];
977
1018
 
978
1019
  let cursor: null | string = null;
@@ -1014,11 +1055,11 @@ assertShapesDeclareReadPolicies(LUNORA_SHAPES, ${JSON.stringify(r)}, (schema as
1014
1055
  // a \`defineShape\`. The Hyperdrive factory simply never reads it.
1015
1056
  const bookmark = this.getInboundBookmark();
1016
1057
  const globalRequest = { ...this.globalCdcOptions(config.cdc ?? false), ...(bookmark === undefined ? {} : { bookmark }) };
1017
- const globalDb: DatabaseWriterLike = ${e}?.(env, globalRequest) ?? globalDbStub;
1058
+ const globalDb: DatabaseWriterLike = ${t}?.(env, globalRequest) ?? globalDbStub;
1018
1059
 
1019
1060
  return globalDb.cdcChangedTables?.(sinceSeq, cursorOnly === undefined ? {} : { cursorOnly });
1020
1061
  }
1021
- `:"",qr=n=>({externalSourceOverride:n?`
1062
+ `:"",Hr=n=>({externalSourceOverride:n?`
1022
1063
  protected override async pollExternalSources(trace?: TraceRefLike): Promise<number | undefined> {
1023
1064
  const env = (this.env ?? {}) as Record<string, unknown>;
1024
1065
  const sourced = Object.entries((schema as unknown as SchemaLike).tables)
@@ -1171,8 +1212,8 @@ assertShapesDeclareReadPolicies(LUNORA_SHAPES, ${JSON.stringify(r)}, (schema as
1171
1212
  `:"",sourceClientCacheConst:n?`
1172
1213
  const sourceClientCache = new WeakMap<object, Map<string, SourceClientLike>>();
1173
1214
  const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
1174
- `:""}),Fr=(n,e)=>{const t=e.length>0,r=n?E("vectorsStub: VectorSearchLike","ctx.vectors: no vectors configured. Pass `vectors` to createShardDO().",["deleteByIds","getByIds","query","upsert","upsertMany","upsertNow"]):"",o=t?` const vectorShardKey = this.currentShardKey();
1175
- `:"",d=t?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",v=`, { ${["deferAfterCommit: (work) => this.deferAfterCommit(work)",...t?["namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey",`shardedIndexNames: [${e.map(c=>JSON.stringify(c)).join(", ")}]`]:[]].join(", ")} }`,l=n?`
1215
+ `:""}),Vr=(n,t)=>{const e=t.length>0,r=n?$("vectorsStub: VectorSearchLike","ctx.vectors: no vectors configured. Pass `vectors` to createShardDO().",["deleteByIds","getByIds","query","upsert","upsertMany","upsertNow"]):"",o=e?` const vectorShardKey = this.currentShardKey();
1216
+ `:"",d=e?"namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey, ":"",g=`, { ${["deferAfterCommit: (work) => this.deferAfterCommit(work)",...e?["namespace: vectorShardKey === ROOT_SHARD_NAME ? undefined : vectorShardKey",`shardedIndexNames: [${t.map(S=>JSON.stringify(S)).join(", ")}]`]:[]].join(", ")} }`,h=n?`
1176
1217
  const vectorSync = this.vectorSync(env);
1177
1218
  // Vectorize lives outside this shard's SQLite, so a query whose result
1178
1219
  // depends on a similarity search cannot be proven current on reconnect —
@@ -1189,7 +1230,7 @@ const sourcePollAtCache = new WeakMap<object, Map<string, number>>();
1189
1230
  }
1190
1231
 
1191
1232
  const lunora = createVectors({ indexes: config.vectors(env) });
1192
- ${o} const vectors = createContextVectors(lunora${v});
1233
+ ${o} const vectors = createContextVectors(lunora${g});
1193
1234
 
1194
1235
  return {
1195
1236
  backfill: createVectorBackfillSync({ ${d}schema: schema as unknown as VectorSchemaLike, upsertMany: lunora.upsertMany, vectors }),
@@ -1215,14 +1256,14 @@ ${o} const vectors = createContextVectors(lunora${v});
1215
1256
  ordered: async (read, work) => this.runOrderedAfterWrites(read, work),
1216
1257
  });
1217
1258
  }
1218
- `:"",vectorsBuild:l,vectorsStub:r}},Xr=({advisories:n=[],advisorProcedures:e=[],agents:t=[],capabilities:a=new Set,containers:r=[],env:o,flagKeys:d=[],hasFlags:f=!1,hasNotify:v=!1,hasRooms:l=!1,hasSockets:b=!1,lazyFunctions:c=!1,hasVectors:L=!0,liveStreamDeclarations:S=[],liveStreams:R=!1,maskMetadata:I,mutators:P=[],queues:k=[],rlsMetadata:N,schema:i,schemaSnapshot:w,shapes:M=[],storageRules:$,studioFeatures:q,services:x=[],topics:F=[],useUmbrella:U=!1,workflows:O=[]})=>{const u=br(U),B=P.length>0,p=M.length>0,ue=w===void 0?"":Ht(w),he=w===void 0?"":`
1259
+ `:"",vectorsBuild:h,vectorsStub:r}},on=({advisories:n=[],advisorProcedures:t=[],agents:e=[],capabilities:a=new Set,containers:r=[],env:o,flagKeys:d=[],hasFlags:m=!1,hasNotify:g=!1,hasRooms:h=!1,hasSecretValues:x=!1,hasSensitiveArgs:S=!1,hasSockets:f=!1,lazyFunctions:c=!1,hasVectors:y=!0,liveStreamDeclarations:M=[],liveStreams:A=!1,maskMetadata:q,mutators:F=[],queues:R=[],rlsMetadata:U,schema:i,schemaSnapshot:v,shapes:E=[],storageRules:B,studioFeatures:I,services:C=[],topics:j=[],useUmbrella:W=!1,workflows:O=[]})=>{const l=Rr(W),H=F.length>0,p=E.length>0,D=E.some(s=>wr(s.args).length>0),V=S||D,ge=v===void 0?"":Jt(v),fe=v===void 0?"":`
1219
1260
  /** Structural schema snapshot + its content hash, recorded in the shard's \`__lunora_schema_history\` ledger on cold start so the studio can show a schema-version timeline and diff any two versions. */
1220
- const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(Vt(w))}, json: ${JSON.stringify(ue)} };
1221
- `,pe=w===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",y=Jt(a),T=zt(f,u.flags),j=Yt(d,f,u.flags),W=ur(v),H=Xt(o),{build:me,contextField:ge,importLines:fe,specs:be}=Zt(wr(k)),{build:we,contextField:ye,importLines:ve,specs:ke}=er(F,k),V=tr(x,u.server),{build:Se,contextField:Re,importLines:xe,specs:Oe}=rr(r,i.jurisdiction),{build:Ae,contextField:De,importLines:Te,specs:Ce}=nr(O),{build:_e,contextField:Ee,importLines:Le,specs:Ie}=ar(t),{build:Pe,configField:Ne,contextField:Me,imports:$e,stub:qe}=sr(a.has("payments")),Fe=n,{advisoryRules:Ue,advisoryRows:Be}=vr(Fe),je=e,X=N??{policies:[],roles:[]},We=I??{columns:[]},He=$??{rules:[]},Ve=q??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,notifications:!1,payments:!1,privacy:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:Ke,override:Ge}=or(O),{constant:Qe,override:Je}=ir(k),m=L&&i.vectorIndexes.length>0,K=new Set(i.tables.filter(s=>yr(s)).map(s=>s.name)),Z=m&&i.vectorIndexes.some(s=>K.has(s.table)),A=i.tables.some(s=>s.shardMode==="global"),G=dr(K),Q=i.tables.some(s=>Kt(s)),ee=i.tables.some(s=>Gt(s)),C=i.tables.some(s=>s.externalSource!==void 0),te=i.tables.some(s=>s.memory===!0),J=i.tables.some(s=>s.shardMode!=="global"&&s.searchIndexes.length>0);if(ee&&Q)throw new de("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const z=i.tables.length>0,ze=Cr(i),Ye=Er(i),Xe=Nr(i),Ze=_r(i),re=Lr(i),ne=cr(m,O.length>0,k.length>0,f,J);p&&ne.push("WhereInput");const ae=lr(A),{customMutatorOverride:et,shapeGuardImport:tt,shapeReadPolicyAssertion:rt,shapeReadPolicyImport:nt,shapeResolveOverride:at}=Mr({hasMutators:B,hasShapes:p,rlsData:X}),D=R?S:[];for(const s of D)if(pr(s.exportName,"live stream export name"),!mr.test(s.filePath))throw new de("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe live stream file path: ${JSON.stringify(s.filePath)}`);const st=c?[]:D.map(s=>`import { ${s.exportName} as liveStream_${s.exportName} } from "../${s.filePath}.js";`),ot=` protected override liveStreams() {
1222
- return { ${D.map(s=>`${gr(s.id)}: liveStream_${s.exportName}`).join(", ")} };
1261
+ const LUNORA_SCHEMA_SNAPSHOT: { hash: string; json: string } = { hash: ${JSON.stringify(Yt(v))}, json: ${JSON.stringify(ge)} };
1262
+ `,be=v===void 0?"":", schemaSnapshot: LUNORA_SCHEMA_SNAPSHOT",k=er(a),L=tr(m,l.flags),K=rr(d,m,l.flags),G=fr(g),Q=nr(o),{build:we,contextField:ye,importLines:ve,specs:ke}=ar(xr(R)),{build:Se,contextField:Re,importLines:xe,specs:Ae}=sr(j,R),J=or(C,l.server),{build:Oe,contextField:De,importLines:Te,specs:_e}=ir(r,i.jurisdiction),{build:Ee,contextField:Ie,importLines:Ce,specs:Le}=dr(O),{build:Pe,contextField:Ne,importLines:$e,specs:Me}=cr(e,x&&e.length>0),{build:qe,configField:Fe,contextField:Ue,imports:Be,stub:je}=lr(a.has("payments")),We=n,{advisoryRules:He,advisoryRows:Ve}=Or(We),Ke=t,ne=U??{policies:[],roles:[]},Ge=q??{columns:[]},Qe=B??{rules:[]},Je=I??{analytics:!1,auth:!1,containers:!1,flags:!1,kv:!1,mail:!1,notifications:!1,payments:!1,privacy:!1,queues:!1,scheduler:!1,storage:!1,vectors:!1,workflows:!1},{constant:Ye,override:ze}=ur(O),{constant:Xe,override:Ze}=hr(R),b=y&&i.vectorIndexes.length>0,Y=new Set(i.tables.filter(s=>Ar(s)).map(s=>s.name)),ae=b&&i.vectorIndexes.some(s=>Y.has(s.table)),T=i.tables.some(s=>s.shardMode==="global"),z=pr(Y),X=i.tables.some(s=>zt(s)),se=i.tables.some(s=>Xt(s)),P=i.tables.some(s=>s.externalSource!==void 0),oe=i.tables.some(s=>s.memory===!0),Z=i.tables.some(s=>s.shardMode!=="global"&&s.searchIndexes.length>0);if(se&&X)throw new he("INTERNAL",'lunora codegen: mixing `.global()` (D1) and `.global({ backend: "hyperdrive" })` tables in one app is not supported yet — use a single global backend.');const ee=i.tables.length>0,et=Nr(i),tt=Mr(i),rt=Br(i),nt=$r(i),ie=qr(i),te=mr(b,O.length>0,R.length>0,m,Z);p&&te.push("WhereInput"),D&&te.push("SensitiveScope");const de=gr(T),{customMutatorOverride:at,shapeGuardImport:st,shapeReadPolicyAssertion:ot,shapeReadPolicyImport:it,shapeResolveOverride:dt}=jr({hasMutators:H,hasSensitiveShapes:D,hasShapes:p,rlsData:ne}),_=A?M:[];for(const s of _)if(yr(s.exportName,"live stream export name"),!vr.test(s.filePath))throw new he("INTERNAL",`@lunora/codegen: refusing to emit import for unsafe live stream file path: ${JSON.stringify(s.filePath)}`);const ct=c?[]:_.map(s=>`import { ${s.exportName} as liveStream_${s.exportName} } from "../${s.filePath}.js";`),lt=` protected override liveStreams() {
1263
+ return { ${_.map(s=>`${kr(s.id)}: liveStream_${s.exportName}`).join(", ")} };
1223
1264
  }
1224
- `,it=` private readonly liveStreamLoaders = new Map<string, () => Promise<{ validatePublish: (topic: string, payload: unknown) => unknown }>>([
1225
- ${D.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}.js").then((module) => module.${s.exportName})],`).join(`
1265
+ `,ut=` private readonly liveStreamLoaders = new Map<string, () => Promise<{ validatePublish: (topic: string, payload: unknown) => unknown }>>([
1266
+ ${_.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}.js").then((module) => module.${s.exportName})],`).join(`
1226
1267
  `)}
1227
1268
  ]);
1228
1269
 
@@ -1243,11 +1284,11 @@ ${D.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}
1243
1284
  protected override liveStreams() {
1244
1285
  return Object.fromEntries(this.loadedLiveStreams);
1245
1286
  }
1246
- `;let se="";D.length>0&&(se=c?it:ot);const _=[`import type { ${ne.join(", ")} } from "${u.do}";`,`import { applyCdcChanges, createStableIdFactory, ${J?"backfillSearchIndexes, ":""}${m?"backfillVectorIndexes, ":""}buildReprojectionMigration, ${te?"clearMemoryTables, ":""}${tt}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${C?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${Z?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${ae.importFragment}ShardDO as ShardDOBase } from "${u.do}";`,...C?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${u.do}";`]:[],p?`import { asBucketStorage, ${nt}beginDeferredDeletes, beginDeferredSchedules, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${u.server}";`:`import { asBucketStorage, beginDeferredDeletes, beginDeferredSchedules, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${u.server}";`];z&&_.push(`import { bindOrm, bindTableFacade } from "${u.server}";`),m&&_.push('import type { SchemaLike as VectorSchemaLike, VectorBackfillSync, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectorBackfillSync, createVectors, createVectorSyncHook, vectorBackfillTargets } from "@lunora/bindings/vectors";'),_.push(...y.importLines,...T.importLines,...W.importLines,...H.importLines,...xe,...Te,...fe,...ve,...V.importLines,...Le,...$e,"",'import schema from "../schema.js";',...st,`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...c?["getLoadedFunction","loadFunction"]:[],...B?["LUNORA_MUTATOR_PATHS"]:[],...l?["LUNORA_ROOMS"]:[],...b?["LUNORA_SOCKETS"]:[],...p?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const dt=m?`
1247
- vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",ct=ee?`
1248
- d1?: (env: Record<string, unknown>, request?: { bookmark?: string; cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; onBookmark?: (bookmark: string | undefined) => void; userId?: string }) => DatabaseWriterLike | undefined;`:"",lt=Q?`
1249
- hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",ut=C?`
1250
- sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",ht="ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().",pt="ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().",mt="ctx.storage: no storage configured. Pass `storage` to createShardDO().",gt=A?E("globalDbStub: DatabaseWriterLike",ht,["aggregate","count","delete","explain","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",{vectorSyncMethod:ft,vectorsBuild:bt,vectorsStub:wt}=Fr(m,Z?i.vectorIndexes.filter(s=>K.has(s.table)).map(s=>s.name):[]),yt=`{
1287
+ `;let ce="";_.length>0&&(ce=c?ut:lt);const N=[`import type { ${te.join(", ")} } from "${l.do}";`,`import { applyCdcChanges, createStableIdFactory, ${Z?"backfillSearchIndexes, ":""}${b?"backfillVectorIndexes, ":""}buildReprojectionMigration, ${oe?"clearMemoryTables, ":""}${st}createReadFootprint, createShardCtxDb, exportShardRows, importShardRows, ${P?"isSourceDue, pullExternalSourceIncrementalTick, pullExternalSourceTick, ":""}markUnvouchableReads, ${ae?"ROOT_SHARD_NAME, ":""}runDataMigration, runShardMigrations, ${de.importFragment}ShardDO as ShardDOBase } from "${l.do}";`,...P?[`import type { ExternalSourceLike, SourceClientLike, TraceRefLike } from "${l.do}";`]:[],p?`import { asBucketStorage, ${it}beginDeferredDeletes, beginDeferredSchedules, composeShapeReadWhere, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${l.server}";`:`import { asBucketStorage, beginDeferredDeletes, beginDeferredSchedules, createSecrets, flushDeferredDeletes, LunoraError, withDeferredDeletes, withDeferredSchedules } from "${l.server}";`];ee&&N.push(`import { bindOrm, bindTableFacade } from "${l.server}";`),b&&N.push('import type { SchemaLike as VectorSchemaLike, VectorBackfillSync, VectorizeIndexLike, VectorSearchLike } from "@lunora/bindings/vectors";','import { createContextVectors, createVectorBackfillSync, createVectors, createVectorSyncHook, vectorBackfillTargets } from "@lunora/bindings/vectors";'),N.push(...k.importLines,...L.importLines,...G.importLines,...Q.importLines,...Te,...Ce,...ve,...xe,...J.importLines,...$e,...Be,...V?[`import { sensitiveArgumentNames } from "${l.values}";`]:[],"",'import schema from "../schema.js";',...ct,`import { ${["LUNORA_FUNCTIONS","LUNORA_LIFECYCLE_HOOKS","LUNORA_MIGRATIONS",...c?["getLoadedFunction","loadFunction"]:[],...H?["LUNORA_MUTATOR_PATHS"]:[],...h?["LUNORA_ROOMS"]:[],...f?["LUNORA_SOCKETS"]:[],...p?["LUNORA_SHAPES"]:[]].join(", ")} } from "./functions.js";`);const ht=b?`
1288
+ vectors?: (env: Record<string, unknown>) => Record<string, VectorizeIndexLike>;`:"",pt=se?`
1289
+ d1?: (env: Record<string, unknown>, request?: { bookmark?: string; cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; onBookmark?: (bookmark: string | undefined) => void; userId?: string }) => DatabaseWriterLike | undefined;`:"",mt=X?`
1290
+ hyperdriveGlobal?: (env: Record<string, unknown>, request?: { cdc?: boolean; cdcRetentionMs?: number; identity?: Record<string, unknown>; userId?: string }) => DatabaseWriterLike | undefined;`:"",gt=P?`
1291
+ sourceClient?: (env: Record<string, unknown>, binding: string) => { query: <Row = Record<string, unknown>>(text: string, params?: readonly unknown[]) => Promise<Row[]> } | undefined;`:"",ft="ctx.db.<globalTable>: no global backend configured. Pass `d1` or `hyperdriveGlobal` to createShardDO().",bt="ctx.scheduler: no scheduler configured. Pass `scheduler` to createShardDO().",wt="ctx.storage: no storage configured. Pass `storage` to createShardDO().",yt=T?$("globalDbStub: DatabaseWriterLike",ft,["aggregate","count","delete","explain","findFirst","findFirstOrThrow","findMany","get","groupBy","insert","normalizeId","patch","query","rank","rankPage","replace"],{sync:["normalizeId","query"]}):"",{vectorSyncMethod:vt,vectorsBuild:kt,vectorsStub:St}=Vr(b,ae?i.vectorIndexes.filter(s=>Y.has(s.table)).map(s=>s.name):[]),Rt=`{
1251
1292
  ...this.ctxDbTuning(),
1252
1293
  auth: { identity: identity ?? null, userId: userId ?? null },
1253
1294
  broadcast: (delta) => {
@@ -1287,7 +1328,7 @@ ${D.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}
1287
1328
  // fallback rather than reporting into a no-op.
1288
1329
  ...(options.onReadRange !== undefined
1289
1330
  ? { onReadRange: options.onReadRange }
1290
- : options.scope === undefined ? {} : { onReadRange: this.getCtxDbReadRangeHook(options.scope) }),${m?`
1331
+ : options.scope === undefined ? {} : { onReadRange: this.getCtxDbReadRangeHook(options.scope) }),${b?`
1291
1332
  // Vectorize is outside this shard's SQLite and cannot roll back, so
1292
1333
  // the sync is held until the mutation's transaction has COMMITTED
1293
1334
  // (\`deferAfterCommit\`) instead of running inline. Inline, a write
@@ -1299,11 +1340,11 @@ ${D.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}
1299
1340
  scheduler,
1300
1341
  schema: schema as unknown as SchemaLike,
1301
1342
  sql: this.sql as SqlExec,
1302
- storage,${A?`
1343
+ storage,${T?`
1303
1344
  globalDb,`:""}
1304
- }`,vt=m?`
1305
- vectors,`:"",kt=z?`
1306
- orm: bindOrm(facade),`:"",oe=Q?"config.hyperdriveGlobal":"config.d1",St=A?` const bookmark = this.getInboundBookmark();
1345
+ }`,xt=b?`
1346
+ vectors,`:"",At=ee?`
1347
+ orm: bindOrm(facade),`:"",le=X?"config.hyperdriveGlobal":"config.d1",Ot=T?` const bookmark = this.getInboundBookmark();
1307
1348
  const globalRequest = {
1308
1349
  ...this.globalCdcOptions(config.cdc ?? false),
1309
1350
  ...(bookmark === undefined ? {} : { bookmark }),
@@ -1311,26 +1352,65 @@ ${D.map(s=>` [${JSON.stringify(s.id)}, () => import("../${s.filePath}
1311
1352
  onBookmark: (bookmarkValue: string | undefined) => { if (options.bookmarks !== undefined) { options.bookmarks.value = bookmarkValue; } },
1312
1353
  ...(userId === undefined ? {} : { userId }),
1313
1354
  };
1314
- const globalDb: DatabaseWriterLike = ${oe}?.(env, globalRequest) ?? globalDbStub;
1315
- `:"",Rt=$r(p&&A,oe),xt=l?` protected override roomHandlerPath(topic: string): string | undefined {
1355
+ const globalDb: DatabaseWriterLike = ${le}?.(env, globalRequest) ?? globalDbStub;
1356
+ `:"",Dt=Wr(p&&T,le),Tt=h?` protected override roomHandlerPath(topic: string): string | undefined {
1316
1357
  // Own properties only: a plain object would resolve \`toString\` and the like to inherited functions.
1317
1358
  return Object.hasOwn(LUNORA_ROOMS, topic) ? LUNORA_ROOMS[topic] : undefined;
1318
1359
  }
1319
- `:"",Ot=b?` protected override socketRoute(path: string): { auth: boolean; functionPath: string } | undefined {
1360
+ `:"",_t=f?` protected override socketRoute(path: string): { auth: boolean; functionPath: string } | undefined {
1320
1361
  return LUNORA_SOCKETS[path];
1321
1362
  }
1322
- `:"",{externalSourceOverride:At,sourceBootstrap:Dt,sourceClientCacheConst:Tt}=qr(C),Ct=`
1363
+ `:"",{externalSourceOverride:Et,sourceBootstrap:It,sourceClientCacheConst:Ct}=Hr(P),Lt=`
1364
+ private shardInitDeferred = false;
1365
+ private deferredShardInit?: Promise<void>;
1366
+
1323
1367
  protected override async runShardInit(): Promise<void> {
1324
1368
  this.ensureMigrated();
1325
- ${te?` clearMemoryTables(this.sql as SqlExec, schema as unknown as SchemaLike);
1369
+ ${oe?` clearMemoryTables(this.sql as SqlExec, schema as unknown as SchemaLike);
1326
1370
  `:""}
1371
+ if (this.blockedUniqueIndexes.length > 0) {
1372
+ this.shardInitDeferred = true;
1373
+
1374
+ return;
1375
+ }
1376
+
1327
1377
  await this.dispatchShardInit();
1328
1378
  }
1329
- `,_t=re.length>0?`
1379
+
1380
+ protected override async ensureShardInit(): Promise<void> {
1381
+ await super.ensureShardInit();
1382
+
1383
+ if (!this.shardInitDeferred) {
1384
+ return;
1385
+ }
1386
+
1387
+ try {
1388
+ this.ensureMigrated();
1389
+ } catch (error: unknown) {
1390
+ this.recordShardInitError("__shard_init__", error);
1391
+
1392
+ return;
1393
+ }
1394
+
1395
+ if (this.blockedUniqueIndexes.length > 0) {
1396
+ return;
1397
+ }
1398
+
1399
+ this.deferredShardInit ??= (async (): Promise<void> => {
1400
+ try {
1401
+ await this.dispatchShardInit();
1402
+ } finally {
1403
+ this.shardInitDeferred = false;
1404
+ }
1405
+ })();
1406
+
1407
+ await this.deferredShardInit;
1408
+ }
1409
+ `,Pt=ie.length>0?`
1330
1410
  if (LUNORA_TTL_SWEEPS.length > 0) {
1331
1411
  void this.scheduleTtlSweep();
1332
1412
  }
1333
- `:"",Et=`
1413
+ `:"",Nt=`
1334
1414
  public constructor(state: ShardDOState, env: unknown) {
1335
1415
  super(state, env, {
1336
1416
  // Every writer this file builds spreads the ctxDbTuning() slice —
@@ -1347,7 +1427,7 @@ ${te?` clearMemoryTables(this.sql as SqlExec, schema as unknown as Sc
1347
1427
  // exists — a trigger that fails first still flushes and fuses.
1348
1428
  ...(config.observability === undefined ? {} : { telemetrySink: () => config.observability?.((env ?? {}) as Record<string, unknown>) }),
1349
1429
  });
1350
- ${Dt}${_t} }
1430
+ ${It}${Pt} }
1351
1431
 
1352
1432
  protected override isCacheableQuery(functionPath: string): boolean {
1353
1433
  // NOT \`kind === "query"\` alone. A cache hit answers without running
@@ -1371,7 +1451,7 @@ ${Dt}${_t} }
1371
1451
  protected override isPaidFunction(functionPath: string): boolean {
1372
1452
  return LUNORA_FUNCTIONS[functionPath]?.x402 !== undefined;
1373
1453
  }
1374
- `,ie=c?`
1454
+ `,ue=c?`
1375
1455
  protected override prepareFunction(functionPath: string, reason: "rpc" | "subscription" | "stream" | "reactor"): Promise<void> | undefined {
1376
1456
  const registered = LUNORA_FUNCTIONS[functionPath];
1377
1457
  const allowsInternal = reason === "reactor" || (reason === "rpc" && this.isSystemDispatch());
@@ -1386,25 +1466,38 @@ ${Dt}${_t} }
1386
1466
 
1387
1467
  return loadFunction(functionPath).then(() => undefined);
1388
1468
  }
1389
- `:"",Lt=ie===""?`
1469
+ `:"",$t=ue===""?`
1390
1470
 
1391
- `:`${ie}
1392
- `,It=xr(c),Pt=c?` const preparation = this.prepareFunction(functionPath, "subscription");
1471
+ `:`${ue}
1472
+ `,Mt=V?`
1473
+ protected override sensitiveArgNames(functionPath: string): ReadonlySet<string> {
1474
+ const registered = LUNORA_FUNCTIONS[functionPath];${D?`
1475
+ const shape = functionPath.startsWith("__shape__:") ? LUNORA_SHAPES[functionPath.slice("__shape__:".length)] : undefined;`:""}
1476
+ const fromValidators = sensitiveArgumentNames(registered?.args ?? ${D?"shape?.args ?? ":""}{});
1477
+
1478
+ if (registered?.sensitiveArgs === undefined) {
1479
+ return fromValidators;
1480
+ }
1481
+
1482
+ return new Set([...registered.sensitiveArgs, ...fromValidators]);
1483
+ }
1484
+
1485
+ `:"",qt=Er(c),Ft=c?` const preparation = this.prepareFunction(functionPath, "subscription");
1393
1486
  if (preparation !== undefined) await preparation;
1394
- `:"",Nt=Ar.replace("__PREPARE_FUNCTION__",Pt),Mt=Tr(l,c),$t=z?`
1487
+ `:"",Ut=Cr.replace("__PREPARE_FUNCTION__",Ft),Bt=Pr(h,c),jt=ee?`
1395
1488
  const facade = db as unknown as Record<string, ReturnType<typeof bindTableFacade>>;
1396
1489
  ${i.tables.map(s=>` facade[${JSON.stringify(s.name)}] = bindTableFacade(db, ${JSON.stringify(s.name)});`).join(`
1397
1490
  `)}
1398
- `:"",qt=`${y.everyBuild}${T.build}${H.build}
1491
+ `:"",Wt=`${k.everyBuild}${L.build}${Q.build}
1399
1492
  const secrets = createSecrets(env);
1400
- `,Ft=`${y.everyFields}${T.contextField}${W.contextField}${H.contextField}
1401
- secrets,`,Ut=W.build,Bt=R?`
1493
+ `,Ht=`${k.everyFields}${L.contextField}${G.contextField}${Q.contextField}
1494
+ secrets,`,Vt=G.build,Kt=A?`
1402
1495
  const live = {
1403
1496
  publish: async (ref: { __lunoraLive: string; topic: string }, payload: unknown, publishOptions?: { shardKey?: string }): Promise<void> => {
1404
1497
  await this.publishLiveFromAction(ref.topic, payload, { ...publishOptions, stream: ref.__lunoraLive });
1405
1498
  },
1406
1499
  };
1407
- `:"",jt=[...y.actionFields,...x.length>0?["services"]:[],...R?["live"]:[]],Wt=`${y.actionBuild}${V.build}${Bt}`;return`${fr}${_.join(`
1500
+ `:"",Gt=[...k.actionFields,...C.length>0?["services"]:[],...A?["live"]:[]],Qt=`${k.actionBuild}${J.build}${Kt}`;return`${Sr}${N.join(`
1408
1501
  `)}
1409
1502
 
1410
1503
  type FunctionKind = "action" | "mutation" | "query";
@@ -1414,13 +1507,13 @@ interface FunctionReference {
1414
1507
  }
1415
1508
 
1416
1509
  /** Foreign-key columns per table (\`v.id("target")\` fields) for the data browser. */
1417
- const LUNORA_TABLE_REFS = ${h(ze,"Record<string, Record<string, string>>")};
1510
+ const LUNORA_TABLE_REFS = ${u(et,"Record<string, Record<string, string>>")};
1418
1511
 
1419
1512
  /** Declared indexes per table (secondary, search, geo, rank, vector) for the schema viewer. */
1420
- const LUNORA_TABLE_INDEXES = ${h(Ye,'Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>>')};
1513
+ const LUNORA_TABLE_INDEXES = ${u(tt,'Record<string, Array<{ fields: string[]; name: string; type: "geo" | "index" | "rank" | "search" | "vector"; unique?: boolean }>>')};
1421
1514
 
1422
1515
  /** Columns per table (typed, with PK/FK markers) for the studio's schema diagram, served via \`__lunora_admin__:describeTable\`. */
1423
- const LUNORA_TABLE_COLUMNS = ${h(Xe,`Record<
1516
+ const LUNORA_TABLE_COLUMNS = ${u(rt,`Record<
1424
1517
  string,
1425
1518
  Array<{
1426
1519
  bucket?: string;
@@ -1437,16 +1530,16 @@ const LUNORA_TABLE_COLUMNS = ${h(Xe,`Record<
1437
1530
  >`)};
1438
1531
 
1439
1532
  /** Storage-key columns per table (\`v.storage(...)\` fields) for the file browser's records↔files join. */
1440
- const LUNORA_STORAGE_COLUMNS = ${h(Ze,"Record<string, string[]>")};
1533
+ const LUNORA_STORAGE_COLUMNS = ${u(nt,"Record<string, string[]>")};
1441
1534
 
1442
1535
  /** Declarative TTL policies (\`.ttl(field, { after? })\`) the DO alarm sweep auto-expires rows for. */
1443
- const LUNORA_TTL_SWEEPS = ${Qt(re,"Array<{ after?: number; field: string; softDeleteField?: string; table: string }>")};
1536
+ const LUNORA_TTL_SWEEPS = ${Zt(ie,"Array<{ after?: number; field: string; softDeleteField?: string; table: string }>")};
1444
1537
 
1445
1538
  /** Static schema advisories (computed by @lunora/advisor at codegen time) served via \`__lunora_admin__:getAdvisories\`. */
1446
- const LUNORA_ADVISORY_RULES = ${h(Ue,"Record<string, Partial<AdvisoryFinding>>")};
1539
+ const LUNORA_ADVISORY_RULES = ${u(He,"Record<string, Partial<AdvisoryFinding>>")};
1447
1540
 
1448
1541
  /** Per-finding rows; rule-level text lives once in \`LUNORA_ADVISORY_RULES\` and is merged back on first read. */
1449
- const LUNORA_ADVISORY_ROWS = ${h(Be,"Array<Partial<AdvisoryFinding> & { name: string }>")};
1542
+ const LUNORA_ADVISORY_ROWS = ${u(Ve,"Array<Partial<AdvisoryFinding> & { name: string }>")};
1450
1543
 
1451
1544
  const LUNORA_ADVISORIES = ((): (() => AdvisoryFinding[]) => {
1452
1545
  let cached: AdvisoryFinding[] | undefined;
@@ -1454,20 +1547,23 @@ const LUNORA_ADVISORIES = ((): (() => AdvisoryFinding[]) => {
1454
1547
  })();
1455
1548
 
1456
1549
  /** Every declared procedure (discovered by @lunora/codegen) served via \`__lunora_admin__:getAdvisorProcedures\` — the health map's denominator. */
1457
- const LUNORA_ADVISOR_PROCEDURES = ${h(je,"AdvisorProcedure[]")};
1550
+ const LUNORA_ADVISOR_PROCEDURES = ${u(Ke,"AdvisorProcedure[]")};
1458
1551
 
1459
1552
  /** Read-only RLS metadata (policies + roles discovered from \`.use(rls(...))\` chains) served via \`__lunora_admin__:rlsPolicies\` for the studio's RLS inspector. */
1460
- const LUNORA_RLS_METADATA = ${h(X,"RlsPoliciesResult")};
1461
- ${rt}
1553
+ const LUNORA_RLS_METADATA = ${u(ne,"RlsPoliciesResult")};
1554
+ ${ot}
1462
1555
  /** Read-only masking metadata (table + column + strategy discovered from \`.use(mask(...))\` chains) served via \`__lunora_admin__:maskPolicies\` for the studio's data-browser mask preview. */
1463
- const LUNORA_MASK_METADATA = ${h(We,"MaskPoliciesResult")};
1556
+ const LUNORA_MASK_METADATA = ${u(Ge,"MaskPoliciesResult")};
1464
1557
 
1465
1558
  /** Read-only storage access-rule metadata (discovered from \`.use(storageRules(...))\` chains) served via \`__lunora_admin__:storageRules\` for the studio's access-rules view. */
1466
- const LUNORA_STORAGE_RULES = ${h(He,"StorageRulesResult")};
1559
+ const LUNORA_STORAGE_RULES = ${u(Qe,"StorageRulesResult")};
1467
1560
 
1468
1561
  /** Which optional package-backed features this app wires up (discovered from imports / \`ctx.*\` reads / schema signals) served via \`__lunora_admin__:studioFeatures\` so the studio hides nav pages whose package isn't enabled. */
1469
- const LUNORA_STUDIO_FEATURES = ${h(Ve,"StudioFeaturesResult")};
1470
- ${he}${G.constant}${j.constant}${Ke}${Qe}${Oe}${Ce}${be}${ke}${V.specs}${Ie}
1562
+ const LUNORA_STUDIO_FEATURES = ${u(Je,"StudioFeaturesResult")};
1563
+
1564
+ /** How long a shard with a UNIQUE index blocked by duplicate rows serves the cached diagnostic before re-attempting the build. */
1565
+ const BLOCKED_MIGRATION_RETRY_MS = 5000;
1566
+ ${fe}${z.constant}${K.constant}${Ye}${Xe}${_e}${Le}${ke}${Ae}${J.specs}${Me}
1471
1567
  export interface ShardDOConfig {
1472
1568
  /** Opt into change-data-capture: records a post-image to \`__cdc_log\` on every write (backs streaming export + replay-PITR). */
1473
1569
  cdc?: boolean;
@@ -1484,25 +1580,27 @@ export interface ShardDOConfig {
1484
1580
  /** \`unknown\` because \`@lunora/scheduler\`'s \`Scheduler\` is not assignable to \`SchedulerLike\`; the shard casts it. */
1485
1581
  scheduler?: (env: Record<string, unknown>) => unknown;
1486
1582
  /** \`origin\` is the origin the current \`/rpc\` request reached the worker on — the fallback base for signed object URLs when no \`publicBaseUrl\` is configured. \`undefined\` off the synchronous dispatch path. */
1487
- storage?: (env: Record<string, unknown>, origin?: string) => unknown;${dt}${y.configFields}${T.configField}${Ne}${ct}${lt}${ut}${G.configField}
1583
+ storage?: (env: Record<string, unknown>, origin?: string) => unknown;${ht}${k.configFields}${L.configField}${Fe}${pt}${mt}${gt}${z.configField}
1488
1584
  }
1489
- ${E("schedulerStub",pt,["cancel","runAfter","runAt"])}${E("storageStub",mt,["createMultipartUpload","delete","download","generateUploadUrl","getMetadata","getPresignedUrl","getSignedUrl","getUrl","head","list","resumeMultipartUpload","store","upload"],{sync:["getUrl","resumeMultipartUpload"]})}${gt}${Tt}${wt}${y.stubs}${qe}
1490
- ${It}
1585
+ ${$("schedulerStub",bt,["cancel","runAfter","runAt"])}${$("storageStub",wt,["createMultipartUpload","delete","download","generateUploadUrl","getMetadata","getPresignedUrl","getSignedUrl","getUrl","head","list","resumeMultipartUpload","store","upload"],{sync:["getUrl","resumeMultipartUpload"]})}${yt}${Ct}${St}${k.stubs}${je}
1586
+ ${qt}
1491
1587
 
1492
1588
  /**
1493
1589
  * Build the project's shard Durable Object. Export the result as \`ShardDO\`
1494
1590
  * from the worker entry so wrangler binds it by name.
1495
1591
  */
1496
1592
  export const createShardDO = (config: ShardDOConfig = {}): new (state: ShardDOState, env: unknown) => ShardDOBase =>
1497
- class extends ShardDOBase {${Et}
1498
- private migrated = false;${Lt}${Mt}
1499
- ${ae.override}
1500
- ${Nt}
1501
- ${et}${at}${Rt}${At}
1593
+ class extends ShardDOBase {${Nt}
1594
+ private blockedUniqueIndexes: readonly string[] = [];
1595
+ private migrated = false;
1596
+ private migrationRetryAt = 0;${$t}${Mt}${Bt}
1597
+ ${de.override}
1598
+ ${Ut}
1599
+ ${at}${dt}${Dt}${Et}
1502
1600
  protected override lifecycleHookPaths(event: "connect" | "disconnect" | "init" | "reactor" | "whisper"): readonly string[] {
1503
1601
  return LUNORA_LIFECYCLE_HOOKS[event];
1504
1602
  }
1505
- ${xt}${Ot}${se}${G.override}${Ct}
1603
+ ${Tt}${_t}${ce}${z.override}${Lt}
1506
1604
  // One \`onQueryChange\` dispatch. Mirrors \`executeSubscription\` — the
1507
1605
  // socket-terminated half of the same reactivity — and differs only in who
1508
1606
  // consumes the result: the base's \`dispatchReactors\` stores the digest as
@@ -1540,7 +1638,7 @@ ${c?` const requestScope = this.captureRequestScope();
1540
1638
  return undefined;
1541
1639
  }
1542
1640
 
1543
- this.ensureMigrated();
1641
+ this.ensureServable();
1544
1642
 
1545
1643
  const footprint = createReadFootprint();
1546
1644
  const ctx = this.buildCtx({ functionPath, headroom: this.subscriptionHeadroom(), onRead: footprint.onRead, onReadRange: footprint.onReadRange, trusted: true });
@@ -1601,7 +1699,7 @@ ${c?` const requestScope = this.captureRequestScope();
1601
1699
  protected override studioFeatures(): StudioFeaturesResult {
1602
1700
  return LUNORA_STUDIO_FEATURES();
1603
1701
  }
1604
- ${j.evaluateOverride}${j.subscriptionOverride}${Ge}${Je}
1702
+ ${K.evaluateOverride}${K.subscriptionOverride}${ze}${Ze}
1605
1703
  protected override advisories(): AdvisoryFinding[] {
1606
1704
  return LUNORA_ADVISORIES();
1607
1705
  }
@@ -1610,17 +1708,44 @@ ${j.evaluateOverride}${j.subscriptionOverride}${Ge}${Je}
1610
1708
  return LUNORA_ADVISOR_PROCEDURES();
1611
1709
  }
1612
1710
 
1613
- ${Sr}
1711
+ ${Tr}
1614
1712
 
1713
+ /**
1714
+ * Migrate the base schema. A UNIQUE index that existing duplicate rows block
1715
+ * is deferred, not thrown: the rest of the pass completes so the admin path
1716
+ * (including the data migration that de-duplicates the table) keeps working.
1717
+ * User dispatch goes through \`ensureServable\`, which refuses until the
1718
+ * index exists. \`migrated\` stays false while one is outstanding, but the
1719
+ * retry (a schema-ledger write plus a full-table duplicate scan per blocked
1720
+ * index) runs at most once per \`BLOCKED_MIGRATION_RETRY_MS\`; in between,
1721
+ * callers see the cached diagnostics. The first call after a cold start
1722
+ * always migrates, and an admin data migration resets the clock so the
1723
+ * de-dup that unblocks the index takes effect on the next call.
1724
+ */
1615
1725
  protected override ensureMigrated(): void {
1616
1726
  if (this.migrated) {
1617
1727
  return;
1618
1728
  }
1619
1729
 
1620
- runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false${pe} });
1621
- this.migrated = true;
1730
+ const now = Date.now();
1731
+
1732
+ if (this.blockedUniqueIndexes.length > 0 && now < this.migrationRetryAt) {
1733
+ return;
1734
+ }
1735
+
1736
+ this.blockedUniqueIndexes = runShardMigrations(this.sql as SqlExec, schema as unknown as SchemaLike, { cdc: config.cdc ?? false, deferBlockedUniqueIndexes: true${be} });
1737
+ this.migrated = this.blockedUniqueIndexes.length === 0;
1738
+ this.migrationRetryAt = now + BLOCKED_MIGRATION_RETRY_MS;
1739
+ }
1740
+
1741
+ private ensureServable(): void {
1742
+ this.ensureMigrated();
1743
+
1744
+ if (this.blockedUniqueIndexes.length > 0) {
1745
+ throw new LunoraError("INTERNAL", this.blockedUniqueIndexes.join("; "));
1746
+ }
1622
1747
  }
1623
- ${J?`
1748
+ ${Z?`
1624
1749
  protected override runShardSearchBackfill(options: { maxPages?: number }): SearchBackfillProgress {
1625
1750
  // Migrations create the fts5 companions; without them every backfill
1626
1751
  // statement would raise "no such table" on a shard that has never
@@ -1629,7 +1754,7 @@ ${J?`
1629
1754
 
1630
1755
  return backfillSearchIndexes(this.sql as SqlExec, schema as unknown as SchemaLike, options);
1631
1756
  }
1632
- `:""}${ft}
1633
- ${Rr({lazyFunctions:c,actionOnlyFields:jt,agentsBuild:_e,agentsContextField:Ee,containersBuild:Se,containersContextField:Re,databaseOptions:yt,everyContextBuild:qt,everyContextField:Ft,facadeBlock:$t,globalDatabaseLine:St,notifyBuild:Ut,ormContextField:kt,paymentsBuild:Pe,paymentsContextField:Me,queuesBuild:me,queuesContextField:ge,topicsBuild:we,topicsContextField:ye,vectorsBuild:bt,vectorsContextField:vt,workflowsBuild:Ae,workflowsContextField:De,actionOnlyBuild:Wt})}
1757
+ `:""}${vt}
1758
+ ${_r({hasSensitiveArgs:V,lazyFunctions:c,actionOnlyFields:Gt,agentsBuild:Pe,agentsContextField:Ne,containersBuild:Oe,containersContextField:De,databaseOptions:Rt,everyContextBuild:Wt,everyContextField:Ht,facadeBlock:jt,globalDatabaseLine:Ot,notifyBuild:Vt,ormContextField:At,paymentsBuild:qe,paymentsContextField:Ue,queuesBuild:we,queuesContextField:ye,topicsBuild:Se,topicsContextField:Re,vectorsBuild:kt,vectorsContextField:xt,workflowsBuild:Ee,workflowsContextField:Ie,actionOnlyBuild:Qt})}
1634
1759
  };
1635
- `};export{_r as b,Xr as e};
1760
+ `};export{$r as b,on as e};