@tearleads/client-sdk 0.1.11 → 0.1.14

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 (144) hide show
  1. package/README.md +50 -9
  2. package/client/Tearleads.d.ts +4 -0
  3. package/client/Tearleads.js +5 -0
  4. package/client/Tearleads.js.map +1 -1
  5. package/client/index.d.ts +1 -0
  6. package/client/index.js.map +1 -1
  7. package/client/principalHistoryProtection.d.ts +19 -0
  8. package/client/principalHistoryProtection.js +76 -0
  9. package/client/principalHistoryProtection.js.map +1 -0
  10. package/client/workflowRuntime.d.ts +5 -0
  11. package/client/workflowRuntime.js +34 -5
  12. package/client/workflowRuntime.js.map +1 -1
  13. package/data/containers/shared/authorAccess.d.ts +2 -2
  14. package/data/containers/shared/authorAccess.js.map +1 -1
  15. package/data/containers/shared/heldContainerHeads.js.map +1 -1
  16. package/data/containers/shared/principalPolicies.js.map +1 -1
  17. package/data/containers/shared/types.d.ts +3 -2
  18. package/data/containers/shared/types.js.map +1 -1
  19. package/data/keyingProjectionVerification/accessManifestCheckpointEnforcement.js.map +1 -1
  20. package/data/keyingProjectionVerification/checkpointContext.d.ts +4 -3
  21. package/data/keyingProjectionVerification/checkpointContext.js.map +1 -1
  22. package/data/keyingProjectionVerification/containerManifestVerification.js.map +1 -1
  23. package/data/keyingProjectionVerification/containerPathVerification.js.map +1 -1
  24. package/data/keyingProjectionVerification/containerProjectionVerification.d.ts +4 -3
  25. package/data/keyingProjectionVerification/containerProjectionVerification.js.map +1 -1
  26. package/data/keyingProjectionVerification/documentManifestPolicies.js.map +1 -1
  27. package/data/keyingProjectionVerification/documentManifestVerification.js.map +1 -1
  28. package/data/keyingProjectionVerification/documentProjectionVerification.d.ts +3 -2
  29. package/data/keyingProjectionVerification/documentProjectionVerification.js.map +1 -1
  30. package/data/keyingProjectionVerification/organizationFounderBinding.js +9 -4
  31. package/data/keyingProjectionVerification/organizationFounderBinding.js.map +1 -1
  32. package/data/keyingProjectionVerification/principalPolicyCache.js +3 -4
  33. package/data/keyingProjectionVerification/principalPolicyCache.js.map +1 -1
  34. package/data/keyingProjectionVerification/principalPolicyVerification.js +12 -2
  35. package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
  36. package/data/keyingProjectionVerification/projectionAuthorizationEvidence.js.map +1 -1
  37. package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js +70 -0
  38. package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js.map +1 -0
  39. package/data/keyingProjectionVerification/types.d.ts +17 -2
  40. package/data/keyingProjectionVerification/types.js +12 -0
  41. package/data/keyingProjectionVerification/types.js.map +1 -1
  42. package/data/persistence/organizationFounderPersistence.js +3 -2
  43. package/data/persistence/organizationFounderPersistence.js.map +1 -1
  44. package/data/persistence/principalHistoryEvidencePersistence.js +91 -0
  45. package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -0
  46. package/data/persistence/principalHistoryPrefixPersistence.js +52 -0
  47. package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -0
  48. package/data/persistence/principalHistoryStagePersistence.js +9 -2
  49. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  50. package/data/persistence/principalKeyEnvelopeCandidates.js +67 -0
  51. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -0
  52. package/data/principals/principalHistoryPrefixProtection.js +29 -0
  53. package/data/principals/principalHistoryPrefixProtection.js.map +1 -0
  54. package/data/principals/principalHistoryProtection.d.ts +10 -0
  55. package/data/principals/principalHistoryProtection.js +14 -0
  56. package/data/principals/principalHistoryProtection.js.map +1 -0
  57. package/data/principals/principalHistoryStageProtection.js.map +1 -1
  58. package/data/principals/principalPolicyCrypto.js +11 -21
  59. package/data/principals/principalPolicyCrypto.js.map +1 -1
  60. package/data/principals/principalPolicyEvidence.d.ts +4 -0
  61. package/data/principals/principalPolicyEvidence.js +12 -0
  62. package/data/principals/principalPolicyEvidence.js.map +1 -0
  63. package/data/sqlite/principalHistoryEvidenceSchema.js +46 -0
  64. package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -0
  65. package/data/sqlite/principalKeyFingerprintJson.js +9 -0
  66. package/data/sqlite/principalKeyFingerprintJson.js.map +1 -0
  67. package/data/sqlite/principalPolicySchema.js +4 -0
  68. package/data/sqlite/principalPolicySchema.js.map +1 -1
  69. package/data/sqlite/schema.d.ts +304 -0
  70. package/data/sqlite/schema.js +5 -0
  71. package/data/sqlite/schema.js.map +1 -1
  72. package/data/sqlite/sqlTableSchema.js +1 -1
  73. package/data/sqlite/sqlTableSchema.js.map +1 -1
  74. package/index.d.ts +3 -3
  75. package/index.js +1 -1
  76. package/index.js.map +1 -1
  77. package/internal/api-client/principalPolicyPages.d.ts +2 -0
  78. package/internal/api-client/principalPolicyPages.js +11 -2
  79. package/internal/api-client/principalPolicyPages.js.map +1 -1
  80. package/internal/crypto/index.d.ts +1 -1
  81. package/internal/crypto/index.js +1 -1
  82. package/internal/crypto/index.js.map +1 -1
  83. package/internal/crypto/keying/index.d.ts +1 -1
  84. package/internal/crypto/keying/index.js +1 -1
  85. package/internal/crypto/keying/index.js.map +1 -1
  86. package/internal/crypto/keying/principalPolicyHistoryIndex.d.ts +6 -2
  87. package/internal/crypto/keying/principalPolicyHistoryIndex.js +11 -5
  88. package/internal/crypto/keying/principalPolicyHistoryIndex.js.map +1 -1
  89. package/internal/crypto/keying/principalPolicyHistoryReferences.d.ts +2 -0
  90. package/internal/crypto/keying/principalPolicyHistoryReferences.js +19 -2
  91. package/internal/crypto/keying/principalPolicyHistoryReferences.js.map +1 -1
  92. package/package.json +4 -1
  93. package/sqlite/sqlite3-licenses.md +38 -0
  94. package/sqlite/sqlite3.wasm +0 -0
  95. package/sqlite/worker.js +4 -0
  96. package/workflows/containers/child/create.js.map +1 -1
  97. package/workflows/containers/child/move.js.map +1 -1
  98. package/workflows/containers/child/moveWraps.js.map +1 -1
  99. package/workflows/containers/child/mutationRequestCore.js.map +1 -1
  100. package/workflows/containers/child/recitePlan.js.map +1 -1
  101. package/workflows/containers/child/rekey.d.ts +3 -2
  102. package/workflows/containers/child/rekey.js.map +1 -1
  103. package/workflows/containers/child/revoke.d.ts +2 -2
  104. package/workflows/containers/child/revoke.js.map +1 -1
  105. package/workflows/containers/child/rotationPrincipalPolicies.js.map +1 -1
  106. package/workflows/containers/child/rotationWraps.js.map +1 -1
  107. package/workflows/containers/child/sharePlanCore.d.ts +11 -10
  108. package/workflows/containers/child/sharePlanCore.js.map +1 -1
  109. package/workflows/documents/linkSetAuthority.js.map +1 -1
  110. package/workflows/principals/index.d.ts +1 -0
  111. package/workflows/principals/index.js +1 -0
  112. package/workflows/principals/index.js.map +1 -1
  113. package/workflows/principals/principalHistoryRecoveryPrefix.js +65 -0
  114. package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -0
  115. package/workflows/principals/principalHistoryRecoveryReferences.js +60 -0
  116. package/workflows/principals/principalHistoryRecoveryReferences.js.map +1 -0
  117. package/workflows/principals/principalHistoryRecoveryStage.js +38 -2
  118. package/workflows/principals/principalHistoryRecoveryStage.js.map +1 -1
  119. package/workflows/principals/principalHistoryRecoveryTypes.d.ts +9 -1
  120. package/workflows/principals/principalHistoryRecoveryTypes.js +7 -0
  121. package/workflows/principals/principalHistoryRecoveryTypes.js.map +1 -1
  122. package/workflows/principals/principalHistoryRecoveryVerification.js +24 -0
  123. package/workflows/principals/principalHistoryRecoveryVerification.js.map +1 -0
  124. package/workflows/principals/principalRecoveryDirectory.d.ts +10 -0
  125. package/workflows/principals/principalRecoveryDirectory.js +107 -0
  126. package/workflows/principals/principalRecoveryDirectory.js.map +1 -0
  127. package/workflows/principals/principalRecoveryMemo.js +46 -0
  128. package/workflows/principals/principalRecoveryMemo.js.map +1 -0
  129. package/workflows/principals/principalRecoveryOutage.js +40 -0
  130. package/workflows/principals/principalRecoveryOutage.js.map +1 -0
  131. package/workflows/principals/principalRecoveryQueue.js +22 -0
  132. package/workflows/principals/principalRecoveryQueue.js.map +1 -0
  133. package/workflows/principals/recoverPrincipalPolicyHistory.d.ts +1 -0
  134. package/workflows/principals/recoverPrincipalPolicyHistory.js +108 -36
  135. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  136. package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +13 -0
  137. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +150 -0
  138. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -0
  139. package/workflows/principals/runtimePolicyRecovery.js +65 -0
  140. package/workflows/principals/runtimePolicyRecovery.js.map +1 -0
  141. package/workflows/principals/runtimePolicyWarmer.js +5 -1
  142. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
  143. package/workflows/sync/remoteResetPrincipalScope.js +10 -0
  144. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"principalPolicyVerification.js","sourceRoot":"","sources":["principalPolicyVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicySignerPublicKey,\n type ReferencedPrincipalHead,\n toFingerprint,\n type VerifiedPrincipalPolicy,\n verifyPrincipalPolicyBundle,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { loadPrincipalPolicyCheckpoint } from \"../persistence/keyingCheckpointPersistence\";\nimport {\n principalPolicyHeadMeetsCheckpoint,\n verifiedPrincipalPolicyMeetsCheckpoint,\n} from \"../persistence/principalPolicyCheckpointSelection\";\nimport { loadPrincipalPolicyBundle } from \"../persistence/principalPolicyPersistence\";\nimport { loadPrincipalPolicyBundleForReference } from \"../persistence/principalPolicyReferencePersistence\";\nimport { principalPolicyBundleStates } from \"../principalPolicyStates\";\nimport {\n parseOrganizationAuthorityDescriptor,\n principalHeadMatchesReference,\n requireOrganizationGroupHead,\n} from \"../principals/organizationAuthorityDescriptor\";\nimport {\n organizationAdminExternalAuthority,\n principalPolicyReferenceFromBundle,\n verifyOrganizationAdminPolicy,\n verifyPrincipalPolicyBundleWithExternalOrganizationAdmins,\n} from \"../principals/principalPolicyAdminSigners\";\nimport {\n observePrincipalPolicy,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { rethrowProjectionVerificationBoundaryError } from \"./error\";\nimport {\n filterUncachedPrincipalPolicyReferences,\n referencedPrincipalPolicyKey,\n verifiedPrincipalPolicyContainsReference,\n} from \"./principalPolicyCache\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\nimport {\n assertProjectionVerificationCurrent,\n generationGuardedPrincipalPolicyWarmer,\n} from \"./types\";\n\nfunction principalPolicyReferenceLabel(\n reference: ReferencedPrincipalHead,\n): string {\n return `${reference.principalType}:${reference.principalId}@${reference.version}`;\n}\n\n/**\n * A referenced principal policy is not in the local store and warming could\n * not fetch it this pass — a transient cold-cache condition, typical for a\n * member whose access arrives via a group policy the device has not hydrated\n * yet. Sync passes discriminate on this type to defer the affected container\n * and retry on a later trigger, rather than failing the whole pass.\n */\nexport class PrincipalPolicyNotCachedError extends Error {\n constructor(referenceLabel: string) {\n super(`Principal policy ${referenceLabel} is not cached`);\n this.name = \"PrincipalPolicyNotCachedError\";\n }\n}\n\nexport function isPrincipalPolicyNotCachedError(error: unknown): boolean {\n return (\n error instanceof PrincipalPolicyNotCachedError ||\n (error instanceof Error && error.name === \"PrincipalPolicyNotCachedError\")\n );\n}\n\nasync function collectPrincipalPolicySignerPublicKeys(input: {\n bundle: PrincipalPolicyBundleResponse;\n label: string;\n resolveUserKey: ProjectionUserKeyResolver;\n}): Promise<PrincipalPolicySignerPublicKey[]> {\n const signerPublicKeysByKey = new Map<\n string,\n PrincipalPolicySignerPublicKey\n >();\n\n for (const state of principalPolicyBundleStates(input.bundle)) {\n const cacheKey = `${state.signerUserId}:${state.signerUserKeyFingerprint}`;\n if (signerPublicKeysByKey.has(cacheKey)) {\n continue;\n }\n\n const signerKey = await input.resolveUserKey(state.signerUserId);\n if (!signerKey) {\n throw new ProjectionDependencyUnavailableError(\n `${input.label} signer key could not be resolved for ${state.signerUserId}`,\n );\n }\n\n const signingKeyFingerprint = await toFingerprint(\n signerKey.signingPublicKey,\n );\n if (signingKeyFingerprint !== state.signerUserKeyFingerprint) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n `${input.label} signer key fingerprint mismatch`,\n );\n }\n\n signerPublicKeysByKey.set(cacheKey, {\n userId: state.signerUserId,\n signingKeyFingerprint,\n signingPublicKey: signerKey.signingPublicKey,\n });\n }\n\n return [...signerPublicKeysByKey.values()];\n}\n\ntype OrganizationAdminPolicyInput = {\n checkpointContext: ProjectionCheckpointContext;\n organizationId: string;\n resolveUserKey: ProjectionUserKeyResolver;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n};\n\nasync function loadOrganizationPolicyForVerification(\n input: OrganizationAdminPolicyInput,\n): Promise<\n | {\n bundle: PrincipalPolicyBundleResponse;\n localCheckpoint: Awaited<\n ReturnType<typeof loadPrincipalPolicyCheckpoint>\n >;\n }\n | undefined\n> {\n const execSql = input.checkpointContext.execSql;\n let bundle = await loadPrincipalPolicyBundle(\n execSql,\n \"organization\",\n input.organizationId,\n );\n if (!bundle) {\n return undefined;\n }\n let localCheckpoint = await loadPrincipalPolicyCheckpoint(\n execSql,\n \"organization\",\n input.organizationId,\n );\n if (\n !principalPolicyHeadMeetsCheckpoint(bundle.currentState, localCheckpoint) &&\n input.warmReferencedPrincipalPolicies\n ) {\n await input.warmReferencedPrincipalPolicies({\n organizationId: input.organizationId,\n references: [principalPolicyReferenceFromBundle(bundle)],\n });\n bundle = await loadPrincipalPolicyBundle(\n execSql,\n \"organization\",\n input.organizationId,\n );\n localCheckpoint = await loadPrincipalPolicyCheckpoint(\n execSql,\n \"organization\",\n input.organizationId,\n );\n if (!bundle) {\n return undefined;\n }\n }\n\n return { bundle, localCheckpoint };\n}\n\nfunction assertReservedAdminsPolicyShape(\n policy: VerifiedPrincipalPolicy,\n): void {\n const history = policy.history ?? [{ projection: policy.projection }];\n if (\n history.some(\n (entry) =>\n entry.projection.length === 0 ||\n entry.projection.some((member) => member.role !== \"admin\"),\n )\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"reserved Admins policy must contain only direct admin users\",\n );\n }\n}\n\nasync function verifyOrganizationAdminsPolicy(input: {\n adminGroupId: string;\n execSql: ProjectionCheckpointContext[\"execSql\"];\n expectedHead: ReferencedPrincipalHead;\n resolveUserKey: ProjectionUserKeyResolver;\n}): Promise<VerifiedPrincipalPolicy | undefined> {\n const adminBundle = await loadPrincipalPolicyBundle(\n input.execSql,\n \"group\",\n input.adminGroupId,\n );\n if (!adminBundle) {\n return undefined;\n }\n if (\n !principalHeadMatchesReference(\n principalPolicyReferenceFromBundle(adminBundle),\n input.expectedHead,\n )\n ) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"Admins policy does not match the signed organization directory\",\n );\n }\n const adminCheckpoint = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n \"group\",\n input.adminGroupId,\n );\n const signerPublicKeys = await collectPrincipalPolicySignerPublicKeys({\n bundle: adminBundle,\n label: `Admins policy ${input.adminGroupId}`,\n resolveUserKey: input.resolveUserKey,\n });\n const verified = await verifyPrincipalPolicyBundle({\n bundle: adminBundle,\n expectedReference: input.expectedHead,\n localCheckpoint: adminCheckpoint,\n signerPublicKeys,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n assertReservedAdminsPolicyShape(verified.value);\n return verified.value;\n}\n\nasync function loadOrganizationExternalAuthority(\n input: OrganizationAdminPolicyInput,\n): Promise<ReturnType<typeof organizationAdminExternalAuthority> | null> {\n const organizationPolicy = await loadOrganizationPolicyForVerification(input);\n if (!organizationPolicy) {\n return null;\n }\n\n try {\n const signerPublicKeys = await collectPrincipalPolicySignerPublicKeys({\n bundle: organizationPolicy.bundle,\n label: `Organization policy ${input.organizationId}`,\n resolveUserKey: input.resolveUserKey,\n });\n const verified = await verifyOrganizationAdminPolicy({\n bundle: organizationPolicy.bundle,\n localCheckpoint: organizationPolicy.localCheckpoint,\n organizationId: input.organizationId,\n signerPublicKeys,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n const descriptor = parseOrganizationAuthorityDescriptor(\n organizationPolicy.bundle.currentPayload.ciphertext,\n );\n if (descriptor.organizationId !== input.organizationId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"organization authority descriptor scope does not match\",\n );\n }\n const verifiedAdmins = await verifyOrganizationAdminsPolicy({\n adminGroupId: descriptor.adminGroupId,\n execSql: input.checkpointContext.execSql,\n expectedHead: requireOrganizationGroupHead(\n descriptor,\n descriptor.adminGroupId,\n ),\n resolveUserKey: input.resolveUserKey,\n });\n if (!verifiedAdmins) {\n return null;\n }\n observePrincipalPolicy(\n input.checkpointContext,\n verified.value,\n input.organizationId,\n );\n observePrincipalPolicy(\n input.checkpointContext,\n verifiedAdmins,\n input.organizationId,\n );\n return organizationAdminExternalAuthority(verifiedAdmins);\n } catch (error) {\n rethrowProjectionVerificationBoundaryError(error);\n if (error instanceof KeyingVerificationError) {\n throw error;\n }\n return null;\n }\n}\n\nasync function verifyReferencedPrincipalPolicy(input: {\n checkpointContext: ProjectionCheckpointContext;\n organizationId: string;\n principalPolicyCache: PrincipalPolicyCache;\n reference: ReferencedPrincipalHead;\n resolveUserKey: ProjectionUserKeyResolver;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<VerifiedPrincipalPolicy> {\n const cacheKey = referencedPrincipalPolicyKey(input.reference);\n const cachedPolicy = input.principalPolicyCache.get(cacheKey);\n const execSql = input.checkpointContext.execSql;\n const localCheckpoint = await loadPrincipalPolicyCheckpoint(\n execSql,\n input.reference.principalType,\n input.reference.principalId,\n );\n if (cachedPolicy) {\n if (\n !verifiedPrincipalPolicyContainsReference(cachedPolicy, input.reference)\n ) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"in-memory principal policy cache does not match its exact reference\",\n );\n }\n if (verifiedPrincipalPolicyMeetsCheckpoint(cachedPolicy, localCheckpoint)) {\n observePrincipalPolicy(\n input.checkpointContext,\n cachedPolicy,\n input.organizationId,\n );\n return cachedPolicy;\n }\n }\n\n const referenceLabel = principalPolicyReferenceLabel(input.reference);\n let bundle = await loadPrincipalPolicyBundleForReference(\n execSql,\n input.reference,\n localCheckpoint,\n );\n if (!bundle && input.warmReferencedPrincipalPolicies) {\n // The reference is not cached locally — the common case for a member who\n // gained access via another org's group grant and never hydrated that\n // group's policy. Fetch+verify+persist it, then re-read from the cache.\n await input.warmReferencedPrincipalPolicies({\n organizationId: input.organizationId,\n references: [input.reference],\n });\n bundle = await loadPrincipalPolicyBundleForReference(\n execSql,\n input.reference,\n localCheckpoint,\n );\n }\n if (!bundle) {\n throw new PrincipalPolicyNotCachedError(referenceLabel);\n }\n\n const signerPublicKeys = await collectPrincipalPolicySignerPublicKeys({\n bundle,\n label: `Principal policy ${referenceLabel}`,\n resolveUserKey: input.resolveUserKey,\n });\n const verified =\n await verifyPrincipalPolicyBundleWithExternalOrganizationAdmins({\n bundle,\n expectedReference: input.reference,\n loadExternalAuthority: () =>\n loadOrganizationExternalAuthority({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies:\n input.warmReferencedPrincipalPolicies,\n }),\n localCheckpoint,\n signerPublicKeys,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n\n observePrincipalPolicy(\n input.checkpointContext,\n verified.value,\n input.organizationId,\n );\n input.principalPolicyCache.set(cacheKey, verified.value);\n return verified.value;\n}\n\nexport async function collectReferencedPrincipalPolicies(input: {\n checkpointContext: ProjectionCheckpointContext;\n organizationId: string;\n principalPolicyCache: PrincipalPolicyCache;\n references: readonly ReferencedPrincipalHead[];\n resolveUserKey: ProjectionUserKeyResolver;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<VerifiedPrincipalPolicy[]> {\n const warmReferencedPrincipalPolicies =\n generationGuardedPrincipalPolicyWarmer(\n input.warmReferencedPrincipalPolicies,\n input.stillCurrent,\n );\n const uniqueReferences = new Map<string, ReferencedPrincipalHead>();\n for (const reference of input.references) {\n uniqueReferences.set(referencedPrincipalPolicyKey(reference), reference);\n }\n\n const references = [...uniqueReferences.values()];\n // Warm every missing reference in one batched fetch before verifying, so a\n // path that references several uncached policies makes a single round of\n // requests rather than one per reference.\n if (warmReferencedPrincipalPolicies) {\n const uncached = await filterUncachedPrincipalPolicyReferences({\n execSql: input.checkpointContext.execSql,\n principalPolicyCache: input.principalPolicyCache,\n references,\n });\n if (uncached.length > 0) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n await warmReferencedPrincipalPolicies({\n organizationId: input.organizationId,\n references: uncached,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n }\n }\n\n return Promise.all(\n references.map((reference) =>\n verifyReferencedPrincipalPolicy({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n reference,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies,\n }),\n ),\n );\n}\n"]}
