@lunora/do 1.0.0-alpha.26 → 1.0.0-alpha.28

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.
package/dist/index.d.mts CHANGED
@@ -756,6 +756,15 @@ declare class ReactiveCache {
756
756
  * RLS-filtered list, or `getMyProfile()` with no args) would otherwise memoize
757
757
  * the first caller's result under an identity-independent key and serve it to
758
758
  * everyone. Anonymous/subscription callers pass `null` (their own bucket).
759
+ *
760
+ * The discriminator is an opaque `null | string`, NOT just a userId: the wiring
761
+ * layer (`ShardDO#runCachedQuery`) folds the FULL resolved identity — userId
762
+ * plus the `getIdentity()` claims (active-org / role / tenant) — into a single
763
+ * `stableStringify`'d string before it reaches here. That matters because RLS
764
+ * can key on a claim OTHER than userId: a multi-tenant caller whose userId is
765
+ * stable but whose active-org claim varies request-to-request must NOT share a
766
+ * cache entry across those requests. Encoding the whole identity, not the
767
+ * userId alone, is what keeps those contexts isolated.
759
768
  */
760
769
  declare const reactiveCacheKey: (functionPath: string, args: Record<string, unknown>, identity: null | string) => string;
761
770
  /** The system tables `ctx.db.system` can read. */
