@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.
Files changed (80) hide show
  1. package/client/Tearleads.d.ts +3 -0
  2. package/client/Tearleads.js +20 -12
  3. package/client/Tearleads.js.map +1 -1
  4. package/client/organizations/organizationGroupHistory.js +1 -1
  5. package/client/organizations/organizationGroupHistory.js.map +1 -1
  6. package/client/organizations/organizationHistory.js +1 -1
  7. package/client/organizations/organizationHistory.js.map +1 -1
  8. package/client/session/index.js +2 -2
  9. package/client/session/index.js.map +1 -1
  10. package/client/session/sessionOrganizationCreation.js +1 -0
  11. package/client/session/sessionOrganizationCreation.js.map +1 -1
  12. package/client/session/sessionTypes.d.ts +3 -0
  13. package/client/session/sessionTypes.js.map +1 -1
  14. package/client/workflowRuntime.d.ts +2 -0
  15. package/client/workflowRuntime.js +34 -16
  16. package/client/workflowRuntime.js.map +1 -1
  17. package/data/keyingProjectionVerification/principalPolicyVerification.js +1 -2
  18. package/data/keyingProjectionVerification/principalPolicyVerification.js.map +1 -1
  19. package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js +39 -51
  20. package/data/keyingProjectionVerification/resolvedPrincipalPolicy.js.map +1 -1
  21. package/data/keyingProjectionVerification/types.d.ts +1 -1
  22. package/data/keyingProjectionVerification/types.js.map +1 -1
  23. package/data/persistence/documents/documentDiscoveryEvidencePersistence.d.ts +16 -0
  24. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js +23 -0
  25. package/data/persistence/documents/documentDiscoveryEvidencePersistence.js.map +1 -1
  26. package/data/persistence/organizations/organizationAccessRevocationPersistence.js +4 -0
  27. package/data/persistence/organizations/organizationAccessRevocationPersistence.js.map +1 -1
  28. package/data/persistence/organizations/organizationReadModelPersistence.js +7 -1
  29. package/data/persistence/organizations/organizationReadModelPersistence.js.map +1 -1
  30. package/data/principals/principalRecoveryEpoch.js +18 -0
  31. package/data/principals/principalRecoveryEpoch.js.map +1 -0
  32. package/data/trustedUserIdentity/index.d.ts +1 -1
  33. package/data/trustedUserIdentity/index.js +1 -1
  34. package/data/trustedUserIdentity/index.js.map +1 -1
  35. package/data/trustedUserIdentity/service.d.ts +12 -1
  36. package/data/trustedUserIdentity/service.js +27 -3
  37. package/data/trustedUserIdentity/service.js.map +1 -1
  38. package/package.json +1 -1
  39. package/workflows/organizations/createOrganization.d.ts +3 -0
  40. package/workflows/organizations/createOrganization.js +1 -0
  41. package/workflows/organizations/createOrganization.js.map +1 -1
  42. package/workflows/organizations/currentGroupPolicyMutationContext.js +5 -5
  43. package/workflows/organizations/currentGroupPolicyMutationContext.js.map +1 -1
  44. package/workflows/principals/principalCurrentRecoveryBatch.js +1 -1
  45. package/workflows/principals/principalCurrentRecoveryBatch.js.map +1 -1
  46. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
  47. package/workflows/principals/principalRecoveryMemo.d.ts +9 -4
  48. package/workflows/principals/principalRecoveryMemo.js +94 -34
  49. package/workflows/principals/principalRecoveryMemo.js.map +1 -1
  50. package/workflows/principals/principalRecoveryMemoValidity.js +33 -0
  51. package/workflows/principals/principalRecoveryMemoValidity.js.map +1 -0
  52. package/workflows/principals/principalRecoveryOutage.js +2 -2
  53. package/workflows/principals/principalRecoveryOutage.js.map +1 -1
  54. package/workflows/principals/recoverCurrentOrganizationPolicy.js +8 -3
  55. package/workflows/principals/recoverCurrentOrganizationPolicy.js.map +1 -1
  56. package/workflows/principals/recoverPrincipalPolicyHistory.js +42 -8
  57. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  58. package/workflows/principals/recoverPublicPrincipalHistory.js +5 -5
  59. package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
  60. package/workflows/principals/recoverScopedPrincipalPolicyHistory.d.ts +9 -2
  61. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js +8 -2
  62. package/workflows/principals/recoverScopedPrincipalPolicyHistory.js.map +1 -1
  63. package/workflows/principals/runtimePolicyRecovery.js +4 -1
  64. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  65. package/workflows/principals/runtimePolicyWarmer.js +12 -4
  66. package/workflows/principals/runtimePolicyWarmer.js.map +1 -1
  67. package/workflows/registration/organizationProvisioningPersistence.d.ts +3 -0
  68. package/workflows/registration/organizationProvisioningPersistence.js +27 -1
  69. package/workflows/registration/organizationProvisioningPersistence.js.map +1 -1
  70. package/workflows/registration/persistRegistrationBootstrap.d.ts +3 -0
  71. package/workflows/registration/persistRegistrationBootstrap.js +7 -1
  72. package/workflows/registration/persistRegistrationBootstrap.js.map +1 -1
  73. package/workflows/registration/provisionedPrincipalHistory.d.ts +45 -0
  74. package/workflows/registration/provisionedPrincipalHistory.js +104 -0
  75. package/workflows/registration/provisionedPrincipalHistory.js.map +1 -0
  76. package/workflows/registration/provisioningAcknowledgement.js +18 -0
  77. package/workflows/registration/provisioningAcknowledgement.js.map +1 -1
  78. package/workflows/registration/registerIdentity.d.ts +3 -0
  79. package/workflows/registration/registerIdentity.js +1 -0
  80. package/workflows/registration/registerIdentity.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"runtimePolicyWarmer.js","sourceRoot":"","sources":["runtimePolicyWarmer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,oCAAoC,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAE,8BAA8B,EAAE,MAAM,+CAA+C,CAAC;AAC/F,OAAO,EACL,mCAAmC,EACnC,sCAAsC,GAEvC,MAAM,+CAA+C,CAAC;AACvD,OAAO,EACL,oCAAoC,GAErC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,qCAAqC,EAAE,MAAM,mCAAmC,CAAC;AAW1F,oFAAoF;AACpF,MAAM,UAAU,kCAAkC,CAChD,OAAmC,EACnC,UAAqD,EAAE;IAEvD,MAAM,OAAO,GAAG,oCAAoC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,gBAAgB,GAAmB,KAAK,EAAE,KAAK,EAAE,EAAE;QACvD,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,oCAAoC,CAC5C,mDAAmD,CACpD,CAAC;QACJ,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAqD,EAAE,EAAE,CACxD,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,EACtD;QACE,gBAAgB;QAChB,wBAAwB,EAAE,qCAAqC,CAAC,OAAO,CAAC;KACzE,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,OAAmC,EACnC,OAAuB,EACvB,KAAqD;IAErD,MAAM,aAAa,GAAG,EAAE,CAAC;IACzB,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,mCAAmC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC,CAAC;YACvE,mCAAmC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,sCAAsC,CAAC,KAAK,CAAC;gBAAE,OAAO;YAC1D,0EAA0E;YAC1E,8BAA8B,CAAC,KAAK,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAChB,8BAA8B,SAAS,CAAC,WAAW,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { errorMessage } from \"../../data/errorMessage\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { rethrowKeyingVerificationError } from \"../../data/keyingProjectionVerification/error\";\nimport {\n assertProjectionVerificationCurrent,\n isProjectionVerificationCancelledError,\n type ReferencedPrincipalPolicyWarmer,\n} from \"../../data/keyingProjectionVerification/types\";\nimport {\n createRuntimePrincipalPolicyResolver,\n type PrincipalPolicyRecoveryRuntime,\n} from \"./runtimePolicyRecovery\";\nimport { createRuntimeProjectionPolicyResolver } from \"./runtimeProjectionPolicyRecovery\";\n\ntype PolicyResolver = NonNullable<\n ReferencedPrincipalPolicyWarmer[\"resolveReference\"]\n>;\ninterface PrincipalPolicyWarmRuntime extends PrincipalPolicyRecoveryRuntime {\n readonly util: PrincipalPolicyRecoveryRuntime[\"util\"] & {\n readonly log?: ((message: string) => void) | undefined;\n };\n}\n\n/** Prefetch is best-effort; exact resolution still rejects unavailable evidence. */\nexport function createRuntimePrincipalPolicyWarmer(\n runtime: PrincipalPolicyWarmRuntime,\n options: { readonly preferLocalCurrent?: boolean } = {},\n): ReferencedPrincipalPolicyWarmer {\n const resolve = createRuntimePrincipalPolicyResolver(runtime, options);\n const resolveReference: PolicyResolver = async (input) => {\n if (!resolve)\n throw new ProjectionDependencyUnavailableError(\n \"Principal policies require private paged recovery\",\n );\n return resolve(input);\n };\n return Object.assign(\n (input: Parameters<ReferencedPrincipalPolicyWarmer>[0]) =>\n prefetchReferences(runtime, resolveReference, input),\n {\n resolveReference,\n resolveProjectionHistory: createRuntimeProjectionPolicyResolver(runtime),\n },\n );\n}\n\nasync function prefetchReferences(\n runtime: PrincipalPolicyWarmRuntime,\n resolve: PolicyResolver,\n input: Parameters<ReferencedPrincipalPolicyWarmer>[0],\n): Promise<void> {\n const recoveryBatch = {};\n for (const reference of input.references) {\n try {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const resolved = await resolve({ ...input, reference, recoveryBatch });\n assertProjectionVerificationCurrent(resolved.stillCurrent);\n } catch (error) {\n if (isProjectionVerificationCancelledError(error)) return;\n // Recovery already reports signature/authority failures. Keep them fatal.\n rethrowKeyingVerificationError(error);\n runtime.util.log?.(\n `Principal policy prefetch: ${reference.principalId}: ${errorMessage(error)}`,\n );\n }\n }\n}\n"]}
