@tearleads/client-sdk 0.1.115 → 0.1.117

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 (67) hide show
  1. package/client/containerContents/documentDiscovery.js +5 -3
  2. package/client/containerContents/documentDiscovery.js.map +1 -1
  3. package/data/persistence/container-contents/containerContentsPersistence.js +14 -13
  4. package/data/persistence/container-contents/containerContentsPersistence.js.map +1 -1
  5. package/data/persistence/documents/internal/ensureDocumentsSchema.js +10 -12
  6. package/data/persistence/documents/internal/ensureDocumentsSchema.js.map +1 -1
  7. package/data/sqlite/schema/containerSchema.d.ts +1 -0
  8. package/data/sqlite/schema/containerSchema.js +8 -1
  9. package/data/sqlite/schema/containerSchema.js.map +1 -1
  10. package/data/sqlite/schema/documentAttachmentSchema.d.ts +0 -2
  11. package/data/sqlite/schema/documentAttachmentSchema.js +0 -4
  12. package/data/sqlite/schema/documentAttachmentSchema.js.map +1 -1
  13. package/data/sqlite/schema/index.d.ts +2 -0
  14. package/data/sqlite/schema/index.js +10 -1
  15. package/data/sqlite/schema/index.js.map +1 -1
  16. package/data/sqlite/schema/principalPolicySchema.js +0 -1
  17. package/data/sqlite/schema/principalPolicySchema.js.map +1 -1
  18. package/data/sqlite/schema/verifiedManifestBundleSchema.js +4 -2
  19. package/data/sqlite/schema/verifiedManifestBundleSchema.js.map +1 -1
  20. package/data/sqlite/sqlExec.d.ts +12 -0
  21. package/data/sqlite/sqlExec.js +47 -3
  22. package/data/sqlite/sqlExec.js.map +1 -1
  23. package/data/sqlite/sqlTableSchema.js +40 -15
  24. package/data/sqlite/sqlTableSchema.js.map +1 -1
  25. package/data/sqlite/sqlitePersistenceRuntime.js +18 -10
  26. package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
  27. package/internal/api-client/ApiClient.d.ts +118 -0
  28. package/internal/api-client/ApiClient.js +4 -0
  29. package/internal/api-client/ApiClient.js.map +1 -1
  30. package/internal/api-client/index.d.ts +1 -1
  31. package/internal/api-client/index.js.map +1 -1
  32. package/internal/api-client/principalPolicyPages.d.ts +15 -1
  33. package/internal/api-client/principalPolicyPages.js +48 -2
  34. package/internal/api-client/principalPolicyPages.js.map +1 -1
  35. package/internal/api-client/principalPolicyRequests.d.ts +118 -1
  36. package/internal/api-client/principalPolicyRequests.js +4 -1
  37. package/internal/api-client/principalPolicyRequests.js.map +1 -1
  38. package/internal/validators/operation/principalPolicyPageQuery.d.ts +9 -0
  39. package/internal/validators/operation/principalPolicyPageQuery.js +10 -0
  40. package/internal/validators/operation/principalPolicyPageQuery.js.map +1 -1
  41. package/internal/validators/operation/principals.d.ts +37 -4
  42. package/internal/validators/operation/principals.js +5 -3
  43. package/internal/validators/operation/principals.js.map +1 -1
  44. package/internal/validators/response/index.d.ts +1 -1
  45. package/internal/validators/response/index.js +1 -1
  46. package/internal/validators/response/index.js.map +1 -1
  47. package/internal/validators/response/principalPolicyPage.d.ts +497 -1
  48. package/internal/validators/response/principalPolicyPage.js +18 -0
  49. package/internal/validators/response/principalPolicyPage.js.map +1 -1
  50. package/package.json +1 -1
  51. package/workflows/container-contents/documentLinks/index.d.ts +4 -0
  52. package/workflows/container-contents/documentLinks/index.js +10 -3
  53. package/workflows/container-contents/documentLinks/index.js.map +1 -1
  54. package/workflows/container-contents/remoteHydration/remoteContainers/remoteContainerPageHydration.js +7 -2
  55. package/workflows/container-contents/remoteHydration/remoteContainers/remoteContainerPageHydration.js.map +1 -1
  56. package/workflows/container-contents/tombstones/documentTombstoneEvidence.js +6 -5
  57. package/workflows/container-contents/tombstones/documentTombstoneEvidence.js.map +1 -1
  58. package/workflows/principals/principalPolicyHistoryReader.d.ts +6 -1
  59. package/workflows/principals/principalPolicyHistoryReader.js +4 -1
  60. package/workflows/principals/principalPolicyHistoryReader.js.map +1 -1
  61. package/workflows/principals/recoveryOperation/principalRecoveryDirectory.js +108 -59
  62. package/workflows/principals/recoveryOperation/principalRecoveryDirectory.js.map +1 -1
  63. package/workflows/principals/runtimePolicyRecovery.js +26 -14
  64. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  65. package/workflows/principals/runtimePolicyWarmer.d.ts +26 -0
  66. package/workflows/principals/runtimePolicyWarmer.js +8 -5
  67. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
@@ -9,11 +9,11 @@ import { createContainerDocumentQueriesFromRuntime } from "../../workflows/conta
9
9
  import { createContainerContentsWorkflowRuntime, } from "../../workflows/container-contents/runtime.js";
10
10
  import { guardDocumentDiscoveryWrites } from "../../workflows/container-contents/syncPause/discoveryGuard.js";
11
11
  import { createContainerDocumentTombstoneVerifier, createDocumentHeadLinkSetLoader, } from "../../workflows/container-contents/tombstones/documentTombstoneEvidence.js";