1
+ {"version":3,"file":"principalPolicyVerification.js","sourceRoot":"","sources":["principalPolicyVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type PrincipalPolicySignerPublicKey,\n type ReferencedPrincipalHead,\n toFingerprint,\n type VerifiedPrincipalPolicy,\n verifyPrincipalPolicyBundle,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { loadPrincipalPolicyCheckpoint } from \"../persistence/keyingCheckpointPersistence\";\nimport {\n principalPolicyHeadMeetsCheckpoint,\n verifiedPrincipalPolicyMeetsCheckpoint,\n} from \"../persistence/principalPolicyCheckpointSelection\";\nimport { loadPrincipalPolicyBundle } from \"../persistence/principalPolicyPersistence\";\nimport { loadPrincipalPolicyBundleForReference } from \"../persistence/principalPolicyReferencePersistence\";\nimport { principalPolicyBundleStates } from \"../principalPolicyStates\";\nimport {\n parseOrganizationAuthorityDescriptor,\n principalHeadMatchesReference,\n requireOrganizationGroupHead,\n} from \"../principals/organizationAuthorityDescriptor\";\nimport {\n organizationAdminExternalAuthority,\n principalPolicyReferenceFromBundle,\n verifyOrganizationAdminPolicy,\n verifyPrincipalPolicyBundleWithExternalOrganizationAdmins,\n} from \"../principals/principalPolicyAdminSigners\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../principals/principalPolicyEvidence\";\nimport {\n observePrincipalPolicy,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport { ProjectionDependencyUnavailableError } from \"./dependencyUnavailable\";\nimport { rethrowProjectionVerificationBoundaryError } from \"./error\";\nimport {\n filterUncachedPrincipalPolicyReferences,\n referencedPrincipalPolicyKey,\n verifiedPrincipalPolicyContainsReference,\n} from \"./principalPolicyCache\";\nimport { resolveReferencedPrincipalPolicy } from \"./resolvedPrincipalPolicy\";\nimport type {\n PrincipalPolicyCache,\n ProjectionUserKeyResolver,\n ReferencedPrincipalPolicyWarmer,\n} from \"./types\";\nimport {\n assertProjectionVerificationCurrent,\n generationGuardedPrincipalPolicyWarmer,\n} from \"./types\";\n\nfunction principalPolicyReferenceLabel(\n reference: ReferencedPrincipalHead,\n): string {\n return `${reference.principalType}:${reference.principalId}@${reference.version}`;\n}\n\n/**\n * A referenced principal policy is not in the local store and warming could\n * not fetch it this pass — a transient cold-cache condition, typical for a\n * member whose access arrives via a group policy the device has not hydrated\n * yet. Sync passes discriminate on this type to defer the affected container\n * and retry on a later trigger, rather than failing the whole pass.\n */\nexport class PrincipalPolicyNotCachedError extends Error {\n constructor(referenceLabel: string) {\n super(`Principal policy ${referenceLabel} is not cached`);\n this.name = \"PrincipalPolicyNotCachedError\";\n }\n}\n\nexport function isPrincipalPolicyNotCachedError(error: unknown): boolean {\n return (\n error instanceof PrincipalPolicyNotCachedError ||\n (error instanceof Error && error.name === \"PrincipalPolicyNotCachedError\")\n );\n}\n\nasync function collectPrincipalPolicySignerPublicKeys(input: {\n bundle: PrincipalPolicyBundleResponse;\n label: string;\n resolveUserKey: ProjectionUserKeyResolver;\n}): Promise<PrincipalPolicySignerPublicKey[]> {\n const signerPublicKeysByKey = new Map<\n string,\n PrincipalPolicySignerPublicKey\n >();\n\n for (const state of principalPolicyBundleStates(input.bundle)) {\n const cacheKey = `${state.signerUserId}:${state.signerUserKeyFingerprint}`;\n if (signerPublicKeysByKey.has(cacheKey)) {\n continue;\n }\n\n const signerKey = await input.resolveUserKey(state.signerUserId);\n if (!signerKey) {\n throw new ProjectionDependencyUnavailableError(\n `${input.label} signer key could not be resolved for ${state.signerUserId}`,\n );\n }\n\n const signingKeyFingerprint = await toFingerprint(\n signerKey.signingPublicKey,\n );\n if (signingKeyFingerprint !== state.signerUserKeyFingerprint) {\n throw new KeyingVerificationError(\n \"signer_mismatch\",\n `${input.label} signer key fingerprint mismatch`,\n );\n }\n\n signerPublicKeysByKey.set(cacheKey, {\n userId: state.signerUserId,\n signingKeyFingerprint,\n signingPublicKey: signerKey.signingPublicKey,\n });\n }\n\n return [...signerPublicKeysByKey.values()];\n}\n\ntype OrganizationAdminPolicyInput = {\n checkpointContext: ProjectionCheckpointContext;\n organizationId: string;\n resolveUserKey: ProjectionUserKeyResolver;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n};\n\nasync function loadOrganizationPolicyForVerification(\n input: OrganizationAdminPolicyInput,\n): Promise<\n | {\n bundle: PrincipalPolicyBundleResponse;\n localCheckpoint: Awaited<\n ReturnType<typeof loadPrincipalPolicyCheckpoint>\n >;\n }\n | undefined\n> {\n const execSql = input.checkpointContext.execSql;\n let bundle = await loadPrincipalPolicyBundle(\n execSql,\n \"organization\",\n input.organizationId,\n );\n if (!bundle) {\n return undefined;\n }\n let localCheckpoint = await loadPrincipalPolicyCheckpoint(\n execSql,\n \"organization\",\n input.organizationId,\n );\n if (\n !principalPolicyHeadMeetsCheckpoint(bundle.currentState, localCheckpoint) &&\n input.warmReferencedPrincipalPolicies\n ) {\n await input.warmReferencedPrincipalPolicies({\n organizationId: input.organizationId,\n references: [principalPolicyReferenceFromBundle(bundle)],\n });\n bundle = await loadPrincipalPolicyBundle(\n execSql,\n \"organization\",\n input.organizationId,\n );\n localCheckpoint = await loadPrincipalPolicyCheckpoint(\n execSql,\n \"organization\",\n input.organizationId,\n );\n if (!bundle) {\n return undefined;\n }\n }\n\n return { bundle, localCheckpoint };\n}\n\nfunction assertReservedAdminsPolicyShape(\n policy: VerifiedPrincipalPolicy,\n): void {\n const history = policy.history ?? [{ projection: policy.projection }];\n if (\n history.some(\n (entry) =>\n entry.projection.length === 0 ||\n entry.projection.some((member) => member.role !== \"admin\"),\n )\n ) {\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"reserved Admins policy must contain only direct admin users\",\n );\n }\n}\n\nasync function verifyOrganizationAdminsPolicy(input: {\n adminGroupId: string;\n execSql: ProjectionCheckpointContext[\"execSql\"];\n expectedHead: ReferencedPrincipalHead;\n resolveUserKey: ProjectionUserKeyResolver;\n}): Promise<VerifiedPrincipalPolicy | undefined> {\n const adminBundle = await loadPrincipalPolicyBundle(\n input.execSql,\n \"group\",\n input.adminGroupId,\n );\n if (!adminBundle) {\n return undefined;\n }\n if (\n !principalHeadMatchesReference(\n principalPolicyReferenceFromBundle(adminBundle),\n input.expectedHead,\n )\n ) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"Admins policy does not match the signed organization directory\",\n );\n }\n const adminCheckpoint = await loadPrincipalPolicyCheckpoint(\n input.execSql,\n \"group\",\n input.adminGroupId,\n );\n const signerPublicKeys = await collectPrincipalPolicySignerPublicKeys({\n bundle: adminBundle,\n label: `Admins policy ${input.adminGroupId}`,\n resolveUserKey: input.resolveUserKey,\n });\n const verified = await verifyPrincipalPolicyBundle({\n bundle: adminBundle,\n expectedReference: input.expectedHead,\n localCheckpoint: adminCheckpoint,\n signerPublicKeys,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n assertReservedAdminsPolicyShape(verified.value);\n return verified.value;\n}\n\nasync function loadOrganizationExternalAuthority(\n input: OrganizationAdminPolicyInput,\n): Promise<ReturnType<typeof organizationAdminExternalAuthority> | null> {\n const organizationPolicy = await loadOrganizationPolicyForVerification(input);\n if (!organizationPolicy) {\n return null;\n }\n\n try {\n const signerPublicKeys = await collectPrincipalPolicySignerPublicKeys({\n bundle: organizationPolicy.bundle,\n label: `Organization policy ${input.organizationId}`,\n resolveUserKey: input.resolveUserKey,\n });\n const verified = await verifyOrganizationAdminPolicy({\n bundle: organizationPolicy.bundle,\n localCheckpoint: organizationPolicy.localCheckpoint,\n organizationId: input.organizationId,\n signerPublicKeys,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n const descriptor = parseOrganizationAuthorityDescriptor(\n organizationPolicy.bundle.currentPayload.ciphertext,\n );\n if (descriptor.organizationId !== input.organizationId) {\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"organization authority descriptor scope does not match\",\n );\n }\n const verifiedAdmins = await verifyOrganizationAdminsPolicy({\n adminGroupId: descriptor.adminGroupId,\n execSql: input.checkpointContext.execSql,\n expectedHead: requireOrganizationGroupHead(\n descriptor,\n descriptor.adminGroupId,\n ),\n resolveUserKey: input.resolveUserKey,\n });\n if (!verifiedAdmins) {\n return null;\n }\n observePrincipalPolicy(\n input.checkpointContext,\n verified.value,\n input.organizationId,\n );\n observePrincipalPolicy(\n input.checkpointContext,\n verifiedAdmins,\n input.organizationId,\n );\n return organizationAdminExternalAuthority(verifiedAdmins);\n } catch (error) {\n rethrowProjectionVerificationBoundaryError(error);\n if (error instanceof KeyingVerificationError) {\n throw error;\n }\n return null;\n }\n}\n\nasync function verifyReferencedPrincipalPolicy(input: {\n recoveryBatch: object;\n checkpointContext: ProjectionCheckpointContext;\n organizationId: string;\n principalPolicyCache: PrincipalPolicyCache;\n reference: ReferencedPrincipalHead;\n stillCurrent?: (() => boolean) | undefined;\n resolveUserKey: ProjectionUserKeyResolver;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<PrincipalPolicyCurrentEvidence> {\n const cacheKey = referencedPrincipalPolicyKey(input.reference);\n const cachedPolicy = input.principalPolicyCache.get(cacheKey);\n const execSql = input.checkpointContext.execSql;\n const localCheckpoint = await loadPrincipalPolicyCheckpoint(\n execSql,\n input.reference.principalType,\n input.reference.principalId,\n );\n if (cachedPolicy && !(\"retainedHistory\" in cachedPolicy)) {\n if (\n !verifiedPrincipalPolicyContainsReference(cachedPolicy, input.reference)\n ) {\n throw new KeyingVerificationError(\n \"hash_mismatch\",\n \"in-memory principal policy cache does not match its exact reference\",\n );\n }\n if (verifiedPrincipalPolicyMeetsCheckpoint(cachedPolicy, localCheckpoint)) {\n observePrincipalPolicy(\n input.checkpointContext,\n cachedPolicy,\n input.organizationId,\n );\n return cachedPolicy;\n }\n }\n\n const referenceLabel = principalPolicyReferenceLabel(input.reference);\n let bundle = await loadPrincipalPolicyBundleForReference(\n execSql,\n input.reference,\n localCheckpoint,\n );\n if (!bundle) {\n const recovered = await resolveReferencedPrincipalPolicy(input);\n if (recovered) return recovered;\n }\n if (!bundle && input.warmReferencedPrincipalPolicies) {\n // The reference is not cached locally — the common case for a member who\n // gained access via another org's group grant and never hydrated that\n // group's policy. Fetch+verify+persist it, then re-read from the cache.\n await input.warmReferencedPrincipalPolicies({\n organizationId: input.organizationId,\n references: [input.reference],\n });\n bundle = await loadPrincipalPolicyBundleForReference(\n execSql,\n input.reference,\n localCheckpoint,\n );\n }\n if (!bundle) {\n throw new PrincipalPolicyNotCachedError(referenceLabel);\n }\n\n const signerPublicKeys = await collectPrincipalPolicySignerPublicKeys({\n bundle,\n label: `Principal policy ${referenceLabel}`,\n resolveUserKey: input.resolveUserKey,\n });\n const verified =\n await verifyPrincipalPolicyBundleWithExternalOrganizationAdmins({\n bundle,\n expectedReference: input.reference,\n loadExternalAuthority: () =>\n loadOrganizationExternalAuthority({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies:\n input.warmReferencedPrincipalPolicies,\n }),\n localCheckpoint,\n signerPublicKeys,\n });\n if (!verified.ok) {\n throw verified.error;\n }\n\n observePrincipalPolicy(\n input.checkpointContext,\n verified.value,\n input.organizationId,\n );\n input.principalPolicyCache.set(cacheKey, verified.value);\n return verified.value;\n}\n\nexport async function collectReferencedPrincipalPolicies(input: {\n checkpointContext: ProjectionCheckpointContext;\n organizationId: string;\n principalPolicyCache: PrincipalPolicyCache;\n references: readonly ReferencedPrincipalHead[];\n resolveUserKey: ProjectionUserKeyResolver;\n stillCurrent?: (() => boolean) | undefined;\n warmReferencedPrincipalPolicies?: ReferencedPrincipalPolicyWarmer | undefined;\n}): Promise<PrincipalPolicyCurrentEvidence[]> {\n const warmReferencedPrincipalPolicies =\n generationGuardedPrincipalPolicyWarmer(\n input.warmReferencedPrincipalPolicies,\n input.stillCurrent,\n );\n const uniqueReferences = new Map<string, ReferencedPrincipalHead>();\n for (const reference of input.references) {\n uniqueReferences.set(referencedPrincipalPolicyKey(reference), reference);\n }\n\n const references = [...uniqueReferences.values()];\n // Warm every missing reference in one batched fetch before verifying, so a\n // path that references several uncached policies makes a single round of\n // requests rather than one per reference.\n if (\n warmReferencedPrincipalPolicies &&\n !warmReferencedPrincipalPolicies.resolveReference\n ) {\n const uncached = await filterUncachedPrincipalPolicyReferences({\n execSql: input.checkpointContext.execSql,\n principalPolicyCache: input.principalPolicyCache,\n references,\n });\n if (uncached.length > 0) {\n assertProjectionVerificationCurrent(input.stillCurrent);\n await warmReferencedPrincipalPolicies({\n organizationId: input.organizationId,\n references: uncached,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n }\n }\n\n const recoveryBatch = {};\n return Promise.all(\n references.map((reference) =>\n verifyReferencedPrincipalPolicy({\n recoveryBatch,\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n reference,\n stillCurrent: input.stillCurrent,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies,\n }),\n ),\n );\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"projectionAuthorizationEvidence.js","sourceRoot":"","sources":["projectionAuthorizationEvidence.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,uBAAuB,EACvB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,kCAAkC,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG/C,mFAAmF;AACnF,KAAK,UAAU,sCAAsC,CAAC,KAOrD;IACC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO;SAC7B,OAAO,CACN,CAAC,MAAM,EAAE,EAAE,CACT,kBAAkB,CAAC,MAAM,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACvD,wBAAwB,CAC9B;SACA,MAAM,CACL,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9B,+BAA+B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CACvD,CACJ,CAAC;IACJ,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,IACE,UAAU,CAAC,IAAI,CACb,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACrB,+BAA+B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CACvD,CACJ;QAED,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,qDAAqD,CACtD,CAAC;IACJ,OAAO;QACL,GAAG,KAAK,CAAC,QAAQ;QACjB,GAAG,CAAC,MAAM,kCAAkC,CAAC;YAC3C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;YAChD,UAAU;YACV,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACzD,KAGiE;IAEjE,OAAO,sCAAsC,CAAC;QAC5C,GAAG,KAAK;QACR,QAAQ,EAAE,MAAM,8BAA8B,CAAC;YAC7C,QAAQ,EAAE,KAAK,CAAC,cAAc;YAC9B,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,OAAO;YACxC,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC;KACH,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n principalPolicyMatchesReference,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n ProjectionPolicyEvidenceResponse,\n} from \"@tearleads/validators/response\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport { collectReferencedPrincipalPolicies } from \"./principalPolicyVerification\";\nimport { verifyProjectionPolicyEvidence } from \"./projectionPolicyEvidence\";\nimport { readAccessManifest } from \"./readers\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\n/** Locally planned successors may cite an already verified, uncommitted policy. */\nasync function resolveProjectionAuthorizationEvidence(input: {\n readonly bundles: readonly AccessManifestBundleWireResponse[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly evidence: readonly AnyVerifiedPrincipalPolicy[];\n readonly organizationId: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}): Promise<AnyVerifiedPrincipalPolicy[]> {\n const references = input.bundles\n .flatMap(\n (bundle) =>\n readAccessManifest(bundle.manifest, \"Projection manifest\")\n .referencedPrincipalHeads,\n )\n .filter(\n (reference) =>\n !input.evidence.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n ),\n );\n const known = [...input.principalPolicyCache.values()];\n if (\n references.some(\n (reference) =>\n !known.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n ),\n )\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Projection omits required principal policy evidence\",\n );\n return [\n ...input.evidence,\n ...(await collectReferencedPrincipalPolicies({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n references,\n resolveUserKey: input.resolveUserKey,\n })),\n ];\n}\n\nexport async function verifyProjectionAuthorizationEvidence(\n input: Omit<\n Parameters<typeof resolveProjectionAuthorizationEvidence>[0],\n \"evidence\"\n > & { readonly policyEvidence: ProjectionPolicyEvidenceResponse },\n) {\n return resolveProjectionAuthorizationEvidence({\n ...input,\n evidence: await verifyProjectionPolicyEvidence({\n evidence: input.policyEvidence,\n execSql: input.checkpointContext.execSql,\n organizationId: input.organizationId,\n resolveUserKey: input.resolveUserKey,\n }),\n });\n}\n"]}
1
+ {"version":3,"file":"projectionAuthorizationEvidence.js","sourceRoot":"","sources":["projectionAuthorizationEvidence.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,+BAA+B,GAChC,MAAM,mBAAmB,CAAC;AAO3B,OAAO,EAAE,kCAAkC,EAAE,MAAM,+BAA+B,CAAC;AACnF,OAAO,EAAE,8BAA8B,EAAE,MAAM,4BAA4B,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAG/C,mFAAmF;AACnF,KAAK,UAAU,sCAAsC,CAAC,KAOrD;IACC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO;SAC7B,OAAO,CACN,CAAC,MAAM,EAAE,EAAE,CACT,kBAAkB,CAAC,MAAM,CAAC,QAAQ,EAAE,qBAAqB,CAAC;SACvD,wBAAwB,CAC9B;SACA,MAAM,CACL,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAC9B,+BAA+B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CACvD,CACJ,CAAC;IACJ,MAAM,KAAK,GAAG,CAAC,GAAG,KAAK,CAAC,oBAAoB,CAAC,MAAM,EAAE,CAAC,CAAC;IACvD,IACE,UAAU,CAAC,IAAI,CACb,CAAC,SAAS,EAAE,EAAE,CACZ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CACrB,+BAA+B,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC,CACvD,CACJ;QAED,MAAM,IAAI,uBAAuB,CAC/B,oBAAoB,EACpB,qDAAqD,CACtD,CAAC;IACJ,OAAO;QACL,GAAG,KAAK,CAAC,QAAQ;QACjB,GAAG,CAAC,MAAM,kCAAkC,CAAC;YAC3C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;YAChD,UAAU;YACV,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,qCAAqC,CACzD,KAGiE;IAEjE,OAAO,sCAAsC,CAAC;QAC5C,GAAG,KAAK;QACR,QAAQ,EAAE,MAAM,8BAA8B,CAAC;YAC7C,QAAQ,EAAE,KAAK,CAAC,cAAc;YAC9B,OAAO,EAAE,KAAK,CAAC,iBAAiB,CAAC,OAAO;YACxC,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,cAAc,EAAE,KAAK,CAAC,cAAc;SACrC,CAAC;KACH,CAAC,CAAC;AACL,CAAC","sourcesContent":["import {\n KeyingVerificationError,\n principalPolicyMatchesReference,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWireResponse,\n ProjectionPolicyEvidenceResponse,\n} from \"@tearleads/validators/response\";\nimport type { PrincipalPolicyCheckpointEvidence } from \"../principals/principalPolicyEvidence\";\nimport type { ProjectionCheckpointContext } from \"./checkpointContext\";\nimport { collectReferencedPrincipalPolicies } from \"./principalPolicyVerification\";\nimport { verifyProjectionPolicyEvidence } from \"./projectionPolicyEvidence\";\nimport { readAccessManifest } from \"./readers\";\nimport type { PrincipalPolicyCache, ProjectionUserKeyResolver } from \"./types\";\n\n/** Locally planned successors may cite an already verified, uncommitted policy. */\nasync function resolveProjectionAuthorizationEvidence(input: {\n readonly bundles: readonly AccessManifestBundleWireResponse[];\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly evidence: readonly PrincipalPolicyCheckpointEvidence[];\n readonly organizationId: string;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly resolveUserKey: ProjectionUserKeyResolver;\n}): Promise<PrincipalPolicyCheckpointEvidence[]> {\n const references = input.bundles\n .flatMap(\n (bundle) =>\n readAccessManifest(bundle.manifest, \"Projection manifest\")\n .referencedPrincipalHeads,\n )\n .filter(\n (reference) =>\n !input.evidence.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n ),\n );\n const known = [...input.principalPolicyCache.values()];\n if (\n references.some(\n (reference) =>\n !known.some((policy) =>\n principalPolicyMatchesReference({ policy, reference }),\n ),\n )\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Projection omits required principal policy evidence\",\n );\n return [\n ...input.evidence,\n ...(await collectReferencedPrincipalPolicies({\n checkpointContext: input.checkpointContext,\n organizationId: input.organizationId,\n principalPolicyCache: input.principalPolicyCache,\n references,\n resolveUserKey: input.resolveUserKey,\n })),\n ];\n}\n\nexport async function verifyProjectionAuthorizationEvidence(\n input: Omit<\n Parameters<typeof resolveProjectionAuthorizationEvidence>[0],\n \"evidence\"\n > & { readonly policyEvidence: ProjectionPolicyEvidenceResponse },\n) {\n return resolveProjectionAuthorizationEvidence({\n ...input,\n evidence: await verifyProjectionPolicyEvidence({\n evidence: input.policyEvidence,\n execSql: input.checkpointContext.execSql,\n organizationId: input.organizationId,\n resolveUserKey: input.resolveUserKey,\n }),\n });\n}\n"]}
@@ -0,0 +1,70 @@
1
+ import { KeyingVerificationError, } from "../../internal/crypto/index.js";
2
+ import { loadPrincipalPolicyCheckpoint } from "../persistence/keyingCheckpointPersistence.js";
3
+ import { verifiedPrincipalPolicyMeetsCheckpoint } from "../persistence/principalPolicyCheckpointSelection.js";
4
+ import { observePrincipalPolicy, } from "./checkpointContext.js";
5
+ import { referencedPrincipalPolicyKey, verifiedPrincipalPolicyContainsReference, } from "./principalPolicyCache.js";
6
+ import { assertProjectionVerificationCurrent, } from "./types.js";
7
+ // Sparse cache hits must carry the organization binding and every dependency
8
+ // into each new admission batch; a bare current-policy capability is insufficient.
9
+ // The caller owns this cache. Cross-generation reuse is deliberately disabled by
10
+ // the saved guard; a new lifetime restores authenticated persistent evidence.
11
+ const recoveredByCache = new WeakMap();
12
+ async function meetsCheckpoints(context, result, refreshMissing) {
13
+ for (const policy of [...result.dependencies, result.policy]) {
14
+ const checkpoint = await loadPrincipalPolicyCheckpoint(context.execSql, policy.principalType, policy.principalId);
15
+ if (refreshMissing &&
16
+ checkpoint &&
17
+ (policy.version < checkpoint.version ||
18
+ (policy.version > checkpoint.version &&
19
+ !policy.retainedHistory.some((entry) => entry.state.version === checkpoint.version))))
20
+ return false;
21
+ if (!verifiedPrincipalPolicyMeetsCheckpoint(policy, checkpoint))
22
+ throw new KeyingVerificationError("rollback", "Recovered principal evidence predates the durable checkpoint");
23
+ }
24
+ return true;
25
+ }
26
+ export async function resolveReferencedPrincipalPolicy(input) {
27
+ assertProjectionVerificationCurrent(input.stillCurrent);
28
+ const key = referencedPrincipalPolicyKey(input.reference);
29
+ const remembered = recoveredByCache.get(input.principalPolicyCache)?.get(key);
30
+ let result = remembered?.organizationId === input.organizationId &&
31
+ remembered.policy === input.principalPolicyCache.get(key) &&
32
+ remembered.stillCurrent()
33
+ ? remembered
34
+ : undefined;
35
+ if (result &&
36
+ !(await meetsCheckpoints(input.checkpointContext, result, true)))
37
+ result = undefined;
38
+ if (!result) {
39
+ const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;
40
+ if (!resolve)
41
+ return null;
42
+ result = await resolve({
43
+ recoveryBatch: input.recoveryBatch,
44
+ organizationId: input.organizationId,
45
+ reference: input.reference,
46
+ stillCurrent: input.stillCurrent,
47
+ });
48
+ await meetsCheckpoints(input.checkpointContext, result, false);
49
+ }
50
+ assertProjectionVerificationCurrent(input.stillCurrent);
51
+ assertProjectionVerificationCurrent(result.stillCurrent);
52
+ if (result.organizationId !== input.organizationId)
53
+ throw new KeyingVerificationError("object_mismatch", "Recovered principal evidence belongs to another organization");
54
+ if (!verifiedPrincipalPolicyContainsReference(result.policy, input.reference))
55
+ throw new KeyingVerificationError("object_mismatch", "Recovered principal evidence does not contain the exact citation");
56
+ for (const policy of [...result.dependencies, result.policy])
57
+ observePrincipalPolicy(input.checkpointContext, policy, input.organizationId);
58
+ let rememberedPolicies = recoveredByCache.get(input.principalPolicyCache);
59
+ if (!rememberedPolicies) {
60
+ rememberedPolicies = new Map();
61
+ recoveredByCache.set(input.principalPolicyCache, rememberedPolicies);
62
+ }
63
+ rememberedPolicies.set(key, {
64
+ ...result,
65
+ dependencies: [...result.dependencies],
66
+ });
67
+ input.principalPolicyCache.set(key, result.policy);
68
+ return result.policy;
69
+ }
70
+ //# sourceMappingURL=resolvedPrincipalPolicy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolvedPrincipalPolicy.js","sourceRoot":"","sources":["resolvedPrincipalPolicy.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n KeyingVerificationError,\n type ReferencedPrincipalHead,\n type VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport { loadPrincipalPolicyCheckpoint } from \"../persistence/keyingCheckpointPersistence\";\nimport { verifiedPrincipalPolicyMeetsCheckpoint } from \"../persistence/principalPolicyCheckpointSelection\";\nimport {\n observePrincipalPolicy,\n type ProjectionCheckpointContext,\n} from \"./checkpointContext\";\nimport {\n referencedPrincipalPolicyKey,\n verifiedPrincipalPolicyContainsReference,\n} from \"./principalPolicyCache\";\nimport {\n assertProjectionVerificationCurrent,\n type PrincipalPolicyCache,\n type ReferencedPrincipalPolicyWarmer,\n type ResolvedPrincipalPolicyEvidence,\n} from \"./types\";\n\n// Sparse cache hits must carry the organization binding and every dependency\n// into each new admission batch; a bare current-policy capability is insufficient.\n// The caller owns this cache. Cross-generation reuse is deliberately disabled by\n// the saved guard; a new lifetime restores authenticated persistent evidence.\nconst recoveredByCache = new WeakMap<\n PrincipalPolicyCache,\n Map<string, ResolvedPrincipalPolicyEvidence>\n>();\n\nasync function meetsCheckpoints(\n context: ProjectionCheckpointContext,\n result: ResolvedPrincipalPolicyEvidence,\n refreshMissing: boolean,\n): Promise<boolean> {\n for (const policy of [...result.dependencies, result.policy]) {\n const checkpoint = await loadPrincipalPolicyCheckpoint(\n context.execSql,\n policy.principalType,\n policy.principalId,\n );\n if (\n refreshMissing &&\n checkpoint &&\n (policy.version < checkpoint.version ||\n (policy.version > checkpoint.version &&\n !policy.retainedHistory.some(\n (entry) => entry.state.version === checkpoint.version,\n )))\n )\n return false;\n if (!verifiedPrincipalPolicyMeetsCheckpoint(policy, checkpoint))\n throw new KeyingVerificationError(\n \"rollback\",\n \"Recovered principal evidence predates the durable checkpoint\",\n );\n }\n return true;\n}\n\nexport async function resolveReferencedPrincipalPolicy(input: {\n readonly recoveryBatch?: object | undefined;\n readonly checkpointContext: ProjectionCheckpointContext;\n readonly organizationId: string;\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly reference: ReferencedPrincipalHead;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}): Promise<VerifiedPrincipalPolicyCurrent | null> {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const key = referencedPrincipalPolicyKey(input.reference);\n const remembered = recoveredByCache.get(input.principalPolicyCache)?.get(key);\n let result =\n remembered?.organizationId === input.organizationId &&\n remembered.policy === input.principalPolicyCache.get(key) &&\n remembered.stillCurrent()\n ? remembered\n : undefined;\n if (\n result &&\n !(await meetsCheckpoints(input.checkpointContext, result, true))\n )\n result = undefined;\n if (!result) {\n const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;\n if (!resolve) return null;\n result = await resolve({\n recoveryBatch: input.recoveryBatch,\n organizationId: input.organizationId,\n reference: input.reference,\n stillCurrent: input.stillCurrent,\n });\n await meetsCheckpoints(input.checkpointContext, result, false);\n }\n assertProjectionVerificationCurrent(input.stillCurrent);\n assertProjectionVerificationCurrent(result.stillCurrent);\n if (result.organizationId !== input.organizationId)\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Recovered principal evidence belongs to another organization\",\n );\n if (!verifiedPrincipalPolicyContainsReference(result.policy, input.reference))\n throw new KeyingVerificationError(\n \"object_mismatch\",\n \"Recovered principal evidence does not contain the exact citation\",\n );\n for (const policy of [...result.dependencies, result.policy])\n observePrincipalPolicy(\n input.checkpointContext,\n policy,\n input.organizationId,\n );\n let rememberedPolicies = recoveredByCache.get(input.principalPolicyCache);\n if (!rememberedPolicies) {\n rememberedPolicies = new Map();\n recoveredByCache.set(input.principalPolicyCache, rememberedPolicies);\n }\n rememberedPolicies.set(key, {\n ...result,\n dependencies: [...result.dependencies],\n });\n input.principalPolicyCache.set(key, result.policy);\n return result.policy;\n}\n"]}
@@ -1,9 +1,23 @@
1
- import type { ReferencedPrincipalHead, VerifiedPrincipalPolicy } from "../../internal/crypto/index.js";
1
+ import type { ReferencedPrincipalHead, VerifiedPrincipalPolicyCurrent } from "../../internal/crypto/index.js";
2
2
  import type { PrincipalPolicyBundleResponse } from "../../internal/validators/response/index.js";
3
+ import type { PrincipalPolicyCurrentEvidence } from "../principals/principalPolicyEvidence.js";
3
4
  import type { TrustedUserIdentity } from "../trustedUserIdentity/index.js";
4
5
  export type ProjectionUserKey = TrustedUserIdentity;
5
6
  export type ProjectionUserKeyResolver = (userId: string) => Promise<ProjectionUserKey | null>;
6
- export type PrincipalPolicyCache = Map<string, VerifiedPrincipalPolicy>;
7
+ export type PrincipalPolicyCache = Map<string, PrincipalPolicyCurrentEvidence>;
8
+ export interface PrincipalPolicyResolveRequest {
9
+ /** Identity of one projection collection, never caller-supplied evidence. */
10
+ readonly recoveryBatch?: object | undefined;
11
+ readonly organizationId: string;
12
+ readonly reference: ReferencedPrincipalHead;
13
+ readonly stillCurrent?: (() => boolean) | undefined;
14
+ }
15
+ export interface ResolvedPrincipalPolicyEvidence {
16
+ readonly stillCurrent: () => boolean;
17
+ readonly organizationId: string;
18
+ readonly policy: VerifiedPrincipalPolicyCurrent;
19
+ readonly dependencies: readonly VerifiedPrincipalPolicyCurrent[];
20
+ }
7
21
  export interface ReferencedPrincipalPolicyWarmRequest {
8
22
  readonly organizationId: string;
9
23
  readonly references: readonly ReferencedPrincipalHead[];
@@ -17,6 +31,7 @@ export interface PrincipalPolicyBundleCacheRequest {
17
31
  export type PrincipalPolicyBundleCacher = (input: PrincipalPolicyBundleCacheRequest) => Promise<void>;
18
32
  export type ReferencedPrincipalPolicyWarmer = ((input: ReferencedPrincipalPolicyWarmRequest) => Promise<void>) & {
19
33
  readonly cacheBundles?: PrincipalPolicyBundleCacher | undefined;
34
+ readonly resolveReference?: ((input: PrincipalPolicyResolveRequest) => Promise<ResolvedPrincipalPolicyEvidence>) | undefined;
20
35
  };
21
36
  export declare class ProjectionVerificationCancelledError extends Error {
22
37
  constructor();
@@ -37,7 +37,19 @@ export function generationGuardedPrincipalPolicyWarmer(warmer, stillCurrent) {
37
37
  };
38
38
  const guardWithCapabilities = (operation) => {
39
39
  const guarded = guard(operation);
40
+ const resolve = operation.resolveReference;
40
41
  return Object.assign(guarded, {
42
+ ...(resolve
43
+ ? {
44
+ resolveReference: async (input) => {
45
+ const current = () => stillCurrent() && input.stillCurrent?.() !== false;
46
+ assertProjectionVerificationCurrent(current);
47
+ const result = await resolve({ ...input, stillCurrent: current });
48
+ assertProjectionVerificationCurrent(current);
49
+ return result;
50
+ },
51
+ }
52
+ : {}),
41
53
  ...(operation.cacheBundles
42
54
  ? {
43
55
  cacheBundles: async (input) => {
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"AAqCA,MAAM,OAAO,oCAAqC,SAAQ,KAAK;IAC7D;QACE,KAAK,CAAC,4CAA4C,CAAC,CAAC;QACpD,IAAI,CAAC,IAAI,GAAG,sCAAsC,CAAC;IACrD,CAAC;CACF;AAED,MAAM,kCAAkC,GACtC,IAAI,oCAAoC,EAAE,CAAC;AAE7C,MAAM,UAAU,sCAAsC,CACpD,KAAc;IAEd,OAAO,KAAK,KAAK,kCAAkC,CAAC;AACtD,CAAC;AAED,MAAM,UAAU,sCAAsC,CAAC,KAAc;IACnE,IAAI,sCAAsC,CAAC,KAAK,CAAC;QAAE,MAAM,KAAK,CAAC;AACjE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,wCAAwC,CAC5D,SAA2B;IAE3B,IAAI,CAAC;QACH,OAAO,MAAM,SAAS,EAAE,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,sCAAsC,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAC/D,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,mCAAmC,CACjD,YAAyC;IAEzC,IAAI,YAAY,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QAC/B,MAAM,kCAAkC,CAAC;IAC3C,CAAC;AACH,CAAC;AAED,MAAM,UAAU,sCAAsC,CACpD,MAAmD,EACnD,YAAyC;IAEzC,IAAI,CAAC,MAAM,IAAI,CAAC,YAAY;QAAE,OAAO,MAAM,CAAC;IAC5C,MAAM,KAAK,GACT,CAAC,SAA0C,EAAE,EAAE,CAC/C,KAAK,EAAE,KAA2C,EAAE,EAAE;QACpD,mCAAmC,CAAC,YAAY,CAAC,CAAC;QAClD,MAAM,SAAS,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;QAC5C,mCAAmC,CAAC,YAAY,CAAC,CAAC;IACpD,CAAC,CAAC;IACJ,MAAM,qBAAqB,GAAG,CAC5B,SAA0C,EACT,EAAE;QACnC,MAAM,OAAO,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE;YAC5B,GAAG,CAAC,SAAS,CAAC,YAAY;gBACxB,CAAC,CAAC;oBACE,YAAY,EAAE,KAAK,EAAE,KAAwC,EAAE,EAAE;wBAC/D,mCAAmC,CAAC,YAAY,CAAC,CAAC;wBAClD,MAAM,SAAS,CAAC,YAAY,EAAE,CAAC,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,CAAC;wBAC3D,mCAAmC,CAAC,YAAY,CAAC,CAAC;oBACpD,CAAC;iBACF;gBACH,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CAAC;IACL,CAAC,CAAC;IACF,OAAO,qBAAqB,CAAC,MAAM,CAAC,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,iCAAiC,CAO/C,KAAY;IACZ,OAAO;QACL,GAAG,KAAK;QACR,+BAA+B,EAAE,sCAAsC,CACrE,KAAK,CAAC,+BAA+B,EACrC,KAAK,CAAC,YAAY,CACnB;KACF,CAAC;AACJ,CAAC","sourcesContent":["import type {\n ReferencedPrincipalHead,\n VerifiedPrincipalPolicy,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport type { TrustedUserIdentity } from \"../trustedUserIdentity\";\n\nexport type ProjectionUserKey = TrustedUserIdentity;\n\nexport type ProjectionUserKeyResolver = (\n userId: string,\n) => Promise<ProjectionUserKey | null>;\n\nexport type PrincipalPolicyCache = Map<string, VerifiedPrincipalPolicy>;\n\nexport interface ReferencedPrincipalPolicyWarmRequest {\n readonly organizationId: string;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nexport interface PrincipalPolicyBundleCacheRequest {\n readonly bundles: readonly PrincipalPolicyBundleResponse[];\n readonly organizationId: string;\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nexport type PrincipalPolicyBundleCacher = (\n input: PrincipalPolicyBundleCacheRequest,\n) => Promise<void>;\n\nexport type ReferencedPrincipalPolicyWarmer = ((\n input: ReferencedPrincipalPolicyWarmRequest,\n) => Promise<void>) & {\n readonly cacheBundles?: PrincipalPolicyBundleCacher | undefined;\n};\n\nexport class ProjectionVerificationCancelledError extends Error {\n constructor() {\n super(\"Projection verification generation expired\");\n this.name = \"ProjectionVerificationCancelledError\";\n }\n}\n\nconst projectionVerificationCancellation =\n new ProjectionVerificationCancelledError();\n\nexport function isProjectionVerificationCancelledError(\n error: unknown,\n): error is ProjectionVerificationCancelledError {\n return error === projectionVerificationCancellation;\n}\n\nexport function rethrowProjectionVerificationCancelled(error: unknown): void {\n if (isProjectionVerificationCancelledError(error)) throw error;\n}\n\nexport async function nullOnProjectionVerificationCancellation<T>(\n operation: () => Promise<T>,\n): Promise<T | null> {\n try {\n return await operation();\n } catch (error) {\n if (isProjectionVerificationCancelledError(error)) return null;\n throw error;\n }\n}\n\nexport function assertProjectionVerificationCurrent(\n stillCurrent: (() => boolean) | undefined,\n): void {\n if (stillCurrent?.() === false) {\n throw projectionVerificationCancellation;\n }\n}\n\nexport function generationGuardedPrincipalPolicyWarmer(\n warmer: ReferencedPrincipalPolicyWarmer | undefined,\n stillCurrent: (() => boolean) | undefined,\n): ReferencedPrincipalPolicyWarmer | undefined {\n if (!warmer || !stillCurrent) return warmer;\n const guard =\n (operation: ReferencedPrincipalPolicyWarmer) =>\n async (input: ReferencedPrincipalPolicyWarmRequest) => {\n assertProjectionVerificationCurrent(stillCurrent);\n await operation({ ...input, stillCurrent });\n assertProjectionVerificationCurrent(stillCurrent);\n };\n const guardWithCapabilities = (\n operation: ReferencedPrincipalPolicyWarmer,\n ): ReferencedPrincipalPolicyWarmer => {\n const guarded = guard(operation);\n return Object.assign(guarded, {\n ...(operation.cacheBundles\n ? {\n cacheBundles: async (input: PrincipalPolicyBundleCacheRequest) => {\n assertProjectionVerificationCurrent(stillCurrent);\n await operation.cacheBundles?.({ ...input, stillCurrent });\n assertProjectionVerificationCurrent(stillCurrent);\n },\n }\n : {}),\n });\n };\n return guardWithCapabilities(warmer);\n}\n\nexport function withGenerationGuardedPolicyWarmer<\n Input extends {\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n },\n>(input: Input): Input {\n return {\n ...input,\n warmReferencedPrincipalPolicies: generationGuardedPrincipalPolicyWarmer(\n input.warmReferencedPrincipalPolicies,\n input.stillCurrent,\n ),\n };\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ReferencedPrincipalHead,\n VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../principals/principalPolicyEvidence\";\nimport type { TrustedUserIdentity } from \"../trustedUserIdentity\";\n\nexport type ProjectionUserKey = TrustedUserIdentity;\n\nexport type ProjectionUserKeyResolver = (\n userId: string,\n) => Promise<ProjectionUserKey | null>;\n\nexport type PrincipalPolicyCache = Map<string, PrincipalPolicyCurrentEvidence>;\n\nexport interface PrincipalPolicyResolveRequest {\n /** Identity of one projection collection, never caller-supplied evidence. */\n readonly recoveryBatch?: object | undefined;\n readonly organizationId: string;\n readonly reference: ReferencedPrincipalHead;\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nexport interface ResolvedPrincipalPolicyEvidence {\n readonly stillCurrent: () => boolean;\n readonly organizationId: string;\n readonly policy: VerifiedPrincipalPolicyCurrent;\n readonly dependencies: readonly VerifiedPrincipalPolicyCurrent[];\n}\n\nexport interface ReferencedPrincipalPolicyWarmRequest {\n readonly organizationId: string;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nexport interface PrincipalPolicyBundleCacheRequest {\n readonly bundles: readonly PrincipalPolicyBundleResponse[];\n readonly organizationId: string;\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nexport type PrincipalPolicyBundleCacher = (\n input: PrincipalPolicyBundleCacheRequest,\n) => Promise<void>;\n\nexport type ReferencedPrincipalPolicyWarmer = ((\n input: ReferencedPrincipalPolicyWarmRequest,\n) => Promise<void>) & {\n readonly cacheBundles?: PrincipalPolicyBundleCacher | undefined;\n readonly resolveReference?:\n | ((\n input: PrincipalPolicyResolveRequest,\n ) => Promise<ResolvedPrincipalPolicyEvidence>)\n | undefined;\n};\n\nexport class ProjectionVerificationCancelledError extends Error {\n constructor() {\n super(\"Projection verification generation expired\");\n this.name = \"ProjectionVerificationCancelledError\";\n }\n}\n\nconst projectionVerificationCancellation =\n new ProjectionVerificationCancelledError();\n\nexport function isProjectionVerificationCancelledError(\n error: unknown,\n): error is ProjectionVerificationCancelledError {\n return error === projectionVerificationCancellation;\n}\n\nexport function rethrowProjectionVerificationCancelled(error: unknown): void {\n if (isProjectionVerificationCancelledError(error)) throw error;\n}\n\nexport async function nullOnProjectionVerificationCancellation<T>(\n operation: () => Promise<T>,\n): Promise<T | null> {\n try {\n return await operation();\n } catch (error) {\n if (isProjectionVerificationCancelledError(error)) return null;\n throw error;\n }\n}\n\nexport function assertProjectionVerificationCurrent(\n stillCurrent: (() => boolean) | undefined,\n): void {\n if (stillCurrent?.() === false) {\n throw projectionVerificationCancellation;\n }\n}\n\nexport function generationGuardedPrincipalPolicyWarmer(\n warmer: ReferencedPrincipalPolicyWarmer | undefined,\n stillCurrent: (() => boolean) | undefined,\n): ReferencedPrincipalPolicyWarmer | undefined {\n if (!warmer || !stillCurrent) return warmer;\n const guard =\n (operation: ReferencedPrincipalPolicyWarmer) =>\n async (input: ReferencedPrincipalPolicyWarmRequest) => {\n assertProjectionVerificationCurrent(stillCurrent);\n await operation({ ...input, stillCurrent });\n assertProjectionVerificationCurrent(stillCurrent);\n };\n const guardWithCapabilities = (\n operation: ReferencedPrincipalPolicyWarmer,\n ): ReferencedPrincipalPolicyWarmer => {\n const guarded = guard(operation);\n const resolve = operation.resolveReference;\n return Object.assign(guarded, {\n ...(resolve\n ? {\n resolveReference: async (input: PrincipalPolicyResolveRequest) => {\n const current = () =>\n stillCurrent() && input.stillCurrent?.() !== false;\n assertProjectionVerificationCurrent(current);\n const result = await resolve({ ...input, stillCurrent: current });\n assertProjectionVerificationCurrent(current);\n return result;\n },\n }\n : {}),\n ...(operation.cacheBundles\n ? {\n cacheBundles: async (input: PrincipalPolicyBundleCacheRequest) => {\n assertProjectionVerificationCurrent(stillCurrent);\n await operation.cacheBundles?.({ ...input, stillCurrent });\n assertProjectionVerificationCurrent(stillCurrent);\n },\n }\n : {}),\n });\n };\n return guardWithCapabilities(warmer);\n}\n\nexport function withGenerationGuardedPolicyWarmer<\n Input extends {\n readonly stillCurrent?: (() => boolean) | undefined;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n },\n>(input: Input): Input {\n return {\n ...input,\n warmReferencedPrincipalPolicies: generationGuardedPrincipalPolicyWarmer(\n input.warmReferencedPrincipalPolicies,\n input.stillCurrent,\n ),\n };\n}\n"]}
@@ -1,5 +1,6 @@
1
- import { KeyingVerificationError, } from "../../internal/crypto/index.js";
1
+ import { KeyingVerificationError } from "../../internal/crypto/index.js";
2
2
  import { eq } from "drizzle-orm";
3
+ import { principalPolicyEvidenceEntries, } from "../principals/principalPolicyEvidence.js";
3
4
  import { organizationFounders } from "../sqlite/organizationFounderSchema.js";
4
5
  import { keyingCheckpointTables } from "../sqlite/schema.js";
5
6
  import { getClientSQLitePersistenceRuntime } from "../sqlite/sqlitePersistenceRuntime.js";
@@ -22,7 +23,7 @@ export async function loadOrganizationFounder(execSql, organizationId) {
22
23
  }
23
24
  /** Pin verified genesis, never a later administrator or a folder's creator. */
24
25
  export async function rememberOrganizationFounder(input) {
25
- const genesis = input.organization.history?.find(({ state }) => state.version === 1)?.state;
26
+ const genesis = principalPolicyEvidenceEntries(input.organization).find(({ state }) => state.version === 1)?.state;
26
27
  if (genesis?.principalType !== "organization" ||
27
28
  genesis.prevStateHash !== null)
28
29
  throw new KeyingVerificationError("missing_dependency", "Organization founder requires verified genesis");
@@ -1 +1 @@
1
- {"version":3,"file":"organizationFounderPersistence.js","sourceRoot":"","sources":["organizationFounderPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type AnyVerifiedPrincipalPolicy,\n KeyingVerificationError,\n} from \"@tearleads/crypto\";\nimport { eq } from \"drizzle-orm\";\nimport { organizationFounders } from \"../sqlite/organizationFounderSchema\";\nimport { keyingCheckpointTables } from \"../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nfunction assertSameFounder(\n stored: typeof organizationFounders.$inferSelect,\n founder: typeof organizationFounders.$inferInsert,\n): void {\n if (\n stored.userId !== founder.userId ||\n stored.signingKeyFingerprint !== founder.signingKeyFingerprint ||\n stored.genesisStateHash !== founder.genesisStateHash\n )\n throw new KeyingVerificationError(\n \"equivocation\",\n \"Organization founder conflicts with its durable genesis binding\",\n );\n}\n\nexport async function loadOrganizationFounder(\n execSql: ExecSql,\n organizationId: string,\n): Promise<typeof organizationFounders.$inferSelect | null> {\n await ensureSqlTables(execSql, keyingCheckpointTables);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const [stored] = await runtime.db\n .select()\n .from(organizationFounders)\n .where(eq(organizationFounders.organizationId, organizationId))\n .limit(1);\n return stored ?? null;\n}\n\n/** Pin verified genesis, never a later administrator or a folder's creator. */\nexport async function rememberOrganizationFounder(input: {\n readonly execSql: ExecSql;\n readonly organization: AnyVerifiedPrincipalPolicy;\n}): Promise<void> {\n const genesis = input.organization.history?.find(\n ({ state }) => state.version === 1,\n )?.state;\n if (\n genesis?.principalType !== \"organization\" ||\n genesis.prevStateHash !== null\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization founder requires verified genesis\",\n );\n const founder = {\n organizationId: genesis.principalId,\n userId: genesis.signerUserId,\n signingKeyFingerprint: genesis.signerUserKeyFingerprint,\n genesisStateHash: genesis.stateHash,\n };\n const held = await loadOrganizationFounder(\n input.execSql,\n founder.organizationId,\n );\n if (held) {\n assertSameFounder(held, founder);\n return;\n }\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n await runtime.transaction(\n async (tx) => {\n const [stored] = await tx\n .select()\n .from(organizationFounders)\n .where(eq(organizationFounders.organizationId, founder.organizationId))\n .limit(1);\n if (stored) {\n assertSameFounder(stored, founder);\n return;\n }\n await tx\n .insert(organizationFounders)\n .values(founder)\n .onConflictDoNothing()\n .run();\n },\n { behavior: \"immediate\" },\n );\n}\n"]}
1
+ {"version":3,"file":"organizationFounderPersistence.js","sourceRoot":"","sources":["organizationFounderPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { KeyingVerificationError } from \"@tearleads/crypto\";\nimport { eq } from \"drizzle-orm\";\nimport {\n type PrincipalPolicyCheckpointEvidence,\n principalPolicyEvidenceEntries,\n} from \"../principals/principalPolicyEvidence\";\nimport { organizationFounders } from \"../sqlite/organizationFounderSchema\";\nimport { keyingCheckpointTables } from \"../sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nfunction assertSameFounder(\n stored: typeof organizationFounders.$inferSelect,\n founder: typeof organizationFounders.$inferInsert,\n): void {\n if (\n stored.userId !== founder.userId ||\n stored.signingKeyFingerprint !== founder.signingKeyFingerprint ||\n stored.genesisStateHash !== founder.genesisStateHash\n )\n throw new KeyingVerificationError(\n \"equivocation\",\n \"Organization founder conflicts with its durable genesis binding\",\n );\n}\n\nexport async function loadOrganizationFounder(\n execSql: ExecSql,\n organizationId: string,\n): Promise<typeof organizationFounders.$inferSelect | null> {\n await ensureSqlTables(execSql, keyingCheckpointTables);\n const runtime = getClientSQLitePersistenceRuntime(execSql);\n const [stored] = await runtime.db\n .select()\n .from(organizationFounders)\n .where(eq(organizationFounders.organizationId, organizationId))\n .limit(1);\n return stored ?? null;\n}\n\n/** Pin verified genesis, never a later administrator or a folder's creator. */\nexport async function rememberOrganizationFounder(input: {\n readonly execSql: ExecSql;\n readonly organization: PrincipalPolicyCheckpointEvidence;\n}): Promise<void> {\n const genesis = principalPolicyEvidenceEntries(input.organization).find(\n ({ state }) => state.version === 1,\n )?.state;\n if (\n genesis?.principalType !== \"organization\" ||\n genesis.prevStateHash !== null\n )\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Organization founder requires verified genesis\",\n );\n const founder = {\n organizationId: genesis.principalId,\n userId: genesis.signerUserId,\n signingKeyFingerprint: genesis.signerUserKeyFingerprint,\n genesisStateHash: genesis.stateHash,\n };\n const held = await loadOrganizationFounder(\n input.execSql,\n founder.organizationId,\n );\n if (held) {\n assertSameFounder(held, founder);\n return;\n }\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n await runtime.transaction(\n async (tx) => {\n const [stored] = await tx\n .select()\n .from(organizationFounders)\n .where(eq(organizationFounders.organizationId, founder.organizationId))\n .limit(1);\n if (stored) {\n assertSameFounder(stored, founder);\n return;\n }\n await tx\n .insert(organizationFounders)\n .values(founder)\n .onConflictDoNothing()\n .run();\n },\n { behavior: \"immediate\" },\n );\n}\n"]}
@@ -0,0 +1,91 @@
1
+ import { compareCanonicalStrings, KeyingVerificationError, PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT, principalHistoryIndexLeaf, resolvePrincipalHistoryIndexProof, } from "../../internal/crypto/index.js";
2
+ import { isPrincipalPolicyStateChainEntryResponse, } from "../../internal/validators/response/index.js";
3
+ import { and, eq } from "drizzle-orm";
4
+ import { principalHistoryEntries, principalHistoryEvidenceTables, principalHistoryNodes, } from "../sqlite/principalHistoryEvidenceSchema.js";
5
+ import { getClientSQLitePersistenceRuntime, } from "../sqlite/sqlitePersistenceRuntime.js";
6
+ import { ensureSqlTables } from "../sqlite/sqlSchema.js";
7
+ /** Prepare only a page accepted by the signature/authorization verifier. */
8
+ export async function preparePrincipalHistoryEvidencePage(input) {
9
+ if (input.entries.length > PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT ||
10
+ input.nodes.length > 2 * PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT)
11
+ throw new KeyingVerificationError("invalid_shape", "Principal evidence page exceeds its batch budget");
12
+ const owned = structuredClone(input);
13
+ return {
14
+ ...owned,
15
+ entries: await Promise.all(owned.entries.map(async (entry) => ({
16
+ leafHash: await principalHistoryIndexLeaf(entry.state),
17
+ entryJson: JSON.stringify(entry),
18
+ }))),
19
+ };
20
+ }
21
+ /** Publish in the same guarded transaction as the accepted page's progress. */
22
+ export async function writePrincipalHistoryEvidencePage(tx, page) {
23
+ const scope = { scopeId: page.scopeId, organizationId: page.organizationId };
24
+ for (const entry of [...page.entries].sort((a, b) => compareCanonicalStrings(a.leafHash, b.leafHash))) {
25
+ const row = { ...scope, ...entry };
26
+ await tx
27
+ .insert(principalHistoryEntries)
28
+ .values(row)
29
+ .onConflictDoUpdate({
30
+ target: [
31
+ principalHistoryEntries.scopeId,
32
+ principalHistoryEntries.leafHash,
33
+ ],
34
+ set: row,
35
+ })
36
+ .run();
37
+ }
38
+ for (const node of [...page.nodes].sort((a, b) => compareCanonicalStrings(a.hash, b.hash))) {
39
+ const row = { ...scope, ...node };
40
+ await tx
41
+ .insert(principalHistoryNodes)
42
+ .values(row)
43
+ .onConflictDoUpdate({
44
+ target: [principalHistoryNodes.scopeId, principalHistoryNodes.hash],
45
+ set: row,
46
+ })
47
+ .run();
48
+ }
49
+ }
50
+ /** Returns untrusted material. The caller must verify it against the issued root. */
51
+ export async function loadPrincipalHistoryReference(input) {
52
+ await ensureSqlTables(input.execSql, principalHistoryEvidenceTables);
53
+ const { db } = getClientSQLitePersistenceRuntime(input.execSql);
54
+ const resolved = await resolvePrincipalHistoryIndexProof({
55
+ rootHash: input.history.indexRootHash,
56
+ treeSize: input.history.currentEntry.state.version,
57
+ version: input.version,
58
+ readNode: async (hash) => {
59
+ const [row] = await db
60
+ .select()
61
+ .from(principalHistoryNodes)
62
+ .where(and(eq(principalHistoryNodes.scopeId, input.scopeId), eq(principalHistoryNodes.hash, hash)))
63
+ .limit(1);
64
+ return row ?? null;
65
+ },
66
+ });
67
+ const [row] = await db
68
+ .select()
69
+ .from(principalHistoryEntries)
70
+ .where(and(eq(principalHistoryEntries.scopeId, input.scopeId), eq(principalHistoryEntries.leafHash, resolved.leafHash)))
71
+ .limit(1);
72
+ let entry;
73
+ try {
74
+ entry = row ? JSON.parse(row.entryJson) : null;
75
+ }
76
+ catch {
77
+ entry = null;
78
+ }
79
+ if (!isPrincipalPolicyStateChainEntryResponse(entry))
80
+ throw new KeyingVerificationError("missing_dependency", "Principal history entry is missing or corrupt");
81
+ const reference = input.expectedReference ?? {
82
+ principalType: entry.state.principalType,
83
+ principalId: entry.state.principalId,
84
+ version: entry.state.version,
85
+ keyEpoch: entry.state.keyEpoch,
86
+ stateHash: entry.state.stateHash,
87
+ keyFingerprint: entry.state.keyFingerprint,
88
+ };
89
+ return { reference, entry, proof: resolved.proof };
90
+ }
91
+ //# sourceMappingURL=principalHistoryEvidencePersistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalHistoryEvidencePersistence.js","sourceRoot":"","sources":["principalHistoryEvidencePersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n compareCanonicalStrings,\n KeyingVerificationError,\n PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT,\n type PrincipalHistoryIndexNode,\n type PrincipalPolicyHistoryReferenceProof,\n principalHistoryIndexLeaf,\n type ReferencedPrincipalHead,\n resolvePrincipalHistoryIndexProof,\n type VerifiedPrincipalPolicyHistory,\n} from \"@tearleads/crypto\";\nimport {\n isPrincipalPolicyStateChainEntryResponse,\n type PrincipalPolicyStateChainEntryResponse,\n} from \"@tearleads/validators/response\";\nimport { and, eq } from \"drizzle-orm\";\nimport {\n principalHistoryEntries,\n principalHistoryEvidenceTables,\n principalHistoryNodes,\n} from \"../sqlite/principalHistoryEvidenceSchema\";\nimport {\n type ClientSQLiteTransactionScope,\n getClientSQLitePersistenceRuntime,\n} from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nexport interface PrincipalHistoryEvidencePage {\n readonly scopeId: string;\n readonly organizationId: string;\n readonly entries: readonly {\n readonly leafHash: string;\n readonly entryJson: string;\n }[];\n readonly nodes: readonly PrincipalHistoryIndexNode[];\n}\n\n/** Prepare only a page accepted by the signature/authorization verifier. */\nexport async function preparePrincipalHistoryEvidencePage(input: {\n readonly scopeId: string;\n readonly organizationId: string;\n readonly entries: readonly PrincipalPolicyStateChainEntryResponse[];\n readonly nodes: readonly PrincipalHistoryIndexNode[];\n}): Promise<PrincipalHistoryEvidencePage> {\n if (\n input.entries.length > PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT ||\n input.nodes.length > 2 * PRINCIPAL_HISTORY_PAGE_ENTRY_LIMIT\n )\n throw new KeyingVerificationError(\n \"invalid_shape\",\n \"Principal evidence page exceeds its batch budget\",\n );\n const owned = structuredClone(input);\n return {\n ...owned,\n entries: await Promise.all(\n owned.entries.map(async (entry) => ({\n leafHash: await principalHistoryIndexLeaf(entry.state),\n entryJson: JSON.stringify(entry),\n })),\n ),\n };\n}\n\n/** Publish in the same guarded transaction as the accepted page's progress. */\nexport async function writePrincipalHistoryEvidencePage(\n tx: ClientSQLiteTransactionScope,\n page: PrincipalHistoryEvidencePage,\n): Promise<void> {\n const scope = { scopeId: page.scopeId, organizationId: page.organizationId };\n for (const entry of [...page.entries].sort((a, b) =>\n compareCanonicalStrings(a.leafHash, b.leafHash),\n )) {\n const row = { ...scope, ...entry };\n await tx\n .insert(principalHistoryEntries)\n .values(row)\n .onConflictDoUpdate({\n target: [\n principalHistoryEntries.scopeId,\n principalHistoryEntries.leafHash,\n ],\n set: row,\n })\n .run();\n }\n for (const node of [...page.nodes].sort((a, b) =>\n compareCanonicalStrings(a.hash, b.hash),\n )) {\n const row = { ...scope, ...node };\n await tx\n .insert(principalHistoryNodes)\n .values(row)\n .onConflictDoUpdate({\n target: [principalHistoryNodes.scopeId, principalHistoryNodes.hash],\n set: row,\n })\n .run();\n }\n}\n\n/** Returns untrusted material. The caller must verify it against the issued root. */\nexport async function loadPrincipalHistoryReference(input: {\n readonly execSql: ExecSql;\n readonly scopeId: string;\n readonly history: VerifiedPrincipalPolicyHistory;\n readonly version: number;\n readonly expectedReference?: ReferencedPrincipalHead | undefined;\n}): Promise<PrincipalPolicyHistoryReferenceProof> {\n await ensureSqlTables(input.execSql, principalHistoryEvidenceTables);\n const { db } = getClientSQLitePersistenceRuntime(input.execSql);\n const resolved = await resolvePrincipalHistoryIndexProof({\n rootHash: input.history.indexRootHash,\n treeSize: input.history.currentEntry.state.version,\n version: input.version,\n readNode: async (hash) => {\n const [row] = await db\n .select()\n .from(principalHistoryNodes)\n .where(\n and(\n eq(principalHistoryNodes.scopeId, input.scopeId),\n eq(principalHistoryNodes.hash, hash),\n ),\n )\n .limit(1);\n return row ?? null;\n },\n });\n const [row] = await db\n .select()\n .from(principalHistoryEntries)\n .where(\n and(\n eq(principalHistoryEntries.scopeId, input.scopeId),\n eq(principalHistoryEntries.leafHash, resolved.leafHash),\n ),\n )\n .limit(1);\n let entry: unknown;\n try {\n entry = row ? JSON.parse(row.entryJson) : null;\n } catch {\n entry = null;\n }\n if (!isPrincipalPolicyStateChainEntryResponse(entry))\n throw new KeyingVerificationError(\n \"missing_dependency\",\n \"Principal history entry is missing or corrupt\",\n );\n const reference = input.expectedReference ?? {\n principalType: entry.state.principalType,\n principalId: entry.state.principalId,\n version: entry.state.version,\n keyEpoch: entry.state.keyEpoch,\n stateHash: entry.state.stateHash,\n keyFingerprint: entry.state.keyFingerprint,\n };\n return { reference, entry, proof: resolved.proof };\n}\n"]}
@@ -0,0 +1,52 @@
1
+ import { and, eq } from "drizzle-orm";
2
+ import { assertProjectionVerificationCurrent } from "../keyingProjectionVerification/types.js";
3
+ import { principalHistoryEvidenceTables, principalHistoryPrefixes, } from "../sqlite/principalHistoryEvidenceSchema.js";
4
+ import { getClientSQLitePersistenceRuntime } from "../sqlite/sqlitePersistenceRuntime.js";
5
+ import { ensureSqlTables } from "../sqlite/sqlSchema.js";
6
+ export async function loadPrincipalHistoryPrefix(execSql, scopeId) {
7
+ await ensureSqlTables(execSql, principalHistoryEvidenceTables);
8
+ const { db } = getClientSQLitePersistenceRuntime(execSql);
9
+ const [prefix] = await db
10
+ .select()
11
+ .from(principalHistoryPrefixes)
12
+ .where(eq(principalHistoryPrefixes.scopeId, scopeId))
13
+ .limit(1);
14
+ return prefix ?? null;
15
+ }
16
+ /** Keep one completed prefix per principal/trust scope; older readers cannot replace it. */
17
+ export async function savePrincipalHistoryPrefix(input) {
18
+ const prefix = { ...input.prefix };
19
+ await ensureSqlTables(input.execSql, principalHistoryEvidenceTables);
20
+ const runtime = getClientSQLitePersistenceRuntime(input.execSql);
21
+ const result = await runtime.guardedTransaction(async (tx) => {
22
+ const [previous] = await tx
23
+ .select()
24
+ .from(principalHistoryPrefixes)
25
+ .where(eq(principalHistoryPrefixes.scopeId, prefix.scopeId))
26
+ .limit(1);
27
+ if (previous && previous.version > prefix.version)
28
+ return;
29
+ await tx
30
+ .insert(principalHistoryPrefixes)
31
+ .values(prefix)
32
+ .onConflictDoUpdate({
33
+ target: principalHistoryPrefixes.scopeId,
34
+ set: prefix,
35
+ })
36
+ .run();
37
+ }, input.stillCurrent, { behavior: "immediate" });
38
+ assertProjectionVerificationCurrent(() => result.committed);
39
+ }
40
+ /** Invalid hints are disposable, but a losing reader must preserve a newer hint. */
41
+ export async function discardPrincipalHistoryPrefix(input) {
42
+ const prefix = { ...input.prefix };
43
+ const runtime = getClientSQLitePersistenceRuntime(input.execSql);
44
+ const result = await runtime.guardedTransaction(async (tx) => {
45
+ await tx
46
+ .delete(principalHistoryPrefixes)
47
+ .where(and(eq(principalHistoryPrefixes.scopeId, prefix.scopeId), eq(principalHistoryPrefixes.progress, prefix.progress)))
48
+ .run();
49
+ }, input.stillCurrent, { behavior: "immediate" });
50
+ assertProjectionVerificationCurrent(() => result.committed);
51
+ }
52
+ //# sourceMappingURL=principalHistoryPrefixPersistence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"principalHistoryPrefixPersistence.js","sourceRoot":"","sources":["principalHistoryPrefixPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { and, eq } from \"drizzle-orm\";\nimport { assertProjectionVerificationCurrent } from \"../keyingProjectionVerification/types\";\nimport {\n principalHistoryEvidenceTables,\n principalHistoryPrefixes,\n} from \"../sqlite/principalHistoryEvidenceSchema\";\nimport { getClientSQLitePersistenceRuntime } from \"../sqlite/sqlitePersistenceRuntime\";\nimport { type ExecSql, ensureSqlTables } from \"../sqlite/sqlSchema\";\n\nexport type PrincipalHistoryPrefix =\n typeof principalHistoryPrefixes.$inferSelect;\n\nexport async function loadPrincipalHistoryPrefix(\n execSql: ExecSql,\n scopeId: string,\n) {\n await ensureSqlTables(execSql, principalHistoryEvidenceTables);\n const { db } = getClientSQLitePersistenceRuntime(execSql);\n const [prefix] = await db\n .select()\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, scopeId))\n .limit(1);\n return prefix ?? null;\n}\n\n/** Keep one completed prefix per principal/trust scope; older readers cannot replace it. */\nexport async function savePrincipalHistoryPrefix(input: {\n readonly execSql: ExecSql;\n readonly prefix: PrincipalHistoryPrefix;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const prefix = { ...input.prefix };\n await ensureSqlTables(input.execSql, principalHistoryEvidenceTables);\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n const [previous] = await tx\n .select()\n .from(principalHistoryPrefixes)\n .where(eq(principalHistoryPrefixes.scopeId, prefix.scopeId))\n .limit(1);\n if (previous && previous.version > prefix.version) return;\n await tx\n .insert(principalHistoryPrefixes)\n .values(prefix)\n .onConflictDoUpdate({\n target: principalHistoryPrefixes.scopeId,\n set: prefix,\n })\n .run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n\n/** Invalid hints are disposable, but a losing reader must preserve a newer hint. */\nexport async function discardPrincipalHistoryPrefix(input: {\n readonly execSql: ExecSql;\n readonly prefix: PrincipalHistoryPrefix;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const prefix = { ...input.prefix };\n const runtime = getClientSQLitePersistenceRuntime(input.execSql);\n const result = await runtime.guardedTransaction(\n async (tx) => {\n await tx\n .delete(principalHistoryPrefixes)\n .where(\n and(\n eq(principalHistoryPrefixes.scopeId, prefix.scopeId),\n eq(principalHistoryPrefixes.progress, prefix.progress),\n ),\n )\n .run();\n },\n input.stillCurrent,\n { behavior: \"immediate\" },\n );\n assertProjectionVerificationCurrent(() => result.committed);\n}\n"]}
@@ -1,8 +1,10 @@
1
1
  import { and, eq } from "drizzle-orm";
2
2
  import { assertProjectionVerificationCurrent } from "../keyingProjectionVerification/types.js";
3
+ import { principalHistoryEvidenceTables } from "../sqlite/principalHistoryEvidenceSchema.js";
3
4
  import { principalHistoryStages, principalHistoryStageTables, } from "../sqlite/principalHistoryStageSchema.js";
4
5
  import { getClientSQLitePersistenceRuntime } from "../sqlite/sqlitePersistenceRuntime.js";
5
6
  import { ensureSqlTables } from "../sqlite/sqlSchema.js";
7
+ import { writePrincipalHistoryEvidencePage, } from "./principalHistoryEvidencePersistence.js";
6
8
  class PrincipalHistoryStageChangedError extends Error {
7
9
  code = "principal_history_stage_changed";
8
10
  constructor() {
@@ -20,10 +22,14 @@ export async function loadPrincipalHistoryStage(execSql, id) {
20
22
  .limit(1);
21
23
  return row ?? null;
22
24
  }
23
- /** The checked evidence lives inside authenticated progress, in the same row. */
25
+ /** Publish accepted entries and index nodes atomically with authenticated progress. */
24
26
  export async function savePrincipalHistoryStage(input) {
25
27
  const stage = { ...input.stage };
26
- await ensureSqlTables(input.execSql, principalHistoryStageTables);
28
+ const evidence = structuredClone(input.evidence);
29
+ await ensureSqlTables(input.execSql, [
30
+ ...principalHistoryStageTables,
31
+ ...principalHistoryEvidenceTables,
32
+ ]);
27
33
  const runtime = getClientSQLitePersistenceRuntime(input.execSql);
28
34
  const saved = await runtime.guardedTransaction(async (tx) => {
29
35
  const [previous] = await tx
@@ -33,6 +39,7 @@ export async function savePrincipalHistoryStage(input) {
33
39
  .limit(1);
34
40
  if ((previous?.progress ?? null) !== input.previousProgress)
35
41
  throw new PrincipalHistoryStageChangedError();
42
+ await writePrincipalHistoryEvidencePage(tx, evidence);
36
43
  await tx
37
44
  .insert(principalHistoryStages)
38
45
  .values(stage)