@tearleads/client-sdk 0.1.19 → 0.1.20

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 (211) hide show
  1. package/client/organizations/index.js +2 -2
  2. package/client/organizations/index.js.map +1 -1
  3. package/client/organizations/organizationHistory.js +66 -0
  4. package/client/organizations/organizationHistory.js.map +1 -0
  5. package/client/organizations/organizationReadModels.d.ts +1 -1
  6. package/client/organizations/organizationReadModels.js +7 -27
  7. package/client/organizations/organizationReadModels.js.map +1 -1
  8. package/client/organizations/organizationsTypes.d.ts +1 -1
  9. package/client/organizations/organizationsTypes.js.map +1 -1
  10. package/data/containers/shared/types.d.ts +2 -2
  11. package/data/containers/shared/types.js.map +1 -1
  12. package/data/documents/shared/syncSubmitFailure.d.ts +2 -2
  13. package/data/documents/shared/syncSubmitFailure.js.map +1 -1
  14. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js +34 -8
  15. package/data/keyingProjectionVerification/documentPurgeCheckpointCurrency.js.map +1 -1
  16. package/data/keyingProjectionVerification/documentPurgeDocumentChainVerification.js.map +1 -1
  17. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js +17 -0
  18. package/data/keyingProjectionVerification/documentPurgePolicyCheckpoints.js.map +1 -0
  19. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js +55 -0
  20. package/data/keyingProjectionVerification/documentPurgePolicyCurrency.js.map +1 -0
  21. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js +25 -13
  22. package/data/keyingProjectionVerification/documentPurgePrincipalEvidence.js.map +1 -1
  23. package/data/keyingProjectionVerification/documentPurgeProofVerification.d.ts +5 -3
  24. package/data/keyingProjectionVerification/documentPurgeProofVerification.js +52 -8
  25. package/data/keyingProjectionVerification/documentPurgeProofVerification.js.map +1 -1
  26. package/data/keyingProjectionVerification/projectionPolicyEvidence.js.map +1 -1
  27. package/data/keyingProjectionVerification/types.d.ts +4 -0
  28. package/data/keyingProjectionVerification/types.js.map +1 -1
  29. package/data/persistence/principalAuthorizationCheckpoints.js +1 -1
  30. package/data/persistence/principalAuthorizationCheckpoints.js.map +1 -1
  31. package/data/persistence/principalCurrentAcknowledgementPersistence.d.ts +1 -0
  32. package/data/persistence/principalCurrentAcknowledgementPersistence.js +58 -12
  33. package/data/persistence/principalCurrentAcknowledgementPersistence.js.map +1 -1
  34. package/data/persistence/principalHistoryEvidencePersistence.d.ts +2 -0
  35. package/data/persistence/principalHistoryEvidencePersistence.js +2 -0
  36. package/data/persistence/principalHistoryEvidencePersistence.js.map +1 -1
  37. package/data/persistence/principalHistoryIncompleteRetention.js +32 -0
  38. package/data/persistence/principalHistoryIncompleteRetention.js.map +1 -0
  39. package/data/persistence/principalHistoryNodeRetention.js +76 -0
  40. package/data/persistence/principalHistoryNodeRetention.js.map +1 -0
  41. package/data/persistence/principalHistoryPrefixPersistence.d.ts +1 -0
  42. package/data/persistence/principalHistoryPrefixPersistence.js +30 -1
  43. package/data/persistence/principalHistoryPrefixPersistence.js.map +1 -1
  44. package/data/persistence/principalHistoryRootOwnership.js +71 -0
  45. package/data/persistence/principalHistoryRootOwnership.js.map +1 -0
  46. package/data/persistence/principalHistoryStagePersistence.js +45 -0
  47. package/data/persistence/principalHistoryStagePersistence.js.map +1 -1
  48. package/data/persistence/principalHistoryStageRetention.js +44 -0
  49. package/data/persistence/principalHistoryStageRetention.js.map +1 -0
  50. package/data/persistence/principalHistoryUnpublishedRetention.js +71 -0
  51. package/data/persistence/principalHistoryUnpublishedRetention.js.map +1 -0
  52. package/data/persistence/principalKeyEnvelopeArchivePersistence.js +63 -0
  53. package/data/persistence/principalKeyEnvelopeArchivePersistence.js.map +1 -0
  54. package/data/persistence/principalKeyEnvelopeCandidates.js +10 -1
  55. package/data/persistence/principalKeyEnvelopeCandidates.js.map +1 -1
  56. package/data/sqlite/principalHistoryEvidenceSchema.js +2 -0
  57. package/data/sqlite/principalHistoryEvidenceSchema.js.map +1 -1
  58. package/data/sqlite/principalHistoryNodeRetentionSchema.js +30 -0
  59. package/data/sqlite/principalHistoryNodeRetentionSchema.js.map +1 -0
  60. package/data/sqlite/principalHistoryRetentionSchema.js +40 -0
  61. package/data/sqlite/principalHistoryRetentionSchema.js.map +1 -0
  62. package/data/sqlite/principalHistoryStageSchema.js +2 -0
  63. package/data/sqlite/principalHistoryStageSchema.js.map +1 -1
  64. package/data/sqlite/schema.d.ts +453 -0
  65. package/data/sqlite/schema.js +6 -0
  66. package/data/sqlite/schema.js.map +1 -1
  67. package/data/sqlite/sqliteCommitGuards.js +49 -0
  68. package/data/sqlite/sqliteCommitGuards.js.map +1 -0
  69. package/data/sqlite/sqlitePersistenceRuntime.js +14 -2
  70. package/data/sqlite/sqlitePersistenceRuntime.js.map +1 -1
  71. package/index.d.ts +3 -1
  72. package/index.js.map +1 -1
  73. package/internal/api-client/ApiClient.d.ts +60 -137
  74. package/internal/api-client/ApiClient.js +7 -5
  75. package/internal/api-client/ApiClient.js.map +1 -1
  76. package/internal/api-client/apiRequestRuntime.js +7 -7
  77. package/internal/api-client/apiRequestRuntime.js.map +1 -1
  78. package/internal/api-client/documentPurge.js +25 -0
  79. package/internal/api-client/documentPurge.js.map +1 -0
  80. package/internal/api-client/organizationPolicyHistory.d.ts +53 -0
  81. package/internal/api-client/organizationPolicyHistory.js +15 -0
  82. package/internal/api-client/organizationPolicyHistory.js.map +1 -0
  83. package/internal/api-client/requestInternals.js +4 -4
  84. package/internal/api-client/requestInternals.js.map +1 -1
  85. package/internal/api-client/types.d.ts +2 -2
  86. package/internal/api-client/types.js.map +1 -1
  87. package/internal/crypto/keying/principalPolicyHistory.js +4 -0
  88. package/internal/crypto/keying/principalPolicyHistory.js.map +1 -1
  89. package/internal/crypto/keying/principalPolicyHistoryTypes.d.ts +2 -0
  90. package/internal/crypto/keying/principalPolicyHistoryTypes.js.map +1 -1
  91. package/internal/validators/operation/containerMutations.d.ts +448 -6528
  92. package/internal/validators/operation/documentMutations.d.ts +323 -579
  93. package/internal/validators/operation/documentMutations.js +22 -4
  94. package/internal/validators/operation/documentMutations.js.map +1 -1
  95. package/internal/validators/operation/documentSync.d.ts +26 -406
  96. package/internal/validators/operation/organizationPolicyHistory.d.ts +188 -310
  97. package/internal/validators/operation/organizationPolicyHistory.js +17 -3
  98. package/internal/validators/operation/organizationPolicyHistory.js.map +1 -1
  99. package/internal/validators/response/containerMutationError.d.ts +28 -408
  100. package/internal/validators/response/documentMutation.d.ts +232 -544
  101. package/internal/validators/response/documentMutation.js +1 -2
  102. package/internal/validators/response/documentMutation.js.map +1 -1
  103. package/internal/validators/response/documentSyncError.d.ts +26 -406
  104. package/internal/validators/response/documentSyncError.js +4 -3
  105. package/internal/validators/response/documentSyncError.js.map +1 -1
  106. package/internal/validators/response/index.d.ts +1 -1
  107. package/internal/validators/response/index.js +1 -1
  108. package/internal/validators/response/index.js.map +1 -1
  109. package/internal/validators/response/organizationPolicyHistory.d.ts +127 -309
  110. package/internal/validators/response/organizationPolicyHistory.js +10 -4
  111. package/internal/validators/response/organizationPolicyHistory.js.map +1 -1
  112. package/internal/validators/response/principal.d.ts +28 -408
  113. package/internal/validators/response/principal.js +3 -1
  114. package/internal/validators/response/principal.js.map +1 -1
  115. package/internal/validators/util/index.d.ts +1 -1
  116. package/internal/validators/util/index.js +1 -1
  117. package/internal/validators/util/index.js.map +1 -1
  118. package/internal/validators/util/principalHistoryWire.d.ts +2 -0
  119. package/internal/validators/util/principalHistoryWire.js +2 -0
  120. package/internal/validators/util/principalHistoryWire.js.map +1 -1
  121. package/package.json +1 -1
  122. package/workflows/container-contents/container-state/createWithMetadata.js +19 -49
  123. package/workflows/container-contents/container-state/createWithMetadata.js.map +1 -1
  124. package/workflows/container-contents/container-state/groupGrantVerification.js +29 -0
  125. package/workflows/container-contents/container-state/groupGrantVerification.js.map +1 -1
  126. package/workflows/container-contents/container-state/groupShareEpoch.js +33 -0
  127. package/workflows/container-contents/container-state/groupShareEpoch.js.map +1 -0
  128. package/workflows/container-contents/container-state/remote.js +4 -1
  129. package/workflows/container-contents/container-state/remote.js.map +1 -1
  130. package/workflows/container-contents/container-state/share.js +2 -24
  131. package/workflows/container-contents/container-state/share.js.map +1 -1
  132. package/workflows/container-contents/documentTombstoneEvidence.js +23 -12
  133. package/workflows/container-contents/documentTombstoneEvidence.js.map +1 -1
  134. package/workflows/containers/child/create.js +1 -3
  135. package/workflows/containers/child/create.js.map +1 -1
  136. package/workflows/containers/child/createSubmission.d.ts +1 -3
  137. package/workflows/containers/child/createSubmission.js +13 -15
  138. package/workflows/containers/child/createSubmission.js.map +1 -1
  139. package/workflows/containers/child/currentShareGrantMutation.js +82 -0
  140. package/workflows/containers/child/currentShareGrantMutation.js.map +1 -0
  141. package/workflows/containers/child/currentSharePrincipalPolicy.js +83 -0
  142. package/workflows/containers/child/currentSharePrincipalPolicy.js.map +1 -0
  143. package/workflows/containers/child/mutationSubmit.js +1 -1
  144. package/workflows/containers/child/mutationSubmit.js.map +1 -1
  145. package/workflows/containers/child/runtimeCurrentGroupShare.js +82 -0
  146. package/workflows/containers/child/runtimeCurrentGroupShare.js.map +1 -0
  147. package/workflows/containers/child/share.js +1 -14
  148. package/workflows/containers/child/share.js.map +1 -1
  149. package/workflows/containers/child/shareProjection.js +15 -0
  150. package/workflows/containers/child/shareProjection.js.map +1 -0
  151. package/workflows/documents/purge.d.ts +3 -0
  152. package/workflows/documents/purge.js +13 -0
  153. package/workflows/documents/purge.js.map +1 -1
  154. package/workflows/documents/sync.js +2 -0
  155. package/workflows/documents/sync.js.map +1 -1
  156. package/workflows/documents/syncFailures.js +2 -2
  157. package/workflows/documents/syncFailures.js.map +1 -1
  158. package/workflows/documents/syncPolicyRepair.js +15 -13
  159. package/workflows/documents/syncPolicyRepair.js.map +1 -1
  160. package/workflows/organizations/initialPrincipalCurrentPublication.js +2 -0
  161. package/workflows/organizations/initialPrincipalCurrentPublication.js.map +1 -1
  162. package/workflows/organizations/loadPolicyHistoryDetails.js +31 -32
  163. package/workflows/organizations/loadPolicyHistoryDetails.js.map +1 -1
  164. package/workflows/organizations/organizationPolicyHistoryDetails.js +37 -15
  165. package/workflows/organizations/organizationPolicyHistoryDetails.js.map +1 -1
  166. package/workflows/organizations/organizationPolicyHistoryVerification.js +56 -69
  167. package/workflows/organizations/organizationPolicyHistoryVerification.js.map +1 -1
  168. package/workflows/organizations/policyHistoryCache.js +5 -2
  169. package/workflows/organizations/policyHistoryCache.js.map +1 -1
  170. package/workflows/organizations/policyHistoryTypes.d.ts +1 -0
  171. package/workflows/organizations/policyHistoryTypes.js.map +1 -1
  172. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js +4 -1
  173. package/workflows/organizations/retainAcknowledgedPrincipalCurrents.js.map +1 -1
  174. package/workflows/principals/loadRecoveredPrincipalHistoryPage.d.ts +0 -1
  175. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js +1 -2
  176. package/workflows/principals/loadRecoveredPrincipalHistoryPage.js.map +1 -1
  177. package/workflows/principals/policyRepair.js +38 -0
  178. package/workflows/principals/policyRepair.js.map +1 -0
  179. package/workflows/principals/policyRepairBudget.d.ts +2 -2
  180. package/workflows/principals/policyRepairBudget.js +3 -3
  181. package/workflows/principals/policyRepairBudget.js.map +1 -1
  182. package/workflows/principals/principalHistoryRecoveryPrefix.js +4 -0
  183. package/workflows/principals/principalHistoryRecoveryPrefix.js.map +1 -1
  184. package/workflows/principals/principalRecoveryLocalPreference.js +3 -2
  185. package/workflows/principals/principalRecoveryLocalPreference.js.map +1 -1
  186. package/workflows/principals/publicPrincipalHistoryPage.js +1 -0
  187. package/workflows/principals/publicPrincipalHistoryPage.js.map +1 -1
  188. package/workflows/principals/publicPrincipalHistoryProgress.js +1 -0
  189. package/workflows/principals/publicPrincipalHistoryProgress.js.map +1 -1
  190. package/workflows/principals/publicPrincipalHistoryTypes.d.ts +2 -0
  191. package/workflows/principals/publicPrincipalHistoryTypes.js.map +1 -1
  192. package/workflows/principals/publicProjectionPrincipal.js +1 -0
  193. package/workflows/principals/publicProjectionPrincipal.js.map +1 -1
  194. package/workflows/principals/recoverPrincipalHistoryPage.js +2 -1
  195. package/workflows/principals/recoverPrincipalHistoryPage.js.map +1 -1
  196. package/workflows/principals/recoverPrincipalPolicyHistory.js +1 -0
  197. package/workflows/principals/recoverPrincipalPolicyHistory.js.map +1 -1
  198. package/workflows/principals/recoverPublicPrincipalHistory.js +2 -0
  199. package/workflows/principals/recoverPublicPrincipalHistory.js.map +1 -1
  200. package/workflows/principals/runtimePolicyRecovery.js +2 -1
  201. package/workflows/principals/runtimePolicyRecovery.js.map +1 -1
  202. package/workflows/principals/selectPublicPrincipalHistory.js +21 -15
  203. package/workflows/principals/selectPublicPrincipalHistory.js.map +1 -1
  204. package/workflows/sync/remoteResetPrincipalScope.js +6 -0
  205. package/workflows/sync/remoteResetPrincipalScope.js.map +1 -1
  206. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js +0 -208
  207. package/data/keyingProjectionVerification/principalPolicySnapshotVerification.js.map +0 -1
  208. package/data/keyingProjectionVerification/snapshotVerificationCache.js +0 -39
  209. package/data/keyingProjectionVerification/snapshotVerificationCache.js.map +0 -1
  210. package/workflows/containers/child/policyRepair.js +0 -23
  211. package/workflows/containers/child/policyRepair.js.map +0 -1
