@tearleads/client-sdk 0.1.41 → 0.1.42

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 (93) hide show
  1. package/client/Tearleads.js +3 -0
  2. package/client/Tearleads.js.map +1 -1
  3. package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js +2 -0
  4. package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js.map +1 -1
  5. package/data/keyingProjectionVerification/checkpointContext.d.ts +12 -0
  6. package/data/keyingProjectionVerification/checkpointContext.js +16 -0
  7. package/data/keyingProjectionVerification/checkpointContext.js.map +1 -1
  8. package/data/keyingProjectionVerification/containerDestinationVerification.js +3 -1
  9. package/data/keyingProjectionVerification/containerDestinationVerification.js.map +1 -1
  10. package/data/keyingProjectionVerification/containerProjectionVerification.js +12 -6
  11. package/data/keyingProjectionVerification/containerProjectionVerification.js.map +1 -1
  12. package/data/keyingProjectionVerification/documentProjectionVerification.js +10 -4
  13. package/data/keyingProjectionVerification/documentProjectionVerification.js.map +1 -1
  14. package/data/persistence/keyingCheckpointAdvancePersistence.js +27 -8
  15. package/data/persistence/keyingCheckpointAdvancePersistence.js.map +1 -1
  16. package/data/persistence/verifiedManifestBundlePersistence.d.ts +45 -0
  17. package/data/persistence/verifiedManifestBundlePersistence.js +282 -0
  18. package/data/persistence/verifiedManifestBundlePersistence.js.map +1 -0
  19. package/data/sqlite/schema.d.ts +157 -0
  20. package/data/sqlite/schema.js +3 -0
  21. package/data/sqlite/schema.js.map +1 -1
  22. package/data/sqlite/verifiedManifestBundleSchema.d.ts +174 -0
  23. package/data/sqlite/verifiedManifestBundleSchema.js +36 -0
  24. package/data/sqlite/verifiedManifestBundleSchema.js.map +1 -0
  25. package/internal/api-client/ApiClient.d.ts +4 -11
  26. package/internal/api-client/ApiClient.js +8 -6
  27. package/internal/api-client/ApiClient.js.map +1 -1
  28. package/internal/api-client/index.d.ts +1 -1
  29. package/internal/api-client/index.js +0 -1
  30. package/internal/api-client/index.js.map +1 -1
  31. package/internal/api-client/principalHistoryRequest.js +8 -2
  32. package/internal/api-client/principalHistoryRequest.js.map +1 -1
  33. package/internal/api-client/principalHistoryRequestContext.js +15 -5
  34. package/internal/api-client/principalHistoryRequestContext.js.map +1 -1
  35. package/internal/api-client/routes/writerProjections.js +6 -3
  36. package/internal/api-client/routes/writerProjections.js.map +1 -1
  37. package/internal/api-client/verifiedManifestCitations.d.ts +23 -0
  38. package/internal/api-client/verifiedManifestCitations.js +60 -0
  39. package/internal/api-client/verifiedManifestCitations.js.map +1 -0
  40. package/internal/api-client/writerProjectionRequests.js +75 -14
  41. package/internal/api-client/writerProjectionRequests.js.map +1 -1
  42. package/internal/crypto/index.d.ts +0 -1
  43. package/internal/crypto/index.js +0 -1
  44. package/internal/crypto/index.js.map +1 -1
  45. package/internal/validators/knownManifestsRefinements.js +5 -0
  46. package/internal/validators/knownManifestsRefinements.js.map +1 -0
  47. package/internal/validators/operation/writerProjections.d.ts +85 -319
  48. package/internal/validators/operation/writerProjections.js +11 -11
  49. package/internal/validators/operation/writerProjections.js.map +1 -1
  50. package/internal/validators/response/container.d.ts +429 -20
  51. package/internal/validators/response/container.js +40 -5
  52. package/internal/validators/response/container.js.map +1 -1
  53. package/internal/validators/response/documentMutation.d.ts +440 -20
  54. package/internal/validators/response/documentMutation.js +33 -3
  55. package/internal/validators/response/documentMutation.js.map +1 -1
  56. package/internal/validators/response/index.d.ts +3 -2
  57. package/internal/validators/response/index.js +3 -2
  58. package/internal/validators/response/index.js.map +1 -1
  59. package/internal/validators/response/manifestBundleReferences.js +79 -0
  60. package/internal/validators/response/manifestBundleReferences.js.map +1 -0
  61. package/internal/validators/response/writerProjectionWire.d.ts +19 -0
  62. package/internal/validators/response/writerProjectionWire.js +132 -0
  63. package/internal/validators/response/writerProjectionWire.js.map +1 -0
  64. package/internal/validators/schema.js +20 -0
  65. package/internal/validators/schema.js.map +1 -1
  66. package/internal/validators/util/index.d.ts +1 -1
  67. package/internal/validators/util/index.js +1 -1
  68. package/internal/validators/util/index.js.map +1 -1
  69. package/internal/validators/util/knownManifestWire.d.ts +11 -0
  70. package/internal/validators/util/knownManifestWire.js +28 -0
  71. package/internal/validators/util/knownManifestWire.js.map +1 -0
  72. package/internal/validators/writerProjectionRefinements.js +5 -0
  73. package/internal/validators/writerProjectionRefinements.js.map +1 -1
  74. package/package.json +1 -1
  75. package/workflows/registration/provisioningBootstrapBuilders.d.ts +0 -5
  76. package/workflows/sync/remoteReset.js +2 -0
  77. package/workflows/sync/remoteReset.js.map +1 -1
  78. package/internal/api-client/projectionHistoryTransport.js +0 -107
  79. package/internal/api-client/projectionHistoryTransport.js.map +0 -1
  80. package/internal/api-client/verifiedProjectionHistory.d.ts +0 -4
  81. package/internal/api-client/verifiedProjectionHistory.js +0 -12
  82. package/internal/api-client/verifiedProjectionHistory.js.map +0 -1
  83. package/internal/crypto/projectionHistory.d.ts +0 -14
  84. package/internal/crypto/projectionHistory.js +0 -90
  85. package/internal/crypto/projectionHistory.js.map +0 -1
  86. package/internal/crypto/projectionHistorySlots.d.ts +0 -13
  87. package/internal/crypto/projectionHistorySlots.js +0 -81
  88. package/internal/crypto/projectionHistorySlots.js.map +0 -1
  89. package/internal/validators/projectionHistoryRefinements.js +0 -5
  90. package/internal/validators/projectionHistoryRefinements.js.map +0 -1
  91. package/internal/validators/util/projectionHistoryWire.d.ts +0 -23
  92. package/internal/validators/util/projectionHistoryWire.js +0 -33
  93. package/internal/validators/util/projectionHistoryWire.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"documentProjectionVerification.js","sourceRoot":"","sources":["documentProjectionVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import { retainVerifiedProjectionHistory } from \"@tearleads/api-client\";\nimport type {\n PrincipalPolicyAuthorization,\n VerifiedContainerAccessManifest,\n VerifiedDocumentLinkSetManifest,\n VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { addBundleByHash } from \"./bundleVerification\";\nimport {\n createProjectionCheckpointContext,\n finalizeProjectionCheckpoints,\n observeAccessManifestCheckpoints,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { verifyContainerManifestPath } from \"./containerPathVerification\";\nimport {\n addContainerWriterProjectionBundles,\n verifiedContainerManifestsForBundles,\n verifyContainerWriterProjectionWithContext,\n} from \"./containerProjectionVerification\";\nimport { documentContainerProjections } from \"./documentContainerProjections\";\nimport { verifyDocumentProjectionManifests } from \"./documentManifestVerification\";\nimport { rejectPurgedDocumentProjection } from \"./documentPurgeCheckpointEnforcement\";\nimport { throwKeyingVerificationShapeFailure } from \"./error\";\nimport { verifyProjectionAuthorizationEvidence } from \"./projectionAuthorizationEvidence\";\nimport { readAccessManifest } from \"./readers\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\nimport { withGenerationGuardedPolicyWarmer } from \"./types\";\n\ntype VerifiedManifestMap = Map<string, VerifiedContainerAccessManifest>;\ntype PolicyWarmer = ReferencedPrincipalPolicyWarmer | undefined;\n\nfunction readDocumentProjectionContainerPaths(\n projection: DocumentWriterProjectionResponse,\n): AccessManifestBundleWireResponse[][] {\n return [\n ...projection.documentManifestContainerPaths,\n ...projection.authorizingContainerPaths.map((path) => path.path),\n ];\n}\n\nfunction collectDocumentProjectionContainerBundles(\n projection: DocumentWriterProjectionResponse,\n): Map<string, AccessManifestBundleWireResponse> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n for (const [index, authorizing] of documentContainerProjections(\n projection,\n ).entries()) {\n addContainerWriterProjectionBundles(\n bundlesByHash,\n authorizing,\n `Document writer projection authorizing path[${index}]`,\n );\n }\n for (const [index, path] of readDocumentProjectionContainerPaths(\n projection,\n ).entries()) {\n for (const [pathIndex, bundle] of path.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document writer projection dependency path[${index}][${pathIndex}]`,\n );\n }\n }\n for (const [\n index,\n bundle,\n ] of projection.documentContainerManifestHistory.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document writer projection container history[${index}]`,\n );\n }\n return bundlesByHash;\n}\n\nasync function verifyProjectionContainerPaths(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly projection: DocumentWriterProjectionResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly verifiedByHash?: VerifiedManifestMap | undefined;\n readonly warmReferencedPrincipalPolicies?: PolicyWarmer;\n}): Promise<Map<string, readonly VerifiedContainerAccessManifest[]>> {\n const bundlesByHash = collectDocumentProjectionContainerBundles(\n input.projection,\n );\n const containerPathByManifestHash = new Map<\n string,\n readonly VerifiedContainerAccessManifest[]\n >();\n // Reuse a caller-supplied cache when provided so a later unwrap pass over the\n // same authorizing container paths does not re-verify identical manifests.\n const verifiedByHash =\n input.verifiedByHash ?? new Map<string, VerifiedContainerAccessManifest>();\n for (const projection of documentContainerProjections(input.projection)) {\n const path = await verifyContainerWriterProjectionWithContext(\n {\n authorizationEvidence: input.authorizationEvidence,\n principalPolicyCache: input.principalPolicyCache,\n projection,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n },\n input.checkpointContext,\n );\n const leaf = path.at(-1);\n if (leaf) {\n containerPathByManifestHash.set(leaf.manifestHash, path);\n }\n for (const manifest of path) {\n verifiedByHash.set(manifest.manifestHash, manifest);\n }\n }\n // Grouping supplies evidence only; each signed artifact selects its citations.\n for (const [\n index,\n path,\n ] of input.projection.documentManifestContainerPaths.entries()) {\n // Historical dependency evidence is verified without current checkpoint\n // enforcement. Its grouping cannot substitute an uncited ancestor into\n // document or content-write authorization.\n const verifiedPath = await verifyContainerManifestPath({\n authorizationEvidence: input.authorizationEvidence,\n requireAuthorizationEvidence: true,\n servedAsCurrent: false,\n authorizationMembership: \"referenced\",\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n enforceLocalCheckpoints: false,\n label: `Document writer projection dependency path[${index}]`,\n path,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n // The authorizing path recorded for the same leaf takes precedence.\n const leaf = verifiedPath.at(-1);\n if (leaf && !containerPathByManifestHash.has(leaf.manifestHash)) {\n containerPathByManifestHash.set(leaf.manifestHash, verifiedPath);\n }\n }\n\n // Keep every verified head as evidence. Events and content headers select\n // their own signed paths through resolveEventContainerPaths.\n for (const [hash, manifest] of verifiedByHash) {\n if (!containerPathByManifestHash.has(hash))\n containerPathByManifestHash.set(hash, [manifest]);\n }\n\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [],\n verifiedManifests: verifiedContainerManifestsForBundles(\n bundlesByHash,\n verifiedByHash,\n ),\n });\n\n return containerPathByManifestHash;\n}\n\ninterface DocumentWriterProjectionVerificationInput {\n readonly execSql: ExecSql;\n readonly persistVerificationCheckpoints?: boolean | undefined;\n readonly principalPolicyCache?: PrincipalPolicyCache | undefined;\n readonly projection: DocumentWriterProjectionResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly verifiedByHash?: VerifiedManifestMap | undefined;\n readonly warmReferencedPrincipalPolicies?: PolicyWarmer;\n}\nexport interface DocumentWriterProjectionAuthorization {\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly documentManifestByHash: ReadonlyMap<\n string,\n VerifiedDocumentLinkSetManifest\n >;\n readonly principalPolicies: readonly PrincipalPolicyAuthorization[];\n}\n\ninterface VerifiedDocumentWriterProjectionResult {\n readonly authorization: DocumentWriterProjectionAuthorization;\n readonly headManifest: VerifiedDocumentLinkSetManifest;\n}\n\nasync function verifyDocumentWriterProjectionWithContext(\n input: Omit<DocumentWriterProjectionVerificationInput, \"execSql\">,\n checkpointContext: ProjectionCheckpointContext,\n): Promise<VerifiedDocumentWriterProjectionResult> {\n const principalPolicyCache =\n input.principalPolicyCache ?? new Map<string, VerifiedPrincipalPolicy>();\n const authorizationEvidence = await verifyProjectionAuthorizationEvidence({\n bundles: [\n input.projection.documentManifest,\n ...input.projection.documentManifestHistory,\n ...collectDocumentProjectionContainerBundles(input.projection).values(),\n ],\n checkpointContext,\n policyEvidence: input.projection.policyEvidence,\n organizationId: readAccessManifest(\n input.projection.documentManifest.manifest,\n \"Document projection manifest\",\n ).organizationId,\n principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const containerPathByManifestHash = await verifyProjectionContainerPaths({\n authorizationEvidence,\n checkpointContext,\n principalPolicyCache,\n projection: input.projection,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash: input.verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const { headManifest, verifiedByHash } =\n await verifyDocumentProjectionManifests({\n authorizationEvidence,\n checkpointContext,\n containerPathByManifestHash,\n principalPolicyCache,\n projection: input.projection,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n await rejectPurgedDocumentProjection(\n headManifest.state.documentId,\n checkpointContext.execSql,\n );\n\n observeAccessManifestCheckpoints(checkpointContext, {\n verifiedHeads: [headManifest],\n verifiedManifests: [...verifiedByHash.values()],\n });\n\n return {\n authorization: {\n containerPathByManifestHash,\n documentManifestByHash: verifiedByHash,\n principalPolicies: authorizationEvidence,\n },\n headManifest,\n };\n}\n\nexport async function verifyDocumentWriterProjection(\n input: DocumentWriterProjectionVerificationInput,\n): Promise<VerifiedDocumentLinkSetManifest> {\n const checkpointContext = createProjectionCheckpointContext({\n execSql: input.execSql,\n });\n const verified = await verifyDocumentWriterProjectionWithContext(\n withGenerationGuardedPolicyWarmer(input),\n checkpointContext,\n );\n await finalizeProjectionCheckpoints(checkpointContext, input);\n retainVerifiedProjectionHistory(input.projection);\n return verified.headManifest;\n}\n\nexport async function verifyDocumentWriterProjectionAuthorization(\n input: DocumentWriterProjectionVerificationInput,\n): Promise<DocumentWriterProjectionAuthorization> {\n try {\n const checkpointContext = createProjectionCheckpointContext({\n execSql: input.execSql,\n });\n const verified = await verifyDocumentWriterProjectionWithContext(\n withGenerationGuardedPolicyWarmer(input),\n checkpointContext,\n );\n await finalizeProjectionCheckpoints(checkpointContext, input);\n retainVerifiedProjectionHistory(input.projection);\n return verified.authorization;\n } catch (error) {\n throwKeyingVerificationShapeFailure(error);\n }\n}\n"]}