@@ -1867,7 +1876,9 @@ interface DatabaseWriterLike {
1867
1876
  * since a global table has no shard boundaries to merge across.
1868
1877
  */
1869
1878
  rankPageRows?: (tableName: string, indexName: string, options?: RankPageOptions) => Promise<ShardRankPageResult>;
1870
- replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
1879
+ replace: (id: string, document: Record<string, unknown>, expectedTable?: string, options?: {
1880
+ allowExplicitId?: boolean;
1881
+ }) => Promise<void>;
1871
1882
  /**
1872
1883
  * Un-soft-delete a row: clears the `.softDelete()` marker column (a by-id
1873
1884
  * UPDATE, so it works on a row that list reads currently hide). Throws when
@@ -4344,6 +4355,8 @@ declare abstract class ShardDO {
4344
4355
  * cleared in the `finally` block of `fetch` like the other per-request fields.
4345
4356
  */
4346
4357
  private currentRequestIp;
4358
+ /** W3C `traceparent` of the inbound RPC; forwarded onto outbound container fetches. */
4359
+ private currentRequestTraceparent;
4347
4360
  /**
4348
4361
  * Client-issued idempotency key for the in-flight mutation, forwarded via the
4349
4362
  * `x-lunora-mutation-id` header. When set, the dispatch path dedups the call
@@ -4754,6 +4767,12 @@ declare abstract class ShardDO {
4754
4767
  */
4755
4768
  protected getCurrentIp(): string | undefined;
4756
4769
  /**
4770
+ * W3C `traceparent` of the inbound RPC (forwarded by the runtime), or
4771
+ * `undefined`. `buildCtx` passes it to `createContainerContext` so outbound
4772
+ * container fetches carry it and the container's spans join the same trace.
4773
+ */
4774
+ protected getCurrentTraceparent(): string | undefined;
4775
+ /**
4757
4776
  * Identity claims (email, name, roles, …) forwarded by the runtime's
4758
4777
  * `resolveIdentity` hook. Returns `undefined` for anonymous requests
4759
4778
  * or when no extra claims were attached. Use this to populate the
package/dist/index.d.ts CHANGED
@@ -756,6 +756,15 @@ declare class ReactiveCache {
756
756
  * RLS-filtered list, or `getMyProfile()` with no args) would otherwise memoize
757
757
  * the first caller's result under an identity-independent key and serve it to
758
758
  * everyone. Anonymous/subscription callers pass `null` (their own bucket).
759
+ *
760
+ * The discriminator is an opaque `null | string`, NOT just a userId: the wiring
761
+ * layer (`ShardDO#runCachedQuery`) folds the FULL resolved identity — userId
762
+ * plus the `getIdentity()` claims (active-org / role / tenant) — into a single
763
+ * `stableStringify`'d string before it reaches here. That matters because RLS
764
+ * can key on a claim OTHER than userId: a multi-tenant caller whose userId is
765
+ * stable but whose active-org claim varies request-to-request must NOT share a
766
+ * cache entry across those requests. Encoding the whole identity, not the
767
+ * userId alone, is what keeps those contexts isolated.
759
768
  */
760
769
  declare const reactiveCacheKey: (functionPath: string, args: Record<string, unknown>, identity: null | string) => string;
761
770
  /** The system tables `ctx.db.system` can read. */
@@ -1867,7 +1876,9 @@ interface DatabaseWriterLike {
1867
1876
  * since a global table has no shard boundaries to merge across.
1868
1877
  */
1869
1878
  rankPageRows?: (tableName: string, indexName: string, options?: RankPageOptions) => Promise<ShardRankPageResult>;
1870
- replace: (id: string, document: Record<string, unknown>, expectedTable?: string) => Promise<void>;
1879
+ replace: (id: string, document: Record<string, unknown>, expectedTable?: string, options?: {
1880
+ allowExplicitId?: boolean;
1881
+ }) => Promise<void>;
1871
1882
  /**
1872
1883
  * Un-soft-delete a row: clears the `.softDelete()` marker column (a by-id
1873
1884
  * UPDATE, so it works on a row that list reads currently hide). Throws when
@@ -4344,6 +4355,8 @@ declare abstract class ShardDO {
4344
4355
  * cleared in the `finally` block of `fetch` like the other per-request fields.
4345
4356
  */
4346
4357
  private currentRequestIp;
4358
+ /** W3C `traceparent` of the inbound RPC; forwarded onto outbound container fetches. */
4359
+ private currentRequestTraceparent;
4347
4360
  /**
4348
4361
  * Client-issued idempotency key for the in-flight mutation, forwarded via the
4349
4362
  * `x-lunora-mutation-id` header. When set, the dispatch path dedups the call
@@ -4754,6 +4767,12 @@ declare abstract class ShardDO {
4754
4767
  */
4755
4768
  protected getCurrentIp(): string | undefined;
4756
4769
  /**
4770
+ * W3C `traceparent` of the inbound RPC (forwarded by the runtime), or
4771
+ * `undefined`. `buildCtx` passes it to `createContainerContext` so outbound
4772
+ * container fetches carry it and the container's spans join the same trace.
4773
+ */
4774
+ protected getCurrentTraceparent(): string | undefined;
4775
+ /**
4757
4776
  * Identity claims (email, name, roles, …) forwarded by the runtime's
4758
4777
  * `resolveIdentity` hook. Returns `undefined` for anonymous requests
4759
4778
  * or when no extra claims were attached. Use this to populate the
package/dist/index.mjs CHANGED
@@ -3,13 +3,13 @@ export { AGGREGATE_SQL_FUNCTION, aggregateSqlFunction, matchesStaticWhere, norma
3
3
  export { aggregateTableName, coerceAggregateNumber, encodeAggregateKey, foldAggregateTally, readAggregateValue } from './packem_shared/aggregateTableName-CxNqY1Sl.mjs';
4
4
  export { CountRlsUnsupportedError, mergeWhere, planAggregateLookup, selectIndexForAggregate, selectIndexForCount, selectIndexForGroupBy } from './packem_shared/CountRlsUnsupportedError-BGxj0pgS.mjs';
5
5
  export { AUTH_METRICS_BUCKETS_TABLE, AUTH_METRICS_BUCKET_MS, AUTH_METRICS_BUCKET_RETENTION, AUTH_METRICS_TABLE, ensureAuthMetricsTables, readAuthMetrics, recordAuthEvent } from './packem_shared/AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
6
- export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-BdDLev9w.mjs';
7
- export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-DB3IYUR3.mjs';
6
+ export { NotUniqueError, assertValidClientId, createShardCtxDb, normalizeIdStructurally } from './packem_shared/NotUniqueError-BigrdT_W.mjs';
7
+ export { DATA_MIGRATION_STATE_TABLE, readMigrationStatus, runDataMigration } from './packem_shared/DATA_MIGRATION_STATE_TABLE-CYwBpyTr.mjs';
8
8
  export { SCAN_DEP, createDependencyTracker, depKey } from './packem_shared/SCAN_DEP-DLJF8dsj.mjs';
9
9
  export { renderSql } from './packem_shared/renderSql-D6eUcn2N.mjs';
10
10
  export { diffExternalSource } from './packem_shared/diffExternalSource-Cx9HUPJj.mjs';
11
- export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-DNcvoLRT.mjs';
12
- export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-BptUN8CR.mjs';
11
+ export { materializeExternalRows, readExternalSourceBaseline, runExternalSourceTick } from './packem_shared/materializeExternalRows-CTqZisSC.mjs';
12
+ export { isSourceDue, liftSourceId, pullExternalSourceTick } from './packem_shared/isSourceDue-CYkt7Ru8.mjs';
13
13
  export { FUNCTION_METRICS_BUCKETS_TABLE, FUNCTION_METRICS_BUCKET_MS, FUNCTION_METRICS_BUCKET_RETENTION, FUNCTION_METRICS_INDEX_TABLE, FUNCTION_METRICS_TABLE, ensureFunctionMetricsTables, readFunctionMetricBuckets, readFunctionMetricIndexHits, readFunctionMetrics, readFunctionMetricsTotals, recordFunctionMetric } from './packem_shared/FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
14
14
  export { ADMIN_FUNCTIONS, ADMIN_FUNCTION_PREFIX, FLAGS_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, facetColumn, listTables, readTablePage, selectMatchingIds } from './packem_shared/ADMIN_FUNCTIONS-Bxdijn66.mjs';
15
15
  export { LogBuffer } from './packem_shared/LogBuffer-B_Ezju_N.mjs';
@@ -22,19 +22,19 @@ export { ReactiveCache, reactiveCacheKey } from './packem_shared/ReactiveCache-B
22
22
  export { serveRelationFanout } from './packem_shared/serveRelationFanout-C56hKu1O.mjs';
23
23
  export { DEFAULT_MAX_RELATION_KEYS, assertFlatPredicate, assertShapeShardable, containsRelationPredicate, isRelationPredicate, resolveRelationPredicates } from './packem_shared/DEFAULT_MAX_RELATION_KEYS-BEan1CRD.mjs';
24
24
  export { applyOnDelete, fanOutScalarCounts, resolveWith, runRowValidators } from './packem_shared/applyOnDelete-BXSq3S70.mjs';
25
- export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-G1eNK4DQ.mjs';
25
+ export { RLS_UNWRAP_SYMBOL, RlsRequiredError, guardWriter } from './packem_shared/RLS_UNWRAP_SYMBOL-DTvHvRzY.mjs';
26
26
  export { buildFtsMatch, ftsTableName, scoreDocument, stringifySearchText, tokenizeSearch } from './packem_shared/buildFtsMatch-BLEMawrp.mjs';
27
27
  export { M as MIN_ADMIN_TOKEN_LENGTH, a as MIN_AUTH_SECRET_LENGTH, b as buildSecurityAudit } from './packem_shared/security-audit-CucgBice.mjs';
28
- export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-D71QAL5h.mjs';
29
- export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-CpURtawE.mjs';
28
+ export { SESSION_DO_TTL_DEFAULT, SessionDO } from './packem_shared/SESSION_DO_TTL_DEFAULT-BnSKgVO4.mjs';
29
+ export { ROOT_DO_SIZE_WARN_BYTES, ROOT_SHARD_NAME, ShardDO } from './packem_shared/ROOT_DO_SIZE_WARN_BYTES-CszdLJhN.mjs';
30
30
  export { SHARD_REGISTRY_DO_NAME, ShardRegistryDO } from './packem_shared/SHARD_REGISTRY_DO_NAME-D99roc-r.mjs';
31
31
  export { MAX_SQL_ROWS, assertReadonly, runReadonlySql } from './packem_shared/MAX_SQL_ROWS-D57CJaT9.mjs';
32
32
  export { createSystemReader } from './packem_shared/createSystemReader-D12eNH13.mjs';
33
33
  export { ConflictError } from './packem_shared/ConflictError-CLoq37xH.mjs';
34
34
  export { hasTrigger, runTriggers } from './packem_shared/hasTrigger-5N6_Fx0A.mjs';
35
35
  export { compileWhereSql } from './packem_shared/compileWhereSql-DE6yfRcQ.mjs';
36
- export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DZSVKRr7.mjs';
36
+ export { CDC_LOG_TABLE, applyCdcChanges, readCdcChanges, trimCdcChanges } from './packem_shared/CDC_LOG_TABLE-DjJEHiM2.mjs';
37
37
  export { backfillAggregateIndexes, backfillRankIndexes } from './packem_shared/backfillAggregateIndexes-DDoT-UUI.mjs';
38
- export { runShardMigrations } from './packem_shared/runShardMigrations-DeZr0KZp.mjs';
38
+ export { runShardMigrations } from './packem_shared/runShardMigrations-BGx4v2B6.mjs';
39
39
  export { stableStringify } from './packem_shared/stableStringify-MydiuScU.mjs';
40
40
  export { s as subscriptionListDeltas } from './packem_shared/subscription-delivery-CK8qga-k.mjs';
@@ -95,7 +95,7 @@ const applyCdcChange = async (writer, change) => {
95
95
  fields[key] = value;
96
96
  }
97
97
  }
98
- await writer.replace(change.id, fields);
98
+ await writer.replace(change.id, fields, void 0, { allowExplicitId: true });
99
99
  }
100
100
  };
101
101
  const applyCdcChanges = async (writer, changes) => {
@@ -178,7 +178,9 @@ const runDataMigration = async (options) => {
178
178
  if (next !== void 0) {
179
179
  changed += 1;
180
180
  if (!dryRun) {
181
- await writer.replace(String(document["_id"]), { ...next, _creationTime: document["_creationTime"], _id: document["_id"] });
181
+ await writer.replace(String(document["_id"]), { ...next, _creationTime: document["_creationTime"], _id: document["_id"] }, void 0, {
182
+ allowExplicitId: true
183
+ });
182
184
  }
183
185
  }
184
186
  if (!dryRun) {
@@ -3,8 +3,8 @@ import { sql } from 'drizzle-orm';
3
3
  import { matchesStaticWhere, aggregateSqlFunction, normalizeCountArgument, throwingScheduler } from './AGGREGATE_SQL_FUNCTION-CQsu2Xga.mjs';
4
4
  import { encodeAggregateKey, foldAggregateTally, aggregateTableName, coerceAggregateNumber, readAggregateValue } from './aggregateTableName-CxNqY1Sl.mjs';
5
5
  import { mergeWhere, CountRlsUnsupportedError, selectIndexForGroupBy, selectIndexForCount, selectIndexForAggregate } from './CountRlsUnsupportedError-BGxj0pgS.mjs';
6
- import { appendCdcChange } from './CDC_LOG_TABLE-DZSVKRr7.mjs';
7
- export { CDC_LOG_TABLE, applyCdcChanges, bumpCdcEpoch, minCdcSeq, readCdcChanges, readCdcCursor, readCdcEpoch, trimCdcChanges } from './CDC_LOG_TABLE-DZSVKRr7.mjs';
6
+ import { appendCdcChange } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
7
+ export { CDC_LOG_TABLE, applyCdcChanges, bumpCdcEpoch, minCdcSeq, readCdcChanges, readCdcCursor, readCdcEpoch, trimCdcChanges } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
8
8
  import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
9
9
  import { i as isFtsAvailable, D as DOC_COLUMN$1, r as rowToDocument, A as AGG_KEY, a as AGG_VALUE, b as AGG_COUNT, d as aggUpsertSql, j as jsonPathSql, q as quoteIdentifier, t as tableColumns, e as qualifiedJsonPathSql } from './do-sql-BCHCWtrD.mjs';
10
10
  import { param } from './renderSql-D6eUcn2N.mjs';
@@ -16,14 +16,14 @@ import { decodeCursor, normalizeOrderKeys, buildSeekWhere, applySelect, encodeCu
16
16
  import NotFoundError from './NotFoundError-C70b9hLw.mjs';
17
17
  import { assertFlatPredicate, resolveRelationPredicates } from './DEFAULT_MAX_RELATION_KEYS-BEan1CRD.mjs';
18
18
  import { runRowValidators, resolveWith, applyOnDelete, fanOutScalarCounts } from './applyOnDelete-BXSq3S70.mjs';
19
- import { guardWriter } from './RLS_UNWRAP_SYMBOL-G1eNK4DQ.mjs';
19
+ import { guardWriter } from './RLS_UNWRAP_SYMBOL-DTvHvRzY.mjs';
20
20
  import { createSystemReader } from './createSystemReader-D12eNH13.mjs';
21
21
  import { ConflictError } from './ConflictError-CLoq37xH.mjs';
22
22
  import { runTriggers } from './hasTrigger-5N6_Fx0A.mjs';
23
23
  import { compileWhereSql } from './compileWhereSql-DE6yfRcQ.mjs';
24
24
  export { backfillAggregateIndexes, backfillRankIndexes } from './backfillAggregateIndexes-DDoT-UUI.mjs';
25
25
  export { C as CLIENT_WATERMARK_TABLE, G as GLOBAL_SHAPE_SNAPSHOT_TABLE, I as IDEMPOTENCY_TABLE, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, e as deleteGlobalShapeSnapshotsForConnection, m as migrateClientWatermark, b as migrateGlobalShapeSnapshot, r as readClientWatermark, f as readGlobalShapeSnapshot, g as readIdempotent, t as trimIdempotent, w as writeGlobalShapeSnapshot, h as writeIdempotent } from './ctx-db-idempotency-BdcNpvY4.mjs';
26
- export { runShardMigrations } from './runShardMigrations-DeZr0KZp.mjs';
26
+ export { runShardMigrations } from './runShardMigrations-BGx4v2B6.mjs';
27
27
  export { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-Cz9dHyh1.mjs';
28
28
 
29
29
  const rankIndexFieldsUnchanged = (index, previous, next) => {
@@ -1574,7 +1574,7 @@ const createShardCtxDb = (options) => {
1574
1574
  } else {
1575
1575
  id = generateId();
1576
1576
  }
1577
- const creationTime = typeof withDefaults["_creationTime"] === "number" ? withDefaults["_creationTime"] : clock();
1577
+ const creationTime = insertOptions?.allowExplicitId && typeof withDefaults["_creationTime"] === "number" ? withDefaults["_creationTime"] : clock();
1578
1578
  const documentWithMeta = { ...withDefaults, _creationTime: creationTime, _id: id };
1579
1579
  if (hasMatchingTrigger(tableName, "before", "insert")) {
1580
1580
  await fireTriggers("before", "insert", { doc: { ...documentWithMeta }, id, op: "insert", table: tableName });
@@ -1617,7 +1617,7 @@ const createShardCtxDb = (options) => {
1617
1617
  const rows = documents.map((document) => {
1618
1618
  const withDefaults = applyInsertDefaults(definition, document, auth);
1619
1619
  const id = batchOptions?.allowExplicitId === true && typeof withDefaults["_id"] === "string" ? withDefaults["_id"] : generateId();
1620
- const creationTime = typeof withDefaults["_creationTime"] === "number" ? withDefaults["_creationTime"] : clock();
1620
+ const creationTime = batchOptions?.allowExplicitId === true && typeof withDefaults["_creationTime"] === "number" ? withDefaults["_creationTime"] : clock();
1621
1621
  return { creationTime, document: { ...withDefaults, _creationTime: creationTime, _id: id }, id };
1622
1622
  });
1623
1623
  const valuesSql = sql.join(
@@ -1847,12 +1847,12 @@ const createShardCtxDb = (options) => {
1847
1847
  syncRanks(located.tableName, id, void 0, located.row);
1848
1848
  }
1849
1849
  },
1850
- async replace(id, document, expectedTable) {
1850
+ async replace(id, document, expectedTable, replaceOptions) {
1851
1851
  const located = locateRowById(id, expectedTable);
1852
1852
  if (!located) {
1853
1853
  const global = expectedTable === void 0 ? globalFallback() : void 0;
1854
1854
  if (global) {
1855
- await global.replace(id, document);
1855
+ await global.replace(id, document, void 0, replaceOptions);
1856
1856
  return;
1857
1857
  }
1858
1858
  throw new LunoraError("INTERNAL", `document not found: ${id}`);
@@ -1863,7 +1863,7 @@ const createShardCtxDb = (options) => {
1863
1863
  throw new LunoraError("INTERNAL", `unknown table: ${tableName}`);
1864
1864
  }
1865
1865
  assertNoExplicitUndefined("replace", document);
1866
- const creationTime = typeof document["_creationTime"] === "number" ? document["_creationTime"] : clock();
1866
+ const creationTime = replaceOptions?.allowExplicitId && typeof document["_creationTime"] === "number" ? document["_creationTime"] : clock();
1867
1867
  const replaced = { ...document, _creationTime: creationTime, _id: id };
1868
1868
  applyOnUpdate(tableDefinition, document, replaced, auth);
1869
1869
  runRowValidators(tableDefinition, replaced);
@@ -120,9 +120,9 @@ const guardWriter = (raw, schema, tableOfId) => {
120
120
  guardTable(tableName);
121
121
  return base.rankPage(tableName, indexName, options);
122
122
  },
123
- replace: async (id, document, expectedTable) => {
123
+ replace: async (id, document, expectedTable, options) => {
124
124
  await guardById(id, expectedTable);
125
- return base.replace(id, document, expectedTable);
125
+ return base.replace(id, document, expectedTable, options);
126
126
  },
127
127
  restore: async (id, expectedTable) => {
128
128
  await guardById(id, expectedTable);
@@ -1,10 +1,11 @@
1
1
  import { LunoraError, toErrorBody } from '@lunora/errors';
2
2
  import { drizzle } from 'drizzle-orm/durable-sqlite';
3
+ import { c as constantTimeEqual } from './constant-time-equal-BVRWZgES.mjs';
3
4
  import { j as jsonResponse } from './json-response-BdbtpOhm.mjs';
4
5
  import { e as encodeWire, a as awaitWsDrain, t as trySendFrame, d as decodeWire, s as subscriptionListDeltas, b as sendDeltaFrames } from './subscription-delivery-CK8qga-k.mjs';
5
6
  import { parseExportShardArgs, parseImportShardArgs } from './exportShardRows-Dy3oFZ26.mjs';
6
7
  import { recordAuthEvent, readAuthMetrics } from './AUTH_METRICS_BUCKETS_TABLE-CiHHYeJi.mjs';
7
- import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-DB3IYUR3.mjs';
8
+ import { DATA_MIGRATION_STATE_TABLE, readMigrationStatus } from './DATA_MIGRATION_STATE_TABLE-CYwBpyTr.mjs';
8
9
  import { SCAN_DEP, createDependencyTracker, tableFromDepKey } from './SCAN_DEP-DLJF8dsj.mjs';
9
10
  import { readFunctionMetricsTotals, readFunctionMetricIndexHits, recordFunctionMetric, mergeScanAttribution, readFunctionMetrics, readFunctionMetricBuckets } from './FUNCTION_METRICS_BUCKETS_TABLE-UDNVD7FS.mjs';
10
11
  import { createFanoutCounters, ADMIN_FUNCTION_PREFIX, RELATION_FUNCTION_PREFIX, selectMatchingIds, ADMIN_FUNCTIONS, findStorageReferences, listTables, summarizeSubscriptions, summarizeFanoutTopics, readTablePage, facetColumn, FLAGS_FUNCTION_PREFIX, recordFanoutPass, MAX_PAGE_SIZE } from './ADMIN_FUNCTIONS-Bxdijn66.mjs';
@@ -18,7 +19,7 @@ import { i as isDevEnvironment, c as buildSettings, b as buildSecurityAudit } fr
18
19
  import { runReadonlySql } from './MAX_SQL_ROWS-D57CJaT9.mjs';
19
20
  import { ConflictError } from './ConflictError-CLoq37xH.mjs';
20
21
  import { e as deleteGlobalShapeSnapshotsForConnection, g as readIdempotent, h as writeIdempotent, t as trimIdempotent, r as readClientWatermark, m as migrateClientWatermark, c as advanceClientWatermark, d as deleteGlobalShapeSnapshot, f as readGlobalShapeSnapshot, w as writeGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
21
- import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-DZSVKRr7.mjs';
22
+ import { CDC_LOG_TABLE, readCdcChanges, readCdcCursor, readCdcEpoch, minCdcSeq, bumpCdcEpoch } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
22
23
  import { a as selectShapeMemberIds, s as selectShapeRows } from './ctx-db-shapes-Cz9dHyh1.mjs';
23
24
 
24
25
  const MAX_BATCH_ENTRIES = 500;
@@ -399,18 +400,6 @@ const relaySecretOf = (env) => {
399
400
  const value = env?.[RELAY_SECRET_KEY];
400
401
  return typeof value === "string" && value.length > 0 ? value : void 0;
401
402
  };
402
- const constantTimeEqual$1 = (a, b) => {
403
- if (a.length !== b.length) {
404
- return false;
405
- }
406
- let mismatch = 0;
407
- for (let index = 0; index < a.length; index += 1) {
408
- const charA = a.charCodeAt(index);
409
- const charB = b.charCodeAt(index);
410
- mismatch |= charA ^ charB;
411
- }
412
- return mismatch === 0;
413
- };
414
403
  const signRelayBody = async (secret, body) => {
415
404
  const encoder = new TextEncoder();
416
405
  const key = await crypto.subtle.importKey("raw", encoder.encode(secret), { hash: "SHA-256", name: "HMAC" }, false, ["sign"]);
@@ -463,7 +452,7 @@ class RelayLink {
463
452
  if (secret !== void 0) {
464
453
  const supplied = request.headers.get(RELAY_SIGNATURE_HEADER);
465
454
  const expected = await signRelayBody(secret, raw);
466
- if (supplied === null || !constantTimeEqual$1(supplied, expected)) {
455
+ if (supplied === null || !constantTimeEqual(supplied, expected)) {
467
456
  return new Response("forbidden", { status: 403 });
468
457
  }
469
458
  }
@@ -1894,16 +1883,6 @@ const extractBearerToken = (authorization) => {
1894
1883
  const value = rest.join(" ").trim();
1895
1884
  return value.length > 0 ? value : void 0;
1896
1885
  };
1897
- const constantTimeEqual = (a, b) => {
1898
- const max = Math.max(a.length, b.length);
1899
- let diff = a.length ^ b.length;
1900
- for (let index = 0; index < max; index += 1) {
1901
- const charA = index < a.length ? a.charCodeAt(index) : 0;
1902
- const charB = index < b.length ? b.charCodeAt(index) : 0;
1903
- diff |= charA ^ charB;
1904
- }
1905
- return diff === 0;
1906
- };
1907
1886
  class ShardDO {
1908
1887
  /**
1909
1888
  * Per-socket cap on concurrent stream iterators. Each in-flight stream
@@ -2038,6 +2017,8 @@ class ShardDO {
2038
2017
  * cleared in the `finally` block of `fetch` like the other per-request fields.
2039
2018
  */
2040
2019
  currentRequestIp;
2020
+ /** W3C `traceparent` of the inbound RPC; forwarded onto outbound container fetches. */
2021
+ currentRequestTraceparent;
2041
2022
  /**
2042
2023
  * Client-issued idempotency key for the in-flight mutation, forwarded via the
2043
2024
  * `x-lunora-mutation-id` header. When set, the dispatch path dedups the call
@@ -2356,6 +2337,7 @@ class ShardDO {
2356
2337
  this.currentRequestIdentity = parseIdentityHeader(request.headers.get("x-lunora-identity"));
2357
2338
  this.currentRequestIp = request.headers.get("x-lunora-client-ip") ?? void 0;
2358
2339
  this.currentRequestSystem = request.headers.get("x-lunora-system") === "1";
2340
+ this.currentRequestTraceparent = request.headers.get("traceparent") ?? void 0;
2359
2341
  this.currentRequestReadTables = void 0;
2360
2342
  this.currentRequestCacheHit = void 0;
2361
2343
  this.metrics.requests += 1;
@@ -2422,6 +2404,7 @@ class ShardDO {
2422
2404
  this.currentRequestIdentity = void 0;
2423
2405
  this.currentRequestIp = void 0;
2424
2406
  this.currentRequestSystem = false;
2407
+ this.currentRequestTraceparent = void 0;
2425
2408
  this.currentScannedTables = void 0;
2426
2409
  this.currentIndexHits = void 0;
2427
2410
  this.currentRequestReadTables = void 0;
@@ -2840,6 +2823,14 @@ class ShardDO {
2840
2823
  getCurrentIp() {
2841
2824
  return this.currentRequestIp;
2842
2825
  }
2826
+ /**
2827
+ * W3C `traceparent` of the inbound RPC (forwarded by the runtime), or
2828
+ * `undefined`. `buildCtx` passes it to `createContainerContext` so outbound
2829
+ * container fetches carry it and the container's spans join the same trace.
2830
+ */
2831
+ getCurrentTraceparent() {
2832
+ return this.currentRequestTraceparent;
2833
+ }
2843
2834
  /**
2844
2835
  * Identity claims (email, name, roles, …) forwarded by the runtime's
2845
2836
  * `resolveIdentity` hook. Returns `undefined` for anonymous requests
@@ -3809,8 +3800,17 @@ class ShardDO {
3809
3800
  const tracker = createDependencyTracker();
3810
3801
  this.currentTracker = tracker;
3811
3802
  const hitsBefore = this.reactiveCache.stats().hits;
3803
+ const userId = this.getCurrentUserId();
3804
+ const claims = this.getCurrentIdentity();
3805
+ const identity = userId === void 0 && claims === void 0 ? (
3806
+ // eslint-disable-next-line unicorn/no-null -- reactiveCacheKey's identity arg is `null | string`; null is the documented "anonymous caller" discriminator
3807
+ null
3808
+ ) : (
3809
+ // eslint-disable-next-line unicorn/no-null -- fold userId/claims into the discriminator; missing fields serialize as null so the shape stays canonical
3810
+ stableStringify({ claims: claims ?? null, userId: userId ?? null })
3811
+ );
3812
3812
  try {
3813
- const result = await this.reactiveCache.run(reactiveCacheKey(functionPath, args, this.getCurrentUserId() ?? null), tracker.collect(), run);
3813
+ const result = await this.reactiveCache.run(reactiveCacheKey(functionPath, args, identity), tracker.collect(), run);
3814
3814
  this.currentRequestCacheHit = this.reactiveCache.stats().hits > hitsBefore;
3815
3815
  this.currentRequestReadTables = tablesFromDeps(tracker.collect());
3816
3816
  return result;
@@ -1,3 +1,4 @@
1
+ import { c as constantTimeEqual } from './constant-time-equal-BVRWZgES.mjs';
1
2
  import { j as jsonResponse } from './json-response-BdbtpOhm.mjs';
2
3
 
3
4
  const SESSION_DO_TTL_DEFAULT = 7 * 24 * 60 * 60;
@@ -9,16 +10,6 @@ const SESSION_TOKEN_PATTERN = /^[\w-]+$/;
9
10
  const MIN_TOKEN_LENGTH = 32;
10
11
  const MAX_TOKEN_LENGTH = 256;
11
12
  const MAX_USER_ID_LENGTH = 256;
12
- const constantTimeEqual = (a, b) => {
13
- const max = Math.max(a.length, b.length);
14
- let diff = a.length ^ b.length;
15
- for (let index = 0; index < max; index += 1) {
16
- const charA = index < a.length ? a.charCodeAt(index) : 0;
17
- const charB = index < b.length ? b.charCodeAt(index) : 0;
18
- diff |= charA ^ charB;
19
- }
20
- return diff === 0;
21
- };
22
13
  const isAuthorized = (request, env) => {
23
14
  const expected = env.SESSION_DO_SECRET;
24
15
  if (typeof expected !== "string" || expected.length === 0) {
@@ -0,0 +1,12 @@
1
+ const constantTimeEqual = (a, b) => {
2
+ const max = Math.max(a.length, b.length);
3
+ let diff = a.length ^ b.length;
4
+ for (let index = 0; index < max; index += 1) {
5
+ const charA = index < a.length ? a.charCodeAt(index) : 0;
6
+ const charB = index < b.length ? b.charCodeAt(index) : 0;
7
+ diff |= charA ^ charB;
8
+ }
9
+ return diff === 0;
10
+ };
11
+
12
+ export { constantTimeEqual as c };
@@ -1,5 +1,5 @@
1
1
  import { LunoraError } from '@lunora/errors';
2
- import { runExternalSourceTick } from './materializeExternalRows-DNcvoLRT.mjs';
2
+ import { runExternalSourceTick } from './materializeExternalRows-CTqZisSC.mjs';
3
3
 
4
4
  const liftSourceId = (row, options = {}) => {
5
5
  const { idColumn = "id", map } = options;
@@ -1,4 +1,4 @@
1
- import { applyCdcChanges } from './CDC_LOG_TABLE-DZSVKRr7.mjs';
1
+ import { applyCdcChanges } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
2
2
  import { s as selectShapeRows } from './ctx-db-shapes-Cz9dHyh1.mjs';
3
3
  import { diffExternalSource, projectExternalSourceRow } from './diffExternalSource-Cx9HUPJj.mjs';
4
4
  import { stableStringify } from './stableStringify-MydiuScU.mjs';
@@ -1,6 +1,6 @@
1
1
  import { sql } from 'drizzle-orm';
2
2
  import { aggregateTableName } from './aggregateTableName-CxNqY1Sl.mjs';
3
- import { migrateCdcLog, migrateCdcMeta } from './CDC_LOG_TABLE-DZSVKRr7.mjs';
3
+ import { migrateCdcLog, migrateCdcMeta } from './CDC_LOG_TABLE-DjJEHiM2.mjs';
4
4
  import { m as migrateClientWatermark, a as migrateIdempotency, b as migrateGlobalShapeSnapshot } from './ctx-db-idempotency-BdcNpvY4.mjs';
5
5
  import { r as runDrizzle } from './do-exec-5eQy5cEi.mjs';
6
6
  import { D as DOC_COLUMN, j as jsonPathSql, c as createIndexSql, t as tableColumns, i as isFtsAvailable, A as AGG_KEY, a as AGG_VALUE, b as AGG_COUNT } from './do-sql-BCHCWtrD.mjs';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/do",
3
- "version": "1.0.0-alpha.26",
3
+ "version": "1.0.0-alpha.28",
4
4
  "description": "Lunora Durable Objects: ShardDO (SQLite, OCC, hibernated WebSocket subscriptions) and SessionDO",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -46,7 +46,7 @@
46
46
  "access": "public"
47
47
  },
48
48
  "dependencies": {
49
- "@lunora/errors": "1.0.0-alpha.3",
49
+ "@lunora/errors": "1.0.0-alpha.4",
50
50
  "@visulima/redact": "3.0.0",
51
51
  "drizzle-orm": "^0.45.2"
52
52
  },