@@ -1,12 +1,12 @@
1
1
  import { isContainerSystemSlot, } from "../../../internal/validators/containerSystemSlot.js";
2
2
  import { locallyAcknowledgedContainerMutationHead } from "../../../data/containers/shared/mutationAcknowledgement.js";
3
- import { isStaleParentContainerPathFailure } from "../../../data/containers/shared/mutationFailures.js";
4
3
  import { assertDocumentWriterProjectionConsistent } from "../../../data/documents/shared/projection.js";
5
4
  import { advanceLocallyAcknowledgedAccessManifestHeadsAtomically, locallyAuthoredAccessManifestHead, } from "../../../data/persistence/locallyAcknowledgedCheckpointPersistence.js";
6
5
  import { readContainerMutationMetadataDocumentId, } from "../../containers/index.js";
6
+ import { repairContainerCreateFailure } from "../../containers/child/createSubmission.js";
7
7
  import { documentWriterProjectionFromCreateResponse, persistedDocumentCreateStateFromResponse, resolveDocumentCreateAuthor, } from "../../documents/index.js";
8
- import { cachePrincipalPolicyBundles } from "../../principals/policyCache.js";
9
8
  import { PrincipalPolicyRepairBudget } from "../../principals/policyRepairBudget.js";
9
+ import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
10
10
  import { settleTerminalCreateFailure } from "./createTerminalFailure.js";
11
11
  import { buildContainerWithMetadataPlans, } from "./createWithMetadataPlan.js";