1
+ {"version":3,"file":"documentProjectionVerification.js","sourceRoot":"","sources":["documentProjectionVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n PrincipalPolicyAuthorization,\n VerifiedContainerAccessManifest,\n VerifiedDocumentLinkSetManifest,\n VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n DocumentWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport type { ExecSql } from \"../sqlite/sqlSchema\";\nimport { addBundleByHash } from \"./bundleVerification\";\nimport {\n createProjectionCheckpointContext,\n finalizeProjectionCheckpoints,\n observeAccessManifestCheckpoints,\n observeVerifiedProjectionBundles,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { verifyContainerManifestPath } from \"./containerPathVerification\";\nimport {\n addContainerWriterProjectionBundles,\n verifiedContainerManifestsForBundles,\n verifyContainerWriterProjectionWithContext,\n} from \"./containerProjectionVerification\";\nimport { documentContainerProjections } from \"./documentContainerProjections\";\nimport { verifyDocumentProjectionManifests } from \"./documentManifestVerification\";\nimport { rejectPurgedDocumentProjection } from \"./documentPurgeCheckpointEnforcement\";\nimport { throwKeyingVerificationShapeFailure } from \"./error\";\nimport { verifyProjectionAuthorizationEvidence } from \"./projectionAuthorizationEvidence\";\nimport { readAccessManifest } from \"./readers\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\nimport { withGenerationGuardedPolicyWarmer } from \"./types\";\n\ntype VerifiedManifestMap = Map<string, VerifiedContainerAccessManifest>;\ntype PolicyWarmer = ReferencedPrincipalPolicyWarmer | undefined;\n\nfunction readDocumentProjectionContainerPaths(\n projection: DocumentWriterProjectionResponse,\n): AccessManifestBundleWireResponse[][] {\n return [\n ...projection.documentManifestContainerPaths,\n ...projection.authorizingContainerPaths.map((path) => path.path),\n ];\n}\n\nfunction collectDocumentProjectionContainerBundles(\n projection: DocumentWriterProjectionResponse,\n): Map<string, AccessManifestBundleWireResponse> {\n const bundlesByHash = new Map<string, AccessManifestBundleWireResponse>();\n for (const [index, authorizing] of documentContainerProjections(\n projection,\n ).entries()) {\n addContainerWriterProjectionBundles(\n bundlesByHash,\n authorizing,\n `Document writer projection authorizing path[${index}]`,\n );\n }\n for (const [index, path] of readDocumentProjectionContainerPaths(\n projection,\n ).entries()) {\n for (const [pathIndex, bundle] of path.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document writer projection dependency path[${index}][${pathIndex}]`,\n );\n }\n }\n for (const [\n index,\n bundle,\n ] of projection.documentContainerManifestHistory.entries()) {\n addBundleByHash(\n bundlesByHash,\n bundle,\n `Document writer projection container history[${index}]`,\n );\n }\n return bundlesByHash;\n}\n\nasync function verifyProjectionContainerPaths(input: {\n readonly authorizationEvidence: readonly PrincipalPolicyAuthorization[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly projection: DocumentWriterProjectionResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly verifiedByHash?: VerifiedManifestMap | undefined;\n readonly warmReferencedPrincipalPolicies?: PolicyWarmer;\n}): Promise<Map<string, readonly VerifiedContainerAccessManifest[]>> {\n const bundlesByHash = collectDocumentProjectionContainerBundles(\n input.projection,\n );\n const containerPathByManifestHash = new Map<\n string,\n readonly VerifiedContainerAccessManifest[]\n >();\n // Reuse a caller-supplied cache when provided so a later unwrap pass over the\n // same authorizing container paths does not re-verify identical manifests.\n const verifiedByHash =\n input.verifiedByHash ?? new Map<string, VerifiedContainerAccessManifest>();\n for (const projection of documentContainerProjections(input.projection)) {\n const path = await verifyContainerWriterProjectionWithContext(\n {\n authorizationEvidence: input.authorizationEvidence,\n principalPolicyCache: input.principalPolicyCache,\n projection,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n },\n input.checkpointContext,\n );\n const leaf = path.at(-1);\n if (leaf) {\n containerPathByManifestHash.set(leaf.manifestHash, path);\n }\n for (const manifest of path) {\n verifiedByHash.set(manifest.manifestHash, manifest);\n }\n }\n // Grouping supplies evidence only; each signed artifact selects its citations.\n for (const [\n index,\n path,\n ] of input.projection.documentManifestContainerPaths.entries()) {\n // Historical dependency evidence is verified without current checkpoint\n // enforcement. Its grouping cannot substitute an uncited ancestor into\n // document or content-write authorization.\n const verifiedPath = await verifyContainerManifestPath({\n authorizationEvidence: input.authorizationEvidence,\n requireAuthorizationEvidence: true,\n servedAsCurrent: false,\n authorizationMembership: \"referenced\",\n bundlesByHash,\n checkpointContext: input.checkpointContext,\n enforceLocalCheckpoints: false,\n label: `Document writer projection dependency path[${index}]`,\n path,\n principalPolicyCache: input.principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n // The authorizing path recorded for the same leaf takes precedence.\n const leaf = verifiedPath.at(-1);\n if (leaf && !containerPathByManifestHash.has(leaf.manifestHash)) {\n containerPathByManifestHash.set(leaf.manifestHash, verifiedPath);\n }\n }\n\n // Keep every verified head as evidence. Events and content headers select\n // their own signed paths through resolveEventContainerPaths.\n for (const [hash, manifest] of verifiedByHash) {\n if (!containerPathByManifestHash.has(hash))\n containerPathByManifestHash.set(hash, [manifest]);\n }\n\n observeAccessManifestCheckpoints(input.checkpointContext, {\n verifiedHeads: [],\n verifiedManifests: verifiedContainerManifestsForBundles(\n bundlesByHash,\n verifiedByHash,\n ),\n });\n\n return containerPathByManifestHash;\n}\n\ninterface DocumentWriterProjectionVerificationInput {\n readonly execSql: ExecSql;\n readonly persistVerificationCheckpoints?: boolean | undefined;\n readonly principalPolicyCache?: PrincipalPolicyCache | undefined;\n readonly projection: DocumentWriterProjectionResponse;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly verifiedByHash?: VerifiedManifestMap | undefined;\n readonly warmReferencedPrincipalPolicies?: PolicyWarmer;\n}\nexport interface DocumentWriterProjectionAuthorization {\n readonly containerPathByManifestHash: ReadonlyMap<\n string,\n readonly VerifiedContainerAccessManifest[]\n >;\n readonly documentManifestByHash: ReadonlyMap<\n string,\n VerifiedDocumentLinkSetManifest\n >;\n readonly principalPolicies: readonly PrincipalPolicyAuthorization[];\n}\n\ninterface VerifiedDocumentWriterProjectionResult {\n readonly authorization: DocumentWriterProjectionAuthorization;\n readonly headManifest: VerifiedDocumentLinkSetManifest;\n}\n\nasync function verifyDocumentWriterProjectionWithContext(\n input: Omit<DocumentWriterProjectionVerificationInput, \"execSql\">,\n checkpointContext: ProjectionCheckpointContext,\n): Promise<VerifiedDocumentWriterProjectionResult> {\n const principalPolicyCache =\n input.principalPolicyCache ?? new Map<string, VerifiedPrincipalPolicy>();\n const authorizationEvidence = await verifyProjectionAuthorizationEvidence({\n bundles: [\n input.projection.documentManifest,\n ...input.projection.documentManifestHistory,\n ...collectDocumentProjectionContainerBundles(input.projection).values(),\n ],\n checkpointContext,\n policyEvidence: input.projection.policyEvidence,\n organizationId: readAccessManifest(\n input.projection.documentManifest.manifest,\n \"Document projection manifest\",\n ).organizationId,\n principalPolicyCache,\n resolveUserKey: input.resolveUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const containerPathByManifestHash = await verifyProjectionContainerPaths({\n authorizationEvidence,\n checkpointContext,\n principalPolicyCache,\n projection: input.projection,\n resolveUserKey: input.resolveUserKey,\n verifiedByHash: input.verifiedByHash,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const { headManifest, verifiedByHash } =\n await verifyDocumentProjectionManifests({\n authorizationEvidence,\n checkpointContext,\n containerPathByManifestHash,\n principalPolicyCache,\n projection: input.projection,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n await rejectPurgedDocumentProjection(\n headManifest.state.documentId,\n checkpointContext.execSql,\n );\n\n observeAccessManifestCheckpoints(checkpointContext, {\n verifiedHeads: [headManifest],\n verifiedManifests: [...verifiedByHash.values()],\n });\n\n return {\n authorization: {\n containerPathByManifestHash,\n documentManifestByHash: verifiedByHash,\n principalPolicies: authorizationEvidence,\n },\n headManifest,\n };\n}\n\n/** Each served bundle, document and container, whose manifest verified. */\nfunction observeVerifiedDocumentProjectionBundles(\n checkpointContext: ProjectionCheckpointContext,\n projection: DocumentWriterProjectionResponse,\n authorization: DocumentWriterProjectionAuthorization,\n): void {\n observeVerifiedProjectionBundles(\n checkpointContext,\n new Map(\n [projection.documentManifest, ...projection.documentManifestHistory].map(\n (bundle) => [bundle.manifestHash, bundle],\n ),\n ),\n authorization.documentManifestByHash,\n );\n observeVerifiedProjectionBundles(\n checkpointContext,\n collectDocumentProjectionContainerBundles(projection),\n new Map(\n [...authorization.containerPathByManifestHash.values()]\n .flat()\n .map((manifest) => [manifest.manifestHash, manifest]),\n ),\n );\n}\n\nexport async function verifyDocumentWriterProjection(\n input: DocumentWriterProjectionVerificationInput,\n): Promise<VerifiedDocumentLinkSetManifest> {\n const checkpointContext = createProjectionCheckpointContext({\n execSql: input.execSql,\n });\n const verified = await verifyDocumentWriterProjectionWithContext(\n withGenerationGuardedPolicyWarmer(input),\n checkpointContext,\n );\n observeVerifiedDocumentProjectionBundles(\n checkpointContext,\n input.projection,\n verified.authorization,\n );\n await finalizeProjectionCheckpoints(checkpointContext, input);\n return verified.headManifest;\n}\n\nexport async function verifyDocumentWriterProjectionAuthorization(\n input: DocumentWriterProjectionVerificationInput,\n): Promise<DocumentWriterProjectionAuthorization> {\n try {\n const checkpointContext = createProjectionCheckpointContext({\n execSql: input.execSql,\n });\n const verified = await verifyDocumentWriterProjectionWithContext(\n withGenerationGuardedPolicyWarmer(input),\n checkpointContext,\n );\n observeVerifiedDocumentProjectionBundles(\n checkpointContext,\n input.projection,\n verified.authorization,\n );\n await finalizeProjectionCheckpoints(checkpointContext, input);\n return verified.authorization;\n } catch (error) {\n throwKeyingVerificationShapeFailure(error);\n }\n}\n"]}
@@ -2,12 +2,14 @@ import { KeyingVerificationError, verifyAccessManifestLocalCheckpoint, verifyPri
2
2
  import { keyingCheckpointTables, principalPolicyTables, } from "../sqlite/schema.js";
3
3
  import { getClientSQLitePersistenceRuntime, } from "../sqlite/sqlitePersistenceRuntime.js";
4
4
  import { ensureSqlTables } from "../sqlite/sqlSchema.js";
5
+ import { verifiedManifestBundleTables } from "../sqlite/verifiedManifestBundleSchema.js";
5
6
  import { storeDocumentPurgeCheckpointInTransaction, } from "./documentPurgeCheckpointPersistence.js";
6
7
  import { validateAccessManifestCheckpointEvidence } from "./keyingCheckpointEvidence.js";
7
8
  import { accessManifestObjectKey, loadStoredAccessManifestCheckpoint, loadStoredPrincipalPolicyCheckpoint, principalPolicyKey, upsertAccessManifestCheckpointInTransaction, upsertPrincipalPolicyCheckpointInTransaction, } from "./keyingCheckpointPersistence.js";
8
9
  import { validatePrincipalAuthorizationCheckpoints } from "./principalAuthorizationCheckpoints.js";
9
10
  import { assertContainerNotRetired } from "./principalGrantRetirementPersistence.js";
10
11
  import { assertPrincipalPolicyBundleStoredInTransaction, writePrincipalPolicyBundleInTransaction, } from "./principalPolicyPersistence.js";
12
+ import { verifiedManifestBundleRows, writeVerifiedManifestBundlesInTransaction, } from "./verifiedManifestBundlePersistence.js";
11
13
  import { assertBundleMatchesVerifiedPolicy } from "./verifiedPrincipalPolicyBundle.js";
12
14
  function validateAccessAdvance(advance, localCheckpoint) {
13
15
  const current = {
@@ -106,18 +108,34 @@ async function writePolicyCheckpoints(tx, pending, updatedAt, organizationId) {
106
108
  await upsertPrincipalPolicyCheckpointInTransaction(tx, policy.checkpoint, updatedAt, organizationId);
107
109
  }
108
110
  }
109
- async function ensureKeyingCheckpointValidationTables(input) {
110
- await ensureSqlTables(input.execSql, input.policies.length > 0 || (input.authorizationPolicies?.length ?? 0) > 0
111
- ? [...principalPolicyTables, ...keyingCheckpointTables]
112
- : keyingCheckpointTables);
111
+ /**
112
+ * Digests the verified bundles and ensures every table the batch touches,
113
+ * all before its transaction begins.
114
+ */
115
+ async function prepareKeyingCheckpointBatch(input) {
116
+ const bundleRows = await verifiedManifestBundleRows(input.verifiedBundles ?? []);
117
+ await ensureSqlTables(input.execSql, [
118
+ ...(input.policies.length > 0 ||
119
+ (input.authorizationPolicies?.length ?? 0) > 0
120
+ ? principalPolicyTables
121
+ : []),
122
+ ...keyingCheckpointTables,
123
+ ...(bundleRows.length > 0 ? verifiedManifestBundleTables : []),
124
+ ]);
125
+ return bundleRows;
113
126
  }
114
- /** Re-checks verified candidates against durable pins without advancing them. */
127
+ /**
128
+ * Re-checks verified candidates against durable pins without advancing them.
129
+ * Only the verified bundles' citation rows are written.
130
+ */
115
131
  export async function validateKeyingCheckpointsAtomically(input) {
116
- await ensureKeyingCheckpointValidationTables(input);
132
+ const bundleRows = await prepareKeyingCheckpointBatch(input);
133
+ const verifiedAt = new Date().toISOString();
117
134
  const validate = async (tx) => {
118
135
  await validateAccessAdvances(tx, input.access);
119
136
  await validatePolicyAdvances(tx, input.policies);
120
137
  await validatePrincipalAuthorizationCheckpoints(tx, input.authorizationPolicies ?? []);
138
+ await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, verifiedAt);
121
139
  };
122
140
  const runtime = getClientSQLitePersistenceRuntime(input.execSql);
123
141
  if (input.stillCurrent) {
@@ -132,10 +150,10 @@ export async function validateKeyingCheckpointsAtomically(input) {
132
150
  * Re-check every verified projection candidate against the latest durable pins
133
151
  * and advance the complete batch atomically. Signature verification and remote
134
152
  * fetching happen before this short transaction; only checkpoint comparison
135
- * and persistence are serialized here.
153
+ * and persistence, with the batch's verified bundles, are serialized here.
136
154
  */
137
155
  export async function advanceKeyingCheckpointsAtomically(input) {
138
- await ensureKeyingCheckpointValidationTables(input);
156
+ const bundleRows = await prepareKeyingCheckpointBatch(input);
139
157
  const updatedAt = new Date().toISOString();
140
158
  const runtime = getClientSQLitePersistenceRuntime(input.execSql);
141
159
  const advance = async (tx) => {
@@ -147,6 +165,7 @@ export async function advanceKeyingCheckpointsAtomically(input) {
147
165
  if (input.documentPurgeCheckpoint) {
148
166
  await storeDocumentPurgeCheckpointInTransaction(tx, input.documentPurgeCheckpoint, updatedAt);
149
167
  }
168
+ await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, updatedAt);
150
169
  };
151
170
  if (input.stillCurrent) {
152
171
  await runtime.guardedTransaction(advance, input.stillCurrent, {
@@ -1 +1 @@
1
- {"version":3,"file":"keyingCheckpointAdvancePersistence.js","sourceRoot":"","sources":["keyingCheckpointAdvancePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n type VerifiedAccessManifestCheckpointEvidence,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n type VerifiedPrincipalPolicySelection,\n verifyAccessManifestLocalCheckpoint,\n verifyPrincipalPolicyCheckpoint,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport {\n keyingCheckpointTables,\n principalPolicyTables,\n} from \"../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport {\n type DocumentPurgeCheckpoint,\n storeDocumentPurgeCheckpointInTransaction,\n} from \"./documentPurgeCheckpointPersistence\";\nimport { validateAccessManifestCheckpointEvidence } from \"./keyingCheckpointEvidence\";\nimport {\n accessManifestObjectKey,\n loadStoredAccessManifestCheckpoint,\n loadStoredPrincipalPolicyCheckpoint,\n principalPolicyKey,\n upsertAccessManifestCheckpointInTransaction,\n upsertPrincipalPolicyCheckpointInTransaction,\n} from \"./keyingCheckpointPersistence\";\nimport { validatePrincipalAuthorizationCheckpoints } from \"./principalAuthorizationCheckpoints\";\nimport { assertContainerNotRetired } from \"./principalGrantRetirementPersistence\";\nimport {\n assertPrincipalPolicyBundleStoredInTransaction,\n writePrincipalPolicyBundleInTransaction,\n} from \"./principalPolicyPersistence\";\nimport { assertBundleMatchesVerifiedPolicy } from \"./verifiedPrincipalPolicyBundle\";\n\nexport interface AccessManifestCheckpointAdvance {\n readonly head: VerifiedAccessManifestCheckpointEvidence;\n readonly predecessors: readonly VerifiedAccessManifestCheckpointEvidence[];\n}\n\ntype CheckpointPolicy =\n | AnyVerifiedPrincipalPolicy\n | VerifiedPrincipalPolicyCurrent;\n\ninterface KeyingCheckpointValidationInput {\n readonly access: readonly AccessManifestCheckpointAdvance[];\n readonly execSql: ExecSql;\n readonly policies: readonly CheckpointPolicy[];\n readonly authorizationPolicies?:\n | readonly VerifiedPrincipalPolicySelection[]\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\ninterface VerifiedPrincipalPolicyBundleEntry {\n readonly bundle: PrincipalPolicyBundleResponse;\n readonly policy: VerifiedPrincipalPolicy;\n}\n\ninterface PendingAccessCheckpoint {\n readonly checkpoint: AccessManifestCheckpoint;\n}\n\nfunction validateAccessAdvance(\n advance: AccessManifestCheckpointAdvance,\n localCheckpoint: AccessManifestCheckpoint | null,\n): PendingAccessCheckpoint {\n const current = {\n ...advance.head.checkpoint,\n previousManifestHash: advance.head.manifest.previousManifestHash,\n };\n const predecessors = [...advance.predecessors].sort(\n (left, right) => left.checkpoint.epoch - right.checkpoint.epoch,\n );\n\n if (localCheckpoint && current.epoch <= localCheckpoint.epoch) {\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: undefined,\n });\n }\n\n validateAccessManifestCheckpointEvidence({\n head: advance.head,\n predecessors,\n localCheckpoint,\n });\n\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: predecessors.filter(\n (manifest) =>\n localCheckpoint !== null &&\n manifest.checkpoint.epoch > localCheckpoint.epoch &&\n manifest.checkpoint.epoch < current.epoch,\n ),\n });\n\n return {\n checkpoint: advance.head.checkpoint,\n };\n}\n\nasync function validateAccessAdvances(\n tx: ClientSQLiteTransactionScope,\n advances: readonly AccessManifestCheckpointAdvance[],\n): Promise<Map<string, PendingAccessCheckpoint>> {\n const pending = new Map<string, PendingAccessCheckpoint>();\n\n for (const advance of advances) {\n await assertContainerNotRetired(tx, advance.head.checkpoint);\n const key = accessManifestObjectKey(advance.head.checkpoint);\n if (pending.has(key)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `projection declares multiple access checkpoint heads for ${key}`,\n );\n }\n const localCheckpoint = await loadStoredAccessManifestCheckpoint(\n tx,\n advance.head.checkpoint,\n );\n pending.set(key, validateAccessAdvance(advance, localCheckpoint));\n }\n\n return pending;\n}\n\nfunction extendsObservedPolicy(\n head: CheckpointPolicy,\n candidate: CheckpointPolicy,\n): boolean {\n const history =\n \"retainedHistory\" in head ? head.retainedHistory : head.history;\n return (\n history?.some(\n ({ state }) =>\n state.principalType === candidate.principalType &&\n state.principalId === candidate.principalId &&\n state.version === candidate.version &&\n state.stateHash === candidate.stateHash,\n ) ?? false\n );\n}\n\nasync function validatePolicyAdvances(\n tx: ClientSQLiteTransactionScope,\n policies: readonly CheckpointPolicy[],\n): Promise<Map<string, CheckpointPolicy>> {\n const policiesByPrincipal = new Map<string, CheckpointPolicy[]>();\n for (const policy of policies) {\n const key = principalPolicyKey(policy);\n const candidates = policiesByPrincipal.get(key) ?? [];\n candidates.push(policy);\n policiesByPrincipal.set(key, candidates);\n }\n\n const pending = new Map<string, CheckpointPolicy>();\n for (const key of [...policiesByPrincipal.keys()].sort()) {\n const candidates = policiesByPrincipal.get(key) ?? [];\n const maxVersion = Math.max(...candidates.map((policy) => policy.version));\n const heads = candidates.filter((policy) => policy.version === maxVersion);\n const head = heads[0];\n if (!head) {\n continue;\n }\n if (heads.some((candidate) => candidate.stateHash !== head.stateHash)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `principal policy declares conflicting heads for ${key}`,\n );\n }\n for (const candidate of candidates) {\n if (candidate.version === head.version) {\n continue;\n }\n if (!extendsObservedPolicy(head, candidate)) {\n throw new KeyingVerificationError(\n \"stale_predecessor\",\n `principal policy head does not extend observed state for ${key}`,\n );\n }\n }\n\n const localCheckpoint = await loadStoredPrincipalPolicyCheckpoint(tx, head);\n verifyPrincipalPolicyCheckpoint({\n chain:\n \"retainedHistory\" in head ? head.retainedHistory : (head.history ?? []),\n currentState: head.state,\n localCheckpoint,\n });\n pending.set(key, head);\n }\n\n return pending;\n}\n\nasync function writeAccessCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, PendingAccessCheckpoint>,\n updatedAt: string,\n): Promise<void> {\n for (const { checkpoint } of pending.values()) {\n await upsertAccessManifestCheckpointInTransaction(\n tx,\n checkpoint,\n updatedAt,\n );\n }\n}\n\nasync function writePolicyCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, CheckpointPolicy>,\n updatedAt: string,\n organizationId?: string | undefined,\n): Promise<void> {\n for (const policy of pending.values()) {\n await upsertPrincipalPolicyCheckpointInTransaction(\n tx,\n policy.checkpoint,\n updatedAt,\n organizationId,\n );\n }\n}\n\nasync function ensureKeyingCheckpointValidationTables(\n input: KeyingCheckpointValidationInput,\n): Promise<void> {\n await ensureSqlTables(\n input.execSql,\n input.policies.length > 0 || (input.authorizationPolicies?.length ?? 0) > 0\n ? [...principalPolicyTables, ...keyingCheckpointTables]\n : keyingCheckpointTables,\n );\n}\n\n/** Re-checks verified candidates against durable pins without advancing them. */\nexport async function validateKeyingCheckpointsAtomically(\n input: KeyingCheckpointValidationInput,\n): Promise<void> {\n await ensureKeyingCheckpointValidationTables(input);\n const validate = async (tx: ClientSQLiteTransactionScope) => {\n await validateAccessAdvances(tx, input.access);\n await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n if (input.stillCurrent) {\n await runtime.guardedTransaction(validate, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(validate, { behavior: \"immediate\" });\n}\n\n/**\n * Re-check every verified projection candidate against the latest durable pins\n * and advance the complete batch atomically. Signature verification and remote\n * fetching happen before this short transaction; only checkpoint comparison\n * and persistence are serialized here.\n */\nexport async function advanceKeyingCheckpointsAtomically(input: {\n readonly access: readonly AccessManifestCheckpointAdvance[];\n readonly documentPurgeCheckpoint?: DocumentPurgeCheckpoint | undefined;\n readonly execSql: ExecSql;\n readonly organizationId?: string | undefined;\n readonly policies: readonly CheckpointPolicy[];\n readonly authorizationPolicies?:\n | readonly VerifiedPrincipalPolicySelection[]\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<void> {\n await ensureKeyingCheckpointValidationTables(input);\n const updatedAt = new Date().toISOString();\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const advance = async (tx: ClientSQLiteTransactionScope) => {\n const access = await validateAccessAdvances(tx, input.access);\n const policies = await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n\n await writeAccessCheckpoints(tx, access, updatedAt);\n await writePolicyCheckpoints(tx, policies, updatedAt, input.organizationId);\n if (input.documentPurgeCheckpoint) {\n await storeDocumentPurgeCheckpointInTransaction(\n tx,\n input.documentPurgeCheckpoint,\n updatedAt,\n );\n }\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(advance, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(advance, { behavior: \"immediate\" });\n}\n\n/**\n * Persists each verified full policy bundle together with its durable head.\n * This prevents a crash or bundle-write failure from leaving a checkpoint\n * without the exact same-head payload and member-envelope evidence.\n */\nexport async function persistVerifiedPrincipalPolicyBundlesAtomically(input: {\n readonly entries: readonly VerifiedPrincipalPolicyBundleEntry[];\n readonly execSql: ExecSql;\n readonly organizationId?: string | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly updatedAt: string;\n}): Promise<void> {\n const seen = new Set<string>();\n for (const entry of input.entries) {\n const key = principalPolicyKey(entry.policy);\n if (seen.has(key)) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `verified policy bundle batch repeats ${key}`,\n );\n }\n seen.add(key);\n }\n await Promise.all(\n input.entries.map((entry) => assertBundleMatchesVerifiedPolicy(entry)),\n );\n await ensureSqlTables(input.execSql, [\n ...principalPolicyTables,\n ...keyingCheckpointTables,\n ]);\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const persist = async (tx: ClientSQLiteTransactionScope) => {\n const policies = await validatePolicyAdvances(\n tx,\n input.entries.map((entry) => entry.policy),\n );\n for (const entry of input.entries) {\n await writePrincipalPolicyBundleInTransaction(\n tx,\n entry.bundle,\n input.updatedAt,\n input.organizationId,\n );\n await assertPrincipalPolicyBundleStoredInTransaction(tx, entry.bundle);\n }\n await writePolicyCheckpoints(\n tx,\n policies,\n input.updatedAt,\n input.organizationId,\n );\n for (const policy of policies.values()) {\n const checkpoint = await loadStoredPrincipalPolicyCheckpoint(tx, policy);\n if (\n !checkpoint ||\n checkpoint.version !== policy.version ||\n checkpoint.stateHash !== policy.stateHash\n ) {\n throw new Error(\n \"Verified principal policy checkpoint was not persisted\",\n );\n }\n }\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(persist, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(persist, { behavior: \"immediate\" });\n}\n"]}
1
+ {"version":3,"file":"keyingCheckpointAdvancePersistence.js","sourceRoot":"","sources":["keyingCheckpointAdvancePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AccessManifestCheckpoint,\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n type VerifiedAccessManifestCheckpointEvidence,\n type VerifiedPrincipalPolicy,\n type VerifiedPrincipalPolicyCurrent,\n type VerifiedPrincipalPolicySelection,\n verifyAccessManifestLocalCheckpoint,\n verifyPrincipalPolicyCheckpoint,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport {\n keyingCheckpointTables,\n principalPolicyTables,\n} from \"../sqlite/schema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\nimport { verifiedManifestBundleTables } from \"../sqlite/verifiedManifestBundleSchema\";\nimport {\n type DocumentPurgeCheckpoint,\n storeDocumentPurgeCheckpointInTransaction,\n} from \"./documentPurgeCheckpointPersistence\";\nimport { validateAccessManifestCheckpointEvidence } from \"./keyingCheckpointEvidence\";\nimport {\n accessManifestObjectKey,\n loadStoredAccessManifestCheckpoint,\n loadStoredPrincipalPolicyCheckpoint,\n principalPolicyKey,\n upsertAccessManifestCheckpointInTransaction,\n upsertPrincipalPolicyCheckpointInTransaction,\n} from \"./keyingCheckpointPersistence\";\nimport { validatePrincipalAuthorizationCheckpoints } from \"./principalAuthorizationCheckpoints\";\nimport { assertContainerNotRetired } from \"./principalGrantRetirementPersistence\";\nimport {\n assertPrincipalPolicyBundleStoredInTransaction,\n writePrincipalPolicyBundleInTransaction,\n} from \"./principalPolicyPersistence\";\nimport {\n type VerifiedManifestBundle,\n type VerifiedManifestBundleRow,\n verifiedManifestBundleRows,\n writeVerifiedManifestBundlesInTransaction,\n} from \"./verifiedManifestBundlePersistence\";\nimport { assertBundleMatchesVerifiedPolicy } from \"./verifiedPrincipalPolicyBundle\";\n\nexport interface AccessManifestCheckpointAdvance {\n readonly head: VerifiedAccessManifestCheckpointEvidence;\n readonly predecessors: readonly VerifiedAccessManifestCheckpointEvidence[];\n}\n\ntype CheckpointPolicy =\n | AnyVerifiedPrincipalPolicy\n | VerifiedPrincipalPolicyCurrent;\n\ninterface KeyingCheckpointValidationInput {\n readonly access: readonly AccessManifestCheckpointAdvance[];\n readonly execSql: ExecSql;\n readonly policies: readonly CheckpointPolicy[];\n readonly authorizationPolicies?:\n | readonly VerifiedPrincipalPolicySelection[]\n | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n /**\n * Bundles this projection verified. They are stored for later citation in\n * the same transaction, so they commit only with the batch they verified.\n */\n readonly verifiedBundles?: readonly VerifiedManifestBundle[] | undefined;\n}\n\ninterface VerifiedPrincipalPolicyBundleEntry {\n readonly bundle: PrincipalPolicyBundleResponse;\n readonly policy: VerifiedPrincipalPolicy;\n}\n\ninterface PendingAccessCheckpoint {\n readonly checkpoint: AccessManifestCheckpoint;\n}\n\nfunction validateAccessAdvance(\n advance: AccessManifestCheckpointAdvance,\n localCheckpoint: AccessManifestCheckpoint | null,\n): PendingAccessCheckpoint {\n const current = {\n ...advance.head.checkpoint,\n previousManifestHash: advance.head.manifest.previousManifestHash,\n };\n const predecessors = [...advance.predecessors].sort(\n (left, right) => left.checkpoint.epoch - right.checkpoint.epoch,\n );\n\n if (localCheckpoint && current.epoch <= localCheckpoint.epoch) {\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: undefined,\n });\n }\n\n validateAccessManifestCheckpointEvidence({\n head: advance.head,\n predecessors,\n localCheckpoint,\n });\n\n verifyAccessManifestLocalCheckpoint({\n current,\n localCheckpoint,\n checkpointPredecessors: predecessors.filter(\n (manifest) =>\n localCheckpoint !== null &&\n manifest.checkpoint.epoch > localCheckpoint.epoch &&\n manifest.checkpoint.epoch < current.epoch,\n ),\n });\n\n return {\n checkpoint: advance.head.checkpoint,\n };\n}\n\nasync function validateAccessAdvances(\n tx: ClientSQLiteTransactionScope,\n advances: readonly AccessManifestCheckpointAdvance[],\n): Promise<Map<string, PendingAccessCheckpoint>> {\n const pending = new Map<string, PendingAccessCheckpoint>();\n\n for (const advance of advances) {\n await assertContainerNotRetired(tx, advance.head.checkpoint);\n const key = accessManifestObjectKey(advance.head.checkpoint);\n if (pending.has(key)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `projection declares multiple access checkpoint heads for ${key}`,\n );\n }\n const localCheckpoint = await loadStoredAccessManifestCheckpoint(\n tx,\n advance.head.checkpoint,\n );\n pending.set(key, validateAccessAdvance(advance, localCheckpoint));\n }\n\n return pending;\n}\n\nfunction extendsObservedPolicy(\n head: CheckpointPolicy,\n candidate: CheckpointPolicy,\n): boolean {\n const history =\n \"retainedHistory\" in head ? head.retainedHistory : head.history;\n return (\n history?.some(\n ({ state }) =>\n state.principalType === candidate.principalType &&\n state.principalId === candidate.principalId &&\n state.version === candidate.version &&\n state.stateHash === candidate.stateHash,\n ) ?? false\n );\n}\n\nasync function validatePolicyAdvances(\n tx: ClientSQLiteTransactionScope,\n policies: readonly CheckpointPolicy[],\n): Promise<Map<string, CheckpointPolicy>> {\n const policiesByPrincipal = new Map<string, CheckpointPolicy[]>();\n for (const policy of policies) {\n const key = principalPolicyKey(policy);\n const candidates = policiesByPrincipal.get(key) ?? [];\n candidates.push(policy);\n policiesByPrincipal.set(key, candidates);\n }\n\n const pending = new Map<string, CheckpointPolicy>();\n for (const key of [...policiesByPrincipal.keys()].sort()) {\n const candidates = policiesByPrincipal.get(key) ?? [];\n const maxVersion = Math.max(...candidates.map((policy) => policy.version));\n const heads = candidates.filter((policy) => policy.version === maxVersion);\n const head = heads[0];\n if (!head) {\n continue;\n }\n if (heads.some((candidate) => candidate.stateHash !== head.stateHash)) {\n throw new KeyingVerificationError(\n \"equivocation\",\n `principal policy declares conflicting heads for ${key}`,\n );\n }\n for (const candidate of candidates) {\n if (candidate.version === head.version) {\n continue;\n }\n if (!extendsObservedPolicy(head, candidate)) {\n throw new KeyingVerificationError(\n \"stale_predecessor\",\n `principal policy head does not extend observed state for ${key}`,\n );\n }\n }\n\n const localCheckpoint = await loadStoredPrincipalPolicyCheckpoint(tx, head);\n verifyPrincipalPolicyCheckpoint({\n chain:\n \"retainedHistory\" in head ? head.retainedHistory : (head.history ?? []),\n currentState: head.state,\n localCheckpoint,\n });\n pending.set(key, head);\n }\n\n return pending;\n}\n\nasync function writeAccessCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, PendingAccessCheckpoint>,\n updatedAt: string,\n): Promise<void> {\n for (const { checkpoint } of pending.values()) {\n await upsertAccessManifestCheckpointInTransaction(\n tx,\n checkpoint,\n updatedAt,\n );\n }\n}\n\nasync function writePolicyCheckpoints(\n tx: ClientSQLiteTransactionScope,\n pending: ReadonlyMap<string, CheckpointPolicy>,\n updatedAt: string,\n organizationId?: string | undefined,\n): Promise<void> {\n for (const policy of pending.values()) {\n await upsertPrincipalPolicyCheckpointInTransaction(\n tx,\n policy.checkpoint,\n updatedAt,\n organizationId,\n );\n }\n}\n\n/**\n * Digests the verified bundles and ensures every table the batch touches,\n * all before its transaction begins.\n */\nasync function prepareKeyingCheckpointBatch(\n input: KeyingCheckpointValidationInput,\n): Promise<VerifiedManifestBundleRow[]> {\n const bundleRows = await verifiedManifestBundleRows(\n input.verifiedBundles ?? [],\n );\n await ensureSqlTables(input.execSql, [\n ...(input.policies.length > 0 ||\n (input.authorizationPolicies?.length ?? 0) > 0\n ? principalPolicyTables\n : []),\n ...keyingCheckpointTables,\n ...(bundleRows.length > 0 ? verifiedManifestBundleTables : []),\n ]);\n return bundleRows;\n}\n\n/**\n * Re-checks verified candidates against durable pins without advancing them.\n * Only the verified bundles' citation rows are written.\n */\nexport async function validateKeyingCheckpointsAtomically(\n input: KeyingCheckpointValidationInput,\n): Promise<void> {\n const bundleRows = await prepareKeyingCheckpointBatch(input);\n const verifiedAt = new Date().toISOString();\n const validate = async (tx: ClientSQLiteTransactionScope) => {\n await validateAccessAdvances(tx, input.access);\n await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, verifiedAt);\n };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n if (input.stillCurrent) {\n await runtime.guardedTransaction(validate, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(validate, { behavior: \"immediate\" });\n}\n\n/**\n * Re-check every verified projection candidate against the latest durable pins\n * and advance the complete batch atomically. Signature verification and remote\n * fetching happen before this short transaction; only checkpoint comparison\n * and persistence, with the batch's verified bundles, are serialized here.\n */\nexport async function advanceKeyingCheckpointsAtomically(\n input: KeyingCheckpointValidationInput & {\n readonly documentPurgeCheckpoint?: DocumentPurgeCheckpoint | undefined;\n readonly organizationId?: string | undefined;\n },\n): Promise<void> {\n const bundleRows = await prepareKeyingCheckpointBatch(input);\n const updatedAt = new Date().toISOString();\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const advance = async (tx: ClientSQLiteTransactionScope) => {\n const access = await validateAccessAdvances(tx, input.access);\n const policies = await validatePolicyAdvances(tx, input.policies);\n await validatePrincipalAuthorizationCheckpoints(\n tx,\n input.authorizationPolicies ?? [],\n );\n\n await writeAccessCheckpoints(tx, access, updatedAt);\n await writePolicyCheckpoints(tx, policies, updatedAt, input.organizationId);\n if (input.documentPurgeCheckpoint) {\n await storeDocumentPurgeCheckpointInTransaction(\n tx,\n input.documentPurgeCheckpoint,\n updatedAt,\n );\n }\n await writeVerifiedManifestBundlesInTransaction(tx, bundleRows, updatedAt);\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(advance, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(advance, { behavior: \"immediate\" });\n}\n\n/**\n * Persists each verified full policy bundle together with its durable head.\n * This prevents a crash or bundle-write failure from leaving a checkpoint\n * without the exact same-head payload and member-envelope evidence.\n */\nexport async function persistVerifiedPrincipalPolicyBundlesAtomically(input: {\n readonly entries: readonly VerifiedPrincipalPolicyBundleEntry[];\n readonly execSql: ExecSql;\n readonly organizationId?: string | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly updatedAt: string;\n}): Promise<void> {\n const seen = new Set<string>();\n for (const entry of input.entries) {\n const key = principalPolicyKey(entry.policy);\n if (seen.has(key)) {\n throw new KeyingVerificationError(\n \"duplicate_entry\",\n `verified policy bundle batch repeats ${key}`,\n );\n }\n seen.add(key);\n }\n await Promise.all(\n input.entries.map((entry) => assertBundleMatchesVerifiedPolicy(entry)),\n );\n await ensureSqlTables(input.execSql, [\n ...principalPolicyTables,\n ...keyingCheckpointTables,\n ]);\n\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const persist = async (tx: ClientSQLiteTransactionScope) => {\n const policies = await validatePolicyAdvances(\n tx,\n input.entries.map((entry) => entry.policy),\n );\n for (const entry of input.entries) {\n await writePrincipalPolicyBundleInTransaction(\n tx,\n entry.bundle,\n input.updatedAt,\n input.organizationId,\n );\n await assertPrincipalPolicyBundleStoredInTransaction(tx, entry.bundle);\n }\n await writePolicyCheckpoints(\n tx,\n policies,\n input.updatedAt,\n input.organizationId,\n );\n for (const policy of policies.values()) {\n const checkpoint = await loadStoredPrincipalPolicyCheckpoint(tx, policy);\n if (\n !checkpoint ||\n checkpoint.version !== policy.version ||\n checkpoint.stateHash !== policy.stateHash\n ) {\n throw new Error(\n \"Verified principal policy checkpoint was not persisted\",\n );\n }\n }\n };\n if (input.stillCurrent) {\n await runtime.guardedTransaction(persist, input.stillCurrent, {\n behavior: \"immediate\",\n });\n return;\n }\n await runtime.transaction(persist, { behavior: \"immediate\" });\n}\n"]}
@@ -0,0 +1,45 @@
1
+ import type { VerifiedManifestCitations, WriterProjectionTarget } from "../../internal/api-client/index.js";
2
+ import { type AccessManifestBundleWireResponse } from "../../internal/validators/response/index.js";
3
+ import { type ClientSQLiteTransactionScope } from "../sqlite/sqlitePersistenceRuntime.js";
4
+ import { type ExecSql } from "../sqlite/sqlSchema.js";
5
+ import { verifiedAccessManifestBundles as bundles } from "../sqlite/verifiedManifestBundleSchema.js";
6
+ /**
7
+ * Bounds local bytes (a bundle is ~10–20 KB). Evicting the least recently
8
+ * verified rows only makes a later read carry those bundles again.
9
+ */
10
+ export declare const MAX_VERIFIED_MANIFEST_BUNDLES = 1024;
11
+ export interface VerifiedManifestBundle {
12
+ readonly bundle: AccessManifestBundleWireResponse;
13
+ readonly checkpoint: {
14
+ readonly objectKind: string;
15
+ readonly organizationId: string;
16
+ readonly objectId: string;
17
+ readonly epoch: number;
18
+ };
19
+ }
20
+ /** A verified bundle's exact JSON and that JSON's digest. */
21
+ export type VerifiedManifestBundleRow = Omit<typeof bundles.$inferInsert, "verifiedAt">;
22
+ /**
23
+ * Prepares rows for bundles that just passed projection verification. The
24
+ * digests are computed here, before the checkpoint transaction that writes
25
+ * them begins.
26
+ */
27
+ export declare function verifiedManifestBundleRows(entries: readonly VerifiedManifestBundle[]): Promise<VerifiedManifestBundleRow[]>;
28
+ /**
29
+ * Records verified bundles inside the transaction that finalizes their
30
+ * projection's checkpoints, so they commit or roll back with it and no cache
31
+ * work outlives the verification. Freshly verified bytes replace any stored
32
+ * copy.
33
+ */
34
+ export declare function writeVerifiedManifestBundlesInTransaction(tx: ClientSQLiteTransactionScope, rows: readonly VerifiedManifestBundleRow[], verifiedAt: string): Promise<void>;
35
+ /**
36
+ * Verified bundles of the target's object and of the containers its
37
+ * projection walks, newest epochs first; then the most recently verified rows
38
+ * of its organization, since a just-verified parent is the likeliest part of
39
+ * a new child's projection. Citations never leave the target's organization:
40
+ * an object whose organization the device cannot place cites nothing.
41
+ * Damaged rows are dropped.
42
+ */
43
+ export declare function loadVerifiedManifestCitations(execSql: ExecSql, target: WriterProjectionTarget, limit?: number): Promise<AccessManifestBundleWireResponse[]>;
44
+ /** Cites from whichever database the signed-in identity currently uses. */
45
+ export declare function createVerifiedManifestCitations(resolveExecSql: () => ExecSql | null): VerifiedManifestCitations;
@@ -0,0 +1,282 @@
1
+ import { toFingerprint } from "../../internal/crypto/index.js";
2
+ import { isAccessManifestBundleWireResponse, } from "../../internal/validators/response/index.js";
3
+ import { KNOWN_MANIFEST_HINT_LIMIT, MAX_CONTAINER_PATH_LENGTH, } from "../../internal/validators/util/index.js";
4
+ import { and, asc, desc, eq, inArray, sql } from "drizzle-orm";
5
+ import { containers } from "../sqlite/containerSchema.js";
6
+ import { documentDiscoveryHeads, pendingDocumentDiscoveries, } from "../sqlite/documentDiscoveryEvidenceSchema.js";
7
+ import { containerTables, documentContainerProjection, documentContainerProjectionTables, } from "../sqlite/schema.js";
8
+ import { getClientSQLitePersistenceRuntime, } from "../sqlite/sqlitePersistenceRuntime.js";
9
+ import { ensureSqlTables } from "../sqlite/sqlSchema.js";
10
+ import { verifiedAccessManifestBundles as bundles, verifiedManifestBundleTables, } from "../sqlite/verifiedManifestBundleSchema.js";
11
+ /**
12
+ * Bounds local bytes (a bundle is ~10–20 KB). Evicting the least recently
13
+ * verified rows only makes a later read carry those bundles again.
14
+ */
15
+ export const MAX_VERIFIED_MANIFEST_BUNDLES = 1024;
16
+ const STATEMENT_BATCH = 200;
17
+ function sha256Hex(text) {
18
+ return toFingerprint(new TextEncoder().encode(text));
19
+ }
20
+ function batches(values) {
21
+ const result = [];
22
+ for (let index = 0; index < values.length; index += STATEMENT_BATCH)
23
+ result.push(values.slice(index, index + STATEMENT_BATCH));
24
+ return result;
25
+ }
26
+ async function pruneInTransaction(tx) {
27
+ const [row] = await tx.select({ count: sql `count(*)` }).from(bundles);
28
+ const excess = (row?.count ?? 0) - MAX_VERIFIED_MANIFEST_BUNDLES;
29
+ if (excess <= 0)
30
+ return;
31
+ const evicted = await tx
32
+ .select({ manifestHash: bundles.manifestHash })
33
+ .from(bundles)
34
+ .orderBy(asc(bundles.verifiedAt), asc(bundles.manifestHash))
35
+ .limit(excess);
36
+ for (const batch of batches(evicted.map((entry) => entry.manifestHash)))
37
+ await tx.delete(bundles).where(inArray(bundles.manifestHash, batch)).run();
38
+ }
39
+ /**
40
+ * Prepares rows for bundles that just passed projection verification. The
41
+ * digests are computed here, before the checkpoint transaction that writes
42
+ * them begins.
43
+ */
44
+ export function verifiedManifestBundleRows(entries) {
45
+ const unique = new Map(entries.map((entry) => [entry.bundle.manifestHash, entry]));
46
+ return Promise.all([...unique.values()].map(async ({ bundle, checkpoint }) => {
47
+ const bundleJson = JSON.stringify(bundle);
48
+ return {
49
+ manifestHash: bundle.manifestHash,
50
+ organizationId: checkpoint.organizationId,
51
+ objectKind: checkpoint.objectKind,
52
+ objectId: checkpoint.objectId,
53
+ epoch: checkpoint.epoch,
54
+ bundleJson,
55
+ bundleDigest: await sha256Hex(bundleJson),
56
+ };
57
+ }));
58
+ }
59
+ /**
60
+ * Records verified bundles inside the transaction that finalizes their
61
+ * projection's checkpoints, so they commit or roll back with it and no cache
62
+ * work outlives the verification. Freshly verified bytes replace any stored
63
+ * copy.
64
+ */
65
+ export async function writeVerifiedManifestBundlesInTransaction(tx, rows, verifiedAt) {
66
+ if (rows.length === 0)
67
+ return;
68
+ const stored = await storedDigests(tx, rows.map((row) => row.manifestHash));
69
+ // An identical stored row only needs its recency refreshed.
70
+ const unchanged = rows.filter((row) => stored.get(row.manifestHash) === row.bundleDigest);
71
+ for (const batch of batches(unchanged.map((row) => row.manifestHash)))
72
+ await tx
73
+ .update(bundles)
74
+ .set({ verifiedAt })
75
+ .where(inArray(bundles.manifestHash, batch))
76
+ .run();
77
+ for (const row of rows) {
78
+ if (stored.get(row.manifestHash) === row.bundleDigest)
79
+ continue;
80
+ const verified = { ...row, verifiedAt };
81
+ await tx
82
+ .insert(bundles)
83
+ .values(verified)
84
+ .onConflictDoUpdate({ target: bundles.manifestHash, set: verified })
85
+ .run();
86
+ }
87
+ await pruneInTransaction(tx);
88
+ }
89
+ async function storedDigests(tx, manifestHashes) {
90
+ const digests = new Map();
91
+ for (const batch of batches(manifestHashes)) {
92
+ const rows = await tx
93
+ .select({
94
+ bundleDigest: bundles.bundleDigest,
95
+ manifestHash: bundles.manifestHash,
96
+ })
97
+ .from(bundles)
98
+ .where(inArray(bundles.manifestHash, batch));
99
+ for (const row of rows)
100
+ digests.set(row.manifestHash, row.bundleDigest);
101
+ }
102
+ return digests;
103
+ }
104
+ /** The requested object first, then each container whose lineage it cites. */
105
+ async function containerLineage(db, containerId) {
106
+ const lineage = [containerId];
107
+ while (lineage.length < MAX_CONTAINER_PATH_LENGTH) {
108
+ const [row] = await db
109
+ .select({ parentId: containers.parentId })
110
+ .from(containers)
111
+ .where(eq(containers.id, lineage.at(-1) ?? ""))
112
+ .limit(1);
113
+ const parentId = row?.parentId;
114
+ if (!parentId || lineage.includes(parentId))
115
+ break;
116
+ lineage.push(parentId);
117
+ }
118
+ return lineage;
119
+ }
120
+ async function citedObjects(db, target) {
121
+ if (target.kind === "container")
122
+ return (await containerLineage(db, target.id)).map((id) => ({
123
+ kind: "container",
124
+ id,
125
+ }));
126
+ // Linked containers, containers listing the document before its signed
127
+ // placement is checked, and a container whose metadata document it is.
128
+ const placements = [
129
+ ...(await db
130
+ .select({ containerId: documentContainerProjection.containerId })
131
+ .from(documentContainerProjection)
132
+ .where(eq(documentContainerProjection.documentId, target.id))),
133
+ ...(await db
134
+ .select({ containerId: pendingDocumentDiscoveries.containerId })
135
+ .from(pendingDocumentDiscoveries)
136
+ .where(eq(pendingDocumentDiscoveries.documentId, target.id))),
137
+ ...(await db
138
+ .select({ containerId: containers.id })
139
+ .from(containers)
140
+ .where(eq(containers.metadataDocumentId, target.id))),
141
+ ];
142
+ const containerIds = new Set();
143
+ for (const { containerId } of placements)
144
+ if (containerId)
145
+ for (const id of await containerLineage(db, containerId))
146
+ containerIds.add(id);
147
+ return [
148
+ { kind: "document", id: target.id },
149
+ ...[...containerIds].map((id) => ({ kind: "container", id })),
150
+ ];
151
+ }
152
+ /**
153
+ * The one organization every local source places the read in. Verified
154
+ * ownership (stored verified bundles of the target and of the containers on
155
+ * its walk, and a document's verified discovery head) and local placement
156
+ * (listed container rows reached through links, pending listings, metadata,
157
+ * or parents) must all agree: any disagreement, or no source at all, yields
158
+ * null, so the read is sent with no hints rather than another
159
+ * organization's.
160
+ */
161
+ async function targetOrganization(db, target, objects) {
162
+ const containerIds = objects
163
+ .filter((object) => object.kind === "container")
164
+ .map((object) => object.id);
165
+ const listed = containerIds.length === 0
166
+ ? []
167
+ : await db
168
+ .select({ organizationId: containers.organizationId })
169
+ .from(containers)
170
+ .where(inArray(containers.id, containerIds));
171
+ const verifiedContainers = containerIds.length === 0
172
+ ? []
173
+ : await db
174
+ .select({ organizationId: bundles.organizationId })
175
+ .from(bundles)
176
+ .where(and(eq(bundles.objectKind, "container"), inArray(bundles.objectId, containerIds)));
177
+ const verifiedTarget = await db
178
+ .select({ organizationId: bundles.organizationId })
179
+ .from(bundles)
180
+ .where(and(eq(bundles.objectKind, target.kind), eq(bundles.objectId, target.id)));
181
+ const discovered = target.kind === "document"
182
+ ? await db
183
+ .select({ organizationId: documentDiscoveryHeads.organizationId })
184
+ .from(documentDiscoveryHeads)
185
+ .where(eq(documentDiscoveryHeads.documentId, target.id))
186
+ : [];
187
+ const sources = [listed, verifiedContainers, verifiedTarget, discovered];
188
+ const organizations = new Set(sources.flat().map((row) => row.organizationId));
189
+ const [organizationId] = organizations;
190
+ return organizations.size === 1 && organizationId ? organizationId : null;
191
+ }
192
+ const storedColumns = {
193
+ bundleDigest: bundles.bundleDigest,
194
+ bundleJson: bundles.bundleJson,
195
+ manifestHash: bundles.manifestHash,
196
+ };
197
+ async function readStoredBundle(row) {
198
+ if ((await sha256Hex(row.bundleJson)) !== row.bundleDigest)
199
+ return null;
200
+ try {
201
+ const bundle = JSON.parse(row.bundleJson);
202
+ return isAccessManifestBundleWireResponse(bundle) &&
203
+ bundle.manifestHash === row.manifestHash
204
+ ? bundle
205
+ : null;
206
+ }
207
+ catch {
208
+ return null;
209
+ }
210
+ }
211
+ function objectRows(db, organizationId, object, limit) {
212
+ return db
213
+ .select(storedColumns)
214
+ .from(bundles)
215
+ .where(and(eq(bundles.organizationId, organizationId), eq(bundles.objectKind, object.kind), eq(bundles.objectId, object.id)))
216
+ .orderBy(desc(bundles.epoch))
217
+ .limit(limit);
218
+ }
219
+ function recentRows(db, organizationId, limit) {
220
+ return db
221
+ .select(storedColumns)
222
+ .from(bundles)
223
+ .where(eq(bundles.organizationId, organizationId))
224
+ .orderBy(desc(bundles.verifiedAt), asc(bundles.manifestHash))
225
+ .limit(limit);
226
+ }
227
+ /**
228
+ * Verified bundles of the target's object and of the containers its
229
+ * projection walks, newest epochs first; then the most recently verified rows
230
+ * of its organization, since a just-verified parent is the likeliest part of
231
+ * a new child's projection. Citations never leave the target's organization:
232
+ * an object whose organization the device cannot place cites nothing.
233
+ * Damaged rows are dropped.
234
+ */
235
+ export async function loadVerifiedManifestCitations(execSql, target, limit = KNOWN_MANIFEST_HINT_LIMIT) {
236
+ await ensureSqlTables(execSql, [
237
+ ...verifiedManifestBundleTables,
238
+ ...containerTables,
239
+ ...documentContainerProjectionTables,
240
+ ]);
241
+ const { db } = getClientSQLitePersistenceRuntime(execSql);
242
+ const cited = new Map();
243
+ const damaged = [];
244
+ const collect = async (rows) => {
245
+ for (const row of rows) {
246
+ if (cited.size >= limit || cited.has(row.manifestHash))
247
+ continue;
248
+ const bundle = await readStoredBundle(row);
249
+ if (bundle)
250
+ cited.set(row.manifestHash, bundle);
251
+ else
252
+ damaged.push(row.manifestHash);
253
+ }
254
+ };
255
+ const objects = await citedObjects(db, target);
256
+ const organizationId = await targetOrganization(db, target, objects);
257
+ if (organizationId === null)
258
+ return [];
259
+ for (const object of objects)
260
+ if (cited.size < limit)
261
+ await collect(await objectRows(db, organizationId, object, limit - cited.size));
262
+ if (cited.size < limit)
263
+ await collect(await recentRows(db, organizationId, limit + cited.size));
264
+ if (damaged.length > 0)
265
+ await getClientSQLitePersistenceRuntime(execSql)
266
+ .runMutation((handle) => handle
267
+ .delete(bundles)
268
+ .where(inArray(bundles.manifestHash, damaged))
269
+ .run())
270
+ .catch(() => undefined);
271
+ return [...cited.values()];
272
+ }
273
+ /** Cites from whichever database the signed-in identity currently uses. */
274
+ export function createVerifiedManifestCitations(resolveExecSql) {
275
+ return {
276
+ cite: async (target) => {
277
+ const execSql = resolveExecSql();
278
+ return execSql ? loadVerifiedManifestCitations(execSql, target) : [];
279
+ },
280
+ };
281
+ }
282
+ //# sourceMappingURL=verifiedManifestBundlePersistence.js.map