12
- import { createRuntimePrincipalPolicyWarmer } from "../../workflows/principals/runtimePolicyWarmer.js";
12
+ import { createPrincipalPolicyOperation, createRuntimePrincipalPolicyWarmer, } from "../../workflows/principals/runtimePolicyWarmer.js";
13
13
  function createDiscoveryLane(input) {
14
14
  const { containerOrganizationId, execSql, request, runtime } = input;
15
- const warmReferencedPrincipalPolicies = createRuntimePrincipalPolicyWarmer(runtime);
16
- const loadHead = createDocumentHeadLinkSetLoader(runtime);
15
+ const warmReferencedPrincipalPolicies = createRuntimePrincipalPolicyWarmer(runtime, { operation: input.policyOperation });
16
+ const loadHead = createDocumentHeadLinkSetLoader(runtime, undefined, input.policyOperation);
17
17
  const loadEpoch = (documentId) => loadLocalDocumentAccessEpoch(execSql, documentId);
18
18
  return {
19
19
  ...input.queries,
@@ -63,6 +63,7 @@ export async function discoverContainerDocumentLanesForRuntime({ onOutcome, requ
63
63
  const syncPauses = getOrCreateOrganizationSyncPauses(input.state.domainScope);
64
64
  await syncPauses.load(execSql);
65
65
  const lanes = [];
66
+ const policyOperation = createPrincipalPolicyOperation();
66
67
  for (const request of requests) {
67
68
  const stored = await sqlContainerContentsPersistence.loadContainerMetadataState(execSql, request.containerId);
68
69
  if (!stored)
@@ -76,6 +77,7 @@ export async function discoverContainerDocumentLanesForRuntime({ onOutcome, requ
76
77
  isContainerPaused,
77
78
  evidenceStore,
78
79
  execSql,
80
+ policyOperation,
79
81
  queries,
80
82
  request,
81
83
  runtime,
@@ -1 +1 @@
1
- {"version":3,"file":"documentDiscovery.js","sourceRoot":"","sources":["documentDiscovery.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { sqlContainerContentsPersistence } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport {\n holdContainerDocumentTombstones,\n listKnownContainerDocumentPlacements,\n listRetryableHeldContainerDocumentTombstones,\n loadLocalDocumentAccessEpoch,\n refuteContainerDocumentTombstoneHolds,\n} from \"../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport { createDocumentDiscoveryEvidenceStore } from \"../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport { getOrCreateOrganizationSyncPauses } from \"../../data/sync/organizationSyncPauses\";\nimport { listContainerDocumentLanesFromApi } from \"../../workflows/container-contents/documentDiscovery/containerDocumentListing\";\nimport { createDiscoveredDocumentVerifier } from \"../../workflows/container-contents/documentDiscovery/documentDiscoveryEvidence\";\nimport {\n type ContainerDocumentDiscoveryLane,\n type ContainerDocumentDiscoveryOutcome,\n type ContainerDocumentDiscoveryOutcomeHandler,\n discoverContainerDocumentLanes,\n} from \"../../workflows/container-contents/documentDiscovery/documentDiscoveryLanes\";\nimport { createContainerDocumentQueriesFromRuntime } from \"../../workflows/container-contents/documentQueries\";\nimport {\n type ContainerContentsWorkflowRuntime,\n createContainerContentsWorkflowRuntime,\n} from \"../../workflows/container-contents/runtime\";\nimport { guardDocumentDiscoveryWrites } from \"../../workflows/container-contents/syncPause/discoveryGuard\";\nimport {\n createContainerDocumentTombstoneVerifier,\n createDocumentHeadLinkSetLoader,\n} from \"../../workflows/container-contents/tombstones/documentTombstoneEvidence\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../workflows/principals/runtimePolicyWarmer\";\nimport type { InternalRuntime } from \"../runtime/workflowRuntime\";\n\nexport type { ContainerDocumentDiscoveryOutcome } from \"../../workflows/container-contents/documentDiscovery/documentDiscoveryLanes\";\n\n/** One container to discover, with the reconciler's per-lane callbacks. */\nexport interface ContainerDocumentDiscoveryRequest {\n readonly containerId: string;\n readonly onFullListing?:\n | ((documentIds: ReadonlyArray<string>) => void)\n | undefined;\n readonly onPendingDiscovery?: ((delayMs: number) => void) | undefined;\n}\n\ntype ExecSql = ReturnType<InternalRuntime[\"workflowInput\"]>[\"infra\"][\"execSql\"];\n\nfunction createDiscoveryLane(input: {\n readonly containerOrganizationId: string | undefined;\n readonly isContainerPaused: () => boolean;\n readonly evidenceStore: ReturnType<\n typeof createDocumentDiscoveryEvidenceStore\n >;\n readonly execSql: ExecSql;\n readonly queries: ReturnType<\n typeof createContainerDocumentQueriesFromRuntime\n >;\n readonly request: ContainerDocumentDiscoveryRequest;\n readonly runtime: ContainerContentsWorkflowRuntime;\n}): ContainerDocumentDiscoveryLane {\n const { containerOrganizationId, execSql, request, runtime } = input;\n const warmReferencedPrincipalPolicies =\n createRuntimePrincipalPolicyWarmer(runtime);\n const loadHead = createDocumentHeadLinkSetLoader(runtime);\n const loadEpoch = (documentId: string) =>\n loadLocalDocumentAccessEpoch(execSql, documentId);\n return {\n ...input.queries,\n cacheReferencedPrincipalPolicies: (references) =>\n containerOrganizationId\n ? warmReferencedPrincipalPolicies({\n organizationId: containerOrganizationId,\n references,\n })\n : Promise.resolve(),\n containerId: request.containerId,\n holdContainerDocumentTombstones: (tombstones) =>\n holdContainerDocumentTombstones(execSql, tombstones),\n listHeldContainerDocumentTombstones: (containerIds) =>\n listRetryableHeldContainerDocumentTombstones(execSql, containerIds),\n listKnownContainerDocumentPlacements: (placements) =>\n listKnownContainerDocumentPlacements(execSql, placements),\n onFullListing: request.onFullListing,\n refuteContainerDocumentTombstoneHolds: (placements) =>\n refuteContainerDocumentTombstoneHolds(execSql, placements),\n verifyContainerDocumentTombstones: createContainerDocumentTombstoneVerifier(\n containerOrganizationId,\n loadHead,\n loadEpoch,\n ),\n ...guardDocumentDiscoveryWrites({\n execSql,\n isPaused: input.isContainerPaused,\n verifyDiscoveredDocuments: createDiscoveredDocumentVerifier(\n containerOrganizationId,\n loadHead,\n loadEpoch,\n input.evidenceStore,\n request.onPendingDiscovery,\n ),\n }),\n };\n}\n\n/**\n * Internal adapter shared by explicit discovery and background reconciliation:\n * one batched listing for every requested container, then per-container\n * verification scoped to each container's durable organization.\n */\nexport async function discoverContainerDocumentLanesForRuntime({\n onOutcome,\n requests,\n runtimeService,\n}: {\n readonly onOutcome?: ContainerDocumentDiscoveryOutcomeHandler | undefined;\n readonly requests: ReadonlyArray<ContainerDocumentDiscoveryRequest>;\n readonly runtimeService: InternalRuntime;\n}): Promise<ReadonlyArray<ContainerDocumentDiscoveryOutcome>> {\n const unlisted = (\n containerId: string,\n ): ContainerDocumentDiscoveryOutcome => ({\n containerId,\n status: \"fulfilled\",\n value: null,\n });\n const input = runtimeService.workflowInput();\n if (input.infra.dbStatus !== \"ready\") {\n return requests.map(({ containerId }) => unlisted(containerId));\n }\n const runtime = createContainerContentsWorkflowRuntime(input);\n const execSql = input.infra.execSql;\n const evidenceStore = createDocumentDiscoveryEvidenceStore(execSql);\n const queries = createContainerDocumentQueriesFromRuntime(runtime);\n // Capture the reset fence before reading any lane's scope, so a reset\n // between these reads and the listing cannot publish old-organization\n // evidence into its replacement.\n const generation = await evidenceStore.begin();\n const syncPauses = getOrCreateOrganizationSyncPauses(input.state.domainScope);\n await syncPauses.load(execSql);\n const lanes: ContainerDocumentDiscoveryLane[] = [];\n for (const request of requests) {\n const stored =\n await sqlContainerContentsPersistence.loadContainerMetadataState(\n execSql,\n request.containerId,\n );\n if (!stored) continue;\n const isContainerPaused = () =>\n syncPauses.isContainerPaused(\n stored.container,\n runtimeService.workflowInput().auth.organizationId ?? null,\n );\n // A paused organization's container lists like one that is not stored,\n // and a pause landing mid-listing stops its write.\n if (!isContainerPaused())\n lanes.push(\n createDiscoveryLane({\n containerOrganizationId: stored.container.organizationId,\n isContainerPaused,\n evidenceStore,\n execSql,\n queries,\n request,\n runtime,\n }),\n );\n }\n const outcomes = await discoverContainerDocumentLanes({\n generation,\n lanes,\n listContainerDocumentLanes: (listed) =>\n listContainerDocumentLanesFromApi(runtime.apiClient, listed),\n loadContainerDocumentWatermark: queries.loadContainerDocumentWatermark,\n onOutcome,\n });\n const outcomeByContainerId = new Map(\n outcomes.map((outcome) => [outcome.containerId, outcome]),\n );\n return requests.map(\n ({ containerId }) =>\n outcomeByContainerId.get(containerId) ?? unlisted(containerId),\n );\n}\n\n/** Discovers one container; a rejected lane rethrows its failure. */\nexport async function discoverContainerDocumentsForRuntime({\n runtimeService,\n ...request\n}: ContainerDocumentDiscoveryRequest & {\n readonly runtimeService: InternalRuntime;\n}): Promise<ReadonlyArray<DocumentSummary> | null> {\n const [outcome] = await discoverContainerDocumentLanesForRuntime({\n requests: [request],\n runtimeService,\n });\n if (outcome?.status === \"rejected\") throw outcome.reason;\n return outcome?.value ?? null;\n}\n"]}
1
+ {"version":3,"file":"documentDiscovery.js","sourceRoot":"","sources":["documentDiscovery.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DocumentSummary } from \"../../data/documents/documentSummary\";\nimport { sqlContainerContentsPersistence } from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport {\n holdContainerDocumentTombstones,\n listKnownContainerDocumentPlacements,\n listRetryableHeldContainerDocumentTombstones,\n loadLocalDocumentAccessEpoch,\n refuteContainerDocumentTombstoneHolds,\n} from \"../../data/persistence/documents/containerDocumentTombstoneHoldsPersistence\";\nimport { createDocumentDiscoveryEvidenceStore } from \"../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport { getOrCreateOrganizationSyncPauses } from \"../../data/sync/organizationSyncPauses\";\nimport { listContainerDocumentLanesFromApi } from \"../../workflows/container-contents/documentDiscovery/containerDocumentListing\";\nimport { createDiscoveredDocumentVerifier } from \"../../workflows/container-contents/documentDiscovery/documentDiscoveryEvidence\";\nimport {\n type ContainerDocumentDiscoveryLane,\n type ContainerDocumentDiscoveryOutcome,\n type ContainerDocumentDiscoveryOutcomeHandler,\n discoverContainerDocumentLanes,\n} from \"../../workflows/container-contents/documentDiscovery/documentDiscoveryLanes\";\nimport { createContainerDocumentQueriesFromRuntime } from \"../../workflows/container-contents/documentQueries\";\nimport {\n type ContainerContentsWorkflowRuntime,\n createContainerContentsWorkflowRuntime,\n} from \"../../workflows/container-contents/runtime\";\nimport { guardDocumentDiscoveryWrites } from \"../../workflows/container-contents/syncPause/discoveryGuard\";\nimport {\n createContainerDocumentTombstoneVerifier,\n createDocumentHeadLinkSetLoader,\n} from \"../../workflows/container-contents/tombstones/documentTombstoneEvidence\";\nimport {\n createPrincipalPolicyOperation,\n createRuntimePrincipalPolicyWarmer,\n type PrincipalPolicyOperation,\n} from \"../../workflows/principals/runtimePolicyWarmer\";\nimport type { InternalRuntime } from \"../runtime/workflowRuntime\";\n\nexport type { ContainerDocumentDiscoveryOutcome } from \"../../workflows/container-contents/documentDiscovery/documentDiscoveryLanes\";\n\n/** One container to discover, with the reconciler's per-lane callbacks. */\nexport interface ContainerDocumentDiscoveryRequest {\n readonly containerId: string;\n readonly onFullListing?:\n | ((documentIds: ReadonlyArray<string>) => void)\n | undefined;\n readonly onPendingDiscovery?: ((delayMs: number) => void) | undefined;\n}\n\ntype ExecSql = ReturnType<InternalRuntime[\"workflowInput\"]>[\"infra\"][\"execSql\"];\n\nfunction createDiscoveryLane(input: {\n readonly containerOrganizationId: string | undefined;\n readonly isContainerPaused: () => boolean;\n readonly evidenceStore: ReturnType<\n typeof createDocumentDiscoveryEvidenceStore\n >;\n readonly execSql: ExecSql;\n /** The discovery pass's token: its lanes share one directory discovery. */\n readonly policyOperation: PrincipalPolicyOperation;\n readonly queries: ReturnType<\n typeof createContainerDocumentQueriesFromRuntime\n >;\n readonly request: ContainerDocumentDiscoveryRequest;\n readonly runtime: ContainerContentsWorkflowRuntime;\n}): ContainerDocumentDiscoveryLane {\n const { containerOrganizationId, execSql, request, runtime } = input;\n const warmReferencedPrincipalPolicies = createRuntimePrincipalPolicyWarmer(\n runtime,\n { operation: input.policyOperation },\n );\n const loadHead = createDocumentHeadLinkSetLoader(\n runtime,\n undefined,\n input.policyOperation,\n );\n const loadEpoch = (documentId: string) =>\n loadLocalDocumentAccessEpoch(execSql, documentId);\n return {\n ...input.queries,\n cacheReferencedPrincipalPolicies: (references) =>\n containerOrganizationId\n ? warmReferencedPrincipalPolicies({\n organizationId: containerOrganizationId,\n references,\n })\n : Promise.resolve(),\n containerId: request.containerId,\n holdContainerDocumentTombstones: (tombstones) =>\n holdContainerDocumentTombstones(execSql, tombstones),\n listHeldContainerDocumentTombstones: (containerIds) =>\n listRetryableHeldContainerDocumentTombstones(execSql, containerIds),\n listKnownContainerDocumentPlacements: (placements) =>\n listKnownContainerDocumentPlacements(execSql, placements),\n onFullListing: request.onFullListing,\n refuteContainerDocumentTombstoneHolds: (placements) =>\n refuteContainerDocumentTombstoneHolds(execSql, placements),\n verifyContainerDocumentTombstones: createContainerDocumentTombstoneVerifier(\n containerOrganizationId,\n loadHead,\n loadEpoch,\n ),\n ...guardDocumentDiscoveryWrites({\n execSql,\n isPaused: input.isContainerPaused,\n verifyDiscoveredDocuments: createDiscoveredDocumentVerifier(\n containerOrganizationId,\n loadHead,\n loadEpoch,\n input.evidenceStore,\n request.onPendingDiscovery,\n ),\n }),\n };\n}\n\n/**\n * Internal adapter shared by explicit discovery and background reconciliation:\n * one batched listing for every requested container, then per-container\n * verification scoped to each container's durable organization.\n */\nexport async function discoverContainerDocumentLanesForRuntime({\n onOutcome,\n requests,\n runtimeService,\n}: {\n readonly onOutcome?: ContainerDocumentDiscoveryOutcomeHandler | undefined;\n readonly requests: ReadonlyArray<ContainerDocumentDiscoveryRequest>;\n readonly runtimeService: InternalRuntime;\n}): Promise<ReadonlyArray<ContainerDocumentDiscoveryOutcome>> {\n const unlisted = (\n containerId: string,\n ): ContainerDocumentDiscoveryOutcome => ({\n containerId,\n status: \"fulfilled\",\n value: null,\n });\n const input = runtimeService.workflowInput();\n if (input.infra.dbStatus !== \"ready\") {\n return requests.map(({ containerId }) => unlisted(containerId));\n }\n const runtime = createContainerContentsWorkflowRuntime(input);\n const execSql = input.infra.execSql;\n const evidenceStore = createDocumentDiscoveryEvidenceStore(execSql);\n const queries = createContainerDocumentQueriesFromRuntime(runtime);\n // Capture the reset fence before reading any lane's scope, so a reset\n // between these reads and the listing cannot publish old-organization\n // evidence into its replacement.\n const generation = await evidenceStore.begin();\n const syncPauses = getOrCreateOrganizationSyncPauses(input.state.domainScope);\n await syncPauses.load(execSql);\n const lanes: ContainerDocumentDiscoveryLane[] = [];\n const policyOperation = createPrincipalPolicyOperation();\n for (const request of requests) {\n const stored =\n await sqlContainerContentsPersistence.loadContainerMetadataState(\n execSql,\n request.containerId,\n );\n if (!stored) continue;\n const isContainerPaused = () =>\n syncPauses.isContainerPaused(\n stored.container,\n runtimeService.workflowInput().auth.organizationId ?? null,\n );\n // A paused organization's container lists like one that is not stored,\n // and a pause landing mid-listing stops its write.\n if (!isContainerPaused())\n lanes.push(\n createDiscoveryLane({\n containerOrganizationId: stored.container.organizationId,\n isContainerPaused,\n evidenceStore,\n execSql,\n policyOperation,\n queries,\n request,\n runtime,\n }),\n );\n }\n const outcomes = await discoverContainerDocumentLanes({\n generation,\n lanes,\n listContainerDocumentLanes: (listed) =>\n listContainerDocumentLanesFromApi(runtime.apiClient, listed),\n loadContainerDocumentWatermark: queries.loadContainerDocumentWatermark,\n onOutcome,\n });\n const outcomeByContainerId = new Map(\n outcomes.map((outcome) => [outcome.containerId, outcome]),\n );\n return requests.map(\n ({ containerId }) =>\n outcomeByContainerId.get(containerId) ?? unlisted(containerId),\n );\n}\n\n/** Discovers one container; a rejected lane rethrows its failure. */\nexport async function discoverContainerDocumentsForRuntime({\n runtimeService,\n ...request\n}: ContainerDocumentDiscoveryRequest & {\n readonly runtimeService: InternalRuntime;\n}): Promise<ReadonlyArray<DocumentSummary> | null> {\n const [outcome] = await discoverContainerDocumentLanesForRuntime({\n requests: [request],\n runtimeService,\n });\n if (outcome?.status === \"rejected\") throw outcome.reason;\n return outcome?.value ?? null;\n}\n"]}
@@ -1,12 +1,11 @@
1
1
  import { eq } from "drizzle-orm";
2
- import { containerHydrationTombstones, containers, documentContainerProjectionTables, keyingCheckpointTables, localIntentTables, } from "../../sqlite/schema/index.js";
2
+ import { containerHydrationTombstones, containerSyncWatermarkTables, containers, containerTables, documentContainerProjectionTables, documentProjectionTables, documentTables, keyingCheckpointTables, localIntentTables, } from "../../sqlite/schema/index.js";
3
3
  import { getClientSQLitePersistenceRuntime, } from "../../sqlite/sqlitePersistenceRuntime.js";
4
4
  import { ensureSqlTables, runOncePerConnection, runSerializedSqlMutation, } from "../../sqlite/sqlSchema.js";
5
- import { enqueueDocumentPendingUpdate, ensureDocumentProjectionTables, ensureDocumentTables, } from "../documents/records/index.js";
5
+ import { enqueueDocumentPendingUpdate } from "../documents/records/index.js";
6
6
  import { hasQueuedDocumentUpdates, settleQueuedDocumentUpdatesInTransaction, } from "../documents/records/documentPendingUpdatePersistence.js";
7
7
  import { getLatestTimestamp } from "../latestTimestamp.js";
8
- import { ensureContainerTables, loadContainerById, } from "./containerPersistence.js";
9
- import { sqlContainerSyncWatermarkPersistence } from "./containerSyncWatermarkPersistence.js";
8
+ import { loadContainerById } from "./containerPersistence.js";
10
9
  import { claimDormantMetadataSweepAttempt, completeDormantMetadataSweepRequest, listDormantMetadataSweepRequests, } from "./dormantMetadataSweep.js";
11
10
  export { CONTAINER_METADATA_APP_KIND } from "./dormantContainerMetadata.js";
12
11
  import { deleteStoredContainers } from "./containerDeletionPersistence.js";
@@ -86,16 +85,18 @@ export const sqlContainerContentsPersistence = {
86
85
  // Once ensured on this connection, skip the outer mutation lock entirely:
87
86
  // ensureSchema runs on every query path, and re-acquiring the lock just to
88
87
  // no-op would queue reads behind unrelated writes.
89
- await runOncePerConnection(execSql, "ensure:container-contents", () => runSerializedSqlMutation(execSql, async (lockedExecSql) => {
90
- await ensureContainerTables(lockedExecSql);
91
- await ensureDocumentTables(lockedExecSql);
92
- await ensureSqlTables(lockedExecSql, localIntentTables);
88
+ await runOncePerConnection(execSql, "ensure:container-contents", () =>
89
+ // One ensure, so a cold connection sends three DDL messages in total.
90
+ ensureSqlTables(execSql, [
91
+ ...containerTables,
92
+ ...documentTables,
93
+ ...localIntentTables,
93
94
  // Metadata rows consult document purge checkpoints before writing.
94
- await ensureSqlTables(lockedExecSql, keyingCheckpointTables);
95
- await ensureSqlTables(lockedExecSql, documentContainerProjectionTables);
96
- await ensureDocumentProjectionTables(lockedExecSql);
97
- await sqlContainerSyncWatermarkPersistence.ensureSchema(lockedExecSql);
98
- }));
95
+ ...keyingCheckpointTables,
96
+ ...documentContainerProjectionTables,
97
+ ...documentProjectionTables,
98
+ ...containerSyncWatermarkTables,
99
+ ]));
99
100
  },
100
101
  async loadHeldContainerBinding(execSql, containerId) {
101
102
  await sqlContainerContentsPersistence.ensureSchema(execSql);
@@ -1 +1 @@
1
- {"version":3,"file":"containerContentsPersistence.js","sourceRoot":"","sources":["containerContentsPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { eq } from \"drizzle-orm\";\nimport {\n containerHydrationTombstones,\n containers,\n documentContainerProjectionTables,\n keyingCheckpointTables,\n localIntentTables,\n} from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport {\n ensureSqlTables,\n runOncePerConnection,\n runSerializedSqlMutation,\n} from \"../../sqlite/sqlSchema\";\nimport {\n enqueueDocumentPendingUpdate,\n ensureDocumentProjectionTables,\n ensureDocumentTables,\n} from \"../documents/records\";\nimport {\n hasQueuedDocumentUpdates,\n settleQueuedDocumentUpdatesInTransaction,\n} from \"../documents/records/documentPendingUpdatePersistence\";\nimport { getLatestTimestamp } from \"../latestTimestamp\";\nimport {\n ensureContainerTables,\n loadContainerById,\n} from \"./containerPersistence\";\nimport { sqlContainerSyncWatermarkPersistence } from \"./containerSyncWatermarkPersistence\";\nimport {\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n listDormantMetadataSweepRequests,\n} from \"./dormantMetadataSweep\";\n\nexport type {\n ContainerContentsPersistence,\n ContainerCreateIntentRecord,\n ContainerHydrationTombstone,\n ContainerMetadataRecord,\n ContainerMoveIntentRecord,\n LocalRootDescendantReparentInput,\n StoredContainerState,\n} from \"./containerContentsPersistenceTypes\";\nexport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\nimport type {\n ContainerContentsPersistence,\n ContainerMetadataRecord,\n SaveContainerOptions,\n SaveContainerWithPendingUpdateOptions,\n} from \"./containerContentsPersistenceTypes\";\nimport { deleteStoredContainers } from \"./containerDeletionPersistence\";\nimport {\n commitStoredHydratedContainer,\n loadStoredHeldContainerBinding,\n} from \"./containerHydrationPersistence\";\nimport { containerIntentPersistence } from \"./containerIntentPersistence\";\nimport {\n commitStoredMetadataMutation,\n settleStoredMetadataPendingUpdates,\n} from \"./containerMetadataMutationPersistence\";\nimport { containerMetadataPullContinuationPersistence } from \"./containerMetadataPullContinuationPersistence\";\nimport {\n getContainerMetadataScope,\n saveContainerContentsContainerRows,\n selectContainerMetadataRecord,\n selectContainersWithMetadataRecords,\n} from \"./containerMetadataRows\";\nimport { abandonStoredMoveIntentRevision } from \"./containerMoveAbandonPersistence\";\nimport { containerPendingUpdatePersistence } from \"./containerPendingUpdatePersistence\";\nimport { rebindStoredHeldContainer } from \"./containerRebindPersistence\";\nimport { containerReconcilePersistence } from \"./containerReconcilePersistence\";\nimport { isSupersededContainerBinding } from \"./supersededContainerBindings\";\n\nasync function saveStoredContainer(\n execSql: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[0],\n container: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[1],\n record: ContainerMetadataRecord | null,\n options?:\n | SaveContainerOptions\n | SaveContainerWithPendingUpdateOptions\n | undefined,\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt =\n options?.localUpdatedAt ?? options?.updatedAt ?? new Date().toISOString();\n const runtime = getClientSQLitePersistenceRuntime(lockedExecSql);\n const save = async (tx: ClientSQLiteTransactionScope) => {\n const saved = await saveContainerContentsContainerRows({\n container,\n createIntent: options?.createIntent,\n moveIntent: options?.moveIntent,\n record,\n serverTimestamps: options?.serverTimestamps,\n tx,\n localUpdatedAt,\n });\n if (options && \"pendingUpdate\" in options) {\n await enqueueDocumentPendingUpdate(\n lockedExecSql,\n getContainerMetadataScope(container.id),\n options.pendingUpdate,\n );\n }\n return saved;\n };\n if (!options?.stillCurrent) {\n return runtime.transaction(save);\n }\n const outcome = await runtime.guardedTransaction(\n save,\n options.stillCurrent,\n { behavior: \"immediate\" },\n );\n // Guarded callers recheck the same monotonic generation immediately after\n // this await. Returning the untouched candidate keeps the long-standing\n // non-null save contract while the transaction itself remains rolled back.\n return outcome.result ?? container;\n });\n}\n\nexport const sqlContainerContentsPersistence: ContainerContentsPersistence = {\n ...containerIntentPersistence,\n ...containerMetadataPullContinuationPersistence,\n commitHydratedContainer: commitStoredHydratedContainer,\n commitMetadataMutation: commitStoredMetadataMutation,\n settleAcceptedMetadataPendingUpdates: settleStoredMetadataPendingUpdates,\n listDormantMetadataSweepRequests,\n ...containerPendingUpdatePersistence,\n ...containerReconcilePersistence,\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n async containerExists(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({ id: containers.id })\n .from(containers)\n .where(eq(containers.id, containerId))\n .limit(1);\n return rows.length > 0;\n },\n async deleteContainer(execSql, containerId, options) {\n await sqlContainerContentsPersistence.deleteContainers(execSql, [\n {\n containerId,\n reason: options?.reason ?? \"deleted\",\n updatedAt: options?.updatedAt ?? new Date().toISOString(),\n },\n ]);\n },\n async deleteContainers(execSql, removals, options) {\n return deleteStoredContainers(execSql, removals, options);\n },\n async ensureSchema(execSql) {\n // Once ensured on this connection, skip the outer mutation lock entirely:\n // ensureSchema runs on every query path, and re-acquiring the lock just to\n // no-op would queue reads behind unrelated writes.\n await runOncePerConnection(execSql, \"ensure:container-contents\", () =>\n runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await ensureContainerTables(lockedExecSql);\n await ensureDocumentTables(lockedExecSql);\n await ensureSqlTables(lockedExecSql, localIntentTables);\n // Metadata rows consult document purge checkpoints before writing.\n await ensureSqlTables(lockedExecSql, keyingCheckpointTables);\n await ensureSqlTables(lockedExecSql, documentContainerProjectionTables);\n await ensureDocumentProjectionTables(lockedExecSql);\n await sqlContainerSyncWatermarkPersistence.ensureSchema(lockedExecSql);\n }),\n );\n },\n async loadHeldContainerBinding(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return loadStoredHeldContainerBinding(execSql, containerId);\n },\n async isSupersededContainerBinding(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return isSupersededContainerBinding(execSql, input);\n },\n async abandonMoveIntentRevision(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return abandonStoredMoveIntentRevision(execSql, input);\n },\n async rebindHeldContainer(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return rebindStoredHeldContainer(execSql, input);\n },\n async loadContainerMetadataRecord(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return selectContainerMetadataRecord(execSql, containerId);\n },\n async loadContainerHydrationTombstones(execSql) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n containerId: containerHydrationTombstones.containerId,\n generation: containerHydrationTombstones.generation,\n reason: containerHydrationTombstones.reason,\n updatedAt: containerHydrationTombstones.updatedAt,\n })\n .from(containerHydrationTombstones)\n .where(eq(containerHydrationTombstones.cleared, false));\n return rows.flatMap((row) =>\n row.reason === \"access_revoked\" || row.reason === \"deleted\"\n ? [{ ...row, reason: row.reason }]\n : [],\n );\n },\n async loadContainers(execSql) {\n return selectContainersWithMetadataRecords(execSql);\n },\n async loadContainerMetadataState(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const container = await loadContainerById(execSql, containerId);\n if (!container) {\n return null;\n }\n return {\n container,\n record: await selectContainerMetadataRecord(execSql, containerId),\n };\n },\n async saveContainer(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerWithPendingUpdate(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerAndDeletePendingUpdates(\n execSql,\n container,\n record,\n pendingUpdateIds,\n ) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt = new Date().toISOString();\n return getClientSQLitePersistenceRuntime(lockedExecSql).transaction(\n async (tx) => {\n const scope = getContainerMetadataScope(container.id);\n await settleQueuedDocumentUpdatesInTransaction(\n tx,\n scope,\n pendingUpdateIds,\n );\n const hasRemainingPendingUpdates = await hasQueuedDocumentUpdates(\n tx,\n scope,\n );\n const containerToSave = hasRemainingPendingUpdates\n ? container\n : {\n ...container,\n serverUpdatedAt: getLatestTimestamp(\n container.serverUpdatedAt,\n localUpdatedAt,\n ),\n };\n\n return saveContainerContentsContainerRows({\n container: containerToSave,\n record,\n tx,\n localUpdatedAt,\n });\n },\n );\n });\n },\n};\n"]}
1
+ {"version":3,"file":"containerContentsPersistence.js","sourceRoot":"","sources":["containerContentsPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { eq } from \"drizzle-orm\";\nimport {\n containerHydrationTombstones,\n containerSyncWatermarkTables,\n containers,\n containerTables,\n documentContainerProjectionTables,\n documentProjectionTables,\n documentTables,\n keyingCheckpointTables,\n localIntentTables,\n} from \"../../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../../sqlite/sqlitePersistenceRuntime\";\nimport {\n ensureSqlTables,\n runOncePerConnection,\n runSerializedSqlMutation,\n} from \"../../sqlite/sqlSchema\";\nimport { enqueueDocumentPendingUpdate } from \"../documents/records\";\nimport {\n hasQueuedDocumentUpdates,\n settleQueuedDocumentUpdatesInTransaction,\n} from \"../documents/records/documentPendingUpdatePersistence\";\nimport { getLatestTimestamp } from \"../latestTimestamp\";\nimport { loadContainerById } from \"./containerPersistence\";\nimport {\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n listDormantMetadataSweepRequests,\n} from \"./dormantMetadataSweep\";\n\nexport type {\n ContainerContentsPersistence,\n ContainerCreateIntentRecord,\n ContainerHydrationTombstone,\n ContainerMetadataRecord,\n ContainerMoveIntentRecord,\n LocalRootDescendantReparentInput,\n StoredContainerState,\n} from \"./containerContentsPersistenceTypes\";\nexport { CONTAINER_METADATA_APP_KIND } from \"./dormantContainerMetadata\";\n\nimport type {\n ContainerContentsPersistence,\n ContainerMetadataRecord,\n SaveContainerOptions,\n SaveContainerWithPendingUpdateOptions,\n} from \"./containerContentsPersistenceTypes\";\nimport { deleteStoredContainers } from \"./containerDeletionPersistence\";\nimport {\n commitStoredHydratedContainer,\n loadStoredHeldContainerBinding,\n} from \"./containerHydrationPersistence\";\nimport { containerIntentPersistence } from \"./containerIntentPersistence\";\nimport {\n commitStoredMetadataMutation,\n settleStoredMetadataPendingUpdates,\n} from \"./containerMetadataMutationPersistence\";\nimport { containerMetadataPullContinuationPersistence } from \"./containerMetadataPullContinuationPersistence\";\nimport {\n getContainerMetadataScope,\n saveContainerContentsContainerRows,\n selectContainerMetadataRecord,\n selectContainersWithMetadataRecords,\n} from \"./containerMetadataRows\";\nimport { abandonStoredMoveIntentRevision } from \"./containerMoveAbandonPersistence\";\nimport { containerPendingUpdatePersistence } from \"./containerPendingUpdatePersistence\";\nimport { rebindStoredHeldContainer } from \"./containerRebindPersistence\";\nimport { containerReconcilePersistence } from \"./containerReconcilePersistence\";\nimport { isSupersededContainerBinding } from \"./supersededContainerBindings\";\n\nasync function saveStoredContainer(\n execSql: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[0],\n container: Parameters<ContainerContentsPersistence[\"saveContainer\"]>[1],\n record: ContainerMetadataRecord | null,\n options?:\n | SaveContainerOptions\n | SaveContainerWithPendingUpdateOptions\n | undefined,\n) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt =\n options?.localUpdatedAt ?? options?.updatedAt ?? new Date().toISOString();\n const runtime = getClientSQLitePersistenceRuntime(lockedExecSql);\n const save = async (tx: ClientSQLiteTransactionScope) => {\n const saved = await saveContainerContentsContainerRows({\n container,\n createIntent: options?.createIntent,\n moveIntent: options?.moveIntent,\n record,\n serverTimestamps: options?.serverTimestamps,\n tx,\n localUpdatedAt,\n });\n if (options && \"pendingUpdate\" in options) {\n await enqueueDocumentPendingUpdate(\n lockedExecSql,\n getContainerMetadataScope(container.id),\n options.pendingUpdate,\n );\n }\n return saved;\n };\n if (!options?.stillCurrent) {\n return runtime.transaction(save);\n }\n const outcome = await runtime.guardedTransaction(\n save,\n options.stillCurrent,\n { behavior: \"immediate\" },\n );\n // Guarded callers recheck the same monotonic generation immediately after\n // this await. Returning the untouched candidate keeps the long-standing\n // non-null save contract while the transaction itself remains rolled back.\n return outcome.result ?? container;\n });\n}\n\nexport const sqlContainerContentsPersistence: ContainerContentsPersistence = {\n ...containerIntentPersistence,\n ...containerMetadataPullContinuationPersistence,\n commitHydratedContainer: commitStoredHydratedContainer,\n commitMetadataMutation: commitStoredMetadataMutation,\n settleAcceptedMetadataPendingUpdates: settleStoredMetadataPendingUpdates,\n listDormantMetadataSweepRequests,\n ...containerPendingUpdatePersistence,\n ...containerReconcilePersistence,\n claimDormantMetadataSweepAttempt,\n completeDormantMetadataSweepRequest,\n async containerExists(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({ id: containers.id })\n .from(containers)\n .where(eq(containers.id, containerId))\n .limit(1);\n return rows.length > 0;\n },\n async deleteContainer(execSql, containerId, options) {\n await sqlContainerContentsPersistence.deleteContainers(execSql, [\n {\n containerId,\n reason: options?.reason ?? \"deleted\",\n updatedAt: options?.updatedAt ?? new Date().toISOString(),\n },\n ]);\n },\n async deleteContainers(execSql, removals, options) {\n return deleteStoredContainers(execSql, removals, options);\n },\n async ensureSchema(execSql) {\n // Once ensured on this connection, skip the outer mutation lock entirely:\n // ensureSchema runs on every query path, and re-acquiring the lock just to\n // no-op would queue reads behind unrelated writes.\n await runOncePerConnection(execSql, \"ensure:container-contents\", () =>\n // One ensure, so a cold connection sends three DDL messages in total.\n ensureSqlTables(execSql, [\n ...containerTables,\n ...documentTables,\n ...localIntentTables,\n // Metadata rows consult document purge checkpoints before writing.\n ...keyingCheckpointTables,\n ...documentContainerProjectionTables,\n ...documentProjectionTables,\n ...containerSyncWatermarkTables,\n ]),\n );\n },\n async loadHeldContainerBinding(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return loadStoredHeldContainerBinding(execSql, containerId);\n },\n async isSupersededContainerBinding(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return isSupersededContainerBinding(execSql, input);\n },\n async abandonMoveIntentRevision(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return abandonStoredMoveIntentRevision(execSql, input);\n },\n async rebindHeldContainer(execSql, input) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return rebindStoredHeldContainer(execSql, input);\n },\n async loadContainerMetadataRecord(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n return selectContainerMetadataRecord(execSql, containerId);\n },\n async loadContainerHydrationTombstones(execSql) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const rows = await db\n .select({\n containerId: containerHydrationTombstones.containerId,\n generation: containerHydrationTombstones.generation,\n reason: containerHydrationTombstones.reason,\n updatedAt: containerHydrationTombstones.updatedAt,\n })\n .from(containerHydrationTombstones)\n .where(eq(containerHydrationTombstones.cleared, false));\n return rows.flatMap((row) =>\n row.reason === \"access_revoked\" || row.reason === \"deleted\"\n ? [{ ...row, reason: row.reason }]\n : [],\n );\n },\n async loadContainers(execSql) {\n return selectContainersWithMetadataRecords(execSql);\n },\n async loadContainerMetadataState(execSql, containerId) {\n await sqlContainerContentsPersistence.ensureSchema(execSql);\n const container = await loadContainerById(execSql, containerId);\n if (!container) {\n return null;\n }\n return {\n container,\n record: await selectContainerMetadataRecord(execSql, containerId),\n };\n },\n async saveContainer(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerWithPendingUpdate(execSql, container, record, options) {\n return saveStoredContainer(execSql, container, record, options);\n },\n async saveContainerAndDeletePendingUpdates(\n execSql,\n container,\n record,\n pendingUpdateIds,\n ) {\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n const localUpdatedAt = new Date().toISOString();\n return getClientSQLitePersistenceRuntime(lockedExecSql).transaction(\n async (tx) => {\n const scope = getContainerMetadataScope(container.id);\n await settleQueuedDocumentUpdatesInTransaction(\n tx,\n scope,\n pendingUpdateIds,\n );\n const hasRemainingPendingUpdates = await hasQueuedDocumentUpdates(\n tx,\n scope,\n );\n const containerToSave = hasRemainingPendingUpdates\n ? container\n : {\n ...container,\n serverUpdatedAt: getLatestTimestamp(\n container.serverUpdatedAt,\n localUpdatedAt,\n ),\n };\n\n return saveContainerContentsContainerRows({\n container: containerToSave,\n record,\n tx,\n localUpdatedAt,\n });\n },\n );\n });\n },\n};\n"]}
@@ -1,15 +1,13 @@
1
- import { documentContainerProjectionTables, documentPlacementIntentTables, keyingCheckpointTables, } from "../../../sqlite/schema/index.js";
2
- import { ensureSqlTables, runOncePerConnection, runSerializedSqlMutation, } from "../../../sqlite/sqlSchema.js";
3
- import { ensureDocumentProjectionTables, ensureDocumentTables, } from "../records/index.js";
1
+ import { documentContainerProjectionTables, documentPlacementIntentTables, documentProjectionTables, documentTables, keyingCheckpointTables, } from "../../../sqlite/schema/index.js";
2
+ import { ensureSqlTables, runOncePerConnection, } from "../../../sqlite/sqlSchema.js";
3
+ // One ensure, so a cold connection sends three DDL messages in total.
4
4
  export async function ensureDocumentsSchema(execSql) {
5
- await runOncePerConnection(execSql, "ensure:documents", () => runSerializedSqlMutation(execSql, async (lockedExecSql) => {
6
- await ensureDocumentTables(lockedExecSql);
7
- await ensureDocumentProjectionTables(lockedExecSql);
8
- await ensureSqlTables(lockedExecSql, [
9
- ...documentContainerProjectionTables,
10
- ...documentPlacementIntentTables,
11
- ...keyingCheckpointTables,
12
- ]);
13
- }));
5
+ await runOncePerConnection(execSql, "ensure:documents", () => ensureSqlTables(execSql, [
6
+ ...documentTables,
7
+ ...documentProjectionTables,
8
+ ...documentContainerProjectionTables,
9
+ ...documentPlacementIntentTables,
10
+ ...keyingCheckpointTables,
11
+ ]));
14
12
  }
15
13
  //# sourceMappingURL=ensureDocumentsSchema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ensureDocumentsSchema.js","sourceRoot":"","sources":["ensureDocumentsSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EACjC,6BAA6B,EAC7B,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,eAAe,EACf,oBAAoB,EACpB,wBAAwB,GACzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,8BAA8B,EAC9B,oBAAoB,GACrB,MAAM,YAAY,CAAC;AAEpB,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAgB;IAC1D,MAAM,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAC3D,wBAAwB,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;QACxD,MAAM,oBAAoB,CAAC,aAAa,CAAC,CAAC;QAC1C,MAAM,8BAA8B,CAAC,aAAa,CAAC,CAAC;QACpD,MAAM,eAAe,CAAC,aAAa,EAAE;YACnC,GAAG,iCAAiC;YACpC,GAAG,6BAA6B;YAChC,GAAG,sBAAsB;SAC1B,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["import {\n documentContainerProjectionTables,\n documentPlacementIntentTables,\n keyingCheckpointTables,\n} from \"../../../sqlite/schema\";\nimport {\n type ExecSql,\n ensureSqlTables,\n runOncePerConnection,\n runSerializedSqlMutation,\n} from \"../../../sqlite/sqlSchema\";\nimport {\n ensureDocumentProjectionTables,\n ensureDocumentTables,\n} from \"../records\";\n\nexport async function ensureDocumentsSchema(execSql: ExecSql): Promise<void> {\n await runOncePerConnection(execSql, \"ensure:documents\", () =>\n runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n await ensureDocumentTables(lockedExecSql);\n await ensureDocumentProjectionTables(lockedExecSql);\n await ensureSqlTables(lockedExecSql, [\n ...documentContainerProjectionTables,\n ...documentPlacementIntentTables,\n ...keyingCheckpointTables,\n ]);\n }),\n );\n}\n"]}
1
+ {"version":3,"file":"ensureDocumentsSchema.js","sourceRoot":"","sources":["ensureDocumentsSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EACjC,6BAA6B,EAC7B,wBAAwB,EACxB,cAAc,EACd,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAEL,eAAe,EACf,oBAAoB,GACrB,MAAM,2BAA2B,CAAC;AAEnC,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,OAAgB;IAC1D,MAAM,oBAAoB,CAAC,OAAO,EAAE,kBAAkB,EAAE,GAAG,EAAE,CAC3D,eAAe,CAAC,OAAO,EAAE;QACvB,GAAG,cAAc;QACjB,GAAG,wBAAwB;QAC3B,GAAG,iCAAiC;QACpC,GAAG,6BAA6B;QAChC,GAAG,sBAAsB;KAC1B,CAAC,CACH,CAAC;AACJ,CAAC","sourcesContent":["import {\n documentContainerProjectionTables,\n documentPlacementIntentTables,\n documentProjectionTables,\n documentTables,\n keyingCheckpointTables,\n} from \"../../../sqlite/schema\";\nimport {\n type ExecSql,\n ensureSqlTables,\n runOncePerConnection,\n} from \"../../../sqlite/sqlSchema\";\n\n// One ensure, so a cold connection sends three DDL messages in total.\nexport async function ensureDocumentsSchema(execSql: ExecSql): Promise<void> {\n await runOncePerConnection(execSql, \"ensure:documents\", () =>\n ensureSqlTables(execSql, [\n ...documentTables,\n ...documentProjectionTables,\n ...documentContainerProjectionTables,\n ...documentPlacementIntentTables,\n ...keyingCheckpointTables,\n ]),\n );\n}\n"]}
@@ -10,6 +10,7 @@ import { type SqlTableSchema } from "../sqlTableSchema.js";
10
10
  * nullable so presentation falls back to `/` for a root and `Untitled`
11
11
  * otherwise. Local timestamps track client storage/structural changes, while
12
12
  * server timestamps are populated once the container has synced.
13
+ * `(parentId) where parentId is not null` serves child-folder listings.
13
14
  */
14
15
  export declare const containers: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
15
16
  name: "containers";
@@ -1,3 +1,4 @@
1
+ import { sql } from "drizzle-orm";
1
2
  import { index, integer, primaryKey, sqliteTable, text, } from "drizzle-orm/sqlite-core";
2
3
  import { defineSqlTableSchema } from "../sqlTableSchema.js";
3
4
  const accessLevelColumn = "effective_access_level";
@@ -12,6 +13,7 @@ const accessLevelColumn = "effective_access_level";
12
13
  * nullable so presentation falls back to `/` for a root and `Untitled`
13
14
  * otherwise. Local timestamps track client storage/structural changes, while
14
15
  * server timestamps are populated once the container has synced.
16
+ * `(parentId) where parentId is not null` serves child-folder listings.
15
17
  */
16
18
  export const containers = sqliteTable("containers", {
17
19
  id: text("id"),
@@ -26,7 +28,12 @@ export const containers = sqliteTable("containers", {
26
28
  localUpdatedAt: text("local_updated_at").notNull(),
27
29
  serverCreatedAt: text("server_created_at"),
28
30
  serverUpdatedAt: text("server_updated_at"),
29
- }, (table) => [primaryKey({ columns: [table.id] })]);
31
+ }, (table) => [
32
+ primaryKey({ columns: [table.id] }),
33
+ index("containers_parent_idx")
34
+ .on(table.parentId)
35
+ .where(sql `${table.parentId} IS NOT NULL`),
36
+ ]);
30
37
  /**
31
38
  * Latest removal observed for each container. Hydration must observe the same
32
39
  * generation before fetching verified restoration evidence; unsigned clocks
@@ -1 +1 @@
1
- {"version":3,"file":"containerSchema.js","sourceRoot":"","sources":["containerSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,IAAI,GACL,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAuB,MAAM,mBAAmB,CAAC;AAE9E,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;AAEnD;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,WAAW,CACnC,YAAY,EACZ;IACE,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC;IACd,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,kBAAkB,EAAE,IAAI,CAAC,sBAAsB,CAAC;IAChD,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;IAC/B,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC;IACjC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC;IAClB,oBAAoB,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC;IACvE,cAAc,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC,OAAO,EAAE;IAClD,cAAc,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC,OAAO,EAAE;IAClD,eAAe,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAC1C,eAAe,EAAE,IAAI,CAAC,mBAAmB,CAAC;CAC3C,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CACjD,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,WAAW,CACrD,gCAAgC,EAChC;IACE,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC3C,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;IACzE,MAAM,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE;IAChC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;CACxC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAC1D,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,WAAW,CACjD,4BAA4B,EAC5B;IACE,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC3C,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;CAC1C,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC;IAC5C,KAAK,CAAC,6CAA6C,CAAC,CAAC,EAAE,CACrD,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,WAAW,CAClB;CACF,CACF,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,WAAW,CACpD,+BAA+B,EAC/B;IACE,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;IAC3C,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,YAAY,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE;CAC9C,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC;CACnE,CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,WAAW,CACrD,iCAAiC,EACjC;IACE,cAAc,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE;IACjD,eAAe,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC,OAAO,EAAE;IACpD,UAAU,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,YAAY,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAC3D,eAAe,EAAE,IAAI,CAAC,mBAAmB,CAAC;IAC1C,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE;CAC5C,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,eAAe,CAAC,EAAE,CAAC;CACvE,CACF,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAkC;IAClE;QACE,GAAG,oBAAoB,CAAC,UAAU,CAAC;QACnC,eAAe,EAAE,CAAC,cAAc,EAAE,MAAM,CAAC;KAC1C;IACD;QACE,GAAG,oBAAoB,CAAC,4BAA4B,CAAC;QACrD,eAAe,EAAE,CAAC,SAAS,CAAC;KAC7B;IACD,oBAAoB,CAAC,wBAAwB,CAAC;IAC9C,oBAAoB,CAAC,4BAA4B,CAAC;IAClD,oBAAoB,CAAC,2BAA2B,CAAC;CAClD,CAAC;AAEF,MAAM,CAAC,MAAM,qBAAqB,GAAG;IACnC,UAAU;IACV,4BAA4B;IAC5B,wBAAwB;IACxB,4BAA4B;IAC5B,2BAA2B;CAC5B,CAAC","sourcesContent":["import {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema, type SqlTableSchema } from \"../sqlTableSchema\";\n\nconst accessLevelColumn = \"effective_access_level\";\n\n/**\n * Materialized local container tree.\n *\n * Container rows describe the tree and its encrypted metadata document;\n * metadata rows live in `documents`. `id` is the primary key for structural\n * lookups. `metadataDocumentId` is the server metadata-document id when known;\n * `systemSlot` is an optional opaque app-owned slot. `displayName` and `icon`\n * are the decrypted metadata projection lists read: `displayName` stays\n * nullable so presentation falls back to `/` for a root and `Untitled`\n * otherwise. Local timestamps track client storage/structural changes, while\n * server timestamps are populated once the container has synced.\n */\nexport const containers = sqliteTable(\n \"containers\",\n {\n id: text(\"id\"),\n organizationId: text(\"organization_id\").notNull(),\n parentId: text(\"parent_id\"),\n metadataDocumentId: text(\"metadata_document_id\"),\n systemSlot: text(\"system_slot\"),\n displayName: text(\"display_name\"),\n icon: text(\"icon\"),\n effectiveAccessLevel: text(accessLevelColumn).notNull().default(\"read\"),\n localCreatedAt: text(\"local_created_at\").notNull(),\n localUpdatedAt: text(\"local_updated_at\").notNull(),\n serverCreatedAt: text(\"server_created_at\"),\n serverUpdatedAt: text(\"server_updated_at\"),\n },\n (table) => [primaryKey({ columns: [table.id] })],\n);\n\n/**\n * Latest removal observed for each container. Hydration must observe the same\n * generation before fetching verified restoration evidence; unsigned clocks\n * never establish a terminal deletion or bypass a concurrent removal. Cleared\n * observations retain their generation so remove/restore/remove cannot reuse it.\n */\nexport const containerHydrationTombstones = sqliteTable(\n \"container_hydration_tombstones\",\n {\n containerId: text(\"container_id\").notNull(),\n generation: integer(\"generation\").notNull().default(1),\n cleared: integer(\"cleared\", { mode: \"boolean\" }).notNull().default(false),\n reason: text(\"reason\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.containerId] })],\n);\n\n/**\n * Organization attribution for container metadata retained after access loss.\n * The container row is removed on revocation, so this marker retains the\n * organization scope needed by a later access-restoration sweep.\n */\nexport const dormantContainerMetadata = sqliteTable(\n \"dormant_container_metadata\",\n {\n containerId: text(\"container_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n retainedAt: text(\"retained_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.containerId] }),\n index(\"dormant_container_metadata_organization_idx\").on(\n table.organizationId,\n table.containerId,\n ),\n ],\n);\n\n/**\n * Organizations a held folder was re-homed away from. Purged-organization\n * recovery re-creates folders under their existing ids and a purged\n * organization never returns, so a later proof binding the folder back to one\n * of these organizations is a replay. Retained across remote resets.\n */\nexport const supersededContainerBindings = sqliteTable(\n \"superseded_container_bindings\",\n {\n containerId: text(\"container_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n supersededAt: text(\"superseded_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.containerId, table.organizationId] }),\n ],\n);\n\n/**\n * Durable request for a post-access-restoration crawl and sweep. Attempt state\n * enforces exponential backoff and a bounded retry budget across restarts.\n */\nexport const dormantMetadataSweepRequests = sqliteTable(\n \"dormant_metadata_sweep_requests\",\n {\n organizationId: text(\"organization_id\").notNull(),\n requesterUserId: text(\"requester_user_id\").notNull(),\n generation: integer(\"generation\").notNull().default(1),\n attemptCount: integer(\"attempt_count\").notNull().default(0),\n lastAttemptedAt: text(\"last_attempted_at\"),\n requestedAt: text(\"requested_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.organizationId, table.requesterUserId] }),\n ],\n);\n\nexport const containerTableSchemas: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(containers),\n requiredColumns: [\"display_name\", \"icon\"],\n },\n {\n ...defineSqlTableSchema(containerHydrationTombstones),\n requiredColumns: [\"cleared\"],\n },\n defineSqlTableSchema(dormantContainerMetadata),\n defineSqlTableSchema(dormantMetadataSweepRequests),\n defineSqlTableSchema(supersededContainerBindings),\n];\n\nexport const containerSQLiteSchema = {\n containers,\n containerHydrationTombstones,\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n supersededContainerBindings,\n};\n"]}
1
+ {"version":3,"file":"containerSchema.js","sourceRoot":"","sources":["containerSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { sql } from \"drizzle-orm\";\nimport {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\nimport { defineSqlTableSchema, type SqlTableSchema } from \"../sqlTableSchema\";\n\nconst accessLevelColumn = \"effective_access_level\";\n\n/**\n * Materialized local container tree.\n *\n * Container rows describe the tree and its encrypted metadata document;\n * metadata rows live in `documents`. `id` is the primary key for structural\n * lookups. `metadataDocumentId` is the server metadata-document id when known;\n * `systemSlot` is an optional opaque app-owned slot. `displayName` and `icon`\n * are the decrypted metadata projection lists read: `displayName` stays\n * nullable so presentation falls back to `/` for a root and `Untitled`\n * otherwise. Local timestamps track client storage/structural changes, while\n * server timestamps are populated once the container has synced.\n * `(parentId) where parentId is not null` serves child-folder listings.\n */\nexport const containers = sqliteTable(\n \"containers\",\n {\n id: text(\"id\"),\n organizationId: text(\"organization_id\").notNull(),\n parentId: text(\"parent_id\"),\n metadataDocumentId: text(\"metadata_document_id\"),\n systemSlot: text(\"system_slot\"),\n displayName: text(\"display_name\"),\n icon: text(\"icon\"),\n effectiveAccessLevel: text(accessLevelColumn).notNull().default(\"read\"),\n localCreatedAt: text(\"local_created_at\").notNull(),\n localUpdatedAt: text(\"local_updated_at\").notNull(),\n serverCreatedAt: text(\"server_created_at\"),\n serverUpdatedAt: text(\"server_updated_at\"),\n },\n (table) => [\n primaryKey({ columns: [table.id] }),\n index(\"containers_parent_idx\")\n .on(table.parentId)\n .where(sql`${table.parentId} IS NOT NULL`),\n ],\n);\n\n/**\n * Latest removal observed for each container. Hydration must observe the same\n * generation before fetching verified restoration evidence; unsigned clocks\n * never establish a terminal deletion or bypass a concurrent removal. Cleared\n * observations retain their generation so remove/restore/remove cannot reuse it.\n */\nexport const containerHydrationTombstones = sqliteTable(\n \"container_hydration_tombstones\",\n {\n containerId: text(\"container_id\").notNull(),\n generation: integer(\"generation\").notNull().default(1),\n cleared: integer(\"cleared\", { mode: \"boolean\" }).notNull().default(false),\n reason: text(\"reason\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n },\n (table) => [primaryKey({ columns: [table.containerId] })],\n);\n\n/**\n * Organization attribution for container metadata retained after access loss.\n * The container row is removed on revocation, so this marker retains the\n * organization scope needed by a later access-restoration sweep.\n */\nexport const dormantContainerMetadata = sqliteTable(\n \"dormant_container_metadata\",\n {\n containerId: text(\"container_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n retainedAt: text(\"retained_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.containerId] }),\n index(\"dormant_container_metadata_organization_idx\").on(\n table.organizationId,\n table.containerId,\n ),\n ],\n);\n\n/**\n * Organizations a held folder was re-homed away from. Purged-organization\n * recovery re-creates folders under their existing ids and a purged\n * organization never returns, so a later proof binding the folder back to one\n * of these organizations is a replay. Retained across remote resets.\n */\nexport const supersededContainerBindings = sqliteTable(\n \"superseded_container_bindings\",\n {\n containerId: text(\"container_id\").notNull(),\n organizationId: text(\"organization_id\").notNull(),\n supersededAt: text(\"superseded_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.containerId, table.organizationId] }),\n ],\n);\n\n/**\n * Durable request for a post-access-restoration crawl and sweep. Attempt state\n * enforces exponential backoff and a bounded retry budget across restarts.\n */\nexport const dormantMetadataSweepRequests = sqliteTable(\n \"dormant_metadata_sweep_requests\",\n {\n organizationId: text(\"organization_id\").notNull(),\n requesterUserId: text(\"requester_user_id\").notNull(),\n generation: integer(\"generation\").notNull().default(1),\n attemptCount: integer(\"attempt_count\").notNull().default(0),\n lastAttemptedAt: text(\"last_attempted_at\"),\n requestedAt: text(\"requested_at\").notNull(),\n },\n (table) => [\n primaryKey({ columns: [table.organizationId, table.requesterUserId] }),\n ],\n);\n\nexport const containerTableSchemas: ReadonlyArray<SqlTableSchema> = [\n {\n ...defineSqlTableSchema(containers),\n requiredColumns: [\"display_name\", \"icon\"],\n },\n {\n ...defineSqlTableSchema(containerHydrationTombstones),\n requiredColumns: [\"cleared\"],\n },\n defineSqlTableSchema(dormantContainerMetadata),\n defineSqlTableSchema(dormantMetadataSweepRequests),\n defineSqlTableSchema(supersededContainerBindings),\n];\n\nexport const containerSQLiteSchema = {\n containers,\n containerHydrationTombstones,\n dormantContainerMetadata,\n dormantMetadataSweepRequests,\n supersededContainerBindings,\n};\n"]}
@@ -17,7 +17,6 @@
17
17
  * Indexes:
18
18
  * - `(localId, slotId)` is the primary key and keeps one pending blob per
19
19
  * document attachment slot.
20
- * - `mimeType` supports blob-browser MIME grouping and sorting.
21
20
  */
22
21
  export declare const documentPendingAttachments: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
23
22
  name: "document_pending_attachments";
@@ -333,7 +332,6 @@ export declare const documentPendingAttachments: import("drizzle-orm/sqlite-core
333
332
  * Indexes:
334
333
  * - `(localId, slotId)` is the primary key and keeps one projected blob per
335
334
  * document attachment slot.
336
- * - `mimeType` supports blob-browser MIME grouping and sorting.
337
335
  */
338
336
  export declare const documentAttachmentBlobProjection: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
339
337
  name: "document_attachment_blob_projection";
@@ -18,7 +18,6 @@ import { index, integer, primaryKey, sqliteTable, text, } from "drizzle-orm/sqli
18
18
  * Indexes:
19
19
  * - `(localId, slotId)` is the primary key and keeps one pending blob per
20
20
  * document attachment slot.
21
- * - `mimeType` supports blob-browser MIME grouping and sorting.
22
21
  */
23
22
  export const documentPendingAttachments = sqliteTable("document_pending_attachments", {
24
23
  localId: text("local_id").notNull(),
@@ -43,7 +42,6 @@ export const documentPendingAttachments = sqliteTable("document_pending_attachme
43
42
  uploadStageId: text("upload_stage_id"),
44
43
  }, (table) => [
45
44
  primaryKey({ columns: [table.localId, table.slotId] }),
46
- index("document_pending_attachments_mime_type_idx").on(table.mimeType),
47
45
  index("document_pending_attachments_storage_key_idx").on(table.storageKey),
48
46
  ]);
49
47
  /**
@@ -74,7 +72,6 @@ export const documentPendingAttachments = sqliteTable("document_pending_attachme
74
72
  * Indexes:
75
73
  * - `(localId, slotId)` is the primary key and keeps one projected blob per
76
74
  * document attachment slot.
77
- * - `mimeType` supports blob-browser MIME grouping and sorting.
78
75
  */
79
76
  export const documentAttachmentBlobProjection = sqliteTable("document_attachment_blob_projection", {
80
77
  localId: text("local_id").notNull(),
@@ -88,7 +85,6 @@ export const documentAttachmentBlobProjection = sqliteTable("document_attachment
88
85
  detachedAt: text("detached_at"),
89
86
  }, (table) => [
90
87
  primaryKey({ columns: [table.localId, table.slotId] }),
91
- index("document_attachment_blob_projection_mime_type_idx").on(table.mimeType),
92
88
  index("document_attachment_blob_projection_storage_key_idx").on(table.storageKey),
93
89
  ]);
94
90
  //# sourceMappingURL=documentAttachmentSchema.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"documentAttachmentSchema.js","sourceRoot":"","sources":["documentAttachmentSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,IAAI,GACL,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CACnD,8BAA8B,EAC9B;IACE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IACzC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IAC5C,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE;IAC/C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,4EAA4E;IAC5E,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,iCAAiC;IACjC,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC;IACpC,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,CAAC;IAC5C,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,qBAAqB,EAAE,OAAO,CAAC,0BAA0B,CAAC;IAC1D,cAAc,EAAE,OAAO,CAAC,kBAAkB,CAAC;IAC3C,qBAAqB,EAAE,IAAI,CAAC,yBAAyB,CAAC;IACtD,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC;CACvC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACtD,KAAK,CAAC,4CAA4C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC;IACtE,KAAK,CAAC,8CAA8C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;CAC3E,CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,WAAW,CACzD,qCAAqC,EACrC;IACE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;IACvB,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IACzC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IAC5C,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE;IAC/C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;CAChC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACtD,KAAK,CAAC,mDAAmD,CAAC,CAAC,EAAE,CAC3D,KAAK,CAAC,QAAQ,CACf;IACD,KAAK,CAAC,qDAAqD,CAAC,CAAC,EAAE,CAC7D,KAAK,CAAC,UAAU,CACjB;CACF,CACF,CAAC","sourcesContent":["import {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\n\n/**\n * Pending attachment uploads for local document changes.\n *\n * These rows describe attachment blobs referenced by local document mutations\n * that have not yet been folded into the synced attachment/blob projection.\n * Once the attachment is accepted or discarded, the pending row is removed.\n *\n * Columns:\n * - `localId`: Local document id that owns the attachment slot.\n * - `slotId`: Stable attachment slot id within the document.\n * - `name`: User-facing attachment filename.\n * - `mimeType`: Optional MIME type supplied for the blob.\n * - `storageKey`: Local blob storage key for upload/readback.\n * - `byteLength`: Blob size in bytes.\n * - `createdAt`: Queue insertion timestamp used for ordered display.\n *\n * Indexes:\n * - `(localId, slotId)` is the primary key and keeps one pending blob per\n * document attachment slot.\n * - `mimeType` supports blob-browser MIME grouping and sorting.\n */\nexport const documentPendingAttachments = sqliteTable(\n \"document_pending_attachments\",\n {\n localId: text(\"local_id\").notNull(),\n slotId: text(\"slot_id\").notNull(),\n name: text(\"name\").notNull(),\n mimeType: text(\"mime_type\"),\n storageKey: text(\"storage_key\").notNull(),\n byteLength: integer(\"byte_length\").notNull(),\n contentSha256: text(\"content_sha256\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n // Upload-resume identity, set on the first upload attempt. Reusing the blob\n // id, content key and IV seed makes every encrypted chunk byte-identical, so\n // the persisted multipart stage can resume instead of being orphaned. All\n // nullable: only in-flight uploads have them, and they are dropped with the\n // row once the upload completes.\n uploadBlobId: text(\"upload_blob_id\"),\n uploadContentKey: text(\"upload_content_key\"),\n uploadIv: text(\"upload_iv\"),\n uploadContentKeyEpoch: integer(\"upload_content_key_epoch\"),\n uploadPartSize: integer(\"upload_part_size\"),\n uploadPlaintextSha256: text(\"upload_plaintext_sha256\"),\n uploadStageId: text(\"upload_stage_id\"),\n },\n (table) => [\n primaryKey({ columns: [table.localId, table.slotId] }),\n index(\"document_pending_attachments_mime_type_idx\").on(table.mimeType),\n index(\"document_pending_attachments_storage_key_idx\").on(table.storageKey),\n ],\n);\n\n/**\n * Local attachment blob projection for stored documents.\n *\n * This table tracks the attachment blobs currently available to the client for\n * each document slot. `blobId` is optional because the local storage key can be\n * known before the server blob identity has been assigned or downloaded.\n *\n * Columns:\n * - `localId`: Local document id that owns the attachment slot.\n * - `slotId`: Stable attachment slot id within the document.\n * - `blobId`: Server blob id when known.\n * - `storageKey`: Local blob storage key for opening the attachment.\n * - `mimeType`: Optional MIME type associated with the blob.\n * - `byteLength`: Blob size in bytes.\n * - `contentSha256`: Plaintext digest of the bytes held at `storageKey`. The\n * document content records the digest it intends for the slot; a held copy\n * whose digest differs is a validly signed served binding the document has\n * not (yet) recorded, and read models flag it rather than hide it.\n * - `updatedAt`: Local timestamp for the attachment projection update.\n * - `detachedAt`: Local timestamp set when the slot is unlinked from a synced\n * document. The row outlives the unlink because it is also the durable\n * \"still needs a remote detach\" marker (see `syncDetachedAttachments`), so\n * read models that answer \"what references this blob\" must skip detached\n * rows instead of waiting for the detach to flush.\n *\n * Indexes:\n * - `(localId, slotId)` is the primary key and keeps one projected blob per\n * document attachment slot.\n * - `mimeType` supports blob-browser MIME grouping and sorting.\n */\nexport const documentAttachmentBlobProjection = sqliteTable(\n \"document_attachment_blob_projection\",\n {\n localId: text(\"local_id\").notNull(),\n slotId: text(\"slot_id\").notNull(),\n blobId: text(\"blob_id\"),\n storageKey: text(\"storage_key\").notNull(),\n mimeType: text(\"mime_type\"),\n byteLength: integer(\"byte_length\").notNull(),\n contentSha256: text(\"content_sha256\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n detachedAt: text(\"detached_at\"),\n },\n (table) => [\n primaryKey({ columns: [table.localId, table.slotId] }),\n index(\"document_attachment_blob_projection_mime_type_idx\").on(\n table.mimeType,\n ),\n index(\"document_attachment_blob_projection_storage_key_idx\").on(\n table.storageKey,\n ),\n ],\n);\n"]}
1
+ {"version":3,"file":"documentAttachmentSchema.js","sourceRoot":"","sources":["documentAttachmentSchema.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EACL,OAAO,EACP,UAAU,EACV,WAAW,EACX,IAAI,GACL,MAAM,yBAAyB,CAAC;AAEjC;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,WAAW,CACnD,8BAA8B,EAC9B;IACE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IACzC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IAC5C,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE;IAC/C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,4EAA4E;IAC5E,6EAA6E;IAC7E,0EAA0E;IAC1E,4EAA4E;IAC5E,iCAAiC;IACjC,YAAY,EAAE,IAAI,CAAC,gBAAgB,CAAC;IACpC,gBAAgB,EAAE,IAAI,CAAC,oBAAoB,CAAC;IAC5C,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,qBAAqB,EAAE,OAAO,CAAC,0BAA0B,CAAC;IAC1D,cAAc,EAAE,OAAO,CAAC,kBAAkB,CAAC;IAC3C,qBAAqB,EAAE,IAAI,CAAC,yBAAyB,CAAC;IACtD,aAAa,EAAE,IAAI,CAAC,iBAAiB,CAAC;CACvC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACtD,KAAK,CAAC,8CAA8C,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC;CAC3E,CACF,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG,WAAW,CACzD,qCAAqC,EACrC;IACE,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;IACjC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC;IACvB,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IACzC,QAAQ,EAAE,IAAI,CAAC,WAAW,CAAC;IAC3B,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,EAAE;IAC5C,aAAa,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE;IAC/C,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC;CAChC,EACD,CAAC,KAAK,EAAE,EAAE,CAAC;IACT,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;IACtD,KAAK,CAAC,qDAAqD,CAAC,CAAC,EAAE,CAC7D,KAAK,CAAC,UAAU,CACjB;CACF,CACF,CAAC","sourcesContent":["import {\n index,\n integer,\n primaryKey,\n sqliteTable,\n text,\n} from \"drizzle-orm/sqlite-core\";\n\n/**\n * Pending attachment uploads for local document changes.\n *\n * These rows describe attachment blobs referenced by local document mutations\n * that have not yet been folded into the synced attachment/blob projection.\n * Once the attachment is accepted or discarded, the pending row is removed.\n *\n * Columns:\n * - `localId`: Local document id that owns the attachment slot.\n * - `slotId`: Stable attachment slot id within the document.\n * - `name`: User-facing attachment filename.\n * - `mimeType`: Optional MIME type supplied for the blob.\n * - `storageKey`: Local blob storage key for upload/readback.\n * - `byteLength`: Blob size in bytes.\n * - `createdAt`: Queue insertion timestamp used for ordered display.\n *\n * Indexes:\n * - `(localId, slotId)` is the primary key and keeps one pending blob per\n * document attachment slot.\n */\nexport const documentPendingAttachments = sqliteTable(\n \"document_pending_attachments\",\n {\n localId: text(\"local_id\").notNull(),\n slotId: text(\"slot_id\").notNull(),\n name: text(\"name\").notNull(),\n mimeType: text(\"mime_type\"),\n storageKey: text(\"storage_key\").notNull(),\n byteLength: integer(\"byte_length\").notNull(),\n contentSha256: text(\"content_sha256\").notNull(),\n createdAt: text(\"created_at\").notNull(),\n // Upload-resume identity, set on the first upload attempt. Reusing the blob\n // id, content key and IV seed makes every encrypted chunk byte-identical, so\n // the persisted multipart stage can resume instead of being orphaned. All\n // nullable: only in-flight uploads have them, and they are dropped with the\n // row once the upload completes.\n uploadBlobId: text(\"upload_blob_id\"),\n uploadContentKey: text(\"upload_content_key\"),\n uploadIv: text(\"upload_iv\"),\n uploadContentKeyEpoch: integer(\"upload_content_key_epoch\"),\n uploadPartSize: integer(\"upload_part_size\"),\n uploadPlaintextSha256: text(\"upload_plaintext_sha256\"),\n uploadStageId: text(\"upload_stage_id\"),\n },\n (table) => [\n primaryKey({ columns: [table.localId, table.slotId] }),\n index(\"document_pending_attachments_storage_key_idx\").on(table.storageKey),\n ],\n);\n\n/**\n * Local attachment blob projection for stored documents.\n *\n * This table tracks the attachment blobs currently available to the client for\n * each document slot. `blobId` is optional because the local storage key can be\n * known before the server blob identity has been assigned or downloaded.\n *\n * Columns:\n * - `localId`: Local document id that owns the attachment slot.\n * - `slotId`: Stable attachment slot id within the document.\n * - `blobId`: Server blob id when known.\n * - `storageKey`: Local blob storage key for opening the attachment.\n * - `mimeType`: Optional MIME type associated with the blob.\n * - `byteLength`: Blob size in bytes.\n * - `contentSha256`: Plaintext digest of the bytes held at `storageKey`. The\n * document content records the digest it intends for the slot; a held copy\n * whose digest differs is a validly signed served binding the document has\n * not (yet) recorded, and read models flag it rather than hide it.\n * - `updatedAt`: Local timestamp for the attachment projection update.\n * - `detachedAt`: Local timestamp set when the slot is unlinked from a synced\n * document. The row outlives the unlink because it is also the durable\n * \"still needs a remote detach\" marker (see `syncDetachedAttachments`), so\n * read models that answer \"what references this blob\" must skip detached\n * rows instead of waiting for the detach to flush.\n *\n * Indexes:\n * - `(localId, slotId)` is the primary key and keeps one projected blob per\n * document attachment slot.\n */\nexport const documentAttachmentBlobProjection = sqliteTable(\n \"document_attachment_blob_projection\",\n {\n localId: text(\"local_id\").notNull(),\n slotId: text(\"slot_id\").notNull(),\n blobId: text(\"blob_id\"),\n storageKey: text(\"storage_key\").notNull(),\n mimeType: text(\"mime_type\"),\n byteLength: integer(\"byte_length\").notNull(),\n contentSha256: text(\"content_sha256\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n detachedAt: text(\"detached_at\"),\n },\n (table) => [\n primaryKey({ columns: [table.localId, table.slotId] }),\n index(\"document_attachment_blob_projection_storage_key_idx\").on(\n table.storageKey,\n ),\n ],\n);\n"]}
@@ -1298,6 +1298,8 @@ export declare const trustedUserIdentityPins: import("drizzle-orm/sqlite-core").
1298
1298
  * Indexes:
1299
1299
  * - `(documentId, containerId)` is the primary key and prevents duplicate
1300
1300
  * links for the same document/container pair.
1301
+ * - `(containerId, documentId)` serves the container-filtered link scans
1302
+ * (folder item and sidebar windows) as a covering index search.
1301
1303
  */
1302
1304
  export declare const documentContainerProjection: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
1303
1305
  name: "document_container_projection";
@@ -176,6 +176,10 @@ export const documentHistoryUpdates = sqliteTable("document_history_updates", {
176
176
  uniqueIndex("document_history_updates_update_id_idx")
177
177
  .on(table.updateId)
178
178
  .where(sql `${table.updateId} IS NOT NULL`),
179
+ // Queued rows only: pending counts and pending loads skip settled history.
180
+ index("document_history_updates_queued_scope_idx")
181
+ .on(table.appKind, table.localId, table.createdAt)
182
+ .where(sql `${table.updateId} IS NOT NULL`),
179
183
  ]);
180
184
  /**
181
185
  * Anti-rollback pin for verified access manifests.
@@ -280,12 +284,17 @@ export const trustedUserIdentityPins = sqliteTable("trusted_user_identity_pins",
280
284
  * Indexes:
281
285
  * - `(documentId, containerId)` is the primary key and prevents duplicate
282
286
  * links for the same document/container pair.
287
+ * - `(containerId, documentId)` serves the container-filtered link scans
288
+ * (folder item and sidebar windows) as a covering index search.
283
289
  */
284
290
  export const documentContainerProjection = sqliteTable("document_container_projection", {
285
291
  documentId: text("document_id").notNull(),
286
292
  containerId: text("container_id").notNull(),
287
293
  updatedAt: text("updated_at").notNull(),
288
- }, (table) => [primaryKey({ columns: [table.documentId, table.containerId] })]);
294
+ }, (table) => [
295
+ primaryKey({ columns: [table.documentId, table.containerId] }),
296
+ index("document_container_projection_container_idx").on(table.containerId, table.documentId),
297
+ ]);
289
298
  /**
290
299
  * Queryable document summary and detail projection.
291
300
  *