12
12
  /**
@@ -24,29 +24,6 @@ async function submitContainerWithMetadataDocument(input) {
24
24
  });
25
25
  return result.ok ? { ok: true, response: result.data } : result;
26
26
  }
27
- async function cacheStalePrincipalPolicyBundles(input) {
28
- const bundles = input.failure.stalePrincipalPolicies;
29
- const apiClient = input.runtime.apiClient;
30
- const getCurrentPrincipalPolicy = apiClient.getCurrentPrincipalPolicy.bind(apiClient);
31
- if (input.stillCurrent?.() === false)
32
- return false;
33
- if (!bundles || bundles.length === 0) {
34
- return false;
35
- }
36
- // A stale-policy failure is actionable only after the supplied bundles have
37
- // been verified and cached; the next attempt will rebuild from that cache.
38
- await cachePrincipalPolicyBundles({
39
- bundles,
40
- execSql: input.runtime.infra.execSql,
41
- getCurrentPrincipalPolicy,
42
- log: input.runtime.util.log,
43
- organizationId: input.organizationId,
44
- reportSecurityIncident: input.runtime.util.reportSecurityIncident,
45
- resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,
46
- stillCurrent: input.stillCurrent,
47
- });
48
- return input.stillCurrent?.() !== false;
49
- }
50
27
  /**
51
28
  * Seed the metadata document's writer projection from the create response so the
52
29
  * first read after the container is created (its own metadata sync, contents
@@ -217,8 +194,10 @@ async function createRemoteContainerWithMetadataDocumentAttempt(input) {
217
194
  async function createContainerWithMetadataWithRepairs(input) {
218
195
  const { apiClient } = input.runtime;
219
196
  let parentProjection = input.parentProjection;
220
- let didRepairStaleParent = false;
221
- const policyRepairs = new PrincipalPolicyRepairBudget();
197
+ const repairState = {
198
+ didRepairStaleParent: false,
199
+ policyRepairs: new PrincipalPolicyRepairBudget(),
200
+ };
222
201
  for (;;) {
223
202
  const submitted = await createRemoteContainerWithMetadataDocumentAttempt({
224
203
  ...input,
@@ -230,30 +209,21 @@ async function createContainerWithMetadataWithRepairs(input) {
230
209
  if (submitted.ok) {
231
210
  return submitted.state;
232
211
  }
233
- if (policyRepairs.take(submitted.stalePrincipalPolicies) &&
234
- (await cacheStalePrincipalPolicyBundles({
235
- failure: submitted,
236
- organizationId: parentProjection.organizationId,
237
- runtime: input.runtime,
238
- stillCurrent: input.stillCurrent,
239
- }))) {
240
- continue;
241
- }
242
- if (!didRepairStaleParent &&
243
- isStaleParentContainerPathFailure(submitted) &&
244
- apiClient.evictContainerWriterProjection &&
245
- input.stillCurrent?.() !== false) {
246
- didRepairStaleParent = true;
247
- apiClient.evictContainerWriterProjection(input.parentContainerId);
248
- const refreshedProjection = await apiClient.getContainerWriterProjection(input.parentContainerId);
249
- if (!refreshedProjection) {
250
- return null;
251
- }
252
- if (input.stillCurrent?.() === false)
253
- return null;
254
- parentProjection = refreshedProjection;
212
+ const repair = await repairContainerCreateFailure({
213
+ apiClient,
214
+ failure: submitted,
215
+ parentContainerId: input.parentContainerId,
216
+ parentProjection,
217
+ state: repairState,
218
+ warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(input.runtime),
219
+ stillCurrent: input.stillCurrent,
220
+ });
221
+ if (repair.kind === "retry") {
222
+ parentProjection = repair.parentProjection;
255
223
  continue;
256
224
  }
225
+ if (repair.kind === "unavailable")
226
+ return null;
257
227
  return settleTerminalCreateFailure(submitted, input.stillCurrent) ===
258
228
  "committed"
259
229
  ? CONTAINER_ALREADY_COMMITTED
@@ -1 +1 @@
1
- {"version":3,"file":"createWithMetadata.js","sourceRoot":"","sources":["createWithMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerAccessManifestState } from \"@tearleads/crypto\";\nimport {\n type ContainerSystemSlot,\n isContainerSystemSlot,\n} from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerCreateWithMetadataDocumentRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerCreateWithMetadataDocumentResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { locallyAcknowledgedContainerMutationHead } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport { isStaleParentContainerPathFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type { ContainerMutationSubmitFailure } from \"../../../data/containers/shared/types\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../../data/documents/shared/projection\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n locallyAuthoredAccessManifestHead,\n} from \"../../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n type buildMaterializedContainerCreatePlan,\n readContainerMutationMetadataDocumentId,\n} from \"../../containers\";\nimport {\n type buildMaterializedDocumentCreatePlan,\n documentWriterProjectionFromCreateResponse,\n persistedDocumentCreateStateFromResponse,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport { cachePrincipalPolicyBundles } from \"../../principals/policyCache\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport { settleTerminalCreateFailure } from \"./createTerminalFailure\";\nimport {\n buildContainerWithMetadataPlans,\n type ContainerWithMetadataPlanInput,\n} from \"./createWithMetadataPlan\";\nimport type {\n ContainerWorkflowRuntime,\n CreatedRemoteContainerState,\n} from \"./types\";\n\n/**\n * Sentinel for a lost-response retry whose manifest already exists remotely.\n * Callers avoid a duplicate; the next parent hydration settles local state.\n */\nexport const CONTAINER_ALREADY_COMMITTED = Symbol(\"containerAlreadyCommitted\");\nexport type ContainerAlreadyCommitted = typeof CONTAINER_ALREADY_COMMITTED;\n\nasync function submitContainerWithMetadataDocument(input: {\n readonly organizationId: string;\n readonly request: ContainerCreateWithMetadataDocumentRequest;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const { apiClient } = input.runtime;\n const result = await apiClient.createContainerWithMetadataDocumentResult(\n input.request,\n {\n expectedPaymentRequiredOrganizationId: input.organizationId,\n reportErrors: false,\n },\n );\n return result.ok ? { ok: true, response: result.data } : result;\n}\n\nasync function cacheStalePrincipalPolicyBundles(input: {\n readonly failure: ContainerMutationSubmitFailure;\n readonly organizationId: string;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n const bundles = input.failure.stalePrincipalPolicies;\n const apiClient = input.runtime.apiClient;\n const getCurrentPrincipalPolicy =\n apiClient.getCurrentPrincipalPolicy.bind(apiClient);\n if (input.stillCurrent?.() === false) return false;\n if (!bundles || bundles.length === 0) {\n return false;\n }\n\n // A stale-policy failure is actionable only after the supplied bundles have\n // been verified and cached; the next attempt will rebuild from that cache.\n await cachePrincipalPolicyBundles({\n bundles,\n execSql: input.runtime.infra.execSql,\n getCurrentPrincipalPolicy,\n log: input.runtime.util.log,\n organizationId: input.organizationId,\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n return input.stillCurrent?.() !== false;\n}\n\n/**\n * Seed the metadata document's writer projection from the create response so the\n * first read after the container is created (its own metadata sync, contents\n * hydration) resolves locally instead of a cold `GET writer-projection`. The\n * authorizing path is the child container projection the create was authored\n * against — locally built rather than server-fetched, so unlike the plain\n * document-create path this is gated on the projection's internal consistency;\n * on any mismatch the seed is skipped and the next read falls back to a fetch.\n */\nasync function seedMetadataDocumentWriterProjection(input: {\n readonly runtime: ContainerWorkflowRuntime;\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly execSql?: ExecSql | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<void> {\n const projection = documentWriterProjectionFromCreateResponse({\n containerProjection: input.childProjection,\n response: input.response.metadataDocument,\n });\n try {\n await assertDocumentWriterProjectionConsistent(projection, {\n execSql: input.execSql,\n stillCurrent: input.stillCurrent,\n trustedLocalProjection: true,\n });\n } catch {\n return;\n }\n if (input.stillCurrent?.() === false) return;\n input.runtime.apiClient.primeDocumentWriterProjection(\n input.response.metadataDocument.id,\n projection,\n );\n}\n\nasync function acknowledgeContainerWithMetadata(input: {\n containerPlan: Parameters<\n typeof locallyAcknowledgedContainerMutationHead\n >[0][\"plan\"];\n execSql: ExecSql;\n metadataDocumentPlan: Parameters<\n typeof persistedDocumentCreateStateFromResponse\n >[0];\n response: ContainerCreateWithMetadataDocumentResponse;\n stillCurrent?: (() => boolean) | undefined;\n}) {\n const persistedState = persistedDocumentCreateStateFromResponse(\n input.metadataDocumentPlan,\n input.response.metadataDocument,\n );\n const containerHead = await locallyAcknowledgedContainerMutationHead({\n plan: input.containerPlan,\n response: input.response.container,\n });\n await advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads: [\n containerHead,\n locallyAuthoredAccessManifestHead(input.metadataDocumentPlan),\n ],\n stillCurrent: input.stillCurrent,\n });\n return persistedState;\n}\n\n/**\n * Prime the new container's writer projection from the create plan the client\n * just authored, so the first write under it (a child folder, a document)\n * resolves locally instead of a cold `GET writer-projection`. Only primed when\n * the locally-built projection matches what the server created — the create\n * response echoes the container id and manifest head — so a mismatch skips the\n * seed and the next write falls back to a fetch (same fail-closed contract as\n * the metadata-document seed). Priming is safe for writes: the server still\n * validates every mutation, so a projection that later goes stale (rekey/share/\n * move evict it) just yields a rejected write that retries with a fresh fetch.\n */\nfunction seedChildContainerWriterProjection(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n}): void {\n const createdManifestHash =\n input.response.container.manifestHead.manifestHash;\n const projectedManifestHash = input.childProjection.path.at(-1)?.manifestHash;\n // Both hashes must be present and equal, or two undefined hashes would compare\n // equal and prime an empty/invalid projection.\n if (\n !createdManifestHash ||\n !projectedManifestHash ||\n input.childProjection.containerId !==\n input.response.container.containerId ||\n projectedManifestHash !== createdManifestHash\n ) {\n return;\n }\n\n input.runtime.apiClient.primeContainerWriterProjection(\n input.response.container.containerId,\n input.childProjection,\n );\n}\n\n/**\n * The persisted slot is the one this client signed into the manifest state.\n * The acknowledgement already refused a response that echoed anything else,\n * so the server's column never chooses which local record becomes Trash.\n */\nfunction signedCreateSystemSlot(\n state: ContainerAccessManifestState,\n): ContainerSystemSlot | null {\n if (state.systemSlot === null) return null;\n if (!isContainerSystemSlot(state.systemSlot)) {\n throw new Error(\"Container create plan signed an invalid system slot\");\n }\n return state.systemSlot;\n}\n\nasync function settleContainerWithMetadataCreate(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly containerPlan: Awaited<\n ReturnType<typeof buildMaterializedContainerCreatePlan>\n >;\n readonly execSql: ExecSql;\n readonly metadataDocumentPlan: Awaited<\n ReturnType<typeof buildMaterializedDocumentCreatePlan>\n >;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<{\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n} | null> {\n if (\n input.response.container.containerId !==\n input.containerPlan.plan.containerId\n ) {\n throw new Error(\"Container metadata create response container mismatch\");\n }\n // The acknowledgement echoed the signed parent, which a child always names.\n const parentId = input.containerPlan.plan.state.parentContainerId;\n if (parentId === null) {\n throw new Error(\"A container create must commit under a parent\");\n }\n const metadataDocumentId = readContainerMutationMetadataDocumentId({\n response: input.response.container,\n });\n if (\n metadataDocumentId !== input.containerPlan.plan.metadataDocumentId ||\n input.response.metadataDocument.id !==\n input.metadataDocumentPlan.plan.documentId\n ) {\n throw new Error(\"Container metadata create response document mismatch\");\n }\n const persistedMetadataState = await acknowledgeContainerWithMetadata({\n containerPlan: input.containerPlan.plan,\n execSql: input.execSql,\n metadataDocumentPlan: input.metadataDocumentPlan.plan,\n response: input.response,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n await seedMetadataDocumentWriterProjection({\n childProjection: input.childProjection,\n execSql: input.execSql,\n response: input.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n seedChildContainerWriterProjection({\n childProjection: input.childProjection,\n response: input.response,\n runtime: input.runtime,\n });\n return {\n ok: true,\n state: {\n accessManifestHash: input.response.container.manifestHead.manifestHash,\n systemSlot: signedCreateSystemSlot(input.containerPlan.plan.state),\n containerId: input.response.container.containerId,\n createdAt: input.response.container.createdAt,\n metadataDocumentId,\n organizationId: input.response.container.organizationId,\n parentId,\n persistedMetadataState,\n updatedAt: input.response.container.updatedAt,\n },\n };\n}\n\nasync function createRemoteContainerWithMetadataDocumentAttempt(\n input: ContainerWithMetadataPlanInput,\n): Promise<\n | {\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n const execSql = input.runtime.infra.execSql;\n const plans = await buildContainerWithMetadataPlans(input);\n if (!plans) return null;\n const { containerPlan, childProjection, metadataDocumentPlan } = plans;\n const submitted = await submitContainerWithMetadataDocument({\n organizationId: containerPlan.plan.state.organizationId,\n request: {\n systemSlot: input.systemSlot ?? null,\n container: containerPlan.plan.request,\n metadataDocument: metadataDocumentPlan.plan.request,\n },\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (!submitted?.ok) {\n return submitted;\n }\n return settleContainerWithMetadataCreate({\n childProjection,\n containerPlan,\n execSql,\n metadataDocumentPlan,\n response: submitted.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n}\n\nasync function createContainerWithMetadataWithRepairs(\n input: Parameters<\n typeof createRemoteContainerWithMetadataDocumentAttempt\n >[0] & {\n readonly parentContainerId: string;\n },\n): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const { apiClient } = input.runtime;\n let parentProjection = input.parentProjection;\n let didRepairStaleParent = false;\n const policyRepairs = new PrincipalPolicyRepairBudget();\n for (;;) {\n const submitted = await createRemoteContainerWithMetadataDocumentAttempt({\n ...input,\n parentProjection,\n });\n if (!submitted) {\n return null;\n }\n if (submitted.ok) {\n return submitted.state;\n }\n if (\n policyRepairs.take(submitted.stalePrincipalPolicies) &&\n (await cacheStalePrincipalPolicyBundles({\n failure: submitted,\n organizationId: parentProjection.organizationId,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n }))\n ) {\n continue;\n }\n if (\n !didRepairStaleParent &&\n isStaleParentContainerPathFailure(submitted) &&\n apiClient.evictContainerWriterProjection &&\n input.stillCurrent?.() !== false\n ) {\n didRepairStaleParent = true;\n apiClient.evictContainerWriterProjection(input.parentContainerId);\n const refreshedProjection = await apiClient.getContainerWriterProjection(\n input.parentContainerId,\n );\n if (!refreshedProjection) {\n return null;\n }\n if (input.stillCurrent?.() === false) return null;\n parentProjection = refreshedProjection;\n continue;\n }\n return settleTerminalCreateFailure(submitted, input.stillCurrent) ===\n \"committed\"\n ? CONTAINER_ALREADY_COMMITTED\n : null;\n }\n}\n\nexport async function createRemoteContainerWithMetadataDocument(input: {\n systemSlot?: ContainerSystemSlot | null | undefined;\n containerId: string;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const author = resolveDocumentCreateAuthor(input.runtime);\n const { apiClient } = input.runtime;\n const parentSecretKey = input.runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!author || !parentSecretKey) {\n input.runtime.util.log(\n \"Container contents: skipped container create because the writer context is unavailable.\",\n );\n return null;\n }\n\n const parentProjection =\n input.parentProjection ??\n (await apiClient.getContainerWriterProjection(input.parentContainerId));\n if (!parentProjection) {\n return null;\n }\n\n const containerEventId = crypto.randomUUID();\n const containerKey = crypto.getRandomValues(new Uint8Array(32));\n const containerSignedAt = new Date().toISOString();\n const metadataContentKey = crypto.getRandomValues(new Uint8Array(32));\n const metadataEventId = crypto.randomUUID();\n const metadataSignedAt = new Date().toISOString();\n return createContainerWithMetadataWithRepairs({\n author,\n containerEventId,\n containerId: input.containerId,\n containerKey,\n containerSignedAt,\n metadataContentKey,\n metadataEventId,\n metadataSignedAt,\n parentContainerId: input.parentContainerId,\n parentProjection,\n parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n systemSlot: input.systemSlot,\n });\n}\n"]}
1
+ {"version":3,"file":"createWithMetadata.js","sourceRoot":"","sources":["createWithMetadata.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerAccessManifestState } from \"@tearleads/crypto\";\nimport {\n type ContainerSystemSlot,\n isContainerSystemSlot,\n} from \"@tearleads/validators/containerSystemSlot\";\nimport type { ContainerCreateWithMetadataDocumentRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerCreateWithMetadataDocumentResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { locallyAcknowledgedContainerMutationHead } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport type { ContainerMutationSubmitFailure } from \"../../../data/containers/shared/types\";\nimport { assertDocumentWriterProjectionConsistent } from \"../../../data/documents/shared/projection\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport {\n advanceLocallyAcknowledgedAccessManifestHeadsAtomically,\n locallyAuthoredAccessManifestHead,\n} from \"../../../data/persistence/locallyAcknowledgedCheckpointPersistence\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport {\n type buildMaterializedContainerCreatePlan,\n readContainerMutationMetadataDocumentId,\n} from \"../../containers\";\nimport { repairContainerCreateFailure } from \"../../containers/child/createSubmission\";\nimport {\n type buildMaterializedDocumentCreatePlan,\n documentWriterProjectionFromCreateResponse,\n persistedDocumentCreateStateFromResponse,\n resolveDocumentCreateAuthor,\n} from \"../../documents\";\nimport { PrincipalPolicyRepairBudget } from \"../../principals/policyRepairBudget\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport { settleTerminalCreateFailure } from \"./createTerminalFailure\";\nimport {\n buildContainerWithMetadataPlans,\n type ContainerWithMetadataPlanInput,\n} from \"./createWithMetadataPlan\";\nimport type {\n ContainerWorkflowRuntime,\n CreatedRemoteContainerState,\n} from \"./types\";\n\n/**\n * Sentinel for a lost-response retry whose manifest already exists remotely.\n * Callers avoid a duplicate; the next parent hydration settles local state.\n */\nexport const CONTAINER_ALREADY_COMMITTED = Symbol(\"containerAlreadyCommitted\");\nexport type ContainerAlreadyCommitted = typeof CONTAINER_ALREADY_COMMITTED;\n\nasync function submitContainerWithMetadataDocument(input: {\n readonly organizationId: string;\n readonly request: ContainerCreateWithMetadataDocumentRequest;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<\n | {\n readonly ok: true;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n if (input.stillCurrent?.() === false) return null;\n const { apiClient } = input.runtime;\n const result = await apiClient.createContainerWithMetadataDocumentResult(\n input.request,\n {\n expectedPaymentRequiredOrganizationId: input.organizationId,\n reportErrors: false,\n },\n );\n return result.ok ? { ok: true, response: result.data } : result;\n}\n\n/**\n * Seed the metadata document's writer projection from the create response so the\n * first read after the container is created (its own metadata sync, contents\n * hydration) resolves locally instead of a cold `GET writer-projection`. The\n * authorizing path is the child container projection the create was authored\n * against — locally built rather than server-fetched, so unlike the plain\n * document-create path this is gated on the projection's internal consistency;\n * on any mismatch the seed is skipped and the next read falls back to a fetch.\n */\nasync function seedMetadataDocumentWriterProjection(input: {\n readonly runtime: ContainerWorkflowRuntime;\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly execSql?: ExecSql | undefined;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<void> {\n const projection = documentWriterProjectionFromCreateResponse({\n containerProjection: input.childProjection,\n response: input.response.metadataDocument,\n });\n try {\n await assertDocumentWriterProjectionConsistent(projection, {\n execSql: input.execSql,\n stillCurrent: input.stillCurrent,\n trustedLocalProjection: true,\n });\n } catch {\n return;\n }\n if (input.stillCurrent?.() === false) return;\n input.runtime.apiClient.primeDocumentWriterProjection(\n input.response.metadataDocument.id,\n projection,\n );\n}\n\nasync function acknowledgeContainerWithMetadata(input: {\n containerPlan: Parameters<\n typeof locallyAcknowledgedContainerMutationHead\n >[0][\"plan\"];\n execSql: ExecSql;\n metadataDocumentPlan: Parameters<\n typeof persistedDocumentCreateStateFromResponse\n >[0];\n response: ContainerCreateWithMetadataDocumentResponse;\n stillCurrent?: (() => boolean) | undefined;\n}) {\n const persistedState = persistedDocumentCreateStateFromResponse(\n input.metadataDocumentPlan,\n input.response.metadataDocument,\n );\n const containerHead = await locallyAcknowledgedContainerMutationHead({\n plan: input.containerPlan,\n response: input.response.container,\n });\n await advanceLocallyAcknowledgedAccessManifestHeadsAtomically({\n execSql: input.execSql,\n heads: [\n containerHead,\n locallyAuthoredAccessManifestHead(input.metadataDocumentPlan),\n ],\n stillCurrent: input.stillCurrent,\n });\n return persistedState;\n}\n\n/**\n * Prime the new container's writer projection from the create plan the client\n * just authored, so the first write under it (a child folder, a document)\n * resolves locally instead of a cold `GET writer-projection`. Only primed when\n * the locally-built projection matches what the server created — the create\n * response echoes the container id and manifest head — so a mismatch skips the\n * seed and the next write falls back to a fetch (same fail-closed contract as\n * the metadata-document seed). Priming is safe for writes: the server still\n * validates every mutation, so a projection that later goes stale (rekey/share/\n * move evict it) just yields a rejected write that retries with a fresh fetch.\n */\nfunction seedChildContainerWriterProjection(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n}): void {\n const createdManifestHash =\n input.response.container.manifestHead.manifestHash;\n const projectedManifestHash = input.childProjection.path.at(-1)?.manifestHash;\n // Both hashes must be present and equal, or two undefined hashes would compare\n // equal and prime an empty/invalid projection.\n if (\n !createdManifestHash ||\n !projectedManifestHash ||\n input.childProjection.containerId !==\n input.response.container.containerId ||\n projectedManifestHash !== createdManifestHash\n ) {\n return;\n }\n\n input.runtime.apiClient.primeContainerWriterProjection(\n input.response.container.containerId,\n input.childProjection,\n );\n}\n\n/**\n * The persisted slot is the one this client signed into the manifest state.\n * The acknowledgement already refused a response that echoed anything else,\n * so the server's column never chooses which local record becomes Trash.\n */\nfunction signedCreateSystemSlot(\n state: ContainerAccessManifestState,\n): ContainerSystemSlot | null {\n if (state.systemSlot === null) return null;\n if (!isContainerSystemSlot(state.systemSlot)) {\n throw new Error(\"Container create plan signed an invalid system slot\");\n }\n return state.systemSlot;\n}\n\nasync function settleContainerWithMetadataCreate(input: {\n readonly childProjection: ContainerWriterProjectionResponse;\n readonly containerPlan: Awaited<\n ReturnType<typeof buildMaterializedContainerCreatePlan>\n >;\n readonly execSql: ExecSql;\n readonly metadataDocumentPlan: Awaited<\n ReturnType<typeof buildMaterializedDocumentCreatePlan>\n >;\n readonly response: ContainerCreateWithMetadataDocumentResponse;\n readonly runtime: ContainerWorkflowRuntime;\n readonly stillCurrent?: (() => boolean) | undefined;\n}): Promise<{\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n} | null> {\n if (\n input.response.container.containerId !==\n input.containerPlan.plan.containerId\n ) {\n throw new Error(\"Container metadata create response container mismatch\");\n }\n // The acknowledgement echoed the signed parent, which a child always names.\n const parentId = input.containerPlan.plan.state.parentContainerId;\n if (parentId === null) {\n throw new Error(\"A container create must commit under a parent\");\n }\n const metadataDocumentId = readContainerMutationMetadataDocumentId({\n response: input.response.container,\n });\n if (\n metadataDocumentId !== input.containerPlan.plan.metadataDocumentId ||\n input.response.metadataDocument.id !==\n input.metadataDocumentPlan.plan.documentId\n ) {\n throw new Error(\"Container metadata create response document mismatch\");\n }\n const persistedMetadataState = await acknowledgeContainerWithMetadata({\n containerPlan: input.containerPlan.plan,\n execSql: input.execSql,\n metadataDocumentPlan: input.metadataDocumentPlan.plan,\n response: input.response,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n await seedMetadataDocumentWriterProjection({\n childProjection: input.childProjection,\n execSql: input.execSql,\n response: input.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n seedChildContainerWriterProjection({\n childProjection: input.childProjection,\n response: input.response,\n runtime: input.runtime,\n });\n return {\n ok: true,\n state: {\n accessManifestHash: input.response.container.manifestHead.manifestHash,\n systemSlot: signedCreateSystemSlot(input.containerPlan.plan.state),\n containerId: input.response.container.containerId,\n createdAt: input.response.container.createdAt,\n metadataDocumentId,\n organizationId: input.response.container.organizationId,\n parentId,\n persistedMetadataState,\n updatedAt: input.response.container.updatedAt,\n },\n };\n}\n\nasync function createRemoteContainerWithMetadataDocumentAttempt(\n input: ContainerWithMetadataPlanInput,\n): Promise<\n | {\n readonly ok: true;\n readonly state: CreatedRemoteContainerState;\n }\n | ContainerMutationSubmitFailure\n | null\n> {\n const execSql = input.runtime.infra.execSql;\n const plans = await buildContainerWithMetadataPlans(input);\n if (!plans) return null;\n const { containerPlan, childProjection, metadataDocumentPlan } = plans;\n const submitted = await submitContainerWithMetadataDocument({\n organizationId: containerPlan.plan.state.organizationId,\n request: {\n systemSlot: input.systemSlot ?? null,\n container: containerPlan.plan.request,\n metadataDocument: metadataDocumentPlan.plan.request,\n },\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n if (!submitted?.ok) {\n return submitted;\n }\n return settleContainerWithMetadataCreate({\n childProjection,\n containerPlan,\n execSql,\n metadataDocumentPlan,\n response: submitted.response,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n });\n}\n\nasync function createContainerWithMetadataWithRepairs(\n input: Parameters<\n typeof createRemoteContainerWithMetadataDocumentAttempt\n >[0] & {\n readonly parentContainerId: string;\n },\n): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const { apiClient } = input.runtime;\n let parentProjection = input.parentProjection;\n const repairState = {\n didRepairStaleParent: false,\n policyRepairs: new PrincipalPolicyRepairBudget(),\n };\n for (;;) {\n const submitted = await createRemoteContainerWithMetadataDocumentAttempt({\n ...input,\n parentProjection,\n });\n if (!submitted) {\n return null;\n }\n if (submitted.ok) {\n return submitted.state;\n }\n const repair = await repairContainerCreateFailure({\n apiClient,\n failure: submitted,\n parentContainerId: input.parentContainerId,\n parentProjection,\n state: repairState,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n stillCurrent: input.stillCurrent,\n });\n if (repair.kind === \"retry\") {\n parentProjection = repair.parentProjection;\n continue;\n }\n if (repair.kind === \"unavailable\") return null;\n return settleTerminalCreateFailure(submitted, input.stillCurrent) ===\n \"committed\"\n ? CONTAINER_ALREADY_COMMITTED\n : null;\n }\n}\n\nexport async function createRemoteContainerWithMetadataDocument(input: {\n systemSlot?: ContainerSystemSlot | null | undefined;\n containerId: string;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n const author = resolveDocumentCreateAuthor(input.runtime);\n const { apiClient } = input.runtime;\n const parentSecretKey = input.runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!author || !parentSecretKey) {\n input.runtime.util.log(\n \"Container contents: skipped container create because the writer context is unavailable.\",\n );\n return null;\n }\n\n const parentProjection =\n input.parentProjection ??\n (await apiClient.getContainerWriterProjection(input.parentContainerId));\n if (!parentProjection) {\n return null;\n }\n\n const containerEventId = crypto.randomUUID();\n const containerKey = crypto.getRandomValues(new Uint8Array(32));\n const containerSignedAt = new Date().toISOString();\n const metadataContentKey = crypto.getRandomValues(new Uint8Array(32));\n const metadataEventId = crypto.randomUUID();\n const metadataSignedAt = new Date().toISOString();\n return createContainerWithMetadataWithRepairs({\n author,\n containerEventId,\n containerId: input.containerId,\n containerKey,\n containerSignedAt,\n metadataContentKey,\n metadataEventId,\n metadataSignedAt,\n parentContainerId: input.parentContainerId,\n parentProjection,\n parentSecretKey,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n runtime: input.runtime,\n stillCurrent: input.stillCurrent,\n systemSlot: input.systemSlot,\n });\n}\n"]}
@@ -4,6 +4,7 @@ import { principalPolicyCacheForVerifiedPolicies } from "../../../data/keyingPro
4
4
  import { savePrincipalPolicyBundle } from "../../../data/persistence/principalPolicyPersistence.js";