1
+ {"version":3,"file":"runtimePolicyWarmer.js","sourceRoot":"","sources":["runtimePolicyWarmer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,oCAAoC,EAAE,MAAM,+DAA+D,CAAC;AACrH,OAAO,EAAE,8BAA8B,EAAE,MAAM,+CAA+C,CAAC;AAC/F,OAAO,EACL,mCAAmC,EACnC,sCAAsC,GAEvC,MAAM,+CAA+C,CAAC;AACvD,OAAO,EACL,oCAAoC,GAErC,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,qCAAqC,EAAE,MAAM,mCAAmC,CAAC;AAW1F;;;;;GAKG;AACH,MAAM,UAAU,kCAAkC,CAChD,OAAmC,EACnC,UAAqD,EAAE;IAEvD,MAAM,OAAO,GAAG,oCAAoC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACvE,MAAM,SAAS,GAAG,EAAE,CAAC;IACrB,MAAM,gBAAgB,GAAmB,KAAK,EAAE,KAAK,EAAE,EAAE;QACvD,IAAI,CAAC,OAAO;YACV,MAAM,IAAI,oCAAoC,CAC5C,mDAAmD,CACpD,CAAC;QACJ,OAAO,OAAO,CAAC;YACb,GAAG,KAAK;YACR,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,SAAS;SAChD,CAAC,CAAC;IACL,CAAC,CAAC;IACF,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAqD,EAAE,EAAE,CACxD,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,EAAE,KAAK,CAAC,EACtD;QACE,gBAAgB;QAChB,wBAAwB,EAAE,qCAAqC,CAAC,OAAO,CAAC;KACzE,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,kBAAkB,CAC/B,OAAmC,EACnC,OAAuB,EACvB,KAAqD;IAErD,KAAK,MAAM,SAAS,IAAI,KAAK,CAAC,UAAU,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,mCAAmC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YACxD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;YACxD,mCAAmC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC7D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,sCAAsC,CAAC,KAAK,CAAC;gBAAE,OAAO;YAC1D,0EAA0E;YAC1E,8BAA8B,CAAC,KAAK,CAAC,CAAC;YACtC,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAChB,8BAA8B,SAAS,CAAC,WAAW,KAAK,YAAY,CAAC,KAAK,CAAC,EAAE,CAC9E,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC","sourcesContent":["import { errorMessage } from \"../../data/errorMessage\";\nimport { ProjectionDependencyUnavailableError } from \"../../data/keyingProjectionVerification/dependencyUnavailable\";\nimport { rethrowKeyingVerificationError } from \"../../data/keyingProjectionVerification/error\";\nimport {\n assertProjectionVerificationCurrent,\n isProjectionVerificationCancelledError,\n type ReferencedPrincipalPolicyWarmer,\n} from \"../../data/keyingProjectionVerification/types\";\nimport {\n createRuntimePrincipalPolicyResolver,\n type PrincipalPolicyRecoveryRuntime,\n} from \"./runtimePolicyRecovery\";\nimport { createRuntimeProjectionPolicyResolver } from \"./runtimeProjectionPolicyRecovery\";\n\ntype PolicyResolver = NonNullable<\n ReferencedPrincipalPolicyWarmer[\"resolveReference\"]\n>;\ninterface PrincipalPolicyWarmRuntime extends PrincipalPolicyRecoveryRuntime {\n readonly util: PrincipalPolicyRecoveryRuntime[\"util\"] & {\n readonly log?: ((message: string) => void) | undefined;\n };\n}\n\n/**\n * One warmer serves one workflow operation; create it per operation. Its\n * projection collections share one authenticated directory view, discovered\n * once per operation and discarded with the warmer. Prefetch is best-effort;\n * exact resolution still rejects unavailable evidence.\n */\nexport function createRuntimePrincipalPolicyWarmer(\n runtime: PrincipalPolicyWarmRuntime,\n options: { readonly preferLocalCurrent?: boolean } = {},\n): ReferencedPrincipalPolicyWarmer {\n const resolve = createRuntimePrincipalPolicyResolver(runtime, options);\n const operation = {};\n const resolveReference: PolicyResolver = async (input) => {\n if (!resolve)\n throw new ProjectionDependencyUnavailableError(\n \"Principal policies require private paged recovery\",\n );\n return resolve({\n ...input,\n recoveryBatch: input.recoveryBatch ?? operation,\n });\n };\n return Object.assign(\n (input: Parameters<ReferencedPrincipalPolicyWarmer>[0]) =>\n prefetchReferences(runtime, resolveReference, input),\n {\n resolveReference,\n resolveProjectionHistory: createRuntimeProjectionPolicyResolver(runtime),\n },\n );\n}\n\nasync function prefetchReferences(\n runtime: PrincipalPolicyWarmRuntime,\n resolve: PolicyResolver,\n input: Parameters<ReferencedPrincipalPolicyWarmer>[0],\n): Promise<void> {\n for (const reference of input.references) {\n try {\n assertProjectionVerificationCurrent(input.stillCurrent);\n const resolved = await resolve({ ...input, reference });\n assertProjectionVerificationCurrent(resolved.stillCurrent);\n } catch (error) {\n if (isProjectionVerificationCancelledError(error)) return;\n // Recovery already reports signature/authority failures. Keep them fatal.\n rethrowKeyingVerificationError(error);\n runtime.util.log?.(\n `Principal policy prefetch: ${reference.principalId}: ${errorMessage(error)}`,\n );\n }\n }\n}\n"]}
@@ -2,6 +2,7 @@ import type { OrganizationProvisioningResponse } from "../../internal/validators
2
2
  import type { DocumentProjectorRegistryInput } from "../../data/documents/documentKinds.js";
3
3
  import type { ExecSqlClientLike } from "../../data/sqlite/sqlSchema.js";
4
4
  import type { OrganizationProvisioningArtifacts } from "./organizationProvisioningArtifacts.js";
5
+ import type { ProvisionedPrincipalHistoryPrimer } from "./provisionedPrincipalHistory.js";
5
6
  type PersistOrganizationProvisioningStateInput = Pick<OrganizationProvisioningArtifacts, "bootstrap" | "initialAdminGroup" | "initialMemberGroup" | "initialOrganizationPolicy" | "organizationMetadataBootstrap" | "rootContainer" | "rootMetadataDocument" | "rootMetadataDocumentRequest" | "rosterProfileBootstrap" | "systemContainerBootstraps"> & {
6
7
  /** Forwarded to the bootstrap persist's in-mutex currency check. */
7
8
  readonly canStartDurableMutation?: (() => boolean) | undefined;
@@ -12,6 +13,8 @@ type PersistOrganizationProvisioningStateInput = Pick<OrganizationProvisioningAr
12
13
  readonly documentProjectors?: DocumentProjectorRegistryInput | undefined;
13
14
  readonly log?: ((message: string) => void) | undefined;
14
15
  readonly logError?: ((message: string | Error, cause?: unknown) => void) | undefined;
16
+ /** Seeds verified recovery progress once the bootstrap commits. */
17
+ readonly primePrincipalHistory?: ProvisionedPrincipalHistoryPrimer | undefined;
15
18
  readonly response: OrganizationProvisioningResponse;
16
19
  };
17
20
  export declare function persistOrganizationProvisioningState(input: PersistOrganizationProvisioningStateInput): Promise<void>;
@@ -3,7 +3,7 @@ import { persistedDocumentCreateStateFromResponse } from "../../data/documents/s
3
3
  import { createExecSql } from "../../data/sqlite/sqlSchema.js";
4
4
  import { persistRegistrationBootstrapFromExecSql } from "./persistRegistrationBootstrap.js";
5
5
  import { buildOrganizationProfileBootstrapInput, buildRosterProfileBootstrapInput, } from "./profileBootstrapPersistence.js";
6
- import { provisioningAcknowledgedAccessHeads } from "./provisioningAcknowledgement.js";
6
+ import { provisioningAcknowledgedAccessHeads, provisioningDiscoveryHeads, } from "./provisioningAcknowledgement.js";
7
7
  import { principalPolicyBundleFromInitialGroupRequest, principalPolicyBundleFromInitialOrganizationRequest, } from "./registrationPrincipalPolicyPersistence.js";
8
8
  function coreMetadataInitialUpdateCommitted(response, updateId) {
9
9
  return (updateId !== undefined &&
@@ -81,6 +81,19 @@ async function buildProvisioningPersistenceArtifacts(input) {
81
81
  ]);
82
82
  return {
83
83
  acknowledgedAccessHeads,
84
+ // Discovery lists the seeded profile documents; their signed heads are the
85
+ // ones this client just authored and the server acknowledged.
86
+ authoredDiscoveryHeads: provisioningDiscoveryHeads([
87
+ {
88
+ plan: input.rosterProfileBootstrap.profileDocument.plan,
89
+ response: input.response.rosterProfileDocument,
90
+ },
91
+ {
92
+ plan: input.organizationMetadataBootstrap.organizationProfileDocument
93
+ .plan,
94
+ response: input.response.organizationProfileDocument,
95
+ },
96
+ ]),
84
97
  initialAdminGroupPolicy,
85
98
  initialMemberGroupPolicy,
86
99
  initialOrganizationPolicy,
@@ -110,6 +123,7 @@ export async function persistOrganizationProvisioningState(input) {
110
123
  const artifacts = await buildProvisioningPersistenceArtifacts(input);
111
124
  const persisted = await persistRegistrationBootstrapFromExecSql(createExecSql(input.dbClient), {
112
125
  acknowledgedAccessHeads: artifacts.acknowledgedAccessHeads,
126
+ authoredDiscoveryHeads: artifacts.authoredDiscoveryHeads,
113
127
  canStartDurableMutation: input.canStartDurableMutation,
114
128
  onPersistQueued: input.onPersistQueued,
115
129
  containerId: input.containerId,
@@ -150,6 +164,18 @@ export async function persistOrganizationProvisioningState(input) {
150
164
  input.log?.(persisted
151
165
  ? "Local organization bootstrap persisted"
152
166
  : "Local organization bootstrap skipped: identity replaced");
167
+ if (persisted)
168
+ await input.primePrincipalHistory?.({
169
+ database: input.dbClient,
170
+ isCurrent: input.canStartDurableMutation ?? (() => true),
171
+ organizationId: input.response.organizationId,
172
+ policies: {
173
+ adminGroup: artifacts.initialAdminGroupPolicy,
174
+ memberGroup: artifacts.initialMemberGroupPolicy,
175
+ organization: artifacts.initialOrganizationPolicy,
176
+ },
177
+ userId: input.response.userId,
178
+ });
153
179
  }
154
180
  catch (error) {
155
181
  if (input.logError) {
@@ -1 +1 @@
1
- {"version":3,"file":"organizationProvisioningPersistence.js","sourceRoot":"","sources":["organizationProvisioningPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport type { OrganizationProvisioningResponse } from \"@tearleads/validators/response\";\nimport type { DocumentProjectorRegistryInput } from \"../../data/documents/documentKinds\";\nimport { persistedDocumentCreateStateFromResponse } from \"../../data/documents/shared/responses\";\nimport type { ExecSqlClientLike } from \"../../data/sqlite/sqlSchema\";\nimport { createExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { OrganizationProvisioningArtifacts } from \"./organizationProvisioningArtifacts\";\nimport { persistRegistrationBootstrapFromExecSql } from \"./persistRegistrationBootstrap\";\nimport {\n buildOrganizationProfileBootstrapInput,\n buildRosterProfileBootstrapInput,\n} from \"./profileBootstrapPersistence\";\nimport { provisioningAcknowledgedAccessHeads } from \"./provisioningAcknowledgement\";\nimport {\n principalPolicyBundleFromInitialGroupRequest,\n principalPolicyBundleFromInitialOrganizationRequest,\n} from \"./registrationPrincipalPolicyPersistence\";\n\ntype PersistOrganizationProvisioningStateInput = Pick<\n OrganizationProvisioningArtifacts,\n | \"bootstrap\"\n | \"initialAdminGroup\"\n | \"initialMemberGroup\"\n | \"initialOrganizationPolicy\"\n | \"organizationMetadataBootstrap\"\n | \"rootContainer\"\n | \"rootMetadataDocument\"\n | \"rootMetadataDocumentRequest\"\n | \"rosterProfileBootstrap\"\n | \"systemContainerBootstraps\"\n> & {\n /** Forwarded to the bootstrap persist's in-mutex currency check. */\n readonly canStartDurableMutation?: (() => boolean) | undefined;\n /** @internal Forwarded to the bootstrap persist; test-only seam. */\n readonly onPersistQueued?: (() => void) | undefined;\n readonly containerId: string;\n readonly dbClient: ExecSqlClientLike;\n readonly documentProjectors?: DocumentProjectorRegistryInput | undefined;\n readonly log?: ((message: string) => void) | undefined;\n readonly logError?:\n | ((message: string | Error, cause?: unknown) => void)\n | undefined;\n readonly response: OrganizationProvisioningResponse;\n};\n\ntype PersistBootstrapInput = Parameters<\n typeof persistRegistrationBootstrapFromExecSql\n>[1];\n\nfunction coreMetadataInitialUpdateCommitted(\n response: OrganizationProvisioningResponse,\n updateId?: string,\n): boolean {\n return (\n updateId !== undefined &&\n response.committedCoreMetadataUpdateIds.includes(updateId)\n );\n}\n\nfunction buildCoreContainerBootstrapInput(\n response: OrganizationProvisioningResponse,\n container: OrganizationProvisioningResponse[\"organizationMetadataContainer\"],\n bootstrap: Pick<\n OrganizationProvisioningArtifacts[\"rosterProfileBootstrap\"],\n | \"containerId\"\n | \"containerMetadataDocument\"\n | \"containerMetadataInitialUpdate\"\n | \"containerRequest\"\n | \"systemSlot\"\n >,\n): NonNullable<PersistBootstrapInput[\"organizationMetadataContainer\"]> {\n return {\n accessEpoch: container.container.manifestHead.epoch,\n accessStateHash: container.container.manifestHead.manifestHash,\n containerId: bootstrap.containerId,\n createdAt: container.container.createdAt,\n metadataDocumentId: container.metadataDocument.id,\n metadataInitialUpdate: bootstrap.containerMetadataInitialUpdate,\n metadataInitialUpdateCommitted: coreMetadataInitialUpdateCommitted(\n response,\n bootstrap.containerRequest.initialMetadataSync.outgoingUpdates[0]?.id,\n ),\n metadataSnapshot: bytesToBase64(bootstrap.containerMetadataInitialUpdate),\n metadataState: persistedDocumentCreateStateFromResponse(\n bootstrap.containerMetadataDocument.plan,\n container.metadataDocument,\n ),\n systemSlot: bootstrap.systemSlot,\n updatedAt: container.container.updatedAt,\n };\n}\n\nfunction buildSystemContainersBootstrapInput(\n input: PersistOrganizationProvisioningStateInput,\n): PersistBootstrapInput[\"systemContainers\"] {\n const responses = input.response.systemContainers;\n if (responses.length === 0) {\n return;\n }\n const responseByContainerId = new Map(\n responses.map((response) => [response.container.containerId, response]),\n );\n const entries: NonNullable<PersistBootstrapInput[\"systemContainers\"]> = [];\n for (const bootstrap of input.systemContainerBootstraps) {\n const response = responseByContainerId.get(bootstrap.containerId);\n if (!response) {\n continue;\n }\n entries.push({\n accessEpoch: response.container.manifestHead.epoch,\n accessStateHash: response.container.manifestHead.manifestHash,\n containerId: bootstrap.containerId,\n createdAt: response.container.createdAt,\n icon: bootstrap.icon,\n metadataDocumentId: response.metadataDocument.id,\n metadataSnapshot: bytesToBase64(bootstrap.containerMetadataInitialUpdate),\n metadataState: persistedDocumentCreateStateFromResponse(\n bootstrap.containerMetadataDocument.plan,\n response.metadataDocument,\n ),\n name: bootstrap.name,\n systemSlot: bootstrap.systemSlot,\n updatedAt: response.container.updatedAt,\n });\n }\n return entries.length > 0 ? entries : undefined;\n}\n\nasync function buildProvisioningPersistenceArtifacts(\n input: PersistOrganizationProvisioningStateInput,\n) {\n const acknowledgedAccessHeads = await provisioningAcknowledgedAccessHeads({\n expectedOrganizationId: input.rootContainer.plan.state.organizationId,\n expectedUserId: input.rootContainer.plan.event.signerUserId,\n organizationMetadata: {\n containerPlan: input.organizationMetadataBootstrap.containerPlan.plan,\n metadataDocumentPlan:\n input.organizationMetadataBootstrap.containerMetadataDocument.plan,\n },\n organizationProfileDocumentPlan:\n input.organizationMetadataBootstrap.organizationProfileDocument.plan,\n response: input.response,\n rootContainerPlan: input.rootContainer.plan,\n rootMetadataDocumentPlan: input.rootMetadataDocument.plan,\n rosterProfile: {\n containerPlan: input.rosterProfileBootstrap.containerPlan.plan,\n metadataDocumentPlan:\n input.rosterProfileBootstrap.containerMetadataDocument.plan,\n },\n rosterProfileDocumentPlan:\n input.rosterProfileBootstrap.profileDocument.plan,\n systemContainers: input.systemContainerBootstraps.map((bootstrap) => ({\n containerPlan: bootstrap.containerPlan.plan,\n metadataDocumentPlan: bootstrap.containerMetadataDocument.plan,\n })),\n });\n const [\n initialAdminGroupPolicy,\n initialMemberGroupPolicy,\n initialOrganizationPolicy,\n ] = await Promise.all([\n principalPolicyBundleFromInitialGroupRequest(input.initialAdminGroup),\n principalPolicyBundleFromInitialGroupRequest(input.initialMemberGroup),\n principalPolicyBundleFromInitialOrganizationRequest(\n input.initialOrganizationPolicy,\n ),\n ]);\n return {\n acknowledgedAccessHeads,\n initialAdminGroupPolicy,\n initialMemberGroupPolicy,\n initialOrganizationPolicy,\n organizationMetadataContainer: buildCoreContainerBootstrapInput(\n input.response,\n input.response.organizationMetadataContainer,\n input.organizationMetadataBootstrap,\n ),\n organizationProfileDocument: buildOrganizationProfileBootstrapInput({\n containerId: input.organizationMetadataBootstrap.containerId,\n materializedDocument:\n input.organizationMetadataBootstrap.organizationProfileDocument,\n request:\n input.organizationMetadataBootstrap.organizationProfileDocumentRequest,\n response: input.response,\n snapshot: input.organizationMetadataBootstrap.organizationProfileSnapshot,\n }),\n rosterProfileContainer: input.response.rosterProfileContainer\n ? buildCoreContainerBootstrapInput(\n input.response,\n input.response.rosterProfileContainer,\n input.rosterProfileBootstrap,\n )\n : undefined,\n rosterProfileDocument: buildRosterProfileBootstrapInput({\n containerId: input.rosterProfileBootstrap.containerId,\n initialUpdate: input.rosterProfileBootstrap.profileDocumentInitialUpdate,\n materializedDocument: input.rosterProfileBootstrap.profileDocument,\n request: input.rosterProfileBootstrap.profileDocumentRequest,\n response: input.response,\n }),\n systemContainers: buildSystemContainersBootstrapInput(input),\n };\n}\n\nexport async function persistOrganizationProvisioningState(\n input: PersistOrganizationProvisioningStateInput,\n): Promise<void> {\n try {\n const artifacts = await buildProvisioningPersistenceArtifacts(input);\n const persisted = await persistRegistrationBootstrapFromExecSql(\n createExecSql(input.dbClient),\n {\n acknowledgedAccessHeads: artifacts.acknowledgedAccessHeads,\n canStartDurableMutation: input.canStartDurableMutation,\n onPersistQueued: input.onPersistQueued,\n containerId: input.containerId,\n documentProjectors: input.documentProjectors,\n initialAdminGroupPolicy: artifacts.initialAdminGroupPolicy,\n initialMemberGroupPolicy: artifacts.initialMemberGroupPolicy,\n initialOrganizationPolicy: artifacts.initialOrganizationPolicy,\n organizationId: input.response.organizationId,\n // The provisioning response does not expose the root container's own\n // timestamps. Its metadata document is created in the same transaction,\n // so its server timestamp is the acknowledged remote anchor for the\n // locally persisted root row.\n rootContainerServerTimestamp:\n input.response.rootMetadataDocument.createdAt,\n rootMetadataAccessEpoch: input.response.rootMetadataAccessEpoch,\n rootMetadataAccessStateHash: input.response.rootMetadataAccessStateHash,\n rootMetadataDocumentId: input.response.rootMetadataDocumentId,\n rootMetadataInitialUpdate: input.bootstrap.initialUpdate,\n rootMetadataInitialUpdateCommitted: coreMetadataInitialUpdateCommitted(\n input.response,\n input.rootMetadataDocumentRequest.initialSync.outgoingUpdates[0]?.id,\n ),\n rootMetadataSnapshot: bytesToBase64(input.bootstrap.initialUpdate),\n rootMetadataState: persistedDocumentCreateStateFromResponse(\n input.rootMetadataDocument.plan,\n input.response.rootMetadataDocument,\n ),\n ...(artifacts.rosterProfileContainer\n ? { rosterProfileContainer: artifacts.rosterProfileContainer }\n : {}),\n organizationMetadataContainer: artifacts.organizationMetadataContainer,\n ...(artifacts.organizationProfileDocument\n ? {\n organizationProfileDocument:\n artifacts.organizationProfileDocument,\n }\n : {}),\n ...(artifacts.rosterProfileDocument\n ? { rosterProfileDocument: artifacts.rosterProfileDocument }\n : {}),\n ...(artifacts.systemContainers\n ? { systemContainers: artifacts.systemContainers }\n : {}),\n userId: input.response.userId,\n },\n );\n input.log?.(\n persisted\n ? \"Local organization bootstrap persisted\"\n : \"Local organization bootstrap skipped: identity replaced\",\n );\n } catch (error: unknown) {\n if (input.logError) {\n input.logError(\"Failed to persist registration data\", error);\n } else {\n console.error(\"Failed to persist registration data:\", error);\n }\n throw error;\n }\n}\n"]}
1
+ {"version":3,"file":"organizationProvisioningPersistence.js","sourceRoot":"","sources":["organizationProvisioningPersistence.ts"],"names":[],"mappings":"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","sourcesContent":["import { bytesToBase64 } from \"@tearleads/encoding\";\nimport type { OrganizationProvisioningResponse } from \"@tearleads/validators/response\";\nimport type { DocumentProjectorRegistryInput } from \"../../data/documents/documentKinds\";\nimport { persistedDocumentCreateStateFromResponse } from \"../../data/documents/shared/responses\";\nimport type { ExecSqlClientLike } from \"../../data/sqlite/sqlSchema\";\nimport { createExecSql } from \"../../data/sqlite/sqlSchema\";\nimport type { OrganizationProvisioningArtifacts } from \"./organizationProvisioningArtifacts\";\nimport { persistRegistrationBootstrapFromExecSql } from \"./persistRegistrationBootstrap\";\nimport {\n buildOrganizationProfileBootstrapInput,\n buildRosterProfileBootstrapInput,\n} from \"./profileBootstrapPersistence\";\nimport type { ProvisionedPrincipalHistoryPrimer } from \"./provisionedPrincipalHistory\";\nimport {\n provisioningAcknowledgedAccessHeads,\n provisioningDiscoveryHeads,\n} from \"./provisioningAcknowledgement\";\nimport {\n principalPolicyBundleFromInitialGroupRequest,\n principalPolicyBundleFromInitialOrganizationRequest,\n} from \"./registrationPrincipalPolicyPersistence\";\n\ntype PersistOrganizationProvisioningStateInput = Pick<\n OrganizationProvisioningArtifacts,\n | \"bootstrap\"\n | \"initialAdminGroup\"\n | \"initialMemberGroup\"\n | \"initialOrganizationPolicy\"\n | \"organizationMetadataBootstrap\"\n | \"rootContainer\"\n | \"rootMetadataDocument\"\n | \"rootMetadataDocumentRequest\"\n | \"rosterProfileBootstrap\"\n | \"systemContainerBootstraps\"\n> & {\n /** Forwarded to the bootstrap persist's in-mutex currency check. */\n readonly canStartDurableMutation?: (() => boolean) | undefined;\n /** @internal Forwarded to the bootstrap persist; test-only seam. */\n readonly onPersistQueued?: (() => void) | undefined;\n readonly containerId: string;\n readonly dbClient: ExecSqlClientLike;\n readonly documentProjectors?: DocumentProjectorRegistryInput | undefined;\n readonly log?: ((message: string) => void) | undefined;\n readonly logError?:\n | ((message: string | Error, cause?: unknown) => void)\n | undefined;\n /** Seeds verified recovery progress once the bootstrap commits. */\n readonly primePrincipalHistory?:\n | ProvisionedPrincipalHistoryPrimer\n | undefined;\n readonly response: OrganizationProvisioningResponse;\n};\n\ntype PersistBootstrapInput = Parameters<\n typeof persistRegistrationBootstrapFromExecSql\n>[1];\n\nfunction coreMetadataInitialUpdateCommitted(\n response: OrganizationProvisioningResponse,\n updateId?: string,\n): boolean {\n return (\n updateId !== undefined &&\n response.committedCoreMetadataUpdateIds.includes(updateId)\n );\n}\n\nfunction buildCoreContainerBootstrapInput(\n response: OrganizationProvisioningResponse,\n container: OrganizationProvisioningResponse[\"organizationMetadataContainer\"],\n bootstrap: Pick<\n OrganizationProvisioningArtifacts[\"rosterProfileBootstrap\"],\n | \"containerId\"\n | \"containerMetadataDocument\"\n | \"containerMetadataInitialUpdate\"\n | \"containerRequest\"\n | \"systemSlot\"\n >,\n): NonNullable<PersistBootstrapInput[\"organizationMetadataContainer\"]> {\n return {\n accessEpoch: container.container.manifestHead.epoch,\n accessStateHash: container.container.manifestHead.manifestHash,\n containerId: bootstrap.containerId,\n createdAt: container.container.createdAt,\n metadataDocumentId: container.metadataDocument.id,\n metadataInitialUpdate: bootstrap.containerMetadataInitialUpdate,\n metadataInitialUpdateCommitted: coreMetadataInitialUpdateCommitted(\n response,\n bootstrap.containerRequest.initialMetadataSync.outgoingUpdates[0]?.id,\n ),\n metadataSnapshot: bytesToBase64(bootstrap.containerMetadataInitialUpdate),\n metadataState: persistedDocumentCreateStateFromResponse(\n bootstrap.containerMetadataDocument.plan,\n container.metadataDocument,\n ),\n systemSlot: bootstrap.systemSlot,\n updatedAt: container.container.updatedAt,\n };\n}\n\nfunction buildSystemContainersBootstrapInput(\n input: PersistOrganizationProvisioningStateInput,\n): PersistBootstrapInput[\"systemContainers\"] {\n const responses = input.response.systemContainers;\n if (responses.length === 0) {\n return;\n }\n const responseByContainerId = new Map(\n responses.map((response) => [response.container.containerId, response]),\n );\n const entries: NonNullable<PersistBootstrapInput[\"systemContainers\"]> = [];\n for (const bootstrap of input.systemContainerBootstraps) {\n const response = responseByContainerId.get(bootstrap.containerId);\n if (!response) {\n continue;\n }\n entries.push({\n accessEpoch: response.container.manifestHead.epoch,\n accessStateHash: response.container.manifestHead.manifestHash,\n containerId: bootstrap.containerId,\n createdAt: response.container.createdAt,\n icon: bootstrap.icon,\n metadataDocumentId: response.metadataDocument.id,\n metadataSnapshot: bytesToBase64(bootstrap.containerMetadataInitialUpdate),\n metadataState: persistedDocumentCreateStateFromResponse(\n bootstrap.containerMetadataDocument.plan,\n response.metadataDocument,\n ),\n name: bootstrap.name,\n systemSlot: bootstrap.systemSlot,\n updatedAt: response.container.updatedAt,\n });\n }\n return entries.length > 0 ? entries : undefined;\n}\n\nasync function buildProvisioningPersistenceArtifacts(\n input: PersistOrganizationProvisioningStateInput,\n) {\n const acknowledgedAccessHeads = await provisioningAcknowledgedAccessHeads({\n expectedOrganizationId: input.rootContainer.plan.state.organizationId,\n expectedUserId: input.rootContainer.plan.event.signerUserId,\n organizationMetadata: {\n containerPlan: input.organizationMetadataBootstrap.containerPlan.plan,\n metadataDocumentPlan:\n input.organizationMetadataBootstrap.containerMetadataDocument.plan,\n },\n organizationProfileDocumentPlan:\n input.organizationMetadataBootstrap.organizationProfileDocument.plan,\n response: input.response,\n rootContainerPlan: input.rootContainer.plan,\n rootMetadataDocumentPlan: input.rootMetadataDocument.plan,\n rosterProfile: {\n containerPlan: input.rosterProfileBootstrap.containerPlan.plan,\n metadataDocumentPlan:\n input.rosterProfileBootstrap.containerMetadataDocument.plan,\n },\n rosterProfileDocumentPlan:\n input.rosterProfileBootstrap.profileDocument.plan,\n systemContainers: input.systemContainerBootstraps.map((bootstrap) => ({\n containerPlan: bootstrap.containerPlan.plan,\n metadataDocumentPlan: bootstrap.containerMetadataDocument.plan,\n })),\n });\n const [\n initialAdminGroupPolicy,\n initialMemberGroupPolicy,\n initialOrganizationPolicy,\n ] = await Promise.all([\n principalPolicyBundleFromInitialGroupRequest(input.initialAdminGroup),\n principalPolicyBundleFromInitialGroupRequest(input.initialMemberGroup),\n principalPolicyBundleFromInitialOrganizationRequest(\n input.initialOrganizationPolicy,\n ),\n ]);\n return {\n acknowledgedAccessHeads,\n // Discovery lists the seeded profile documents; their signed heads are the\n // ones this client just authored and the server acknowledged.\n authoredDiscoveryHeads: provisioningDiscoveryHeads([\n {\n plan: input.rosterProfileBootstrap.profileDocument.plan,\n response: input.response.rosterProfileDocument,\n },\n {\n plan: input.organizationMetadataBootstrap.organizationProfileDocument\n .plan,\n response: input.response.organizationProfileDocument,\n },\n ]),\n initialAdminGroupPolicy,\n initialMemberGroupPolicy,\n initialOrganizationPolicy,\n organizationMetadataContainer: buildCoreContainerBootstrapInput(\n input.response,\n input.response.organizationMetadataContainer,\n input.organizationMetadataBootstrap,\n ),\n organizationProfileDocument: buildOrganizationProfileBootstrapInput({\n containerId: input.organizationMetadataBootstrap.containerId,\n materializedDocument:\n input.organizationMetadataBootstrap.organizationProfileDocument,\n request:\n input.organizationMetadataBootstrap.organizationProfileDocumentRequest,\n response: input.response,\n snapshot: input.organizationMetadataBootstrap.organizationProfileSnapshot,\n }),\n rosterProfileContainer: input.response.rosterProfileContainer\n ? buildCoreContainerBootstrapInput(\n input.response,\n input.response.rosterProfileContainer,\n input.rosterProfileBootstrap,\n )\n : undefined,\n rosterProfileDocument: buildRosterProfileBootstrapInput({\n containerId: input.rosterProfileBootstrap.containerId,\n initialUpdate: input.rosterProfileBootstrap.profileDocumentInitialUpdate,\n materializedDocument: input.rosterProfileBootstrap.profileDocument,\n request: input.rosterProfileBootstrap.profileDocumentRequest,\n response: input.response,\n }),\n systemContainers: buildSystemContainersBootstrapInput(input),\n };\n}\n\nexport async function persistOrganizationProvisioningState(\n input: PersistOrganizationProvisioningStateInput,\n): Promise<void> {\n try {\n const artifacts = await buildProvisioningPersistenceArtifacts(input);\n const persisted = await persistRegistrationBootstrapFromExecSql(\n createExecSql(input.dbClient),\n {\n acknowledgedAccessHeads: artifacts.acknowledgedAccessHeads,\n authoredDiscoveryHeads: artifacts.authoredDiscoveryHeads,\n canStartDurableMutation: input.canStartDurableMutation,\n onPersistQueued: input.onPersistQueued,\n containerId: input.containerId,\n documentProjectors: input.documentProjectors,\n initialAdminGroupPolicy: artifacts.initialAdminGroupPolicy,\n initialMemberGroupPolicy: artifacts.initialMemberGroupPolicy,\n initialOrganizationPolicy: artifacts.initialOrganizationPolicy,\n organizationId: input.response.organizationId,\n // The provisioning response does not expose the root container's own\n // timestamps. Its metadata document is created in the same transaction,\n // so its server timestamp is the acknowledged remote anchor for the\n // locally persisted root row.\n rootContainerServerTimestamp:\n input.response.rootMetadataDocument.createdAt,\n rootMetadataAccessEpoch: input.response.rootMetadataAccessEpoch,\n rootMetadataAccessStateHash: input.response.rootMetadataAccessStateHash,\n rootMetadataDocumentId: input.response.rootMetadataDocumentId,\n rootMetadataInitialUpdate: input.bootstrap.initialUpdate,\n rootMetadataInitialUpdateCommitted: coreMetadataInitialUpdateCommitted(\n input.response,\n input.rootMetadataDocumentRequest.initialSync.outgoingUpdates[0]?.id,\n ),\n rootMetadataSnapshot: bytesToBase64(input.bootstrap.initialUpdate),\n rootMetadataState: persistedDocumentCreateStateFromResponse(\n input.rootMetadataDocument.plan,\n input.response.rootMetadataDocument,\n ),\n ...(artifacts.rosterProfileContainer\n ? { rosterProfileContainer: artifacts.rosterProfileContainer }\n : {}),\n organizationMetadataContainer: artifacts.organizationMetadataContainer,\n ...(artifacts.organizationProfileDocument\n ? {\n organizationProfileDocument:\n artifacts.organizationProfileDocument,\n }\n : {}),\n ...(artifacts.rosterProfileDocument\n ? { rosterProfileDocument: artifacts.rosterProfileDocument }\n : {}),\n ...(artifacts.systemContainers\n ? { systemContainers: artifacts.systemContainers }\n : {}),\n userId: input.response.userId,\n },\n );\n input.log?.(\n persisted\n ? \"Local organization bootstrap persisted\"\n : \"Local organization bootstrap skipped: identity replaced\",\n );\n if (persisted)\n await input.primePrincipalHistory?.({\n database: input.dbClient,\n isCurrent: input.canStartDurableMutation ?? (() => true),\n organizationId: input.response.organizationId,\n policies: {\n adminGroup: artifacts.initialAdminGroupPolicy,\n memberGroup: artifacts.initialMemberGroupPolicy,\n organization: artifacts.initialOrganizationPolicy,\n },\n userId: input.response.userId,\n });\n } catch (error: unknown) {\n if (input.logError) {\n input.logError(\"Failed to persist registration data\", error);\n } else {\n console.error(\"Failed to persist registration data:\", error);\n }\n throw error;\n }\n}\n"]}
@@ -1,6 +1,7 @@
1
1
  import type { ContainerSystemSlot } from "../../internal/validators/containerSystemSlot.js";
2
2
  import type { PrincipalPolicyBundleResponse } from "../../internal/validators/response/index.js";
3
3
  import type { DocumentProjectorRegistryInput } from "../../data/documents/documentKinds.js";
4
+ import { type AuthoredDiscoveryHead } from "../../data/persistence/documents/documentDiscoveryEvidencePersistence.js";
4
5
  import { type LocallyAcknowledgedAccessManifestHead } from "../../data/persistence/locallyAcknowledgedCheckpointPersistence.js";
5
6
  import type { DocumentRecord } from "../../data/sqlite/documentPersistence.js";
6
7
  import { type ExecSql, type ExecSqlClientLike } from "../../data/sqlite/sqlSchema.js";
@@ -27,6 +28,8 @@ interface ProvisionedProfileDocumentBootstrapInput {
27
28
  }
28
29
  export interface RegistrationBootstrapInput {
29
30
  acknowledgedAccessHeads: readonly LocallyAcknowledgedAccessManifestHead[];
31
+ /** Seeded documents' acknowledged signed heads; see the discovery cache. */
32
+ authoredDiscoveryHeads: readonly AuthoredDiscoveryHead[];
30
33
  /** Checked inside the mutation queue claim; false skips every write. */
31
34
  canStartDurableMutation?: (() => boolean) | undefined;
32
35
  /**
@@ -2,10 +2,12 @@ import { createDocument, encodeVersionVector, importUpdates, } from "../../inter
2
2
  import { getScopedPeerSeed } from "../../data/crdtPeerSeed.js";
3
3
  import { createPendingUpdateFields } from "../../data/documents/documentSync.js";
4
4
  import { sqlContainerContentsPersistence, } from "../../data/persistence/container-contents/containerContentsPersistence.js";
5
+ import { primeAuthoredDocumentDiscoveryHeads, } from "../../data/persistence/documents/documentDiscoveryEvidencePersistence.js";
5
6
  import { DOCUMENTS_APP_KIND, sqlDocumentsPersistence, } from "../../data/persistence/documents/documentsPersistence.js";
6
7
  import { advanceLocallyAcknowledgedAccessManifestHeadsAtomically, } from "../../data/persistence/locallyAcknowledgedCheckpointPersistence.js";
8
+ import { documentContainerProjectionTables } from "../../data/sqlite/schema.js";
7
9
  import { getClientSQLitePersistenceRuntime } from "../../data/sqlite/sqlitePersistenceRuntime.js";
8
- import { createExecSql, runSerializedSqlMutation, } from "../../data/sqlite/sqlSchema.js";
10
+ import { createExecSql, ensureSqlTables, runSerializedSqlMutation, } from "../../data/sqlite/sqlSchema.js";
9
11
  import { persistDocumentState } from "../documents/persistence.js";
10
12
  import { ORGANIZATION_PROFILE_DOCUMENT_KIND } from "../organizations/organizationProfile.js";
11
13
  import { ORGANIZATION_METADATA_CONTAINER_NAME, ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME, ROSTER_PROFILE_DOCUMENT_KIND, } from "../organizations/rosterProfileContainer.js";
@@ -175,6 +177,7 @@ export async function persistRegistrationBootstrapFromExecSql(execSql, input) {
175
177
  // Idempotent DDL stays outside the atomic boundary.
176
178
  await sqlContainerContentsPersistence.ensureSchema(lockedExecSql);
177
179
  await sqlDocumentsPersistence.ensureSchema(lockedExecSql);
180
+ await ensureSqlTables(lockedExecSql, documentContainerProjectionTables);
178
181
  // Pre-commit currency guard: the write sequence awaits real work, so
179
182
  // the identity can be replaced mid-sequence. The guard runs
180
183
  // synchronously with the COMMIT dispatch, so a refusal rolls the whole
@@ -197,6 +200,9 @@ export async function persistRegistrationBootstrapFromExecSql(execSql, input) {
197
200
  await persistNamedChildContainerBootstrap(lockedExecSql, input, input.organizationMetadataContainer, ORGANIZATION_METADATA_CONTAINER_NAME);
198
201
  await persistProfileDocumentBootstrap(lockedExecSql, input, input.organizationProfileDocument, ORGANIZATION_PROFILE_DOCUMENT_KIND);
199
202
  await persistSystemContainersBootstrap(lockedExecSql, input);
203
+ // After the checkpoints above: discovery reuses a cached head only
204
+ // while its access-manifest checkpoint still matches.
205
+ await primeAuthoredDocumentDiscoveryHeads(lockedExecSql, input.authoredDiscoveryHeads);
200
206
  }, () => !input.canStartDurableMutation || input.canStartDurableMutation());
201
207
  return committed;
202
208
  });
@@ -1 +1 @@
1
- {"version":3,"file":"persistRegistrationBootstrap.js","sourceRoot":"","sources":["persistRegistrationBootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,aAAa,GACd,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAE5D,OAAO,EAAE,yBAAyB,EAAE,MAAM,mCAAmC,CAAC;AAC9E,OAAO,EAEL,+BAA+B,GAChC,MAAM,wEAAwE,CAAC;AAChF,OAAO,EACL,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,uDAAuD,CAAC;AAC/D,OAAO,EACL,uDAAuD,GAExD,MAAM,iEAAiE,CAAC;AAEzE,OAAO,EAAE,iCAAiC,EAAE,MAAM,4CAA4C,CAAC;AAC/F,OAAO,EACL,aAAa,EAGb,wBAAwB,GACzB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,kCAAkC,EAAE,MAAM,sCAAsC,CAAC;AAC1F,OAAO,EACL,oCAAoC,EACpC,0CAA0C,EAC1C,4BAA4B,GAC7B,MAAM,yCAAyC,CAAC;AACjD,OAAO,EAAE,qCAAqC,EAAE,MAAM,uCAAuC,CAAC;AAC9F,OAAO,EAAE,oCAAoC,EAAE,MAAM,0CAA0C,CAAC;AA+EhG,KAAK,UAAU,oCAAoC,CACjD,OAAgB,EAChB,KAMC;IAED,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAC5B,MAAM,aAAa,GAAG,SAAS,CAAC,aAAa,CAAC;IAC9C,MAAM,MAAM,GAA4B;QACtC,WAAW,EAAE,SAAS,CAAC,WAAW;QAClC,eAAe,EAAE,SAAS,CAAC,eAAe;QAC1C,UAAU,EAAE,SAAS,CAAC,kBAAkB;QACxC,EAAE,EAAE,SAAS,CAAC,WAAW;QACzB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,SAAS,CAAC,gBAAgB;QAC3C,kBAAkB,EAAE,EAAE;QACtB,gBAAgB,EAAE,aAAa,CAAC,gBAAgB,IAAI,IAAI;QACxD,kBAAkB,EAAE,aAAa,CAAC,kBAAkB,IAAI,IAAI;QAC5D,sBAAsB,EAAE,aAAa,CAAC,sBAAsB,IAAI,IAAI;KACrE,CAAC;IACF,MAAM,+BAA+B,CAAC,aAAa,CACjD,OAAO,EACP;QACE,EAAE,EAAE,SAAS,CAAC,WAAW;QACzB,oBAAoB,EAAE,OAAO;QAC7B,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,kBAAkB,EAAE,SAAS,CAAC,kBAAkB;QAChD,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,EACD,MAAM,EACN;QACE,cAAc,EAAE,SAAS,CAAC,SAAS;QACnC,gBAAgB,EAAE;YAChB,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,SAAS,EAAE,SAAS,CAAC,SAAS;SAC/B;KACF,CACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,6BAA6B,CAC1C,OAAgB,EAChB,KAAiC;IAEjC,MAAM,UAAU,GAA4B;QAC1C,WAAW,EAAE,KAAK,CAAC,uBAAuB;QAC1C,eAAe,EAAE,KAAK,CAAC,2BAA2B;QAClD,UAAU,EAAE,KAAK,CAAC,sBAAsB;QACxC,EAAE,EAAE,KAAK,CAAC,WAAW;QACrB,aAAa,EAAE,IAAI;QACnB,eAAe,EAAE,KAAK,CAAC,oBAAoB;QAC3C,kBAAkB,EAAE,EAAE;QACtB,gBAAgB,EAAE,KAAK,CAAC,iBAAiB,CAAC,gBAAgB,IAAI,IAAI;QAClE,kBAAkB,EAAE,KAAK,CAAC,iBAAiB,CAAC,kBAAkB,IAAI,IAAI;QACtE,sBAAsB,EACpB,KAAK,CAAC,iBAAiB,CAAC,sBAAsB,IAAI,IAAI;KACzD,CAAC;IACF,MAAM,+BAA+B,CAAC,aAAa,CACjD,OAAO,EACP;QACE,EAAE,EAAE,KAAK,CAAC,WAAW;QACrB,oBAAoB,EAAE,OAAO;QAC7B,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,QAAQ,EAAE,IAAI;QACd,kBAAkB,EAAE,KAAK,CAAC,sBAAsB;QAChD,IAAI,EAAE,GAAG;QACT,IAAI,EAAE,IAAI;KACX,EACD,UAAU,EACV;QACE,cAAc,EAAE,KAAK,CAAC,4BAA4B;QAClD,gBAAgB,EAAE;YAChB,SAAS,EAAE,KAAK,CAAC,4BAA4B;YAC7C,SAAS,EAAE,KAAK,CAAC,4BAA4B;SAC9C;KACF,CACF,CAAC;IACF,MAAM,qCAAqC,CACzC,OAAO,EACP,KAAK,CAAC,WAAW,EACjB,KAAK,CAAC,yBAAyB,EAC/B,KAAK,CAAC,kCAAkC,CACzC,CAAC;AACJ,CAAC;AAED,kFAAkF;AAClF,mFAAmF;AACnF,KAAK,UAAU,mCAAmC,CAChD,OAAgB,EAChB,KAAiC,EACjC,SAA+D,EAC/D,IAAY;IAEZ,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO;IACT,CAAC;IAED,MAAM,oCAAoC,CAAC,OAAO,EAAE;QAClD,SAAS;QACT,IAAI,EAAE,IAAI;QACV,IAAI;QACJ,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,QAAQ,EACN,SAAS,KAAK,KAAK,CAAC,6BAA6B;YAC/C,CAAC,CAAC,IAAI;YACN,CAAC,CAAC,KAAK,CAAC,WAAW;KACxB,CAAC,CAAC;IACH,MAAM,qCAAqC,CACzC,OAAO,EACP,SAAS,CAAC,WAAW,EACrB,SAAS,CAAC,qBAAqB,EAC/B,SAAS,CAAC,8BAA8B,CACzC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gCAAgC,CAC7C,OAAgB,EAChB,KAAiC;IAEjC,MAAM,gBAAgB,GAAG,KAAK,CAAC,gBAAgB,CAAC;IAChD,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,OAAO;IACT,CAAC;IAED,KAAK,MAAM,eAAe,IAAI,gBAAgB,EAAE,CAAC;QAC/C,MAAM,oCAAoC,CAAC,OAAO,EAAE;YAClD,SAAS,EAAE,eAAe;YAC1B,IAAI,EAAE,eAAe,CAAC,IAAI;YAC1B,IAAI,EAAE,eAAe,CAAC,IAAI;YAC1B,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,QAAQ,EAAE,KAAK,CAAC,WAAW;SAC5B,CAAC,CAAC;QACH,yEAAyE;QACzE,0EAA0E;QAC1E,8DAA8D;IAChE,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,uEAAuE;AACvE,uEAAuE;AACvE,KAAK,UAAU,+BAA+B,CAC5C,OAAgB,EAChB,KAAiC,EACjC,eAAqE,EACrE,YAAoB;IAEpB,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO;IACT,CAAC;IAED,MAAM,+BAA+B,CAAC,OAAO,EAAE;QAC7C,GAAG,eAAe;QAClB,YAAY;QACZ,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;KAC7C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,+BAA+B,CACnD,OAAgB,EAChB,KAcC;IAED,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,MAAM,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IAC9E,aAAa,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC;IAC1C,MAAM,aAAa,GAAG,KAAK,CAAC,sBAAsB;QAChD,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,SAAS,CAAC,CAAC;IAElE,MAAM,oBAAoB,CAAC;QACzB,UAAU,EAAE,GAAG;QACf,aAAa,EAAE,IAAI;QACnB,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,IAAI,EAAE;QAClD,OAAO;QACP,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,KAAK,EAAE;YACL,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,eAAe,EAAE,KAAK,CAAC,eAAe;YACtC,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,gBAAgB,EAAE,KAAK,CAAC,aAAa,CAAC,gBAAgB,IAAI,IAAI;YAC9D,UAAU,EAAE,KAAK,CAAC,UAAU;YAC5B,uEAAuE;YACvE,kEAAkE;YAClE,oBAAoB,EAAE,OAAO;YAC7B,kBAAkB,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,IAAI,IAAI;YAClE,YAAY,EAAE,KAAK,CAAC,YAAY;YAChC,sBAAsB,EACpB,KAAK,CAAC,aAAa,CAAC,sBAAsB,IAAI,IAAI;YACpD,qEAAqE;YACrE,8CAA8C;YAC9C,kBAAkB,EAAE,mBAAmB,CAAC,GAAG,CAAC;SAC7C;QACD,aAAa;QACb,WAAW,EAAE,uBAAuB;KACrC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,uCAAuC,CAC3D,OAAgB,EAChB,KAAiC;IAEjC,KAAK,CAAC,eAAe,EAAE,EAAE,CAAC;IAC1B,OAAO,wBAAwB,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,EAAE;QAC/D,qEAAqE;QACrE,sEAAsE;QACtE,qEAAqE;QACrE,sDAAsD;QACtD,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,KAAK,CAAC,uBAAuB,EAAE,EAAE,CAAC;YACtE,OAAO,KAAK,CAAC;QACf,CAAC;QACD,oDAAoD;QACpD,MAAM,+BAA+B,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAClE,MAAM,uBAAuB,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC1D,qEAAqE;QACrE,4DAA4D;QAC5D,uEAAuE;QACvE,wEAAwE;QACxE,+DAA+D;QAC/D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,iCAAiC,CAC3D,aAAa,CACd,CAAC,kBAAkB,CAClB,KAAK,IAAI,EAAE;YACT,MAAM,uDAAuD,CAAC;gBAC5D,OAAO,EAAE,aAAa;gBACtB,KAAK,EAAE,KAAK,CAAC,uBAAuB;aACrC,CAAC,CAAC;YACH,MAAM,oCAAoC,CAAC;gBACzC,UAAU,EAAE,KAAK,CAAC,uBAAuB;gBACzC,OAAO,EAAE,aAAa;gBACtB,WAAW,EAAE,KAAK,CAAC,wBAAwB;gBAC3C,YAAY,EAAE,KAAK,CAAC,yBAAyB;aAC9C,CAAC,CAAC;YACH,MAAM,6BAA6B,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YAC1D,MAAM,mCAAmC,CACvC,aAAa,EACb,KAAK,EACL,KAAK,CAAC,sBAAsB,EAC5B,0CAA0C,CAC3C,CAAC;YACF,MAAM,+BAA+B,CACnC,aAAa,EACb,KAAK,EACL,KAAK,CAAC,qBAAqB,EAC3B,4BAA4B,CAC7B,CAAC;YACF,MAAM,mCAAmC,CACvC,aAAa,EACb,KAAK,EACL,KAAK,CAAC,6BAA6B,EACnC,oCAAoC,CACrC,CAAC;YACF,MAAM,+BAA+B,CACnC,aAAa,EACb,KAAK,EACL,KAAK,CAAC,2BAA2B,EACjC,kCAAkC,CACnC,CAAC;YACF,MAAM,gCAAgC,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;QAC/D,CAAC,EACD,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,uBAAuB,IAAI,KAAK,CAAC,uBAAuB,EAAE,CACxE,CAAC;QACF,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,4BAA4B,CAChD,MAAyB,EACzB,KAAiC;IAEjC,MAAM,uCAAuC,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["import {\n createDocument,\n encodeVersionVector,\n importUpdates,\n} from \"@tearleads/loro\";\nimport type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { getScopedPeerSeed } from \"../../data/crdtPeerSeed\";\nimport type { DocumentProjectorRegistryInput } from \"../../data/documents/documentKinds\";\nimport { createPendingUpdateFields } from \"../../data/documents/documentSync\";\nimport {\n type ContainerMetadataRecord,\n sqlContainerContentsPersistence,\n} from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport {\n DOCUMENTS_APP_KIND,\n sqlDocumentsPersistence,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n type LocallyAcknowledgedAccessManifestHead,\n} from \"../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { DocumentRecord } from \"../../data/sqlite/documentPersistence\";\nimport { getClientSQLitePersistenceRuntime } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport {\n createExecSql,\n type ExecSql,\n type ExecSqlClientLike,\n runSerializedSqlMutation,\n} from \"../../data/sqlite/sqlSchema\";\nimport { persistDocumentState } from \"../documents/persistence\";\nimport { ORGANIZATION_PROFILE_DOCUMENT_KIND } from \"../organizations/organizationProfile\";\nimport {\n ORGANIZATION_METADATA_CONTAINER_NAME,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n ROSTER_PROFILE_DOCUMENT_KIND,\n} from \"../organizations/rosterProfileContainer\";\nimport { enqueueInitialContainerMetadataUpdate } from \"./registrationBootstrapPendingUpdates\";\nimport { persistRegistrationPrincipalPolicies } from \"./registrationPrincipalPolicyPersistence\";\n\ninterface ProvisionedContainerBootstrapInput {\n accessEpoch: number;\n accessStateHash: string;\n containerId: string;\n createdAt: string;\n metadataDocumentId: string;\n metadataSnapshot: string;\n metadataState: Pick<\n DocumentRecord,\n | \"documentId\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\"\n >;\n systemSlot: ContainerSystemSlot;\n updatedAt: string;\n}\n\ninterface ProvisionedProfileDocumentBootstrapInput {\n accessEpoch: number;\n accessStateHash: string;\n containerId: string;\n documentId: string;\n documentState: ProvisionedContainerBootstrapInput[\"metadataState\"];\n initialUpdate: Uint8Array;\n initialUpdateCommitted: boolean;\n localId: string;\n}\n\nexport interface RegistrationBootstrapInput {\n acknowledgedAccessHeads: readonly LocallyAcknowledgedAccessManifestHead[];\n /** Checked inside the mutation queue claim; false skips every write. */\n canStartDurableMutation?: (() => boolean) | undefined;\n /**\n * @internal Test-only synchronization seam. Invoked synchronously,\n * immediately before this persist joins the serialized mutation queue —\n * no interleaving can separate the two. Lets identity-race tests\n * deterministically place an identity replacement inside the queue-wait\n * window instead of sleeping.\n */\n onPersistQueued?: (() => void) | undefined;\n containerId: string;\n initialAdminGroupPolicy: PrincipalPolicyBundleResponse;\n initialMemberGroupPolicy: PrincipalPolicyBundleResponse;\n initialOrganizationPolicy: PrincipalPolicyBundleResponse;\n rootMetadataAccessEpoch: number;\n rootMetadataAccessStateHash: string;\n rootContainerServerTimestamp: string;\n rootMetadataDocumentId: string;\n rootMetadataInitialUpdate: Uint8Array;\n rootMetadataInitialUpdateCommitted?: boolean | undefined;\n rootMetadataSnapshot: string;\n rootMetadataState: ProvisionedContainerBootstrapInput[\"metadataState\"];\n rosterProfileContainer?: ProvisionedContainerBootstrapInput & {\n metadataInitialUpdate: Uint8Array;\n metadataInitialUpdateCommitted?: boolean | undefined;\n };\n organizationMetadataContainer?: ProvisionedContainerBootstrapInput & {\n metadataInitialUpdate: Uint8Array;\n metadataInitialUpdateCommitted?: boolean | undefined;\n };\n organizationProfileDocument?: ProvisionedProfileDocumentBootstrapInput;\n rosterProfileDocument?: ProvisionedProfileDocumentBootstrapInput;\n // Additional app-owned system containers provisioned with the organization\n // (e.g. a trash bin). Each carries its own display name and icon (unlike the\n // roster/organization-metadata containers, whose names are fixed), since the\n // caller declares them.\n systemContainers?: Array<\n ProvisionedContainerBootstrapInput & {\n icon: string | null;\n name: string;\n }\n >;\n documentProjectors?: DocumentProjectorRegistryInput | undefined;\n organizationId: string;\n userId: string;\n}\nasync function persistProvisionedContainerBootstrap(\n execSql: ExecSql,\n input: {\n container: ProvisionedContainerBootstrapInput;\n icon: string | null;\n name: string;\n organizationId: string;\n parentId: string | null;\n },\n): Promise<void> {\n const { container } = input;\n const metadataState = container.metadataState;\n const record: ContainerMetadataRecord = {\n accessEpoch: container.accessEpoch,\n accessStateHash: container.accessStateHash,\n documentId: container.metadataDocumentId,\n id: container.containerId,\n lastCommitLsn: null,\n metadataUpdates: container.metadataSnapshot,\n snapshotEndVersion: \"\",\n contentKeyBundle: metadataState.contentKeyBundle ?? null,\n documentKekTargets: metadataState.documentKekTargets ?? null,\n documentManifestBundle: metadataState.documentManifestBundle ?? null,\n };\n await sqlContainerContentsPersistence.saveContainer(\n execSql,\n {\n id: container.containerId,\n effectiveAccessLevel: \"admin\",\n organizationId: input.organizationId,\n parentId: input.parentId,\n metadataDocumentId: container.metadataDocumentId,\n systemSlot: container.systemSlot,\n name: input.name,\n icon: input.icon,\n },\n record,\n {\n localUpdatedAt: container.updatedAt,\n serverTimestamps: {\n createdAt: container.createdAt,\n updatedAt: container.updatedAt,\n },\n },\n );\n}\n\nasync function persistRootContainerBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n): Promise<void> {\n const rootRecord: ContainerMetadataRecord = {\n accessEpoch: input.rootMetadataAccessEpoch,\n accessStateHash: input.rootMetadataAccessStateHash,\n documentId: input.rootMetadataDocumentId,\n id: input.containerId,\n lastCommitLsn: null,\n metadataUpdates: input.rootMetadataSnapshot,\n snapshotEndVersion: \"\",\n contentKeyBundle: input.rootMetadataState.contentKeyBundle ?? null,\n documentKekTargets: input.rootMetadataState.documentKekTargets ?? null,\n documentManifestBundle:\n input.rootMetadataState.documentManifestBundle ?? null,\n };\n await sqlContainerContentsPersistence.saveContainer(\n execSql,\n {\n id: input.containerId,\n effectiveAccessLevel: \"admin\",\n organizationId: input.organizationId,\n parentId: null,\n metadataDocumentId: input.rootMetadataDocumentId,\n name: \"/\",\n icon: null,\n },\n rootRecord,\n {\n localUpdatedAt: input.rootContainerServerTimestamp,\n serverTimestamps: {\n createdAt: input.rootContainerServerTimestamp,\n updatedAt: input.rootContainerServerTimestamp,\n },\n },\n );\n await enqueueInitialContainerMetadataUpdate(\n execSql,\n input.containerId,\n input.rootMetadataInitialUpdate,\n input.rootMetadataInitialUpdateCommitted,\n );\n}\n\n// Persist reserved profile containers using their fixed topology: roster profiles\n// inherit the personal root; shared organization metadata has an independent root.\nasync function persistNamedChildContainerBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n container: RegistrationBootstrapInput[\"rosterProfileContainer\"],\n name: string,\n): Promise<void> {\n if (!container) {\n return;\n }\n\n await persistProvisionedContainerBootstrap(execSql, {\n container,\n icon: null,\n name,\n organizationId: input.organizationId,\n parentId:\n container === input.organizationMetadataContainer\n ? null\n : input.containerId,\n });\n await enqueueInitialContainerMetadataUpdate(\n execSql,\n container.containerId,\n container.metadataInitialUpdate,\n container.metadataInitialUpdateCommitted,\n );\n}\n\nasync function persistSystemContainersBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n): Promise<void> {\n const systemContainers = input.systemContainers;\n if (!systemContainers) {\n return;\n }\n\n for (const systemContainer of systemContainers) {\n await persistProvisionedContainerBootstrap(execSql, {\n container: systemContainer,\n icon: systemContainer.icon,\n name: systemContainer.name,\n organizationId: input.organizationId,\n parentId: input.containerId,\n });\n // Provisioned system-container metadata is already committed remotely in\n // the organization transaction. Persist the initialized snapshot locally,\n // but do not queue a duplicate write with a second update id.\n }\n}\n\n// The ONE persist shape for the provisioned profile documents (organization\n// profile and roster profile): the input carries exactly the bootstrap\n// fields, so only the document kind and the host's projectors join it.\nasync function persistProfileDocumentBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n profileDocument: ProvisionedProfileDocumentBootstrapInput | undefined,\n documentKind: string,\n): Promise<void> {\n if (!profileDocument) {\n return;\n }\n\n await persistInitialDocumentBootstrap(execSql, {\n ...profileDocument,\n documentKind,\n documentProjectors: input.documentProjectors,\n });\n}\n\nexport async function persistInitialDocumentBootstrap(\n execSql: ExecSql,\n input: {\n accessEpoch: number;\n accessStateHash: string;\n containerId: string;\n documentId: string;\n documentKind: string;\n documentProjectors: DocumentProjectorRegistryInput | undefined;\n documentState: Pick<\n DocumentRecord,\n \"contentKeyBundle\" | \"documentKekTargets\" | \"documentManifestBundle\"\n >;\n initialUpdate: Uint8Array;\n initialUpdateCommitted: boolean;\n localId: string;\n },\n): Promise<void> {\n const doc = await createDocument(await getScopedPeerSeed(DOCUMENTS_APP_KIND));\n importUpdates(doc, [input.initialUpdate]);\n const pendingUpdate = input.initialUpdateCommitted\n ? undefined\n : (createPendingUpdateFields(input.initialUpdate) ?? undefined);\n\n await persistDocumentState({\n currentDoc: doc,\n currentRecord: null,\n documentProjectors: input.documentProjectors ?? [],\n execSql,\n localId: input.localId,\n patch: {\n accessEpoch: input.accessEpoch,\n accessStateHash: input.accessStateHash,\n containerId: input.containerId,\n contentKeyBundle: input.documentState.contentKeyBundle ?? null,\n documentId: input.documentId,\n // Successful provisioning makes this device's user the founding admin.\n // Stores can open before discovery returns the same access level.\n effectiveAccessLevel: \"admin\",\n documentKekTargets: input.documentState.documentKekTargets ?? null,\n documentKind: input.documentKind,\n documentManifestBundle:\n input.documentState.documentManifestBundle ?? null,\n // The create-only persistence primitive stores this frontier and the\n // full-history checkpoint in one transaction.\n snapshotEndVersion: encodeVersionVector(doc),\n },\n pendingUpdate,\n persistence: sqlDocumentsPersistence,\n });\n}\n\n/**\n * Persists the local root-container bootstrap created during successful\n * registration so container contents can initialize from SQLite on first\n * login — atomically: every write lands inside ONE transaction whose last\n * act re-checks identity currency, so an identity replaced anywhere between\n * the queue claim and the commit rolls the entire bootstrap back instead of\n * leaving a partial one. Resolves false when either currency check rejected\n * the write, so callers do not report a bootstrap that was never persisted.\n */\nexport async function persistRegistrationBootstrapFromExecSql(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n): Promise<boolean> {\n input.onPersistQueued?.();\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n // In-mutex currency check, adjacent to the serialized-mutation claim\n // (see persistDocumentState): the identity can be replaced while this\n // persist waits for the queue, and its bootstrap must not be written\n // through a client the replacement closed or renewed.\n if (input.canStartDurableMutation && !input.canStartDurableMutation()) {\n return false;\n }\n // Idempotent DDL stays outside the atomic boundary.\n await sqlContainerContentsPersistence.ensureSchema(lockedExecSql);\n await sqlDocumentsPersistence.ensureSchema(lockedExecSql);\n // Pre-commit currency guard: the write sequence awaits real work, so\n // the identity can be replaced mid-sequence. The guard runs\n // synchronously with the COMMIT dispatch, so a refusal rolls the whole\n // write set back and a pass cannot go stale before the commit is sent —\n // the partial-persist window a single entry check leaves open.\n const { committed } = await getClientSQLitePersistenceRuntime(\n lockedExecSql,\n ).guardedTransaction(\n async () => {\n await advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: lockedExecSql,\n heads: input.acknowledgedAccessHeads,\n });\n await persistRegistrationPrincipalPolicies({\n adminGroup: input.initialAdminGroupPolicy,\n execSql: lockedExecSql,\n memberGroup: input.initialMemberGroupPolicy,\n organization: input.initialOrganizationPolicy,\n });\n await persistRootContainerBootstrap(lockedExecSql, input);\n await persistNamedChildContainerBootstrap(\n lockedExecSql,\n input,\n input.rosterProfileContainer,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n );\n await persistProfileDocumentBootstrap(\n lockedExecSql,\n input,\n input.rosterProfileDocument,\n ROSTER_PROFILE_DOCUMENT_KIND,\n );\n await persistNamedChildContainerBootstrap(\n lockedExecSql,\n input,\n input.organizationMetadataContainer,\n ORGANIZATION_METADATA_CONTAINER_NAME,\n );\n await persistProfileDocumentBootstrap(\n lockedExecSql,\n input,\n input.organizationProfileDocument,\n ORGANIZATION_PROFILE_DOCUMENT_KIND,\n );\n await persistSystemContainersBootstrap(lockedExecSql, input);\n },\n () => !input.canStartDurableMutation || input.canStartDurableMutation(),\n );\n return committed;\n });\n}\n\nexport async function persistRegistrationBootstrap(\n client: ExecSqlClientLike,\n input: RegistrationBootstrapInput,\n): Promise<void> {\n await persistRegistrationBootstrapFromExecSql(createExecSql(client), input);\n}\n"]}
1
+ {"version":3,"file":"persistRegistrationBootstrap.js","sourceRoot":"","sources":["persistRegistrationBootstrap.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n createDocument,\n encodeVersionVector,\n importUpdates,\n} from \"@tearleads/loro\";\nimport type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { getScopedPeerSeed } from \"../../data/crdtPeerSeed\";\nimport type { DocumentProjectorRegistryInput } from \"../../data/documents/documentKinds\";\nimport { createPendingUpdateFields } from \"../../data/documents/documentSync\";\nimport {\n type ContainerMetadataRecord,\n sqlContainerContentsPersistence,\n} from \"../../data/persistence/container-contents/containerContentsPersistence\";\nimport {\n type AuthoredDiscoveryHead,\n primeAuthoredDocumentDiscoveryHeads,\n} from \"../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport {\n DOCUMENTS_APP_KIND,\n sqlDocumentsPersistence,\n} from \"../../data/persistence/documents/documentsPersistence\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n type LocallyAcknowledgedAccessManifestHead,\n} from \"../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { DocumentRecord } from \"../../data/sqlite/documentPersistence\";\nimport { documentContainerProjectionTables } from \"../../data/sqlite/schema\";\nimport { getClientSQLitePersistenceRuntime } from \"../../data/sqlite/sqlitePersistenceRuntime\";\nimport {\n createExecSql,\n type ExecSql,\n type ExecSqlClientLike,\n ensureSqlTables,\n runSerializedSqlMutation,\n} from \"../../data/sqlite/sqlSchema\";\nimport { persistDocumentState } from \"../documents/persistence\";\nimport { ORGANIZATION_PROFILE_DOCUMENT_KIND } from \"../organizations/organizationProfile\";\nimport {\n ORGANIZATION_METADATA_CONTAINER_NAME,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n ROSTER_PROFILE_DOCUMENT_KIND,\n} from \"../organizations/rosterProfileContainer\";\nimport { enqueueInitialContainerMetadataUpdate } from \"./registrationBootstrapPendingUpdates\";\nimport { persistRegistrationPrincipalPolicies } from \"./registrationPrincipalPolicyPersistence\";\n\ninterface ProvisionedContainerBootstrapInput {\n accessEpoch: number;\n accessStateHash: string;\n containerId: string;\n createdAt: string;\n metadataDocumentId: string;\n metadataSnapshot: string;\n metadataState: Pick<\n DocumentRecord,\n | \"documentId\"\n | \"contentKeyBundle\"\n | \"documentKekTargets\"\n | \"documentManifestBundle\"\n >;\n systemSlot: ContainerSystemSlot;\n updatedAt: string;\n}\n\ninterface ProvisionedProfileDocumentBootstrapInput {\n accessEpoch: number;\n accessStateHash: string;\n containerId: string;\n documentId: string;\n documentState: ProvisionedContainerBootstrapInput[\"metadataState\"];\n initialUpdate: Uint8Array;\n initialUpdateCommitted: boolean;\n localId: string;\n}\n\nexport interface RegistrationBootstrapInput {\n acknowledgedAccessHeads: readonly LocallyAcknowledgedAccessManifestHead[];\n /** Seeded documents' acknowledged signed heads; see the discovery cache. */\n authoredDiscoveryHeads: readonly AuthoredDiscoveryHead[];\n /** Checked inside the mutation queue claim; false skips every write. */\n canStartDurableMutation?: (() => boolean) | undefined;\n /**\n * @internal Test-only synchronization seam. Invoked synchronously,\n * immediately before this persist joins the serialized mutation queue —\n * no interleaving can separate the two. Lets identity-race tests\n * deterministically place an identity replacement inside the queue-wait\n * window instead of sleeping.\n */\n onPersistQueued?: (() => void) | undefined;\n containerId: string;\n initialAdminGroupPolicy: PrincipalPolicyBundleResponse;\n initialMemberGroupPolicy: PrincipalPolicyBundleResponse;\n initialOrganizationPolicy: PrincipalPolicyBundleResponse;\n rootMetadataAccessEpoch: number;\n rootMetadataAccessStateHash: string;\n rootContainerServerTimestamp: string;\n rootMetadataDocumentId: string;\n rootMetadataInitialUpdate: Uint8Array;\n rootMetadataInitialUpdateCommitted?: boolean | undefined;\n rootMetadataSnapshot: string;\n rootMetadataState: ProvisionedContainerBootstrapInput[\"metadataState\"];\n rosterProfileContainer?: ProvisionedContainerBootstrapInput & {\n metadataInitialUpdate: Uint8Array;\n metadataInitialUpdateCommitted?: boolean | undefined;\n };\n organizationMetadataContainer?: ProvisionedContainerBootstrapInput & {\n metadataInitialUpdate: Uint8Array;\n metadataInitialUpdateCommitted?: boolean | undefined;\n };\n organizationProfileDocument?: ProvisionedProfileDocumentBootstrapInput;\n rosterProfileDocument?: ProvisionedProfileDocumentBootstrapInput;\n // Additional app-owned system containers provisioned with the organization\n // (e.g. a trash bin). Each carries its own display name and icon (unlike the\n // roster/organization-metadata containers, whose names are fixed), since the\n // caller declares them.\n systemContainers?: Array<\n ProvisionedContainerBootstrapInput & {\n icon: string | null;\n name: string;\n }\n >;\n documentProjectors?: DocumentProjectorRegistryInput | undefined;\n organizationId: string;\n userId: string;\n}\nasync function persistProvisionedContainerBootstrap(\n execSql: ExecSql,\n input: {\n container: ProvisionedContainerBootstrapInput;\n icon: string | null;\n name: string;\n organizationId: string;\n parentId: string | null;\n },\n): Promise<void> {\n const { container } = input;\n const metadataState = container.metadataState;\n const record: ContainerMetadataRecord = {\n accessEpoch: container.accessEpoch,\n accessStateHash: container.accessStateHash,\n documentId: container.metadataDocumentId,\n id: container.containerId,\n lastCommitLsn: null,\n metadataUpdates: container.metadataSnapshot,\n snapshotEndVersion: \"\",\n contentKeyBundle: metadataState.contentKeyBundle ?? null,\n documentKekTargets: metadataState.documentKekTargets ?? null,\n documentManifestBundle: metadataState.documentManifestBundle ?? null,\n };\n await sqlContainerContentsPersistence.saveContainer(\n execSql,\n {\n id: container.containerId,\n effectiveAccessLevel: \"admin\",\n organizationId: input.organizationId,\n parentId: input.parentId,\n metadataDocumentId: container.metadataDocumentId,\n systemSlot: container.systemSlot,\n name: input.name,\n icon: input.icon,\n },\n record,\n {\n localUpdatedAt: container.updatedAt,\n serverTimestamps: {\n createdAt: container.createdAt,\n updatedAt: container.updatedAt,\n },\n },\n );\n}\n\nasync function persistRootContainerBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n): Promise<void> {\n const rootRecord: ContainerMetadataRecord = {\n accessEpoch: input.rootMetadataAccessEpoch,\n accessStateHash: input.rootMetadataAccessStateHash,\n documentId: input.rootMetadataDocumentId,\n id: input.containerId,\n lastCommitLsn: null,\n metadataUpdates: input.rootMetadataSnapshot,\n snapshotEndVersion: \"\",\n contentKeyBundle: input.rootMetadataState.contentKeyBundle ?? null,\n documentKekTargets: input.rootMetadataState.documentKekTargets ?? null,\n documentManifestBundle:\n input.rootMetadataState.documentManifestBundle ?? null,\n };\n await sqlContainerContentsPersistence.saveContainer(\n execSql,\n {\n id: input.containerId,\n effectiveAccessLevel: \"admin\",\n organizationId: input.organizationId,\n parentId: null,\n metadataDocumentId: input.rootMetadataDocumentId,\n name: \"/\",\n icon: null,\n },\n rootRecord,\n {\n localUpdatedAt: input.rootContainerServerTimestamp,\n serverTimestamps: {\n createdAt: input.rootContainerServerTimestamp,\n updatedAt: input.rootContainerServerTimestamp,\n },\n },\n );\n await enqueueInitialContainerMetadataUpdate(\n execSql,\n input.containerId,\n input.rootMetadataInitialUpdate,\n input.rootMetadataInitialUpdateCommitted,\n );\n}\n\n// Persist reserved profile containers using their fixed topology: roster profiles\n// inherit the personal root; shared organization metadata has an independent root.\nasync function persistNamedChildContainerBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n container: RegistrationBootstrapInput[\"rosterProfileContainer\"],\n name: string,\n): Promise<void> {\n if (!container) {\n return;\n }\n\n await persistProvisionedContainerBootstrap(execSql, {\n container,\n icon: null,\n name,\n organizationId: input.organizationId,\n parentId:\n container === input.organizationMetadataContainer\n ? null\n : input.containerId,\n });\n await enqueueInitialContainerMetadataUpdate(\n execSql,\n container.containerId,\n container.metadataInitialUpdate,\n container.metadataInitialUpdateCommitted,\n );\n}\n\nasync function persistSystemContainersBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n): Promise<void> {\n const systemContainers = input.systemContainers;\n if (!systemContainers) {\n return;\n }\n\n for (const systemContainer of systemContainers) {\n await persistProvisionedContainerBootstrap(execSql, {\n container: systemContainer,\n icon: systemContainer.icon,\n name: systemContainer.name,\n organizationId: input.organizationId,\n parentId: input.containerId,\n });\n // Provisioned system-container metadata is already committed remotely in\n // the organization transaction. Persist the initialized snapshot locally,\n // but do not queue a duplicate write with a second update id.\n }\n}\n\n// The ONE persist shape for the provisioned profile documents (organization\n// profile and roster profile): the input carries exactly the bootstrap\n// fields, so only the document kind and the host's projectors join it.\nasync function persistProfileDocumentBootstrap(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n profileDocument: ProvisionedProfileDocumentBootstrapInput | undefined,\n documentKind: string,\n): Promise<void> {\n if (!profileDocument) {\n return;\n }\n\n await persistInitialDocumentBootstrap(execSql, {\n ...profileDocument,\n documentKind,\n documentProjectors: input.documentProjectors,\n });\n}\n\nexport async function persistInitialDocumentBootstrap(\n execSql: ExecSql,\n input: {\n accessEpoch: number;\n accessStateHash: string;\n containerId: string;\n documentId: string;\n documentKind: string;\n documentProjectors: DocumentProjectorRegistryInput | undefined;\n documentState: Pick<\n DocumentRecord,\n \"contentKeyBundle\" | \"documentKekTargets\" | \"documentManifestBundle\"\n >;\n initialUpdate: Uint8Array;\n initialUpdateCommitted: boolean;\n localId: string;\n },\n): Promise<void> {\n const doc = await createDocument(await getScopedPeerSeed(DOCUMENTS_APP_KIND));\n importUpdates(doc, [input.initialUpdate]);\n const pendingUpdate = input.initialUpdateCommitted\n ? undefined\n : (createPendingUpdateFields(input.initialUpdate) ?? undefined);\n\n await persistDocumentState({\n currentDoc: doc,\n currentRecord: null,\n documentProjectors: input.documentProjectors ?? [],\n execSql,\n localId: input.localId,\n patch: {\n accessEpoch: input.accessEpoch,\n accessStateHash: input.accessStateHash,\n containerId: input.containerId,\n contentKeyBundle: input.documentState.contentKeyBundle ?? null,\n documentId: input.documentId,\n // Successful provisioning makes this device's user the founding admin.\n // Stores can open before discovery returns the same access level.\n effectiveAccessLevel: \"admin\",\n documentKekTargets: input.documentState.documentKekTargets ?? null,\n documentKind: input.documentKind,\n documentManifestBundle:\n input.documentState.documentManifestBundle ?? null,\n // The create-only persistence primitive stores this frontier and the\n // full-history checkpoint in one transaction.\n snapshotEndVersion: encodeVersionVector(doc),\n },\n pendingUpdate,\n persistence: sqlDocumentsPersistence,\n });\n}\n\n/**\n * Persists the local root-container bootstrap created during successful\n * registration so container contents can initialize from SQLite on first\n * login — atomically: every write lands inside ONE transaction whose last\n * act re-checks identity currency, so an identity replaced anywhere between\n * the queue claim and the commit rolls the entire bootstrap back instead of\n * leaving a partial one. Resolves false when either currency check rejected\n * the write, so callers do not report a bootstrap that was never persisted.\n */\nexport async function persistRegistrationBootstrapFromExecSql(\n execSql: ExecSql,\n input: RegistrationBootstrapInput,\n): Promise<boolean> {\n input.onPersistQueued?.();\n return runSerializedSqlMutation(execSql, async (lockedExecSql) => {\n // In-mutex currency check, adjacent to the serialized-mutation claim\n // (see persistDocumentState): the identity can be replaced while this\n // persist waits for the queue, and its bootstrap must not be written\n // through a client the replacement closed or renewed.\n if (input.canStartDurableMutation && !input.canStartDurableMutation()) {\n return false;\n }\n // Idempotent DDL stays outside the atomic boundary.\n await sqlContainerContentsPersistence.ensureSchema(lockedExecSql);\n await sqlDocumentsPersistence.ensureSchema(lockedExecSql);\n await ensureSqlTables(lockedExecSql, documentContainerProjectionTables);\n // Pre-commit currency guard: the write sequence awaits real work, so\n // the identity can be replaced mid-sequence. The guard runs\n // synchronously with the COMMIT dispatch, so a refusal rolls the whole\n // write set back and a pass cannot go stale before the commit is sent —\n // the partial-persist window a single entry check leaves open.\n const { committed } = await getClientSQLitePersistenceRuntime(\n lockedExecSql,\n ).guardedTransaction(\n async () => {\n await advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: lockedExecSql,\n heads: input.acknowledgedAccessHeads,\n });\n await persistRegistrationPrincipalPolicies({\n adminGroup: input.initialAdminGroupPolicy,\n execSql: lockedExecSql,\n memberGroup: input.initialMemberGroupPolicy,\n organization: input.initialOrganizationPolicy,\n });\n await persistRootContainerBootstrap(lockedExecSql, input);\n await persistNamedChildContainerBootstrap(\n lockedExecSql,\n input,\n input.rosterProfileContainer,\n ORGANIZATION_ROSTER_PROFILE_CONTAINER_NAME,\n );\n await persistProfileDocumentBootstrap(\n lockedExecSql,\n input,\n input.rosterProfileDocument,\n ROSTER_PROFILE_DOCUMENT_KIND,\n );\n await persistNamedChildContainerBootstrap(\n lockedExecSql,\n input,\n input.organizationMetadataContainer,\n ORGANIZATION_METADATA_CONTAINER_NAME,\n );\n await persistProfileDocumentBootstrap(\n lockedExecSql,\n input,\n input.organizationProfileDocument,\n ORGANIZATION_PROFILE_DOCUMENT_KIND,\n );\n await persistSystemContainersBootstrap(lockedExecSql, input);\n // After the checkpoints above: discovery reuses a cached head only\n // while its access-manifest checkpoint still matches.\n await primeAuthoredDocumentDiscoveryHeads(\n lockedExecSql,\n input.authoredDiscoveryHeads,\n );\n },\n () => !input.canStartDurableMutation || input.canStartDurableMutation(),\n );\n return committed;\n });\n}\n\nexport async function persistRegistrationBootstrap(\n client: ExecSqlClientLike,\n input: RegistrationBootstrapInput,\n): Promise<void> {\n await persistRegistrationBootstrapFromExecSql(createExecSql(client), input);\n}\n"]}
@@ -0,0 +1,45 @@
1
+ import type { PrincipalPolicyBundleResponse } from "../../internal/validators/response/index.js";
2
+ import type { PrincipalHistoryProtectionLease } from "../../data/principals/principalHistoryProtection.js";
3
+ import type { ExecSql, ExecSqlClientLike } from "../../data/sqlite/sqlSchema.js";
4
+ import type { TrustedUserIdentity } from "../../data/trustedUserIdentity/index.js";
5
+ /** The version-1 policies a provisioning request signed and its response acknowledged. */
6
+ interface ProvisionedPrincipalPolicies {
7
+ readonly adminGroup: PrincipalPolicyBundleResponse;
8
+ readonly memberGroup: PrincipalPolicyBundleResponse;
9
+ readonly organization: PrincipalPolicyBundleResponse;
10
+ }
11
+ /**
12
+ * Records verified recovery progress for an organization's founding policy
13
+ * heads, so the device's first scoped recovery of them needs no history read.
14
+ * It is bound to the provisioning scope: the database the bootstrap committed
15
+ * to and the identity that signed it. Failure leaves the online path.
16
+ */
17
+ export type ProvisionedPrincipalHistoryPrimer = (input: {
18
+ /** The database client the provisioning bootstrap committed to. */
19
+ readonly database: ExecSqlClientLike;
20
+ /** Whether the identity that provisioned is still the active one. */
21
+ readonly isCurrent: () => boolean;
22
+ readonly organizationId: string;
23
+ readonly policies: ProvisionedPrincipalPolicies;
24
+ readonly userId: string;
25
+ }) => Promise<void>;
26
+ /** The runtime seams priming reads; none of them writes durable state. */
27
+ interface ProvisionedPrincipalHistoryRuntime {
28
+ readonly bindLease: () => PrincipalHistoryProtectionLease | undefined;
29
+ /** The runtime executor, only while `database` is its ready database. */
30
+ readonly execSqlFor: (database: ExecSqlClientLike) => ExecSql | null;
31
+ readonly logError: (message: string | Error, cause?: unknown) => void;
32
+ /** Read-only: the identity the trust store already pins for a user. */
33
+ readonly loadPinnedIdentity: (execSql: ExecSql, userId: string) => Promise<TrustedUserIdentity | null>;
34
+ readonly signingFingerprint: () => string | null;
35
+ }
36
+ /**
37
+ * Binds priming to the exact provisioning scope, captured before any await:
38
+ * the bootstrap's database and runtime executor, the identity whose key signed
39
+ * the founding states, and a protection lease for that identity. Every later
40
+ * step, and every progress write inside its transaction, rechecks that scope,
41
+ * so a switched identity or database aborts priming without a durable write.
42
+ * Priming never writes a trust pin; it only reads the founder's existing one.
43
+ */
44
+ export declare function createProvisionedPrincipalHistoryPrimer(runtime: ProvisionedPrincipalHistoryRuntime): ProvisionedPrincipalHistoryPrimer;
45
+ export {};
@@ -0,0 +1,104 @@
1
+ import { assertProjectionVerificationCurrent } from "../../data/keyingProjectionVerification/types.js";
2
+ import { principalPolicyReferenceFromBundle } from "../../data/principals/principalPolicyAdminSigners.js";
3
+ import { createPrincipalCurrentRecoveryBatch } from "../principals/principalCurrentRecoveryBatch.js";
4
+ import { queuePrincipalRecovery } from "../principals/principalRecoveryQueue.js";
5
+ /**
6
+ * Serves only the acknowledged initial heads, each complete in one page. The
7
+ * ordinary verifier still checks every signature, the directory binding and
8
+ * strict Admins rules before any progress is saved.
9
+ */
10
+ function provisionedPolicyPages(policies) {
11
+ const bundles = [
12
+ policies.organization,
13
+ policies.adminGroup,
14
+ policies.memberGroup,
15
+ ];
16
+ return {
17
+ async *getPrincipalPolicyPages(principalType, principalId, options = {}) {
18
+ const bundle = bundles.find(({ currentState }) => currentState.principalType === principalType &&
19
+ currentState.principalId === principalId);
20
+ if (!bundle ||
21
+ options.resume !== undefined ||
22
+ (options.afterVersion ?? 0) !== 0 ||
23
+ (options.stateHash !== undefined &&
24
+ options.stateHash !== bundle.currentState.stateHash))
25
+ throw new Error("Provisioned principal history holds only the acknowledged initial heads");
26
+ yield {
27
+ ok: true,
28
+ data: {
29
+ ...structuredClone(bundle),
30
+ historyPage: { afterVersion: 0, nextAfterVersion: null },
31
+ },
32
+ };
33
+ },
34
+ };
35
+ }
36
+ async function primeProvisionedPrincipalHistory(input) {
37
+ const { recover } = createPrincipalCurrentRecoveryBatch();
38
+ const options = {
39
+ apiClient: provisionedPolicyPages(input.policies),
40
+ execSql: input.execSql,
41
+ offline: false,
42
+ organizationId: input.organizationId,
43
+ protection: input.protection,
44
+ resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,
45
+ stillCurrent: input.stillCurrent,
46
+ };
47
+ // Scoped recovery of each group also completes the directory and strict
48
+ // Admins stages; Members reuses them through the shared batch.
49
+ for (const group of [input.policies.adminGroup, input.policies.memberGroup])
50
+ await recover({
51
+ ...options,
52
+ reference: principalPolicyReferenceFromBundle(group),
53
+ });
54
+ }
55
+ /**
56
+ * Binds priming to the exact provisioning scope, captured before any await:
57
+ * the bootstrap's database and runtime executor, the identity whose key signed
58
+ * the founding states, and a protection lease for that identity. Every later
59
+ * step, and every progress write inside its transaction, rechecks that scope,
60
+ * so a switched identity or database aborts priming without a durable write.
61
+ * Priming never writes a trust pin; it only reads the founder's existing one.
62
+ */
63
+ export function createProvisionedPrincipalHistoryPrimer(runtime) {
64
+ return async (input) => {
65
+ try {
66
+ await primeInProvisioningScope(runtime, input);
67
+ }
68
+ catch (error) {
69
+ runtime.logError("Provisioned principal history was not primed; recovery reads it online", error);
70
+ }
71
+ };
72
+ }
73
+ async function primeInProvisioningScope(runtime, input) {
74
+ // Everything below is captured synchronously, before the first await.
75
+ const founderFingerprint = input.policies.organization.currentState.signerUserKeyFingerprint;
76
+ const execSql = runtime.execSqlFor(input.database);
77
+ const scopeCurrent = () => execSql !== null &&
78
+ input.isCurrent() &&
79
+ runtime.execSqlFor(input.database) === execSql &&
80
+ runtime.signingFingerprint() === founderFingerprint;
81
+ const lease = scopeCurrent() ? runtime.bindLease() : undefined;
82
+ if (!execSql || !lease)
83
+ return;
84
+ const resolveTrustedUserIdentity = async (signerUserId) => {
85
+ if (signerUserId !== input.userId)
86
+ return null;
87
+ assertProjectionVerificationCurrent(scopeCurrent);
88
+ const identity = await runtime.loadPinnedIdentity(execSql, input.userId);
89
+ assertProjectionVerificationCurrent(scopeCurrent);
90
+ return identity?.signingKeyFingerprint === founderFingerprint
91
+ ? identity
92
+ : null;
93
+ };
94
+ await queuePrincipalRecovery(execSql, input.organizationId, () => lease(({ protection, stillCurrent }) => primeProvisionedPrincipalHistory({
95
+ execSql,
96
+ organizationId: input.organizationId,
97
+ policies: input.policies,
98
+ protection,
99
+ resolveTrustedUserIdentity,
100
+ // Progress writes check this inside their transactions.
101
+ stillCurrent: () => stillCurrent() && scopeCurrent(),
102
+ })));
103
+ }
104
+ //# sourceMappingURL=provisionedPrincipalHistory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"provisionedPrincipalHistory.js","sourceRoot":"","sources":["provisionedPrincipalHistory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { PrincipalPolicyHistoryProgressOptions } from \"@tearleads/crypto\";\nimport type { PrincipalPolicyBundleResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../data/keyingProjectionVerification/types\";\nimport type { PrincipalHistoryProtectionLease } from \"../../data/principals/principalHistoryProtection\";\nimport { principalPolicyReferenceFromBundle } from \"../../data/principals/principalPolicyAdminSigners\";\nimport type { ExecSql, ExecSqlClientLike } from \"../../data/sqlite/sqlSchema\";\nimport type {\n TrustedUserIdentity,\n TrustedUserIdentityResolver,\n} from \"../../data/trustedUserIdentity\";\nimport { createPrincipalCurrentRecoveryBatch } from \"../principals/principalCurrentRecoveryBatch\";\nimport { queuePrincipalRecovery } from \"../principals/principalRecoveryQueue\";\n\n/** The version-1 policies a provisioning request signed and its response acknowledged. */\ninterface ProvisionedPrincipalPolicies {\n readonly adminGroup: PrincipalPolicyBundleResponse;\n readonly memberGroup: PrincipalPolicyBundleResponse;\n readonly organization: PrincipalPolicyBundleResponse;\n}\n\n/**\n * Records verified recovery progress for an organization's founding policy\n * heads, so the device's first scoped recovery of them needs no history read.\n * It is bound to the provisioning scope: the database the bootstrap committed\n * to and the identity that signed it. Failure leaves the online path.\n */\nexport type ProvisionedPrincipalHistoryPrimer = (input: {\n /** The database client the provisioning bootstrap committed to. */\n readonly database: ExecSqlClientLike;\n /** Whether the identity that provisioned is still the active one. */\n readonly isCurrent: () => boolean;\n readonly organizationId: string;\n readonly policies: ProvisionedPrincipalPolicies;\n readonly userId: string;\n}) => Promise<void>;\n\n/**\n * Serves only the acknowledged initial heads, each complete in one page. The\n * ordinary verifier still checks every signature, the directory binding and\n * strict Admins rules before any progress is saved.\n */\nfunction provisionedPolicyPages(\n policies: ProvisionedPrincipalPolicies,\n): Pick<ApiClient, \"getPrincipalPolicyPages\"> {\n const bundles = [\n policies.organization,\n policies.adminGroup,\n policies.memberGroup,\n ];\n return {\n async *getPrincipalPolicyPages(principalType, principalId, options = {}) {\n const bundle = bundles.find(\n ({ currentState }) =>\n currentState.principalType === principalType &&\n currentState.principalId === principalId,\n );\n if (\n !bundle ||\n options.resume !== undefined ||\n (options.afterVersion ?? 0) !== 0 ||\n (options.stateHash !== undefined &&\n options.stateHash !== bundle.currentState.stateHash)\n )\n throw new Error(\n \"Provisioned principal history holds only the acknowledged initial heads\",\n );\n yield {\n ok: true,\n data: {\n ...structuredClone(bundle),\n historyPage: { afterVersion: 0, nextAfterVersion: null },\n },\n };\n },\n };\n}\n\nasync function primeProvisionedPrincipalHistory(input: {\n readonly execSql: ExecSql;\n readonly organizationId: string;\n readonly policies: ProvisionedPrincipalPolicies;\n readonly protection: PrincipalPolicyHistoryProgressOptions;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly stillCurrent: () => boolean;\n}): Promise<void> {\n const { recover } = createPrincipalCurrentRecoveryBatch();\n const options = {\n apiClient: provisionedPolicyPages(input.policies),\n execSql: input.execSql,\n offline: false,\n organizationId: input.organizationId,\n protection: input.protection,\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n };\n // Scoped recovery of each group also completes the directory and strict\n // Admins stages; Members reuses them through the shared batch.\n for (const group of [input.policies.adminGroup, input.policies.memberGroup])\n await recover({\n ...options,\n reference: principalPolicyReferenceFromBundle(group),\n });\n}\n\n/** The runtime seams priming reads; none of them writes durable state. */\ninterface ProvisionedPrincipalHistoryRuntime {\n readonly bindLease: () => PrincipalHistoryProtectionLease | undefined;\n /** The runtime executor, only while `database` is its ready database. */\n readonly execSqlFor: (database: ExecSqlClientLike) => ExecSql | null;\n readonly logError: (message: string | Error, cause?: unknown) => void;\n /** Read-only: the identity the trust store already pins for a user. */\n readonly loadPinnedIdentity: (\n execSql: ExecSql,\n userId: string,\n ) => Promise<TrustedUserIdentity | null>;\n readonly signingFingerprint: () => string | null;\n}\n\n/**\n * Binds priming to the exact provisioning scope, captured before any await:\n * the bootstrap's database and runtime executor, the identity whose key signed\n * the founding states, and a protection lease for that identity. Every later\n * step, and every progress write inside its transaction, rechecks that scope,\n * so a switched identity or database aborts priming without a durable write.\n * Priming never writes a trust pin; it only reads the founder's existing one.\n */\nexport function createProvisionedPrincipalHistoryPrimer(\n runtime: ProvisionedPrincipalHistoryRuntime,\n): ProvisionedPrincipalHistoryPrimer {\n return async (input) => {\n try {\n await primeInProvisioningScope(runtime, input);\n } catch (error) {\n runtime.logError(\n \"Provisioned principal history was not primed; recovery reads it online\",\n error,\n );\n }\n };\n}\n\nasync function primeInProvisioningScope(\n runtime: ProvisionedPrincipalHistoryRuntime,\n input: Parameters<ProvisionedPrincipalHistoryPrimer>[0],\n): Promise<void> {\n // Everything below is captured synchronously, before the first await.\n const founderFingerprint =\n input.policies.organization.currentState.signerUserKeyFingerprint;\n const execSql = runtime.execSqlFor(input.database);\n const scopeCurrent = () =>\n execSql !== null &&\n input.isCurrent() &&\n runtime.execSqlFor(input.database) === execSql &&\n runtime.signingFingerprint() === founderFingerprint;\n const lease = scopeCurrent() ? runtime.bindLease() : undefined;\n if (!execSql || !lease) return;\n const resolveTrustedUserIdentity: TrustedUserIdentityResolver = async (\n signerUserId,\n ) => {\n if (signerUserId !== input.userId) return null;\n assertProjectionVerificationCurrent(scopeCurrent);\n const identity = await runtime.loadPinnedIdentity(execSql, input.userId);\n assertProjectionVerificationCurrent(scopeCurrent);\n return identity?.signingKeyFingerprint === founderFingerprint\n ? identity\n : null;\n };\n await queuePrincipalRecovery(execSql, input.organizationId, () =>\n lease(({ protection, stillCurrent }) =>\n primeProvisionedPrincipalHistory({\n execSql,\n organizationId: input.organizationId,\n policies: input.policies,\n protection,\n resolveTrustedUserIdentity,\n // Progress writes check this inside their transactions.\n stillCurrent: () => stillCurrent() && scopeCurrent(),\n }),\n ),\n );\n}\n"]}
@@ -82,4 +82,22 @@ export async function provisioningAcknowledgedAccessHeads(input) {
82
82
  }
83
83
  return heads;
84
84
  }
85
+ /**
86
+ * The signed heads of the seeded profile documents, for the discovery head
87
+ * cache. Each plan was checked against its create acknowledgement by
88
+ * {@link provisioningAcknowledgedAccessHeads}; checking again here keeps the
89
+ * cache entry bound to exactly the head the server returned.
90
+ */
91
+ export function provisioningDiscoveryHeads(documents) {
92
+ return documents.map(({ plan, response }) => {
93
+ assertDocumentCreateResponseMatchesPlan(plan, requireResponse(response, "seeded document"));
94
+ return {
95
+ documentId: plan.documentId,
96
+ organizationId: plan.state.organizationId,
97
+ accessEpoch: plan.state.epoch,
98
+ accessStateHash: plan.manifestHash,
99
+ linkedContainerIds: plan.state.linkedContainerIds,
100
+ };
101
+ });
102
+ }
85
103
  //# sourceMappingURL=provisioningAcknowledgement.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"provisioningAcknowledgement.js","sourceRoot":"","sources":["provisioningAcknowledgement.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerCreateWithMetadataDocumentResponse,\n DocumentCreateResponse,\n OrganizationProvisioningResponse,\n} from \"@tearleads/validators/response\";\nimport { locallyAcknowledgedContainerMutationHead } from \"../../data/containers/shared/mutationAcknowledgement\";\nimport { assertDocumentCreateResponseMatchesPlan } from \"../../data/documents/shared/responses\";\nimport {\n type LocallyAcknowledgedAccessManifestHead,\n locallyAuthoredAccessManifestHead,\n} from \"../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\n\ntype ContainerPlan = Parameters<\n typeof locallyAcknowledgedContainerMutationHead\n>[0][\"plan\"];\ntype DocumentPlan = Parameters<\n typeof assertDocumentCreateResponseMatchesPlan\n>[0];\n\ninterface ProvisioningContainerArtifact {\n readonly containerPlan: ContainerPlan;\n readonly metadataDocumentPlan: DocumentPlan;\n}\n\nfunction requireResponse<T>(value: T | undefined, label: string): T {\n if (!value) {\n throw new Error(`Organization provisioning response is missing ${label}`);\n }\n return value;\n}\n\nfunction assertId(\n actual: string | undefined,\n expected: string,\n label: string,\n): void {\n if (actual !== expected) {\n throw new Error(`Organization provisioning response ${label} mismatch`);\n }\n}\n\nfunction assertProvisioningIdentity(input: {\n expectedOrganizationId: string;\n expectedUserId: string;\n response: OrganizationProvisioningResponse;\n rootContainerPlan: ContainerPlan;\n rootMetadataDocumentPlan: DocumentPlan;\n}): void {\n const { response, rootContainerPlan, rootMetadataDocumentPlan } = input;\n if (\n response.userId !== input.expectedUserId ||\n response.organizationId !== input.expectedOrganizationId ||\n response.rootContainerId !== rootContainerPlan.containerId ||\n response.rootMetadataDocumentId !== rootMetadataDocumentPlan.documentId ||\n response.rootMetadataAccessEpoch !== rootContainerPlan.manifest.epoch ||\n response.rootMetadataAccessStateHash !== rootContainerPlan.manifestHash\n ) {\n throw new Error(\"Organization provisioning response identity mismatch\");\n }\n}\n\nasync function containerArtifactHeads(input: {\n artifact: ProvisioningContainerArtifact;\n response: ContainerCreateWithMetadataDocumentResponse;\n}): Promise<LocallyAcknowledgedAccessManifestHead[]> {\n assertDocumentCreateResponseMatchesPlan(\n input.artifact.metadataDocumentPlan,\n input.response.metadataDocument,\n );\n return [\n await locallyAcknowledgedContainerMutationHead({\n plan: input.artifact.containerPlan,\n response: input.response.container,\n }),\n locallyAuthoredAccessManifestHead(input.artifact.metadataDocumentPlan),\n ];\n}\n\nfunction documentHead(input: {\n plan: DocumentPlan;\n response: DocumentCreateResponse;\n}): LocallyAcknowledgedAccessManifestHead {\n assertDocumentCreateResponseMatchesPlan(input.plan, input.response);\n return locallyAuthoredAccessManifestHead(input.plan);\n}\n\nexport async function provisioningAcknowledgedAccessHeads(input: {\n expectedOrganizationId: string;\n expectedUserId: string;\n organizationMetadata: ProvisioningContainerArtifact;\n organizationProfileDocumentPlan: DocumentPlan;\n response: OrganizationProvisioningResponse;\n rootContainerPlan: ContainerPlan;\n rootMetadataDocumentPlan: DocumentPlan;\n rosterProfile: ProvisioningContainerArtifact;\n rosterProfileDocumentPlan: DocumentPlan;\n systemContainers: readonly ProvisioningContainerArtifact[];\n}): Promise<LocallyAcknowledgedAccessManifestHead[]> {\n assertProvisioningIdentity(input);\n const response = input.response;\n assertDocumentCreateResponseMatchesPlan(\n input.rootMetadataDocumentPlan,\n response.rootMetadataDocument,\n );\n const rosterContainer = requireResponse(\n response.rosterProfileContainer,\n \"roster profile container\",\n );\n const rosterDocument = requireResponse(\n response.rosterProfileDocument,\n \"roster profile document\",\n );\n const organizationContainer = requireResponse(\n response.organizationMetadataContainer,\n \"organization metadata container\",\n );\n const organizationDocument = requireResponse(\n response.organizationProfileDocument,\n \"organization profile document\",\n );\n assertId(\n response.rosterProfileContainerId,\n input.rosterProfile.containerPlan.containerId,\n \"roster profile container id\",\n );\n assertId(\n response.rosterProfileDocumentId,\n input.rosterProfileDocumentPlan.documentId,\n \"roster profile document id\",\n );\n assertId(\n response.organizationMetadataContainerId,\n input.organizationMetadata.containerPlan.containerId,\n \"organization metadata container id\",\n );\n assertId(\n response.organizationProfileDocumentId,\n input.organizationProfileDocumentPlan.documentId,\n \"organization profile document id\",\n );\n\n const systemResponses = response.systemContainers;\n if (systemResponses.length !== input.systemContainers.length) {\n throw new Error(\n \"Organization provisioning response system container count mismatch\",\n );\n }\n const heads: LocallyAcknowledgedAccessManifestHead[] = [\n locallyAuthoredAccessManifestHead(input.rootContainerPlan),\n locallyAuthoredAccessManifestHead(input.rootMetadataDocumentPlan),\n ...(await containerArtifactHeads({\n artifact: input.rosterProfile,\n response: rosterContainer,\n })),\n documentHead({\n plan: input.rosterProfileDocumentPlan,\n response: rosterDocument,\n }),\n ...(await containerArtifactHeads({\n artifact: input.organizationMetadata,\n response: organizationContainer,\n })),\n documentHead({\n plan: input.organizationProfileDocumentPlan,\n response: organizationDocument,\n }),\n ];\n for (const [index, artifact] of input.systemContainers.entries()) {\n const systemResponse = systemResponses[index];\n if (!systemResponse) {\n throw new Error(\"Organization provisioning system response is missing\");\n }\n heads.push(\n ...(await containerArtifactHeads({ artifact, response: systemResponse })),\n );\n }\n return heads;\n}\n"]}
1
+ {"version":3,"file":"provisioningAcknowledgement.js","sourceRoot":"","sources":["provisioningAcknowledgement.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerCreateWithMetadataDocumentResponse,\n DocumentCreateResponse,\n OrganizationProvisioningResponse,\n} from \"@tearleads/validators/response\";\nimport { locallyAcknowledgedContainerMutationHead } from \"../../data/containers/shared/mutationAcknowledgement\";\nimport { assertDocumentCreateResponseMatchesPlan } from \"../../data/documents/shared/responses\";\nimport type { AuthoredDiscoveryHead } from \"../../data/persistence/documents/documentDiscoveryEvidencePersistence\";\nimport {\n type LocallyAcknowledgedAccessManifestHead,\n locallyAuthoredAccessManifestHead,\n} from \"../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\n\ntype ContainerPlan = Parameters<\n typeof locallyAcknowledgedContainerMutationHead\n>[0][\"plan\"];\ntype DocumentPlan = Parameters<\n typeof assertDocumentCreateResponseMatchesPlan\n>[0];\n\ninterface ProvisioningContainerArtifact {\n readonly containerPlan: ContainerPlan;\n readonly metadataDocumentPlan: DocumentPlan;\n}\n\nfunction requireResponse<T>(value: T | undefined, label: string): T {\n if (!value) {\n throw new Error(`Organization provisioning response is missing ${label}`);\n }\n return value;\n}\n\nfunction assertId(\n actual: string | undefined,\n expected: string,\n label: string,\n): void {\n if (actual !== expected) {\n throw new Error(`Organization provisioning response ${label} mismatch`);\n }\n}\n\nfunction assertProvisioningIdentity(input: {\n expectedOrganizationId: string;\n expectedUserId: string;\n response: OrganizationProvisioningResponse;\n rootContainerPlan: ContainerPlan;\n rootMetadataDocumentPlan: DocumentPlan;\n}): void {\n const { response, rootContainerPlan, rootMetadataDocumentPlan } = input;\n if (\n response.userId !== input.expectedUserId ||\n response.organizationId !== input.expectedOrganizationId ||\n response.rootContainerId !== rootContainerPlan.containerId ||\n response.rootMetadataDocumentId !== rootMetadataDocumentPlan.documentId ||\n response.rootMetadataAccessEpoch !== rootContainerPlan.manifest.epoch ||\n response.rootMetadataAccessStateHash !== rootContainerPlan.manifestHash\n ) {\n throw new Error(\"Organization provisioning response identity mismatch\");\n }\n}\n\nasync function containerArtifactHeads(input: {\n artifact: ProvisioningContainerArtifact;\n response: ContainerCreateWithMetadataDocumentResponse;\n}): Promise<LocallyAcknowledgedAccessManifestHead[]> {\n assertDocumentCreateResponseMatchesPlan(\n input.artifact.metadataDocumentPlan,\n input.response.metadataDocument,\n );\n return [\n await locallyAcknowledgedContainerMutationHead({\n plan: input.artifact.containerPlan,\n response: input.response.container,\n }),\n locallyAuthoredAccessManifestHead(input.artifact.metadataDocumentPlan),\n ];\n}\n\nfunction documentHead(input: {\n plan: DocumentPlan;\n response: DocumentCreateResponse;\n}): LocallyAcknowledgedAccessManifestHead {\n assertDocumentCreateResponseMatchesPlan(input.plan, input.response);\n return locallyAuthoredAccessManifestHead(input.plan);\n}\n\nexport async function provisioningAcknowledgedAccessHeads(input: {\n expectedOrganizationId: string;\n expectedUserId: string;\n organizationMetadata: ProvisioningContainerArtifact;\n organizationProfileDocumentPlan: DocumentPlan;\n response: OrganizationProvisioningResponse;\n rootContainerPlan: ContainerPlan;\n rootMetadataDocumentPlan: DocumentPlan;\n rosterProfile: ProvisioningContainerArtifact;\n rosterProfileDocumentPlan: DocumentPlan;\n systemContainers: readonly ProvisioningContainerArtifact[];\n}): Promise<LocallyAcknowledgedAccessManifestHead[]> {\n assertProvisioningIdentity(input);\n const response = input.response;\n assertDocumentCreateResponseMatchesPlan(\n input.rootMetadataDocumentPlan,\n response.rootMetadataDocument,\n );\n const rosterContainer = requireResponse(\n response.rosterProfileContainer,\n \"roster profile container\",\n );\n const rosterDocument = requireResponse(\n response.rosterProfileDocument,\n \"roster profile document\",\n );\n const organizationContainer = requireResponse(\n response.organizationMetadataContainer,\n \"organization metadata container\",\n );\n const organizationDocument = requireResponse(\n response.organizationProfileDocument,\n \"organization profile document\",\n );\n assertId(\n response.rosterProfileContainerId,\n input.rosterProfile.containerPlan.containerId,\n \"roster profile container id\",\n );\n assertId(\n response.rosterProfileDocumentId,\n input.rosterProfileDocumentPlan.documentId,\n \"roster profile document id\",\n );\n assertId(\n response.organizationMetadataContainerId,\n input.organizationMetadata.containerPlan.containerId,\n \"organization metadata container id\",\n );\n assertId(\n response.organizationProfileDocumentId,\n input.organizationProfileDocumentPlan.documentId,\n \"organization profile document id\",\n );\n\n const systemResponses = response.systemContainers;\n if (systemResponses.length !== input.systemContainers.length) {\n throw new Error(\n \"Organization provisioning response system container count mismatch\",\n );\n }\n const heads: LocallyAcknowledgedAccessManifestHead[] = [\n locallyAuthoredAccessManifestHead(input.rootContainerPlan),\n locallyAuthoredAccessManifestHead(input.rootMetadataDocumentPlan),\n ...(await containerArtifactHeads({\n artifact: input.rosterProfile,\n response: rosterContainer,\n })),\n documentHead({\n plan: input.rosterProfileDocumentPlan,\n response: rosterDocument,\n }),\n ...(await containerArtifactHeads({\n artifact: input.organizationMetadata,\n response: organizationContainer,\n })),\n documentHead({\n plan: input.organizationProfileDocumentPlan,\n response: organizationDocument,\n }),\n ];\n for (const [index, artifact] of input.systemContainers.entries()) {\n const systemResponse = systemResponses[index];\n if (!systemResponse) {\n throw new Error(\"Organization provisioning system response is missing\");\n }\n heads.push(\n ...(await containerArtifactHeads({ artifact, response: systemResponse })),\n );\n }\n return heads;\n}\n\n/**\n * The signed heads of the seeded profile documents, for the discovery head\n * cache. Each plan was checked against its create acknowledgement by\n * {@link provisioningAcknowledgedAccessHeads}; checking again here keeps the\n * cache entry bound to exactly the head the server returned.\n */\nexport function provisioningDiscoveryHeads(\n documents: readonly {\n plan: DocumentPlan;\n response: DocumentCreateResponse | undefined;\n }[],\n): AuthoredDiscoveryHead[] {\n return documents.map(({ plan, response }) => {\n assertDocumentCreateResponseMatchesPlan(\n plan,\n requireResponse(response, \"seeded document\"),\n );\n return {\n documentId: plan.documentId,\n organizationId: plan.state.organizationId,\n accessEpoch: plan.state.epoch,\n accessStateHash: plan.manifestHash,\n linkedContainerIds: plan.state.linkedContainerIds,\n };\n });\n}\n"]}