@tearleads/client-sdk 0.1.37 → 0.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/Tearleads.d.ts +3 -0
- package/client/Tearleads.js +20 -12
- package/client/Tearleads.js.map +1 -1
- package/client/organizations/organizationGroupHistory.js +1 -1
- package/client/organizations/organizationGroupHistory.js.map +1 -1
- package/client/organizations/organizationHistory.js +1 -1
- package/client/organizations/organizationHistory.js.map +1 -1
- package/client/session/index.js +2 -2
- package/client/session/index.js.map +1 -1
- package/client/session/sessionOrganizationCreation.js +1 -0
- package/client/session/sessionOrganizationCreation.js.map +1 -1
- package/client/session/sessionTypes.d.ts +3 -0
- package/client/session/sessionTypes.js.map +1 -1
- package/client/workflowRuntime.d.ts +2 -0
- package/client/workflowRuntime.js +34 -16
- package/client/workflowRuntime.js.map +1 -1
- package/data/keyingProjectionVerification/principalPolicyVerification.js +1 -2
- package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
- package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js +39 -51
- package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js.map +1 -1
- package/data/keyingProjectionVerification/types.d.ts +1 -1
- package/data/keyingProjectionVerification/types.js.map +1 -1
- package/data/persistence/documents/documentDiscoveryEvidencePersistence.d.ts +16 -0
- package/data/persistence/documents/documentDiscoveryEvidencePersistence.js +23 -0
- package/data/persistence/documents/documentDiscoveryEvidencePersistence.js.map +1 -1
- package/data/persistence/organizations/organizationAccessRevocationPersistence.js +4 -0
- package/data/persistence/organizations/organizationAccessRevocationPersistence.js.map +1 -1
- package/data/persistence/organizations/organizationReadModelPersistence.js +7 -1
- package/data/persistence/organizations/organizationReadModelPersistence.js.map +1 -1
- package/data/principals/principalRecoveryEpoch.js +18 -0
- package/data/principals/principalRecoveryEpoch.js.map +1 -0
- package/data/trustedUserIdentity/index.d.ts +1 -1
- package/data/trustedUserIdentity/index.js +1 -1
- package/data/trustedUserIdentity/index.js.map +1 -1
- package/data/trustedUserIdentity/service.d.ts +12 -1
- package/data/trustedUserIdentity/service.js +27 -3
- package/data/trustedUserIdentity/service.js.map +1 -1
- package/package.json +1 -1
- package/workflows/organizations/createOrganization.d.ts +3 -0
- package/workflows/organizations/createOrganization.js +1 -0
- package/workflows/organizations/createOrganization.js.map +1 -1
- package/workflows/organizations/currentGroupPolicyMutationContext.js +5 -5
- package/workflows/organizations/currentGroupPolicyMutationContext.js.map +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js +1 -1
- package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -1
- package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
- package/workflows/principals/principalRecoveryMemo.d.ts +9 -4
- package/workflows/principals/principalRecoveryMemo.js +94 -34
- package/workflows/principals/principalRecoveryMemo.js.map +1 -1
- package/workflows/principals/principalRecoveryMemoValidity.js +33 -0
- package/workflows/principals/principalRecoveryMemoValidity.js.map +1 -0
- package/workflows/principals/principalRecoveryOutage.js +2 -2
- package/workflows/principals/principalRecoveryOutage.js.map +1 -1
- package/workflows/principals/recoverCurrentOrganizationPolicy.js +8 -3
- package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -1
- package/workflows/principals/recoverPrincipalPolicyHistory.js +42 -8
- package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/recoverPublicPrincipalHistory.js +5 -5
- package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +9 -2
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +8 -2
- package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
- package/workflows/principals/runtimePolicyRecovery.js +4 -1
- package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
- package/workflows/principals/runtimePolicyWarmer.js +12 -4
- package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
- package/workflows/registration/organizationProvisioningPersistence.d.ts +3 -0
- package/workflows/registration/organizationProvisioningPersistence.js +27 -1
- package/workflows/registration/organizationProvisioningPersistence.js.map +1 -1
- package/workflows/registration/persistRegistrationBootstrap.d.ts +3 -0
- package/workflows/registration/persistRegistrationBootstrap.js +7 -1
- package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
- package/workflows/registration/provisionedPrincipalHistory.d.ts +45 -0
- package/workflows/registration/provisionedPrincipalHistory.js +104 -0
- package/workflows/registration/provisionedPrincipalHistory.js.map +1 -0
- package/workflows/registration/provisioningAcknowledgement.js +18 -0
- package/workflows/registration/provisioningAcknowledgement.js.map +1 -1
- package/workflows/registration/registerIdentity.d.ts +3 -0
- package/workflows/registration/registerIdentity.js +1 -0
- package/workflows/registration/registerIdentity.js.map +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { runWithSecurityIncidentReporting } from "../data/keyingProjectionVerification/error.js";
|
|
2
2
|
import { unavailableExecSql } from "../data/sqlite/sqlSchema.js";
|
|
3
|
-
import { createApiUserIdentitySource, createTrustedUserIdentityService, } from "../data/trustedUserIdentity/index.js";
|
|
3
|
+
import { createApiUserIdentitySource, createTrustedUserIdentityService, loadPinnedUserIdentity, } from "../data/trustedUserIdentity/index.js";
|
|
4
|
+
import { createProvisionedPrincipalHistoryPrimer, } from "../workflows/registration/provisionedPrincipalHistory.js";
|
|
4
5
|
import { createListenerSet } from "./listenerSet.js";
|
|
5
6
|
import { createPrincipalHistoryProtectionCustody, } from "./principalHistoryProtection.js";
|
|
6
7
|
import { createPrincipalMutationApiCustody, } from "./principalMutationApi.js";
|
|
@@ -33,23 +34,39 @@ function createRuntimeMutationApi(dependencies, readGeneration) {
|
|
|
33
34
|
},
|
|
34
35
|
});
|
|
35
36
|
}
|
|
37
|
+
function localIdentityCandidate(identity) {
|
|
38
|
+
const { encapsulationKeyPair, signingKeyPair } = identity;
|
|
39
|
+
if (!encapsulationKeyPair || !signingKeyPair)
|
|
40
|
+
return null;
|
|
41
|
+
return {
|
|
42
|
+
encapsulationPublicKey: encapsulationKeyPair.publicKey,
|
|
43
|
+
signingKeyFingerprint: identity.signingFingerprint,
|
|
44
|
+
signingPublicKey: signingKeyPair.signingPublicKey,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Priming reads the runtime's database, identity and trust pins; it pins nothing. */
|
|
48
|
+
function createRuntimeProvisioningPrimer(dependencies, bindLease, readyExecSql) {
|
|
49
|
+
return createProvisionedPrincipalHistoryPrimer({
|
|
50
|
+
bindLease,
|
|
51
|
+
execSqlFor: (database) => dependencies.database.client === database ? readyExecSql() : null,
|
|
52
|
+
loadPinnedIdentity: async (execSql, userId) => dependencies.identityTrustDomain
|
|
53
|
+
? loadPinnedUserIdentity({
|
|
54
|
+
execSql,
|
|
55
|
+
identityTrustDomain: dependencies.identityTrustDomain,
|
|
56
|
+
userId,
|
|
57
|
+
})
|
|
58
|
+
: null,
|
|
59
|
+
logError: dependencies.logError,
|
|
60
|
+
signingFingerprint: () => dependencies.identity.signingFingerprint,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
36
63
|
export function createRuntime(dependencies) {
|
|
64
|
+
const readyExecSql = () => dependencies.database.status === "ready"
|
|
65
|
+
? dependencies.database.requireExecSql("trusted user identity")
|
|
66
|
+
: null;
|
|
37
67
|
const trustedUserIdentityService = createTrustedUserIdentityService({
|
|
38
|
-
getExecSql:
|
|
39
|
-
|
|
40
|
-
: null,
|
|
41
|
-
getLocalIdentity: () => {
|
|
42
|
-
const encapsulationKeyPair = dependencies.identity.encapsulationKeyPair;
|
|
43
|
-
const signingKeyPair = dependencies.identity.signingKeyPair;
|
|
44
|
-
if (!encapsulationKeyPair || !signingKeyPair) {
|
|
45
|
-
return null;
|
|
46
|
-
}
|
|
47
|
-
return {
|
|
48
|
-
encapsulationPublicKey: encapsulationKeyPair.publicKey,
|
|
49
|
-
signingKeyFingerprint: dependencies.identity.signingFingerprint,
|
|
50
|
-
signingPublicKey: signingKeyPair.signingPublicKey,
|
|
51
|
-
};
|
|
52
|
-
},
|
|
68
|
+
getExecSql: readyExecSql,
|
|
69
|
+
getLocalIdentity: () => localIdentityCandidate(dependencies.identity),
|
|
53
70
|
getLocalUserId: () => dependencies.session.userId,
|
|
54
71
|
identityTrustDomain: dependencies.identityTrustDomain,
|
|
55
72
|
remoteSource: createApiUserIdentitySource(dependencies.api),
|
|
@@ -94,6 +111,7 @@ export function createRuntime(dependencies) {
|
|
|
94
111
|
organizationId: dependencies.session.organizationId,
|
|
95
112
|
}, () => trustedUserIdentityService.pinLocal(userId, candidate));
|
|
96
113
|
},
|
|
114
|
+
primeProvisionedPrincipalHistory: createRuntimeProvisioningPrimer(dependencies, historyProtection.bind, readyExecSql),
|
|
97
115
|
publicRuntime: {
|
|
98
116
|
get version() {
|
|
99
117
|
return runtimeSubscription.version;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workflowRuntime.js","sourceRoot":"","sources":["workflowRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { DocumentProjectorRegistry } from \"../data/documents/documentKinds\";\nimport type { DomainScope } from \"../data/domainScope\";\nimport { runWithSecurityIncidentReporting } from \"../data/keyingProjectionVerification/error\";\nimport type { PrincipalHistoryProtectionLease } from \"../data/principals/principalHistoryProtection\";\nimport type { SecurityIncidentReporter } from \"../data/securityIncidents\";\nimport { unavailableExecSql } from \"../data/sqlite/sqlSchema\";\nimport {\n createApiUserIdentitySource,\n createTrustedUserIdentityService,\n type LocalUserIdentityCandidate,\n type TrustedUserIdentityResolver,\n} from \"../data/trustedUserIdentity\";\nimport type { ContainerContentsRootAdopter } from \"../workflows/container-contents/runtime\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeGroups,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../workflows/runtimeInput\";\nimport type { Blobs } from \"./blobs\";\nimport type { Database } from \"./database\";\nimport type { Events } from \"./events\";\nimport type { Identity } from \"./identity\";\nimport { createListenerSet } from \"./listenerSet\";\nimport type { Network } from \"./network\";\nimport {\n createPrincipalHistoryProtectionCustody,\n type PrincipalHistoryKeyProvider,\n} from \"./principalHistoryProtection\";\nimport {\n createPrincipalMutationApiCustody,\n type PrincipalMutationApi,\n} from \"./principalMutationApi\";\nimport { adoptSessionRootContainer } from \"./rootContainerAdoption\";\nimport { acknowledgedSessionRoot } from \"./session/sessionRootAuthority\";\nimport type { Session, SessionSnapshot } from \"./session/sessionTypes\";\nimport type { SyncBillingGate } from \"./syncBillingGate\";\n\ntype HostWorkflowRuntimeUtilInput = Omit<\n WorkflowRuntimeUtilInput,\n \"reportSecurityIncident\"\n>;\n\nexport interface WorkflowRuntimeInput\n extends Omit<WorkflowRuntimeGroups, \"util\"> {\n readonly util: HostWorkflowRuntimeUtilInput;\n}\n\nexport type RuntimeListener = () => void;\n\nexport interface Runtime {\n readonly version: number;\n input(containerId?: string | null | undefined): WorkflowRuntimeInput;\n subscribe(listener: RuntimeListener): () => void;\n}\n\nexport interface InternalWorkflowRuntimeInput extends WorkflowRuntimeGroups {\n readonly apiClient: PrincipalMutationApi;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n}\n\nexport interface InternalRuntime {\n retirePrincipalHistoryProtection(): void;\n readonly sessionGeneration: number;\n readonly adoptRootContainer: ContainerContentsRootAdopter;\n readonly publicRuntime: Runtime;\n boundUserId(signingKeyFingerprint: string): Promise<string | null>;\n pinLocalUserIdentity(\n userId: string,\n candidate: LocalUserIdentityCandidate,\n ): Promise<void>;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\ninterface WorkflowRuntimeDependencies {\n api: ApiClient;\n blobs: Blobs;\n database: Database;\n documentProjectors: DocumentProjectorRegistry;\n events: Events;\n getDomainScope: () => DomainScope;\n identity: Identity;\n identityTrustDomain: string | null;\n log: (message: string) => void;\n logError: (message: string | Error, cause?: unknown) => void;\n network: Network;\n peerScope?: string | null;\n principalHistoryKeyProvider?: PrincipalHistoryKeyProvider | undefined;\n principalMutationTimeoutMs?: number | undefined;\n reportSecurityIncident: SecurityIncidentReporter;\n session: Session;\n syncBillingGate?: SyncBillingGate | undefined;\n}\n\nfunction createRuntimeMutationApi(\n dependencies: WorkflowRuntimeDependencies,\n readGeneration: () => number,\n) {\n return createPrincipalMutationApiCustody({\n api: dependencies.api,\n principalMutationTimeoutMs: dependencies.principalMutationTimeoutMs,\n readScope: () => {\n const { signingKeyPair, signingFingerprint } = dependencies.identity;\n const { userId, isAuthenticated } = dependencies.session;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !isAuthenticated ||\n !userId ||\n !signingKeyPair ||\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n database: dependencies.getDomainScope(),\n execSql: dependencies.database.requireExecSql(\"principal mutation\"),\n generation: readGeneration(),\n identityTrustDomain,\n signingFingerprint,\n signingKeyPair,\n userId,\n };\n },\n });\n}\n\nexport function createRuntime(\n dependencies: WorkflowRuntimeDependencies,\n): InternalRuntime {\n const trustedUserIdentityService = createTrustedUserIdentityService({\n getExecSql: () =>\n dependencies.database.status === \"ready\"\n ? dependencies.database.requireExecSql(\"trusted user identity\")\n : null,\n getLocalIdentity: () => {\n const encapsulationKeyPair = dependencies.identity.encapsulationKeyPair;\n const signingKeyPair = dependencies.identity.signingKeyPair;\n if (!encapsulationKeyPair || !signingKeyPair) {\n return null;\n }\n return {\n encapsulationPublicKey: encapsulationKeyPair.publicKey,\n signingKeyFingerprint: dependencies.identity.signingFingerprint,\n signingPublicKey: signingKeyPair.signingPublicKey,\n };\n },\n getLocalUserId: () => dependencies.session.userId,\n identityTrustDomain: dependencies.identityTrustDomain,\n remoteSource: createApiUserIdentitySource(dependencies.api),\n });\n const resolveTrustedUserIdentity: TrustedUserIdentityResolver = (userId) =>\n runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.resolve\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.resolve(userId),\n );\n const runtimeSubscription = createRuntimeSubscription(dependencies);\n const historyProtection = createPrincipalHistoryProtectionCustody({\n keyProvider: dependencies.principalHistoryKeyProvider,\n readScope: () => {\n const signingFingerprint = dependencies.identity.signingFingerprint;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n signingFingerprint,\n identityTrustDomain,\n database: dependencies.getDomainScope(),\n generation: runtimeSubscription.recoveryGeneration,\n };\n },\n });\n const runtimeInput = createRuntimeInputFactory(\n dependencies,\n resolveTrustedUserIdentity,\n historyProtection.bind,\n createRuntimeMutationApi(\n dependencies,\n () => runtimeSubscription.mutationGeneration,\n ).bind,\n );\n\n return {\n retirePrincipalHistoryProtection: historyProtection.retire,\n get sessionGeneration() {\n return runtimeSubscription.sessionGeneration;\n },\n adoptRootContainer: (input) =>\n adoptSessionRootContainer(dependencies, input),\n boundUserId: (signingKeyFingerprint) =>\n trustedUserIdentityService.boundUserId(signingKeyFingerprint),\n async pinLocalUserIdentity(userId, candidate) {\n await runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.pin_local\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.pinLocal(userId, candidate),\n );\n },\n publicRuntime: {\n get version() {\n return runtimeSubscription.version;\n },\n input: runtimeInput.hostInput,\n subscribe: runtimeSubscription.subscribe,\n },\n workflowInput: runtimeInput.workflowInput,\n };\n}\n\nfunction createRuntimeSubscription(dependencies: WorkflowRuntimeDependencies) {\n const listeners = createListenerSet();\n let version = 0;\n let sessionGeneration = 0;\n let recoveryGeneration = 0;\n let mutationGeneration = 0;\n let sessionSnapshot = dependencies.session.snapshot;\n const notifyListeners = () => {\n version += 1;\n listeners.notify();\n };\n\n const notifyAuthority = () => {\n recoveryGeneration += 1;\n mutationGeneration += 1;\n notifyListeners();\n };\n dependencies.database.subscribe(notifyAuthority);\n dependencies.events.subscribe(notifyListeners);\n dependencies.identity.subscribe(notifyAuthority);\n dependencies.network.subscribe(() => notifyListeners());\n dependencies.session.subscribe(() => {\n const next = dependencies.session.snapshot;\n if (sessionAuthorityChanged(sessionSnapshot, next)) {\n sessionGeneration += 1;\n recoveryGeneration += 1;\n }\n if (sessionScopeChanged(sessionSnapshot, next)) mutationGeneration += 1;\n sessionSnapshot = next;\n notifyListeners();\n });\n dependencies.syncBillingGate?.subscribe(notifyListeners);\n\n return {\n get mutationGeneration() {\n return mutationGeneration;\n },\n get recoveryGeneration() {\n return recoveryGeneration;\n },\n get sessionGeneration() {\n return sessionGeneration;\n },\n get version() {\n return version;\n },\n subscribe(listener: RuntimeListener): () => void {\n return listeners.subscribe(listener);\n },\n };\n}\n\ninterface RuntimeInputFactory {\n hostInput(containerId?: string | null | undefined): WorkflowRuntimeInput;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\nfunction sessionAuthInput({\n session,\n identity,\n}: WorkflowRuntimeDependencies): WorkflowRuntimeAuthInput {\n const signingFingerprint = identity.snapshot.signingFingerprint;\n return {\n defaultOrganizationId: session.defaultOrganizationId,\n rootContainerId: acknowledgedSessionRoot(session, signingFingerprint),\n isAuthenticated: session.isAuthenticated,\n isRoot: session.isRoot,\n organizationId: session.organizationId,\n userId: session.userId,\n };\n}\n\n/** Fields whose change invalidates work keyed on the session's authority. */\nfunction sessionAuthorityChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.authToken !== previous.authToken || sessionScopeChanged(previous, next)\n );\n}\n\n// A transport token renewal cannot turn a definite write refusal into saved work.\n// Journal custody still expires on every change to its identity or storage scope.\nfunction sessionScopeChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.isAuthenticated !== previous.isAuthenticated ||\n next.isRoot !== previous.isRoot ||\n next.organizationId !== previous.organizationId ||\n next.userId !== previous.userId\n );\n}\n\nfunction createRuntimeInputFactory(\n dependencies: WorkflowRuntimeDependencies,\n resolveTrustedUserIdentity: TrustedUserIdentityResolver,\n bindHistoryProtection: () => PrincipalHistoryProtectionLease | undefined,\n bindMutationApi: () => PrincipalMutationApi,\n): RuntimeInputFactory {\n let auth: WorkflowRuntimeAuthInput | undefined;\n let crypto: WorkflowRuntimeCryptoInput | undefined;\n let infra: WorkflowRuntimeInfraInput | undefined;\n let state: WorkflowRuntimeStateInput | undefined;\n let util: WorkflowRuntimeUtilInput | undefined;\n let hostUtil: HostWorkflowRuntimeUtilInput | undefined;\n\n const workflowInput = (\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput => {\n const dbStatus = dependencies.database.status;\n const execSql =\n dbStatus === \"ready\"\n ? dependencies.database.requireExecSql(\"tearleads.runtime.input\")\n : unavailableExecSql;\n const nextContainerId =\n (containerId === undefined\n ? dependencies.session.containerId\n : containerId) ?? null;\n\n auth = reuseIfShallowEqual(auth, sessionAuthInput(dependencies));\n crypto = reuseIfShallowEqual(crypto, {\n encapsulationKeyPair: dependencies.identity.encapsulationKeyPair,\n signingFingerprint: dependencies.identity.signingFingerprint,\n signingKeyPair: dependencies.identity.signingKeyPair,\n });\n infra = reuseIfShallowEqual(infra, {\n blobStore: dependencies.blobs.store,\n dbStatus,\n documentProjectors: dependencies.documentProjectors,\n // Runtime consumers branch on dbStatus before touching SQLite. The\n // fallback preserves the runtime shape and catches lifecycle bugs.\n execSql,\n });\n state = reuseIfShallowEqual(state, {\n containerId: nextContainerId,\n domainScope: dependencies.getDomainScope(),\n events: dependencies.events.events,\n // Resolved sync-online: workflows treat local-only mode exactly like being\n // offline (no server I/O), while `tearleads.network` stays the truthful\n // connectivity signal for host/UI. See Session.syncEnabled.\n online: dependencies.network.online && dependencies.session.syncEnabled,\n peerScope: dependencies.peerScope ?? null,\n serverEventsConnectionGeneration:\n dependencies.events.connectionGeneration,\n });\n if (\n !util ||\n util.log !== dependencies.log ||\n util.logError !== dependencies.logError ||\n util.reportSecurityIncident !== dependencies.reportSecurityIncident\n ) {\n util = {\n isRemoteSyncBlocked: (organizationId) =>\n dependencies.syncBillingGate?.isBlockedForOrganization(\n organizationId,\n ) ?? false,\n log: dependencies.log,\n logError: dependencies.logError,\n reportSecurityIncident: dependencies.reportSecurityIncident,\n };\n }\n\n return {\n apiClient: bindMutationApi(),\n auth,\n crypto,\n infra,\n state,\n util,\n resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: bindHistoryProtection(),\n };\n };\n\n return {\n hostInput(containerId) {\n const {\n apiClient: _apiClient,\n resolveTrustedUserIdentity: _resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: _withPrincipalHistoryProtection,\n util: workflowUtil,\n ...input\n } = workflowInput(containerId);\n hostUtil = reuseIfShallowEqual(hostUtil, {\n isRemoteSyncBlocked: workflowUtil.isRemoteSyncBlocked,\n log: workflowUtil.log,\n logError: workflowUtil.logError,\n });\n return { ...input, util: hostUtil };\n },\n workflowInput,\n };\n}\n\n/**\n * Reuses the current runtime-input group when every field of the freshly\n * constructed `next` literal is reference-equal, so unchanged groups keep a\n * stable identity across runtime reads.\n */\nfunction reuseIfShallowEqual<T extends object>(\n current: T | undefined,\n next: T,\n): T {\n if (!current) {\n return next;\n }\n for (const key of Object.keys(next)) {\n if (Reflect.get(current, key) !== Reflect.get(next, key)) {\n return next;\n }\n }\n return current;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"workflowRuntime.js","sourceRoot":"","sources":["workflowRuntime.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { DocumentProjectorRegistry } from \"../data/documents/documentKinds\";\nimport type { DomainScope } from \"../data/domainScope\";\nimport { runWithSecurityIncidentReporting } from \"../data/keyingProjectionVerification/error\";\nimport type { PrincipalHistoryProtectionLease } from \"../data/principals/principalHistoryProtection\";\nimport type { SecurityIncidentReporter } from \"../data/securityIncidents\";\nimport { type ExecSql, unavailableExecSql } from \"../data/sqlite/sqlSchema\";\nimport {\n createApiUserIdentitySource,\n createTrustedUserIdentityService,\n type LocalUserIdentityCandidate,\n loadPinnedUserIdentity,\n type TrustedUserIdentityResolver,\n} from \"../data/trustedUserIdentity\";\nimport type { ContainerContentsRootAdopter } from \"../workflows/container-contents/runtime\";\nimport {\n createProvisionedPrincipalHistoryPrimer,\n type ProvisionedPrincipalHistoryPrimer,\n} from \"../workflows/registration/provisionedPrincipalHistory\";\nimport type {\n WorkflowRuntimeAuthInput,\n WorkflowRuntimeCryptoInput,\n WorkflowRuntimeGroups,\n WorkflowRuntimeInfraInput,\n WorkflowRuntimeStateInput,\n WorkflowRuntimeUtilInput,\n} from \"../workflows/runtimeInput\";\nimport type { Blobs } from \"./blobs\";\nimport type { Database } from \"./database\";\nimport type { Events } from \"./events\";\nimport type { Identity } from \"./identity\";\nimport { createListenerSet } from \"./listenerSet\";\nimport type { Network } from \"./network\";\nimport {\n createPrincipalHistoryProtectionCustody,\n type PrincipalHistoryKeyProvider,\n} from \"./principalHistoryProtection\";\nimport {\n createPrincipalMutationApiCustody,\n type PrincipalMutationApi,\n} from \"./principalMutationApi\";\nimport { adoptSessionRootContainer } from \"./rootContainerAdoption\";\nimport { acknowledgedSessionRoot } from \"./session/sessionRootAuthority\";\nimport type { Session, SessionSnapshot } from \"./session/sessionTypes\";\nimport type { SyncBillingGate } from \"./syncBillingGate\";\n\ntype HostWorkflowRuntimeUtilInput = Omit<\n WorkflowRuntimeUtilInput,\n \"reportSecurityIncident\"\n>;\n\nexport interface WorkflowRuntimeInput\n extends Omit<WorkflowRuntimeGroups, \"util\"> {\n readonly util: HostWorkflowRuntimeUtilInput;\n}\n\nexport type RuntimeListener = () => void;\n\nexport interface Runtime {\n readonly version: number;\n input(containerId?: string | null | undefined): WorkflowRuntimeInput;\n subscribe(listener: RuntimeListener): () => void;\n}\n\nexport interface InternalWorkflowRuntimeInput extends WorkflowRuntimeGroups {\n readonly apiClient: PrincipalMutationApi;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly withPrincipalHistoryProtection?:\n | PrincipalHistoryProtectionLease\n | undefined;\n}\n\nexport interface InternalRuntime {\n retirePrincipalHistoryProtection(): void;\n readonly sessionGeneration: number;\n readonly adoptRootContainer: ContainerContentsRootAdopter;\n readonly publicRuntime: Runtime;\n boundUserId(signingKeyFingerprint: string): Promise<string | null>;\n pinLocalUserIdentity(\n userId: string,\n candidate: LocalUserIdentityCandidate,\n ): Promise<void>;\n readonly primeProvisionedPrincipalHistory: ProvisionedPrincipalHistoryPrimer;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\ninterface WorkflowRuntimeDependencies {\n api: ApiClient;\n blobs: Blobs;\n database: Database;\n documentProjectors: DocumentProjectorRegistry;\n events: Events;\n getDomainScope: () => DomainScope;\n identity: Identity;\n identityTrustDomain: string | null;\n log: (message: string) => void;\n logError: (message: string | Error, cause?: unknown) => void;\n network: Network;\n peerScope?: string | null;\n principalHistoryKeyProvider?: PrincipalHistoryKeyProvider | undefined;\n principalMutationTimeoutMs?: number | undefined;\n reportSecurityIncident: SecurityIncidentReporter;\n session: Session;\n syncBillingGate?: SyncBillingGate | undefined;\n}\n\nfunction createRuntimeMutationApi(\n dependencies: WorkflowRuntimeDependencies,\n readGeneration: () => number,\n) {\n return createPrincipalMutationApiCustody({\n api: dependencies.api,\n principalMutationTimeoutMs: dependencies.principalMutationTimeoutMs,\n readScope: () => {\n const { signingKeyPair, signingFingerprint } = dependencies.identity;\n const { userId, isAuthenticated } = dependencies.session;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !isAuthenticated ||\n !userId ||\n !signingKeyPair ||\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n database: dependencies.getDomainScope(),\n execSql: dependencies.database.requireExecSql(\"principal mutation\"),\n generation: readGeneration(),\n identityTrustDomain,\n signingFingerprint,\n signingKeyPair,\n userId,\n };\n },\n });\n}\n\nfunction localIdentityCandidate(\n identity: Identity,\n): LocalUserIdentityCandidate | null {\n const { encapsulationKeyPair, signingKeyPair } = identity;\n if (!encapsulationKeyPair || !signingKeyPair) return null;\n return {\n encapsulationPublicKey: encapsulationKeyPair.publicKey,\n signingKeyFingerprint: identity.signingFingerprint,\n signingPublicKey: signingKeyPair.signingPublicKey,\n };\n}\n\n/** Priming reads the runtime's database, identity and trust pins; it pins nothing. */\nfunction createRuntimeProvisioningPrimer(\n dependencies: WorkflowRuntimeDependencies,\n bindLease: () => PrincipalHistoryProtectionLease | undefined,\n readyExecSql: () => ExecSql | null,\n): ProvisionedPrincipalHistoryPrimer {\n return createProvisionedPrincipalHistoryPrimer({\n bindLease,\n execSqlFor: (database) =>\n dependencies.database.client === database ? readyExecSql() : null,\n loadPinnedIdentity: async (execSql, userId) =>\n dependencies.identityTrustDomain\n ? loadPinnedUserIdentity({\n execSql,\n identityTrustDomain: dependencies.identityTrustDomain,\n userId,\n })\n : null,\n logError: dependencies.logError,\n signingFingerprint: () => dependencies.identity.signingFingerprint,\n });\n}\n\nexport function createRuntime(\n dependencies: WorkflowRuntimeDependencies,\n): InternalRuntime {\n const readyExecSql = () =>\n dependencies.database.status === \"ready\"\n ? dependencies.database.requireExecSql(\"trusted user identity\")\n : null;\n const trustedUserIdentityService = createTrustedUserIdentityService({\n getExecSql: readyExecSql,\n getLocalIdentity: () => localIdentityCandidate(dependencies.identity),\n getLocalUserId: () => dependencies.session.userId,\n identityTrustDomain: dependencies.identityTrustDomain,\n remoteSource: createApiUserIdentitySource(dependencies.api),\n });\n const resolveTrustedUserIdentity: TrustedUserIdentityResolver = (userId) =>\n runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.resolve\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.resolve(userId),\n );\n const runtimeSubscription = createRuntimeSubscription(dependencies);\n const historyProtection = createPrincipalHistoryProtectionCustody({\n keyProvider: dependencies.principalHistoryKeyProvider,\n readScope: () => {\n const signingFingerprint = dependencies.identity.signingFingerprint;\n const identityTrustDomain = dependencies.identityTrustDomain;\n if (\n !signingFingerprint ||\n !identityTrustDomain ||\n dependencies.database.status !== \"ready\"\n )\n return null;\n return {\n signingFingerprint,\n identityTrustDomain,\n database: dependencies.getDomainScope(),\n generation: runtimeSubscription.recoveryGeneration,\n };\n },\n });\n const runtimeInput = createRuntimeInputFactory(\n dependencies,\n resolveTrustedUserIdentity,\n historyProtection.bind,\n createRuntimeMutationApi(\n dependencies,\n () => runtimeSubscription.mutationGeneration,\n ).bind,\n );\n\n return {\n retirePrincipalHistoryProtection: historyProtection.retire,\n get sessionGeneration() {\n return runtimeSubscription.sessionGeneration;\n },\n adoptRootContainer: (input) =>\n adoptSessionRootContainer(dependencies, input),\n boundUserId: (signingKeyFingerprint) =>\n trustedUserIdentityService.boundUserId(signingKeyFingerprint),\n async pinLocalUserIdentity(userId, candidate) {\n await runWithSecurityIncidentReporting(\n dependencies.reportSecurityIncident,\n {\n objectId: userId,\n objectKind: \"user\",\n operation: \"user.identity.pin_local\",\n organizationId: dependencies.session.organizationId,\n },\n () => trustedUserIdentityService.pinLocal(userId, candidate),\n );\n },\n primeProvisionedPrincipalHistory: createRuntimeProvisioningPrimer(\n dependencies,\n historyProtection.bind,\n readyExecSql,\n ),\n publicRuntime: {\n get version() {\n return runtimeSubscription.version;\n },\n input: runtimeInput.hostInput,\n subscribe: runtimeSubscription.subscribe,\n },\n workflowInput: runtimeInput.workflowInput,\n };\n}\n\nfunction createRuntimeSubscription(dependencies: WorkflowRuntimeDependencies) {\n const listeners = createListenerSet();\n let version = 0;\n let sessionGeneration = 0;\n let recoveryGeneration = 0;\n let mutationGeneration = 0;\n let sessionSnapshot = dependencies.session.snapshot;\n const notifyListeners = () => {\n version += 1;\n listeners.notify();\n };\n\n const notifyAuthority = () => {\n recoveryGeneration += 1;\n mutationGeneration += 1;\n notifyListeners();\n };\n dependencies.database.subscribe(notifyAuthority);\n dependencies.events.subscribe(notifyListeners);\n dependencies.identity.subscribe(notifyAuthority);\n dependencies.network.subscribe(() => notifyListeners());\n dependencies.session.subscribe(() => {\n const next = dependencies.session.snapshot;\n if (sessionAuthorityChanged(sessionSnapshot, next)) {\n sessionGeneration += 1;\n recoveryGeneration += 1;\n }\n if (sessionScopeChanged(sessionSnapshot, next)) mutationGeneration += 1;\n sessionSnapshot = next;\n notifyListeners();\n });\n dependencies.syncBillingGate?.subscribe(notifyListeners);\n\n return {\n get mutationGeneration() {\n return mutationGeneration;\n },\n get recoveryGeneration() {\n return recoveryGeneration;\n },\n get sessionGeneration() {\n return sessionGeneration;\n },\n get version() {\n return version;\n },\n subscribe(listener: RuntimeListener): () => void {\n return listeners.subscribe(listener);\n },\n };\n}\n\ninterface RuntimeInputFactory {\n hostInput(containerId?: string | null | undefined): WorkflowRuntimeInput;\n workflowInput(\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput;\n}\n\nfunction sessionAuthInput({\n session,\n identity,\n}: WorkflowRuntimeDependencies): WorkflowRuntimeAuthInput {\n const signingFingerprint = identity.snapshot.signingFingerprint;\n return {\n defaultOrganizationId: session.defaultOrganizationId,\n rootContainerId: acknowledgedSessionRoot(session, signingFingerprint),\n isAuthenticated: session.isAuthenticated,\n isRoot: session.isRoot,\n organizationId: session.organizationId,\n userId: session.userId,\n };\n}\n\n/** Fields whose change invalidates work keyed on the session's authority. */\nfunction sessionAuthorityChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.authToken !== previous.authToken || sessionScopeChanged(previous, next)\n );\n}\n\n// A transport token renewal cannot turn a definite write refusal into saved work.\n// Journal custody still expires on every change to its identity or storage scope.\nfunction sessionScopeChanged(\n previous: SessionSnapshot,\n next: SessionSnapshot,\n): boolean {\n return (\n next.isAuthenticated !== previous.isAuthenticated ||\n next.isRoot !== previous.isRoot ||\n next.organizationId !== previous.organizationId ||\n next.userId !== previous.userId\n );\n}\n\nfunction createRuntimeInputFactory(\n dependencies: WorkflowRuntimeDependencies,\n resolveTrustedUserIdentity: TrustedUserIdentityResolver,\n bindHistoryProtection: () => PrincipalHistoryProtectionLease | undefined,\n bindMutationApi: () => PrincipalMutationApi,\n): RuntimeInputFactory {\n let auth: WorkflowRuntimeAuthInput | undefined;\n let crypto: WorkflowRuntimeCryptoInput | undefined;\n let infra: WorkflowRuntimeInfraInput | undefined;\n let state: WorkflowRuntimeStateInput | undefined;\n let util: WorkflowRuntimeUtilInput | undefined;\n let hostUtil: HostWorkflowRuntimeUtilInput | undefined;\n\n const workflowInput = (\n containerId?: string | null | undefined,\n ): InternalWorkflowRuntimeInput => {\n const dbStatus = dependencies.database.status;\n const execSql =\n dbStatus === \"ready\"\n ? dependencies.database.requireExecSql(\"tearleads.runtime.input\")\n : unavailableExecSql;\n const nextContainerId =\n (containerId === undefined\n ? dependencies.session.containerId\n : containerId) ?? null;\n\n auth = reuseIfShallowEqual(auth, sessionAuthInput(dependencies));\n crypto = reuseIfShallowEqual(crypto, {\n encapsulationKeyPair: dependencies.identity.encapsulationKeyPair,\n signingFingerprint: dependencies.identity.signingFingerprint,\n signingKeyPair: dependencies.identity.signingKeyPair,\n });\n infra = reuseIfShallowEqual(infra, {\n blobStore: dependencies.blobs.store,\n dbStatus,\n documentProjectors: dependencies.documentProjectors,\n // Runtime consumers branch on dbStatus before touching SQLite. The\n // fallback preserves the runtime shape and catches lifecycle bugs.\n execSql,\n });\n state = reuseIfShallowEqual(state, {\n containerId: nextContainerId,\n domainScope: dependencies.getDomainScope(),\n events: dependencies.events.events,\n // Resolved sync-online: workflows treat local-only mode exactly like being\n // offline (no server I/O), while `tearleads.network` stays the truthful\n // connectivity signal for host/UI. See Session.syncEnabled.\n online: dependencies.network.online && dependencies.session.syncEnabled,\n peerScope: dependencies.peerScope ?? null,\n serverEventsConnectionGeneration:\n dependencies.events.connectionGeneration,\n });\n if (\n !util ||\n util.log !== dependencies.log ||\n util.logError !== dependencies.logError ||\n util.reportSecurityIncident !== dependencies.reportSecurityIncident\n ) {\n util = {\n isRemoteSyncBlocked: (organizationId) =>\n dependencies.syncBillingGate?.isBlockedForOrganization(\n organizationId,\n ) ?? false,\n log: dependencies.log,\n logError: dependencies.logError,\n reportSecurityIncident: dependencies.reportSecurityIncident,\n };\n }\n\n return {\n apiClient: bindMutationApi(),\n auth,\n crypto,\n infra,\n state,\n util,\n resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: bindHistoryProtection(),\n };\n };\n\n return {\n hostInput(containerId) {\n const {\n apiClient: _apiClient,\n resolveTrustedUserIdentity: _resolveTrustedUserIdentity,\n withPrincipalHistoryProtection: _withPrincipalHistoryProtection,\n util: workflowUtil,\n ...input\n } = workflowInput(containerId);\n hostUtil = reuseIfShallowEqual(hostUtil, {\n isRemoteSyncBlocked: workflowUtil.isRemoteSyncBlocked,\n log: workflowUtil.log,\n logError: workflowUtil.logError,\n });\n return { ...input, util: hostUtil };\n },\n workflowInput,\n };\n}\n\n/**\n * Reuses the current runtime-input group when every field of the freshly\n * constructed `next` literal is reference-equal, so unchanged groups keep a\n * stable identity across runtime reads.\n */\nfunction reuseIfShallowEqual<T extends object>(\n current: T | undefined,\n next: T,\n): T {\n if (!current) {\n return next;\n }\n for (const key of Object.keys(next)) {\n if (Reflect.get(current, key) !== Reflect.get(next, key)) {\n return next;\n }\n }\n return current;\n}\n"]}
|
|
@@ -238,9 +238,8 @@ export async function collectReferencedPrincipalPolicies(input) {
|
|
|
238
238
|
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
|
-
|
|
241
|
+
// The warmer's operation shares one recovery view across its collections.
|
|
242
242
|
return Promise.all(references.map((reference) => verifyReferencedPrincipalPolicy({
|
|
243
|
-
recoveryBatch,
|
|
244
243
|
checkpointContext: input.checkpointContext,
|
|
245
244
|
organizationId: input.organizationId,
|
|
246
245
|
principalPolicyCache: input.principalPolicyCache,
|
|
@@ -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 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 // Scoped recovery carries organization, dependency and lifetime bindings.\n // A bare policy cache entry cannot replace those bindings.\n const recovered = await resolveReferencedPrincipalPolicy(input);\n if (recovered) return recovered;\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 && 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
|
+
{"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 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 // Scoped recovery carries organization, dependency and lifetime bindings.\n // A bare policy cache entry cannot replace those bindings.\n const recovered = await resolveReferencedPrincipalPolicy(input);\n if (recovered) return recovered;\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 && 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 // The warmer's operation shares one recovery view across its collections.\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 stillCurrent: input.stillCurrent,\n resolveUserKey: input.resolveUserKey,\n warmReferencedPrincipalPolicies,\n }),\n ),\n );\n}\n"]}
|
|
@@ -3,12 +3,12 @@ import { loadPrincipalPolicyCheckpoint } from "../persistence/keyingCheckpointPe
|
|
|
3
3
|
import { verifiedPrincipalPolicyMeetsCheckpoint } from "../persistence/principalPolicyCheckpointSelection.js";
|
|
4
4
|
import { observePrincipalPolicy, } from "./checkpointContext.js";
|
|
5
5
|
import { referencedPrincipalPolicyKey, verifiedPrincipalPolicyContainsReference, } from "./principalPolicyCache.js";
|
|
6
|
+
import { observeProjectionLifetime } from "./projectionLifetimes.js";
|
|
6
7
|
import { assertProjectionVerificationCurrent, } from "./types.js";
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
// The caller
|
|
10
|
-
//
|
|
11
|
-
const recoveredByCache = new WeakMap();
|
|
8
|
+
// Scoped evidence is always resolved through the warmer: its operation memo is
|
|
9
|
+
// the only reuse of recovered directory and Admins evidence, with one set of
|
|
10
|
+
// validity rules. The caller's policy cache keeps bare verified policies; it
|
|
11
|
+
// never stands in for organization, dependency or lifetime bindings.
|
|
12
12
|
async function meetsCheckpoints(context, result, refreshMissing) {
|
|
13
13
|
for (const policy of [...result.dependencies, result.policy]) {
|
|
14
14
|
const checkpoint = await loadPrincipalPolicyCheckpoint(context.execSql, policy.principalType, policy.principalId);
|
|
@@ -23,61 +23,49 @@ async function meetsCheckpoints(context, result, refreshMissing) {
|
|
|
23
23
|
}
|
|
24
24
|
return true;
|
|
25
25
|
}
|
|
26
|
+
async function recoverEvidence(input, resolve) {
|
|
27
|
+
const read = async (recoveryBatch) => {
|
|
28
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
29
|
+
const recovered = await resolve({
|
|
30
|
+
recoveryBatch,
|
|
31
|
+
organizationId: input.organizationId,
|
|
32
|
+
reference: input.reference,
|
|
33
|
+
stillCurrent: input.stillCurrent,
|
|
34
|
+
});
|
|
35
|
+
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
36
|
+
assertProjectionVerificationCurrent(recovered.stillCurrent);
|
|
37
|
+
return recovered;
|
|
38
|
+
};
|
|
39
|
+
let result = await read();
|
|
40
|
+
// A concurrent admission may advance a pin after recovery verified it.
|
|
41
|
+
// Refresh once outside the operation's directory view; the fresh
|
|
42
|
+
// recovery and final checkpoint check still reject rollback/equivocation.
|
|
43
|
+
if (!(await meetsCheckpoints(input.checkpointContext, result, true))) {
|
|
44
|
+
assertProjectionVerificationCurrent(result.stillCurrent);
|
|
45
|
+
result = await read({});
|
|
46
|
+
await meetsCheckpoints(input.checkpointContext, result, false);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
26
50
|
export async function resolveReferencedPrincipalPolicy(input) {
|
|
27
51
|
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
28
52
|
const key = referencedPrincipalPolicyKey(input.reference);
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;
|
|
40
|
-
if (!resolve)
|
|
41
|
-
return null;
|
|
42
|
-
const read = async (recoveryBatch) => {
|
|
43
|
-
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
44
|
-
const recovered = await resolve({
|
|
45
|
-
recoveryBatch,
|
|
46
|
-
organizationId: input.organizationId,
|
|
47
|
-
reference: input.reference,
|
|
48
|
-
stillCurrent: input.stillCurrent,
|
|
49
|
-
});
|
|
50
|
-
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
51
|
-
assertProjectionVerificationCurrent(recovered.stillCurrent);
|
|
52
|
-
return recovered;
|
|
53
|
-
};
|
|
54
|
-
result = await read(input.recoveryBatch);
|
|
55
|
-
// A concurrent admission may advance a pin after recovery verified it.
|
|
56
|
-
// Refresh once outside the old batch's pinned directory view; the fresh
|
|
57
|
-
// recovery and final checkpoint check still reject rollback/equivocation.
|
|
58
|
-
if (!(await meetsCheckpoints(input.checkpointContext, result, true))) {
|
|
59
|
-
assertProjectionVerificationCurrent(result.stillCurrent);
|
|
60
|
-
result = await read({});
|
|
61
|
-
await meetsCheckpoints(input.checkpointContext, result, false);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
assertProjectionVerificationCurrent(input.stillCurrent);
|
|
65
|
-
assertProjectionVerificationCurrent(result.stillCurrent);
|
|
53
|
+
const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;
|
|
54
|
+
if (!resolve)
|
|
55
|
+
return null;
|
|
56
|
+
const result = await recoverEvidence(input, resolve);
|
|
57
|
+
const evidenceCurrent = result.stillCurrent;
|
|
58
|
+
// The consumer's and every producer's lifetime guard the evidence where it
|
|
59
|
+
// is used: projection admission rechecks them through the context.
|
|
60
|
+
const lifetime = () => input.stillCurrent?.() !== false && evidenceCurrent();
|
|
61
|
+
assertProjectionVerificationCurrent(lifetime);
|
|
62
|
+
observeProjectionLifetime(input.checkpointContext, lifetime);
|
|
66
63
|
if (result.organizationId !== input.organizationId)
|
|
67
64
|
throw new KeyingVerificationError("object_mismatch", "Recovered principal evidence belongs to another organization");
|
|
68
65
|
if (!verifiedPrincipalPolicyContainsReference(result.policy, input.reference))
|
|
69
66
|
throw new KeyingVerificationError("object_mismatch", "Recovered principal evidence does not contain the exact citation");
|
|
70
67
|
for (const policy of [...result.dependencies, result.policy])
|
|
71
68
|
observePrincipalPolicy(input.checkpointContext, policy, input.organizationId);
|
|
72
|
-
let rememberedPolicies = recoveredByCache.get(input.principalPolicyCache);
|
|
73
|
-
if (!rememberedPolicies) {
|
|
74
|
-
rememberedPolicies = new Map();
|
|
75
|
-
recoveredByCache.set(input.principalPolicyCache, rememberedPolicies);
|
|
76
|
-
}
|
|
77
|
-
rememberedPolicies.set(key, {
|
|
78
|
-
...result,
|
|
79
|
-
dependencies: [...result.dependencies],
|
|
80
|
-
});
|
|
81
69
|
input.principalPolicyCache.set(key, result.policy);
|
|
82
70
|
return result.policy;
|
|
83
71
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolvedPrincipalPolicy.js","sourceRoot":"","sources":["resolvedPrincipalPolicy.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,GAGxB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,4CAA4C,CAAC;AAC3F,OAAO,EAAE,sCAAsC,EAAE,MAAM,mDAAmD,CAAC;AAC3G,OAAO,EACL,sBAAsB,GAEvB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,4BAA4B,EAC5B,wCAAwC,GACzC,MAAM,wBAAwB,CAAC;AAChC,OAAO,EACL,mCAAmC,GAIpC,MAAM,SAAS,CAAC;AAEjB,6EAA6E;AAC7E,
|
|
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 { observeProjectionLifetime } from \"./projectionLifetimes\";\nimport {\n assertProjectionVerificationCurrent,\n type PrincipalPolicyCache,\n type ReferencedPrincipalPolicyWarmer,\n type ResolvedPrincipalPolicyEvidence,\n} from \"./types\";\n\n// Scoped evidence is always resolved through the warmer: its operation memo is\n// the only reuse of recovered directory and Admins evidence, with one set of\n// validity rules. The caller's policy cache keeps bare verified policies; it\n// never stands in for organization, dependency or lifetime bindings.\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\ninterface ResolveReferencedPrincipalPolicyInput {\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}\n\nasync function recoverEvidence(\n input: ResolveReferencedPrincipalPolicyInput,\n resolve: NonNullable<ReferencedPrincipalPolicyWarmer[\"resolveReference\"]>,\n): Promise<ResolvedPrincipalPolicyEvidence> {\n const read = async (recoveryBatch?: object) => {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const recovered = await resolve({\n recoveryBatch,\n organizationId: input.organizationId,\n reference: input.reference,\n stillCurrent: input.stillCurrent,\n });\n assertProjectionVerificationCurrent(input.stillCurrent);\n assertProjectionVerificationCurrent(recovered.stillCurrent);\n return recovered;\n };\n let result = await read();\n // A concurrent admission may advance a pin after recovery verified it.\n // Refresh once outside the operation's directory view; the fresh\n // recovery and final checkpoint check still reject rollback/equivocation.\n if (!(await meetsCheckpoints(input.checkpointContext, result, true))) {\n assertProjectionVerificationCurrent(result.stillCurrent);\n result = await read({});\n await meetsCheckpoints(input.checkpointContext, result, false);\n }\n return result;\n}\n\nexport async function resolveReferencedPrincipalPolicy(\n input: ResolveReferencedPrincipalPolicyInput,\n): Promise<VerifiedPrincipalPolicyCurrent | null> {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const key = referencedPrincipalPolicyKey(input.reference);\n const resolve = input.warmReferencedPrincipalPolicies?.resolveReference;\n if (!resolve) return null;\n const result = await recoverEvidence(input, resolve);\n const evidenceCurrent = result.stillCurrent;\n // The consumer's and every producer's lifetime guard the evidence where it\n // is used: projection admission rechecks them through the context.\n const lifetime = () => input.stillCurrent?.() !== false && evidenceCurrent();\n assertProjectionVerificationCurrent(lifetime);\n observeProjectionLifetime(input.checkpointContext, lifetime);\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 input.principalPolicyCache.set(key, result.policy);\n return result.policy;\n}\n"]}
|
|
@@ -8,7 +8,7 @@ export type PrincipalPolicyCache = Map<string, PrincipalPolicyCurrentEvidence>;
|
|
|
8
8
|
export interface PrincipalPolicyResolveRequest {
|
|
9
9
|
/** Reuse authenticated local ancestry before an authorized online recovery. */
|
|
10
10
|
readonly preferLocalHistory?: boolean | undefined;
|
|
11
|
-
/**
|
|
11
|
+
/** One recovery view: the warmer's operation unless a caller supplies its own. */
|
|
12
12
|
readonly recoveryBatch?: object | undefined;
|
|
13
13
|
readonly organizationId: string;
|
|
14
14
|
readonly reference: ReferencedPrincipalHead;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ReferencedPrincipalHead,\n VerifiedPrincipalPolicyCurrent,\n VerifiedPrincipalPolicySelection,\n} from \"@tearleads/crypto\";\nimport type { ProjectionPolicyEvidenceResponse } 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 /** Reuse authenticated local ancestry before an authorized online recovery. */\n readonly preferLocalHistory?: boolean | undefined;\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 VerifiedPrincipalPolicySelection,\n} from \"@tearleads/crypto\";\nimport type { ProjectionPolicyEvidenceResponse } 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 /** Reuse authenticated local ancestry before an authorized online recovery. */\n readonly preferLocalHistory?: boolean | undefined;\n /** One recovery view: the warmer's operation unless a caller supplies its own. */\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 ProjectionPolicyHistoryResolveRequest {\n /** Authenticate terminal evidence first; its consumer must validate durable currency. */\n readonly historicalProof?: boolean | undefined;\n readonly organizationId: string;\n readonly evidence: ProjectionPolicyEvidenceResponse;\n readonly references: readonly ReferencedPrincipalHead[];\n readonly stillCurrent?: (() => boolean) | undefined;\n}\n\nexport interface ResolvedProjectionPolicyHistory {\n readonly policies: readonly VerifiedPrincipalPolicySelection[];\n readonly stillCurrent: () => boolean;\n}\n\nexport type ReferencedPrincipalPolicyWarmer = ((\n input: ReferencedPrincipalPolicyWarmRequest,\n) => Promise<void>) & {\n readonly resolveProjectionHistory?:\n | ((\n input: ProjectionPolicyHistoryResolveRequest,\n ) => Promise<ResolvedProjectionPolicyHistory>)\n | 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 const resolveProjectionHistory = operation.resolveProjectionHistory;\n return Object.assign(guarded, {\n ...(resolveProjectionHistory\n ? {\n resolveProjectionHistory: async (\n input: ProjectionPolicyHistoryResolveRequest,\n ) => {\n const current = () =>\n stillCurrent() && input.stillCurrent?.() !== false;\n assertProjectionVerificationCurrent(current);\n const result = await resolveProjectionHistory({\n ...input,\n stillCurrent: current,\n });\n assertProjectionVerificationCurrent(current);\n return result;\n },\n }\n : {}),\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 });\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"]}
|
|
@@ -23,4 +23,20 @@ export interface DocumentDiscoveryEvidenceStore {
|
|
|
23
23
|
loadHead(documentId: string, manifestHash: string | null | undefined): Promise<CachedDiscoveryHead | null>;
|
|
24
24
|
saveHead(documentId: string, head: CachedDiscoveryHead, generation: number): Promise<boolean>;
|
|
25
25
|
}
|
|
26
|
+
/**
|
|
27
|
+
* A document head this client signed, already checked against the server's
|
|
28
|
+
* create acknowledgement and pinned as its access-manifest checkpoint in the
|
|
29
|
+
* same transaction. It is the same signed head a discovery projection would
|
|
30
|
+
* verify, so it seeds the exact-head cache; `loadHead` still reuses it only
|
|
31
|
+
* while that checkpoint matches.
|
|
32
|
+
*/
|
|
33
|
+
export interface AuthoredDiscoveryHead {
|
|
34
|
+
readonly documentId: string;
|
|
35
|
+
readonly organizationId: string;
|
|
36
|
+
readonly accessEpoch: number;
|
|
37
|
+
readonly accessStateHash: string;
|
|
38
|
+
readonly linkedContainerIds: readonly string[];
|
|
39
|
+
}
|
|
40
|
+
/** Writes authored heads inside the caller's serialized write transaction. */
|
|
41
|
+
export declare function primeAuthoredDocumentDiscoveryHeads(execSql: ExecSql, authored: readonly AuthoredDiscoveryHead[]): Promise<void>;
|
|
26
42
|
export declare function createDocumentDiscoveryEvidenceStore(execSql: ExecSql, now?: () => number): DocumentDiscoveryEvidenceStore;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { and, asc, eq, inArray, lte, min, sql } from "drizzle-orm";
|
|
2
|
+
import { uniqueSortedStrings } from "../../documents/shared/readers.js";
|
|
2
3
|
import { readStringArray } from "../../recordReaders.js";
|
|
3
4
|
import { documentDiscoveryHeads, documentDiscoverySequence, pendingDocumentDiscoveries, } from "../../sqlite/documentDiscoveryEvidenceSchema.js";
|
|
4
5
|
import { accessManifestCheckpoints, documentContainerProjectionTables, } from "../../sqlite/schema.js";
|
|
@@ -231,6 +232,28 @@ class SqlDocumentDiscoveryEvidenceStore {
|
|
|
231
232
|
return true;
|
|
232
233
|
});
|
|
233
234
|
}
|
|
235
|
+
/** Writes authored heads inside the caller's serialized write transaction. */
|
|
236
|
+
export async function primeAuthoredDocumentDiscoveryHeads(execSql, authored) {
|
|
237
|
+
const db = getClientSQLitePersistenceRuntime(execSql).db;
|
|
238
|
+
for (const head of authored) {
|
|
239
|
+
const row = {
|
|
240
|
+
documentId: head.documentId,
|
|
241
|
+
organizationId: head.organizationId,
|
|
242
|
+
manifestHash: head.accessStateHash,
|
|
243
|
+
accessEpoch: head.accessEpoch,
|
|
244
|
+
linksJson: JSON.stringify(uniqueSortedStrings(head.linkedContainerIds)),
|
|
245
|
+
};
|
|
246
|
+
await db
|
|
247
|
+
.insert(heads)
|
|
248
|
+
.values(row)
|
|
249
|
+
.onConflictDoUpdate({
|
|
250
|
+
target: [heads.documentId, heads.organizationId],
|
|
251
|
+
set: row,
|
|
252
|
+
setWhere: lte(heads.accessEpoch, head.accessEpoch),
|
|
253
|
+
})
|
|
254
|
+
.run();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
234
257
|
export function createDocumentDiscoveryEvidenceStore(execSql, now = Date.now) {
|
|
235
258
|
return new SqlDocumentDiscoveryEvidenceStore(execSql, now);
|
|
236
259
|
}
|