5
5
  import { principalPolicyBundleContainsReference } from "../../../data/principalPolicyStates.js";
6
6
  import { advanceVerifiedSharePolicies, loadVerifiedGroupSharePrincipalPolicy, referencedPrincipalHeadFromPolicy, } from "../../containers/index.js";
7
+ import { createRuntimeCurrentSharePrincipalPolicy } from "../../containers/child/currentSharePrincipalPolicy.js";
7
8
  import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
8
9
  import { loadContainerWriterProjectionForState } from "./projectionCache.js";
9
10
  function projectionHasCurrentGroupGrant(input) {
@@ -38,6 +39,34 @@ async function containerStateHasCurrentGroupGrantInternal(input) {
38
39
  projection.organizationId !== input.expectedOrganizationId) {
39
40
  return false;
40
41
  }
42
+ const readCurrent = createRuntimeCurrentSharePrincipalPolicy(input.runtime);
43
+ if (readCurrent)
44
+ return readCurrent({
45
+ expectedGroupHead: input.expectedGroupHead,
46
+ groupId: input.groupId,
47
+ organizationId: input.expectedOrganizationId,
48
+ stillCurrent: input.stillCurrent ?? (() => true),
49
+ }, async ({ checkpointPolicies, policy, stillCurrent }) => {
50
+ await verifyContainerWriterProjection({
51
+ execSql: input.runtime.infra.execSql,
52
+ principalPolicyCache: principalPolicyCacheForVerifiedPolicies(checkpointPolicies),
53
+ projection,
54
+ resolveUserKey: input.resolveProjectionUserKey,
55
+ stillCurrent,
56
+ warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(input.runtime),
57
+ });
58
+ return projectionHasCurrentGroupGrant({
59
+ accessLevel: input.accessLevel,
60
+ currentHead: referencedPrincipalHeadFromPolicy(policy),
61
+ expectedContainerId: input.expectedContainerId,
62
+ expectedOrganizationId: input.expectedOrganizationId,
63
+ groupId: input.groupId,
64
+ projection,
65
+ });
66
+ });
67
+ return verifyLegacyCurrentGroupGrant(input, projection);
68
+ }
69
+ async function verifyLegacyCurrentGroupGrant(input, projection) {
41
70
  const { bundle, checkpointPolicies, dependencyBundles, policy } = await loadVerifiedGroupSharePrincipalPolicy({
42
71
  apiClient: input.runtime.apiClient,
43
72
  execSql: input.runtime.infra.execSql,
@@ -1 +1 @@
1
- {"version":3,"file":"groupGrantVerification.js","sourceRoot":"","sources":["groupGrantVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReferencedPrincipalHead } from \"@tearleads/crypto\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport {\n nullOnProjectionVerificationCancellation,\n type ProjectionUserKeyResolver,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport { principalPolicyCacheForVerifiedPolicies } from \"../../../data/keyingProjectionVerification/principalPolicyCache\";\nimport { savePrincipalPolicyBundle } from \"../../../data/persistence/principalPolicyPersistence\";\nimport { principalPolicyBundleContainsReference } from \"../../../data/principalPolicyStates\";\nimport {\n advanceVerifiedSharePolicies,\n loadVerifiedGroupSharePrincipalPolicy,\n referencedPrincipalHeadFromPolicy,\n} from \"../../containers\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { loadContainerWriterProjectionForState } from \"./projectionCache\";\nimport type { ContainerWorkflowRuntime } from \"./types\";\n\ntype GroupGrantAccessLevel = \"read\" | \"write\" | \"admin\";\n\nfunction projectionHasCurrentGroupGrant(input: {\n accessLevel: GroupGrantAccessLevel;\n expectedContainerId: string;\n expectedOrganizationId: string;\n groupId: string;\n currentHead: ReferencedPrincipalHead;\n projection: NonNullable<\n Awaited<ReturnType<typeof loadContainerWriterProjectionForState>>\n >;\n}): boolean {\n const state = readContainerState(\n getTargetContainerContext(input.projection).manifest,\n );\n return (\n state.containerId === input.expectedContainerId &&\n state.organizationId === input.expectedOrganizationId &&\n state.directGrants.some(\n (grant) =>\n grant.subjectType === \"group\" &&\n grant.subjectId === input.groupId &&\n grant.accessLevel === input.accessLevel,\n ) &&\n state.referencedPrincipalHeads.some(\n (head) =>\n head.principalType === input.currentHead.principalType &&\n head.principalId === input.currentHead.principalId &&\n head.version === input.currentHead.version &&\n head.keyEpoch === input.currentHead.keyEpoch &&\n head.stateHash === input.currentHead.stateHash &&\n head.keyFingerprint === input.currentHead.keyFingerprint,\n )\n );\n}\n\nasync function containerStateHasCurrentGroupGrantInternal(input: {\n accessLevel: GroupGrantAccessLevel;\n containerState: ContainerState;\n expectedContainerId: string;\n expectedGroupHead: ReferencedPrincipalHead;\n expectedOrganizationId: string;\n groupId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n if (input.stillCurrent?.() === false) return false;\n const projection = await loadContainerWriterProjectionForState({\n containerState: input.containerState,\n runtime: input.runtime,\n });\n if (\n !projection ||\n input.stillCurrent?.() === false ||\n input.expectedGroupHead.principalType !== \"group\" ||\n input.expectedGroupHead.principalId !== input.groupId ||\n input.containerState.container.id !== input.expectedContainerId ||\n input.containerState.container.organizationId !==\n input.expectedOrganizationId ||\n projection.containerId !== input.expectedContainerId ||\n projection.organizationId !== input.expectedOrganizationId\n ) {\n return false;\n }\n\n const { bundle, checkpointPolicies, dependencyBundles, policy } =\n await loadVerifiedGroupSharePrincipalPolicy({\n apiClient: input.runtime.apiClient,\n execSql: input.runtime.infra.execSql,\n expectedGroupHead: input.expectedGroupHead,\n groupId: input.groupId,\n organizationId: input.expectedOrganizationId,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return false;\n if (\n !principalPolicyBundleContainsReference(bundle, input.expectedGroupHead)\n ) {\n return false;\n }\n const currentHead = referencedPrincipalHeadFromPolicy(policy);\n await advanceVerifiedSharePolicies(\n input.runtime.infra.execSql,\n {\n checkpointPolicies,\n dependencyBundles,\n organizationId: input.expectedOrganizationId,\n },\n input.stillCurrent,\n );\n if (input.stillCurrent?.() === false) return false;\n await verifyContainerWriterProjection({\n execSql: input.runtime.infra.execSql,\n principalPolicyCache:\n principalPolicyCacheForVerifiedPolicies(checkpointPolicies),\n projection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n const isCurrent = projectionHasCurrentGroupGrant({\n accessLevel: input.accessLevel,\n currentHead,\n expectedContainerId: input.expectedContainerId,\n expectedOrganizationId: input.expectedOrganizationId,\n groupId: input.groupId,\n projection,\n });\n if (isCurrent) {\n try {\n await savePrincipalPolicyBundle(\n input.runtime.infra.execSql,\n bundle,\n new Date().toISOString(),\n input.expectedOrganizationId,\n { stillCurrent: input.stillCurrent },\n );\n } catch {\n // The cryptographically verified root grant is already safe. A local\n // cache failure must not keep it pending or trigger duplicate re-wraps.\n }\n }\n return input.stillCurrent?.() !== false && isCurrent;\n}\n\nexport async function containerStateHasCurrentGroupGrant(\n input: Parameters<typeof containerStateHasCurrentGroupGrantInternal>[0],\n): Promise<boolean> {\n return (\n (await nullOnProjectionVerificationCancellation(() =>\n containerStateHasCurrentGroupGrantInternal(input),\n )) ?? false\n );\n}\n"]}
1
+ {"version":3,"file":"groupGrantVerification.js","sourceRoot":"","sources":["groupGrantVerification.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ReferencedPrincipalHead } from \"@tearleads/crypto\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport {\n nullOnProjectionVerificationCancellation,\n type ProjectionUserKeyResolver,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport { principalPolicyCacheForVerifiedPolicies } from \"../../../data/keyingProjectionVerification/principalPolicyCache\";\nimport { savePrincipalPolicyBundle } from \"../../../data/persistence/principalPolicyPersistence\";\nimport { principalPolicyBundleContainsReference } from \"../../../data/principalPolicyStates\";\nimport {\n advanceVerifiedSharePolicies,\n loadVerifiedGroupSharePrincipalPolicy,\n referencedPrincipalHeadFromPolicy,\n} from \"../../containers\";\nimport { createRuntimeCurrentSharePrincipalPolicy } from \"../../containers/child/currentSharePrincipalPolicy\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport type { ContainerState } from \"../remoteHydration\";\nimport { loadContainerWriterProjectionForState } from \"./projectionCache\";\nimport type { ContainerWorkflowRuntime } from \"./types\";\n\ntype GroupGrantAccessLevel = \"read\" | \"write\" | \"admin\";\n\nfunction projectionHasCurrentGroupGrant(input: {\n accessLevel: GroupGrantAccessLevel;\n expectedContainerId: string;\n expectedOrganizationId: string;\n groupId: string;\n currentHead: ReferencedPrincipalHead;\n projection: NonNullable<\n Awaited<ReturnType<typeof loadContainerWriterProjectionForState>>\n >;\n}): boolean {\n const state = readContainerState(\n getTargetContainerContext(input.projection).manifest,\n );\n return (\n state.containerId === input.expectedContainerId &&\n state.organizationId === input.expectedOrganizationId &&\n state.directGrants.some(\n (grant) =>\n grant.subjectType === \"group\" &&\n grant.subjectId === input.groupId &&\n grant.accessLevel === input.accessLevel,\n ) &&\n state.referencedPrincipalHeads.some(\n (head) =>\n head.principalType === input.currentHead.principalType &&\n head.principalId === input.currentHead.principalId &&\n head.version === input.currentHead.version &&\n head.keyEpoch === input.currentHead.keyEpoch &&\n head.stateHash === input.currentHead.stateHash &&\n head.keyFingerprint === input.currentHead.keyFingerprint,\n )\n );\n}\n\nasync function containerStateHasCurrentGroupGrantInternal(input: {\n accessLevel: GroupGrantAccessLevel;\n containerState: ContainerState;\n expectedContainerId: string;\n expectedGroupHead: ReferencedPrincipalHead;\n expectedOrganizationId: string;\n groupId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<boolean> {\n if (input.stillCurrent?.() === false) return false;\n const projection = await loadContainerWriterProjectionForState({\n containerState: input.containerState,\n runtime: input.runtime,\n });\n if (\n !projection ||\n input.stillCurrent?.() === false ||\n input.expectedGroupHead.principalType !== \"group\" ||\n input.expectedGroupHead.principalId !== input.groupId ||\n input.containerState.container.id !== input.expectedContainerId ||\n input.containerState.container.organizationId !==\n input.expectedOrganizationId ||\n projection.containerId !== input.expectedContainerId ||\n projection.organizationId !== input.expectedOrganizationId\n ) {\n return false;\n }\n\n const readCurrent = createRuntimeCurrentSharePrincipalPolicy(input.runtime);\n if (readCurrent)\n return readCurrent(\n {\n expectedGroupHead: input.expectedGroupHead,\n groupId: input.groupId,\n organizationId: input.expectedOrganizationId,\n stillCurrent: input.stillCurrent ?? (() => true),\n },\n async ({ checkpointPolicies, policy, stillCurrent }) => {\n await verifyContainerWriterProjection({\n execSql: input.runtime.infra.execSql,\n principalPolicyCache:\n principalPolicyCacheForVerifiedPolicies(checkpointPolicies),\n projection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n return projectionHasCurrentGroupGrant({\n accessLevel: input.accessLevel,\n currentHead: referencedPrincipalHeadFromPolicy(policy),\n expectedContainerId: input.expectedContainerId,\n expectedOrganizationId: input.expectedOrganizationId,\n groupId: input.groupId,\n projection,\n });\n },\n );\n\n return verifyLegacyCurrentGroupGrant(input, projection);\n}\n\nasync function verifyLegacyCurrentGroupGrant(\n input: Parameters<typeof containerStateHasCurrentGroupGrantInternal>[0],\n projection: Parameters<\n typeof projectionHasCurrentGroupGrant\n >[0][\"projection\"],\n): Promise<boolean> {\n const { bundle, checkpointPolicies, dependencyBundles, policy } =\n await loadVerifiedGroupSharePrincipalPolicy({\n apiClient: input.runtime.apiClient,\n execSql: input.runtime.infra.execSql,\n expectedGroupHead: input.expectedGroupHead,\n groupId: input.groupId,\n organizationId: input.expectedOrganizationId,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return false;\n if (\n !principalPolicyBundleContainsReference(bundle, input.expectedGroupHead)\n ) {\n return false;\n }\n const currentHead = referencedPrincipalHeadFromPolicy(policy);\n await advanceVerifiedSharePolicies(\n input.runtime.infra.execSql,\n {\n checkpointPolicies,\n dependencyBundles,\n organizationId: input.expectedOrganizationId,\n },\n input.stillCurrent,\n );\n if (input.stillCurrent?.() === false) return false;\n await verifyContainerWriterProjection({\n execSql: input.runtime.infra.execSql,\n principalPolicyCache:\n principalPolicyCacheForVerifiedPolicies(checkpointPolicies),\n projection,\n resolveUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n const isCurrent = projectionHasCurrentGroupGrant({\n accessLevel: input.accessLevel,\n currentHead,\n expectedContainerId: input.expectedContainerId,\n expectedOrganizationId: input.expectedOrganizationId,\n groupId: input.groupId,\n projection,\n });\n if (isCurrent) {\n try {\n await savePrincipalPolicyBundle(\n input.runtime.infra.execSql,\n bundle,\n new Date().toISOString(),\n input.expectedOrganizationId,\n { stillCurrent: input.stillCurrent },\n );\n } catch {\n // The cryptographically verified root grant is already safe. A local\n // cache failure must not keep it pending or trigger duplicate re-wraps.\n }\n }\n return input.stillCurrent?.() !== false && isCurrent;\n}\n\nexport async function containerStateHasCurrentGroupGrant(\n input: Parameters<typeof containerStateHasCurrentGroupGrantInternal>[0],\n): Promise<boolean> {\n return (\n (await nullOnProjectionVerificationCancellation(() =>\n containerStateHasCurrentGroupGrantInternal(input),\n )) ?? false\n );\n}\n"]}
@@ -0,0 +1,33 @@
1
+ import { advanceVerifiedSharePolicies, loadVerifiedGroupSharePrincipalPolicy, } from "../../containers/index.js";
2
+ import { createRuntimeCurrentSharePrincipalPolicy } from "../../containers/child/currentSharePrincipalPolicy.js";
3
+ import { createRuntimeGroupMetadataAccess } from "../../organizations/groupMetadataRuntime.js";
4
+ export async function resolveCurrentGroupKeyEpoch(input) {
5
+ if (input.stillCurrent?.() === false)
6
+ return null;
7
+ const readCurrent = createRuntimeCurrentSharePrincipalPolicy(input.runtime);
8
+ if (readCurrent)
9
+ return readCurrent({
10
+ expectedGroupName: input.expectedGroupName,
11
+ groupId: input.groupId,
12
+ organizationId: input.organizationId,
13
+ stillCurrent: input.stillCurrent ?? (() => true),
14
+ }, async ({ policy }) => policy.keyEpoch);
15
+ const verified = await loadVerifiedGroupSharePrincipalPolicy({
16
+ apiClient: input.runtime.apiClient,
17
+ execSql: input.runtime.infra.execSql,
18
+ expectedGroupName: input.expectedGroupName,
19
+ readEncryptedName: (bundle) => createRuntimeGroupMetadataAccess(input.runtime, input.organizationId, input.stillCurrent).readName(bundle),
20
+ groupId: input.groupId,
21
+ organizationId: input.organizationId,
22
+ resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,
23
+ stillCurrent: input.stillCurrent,
24
+ });
25
+ if (input.stillCurrent?.() === false)
26
+ return null;
27
+ // Commit the verification immediately: this read stands alone (no enclosing
28
+ // mutation advances it later), and an unadvanced checkpoint would let a
29
+ // newer same-epoch policy be rolled back on the next fetch.
30
+ await advanceVerifiedSharePolicies(input.runtime.infra.execSql, verified, input.stillCurrent);
31
+ return input.stillCurrent?.() === false ? null : verified.policy.keyEpoch;
32
+ }
33
+ //# sourceMappingURL=groupShareEpoch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"groupShareEpoch.js","sourceRoot":"","sources":["groupShareEpoch.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,4BAA4B,EAC5B,qCAAqC,GACtC,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,wCAAwC,EAAE,MAAM,oDAAoD,CAAC;AAC9G,OAAO,EAAE,gCAAgC,EAAE,MAAM,0CAA0C,CAAC;AAG5F,MAAM,CAAC,KAAK,UAAU,2BAA2B,CAAC,KAQjD;IACC,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,MAAM,WAAW,GAAG,wCAAwC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC5E,IAAI,WAAW;QACb,OAAO,WAAW,CAChB;YACE,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;YAC1C,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,cAAc,EAAE,KAAK,CAAC,cAAc;YACpC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;SACjD,EACD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CACtC,CAAC;IACJ,MAAM,QAAQ,GAAG,MAAM,qCAAqC,CAAC;QAC3D,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS;QAClC,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO;QACpC,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;QAC1C,iBAAiB,EAAE,CAAC,MAAM,EAAE,EAAE,CAC5B,gCAAgC,CAC9B,KAAK,CAAC,OAAO,EACb,KAAK,CAAC,cAAc,EACpB,KAAK,CAAC,YAAY,CACnB,CAAC,QAAQ,CAAC,MAAM,CAAC;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,0BAA0B,EAAE,KAAK,CAAC,OAAO,CAAC,0BAA0B;QACpE,YAAY,EAAE,KAAK,CAAC,YAAY;KACjC,CAAC,CAAC;IACH,IAAI,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IAClD,4EAA4E;IAC5E,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM,4BAA4B,CAChC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,EAC3B,QAAQ,EACR,KAAK,CAAC,YAAY,CACnB,CAAC;IACF,OAAO,KAAK,CAAC,YAAY,EAAE,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC;AAC5E,CAAC","sourcesContent":["import {\n advanceVerifiedSharePolicies,\n loadVerifiedGroupSharePrincipalPolicy,\n} from \"../../containers\";\nimport { createRuntimeCurrentSharePrincipalPolicy } from \"../../containers/child/currentSharePrincipalPolicy\";\nimport { createRuntimeGroupMetadataAccess } from \"../../organizations/groupMetadataRuntime\";\nimport type { ContainerWorkflowRuntime } from \"./types\";\n\nexport async function resolveCurrentGroupKeyEpoch(input: {\n // Bound here, in the one verified load a duplicate share performs, so a\n // duplicate never reports success for a group the user did not choose.\n expectedGroupName?: string | undefined;\n groupId: string;\n organizationId: string;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<number | null> {\n if (input.stillCurrent?.() === false) return null;\n const readCurrent = createRuntimeCurrentSharePrincipalPolicy(input.runtime);\n if (readCurrent)\n return readCurrent(\n {\n expectedGroupName: input.expectedGroupName,\n groupId: input.groupId,\n organizationId: input.organizationId,\n stillCurrent: input.stillCurrent ?? (() => true),\n },\n async ({ policy }) => policy.keyEpoch,\n );\n const verified = await loadVerifiedGroupSharePrincipalPolicy({\n apiClient: input.runtime.apiClient,\n execSql: input.runtime.infra.execSql,\n expectedGroupName: input.expectedGroupName,\n readEncryptedName: (bundle) =>\n createRuntimeGroupMetadataAccess(\n input.runtime,\n input.organizationId,\n input.stillCurrent,\n ).readName(bundle),\n groupId: input.groupId,\n organizationId: input.organizationId,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n });\n if (input.stillCurrent?.() === false) return null;\n // Commit the verification immediately: this read stands alone (no enclosing\n // mutation advances it later), and an unadvanced checkpoint would let a\n // newer same-epoch policy be rolled back on the next fetch.\n await advanceVerifiedSharePolicies(\n input.runtime.infra.execSql,\n verified,\n input.stillCurrent,\n );\n return input.stillCurrent?.() === false ? null : verified.policy.keyEpoch;\n}\n"]}
@@ -1,5 +1,6 @@
1
1
  import { isContainerNotFoundFailure } from "../../../data/containers/shared/mutationFailures.js";
2
2
  import { moveRemoteContainer as moveRemoteContainerMutation, readContainerMutationMetadataDocumentId, referencedPrincipalHeadsFromContainerMutationResponse, shareRemoteContainer as shareRemoteContainerMutation, shareRemoteContainerWithGroup as shareRemoteContainerWithGroupMutation, } from "../../containers/index.js";
3
+ import { createRuntimeCurrentGroupShare } from "../../containers/child/runtimeCurrentGroupShare.js";
3
4
  import { resolveDocumentCreateAuthor } from "../../documents/index.js";
4
5
  import { createRuntimeGroupMetadataAccess } from "../../organizations/groupMetadataRuntime.js";
5
6
  import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
@@ -74,7 +75,9 @@ export async function shareRemoteContainerWithGroup(input) {
74
75
  return null;
75
76
  }
76
77
  const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;
77
- const shared = await shareRemoteContainerWithGroupMutation({
78
+ const shareWithGroup = createRuntimeCurrentGroupShare(input.runtime) ??
79
+ shareRemoteContainerWithGroupMutation;
80
+ const shared = await shareWithGroup({
78
81
  reportSecurityIncident: input.runtime.util.reportSecurityIncident,
79
82
  accessLevel: input.accessLevel,
80
83
  apiClient,
@@ -1 +1 @@
1
- {"version":3,"file":"remote.js","sourceRoot":"","sources":["remote.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type {\n ContainerMutationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { isContainerNotFoundFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport {\n moveRemoteContainer as moveRemoteContainerMutation,\n readContainerMutationMetadataDocumentId,\n referencedPrincipalHeadsFromContainerMutationResponse,\n shareRemoteContainer as shareRemoteContainerMutation,\n shareRemoteContainerWithGroup as shareRemoteContainerWithGroupMutation,\n} from \"../../containers\";\nimport { resolveDocumentCreateAuthor } from \"../../documents\";\nimport { createRuntimeGroupMetadataAccess } from \"../../organizations/groupMetadataRuntime\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport {\n type ContainerAlreadyCommitted,\n createRemoteContainerWithMetadataDocument,\n} from \"./createWithMetadata\";\nimport type {\n ContainerWorkflowRuntime,\n CreatedRemoteContainerState,\n RemoteContainer,\n SharedRemoteContainerState,\n} from \"./types\";\n\n/**\n * Resolve the author, api client, executor, and encapsulation secret a remote\n * container mutation needs, logging a skip for the given operation when the\n * writer context is unavailable.\n */\nfunction resolveContainerWriterContext(\n runtime: ContainerWorkflowRuntime,\n operation:\n | \"container create\"\n | \"container group share\"\n | \"container move\"\n | \"container share\",\n) {\n const author = resolveDocumentCreateAuthor(runtime);\n const secretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!author || !secretKey) {\n runtime.util.log(\n `Container contents: skipped ${operation} because the writer context is unavailable.`,\n );\n return null;\n }\n\n return {\n apiClient: runtime.apiClient,\n author,\n execSql: runtime.infra.execSql,\n secretKey,\n };\n}\n\nexport async function createRemoteContainer(input: {\n systemSlot?: ContainerSystemSlot | null | undefined;\n containerId: string;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n return createRemoteContainerWithMetadataDocument(input);\n}\n\nfunction sharedRemoteContainerStateFromMutation(\n previousProjection: ContainerWriterProjectionResponse,\n response: ContainerMutationResponse,\n): SharedRemoteContainerState {\n if (\n response.containerId !== previousProjection.containerId ||\n response.organizationId !== previousProjection.organizationId\n )\n throw new Error(\"Container mutation response projection mismatch\");\n return {\n accessManifestHash: response.manifestHead.manifestHash,\n accessEpoch: response.manifestHead.epoch,\n createdAt: response.createdAt,\n metadataDocumentId: readContainerMutationMetadataDocumentId({ response }),\n referencedPrincipalHeads:\n referencedPrincipalHeadsFromContainerMutationResponse({ response }),\n updatedAt: response.updatedAt,\n // The next read obtains the post-commit proof. A failed read cannot undo\n // acknowledgement of this successful mutation.\n writerProjection: null,\n };\n}\n\nexport async function shareRemoteContainer(input: {\n accessLevel: \"read\" | \"write\" | \"admin\";\n containerId: string;\n previousProjection: ContainerWriterProjectionResponse;\n recipientUserId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedRemoteContainerState | null> {\n const writer = resolveContainerWriterContext(\n input.runtime,\n \"container share\",\n );\n if (!writer) {\n return null;\n }\n const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;\n\n const shared = await shareRemoteContainerMutation({\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n accessLevel: input.accessLevel,\n apiClient,\n author,\n containerId: input.containerId,\n execSql,\n previousProjection: input.previousProjection,\n recipientUserId: input.recipientUserId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n targetSecretKey,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (!shared) {\n return null;\n }\n\n return sharedRemoteContainerStateFromMutation(\n input.previousProjection,\n shared.response,\n );\n}\n\nexport async function shareRemoteContainerWithGroup(input: {\n accessLevel: \"read\" | \"write\" | \"admin\";\n containerId: string;\n expectedGroupName?: string | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n previousProjection: ContainerWriterProjectionResponse;\n recipientGroupId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedRemoteContainerState | null> {\n const writer = resolveContainerWriterContext(\n input.runtime,\n \"container group share\",\n );\n if (!writer) {\n return null;\n }\n const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;\n\n const shared = await shareRemoteContainerWithGroupMutation({\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n accessLevel: input.accessLevel,\n apiClient,\n author,\n containerId: input.containerId,\n execSql,\n expectedGroupName: input.expectedGroupName ?? null,\n readEncryptedName: (bundle) =>\n createRuntimeGroupMetadataAccess(\n input.runtime,\n author.organizationId,\n input.stillCurrent,\n ).readName(bundle),\n knownContainerKeks: input.knownContainerKeks,\n previousProjection: input.previousProjection,\n recipientGroupId: input.recipientGroupId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n signingKeyPair: input.runtime.crypto.signingKeyPair,\n stillCurrent: input.stillCurrent,\n targetSecretKey,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (!shared) {\n return null;\n }\n\n return sharedRemoteContainerStateFromMutation(\n input.previousProjection,\n shared.response,\n );\n}\n\nexport async function moveRemoteContainer(input: {\n containerId: string;\n parentContainerId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<RemoteContainer | null> {\n const writer = resolveContainerWriterContext(input.runtime, \"container move\");\n if (!writer) {\n return null;\n }\n const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;\n\n const moved = await moveRemoteContainerMutation({\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n apiClient,\n author,\n containerId: input.containerId,\n destinationParentContainerId: input.parentContainerId,\n execSql,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (!moved) {\n return null;\n }\n\n return {\n createdAt: moved.response.createdAt,\n effectiveAccessLevel: \"admin\",\n id: moved.response.containerId,\n organizationId: moved.response.organizationId,\n parentId: moved.response.parentId,\n metadataDocumentId: readContainerMutationMetadataDocumentId({\n response: moved.response,\n }),\n metadataAccessEpoch: moved.response.manifestHead.epoch,\n metadataAccessStateHash: moved.response.manifestHead.manifestHash,\n metadataReferencedPrincipals:\n referencedPrincipalHeadsFromContainerMutationResponse({\n response: moved.response,\n }),\n updatedAt: moved.response.updatedAt,\n };\n}\n\nexport async function deleteRemoteContainer(input: {\n containerId: string;\n organizationId: string;\n runtime: ContainerWorkflowRuntime;\n}): Promise<{ deletedAt: string } | null> {\n const deleteResult = await input.runtime.apiClient.deleteContainerResult(\n input.containerId,\n {\n expectedPaymentRequiredOrganizationId: input.organizationId,\n reportErrors: false,\n },\n );\n if (!deleteResult.ok && !isContainerNotFoundFailure(deleteResult)) {\n deleteResult.report();\n return null;\n }\n\n if (!deleteResult.ok) {\n // A 404 proves this immutable id is permanently absent, but it does not\n // carry the server deletion time. A maximal fence prevents an older\n // in-flight listing page from resurrecting it.\n return { deletedAt: \"9999-12-31T23:59:59.999Z\" };\n }\n\n return { deletedAt: deleteResult.data.deletedAt };\n}\n"]}
1
+ {"version":3,"file":"remote.js","sourceRoot":"","sources":["remote.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ContainerSystemSlot } from \"@tearleads/validators/containerSystemSlot\";\nimport type {\n ContainerMutationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { isContainerNotFoundFailure } from \"../../../data/containers/shared/mutationFailures\";\nimport type { ProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification\";\nimport {\n moveRemoteContainer as moveRemoteContainerMutation,\n readContainerMutationMetadataDocumentId,\n referencedPrincipalHeadsFromContainerMutationResponse,\n shareRemoteContainer as shareRemoteContainerMutation,\n shareRemoteContainerWithGroup as shareRemoteContainerWithGroupMutation,\n} from \"../../containers\";\nimport { createRuntimeCurrentGroupShare } from \"../../containers/child/runtimeCurrentGroupShare\";\nimport { resolveDocumentCreateAuthor } from \"../../documents\";\nimport { createRuntimeGroupMetadataAccess } from \"../../organizations/groupMetadataRuntime\";\nimport { createRuntimePrincipalPolicyWarmer } from \"../../principals/runtimePolicyWarmer\";\nimport {\n type ContainerAlreadyCommitted,\n createRemoteContainerWithMetadataDocument,\n} from \"./createWithMetadata\";\nimport type {\n ContainerWorkflowRuntime,\n CreatedRemoteContainerState,\n RemoteContainer,\n SharedRemoteContainerState,\n} from \"./types\";\n\n/**\n * Resolve the author, api client, executor, and encapsulation secret a remote\n * container mutation needs, logging a skip for the given operation when the\n * writer context is unavailable.\n */\nfunction resolveContainerWriterContext(\n runtime: ContainerWorkflowRuntime,\n operation:\n | \"container create\"\n | \"container group share\"\n | \"container move\"\n | \"container share\",\n) {\n const author = resolveDocumentCreateAuthor(runtime);\n const secretKey = runtime.crypto.encapsulationKeyPair?.secretKey;\n if (!author || !secretKey) {\n runtime.util.log(\n `Container contents: skipped ${operation} because the writer context is unavailable.`,\n );\n return null;\n }\n\n return {\n apiClient: runtime.apiClient,\n author,\n execSql: runtime.infra.execSql,\n secretKey,\n };\n}\n\nexport async function createRemoteContainer(input: {\n systemSlot?: ContainerSystemSlot | null | undefined;\n containerId: string;\n parentContainerId: string;\n parentProjection?: ContainerWriterProjectionResponse | undefined;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<CreatedRemoteContainerState | ContainerAlreadyCommitted | null> {\n return createRemoteContainerWithMetadataDocument(input);\n}\n\nfunction sharedRemoteContainerStateFromMutation(\n previousProjection: ContainerWriterProjectionResponse,\n response: ContainerMutationResponse,\n): SharedRemoteContainerState {\n if (\n response.containerId !== previousProjection.containerId ||\n response.organizationId !== previousProjection.organizationId\n )\n throw new Error(\"Container mutation response projection mismatch\");\n return {\n accessManifestHash: response.manifestHead.manifestHash,\n accessEpoch: response.manifestHead.epoch,\n createdAt: response.createdAt,\n metadataDocumentId: readContainerMutationMetadataDocumentId({ response }),\n referencedPrincipalHeads:\n referencedPrincipalHeadsFromContainerMutationResponse({ response }),\n updatedAt: response.updatedAt,\n // The next read obtains the post-commit proof. A failed read cannot undo\n // acknowledgement of this successful mutation.\n writerProjection: null,\n };\n}\n\nexport async function shareRemoteContainer(input: {\n accessLevel: \"read\" | \"write\" | \"admin\";\n containerId: string;\n previousProjection: ContainerWriterProjectionResponse;\n recipientUserId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedRemoteContainerState | null> {\n const writer = resolveContainerWriterContext(\n input.runtime,\n \"container share\",\n );\n if (!writer) {\n return null;\n }\n const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;\n\n const shared = await shareRemoteContainerMutation({\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n accessLevel: input.accessLevel,\n apiClient,\n author,\n containerId: input.containerId,\n execSql,\n previousProjection: input.previousProjection,\n recipientUserId: input.recipientUserId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n stillCurrent: input.stillCurrent,\n targetSecretKey,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (!shared) {\n return null;\n }\n\n return sharedRemoteContainerStateFromMutation(\n input.previousProjection,\n shared.response,\n );\n}\n\nexport async function shareRemoteContainerWithGroup(input: {\n accessLevel: \"read\" | \"write\" | \"admin\";\n containerId: string;\n expectedGroupName?: string | undefined;\n knownContainerKeks?: ReadonlyMap<string, Uint8Array> | undefined;\n previousProjection: ContainerWriterProjectionResponse;\n recipientGroupId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<SharedRemoteContainerState | null> {\n const writer = resolveContainerWriterContext(\n input.runtime,\n \"container group share\",\n );\n if (!writer) {\n return null;\n }\n const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;\n\n const shareWithGroup =\n createRuntimeCurrentGroupShare(input.runtime) ??\n shareRemoteContainerWithGroupMutation;\n const shared = await shareWithGroup({\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n accessLevel: input.accessLevel,\n apiClient,\n author,\n containerId: input.containerId,\n execSql,\n expectedGroupName: input.expectedGroupName ?? null,\n readEncryptedName: (bundle) =>\n createRuntimeGroupMetadataAccess(\n input.runtime,\n author.organizationId,\n input.stillCurrent,\n ).readName(bundle),\n knownContainerKeks: input.knownContainerKeks,\n previousProjection: input.previousProjection,\n recipientGroupId: input.recipientGroupId,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,\n signingKeyPair: input.runtime.crypto.signingKeyPair,\n stillCurrent: input.stillCurrent,\n targetSecretKey,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (!shared) {\n return null;\n }\n\n return sharedRemoteContainerStateFromMutation(\n input.previousProjection,\n shared.response,\n );\n}\n\nexport async function moveRemoteContainer(input: {\n containerId: string;\n parentContainerId: string;\n resolveProjectionUserKey: ProjectionUserKeyResolver;\n runtime: ContainerWorkflowRuntime;\n stillCurrent?: (() => boolean) | undefined;\n}): Promise<RemoteContainer | null> {\n const writer = resolveContainerWriterContext(input.runtime, \"container move\");\n if (!writer) {\n return null;\n }\n const { apiClient, author, execSql, secretKey: targetSecretKey } = writer;\n\n const moved = await moveRemoteContainerMutation({\n reportSecurityIncident: input.runtime.util.reportSecurityIncident,\n apiClient,\n author,\n containerId: input.containerId,\n destinationParentContainerId: input.parentContainerId,\n execSql,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: input.stillCurrent,\n targetSecretKey,\n warmReferencedPrincipalPolicies: createRuntimePrincipalPolicyWarmer(\n input.runtime,\n ),\n });\n if (!moved) {\n return null;\n }\n\n return {\n createdAt: moved.response.createdAt,\n effectiveAccessLevel: \"admin\",\n id: moved.response.containerId,\n organizationId: moved.response.organizationId,\n parentId: moved.response.parentId,\n metadataDocumentId: readContainerMutationMetadataDocumentId({\n response: moved.response,\n }),\n metadataAccessEpoch: moved.response.manifestHead.epoch,\n metadataAccessStateHash: moved.response.manifestHead.manifestHash,\n metadataReferencedPrincipals:\n referencedPrincipalHeadsFromContainerMutationResponse({\n response: moved.response,\n }),\n updatedAt: moved.response.updatedAt,\n };\n}\n\nexport async function deleteRemoteContainer(input: {\n containerId: string;\n organizationId: string;\n runtime: ContainerWorkflowRuntime;\n}): Promise<{ deletedAt: string } | null> {\n const deleteResult = await input.runtime.apiClient.deleteContainerResult(\n input.containerId,\n {\n expectedPaymentRequiredOrganizationId: input.organizationId,\n reportErrors: false,\n },\n );\n if (!deleteResult.ok && !isContainerNotFoundFailure(deleteResult)) {\n deleteResult.report();\n return null;\n }\n\n if (!deleteResult.ok) {\n // A 404 proves this immutable id is permanently absent, but it does not\n // carry the server deletion time. A maximal fence prevents an older\n // in-flight listing page from resurrecting it.\n return { deletedAt: \"9999-12-31T23:59:59.999Z\" };\n }\n\n return { deletedAt: deleteResult.data.deletedAt };\n}\n"]}
@@ -1,10 +1,9 @@
1
1
  import { getTargetContainerContext, readContainerState, } from "../../../data/containers/shared/projection.js";
2
2
  import { unwrapContainerKekPath } from "../../../data/documents/shared/projection.js";
3
3
  import { nullOnProjectionVerificationCancellation, verifyContainerWriterProjection, } from "../../../data/keyingProjectionVerification.js";
4
- import { advanceVerifiedSharePolicies, loadVerifiedGroupSharePrincipalPolicy, } from "../../containers/index.js";
5
- import { createRuntimeGroupMetadataAccess } from "../../organizations/groupMetadataRuntime.js";
6
4
  import { createRuntimePrincipalPolicyWarmer } from "../../principals/runtimePolicyWarmer.js";
7
5
  import { projectionGeneration } from "../projectionGeneration.js";
6
+ import { resolveCurrentGroupKeyEpoch } from "./groupShareEpoch.js";
8
7
  import { loadContainerWriterProjectionForState } from "./projectionCache.js";
9
8
  import { shareRemoteContainer, shareRemoteContainerWithGroup } from "./remote.js";
10
9
  import { persistDuplicateContainerShare, persistSharedContainerState, } from "./sharePersistence.js";
@@ -12,27 +11,6 @@ function readOptionalProjectionString(projection, key) {
12
11
  const value = Reflect.get(projection, key);
13
12
  return typeof value === "string" && value.length > 0 ? value : null;
14
13
  }
15
- async function resolveCurrentGroupKeyEpoch(input) {
16
- if (input.stillCurrent?.() === false)
17
- return null;
18
- const verified = await loadVerifiedGroupSharePrincipalPolicy({
19
- apiClient: input.runtime.apiClient,
20
- execSql: input.runtime.infra.execSql,
21
- expectedGroupName: input.expectedGroupName,
22
- readEncryptedName: (bundle) => createRuntimeGroupMetadataAccess(input.runtime, input.organizationId, input.stillCurrent).readName(bundle),
23
- groupId: input.groupId,
24
- organizationId: input.organizationId,
25
- resolveTrustedUserIdentity: input.runtime.resolveTrustedUserIdentity,
26
- stillCurrent: input.stillCurrent,
27
- });
28
- if (input.stillCurrent?.() === false)
29
- return null;
30
- // Commit the verification immediately: this read stands alone (no enclosing
31
- // mutation advances it later), and an unadvanced checkpoint would let a
32
- // newer same-epoch policy be rolled back on the next fetch.
33
- await advanceVerifiedSharePolicies(input.runtime.infra.execSql, verified, input.stillCurrent);
34
- return input.stillCurrent?.() === false ? null : verified.policy.keyEpoch;
35
- }
36
14
  // A container's KEK is wrapped to a group's encapsulation key at a specific key
37
15
  // epoch, pinned into the manifest as a referenced principal head. When the group
38
16
  // rotates (org-admin add or any removal bumps the epoch and mints a fresh KEM
@@ -40,7 +18,7 @@ async function resolveCurrentGroupKeyEpoch(input) {
40
18
  // no longer unwrap it. A re-share to the same group at the same access level is
41
19
  // therefore NOT redundant when the pinned epoch trails the group's current head,
42
20
  // so it must not be deduped away. The current epoch comes from a network-fresh,
43
- // fully verified policy bundle guarded by any durable local checkpoint.
21
+ // fully verified current policy guarded by durable local checkpoints.
44
22
  function groupGrantIsStale(input) {
45
23
  const pinnedHead = (input.referencedPrincipalHeads ?? []).find((head) => head.principalType === "group" && head.principalId === input.subjectId);
46
24
  if (!pinnedHead) {