@tearleads/client-sdk 0.1.99 → 0.1.100
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/workflows/containers/rematerialization/principalContainerRematerialization.js +4 -6
- package/workflows/containers/rematerialization/principalContainerRematerialization.js.map +1 -1
- package/workflows/containers/rematerialization/principalContainerRematerializationPlanning.js +34 -1
- package/workflows/containers/rematerialization/principalContainerRematerializationPlanning.js.map +1 -1
- package/workflows/organizations/groupPolicy/commitCurrentGroupPolicyMutation.js +22 -16
- package/workflows/organizations/groupPolicy/commitCurrentGroupPolicyMutation.js.map +1 -1
- package/workflows/organizations/groupShare/currentShareGrantMutation.js +4 -3
- package/workflows/organizations/groupShare/currentShareGrantMutation.js.map +1 -1
package/package.json
CHANGED
|
@@ -12,7 +12,7 @@ import { buildMaterializedContainerRevokePlan } from "../child/revoke.js";
|
|
|
12
12
|
import { selectReplacementPrincipalPolicyReferences } from "../child/rotation/replacementPrincipalPolicyReferences.js";
|
|
13
13
|
import { buildMaterializedContainerSharePlan } from "../child/share/shareMaterialization.js";
|
|
14
14
|
import { withPrecedingRematerialization } from "./precedingPrincipalRematerialization.js";
|
|
15
|
-
import { addPlan, carryLevel, staleLevelsAbove, } from "./principalContainerRematerializationPlanning.js";
|
|
15
|
+
import { addPlan, carryLevel, rerootOnAuthoredPaths, staleLevelsAbove, } from "./principalContainerRematerializationPlanning.js";
|
|
16
16
|
import { loadRematerializationTargets, loadServedProjection, seededPrincipalPolicyCache, } from "./principalContainerRematerializationTargets.js";
|
|
17
17
|
function matchingGroupGrant(input) {
|
|
18
18
|
return (input.directGrants.find((grant) => grant.subjectType === "group" && grant.subjectId === input.groupId) ?? null);
|
|
@@ -143,7 +143,7 @@ async function buildPrincipalContainerRematerializationPlan(input) {
|
|
|
143
143
|
*/
|
|
144
144
|
async function planRematerializationTarget(batch, target) {
|
|
145
145
|
const { rematerialization } = batch;
|
|
146
|
-
|
|
146
|
+
const rebased = rebaseOnDeepestAncestor(target.projection, batch.rotatedAbove);
|
|
147
147
|
const stale = rebased
|
|
148
148
|
? staleLevelsAbove(rebased.projection, rebased.ancestor.containerKeks.at(-1)?.containerId ?? "")
|
|
149
149
|
: [];
|
|
@@ -155,10 +155,7 @@ async function planRematerializationTarget(batch, target) {
|
|
|
155
155
|
return;
|
|
156
156
|
}
|
|
157
157
|
// Each level carried above re-roots the target one step deeper.
|
|
158
|
-
|
|
159
|
-
rebased = rebaseOnDeepestAncestor(target.projection, batch.rotatedAbove);
|
|
160
|
-
}
|
|
161
|
-
const previousProjection = rebased?.projection ?? target.projection;
|
|
158
|
+
const previousProjection = await rerootOnAuthoredPaths(batch, target.projection);
|
|
162
159
|
const planned = await buildPrincipalContainerRematerializationPlan({
|
|
163
160
|
grantRow: target.grantRow,
|
|
164
161
|
knownContainerKeks: batch.knownContainerKeks,
|
|
@@ -216,6 +213,7 @@ async function buildPrincipalContainerRematerializationPlans(input, carriedConta
|
|
|
216
213
|
resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,
|
|
217
214
|
}),
|
|
218
215
|
rotatedAbove: [],
|
|
216
|
+
authoredAbove: [],
|
|
219
217
|
};
|
|
220
218
|
for (const target of targets) {
|
|
221
219
|
await planRematerializationTarget(batch, target);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principalContainerRematerialization.js","sourceRoot":"","sources":["principalContainerRematerialization.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerDirectGrant,\n PrincipalContainerGrant,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerMutationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { MAX_ROTATION_CONTAINER_REKEYS } from \"@tearleads/validators/util\";\nimport { rememberVerifiedContainerHeads } from \"../../../data/containers/shared/heldContainerHeads\";\nimport type { AuthoredContainerMutationHead } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport { acknowledgeContainerMutationBatch } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport {\n type PrincipalPolicyCache,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport { createProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification/userKeyResolver\";\nimport { scheduleHeldDescendantRecitations } from \"../child/recite\";\nimport { buildMaterializedContainerRekeyPlan } from \"../child/rekey\";\nimport { rebaseOnDeepestAncestor } from \"../child/rekey/carriedDescendantRekeys\";\nimport {\n containerWriterProjectionFromRotationPlan,\n containerWriterProjectionFromSharePlan,\n isSpeculativeContainerWriterProjection,\n} from \"../child/rekey/rekeyProjection\";\nimport { buildMaterializedContainerRevokePlan } from \"../child/revoke\";\nimport { selectReplacementPrincipalPolicyReferences } from \"../child/rotation/replacementPrincipalPolicyReferences\";\nimport { buildMaterializedContainerSharePlan } from \"../child/share/shareMaterialization\";\nimport { withPrecedingRematerialization } from \"./precedingPrincipalRematerialization\";\nimport {\n addPlan,\n type BatchPlanning,\n carryLevel,\n type PrincipalContainerRematerializationInput,\n type PrincipalRematerializationPredecessor,\n staleLevelsAbove,\n} from \"./principalContainerRematerializationPlanning\";\nimport {\n loadRematerializationTargets,\n loadServedProjection,\n type MaterializedPrincipalContainerMutationPlan,\n type PlannedRematerialization,\n type RematerializationTarget,\n seededPrincipalPolicyCache,\n} from \"./principalContainerRematerializationTargets\";\n\nfunction matchingGroupGrant(input: {\n readonly directGrants: readonly ContainerDirectGrant[];\n readonly groupId: string;\n}): ContainerDirectGrant | null {\n return (\n input.directGrants.find(\n (grant) =>\n grant.subjectType === \"group\" && grant.subjectId === input.groupId,\n ) ?? null\n );\n}\n\nfunction referencedGroupKeyEpoch(input: {\n readonly groupId: string;\n readonly referencedPrincipalHeads: ReturnType<\n typeof readContainerState\n >[\"referencedPrincipalHeads\"];\n}): number | null {\n return (\n input.referencedPrincipalHeads.find(\n (head) =>\n head.principalType === \"group\" && head.principalId === input.groupId,\n )?.keyEpoch ?? null\n );\n}\n\nasync function loadGrantedContainerContext(\n input: PrincipalContainerRematerializationInput,\n grantRow: PrincipalContainerGrant,\n projection: ContainerWriterProjectionResponse,\n principalPolicyCache: PrincipalPolicyCache,\n) {\n // A projection re-rooted on a rotation this batch has yet to commit must\n // not pin anything: its heads are speculative until acknowledged, and a\n // pin past the group's served head would refuse the other served paths.\n await verifyContainerWriterProjection({\n execSql: input.execSql,\n persistVerificationCheckpoints:\n !isSpeculativeContainerWriterProjection(projection),\n principalPolicyCache,\n projection,\n resolveUserKey: createProjectionUserKeyResolver({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n }),\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const state = readContainerState(\n getTargetContainerContext(projection).manifest,\n );\n const grant = matchingGroupGrant({\n directGrants: state.directGrants,\n groupId: input.groupId,\n });\n if (grant && grant.accessLevel !== grantRow.accessLevel) {\n const nextGrant = input.nextPolicy.grants.find(\n (candidate) => candidate.containerId === grantRow.containerId,\n );\n if (!nextGrant || nextGrant.accessLevel !== grantRow.accessLevel) {\n throw new Error(\n `Container ${grantRow.containerId} does not contain the expected group grant`,\n );\n }\n }\n const referencedKeyEpoch = referencedGroupKeyEpoch({\n groupId: input.groupId,\n referencedPrincipalHeads: state.referencedPrincipalHeads,\n });\n if (grant && referencedKeyEpoch === null) {\n throw new Error(\n `Container ${grantRow.containerId} is missing its group reference`,\n );\n }\n return { grant, projection, referencedKeyEpoch };\n}\n\nexport async function buildPrincipalContainerRematerializationBatch(\n input: PrincipalContainerRematerializationInput,\n): Promise<ContainerMutationRequest[]> {\n return (\n await buildPrincipalContainerRematerializationPlans(input)\n ).entries.map((entry) => entry.planned.plan.request);\n}\n\nexport interface PreparedPrincipalContainerRematerializationBatch {\n readonly preceding?: PrincipalRematerializationPredecessor | undefined;\n readonly retiredContainerIds: readonly string[];\n readonly acknowledge: (\n responses: readonly ContainerMutationResponse[],\n stillCurrent?: (() => boolean) | undefined,\n ) => Promise<void>;\n /**\n * Re-sign the batch with the descendant rekeys the server named for its\n * rotations woven in, parent-first, each against the path the batch will\n * leave behind. A named container the batch already rotates is re-planned\n * under what is carried above it, so no container rotates twice. Returns the\n * whole request list, which replaces `requests`; `acknowledge` then expects\n * the responses in that order.\n */\n readonly carry: (\n requiredContainerIds: readonly string[],\n ) => Promise<readonly ContainerMutationRequest[]>;\n readonly plans: readonly MaterializedPrincipalContainerMutationPlan[];\n readonly requests: readonly ContainerMutationRequest[];\n}\n\nfunction authoredMutationHead(\n planned: MaterializedPrincipalContainerMutationPlan,\n): AuthoredContainerMutationHead {\n return planned.plan;\n}\n\nasync function buildPrincipalContainerRematerializationPlan(input: {\n readonly grantRow: PrincipalContainerGrant;\n /** Keys the batch minted above this container; see `BatchPlanning`. */\n readonly knownContainerKeks: ReadonlyMap<string, Uint8Array>;\n /** Holds the policy this batch commits, which rebased paths already cite. */\n readonly principalPolicyCache: PrincipalPolicyCache;\n /** The served projection, re-rooted on any rotation planned above it. */\n readonly projection: ContainerWriterProjectionResponse;\n readonly rematerialization: PrincipalContainerRematerializationInput;\n readonly resolveProjectionUserKey: ReturnType<\n typeof createProjectionUserKeyResolver\n >;\n}): Promise<MaterializedPrincipalContainerMutationPlan> {\n const { grantRow } = input;\n const rematerialization = {\n ...input.rematerialization,\n nextPolicy: await selectReplacementPrincipalPolicyReferences({\n policy: input.rematerialization.nextPolicy,\n projection: input.projection,\n principalPolicyCache: input.principalPolicyCache,\n resolveAuthoredPolicyReferences:\n input.rematerialization.resolveAuthoredPolicyReferences,\n }),\n };\n const { grant, projection, referencedKeyEpoch } =\n await loadGrantedContainerContext(\n rematerialization,\n grantRow,\n input.projection,\n input.principalPolicyCache,\n );\n const nextGrant = rematerialization.nextPolicy.grants.find(\n (candidate) => candidate.containerId === grantRow.containerId,\n );\n const author = {\n ...rematerialization.author,\n organizationId: projection.organizationId,\n };\n const sharedInput = {\n author,\n execSql: rematerialization.execSql,\n knownContainerKeks: input.knownContainerKeks,\n // Planning against a path this batch has yet to commit pins nothing; the\n // acknowledgement advances every head at once. The rekey planner applies\n // this rule itself; revoke and grant planning take it from here.\n persistVerificationCheckpoints:\n !isSpeculativeContainerWriterProjection(projection),\n previousProjection: projection,\n principalPolicyCache: input.principalPolicyCache,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: rematerialization.stillCurrent,\n targetSecretKey: rematerialization.targetSecretKey,\n warmReferencedPrincipalPolicies:\n rematerialization.warmReferencedPrincipalPolicies,\n };\n if (grantRow.containerId === rematerialization.revokedContainerId) {\n if (!grant) {\n throw new Error(\n `Container ${grantRow.containerId} does not contain the revoked group grant`,\n );\n }\n return buildMaterializedContainerRevokePlan({\n ...sharedInput,\n replacementPrincipalPolicy: rematerialization.nextPolicy,\n revokedSubject: {\n subjectId: rematerialization.groupId,\n subjectType: \"group\",\n },\n });\n }\n if (!grant || grant.accessLevel !== nextGrant?.accessLevel) {\n if (!nextGrant) {\n throw new Error(\n `Container ${grantRow.containerId} is absent from the next group grant set`,\n );\n }\n return buildMaterializedContainerSharePlan({\n ...sharedInput,\n accessLevel: nextGrant.accessLevel,\n recipient: {\n principalPolicy: rematerialization.nextPolicy,\n subjectId: rematerialization.groupId,\n subjectType: \"group\",\n },\n });\n }\n if (referencedKeyEpoch === rematerialization.nextPolicy.keyEpoch) {\n return buildMaterializedContainerSharePlan({\n ...sharedInput,\n accessLevel: grant.accessLevel,\n recipient: {\n principalPolicy: rematerialization.nextPolicy,\n subjectId: rematerialization.groupId,\n subjectType: \"group\",\n },\n });\n }\n return buildMaterializedContainerRekeyPlan({\n ...sharedInput,\n replacementPrincipalPolicy: rematerialization.nextPolicy,\n });\n}\n\n/**\n * Plan one target against the paths already planned above it. A grant's\n * rematerialization extends the served head; a rotation's, and every carried\n * rekey, extends the epoch the batch mints above it.\n */\nasync function planRematerializationTarget(\n batch: BatchPlanning,\n target: RematerializationTarget,\n): Promise<void> {\n const { rematerialization } = batch;\n let rebased = rebaseOnDeepestAncestor(target.projection, batch.rotatedAbove);\n const stale = rebased\n ? staleLevelsAbove(\n rebased.projection,\n rebased.ancestor.containerKeks.at(-1)?.containerId ?? \"\",\n )\n : [];\n for (const containerId of stale) {\n await carryLevel(\n batch,\n await loadServedProjection(rematerialization.apiClient, containerId),\n );\n }\n if (!target.grantRow) {\n await carryLevel(batch, target.projection);\n return;\n }\n // Each level carried above re-roots the target one step deeper.\n if (stale.length > 0) {\n rebased = rebaseOnDeepestAncestor(target.projection, batch.rotatedAbove);\n }\n const previousProjection = rebased?.projection ?? target.projection;\n const planned = await buildPrincipalContainerRematerializationPlan({\n grantRow: target.grantRow,\n knownContainerKeks: batch.knownContainerKeks,\n principalPolicyCache: batch.principalPolicyCache,\n projection: previousProjection,\n rematerialization,\n resolveProjectionUserKey: batch.resolveProjectionUserKey,\n });\n const nextProjection =\n \"keyring\" in planned.plan\n ? await containerWriterProjectionFromRotationPlan({\n plan: planned.plan,\n previousProjection,\n })\n : await containerWriterProjectionFromSharePlan({\n plan: planned.plan,\n previousProjection,\n });\n addPlan(batch, {\n carried: false,\n planned,\n rotated: \"keyring\" in planned.plan ? nextProjection : null,\n nextProjection,\n });\n}\n\n/**\n * Sign the batch parent-first. `carriedContainerIds` are the descendant rekeys\n * a refused attempt was told to carry; woven in by depth, each sits under the\n * rotation it rides, and a named container the batch rematerializes anyway is\n * re-planned there rather than rotated twice.\n */\nasync function buildPrincipalContainerRematerializationPlans(\n input: PrincipalContainerRematerializationInput,\n carriedContainerIds: readonly string[] = [],\n): Promise<{\n entries: PlannedRematerialization[];\n retiredContainerIds: readonly string[];\n preceding: PrincipalRematerializationPredecessor;\n}> {\n input = withPrecedingRematerialization(input);\n if (\n input.revokedContainerId &&\n !input.grants.some(\n (grant) => grant.containerId === input.revokedContainerId,\n )\n ) {\n throw new Error(\"Revoked container is not granted to the group\");\n }\n const { targets, retiredContainerIds } = await loadRematerializationTargets({\n apiClient: input.apiClient,\n carriedContainerIds,\n grants: input.grants,\n });\n const batch: BatchPlanning = {\n knownContainerKeks: new Map(input.preceding?.knownContainerKeks),\n plans: [],\n // A rotation planned above cites the group at the head this batch commits,\n // which no store holds yet; the cache is what lets a rebased path verify.\n principalPolicyCache: new Map([\n ...(input.preceding?.policies ?? []).flatMap((policy) => [\n ...seededPrincipalPolicyCache(policy),\n ]),\n ...seededPrincipalPolicyCache(input.nextPolicy),\n ]),\n rematerialization: input,\n resolveProjectionUserKey: createProjectionUserKeyResolver({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n }),\n rotatedAbove: [],\n };\n for (const target of targets) {\n await planRematerializationTarget(batch, target);\n }\n return {\n entries: batch.plans,\n retiredContainerIds,\n preceding: {\n policies: [...(input.preceding?.policies ?? []), input.nextPolicy],\n projections: [\n ...(input.preceding?.projections ?? []),\n ...batch.plans.flatMap((entry) =>\n entry.nextProjection ? [entry.nextProjection] : [],\n ),\n ],\n knownContainerKeks: batch.knownContainerKeks,\n },\n };\n}\n\n/**\n * The server names a level it found pinned to a retired epoch. A batch answers\n * with a rotation of it: a carried rekey, or its own rematerialization when\n * that is a rekey or revoke. A rematerialized grant rotates nothing, so a\n * batch that both grants a container and must re-key it cannot be signed;\n * no policy change the SDK builds combines the two.\n */\nfunction assertNamedContainersRotated(\n plans: readonly PlannedRematerialization[],\n requiredContainerIds: readonly string[],\n): void {\n const rotatedIds = new Set(\n plans.flatMap((entry) =>\n entry.rotated ? [entry.planned.plan.containerId] : [],\n ),\n );\n const unrotated = requiredContainerIds\n .slice(0, MAX_ROTATION_CONTAINER_REKEYS)\n .find((containerId) => !rotatedIds.has(containerId));\n if (unrotated !== undefined) {\n throw new Error(\n `Container ${unrotated} needs a rekey this policy change only grants`,\n );\n }\n}\n\nexport async function preparePrincipalContainerRematerializationBatch(\n input: PrincipalContainerRematerializationInput,\n): Promise<PreparedPrincipalContainerRematerializationBatch> {\n let { entries, retiredContainerIds, preceding } =\n await buildPrincipalContainerRematerializationPlans(input);\n const requests = () => entries.map((entry) => entry.planned.plan.request);\n return {\n get preceding() {\n return preceding;\n },\n get retiredContainerIds() {\n return retiredContainerIds;\n },\n get plans() {\n return entries.map((entry) => entry.planned);\n },\n get requests() {\n return requests();\n },\n carry: async (requiredContainerIds) => {\n // The refused attempt rolled back whole, so every served head still\n // stands; the batch is signed again from them with the named levels in.\n const replanned = await buildPrincipalContainerRematerializationPlans(\n input,\n requiredContainerIds,\n );\n assertNamedContainersRotated(replanned.entries, requiredContainerIds);\n entries = replanned.entries;\n retiredContainerIds = replanned.retiredContainerIds;\n preceding = replanned.preceding;\n return requests();\n },\n acknowledge: async (responses, stillCurrent) => {\n const isCurrent = () =>\n input.stillCurrent?.() !== false && stillCurrent?.() !== false;\n const heads = entries.map((entry) => authoredMutationHead(entry.planned));\n const acknowledged = await acknowledgeContainerMutationBatch({\n execSql: input.execSql,\n plans: heads,\n responses,\n stillCurrent: isCurrent,\n });\n if (!acknowledged || !isCurrent()) return;\n const plansByOrganization = new Map<\n string,\n AuthoredContainerMutationHead[]\n >();\n for (const head of heads) {\n const organizationId = head.state.organizationId;\n const group = plansByOrganization.get(organizationId) ?? [];\n group.push(head);\n plansByOrganization.set(organizationId, group);\n }\n for (const [organizationId, organizationPlans] of plansByOrganization) {\n try {\n rememberVerifiedContainerHeads({\n organizationId,\n execSql: input.execSql,\n heads: [],\n policies: [input.nextPolicy],\n });\n } catch {\n // Cache failure must not invalidate the durably acknowledged batch.\n continue;\n }\n scheduleHeldDescendantRecitations({\n apiClient: input.apiClient,\n author: { ...input.author, organizationId },\n execSql: input.execSql,\n plans: organizationPlans,\n stillCurrent: input.recitationStillCurrent ?? isCurrent,\n reportSecurityIncident: input.reportSecurityIncident,\n });\n }\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"principalContainerRematerialization.js","sourceRoot":"","sources":["principalContainerRematerialization.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n ContainerDirectGrant,\n PrincipalContainerGrant,\n} from \"@tearleads/crypto\";\nimport type { ContainerMutationRequest } from \"@tearleads/validators/request\";\nimport type {\n ContainerMutationResponse,\n ContainerWriterProjectionResponse,\n} from \"@tearleads/validators/response\";\nimport { MAX_ROTATION_CONTAINER_REKEYS } from \"@tearleads/validators/util\";\nimport { rememberVerifiedContainerHeads } from \"../../../data/containers/shared/heldContainerHeads\";\nimport type { AuthoredContainerMutationHead } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport { acknowledgeContainerMutationBatch } from \"../../../data/containers/shared/mutationAcknowledgement\";\nimport {\n getTargetContainerContext,\n readContainerState,\n} from \"../../../data/containers/shared/projection\";\nimport {\n type PrincipalPolicyCache,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport { createProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification/userKeyResolver\";\nimport { scheduleHeldDescendantRecitations } from \"../child/recite\";\nimport { buildMaterializedContainerRekeyPlan } from \"../child/rekey\";\nimport { rebaseOnDeepestAncestor } from \"../child/rekey/carriedDescendantRekeys\";\nimport {\n containerWriterProjectionFromRotationPlan,\n containerWriterProjectionFromSharePlan,\n isSpeculativeContainerWriterProjection,\n} from \"../child/rekey/rekeyProjection\";\nimport { buildMaterializedContainerRevokePlan } from \"../child/revoke\";\nimport { selectReplacementPrincipalPolicyReferences } from \"../child/rotation/replacementPrincipalPolicyReferences\";\nimport { buildMaterializedContainerSharePlan } from \"../child/share/shareMaterialization\";\nimport { withPrecedingRematerialization } from \"./precedingPrincipalRematerialization\";\nimport {\n addPlan,\n type BatchPlanning,\n carryLevel,\n type PrincipalContainerRematerializationInput,\n type PrincipalRematerializationPredecessor,\n rerootOnAuthoredPaths,\n staleLevelsAbove,\n} from \"./principalContainerRematerializationPlanning\";\nimport {\n loadRematerializationTargets,\n loadServedProjection,\n type MaterializedPrincipalContainerMutationPlan,\n type PlannedRematerialization,\n type RematerializationTarget,\n seededPrincipalPolicyCache,\n} from \"./principalContainerRematerializationTargets\";\n\nfunction matchingGroupGrant(input: {\n readonly directGrants: readonly ContainerDirectGrant[];\n readonly groupId: string;\n}): ContainerDirectGrant | null {\n return (\n input.directGrants.find(\n (grant) =>\n grant.subjectType === \"group\" && grant.subjectId === input.groupId,\n ) ?? null\n );\n}\n\nfunction referencedGroupKeyEpoch(input: {\n readonly groupId: string;\n readonly referencedPrincipalHeads: ReturnType<\n typeof readContainerState\n >[\"referencedPrincipalHeads\"];\n}): number | null {\n return (\n input.referencedPrincipalHeads.find(\n (head) =>\n head.principalType === \"group\" && head.principalId === input.groupId,\n )?.keyEpoch ?? null\n );\n}\n\nasync function loadGrantedContainerContext(\n input: PrincipalContainerRematerializationInput,\n grantRow: PrincipalContainerGrant,\n projection: ContainerWriterProjectionResponse,\n principalPolicyCache: PrincipalPolicyCache,\n) {\n // A projection re-rooted on a rotation this batch has yet to commit must\n // not pin anything: its heads are speculative until acknowledged, and a\n // pin past the group's served head would refuse the other served paths.\n await verifyContainerWriterProjection({\n execSql: input.execSql,\n persistVerificationCheckpoints:\n !isSpeculativeContainerWriterProjection(projection),\n principalPolicyCache,\n projection,\n resolveUserKey: createProjectionUserKeyResolver({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n }),\n stillCurrent: input.stillCurrent,\n warmReferencedPrincipalPolicies: input.warmReferencedPrincipalPolicies,\n });\n const state = readContainerState(\n getTargetContainerContext(projection).manifest,\n );\n const grant = matchingGroupGrant({\n directGrants: state.directGrants,\n groupId: input.groupId,\n });\n if (grant && grant.accessLevel !== grantRow.accessLevel) {\n const nextGrant = input.nextPolicy.grants.find(\n (candidate) => candidate.containerId === grantRow.containerId,\n );\n if (!nextGrant || nextGrant.accessLevel !== grantRow.accessLevel) {\n throw new Error(\n `Container ${grantRow.containerId} does not contain the expected group grant`,\n );\n }\n }\n const referencedKeyEpoch = referencedGroupKeyEpoch({\n groupId: input.groupId,\n referencedPrincipalHeads: state.referencedPrincipalHeads,\n });\n if (grant && referencedKeyEpoch === null) {\n throw new Error(\n `Container ${grantRow.containerId} is missing its group reference`,\n );\n }\n return { grant, projection, referencedKeyEpoch };\n}\n\nexport async function buildPrincipalContainerRematerializationBatch(\n input: PrincipalContainerRematerializationInput,\n): Promise<ContainerMutationRequest[]> {\n return (\n await buildPrincipalContainerRematerializationPlans(input)\n ).entries.map((entry) => entry.planned.plan.request);\n}\n\nexport interface PreparedPrincipalContainerRematerializationBatch {\n readonly preceding?: PrincipalRematerializationPredecessor | undefined;\n readonly retiredContainerIds: readonly string[];\n readonly acknowledge: (\n responses: readonly ContainerMutationResponse[],\n stillCurrent?: (() => boolean) | undefined,\n ) => Promise<void>;\n /**\n * Re-sign the batch with the descendant rekeys the server named for its\n * rotations woven in, parent-first, each against the path the batch will\n * leave behind. A named container the batch already rotates is re-planned\n * under what is carried above it, so no container rotates twice. Returns the\n * whole request list, which replaces `requests`; `acknowledge` then expects\n * the responses in that order.\n */\n readonly carry: (\n requiredContainerIds: readonly string[],\n ) => Promise<readonly ContainerMutationRequest[]>;\n readonly plans: readonly MaterializedPrincipalContainerMutationPlan[];\n readonly requests: readonly ContainerMutationRequest[];\n}\n\nfunction authoredMutationHead(\n planned: MaterializedPrincipalContainerMutationPlan,\n): AuthoredContainerMutationHead {\n return planned.plan;\n}\n\nasync function buildPrincipalContainerRematerializationPlan(input: {\n readonly grantRow: PrincipalContainerGrant;\n /** Keys the batch minted above this container; see `BatchPlanning`. */\n readonly knownContainerKeks: ReadonlyMap<string, Uint8Array>;\n /** Holds the policy this batch commits, which rebased paths already cite. */\n readonly principalPolicyCache: PrincipalPolicyCache;\n /** The served projection, re-rooted on any rotation planned above it. */\n readonly projection: ContainerWriterProjectionResponse;\n readonly rematerialization: PrincipalContainerRematerializationInput;\n readonly resolveProjectionUserKey: ReturnType<\n typeof createProjectionUserKeyResolver\n >;\n}): Promise<MaterializedPrincipalContainerMutationPlan> {\n const { grantRow } = input;\n const rematerialization = {\n ...input.rematerialization,\n nextPolicy: await selectReplacementPrincipalPolicyReferences({\n policy: input.rematerialization.nextPolicy,\n projection: input.projection,\n principalPolicyCache: input.principalPolicyCache,\n resolveAuthoredPolicyReferences:\n input.rematerialization.resolveAuthoredPolicyReferences,\n }),\n };\n const { grant, projection, referencedKeyEpoch } =\n await loadGrantedContainerContext(\n rematerialization,\n grantRow,\n input.projection,\n input.principalPolicyCache,\n );\n const nextGrant = rematerialization.nextPolicy.grants.find(\n (candidate) => candidate.containerId === grantRow.containerId,\n );\n const author = {\n ...rematerialization.author,\n organizationId: projection.organizationId,\n };\n const sharedInput = {\n author,\n execSql: rematerialization.execSql,\n knownContainerKeks: input.knownContainerKeks,\n // Planning against a path this batch has yet to commit pins nothing; the\n // acknowledgement advances every head at once. The rekey planner applies\n // this rule itself; revoke and grant planning take it from here.\n persistVerificationCheckpoints:\n !isSpeculativeContainerWriterProjection(projection),\n previousProjection: projection,\n principalPolicyCache: input.principalPolicyCache,\n resolveProjectionUserKey: input.resolveProjectionUserKey,\n stillCurrent: rematerialization.stillCurrent,\n targetSecretKey: rematerialization.targetSecretKey,\n warmReferencedPrincipalPolicies:\n rematerialization.warmReferencedPrincipalPolicies,\n };\n if (grantRow.containerId === rematerialization.revokedContainerId) {\n if (!grant) {\n throw new Error(\n `Container ${grantRow.containerId} does not contain the revoked group grant`,\n );\n }\n return buildMaterializedContainerRevokePlan({\n ...sharedInput,\n replacementPrincipalPolicy: rematerialization.nextPolicy,\n revokedSubject: {\n subjectId: rematerialization.groupId,\n subjectType: \"group\",\n },\n });\n }\n if (!grant || grant.accessLevel !== nextGrant?.accessLevel) {\n if (!nextGrant) {\n throw new Error(\n `Container ${grantRow.containerId} is absent from the next group grant set`,\n );\n }\n return buildMaterializedContainerSharePlan({\n ...sharedInput,\n accessLevel: nextGrant.accessLevel,\n recipient: {\n principalPolicy: rematerialization.nextPolicy,\n subjectId: rematerialization.groupId,\n subjectType: \"group\",\n },\n });\n }\n if (referencedKeyEpoch === rematerialization.nextPolicy.keyEpoch) {\n return buildMaterializedContainerSharePlan({\n ...sharedInput,\n accessLevel: grant.accessLevel,\n recipient: {\n principalPolicy: rematerialization.nextPolicy,\n subjectId: rematerialization.groupId,\n subjectType: \"group\",\n },\n });\n }\n return buildMaterializedContainerRekeyPlan({\n ...sharedInput,\n replacementPrincipalPolicy: rematerialization.nextPolicy,\n });\n}\n\n/**\n * Plan one target against the paths already planned above it. A grant's\n * rematerialization extends the served head; a rotation's, and every carried\n * rekey, extends the epoch the batch mints above it.\n */\nasync function planRematerializationTarget(\n batch: BatchPlanning,\n target: RematerializationTarget,\n): Promise<void> {\n const { rematerialization } = batch;\n const rebased = rebaseOnDeepestAncestor(\n target.projection,\n batch.rotatedAbove,\n );\n const stale = rebased\n ? staleLevelsAbove(\n rebased.projection,\n rebased.ancestor.containerKeks.at(-1)?.containerId ?? \"\",\n )\n : [];\n for (const containerId of stale) {\n await carryLevel(\n batch,\n await loadServedProjection(rematerialization.apiClient, containerId),\n );\n }\n if (!target.grantRow) {\n await carryLevel(batch, target.projection);\n return;\n }\n // Each level carried above re-roots the target one step deeper.\n const previousProjection = await rerootOnAuthoredPaths(\n batch,\n target.projection,\n );\n const planned = await buildPrincipalContainerRematerializationPlan({\n grantRow: target.grantRow,\n knownContainerKeks: batch.knownContainerKeks,\n principalPolicyCache: batch.principalPolicyCache,\n projection: previousProjection,\n rematerialization,\n resolveProjectionUserKey: batch.resolveProjectionUserKey,\n });\n const nextProjection =\n \"keyring\" in planned.plan\n ? await containerWriterProjectionFromRotationPlan({\n plan: planned.plan,\n previousProjection,\n })\n : await containerWriterProjectionFromSharePlan({\n plan: planned.plan,\n previousProjection,\n });\n addPlan(batch, {\n carried: false,\n planned,\n rotated: \"keyring\" in planned.plan ? nextProjection : null,\n nextProjection,\n });\n}\n\n/**\n * Sign the batch parent-first. `carriedContainerIds` are the descendant rekeys\n * a refused attempt was told to carry; woven in by depth, each sits under the\n * rotation it rides, and a named container the batch rematerializes anyway is\n * re-planned there rather than rotated twice.\n */\nasync function buildPrincipalContainerRematerializationPlans(\n input: PrincipalContainerRematerializationInput,\n carriedContainerIds: readonly string[] = [],\n): Promise<{\n entries: PlannedRematerialization[];\n retiredContainerIds: readonly string[];\n preceding: PrincipalRematerializationPredecessor;\n}> {\n input = withPrecedingRematerialization(input);\n if (\n input.revokedContainerId &&\n !input.grants.some(\n (grant) => grant.containerId === input.revokedContainerId,\n )\n ) {\n throw new Error(\"Revoked container is not granted to the group\");\n }\n const { targets, retiredContainerIds } = await loadRematerializationTargets({\n apiClient: input.apiClient,\n carriedContainerIds,\n grants: input.grants,\n });\n const batch: BatchPlanning = {\n knownContainerKeks: new Map(input.preceding?.knownContainerKeks),\n plans: [],\n // A rotation planned above cites the group at the head this batch commits,\n // which no store holds yet; the cache is what lets a rebased path verify.\n principalPolicyCache: new Map([\n ...(input.preceding?.policies ?? []).flatMap((policy) => [\n ...seededPrincipalPolicyCache(policy),\n ]),\n ...seededPrincipalPolicyCache(input.nextPolicy),\n ]),\n rematerialization: input,\n resolveProjectionUserKey: createProjectionUserKeyResolver({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n }),\n rotatedAbove: [],\n authoredAbove: [],\n };\n for (const target of targets) {\n await planRematerializationTarget(batch, target);\n }\n return {\n entries: batch.plans,\n retiredContainerIds,\n preceding: {\n policies: [...(input.preceding?.policies ?? []), input.nextPolicy],\n projections: [\n ...(input.preceding?.projections ?? []),\n ...batch.plans.flatMap((entry) =>\n entry.nextProjection ? [entry.nextProjection] : [],\n ),\n ],\n knownContainerKeks: batch.knownContainerKeks,\n },\n };\n}\n\n/**\n * The server names a level it found pinned to a retired epoch. A batch answers\n * with a rotation of it: a carried rekey, or its own rematerialization when\n * that is a rekey or revoke. A rematerialized grant rotates nothing, so a\n * batch that both grants a container and must re-key it cannot be signed;\n * no policy change the SDK builds combines the two.\n */\nfunction assertNamedContainersRotated(\n plans: readonly PlannedRematerialization[],\n requiredContainerIds: readonly string[],\n): void {\n const rotatedIds = new Set(\n plans.flatMap((entry) =>\n entry.rotated ? [entry.planned.plan.containerId] : [],\n ),\n );\n const unrotated = requiredContainerIds\n .slice(0, MAX_ROTATION_CONTAINER_REKEYS)\n .find((containerId) => !rotatedIds.has(containerId));\n if (unrotated !== undefined) {\n throw new Error(\n `Container ${unrotated} needs a rekey this policy change only grants`,\n );\n }\n}\n\nexport async function preparePrincipalContainerRematerializationBatch(\n input: PrincipalContainerRematerializationInput,\n): Promise<PreparedPrincipalContainerRematerializationBatch> {\n let { entries, retiredContainerIds, preceding } =\n await buildPrincipalContainerRematerializationPlans(input);\n const requests = () => entries.map((entry) => entry.planned.plan.request);\n return {\n get preceding() {\n return preceding;\n },\n get retiredContainerIds() {\n return retiredContainerIds;\n },\n get plans() {\n return entries.map((entry) => entry.planned);\n },\n get requests() {\n return requests();\n },\n carry: async (requiredContainerIds) => {\n // The refused attempt rolled back whole, so every served head still\n // stands; the batch is signed again from them with the named levels in.\n const replanned = await buildPrincipalContainerRematerializationPlans(\n input,\n requiredContainerIds,\n );\n assertNamedContainersRotated(replanned.entries, requiredContainerIds);\n entries = replanned.entries;\n retiredContainerIds = replanned.retiredContainerIds;\n preceding = replanned.preceding;\n return requests();\n },\n acknowledge: async (responses, stillCurrent) => {\n const isCurrent = () =>\n input.stillCurrent?.() !== false && stillCurrent?.() !== false;\n const heads = entries.map((entry) => authoredMutationHead(entry.planned));\n const acknowledged = await acknowledgeContainerMutationBatch({\n execSql: input.execSql,\n plans: heads,\n responses,\n stillCurrent: isCurrent,\n });\n if (!acknowledged || !isCurrent()) return;\n const plansByOrganization = new Map<\n string,\n AuthoredContainerMutationHead[]\n >();\n for (const head of heads) {\n const organizationId = head.state.organizationId;\n const group = plansByOrganization.get(organizationId) ?? [];\n group.push(head);\n plansByOrganization.set(organizationId, group);\n }\n for (const [organizationId, organizationPlans] of plansByOrganization) {\n try {\n rememberVerifiedContainerHeads({\n organizationId,\n execSql: input.execSql,\n heads: [],\n policies: [input.nextPolicy],\n });\n } catch {\n // Cache failure must not invalidate the durably acknowledged batch.\n continue;\n }\n scheduleHeldDescendantRecitations({\n apiClient: input.apiClient,\n author: { ...input.author, organizationId },\n execSql: input.execSql,\n plans: organizationPlans,\n stillCurrent: input.recitationStillCurrent ?? isCurrent,\n reportSecurityIncident: input.reportSecurityIncident,\n });\n }\n },\n };\n}\n"]}
|
package/workflows/containers/rematerialization/principalContainerRematerializationPlanning.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { MAX_ROTATION_CONTAINER_REKEYS } from "../../../internal/validators/util/index.js";
|
|
2
|
-
import {
|
|
2
|
+
import { verifyContainerWriterProjection, } from "../../../data/keyingProjectionVerification/index.js";
|
|
3
|
+
import { planCarriedDescendantRekey, rebaseOnDeepestAncestor, } from "../child/rekey/carriedDescendantRekeys.js";
|
|
4
|
+
import { isSpeculativeContainerWriterProjection } from "../child/rekey/rekeyProjection.js";
|
|
3
5
|
/** How many rekeys the batch carries beyond its rematerializations. */
|
|
4
6
|
function carriedCount(batch) {
|
|
5
7
|
return batch.plans.filter((entry) => entry.carried).length;
|
|
@@ -42,8 +44,39 @@ export async function carryLevel(batch, served) {
|
|
|
42
44
|
nextProjection: planned.writerProjection,
|
|
43
45
|
});
|
|
44
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Re-root a granted target on the deepest path the batch authored above it, a
|
|
49
|
+
* grant's included: the server applies the batch in order, so the target
|
|
50
|
+
* cites every head an earlier entry advances. Its served head is pinned first,
|
|
51
|
+
* as a carried rekey's is. The batch is acknowledged against the latest
|
|
52
|
+
* durable pin, and a re-rooted path pins nothing, so a device that never
|
|
53
|
+
* pinned this container would refuse its own batch once the server took it.
|
|
54
|
+
* Only what the API served is pinned: in a compound transaction the target
|
|
55
|
+
* may already sit on the preceding batch's heads, which a refused commit
|
|
56
|
+
* never makes real.
|
|
57
|
+
*/
|
|
58
|
+
export async function rerootOnAuthoredPaths(batch, served) {
|
|
59
|
+
const rebased = rebaseOnDeepestAncestor(served, batch.authoredAbove);
|
|
60
|
+
if (!rebased)
|
|
61
|
+
return served;
|
|
62
|
+
if (isSpeculativeContainerWriterProjection(served)) {
|
|
63
|
+
return rebased.projection;
|
|
64
|
+
}
|
|
65
|
+
const { rematerialization } = batch;
|
|
66
|
+
await verifyContainerWriterProjection({
|
|
67
|
+
execSql: rematerialization.execSql,
|
|
68
|
+
principalPolicyCache: batch.principalPolicyCache,
|
|
69
|
+
projection: served,
|
|
70
|
+
resolveUserKey: batch.resolveProjectionUserKey,
|
|
71
|
+
stillCurrent: rematerialization.stillCurrent,
|
|
72
|
+
warmReferencedPrincipalPolicies: rematerialization.warmReferencedPrincipalPolicies,
|
|
73
|
+
});
|
|
74
|
+
return rebased.projection;
|
|
75
|
+
}
|
|
45
76
|
export function addPlan(batch, entry) {
|
|
46
77
|
batch.plans.push(entry);
|
|
78
|
+
if (entry.nextProjection)
|
|
79
|
+
batch.authoredAbove.push(entry.nextProjection);
|
|
47
80
|
if (!entry.rotated)
|
|
48
81
|
return;
|
|
49
82
|
batch.rotatedAbove.push(entry.rotated);
|
package/workflows/containers/rematerialization/principalContainerRematerializationPlanning.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"principalContainerRematerializationPlanning.js","sourceRoot":"","sources":["principalContainerRematerializationPlanning.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,6BAA6B,EAAE,MAAM,4BAA4B,CAAC;AAc3E,OAAO,EACL,0BAA0B,GAE3B,MAAM,wCAAwC,CAAC;AA2DhD,uEAAuE;AACvE,SAAS,YAAY,CAAC,KAAoB;IACxC,OAAO,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC;AAC7D,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,KAAoB,EACpB,MAAyC;IAEzC,MAAM,EAAE,iBAAiB,EAAE,GAAG,KAAK,CAAC;IACpC,IAAI,YAAY,CAAC,KAAK,CAAC,IAAI,6BAA6B,EAAE,CAAC;QACzD,MAAM,IAAI,KAAK,CACb,uCAAuC,6BAA6B,oBAAoB,CACzF,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,0BAA0B,CAAC;QAC/C,SAAS,EAAE,iBAAiB,CAAC,SAAS;QACtC,MAAM,EAAE,iBAAiB,CAAC,MAAM;QAChC,OAAO,EAAE,iBAAiB,CAAC,OAAO;QAClC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,oBAAoB,EAAE,KAAK,CAAC,oBAAoB;QAChD,8DAA8D;QAC9D,sDAAsD;QACtD,0BAA0B,EAAE,iBAAiB,CAAC,UAAU;QACxD,+BAA+B,EAC7B,iBAAiB,CAAC,+BAA+B;QACnD,wBAAwB,EAAE,KAAK,CAAC,wBAAwB;QACxD,OAAO,EAAE,KAAK,CAAC,YAAY;QAC3B,MAAM;QACN,YAAY,EAAE,iBAAiB,CAAC,YAAY;QAC5C,eAAe,EAAE,iBAAiB,CAAC,eAAe;QAClD,+BAA+B,EAC7B,iBAAiB,CAAC,+BAA+B;KACpD,CAAC,CAAC;IACH,OAAO,CAAC,KAAK,EAAE;QACb,OAAO,EAAE,IAAI;QACb,OAAO;QACP,OAAO,EAAE,OAAO,CAAC,gBAAgB;QACjC,cAAc,EAAE,OAAO,CAAC,gBAAgB;KACzC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,OAAO,CACrB,KAAoB,EACpB,KAA+B;IAE/B,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,IAAI,CAAC,KAAK,CAAC,OAAO;QAAE,OAAO;IAC3B,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,mBAAmB,CAAC;IACvE,IAAI,MAAM;QAAE,KAAK,CAAC,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AAC/E,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAC9B,UAA6C,EAC7C,iBAAyB;IAEzB,MAAM,IAAI,GAAG,UAAU,CAAC,aAAa,CAAC;IACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAC7B,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,KAAK,iBAAiB,CAC/C,CAAC;IACF,IAAI,QAAQ,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAClC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CACb,KAAK,GAAG,CAAC;QACT,GAAG,CAAC,yBAAyB,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,EAAE,mBAAmB,CAC5E,CAAC;IACF,OAAO,UAAU,GAAG,CAAC;QACnB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;AAC9D,CAAC","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { PrincipalContainerGrant } from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { MAX_ROTATION_CONTAINER_REKEYS } from \"@tearleads/validators/util\";\nimport type { ContainerReciteApi } from \"../../../data/containers/shared/reciteApi\";\nimport type { ContainerMutationAuthor } from \"../../../data/containers/shared/types\";\nimport type {\n PrincipalPolicyCache,\n ReferencedPrincipalPolicyWarmer,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { ResolvedPrincipalPolicyEvidence } from \"../../../data/keyingProjectionVerification/types\";\nimport type { createProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification/userKeyResolver\";\nimport type { CurrentPolicyReferenceResolver } from \"../../../data/principals/currentPolicyReferenceResolver\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { SecurityIncidentReporter } from \"../../../data/shared/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport {\n planCarriedDescendantRekey,\n type SpeculativePath,\n} from \"../child/rekey/carriedDescendantRekeys\";\nimport type { PlannedRematerialization } from \"./principalContainerRematerializationTargets\";\n\nexport interface RematerializationApi\n extends ContainerReciteApi,\n Pick<ApiClient, \"getContainerWriterProjectionResult\"> {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport interface PrincipalRematerializationPredecessor {\n readonly authored?: readonly ResolvedPrincipalPolicyEvidence[] | undefined;\n readonly policies: readonly PrincipalPolicyCurrentEvidence[];\n readonly projections: readonly ContainerWriterProjectionResponse[];\n readonly knownContainerKeks: ReadonlyMap<string, Uint8Array>;\n}\n\nexport interface PrincipalContainerRematerializationInput {\n readonly preceding?: PrincipalRematerializationPredecessor | undefined;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n readonly apiClient: RematerializationApi;\n readonly author: ContainerMutationAuthor;\n readonly execSql: ExecSql;\n readonly grants: readonly PrincipalContainerGrant[];\n readonly groupId: string;\n readonly nextPolicy: PrincipalPolicyCurrentEvidence;\n readonly resolveAuthoredPolicyReferences?:\n | CurrentPolicyReferenceResolver\n | undefined;\n readonly revokedContainerId?: string | undefined;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n /** Session lifetime for best-effort work after durable acknowledgement. */\n readonly recitationStillCurrent?: (() => boolean) | undefined;\n readonly targetSecretKey: Uint8Array;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}\n\n/** What the batch has signed so far, in the order it will be submitted. */\nexport interface BatchPlanning {\n /**\n * Keys the batch minted, by epoch id. A rotation wraps its successor to the\n * group at the head this batch commits, which no store can open yet; a\n * level planned beneath it opens that epoch with the key minted here, and\n * its keyring then opens the retired epoch the level below is pinned to.\n */\n readonly knownContainerKeks: Map<string, Uint8Array>;\n readonly plans: PlannedRematerialization[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly rematerialization: PrincipalContainerRematerializationInput;\n readonly resolveProjectionUserKey: ReturnType<\n typeof createProjectionUserKeyResolver\n >;\n readonly rotatedAbove: SpeculativePath[];\n}\n\n/** How many rekeys the batch carries beyond its rematerializations. */\nfunction carriedCount(batch: BatchPlanning): number {\n return batch.plans.filter((entry) => entry.carried).length;\n}\n\n/**\n * Sign a rekey of `served` under the batch's rotations above it, and add it.\n * The server accepts at most `MAX_ROTATION_CONTAINER_REKEYS` carried entries;\n * past that a rematerialization below them could not be signed on a current\n * path, so the batch is refused here, before signing what the server would\n * refuse anyway, and the policy change has to wait for a lazy repair of the\n * tree. Groups granted that far apart on one chain are not a shape the SDK\n * creates.\n */\nexport async function carryLevel(\n batch: BatchPlanning,\n served: ContainerWriterProjectionResponse,\n): Promise<void> {\n const { rematerialization } = batch;\n if (carriedCount(batch) >= MAX_ROTATION_CONTAINER_REKEYS) {\n throw new Error(\n `Policy change would carry more than ${MAX_ROTATION_CONTAINER_REKEYS} descendant rekeys`,\n );\n }\n const planned = await planCarriedDescendantRekey({\n apiClient: rematerialization.apiClient,\n author: rematerialization.author,\n execSql: rematerialization.execSql,\n knownContainerKeks: batch.knownContainerKeks,\n principalPolicyCache: batch.principalPolicyCache,\n // Its path cites the policy this batch commits, so like every\n // rematerialized rotation it must cite the successor.\n replacementPrincipalPolicy: rematerialization.nextPolicy,\n resolveAuthoredPolicyReferences:\n rematerialization.resolveAuthoredPolicyReferences,\n resolveProjectionUserKey: batch.resolveProjectionUserKey,\n rotated: batch.rotatedAbove,\n served,\n stillCurrent: rematerialization.stillCurrent,\n targetSecretKey: rematerialization.targetSecretKey,\n warmReferencedPrincipalPolicies:\n rematerialization.warmReferencedPrincipalPolicies,\n });\n addPlan(batch, {\n carried: true,\n planned,\n rotated: planned.writerProjection,\n nextProjection: planned.writerProjection,\n });\n}\n\nexport function addPlan(\n batch: BatchPlanning,\n entry: PlannedRematerialization,\n): void {\n batch.plans.push(entry);\n if (!entry.rotated) return;\n batch.rotatedAbove.push(entry.rotated);\n const minted = entry.rotated.containerKeks.at(-1)?.containerKeyEpochId;\n if (minted) batch.knownContainerKeks.set(minted, entry.planned.containerKey);\n}\n\n/**\n * Levels of a re-rooted path pinned to an epoch the batch retires above them:\n * those strictly between the rotated ancestor the path was re-rooted on and\n * the target, parent-first, from the first stale one down. A rotation planned\n * above a target strands every level between the two, and each must be\n * re-keyed under the one above before the target can be signed. The batch\n * carries them without waiting to be told: they are proper ancestors of a\n * granted container, so the server would name them, and a refusal per level\n * is a round trip each. Anything stale above the rotated ancestor is not this\n * batch's doing and is left alone. `carryLevel` holds the count to the cap.\n */\nexport function staleLevelsAbove(\n projection: ContainerWriterProjectionResponse,\n rotatedAncestorId: string,\n): string[] {\n const keks = projection.containerKeks;\n const ancestor = keks.findIndex(\n (kek) => kek.containerId === rotatedAncestorId,\n );\n if (ancestor < 0) return [];\n const between = keks.slice(ancestor, -1);\n const firstStale = between.findIndex(\n (kek, index) =>\n index > 0 &&\n kek.parentContainerKeyEpochId !== between[index - 1]?.containerKeyEpochId,\n );\n return firstStale < 0\n ? []\n : between.slice(firstStale).map((kek) => kek.containerId);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"principalContainerRematerializationPlanning.js","sourceRoot":"","sources":["principalContainerRematerializationPlanning.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ApiClient } from \"@tearleads/api-client\";\nimport type { PrincipalContainerGrant } from \"@tearleads/crypto\";\nimport type { ContainerWriterProjectionResponse } from \"@tearleads/validators/response\";\nimport { MAX_ROTATION_CONTAINER_REKEYS } from \"@tearleads/validators/util\";\nimport type { ContainerReciteApi } from \"../../../data/containers/shared/reciteApi\";\nimport type { ContainerMutationAuthor } from \"../../../data/containers/shared/types\";\nimport {\n type PrincipalPolicyCache,\n type ReferencedPrincipalPolicyWarmer,\n verifyContainerWriterProjection,\n} from \"../../../data/keyingProjectionVerification\";\nimport type { ResolvedPrincipalPolicyEvidence } from \"../../../data/keyingProjectionVerification/types\";\nimport type { createProjectionUserKeyResolver } from \"../../../data/keyingProjectionVerification/userKeyResolver\";\nimport type { CurrentPolicyReferenceResolver } from \"../../../data/principals/currentPolicyReferenceResolver\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../../data/principals/principalPolicyEvidence\";\nimport type { SecurityIncidentReporter } from \"../../../data/shared/securityIncidents\";\nimport type { ExecSql } from \"../../../data/sqlite/sqlSchema\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport {\n planCarriedDescendantRekey,\n rebaseOnDeepestAncestor,\n type SpeculativePath,\n} from \"../child/rekey/carriedDescendantRekeys\";\nimport { isSpeculativeContainerWriterProjection } from \"../child/rekey/rekeyProjection\";\nimport type { PlannedRematerialization } from \"./principalContainerRematerializationTargets\";\n\nexport interface RematerializationApi\n extends ContainerReciteApi,\n Pick<ApiClient, \"getContainerWriterProjectionResult\"> {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport interface PrincipalRematerializationPredecessor {\n readonly authored?: readonly ResolvedPrincipalPolicyEvidence[] | undefined;\n readonly policies: readonly PrincipalPolicyCurrentEvidence[];\n readonly projections: readonly ContainerWriterProjectionResponse[];\n readonly knownContainerKeks: ReadonlyMap<string, Uint8Array>;\n}\n\nexport interface PrincipalContainerRematerializationInput {\n readonly preceding?: PrincipalRematerializationPredecessor | undefined;\n readonly reportSecurityIncident: SecurityIncidentReporter;\n readonly apiClient: RematerializationApi;\n readonly author: ContainerMutationAuthor;\n readonly execSql: ExecSql;\n readonly grants: readonly PrincipalContainerGrant[];\n readonly groupId: string;\n readonly nextPolicy: PrincipalPolicyCurrentEvidence;\n readonly resolveAuthoredPolicyReferences?:\n | CurrentPolicyReferenceResolver\n | undefined;\n readonly revokedContainerId?: string | undefined;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n readonly stillCurrent?: (() => boolean) | undefined;\n /** Session lifetime for best-effort work after durable acknowledgement. */\n readonly recitationStillCurrent?: (() => boolean) | undefined;\n readonly targetSecretKey: Uint8Array;\n readonly warmReferencedPrincipalPolicies?:\n | ReferencedPrincipalPolicyWarmer\n | undefined;\n}\n\n/** What the batch has signed so far, in the order it will be submitted. */\nexport interface BatchPlanning {\n /**\n * Keys the batch minted, by epoch id. A rotation wraps its successor to the\n * group at the head this batch commits, which no store can open yet; a\n * level planned beneath it opens that epoch with the key minted here, and\n * its keyring then opens the retired epoch the level below is pinned to.\n */\n readonly knownContainerKeks: Map<string, Uint8Array>;\n readonly plans: PlannedRematerialization[];\n readonly principalPolicyCache: PrincipalPolicyCache;\n readonly rematerialization: PrincipalContainerRematerializationInput;\n readonly resolveProjectionUserKey: ReturnType<\n typeof createProjectionUserKeyResolver\n >;\n readonly rotatedAbove: SpeculativePath[];\n /** Every path the batch authored, a grant's included, in signing order. */\n readonly authoredAbove: SpeculativePath[];\n}\n\n/** How many rekeys the batch carries beyond its rematerializations. */\nfunction carriedCount(batch: BatchPlanning): number {\n return batch.plans.filter((entry) => entry.carried).length;\n}\n\n/**\n * Sign a rekey of `served` under the batch's rotations above it, and add it.\n * The server accepts at most `MAX_ROTATION_CONTAINER_REKEYS` carried entries;\n * past that a rematerialization below them could not be signed on a current\n * path, so the batch is refused here, before signing what the server would\n * refuse anyway, and the policy change has to wait for a lazy repair of the\n * tree. Groups granted that far apart on one chain are not a shape the SDK\n * creates.\n */\nexport async function carryLevel(\n batch: BatchPlanning,\n served: ContainerWriterProjectionResponse,\n): Promise<void> {\n const { rematerialization } = batch;\n if (carriedCount(batch) >= MAX_ROTATION_CONTAINER_REKEYS) {\n throw new Error(\n `Policy change would carry more than ${MAX_ROTATION_CONTAINER_REKEYS} descendant rekeys`,\n );\n }\n const planned = await planCarriedDescendantRekey({\n apiClient: rematerialization.apiClient,\n author: rematerialization.author,\n execSql: rematerialization.execSql,\n knownContainerKeks: batch.knownContainerKeks,\n principalPolicyCache: batch.principalPolicyCache,\n // Its path cites the policy this batch commits, so like every\n // rematerialized rotation it must cite the successor.\n replacementPrincipalPolicy: rematerialization.nextPolicy,\n resolveAuthoredPolicyReferences:\n rematerialization.resolveAuthoredPolicyReferences,\n resolveProjectionUserKey: batch.resolveProjectionUserKey,\n rotated: batch.rotatedAbove,\n served,\n stillCurrent: rematerialization.stillCurrent,\n targetSecretKey: rematerialization.targetSecretKey,\n warmReferencedPrincipalPolicies:\n rematerialization.warmReferencedPrincipalPolicies,\n });\n addPlan(batch, {\n carried: true,\n planned,\n rotated: planned.writerProjection,\n nextProjection: planned.writerProjection,\n });\n}\n\n/**\n * Re-root a granted target on the deepest path the batch authored above it, a\n * grant's included: the server applies the batch in order, so the target\n * cites every head an earlier entry advances. Its served head is pinned first,\n * as a carried rekey's is. The batch is acknowledged against the latest\n * durable pin, and a re-rooted path pins nothing, so a device that never\n * pinned this container would refuse its own batch once the server took it.\n * Only what the API served is pinned: in a compound transaction the target\n * may already sit on the preceding batch's heads, which a refused commit\n * never makes real.\n */\nexport async function rerootOnAuthoredPaths(\n batch: BatchPlanning,\n served: ContainerWriterProjectionResponse,\n): Promise<ContainerWriterProjectionResponse> {\n const rebased = rebaseOnDeepestAncestor(served, batch.authoredAbove);\n if (!rebased) return served;\n if (isSpeculativeContainerWriterProjection(served)) {\n return rebased.projection;\n }\n const { rematerialization } = batch;\n await verifyContainerWriterProjection({\n execSql: rematerialization.execSql,\n principalPolicyCache: batch.principalPolicyCache,\n projection: served,\n resolveUserKey: batch.resolveProjectionUserKey,\n stillCurrent: rematerialization.stillCurrent,\n warmReferencedPrincipalPolicies:\n rematerialization.warmReferencedPrincipalPolicies,\n });\n return rebased.projection;\n}\n\nexport function addPlan(\n batch: BatchPlanning,\n entry: PlannedRematerialization,\n): void {\n batch.plans.push(entry);\n if (entry.nextProjection) batch.authoredAbove.push(entry.nextProjection);\n if (!entry.rotated) return;\n batch.rotatedAbove.push(entry.rotated);\n const minted = entry.rotated.containerKeks.at(-1)?.containerKeyEpochId;\n if (minted) batch.knownContainerKeks.set(minted, entry.planned.containerKey);\n}\n\n/**\n * Levels of a re-rooted path pinned to an epoch the batch retires above them:\n * those strictly between the rotated ancestor the path was re-rooted on and\n * the target, parent-first, from the first stale one down. A rotation planned\n * above a target strands every level between the two, and each must be\n * re-keyed under the one above before the target can be signed. The batch\n * carries them without waiting to be told: they are proper ancestors of a\n * granted container, so the server would name them, and a refusal per level\n * is a round trip each. Anything stale above the rotated ancestor is not this\n * batch's doing and is left alone. `carryLevel` holds the count to the cap.\n */\nexport function staleLevelsAbove(\n projection: ContainerWriterProjectionResponse,\n rotatedAncestorId: string,\n): string[] {\n const keks = projection.containerKeks;\n const ancestor = keks.findIndex(\n (kek) => kek.containerId === rotatedAncestorId,\n );\n if (ancestor < 0) return [];\n const between = keks.slice(ancestor, -1);\n const firstStale = between.findIndex(\n (kek, index) =>\n index > 0 &&\n kek.parentContainerKeyEpochId !== between[index - 1]?.containerKeyEpochId,\n );\n return firstStale < 0\n ? []\n : between.slice(firstStale).map((kek) => kek.containerId);\n}\n"]}
|
|
@@ -76,27 +76,33 @@ async function prepareChange(change, signer, preceding) {
|
|
|
76
76
|
localPolicyCheckpoint: change.context.localPolicyCheckpoint,
|
|
77
77
|
stillCurrent: change.context.stillCurrent,
|
|
78
78
|
});
|
|
79
|
-
const
|
|
79
|
+
const authored = [
|
|
80
|
+
...(preceding?.authored ?? []),
|
|
81
|
+
{
|
|
82
|
+
organizationId: change.context.organizationDescriptor.organizationId,
|
|
83
|
+
policy: nextPolicy,
|
|
84
|
+
dependencies: [
|
|
85
|
+
change.context.organizationCurrent.policy,
|
|
86
|
+
change.context.adminCurrent.policy,
|
|
87
|
+
],
|
|
88
|
+
stillCurrent: change.context.stillCurrent,
|
|
89
|
+
},
|
|
90
|
+
];
|
|
91
|
+
// A level the batch plans under its own rotation cites this successor
|
|
92
|
+
// before the transaction commits, so the batch resolves it as authored,
|
|
93
|
+
// exactly as the next group in a compound transaction does (#2646).
|
|
94
|
+
const prepared = await change.prepareContainerMutations(nextPolicy, {
|
|
95
|
+
policies: preceding?.policies ?? [],
|
|
96
|
+
projections: preceding?.projections ?? [],
|
|
97
|
+
knownContainerKeks: preceding?.knownContainerKeks ?? new Map(),
|
|
98
|
+
authored,
|
|
99
|
+
});
|
|
80
100
|
change.request.containerMutations = [...prepared.requests];
|
|
81
101
|
return {
|
|
82
102
|
expectedHead,
|
|
83
103
|
prepared,
|
|
84
104
|
preceding: prepared.preceding
|
|
85
|
-
? {
|
|
86
|
-
...prepared.preceding,
|
|
87
|
-
authored: [
|
|
88
|
-
...(preceding?.authored ?? []),
|
|
89
|
-
{
|
|
90
|
-
organizationId: change.context.organizationDescriptor.organizationId,
|
|
91
|
-
policy: nextPolicy,
|
|
92
|
-
dependencies: [
|
|
93
|
-
change.context.organizationCurrent.policy,
|
|
94
|
-
change.context.adminCurrent.policy,
|
|
95
|
-
],
|
|
96
|
-
stillCurrent: change.context.stillCurrent,
|
|
97
|
-
},
|
|
98
|
-
],
|
|
99
|
-
}
|
|
105
|
+
? { ...prepared.preceding, authored }
|
|
100
106
|
: undefined,
|
|
101
107
|
};
|
|
102
108
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commitCurrentGroupPolicyMutation.js","sourceRoot":"","sources":["commitCurrentGroupPolicyMutation.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mCAAmC,EAAE,MAAM,kDAAkD,CAAC;AAMvG,OAAO,EACL,4CAA4C,EAC5C,4BAA4B,GAC7B,MAAM,sCAAsC,CAAC;AAC9C,OAAO,EAAE,sCAAsC,EAAE,MAAM,gDAAgD,CAAC;AAExG,OAAO,EACL,iBAAiB,EACjB,6BAA6B,GAC9B,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAClF,OAAO,EAEL,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAsBpE,sFAAsF;AACtF,MAAM,CAAC,KAAK,UAAU,gCAAgC,CACpD,KAAkB;IAElB,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1B,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,CAAC,MAAM,CAAC,GAAG,MAAM,6BAA6B,CAAC;QACnD,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;QAC5D,OAAO,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC;KAC9B,CAAC,CAAC;IACH,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACnE,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM;QACzB,CAAC,CAAC,MAAM,aAAa,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,CAAC;QAC3C,CAAC,CAAC,IAAI,CAAC;IACT,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CACpD,KAAK,EACL,MAAM,EACN,MAAM,EAAE,SAAS,CAClB,CAAC;IACF,MAAM,mBAAmB,GAAG,MAAM,gBAAgB,CAChD,KAAK,EACL,YAAY,EACZ,MAAM,EAAE,YAAY,CACrB,CAAC;IACF,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC;QAC7C,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,cAAc,EAAE,KAAK,CAAC,cAAc;QACpC,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,mBAAmB;QACnB,aAAa,EAAE,KAAK,CAAC,MAAM,EAAE,OAAO;QACpC,wEAAwE;QACxE,2EAA2E;QAC3E,wEAAwE;QACxE,qBAAqB,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK;QAC1D,YAAY,EAAE,OAAO,CAAC,YAAY;KACnC,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAC7D,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,MAAM,sCAAsC,CAC1C;QACE,WAAW,EAAE,KAAK,CAAC,OAAO;QAC1B,kBAAkB,EAAE,mBAAmB;QACvC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChE,EACD,QAAQ,CACT,CAAC;IACF,MAAM,OAAO,CAAC,kBAAkB,CAAC;QAC/B,gBAAgB,EACd,KAAK,CAAC,MAAM,IAAI,QAAQ,CAAC,YAAY;YACnC,CAAC,CAAC;gBACE;oBACE,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,cAAc;oBACtC,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO;oBAC7B,QAAQ,EAAE,QAAQ,CAAC,YAAY;oBAC/B,mBAAmB,EAAE,MAAM,EAAE,QAAQ,CAAC,mBAAmB;iBAC1D;aACF;YACH,CAAC,CAAC,EAAE;QACR,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,mBAAmB;QACnB,QAAQ;QACR,mBAAmB,EAAE,QAAQ,CAAC,mBAAmB;KAClD,CAAC,CAAC;IACH,IAAI,MAAM,IAAI,QAAQ,CAAC,YAAY,EAAE,CAAC;QACpC,MAAM,MAAM,CAAC,QAAQ,CAAC,WAAW,CAC/B,QAAQ,CAAC,YAAY,CAAC,kBAAkB,EACxC,OAAO,CAAC,YAAY,CACrB,CAAC;IACJ,CAAC;IACD,MAAM,QAAQ,CAAC,WAAW,CACxB,QAAQ,CAAC,WAAW,CAAC,kBAAkB,EACvC,OAAO,CAAC,YAAY,CACrB,CAAC;IACF,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC1D,OAAO,QAAQ,CAAC,WAAW,CAAC;AAC9B,CAAC;AAED,KAAK,UAAU,aAAa,CAC1B,MAAyB,EACzB,MAAyE,EACzE,SAAiD;IAEjD,MAAM,YAAY,GAAG,MAAM,uBAAuB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,MAAM,0BAA0B,CAAC;QAClD,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,qBAAqB;QAC3D,YAAY;QACZ,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,gBAAgB,EAAE,CAAC,MAAM,CAAC;QAC1B,iBAAiB,EAAE,MAAM,CAAC,OAAO,CAAC,iBAAiB;QACnD,qBAAqB,EAAE,MAAM,CAAC,OAAO,CAAC,qBAAqB;QAC3D,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;KAC1C,CAAC,CAAC;IACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,yBAAyB,CACrD,UAAU,EACV,SAAS,CACV,CAAC;IACF,MAAM,CAAC,OAAO,CAAC,kBAAkB,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC3D,OAAO;QACL,YAAY;QACZ,QAAQ;QACR,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC3B,CAAC,CAAC;gBACE,GAAG,QAAQ,CAAC,SAAS;gBACrB,QAAQ,EAAE;oBACR,GAAG,CAAC,SAAS,EAAE,QAAQ,IAAI,EAAE,CAAC;oBAC9B;wBACE,cAAc,EACZ,MAAM,CAAC,OAAO,CAAC,sBAAsB,CAAC,cAAc;wBACtD,MAAM,EAAE,UAAU;wBAClB,YAAY,EAAE;4BACZ,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,MAAM;4BACzC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,MAAM;yBACnC;wBACD,YAAY,EAAE,MAAM,CAAC,OAAO,CAAC,YAAY;qBAC1C;iBACF;aACF;YACH,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,KAAkB,EAClB,YAAiE,EACjE,UAA2E;IAE3E,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC;IAC1B,IACE,KAAK,CAAC,MAAM;QACZ,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,YAAY,CAAC,WAAW;YAC1D,OAAO,CAAC,aAAa;YACrB,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,YAAY;iBAC1D,SAAS;gBACV,OAAO,CAAC,mBAAmB,CAAC,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC;QAE/D,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;IACJ,IAAI,UAAU,GAAG,4BAA4B,CAAC;QAC5C,UAAU,EAAE,OAAO,CAAC,sBAAsB;QAC1C,QAAQ,EAAE,YAAY;KACvB,CAAC,CAAC;IACH,IAAI,UAAU;QACZ,UAAU,GAAG,4BAA4B,CAAC;YACxC,UAAU,EAAE,EAAE,GAAG,OAAO,CAAC,sBAAsB,EAAE,UAAU,EAAE;YAC7D,QAAQ,EAAE,UAAU;SACrB,CAAC,CAAC;IACL,MAAM,eAAe,GAAG,OAAO,CAAC,yBAAyB;QACvD,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU;QAC1B,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,OAAO,CAAC,iBAAiB,CAAC;IACnD,MAAM,UAAU,GAAG,MAAM,6BAA6B,CAAC;QACrD,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;QAC5D,OAAO,EAAE,iBAAiB,CAAC,eAAe,CAAC;KAC5C,CAAC,CAAC;IACH,OAAO,4CAA4C,CAAC;QAClD,eAAe;QACf,UAAU;QACV,aAAa,EAAE,OAAO,CAAC,mBAAmB,CAAC,OAAO;QAClD,UAAU,EAAE,OAAO,CAAC,sBAAsB;QAC1C,UAAU;QACV,YAAY,EAAE,KAAK,CAAC,YAAY;QAChC,kBAAkB,EAAE,KAAK,CAAC,kBAAkB;QAC5C,cAAc,EAAE,KAAK,CAAC,cAAc;KACrC,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type {\n SigningKeyPair,\n VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyMutationResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport type {\n PreparedPrincipalContainerRematerializationBatch,\n PrincipalRematerializationPredecessor,\n} from \"../../containers/rematerialization\";\nimport {\n buildOrganizationGroupDirectoryPolicyRequest,\n replaceOrganizationGroupHead,\n} from \"../groups/organizationGroupDirectory\";\nimport { assertAuthoredPrincipalMutationReceipt } from \"../principalMutations/principalMutationReceipt\";\nimport type { RuntimeCurrentGroupMutationContext } from \"../principalMutations/runtimeCurrentGroupMutation\";\nimport {\n projectionUserIds,\n resolveRequiredUserIdentities,\n} from \"../trustedOrganizationUsers\";\nimport { prepareAuthoredGroupPolicy } from \"./groupPolicyMutationAcknowledgement\";\nimport {\n type PrincipalPolicyReadWriteApi,\n submitGroupPolicyCommit,\n} from \"./groupPolicyMutationContext\";\nimport { groupPolicyMutationHead } from \"./groupPolicyMutationHead\";\n\ninterface GroupPolicyChange {\n readonly context: RuntimeCurrentGroupMutationContext;\n readonly request: PutPrincipalPolicyRequest;\n readonly prepareContainerMutations: (\n nextPolicy: VerifiedPrincipalPolicyCurrent,\n preceding?: PrincipalRematerializationPredecessor | undefined,\n ) => Promise<PreparedPrincipalContainerRematerializationBatch>;\n}\n\ninterface CommitInput extends GroupPolicyChange {\n readonly member?: GroupPolicyChange | undefined;\n readonly apiClient: PrincipalPolicyReadWriteApi;\n readonly groupId: string;\n readonly organizationId: string;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\n/** Commit and retain the group, optional roster enrollment and directory together. */\nexport async function commitCurrentGroupPolicyMutation(\n input: CommitInput,\n): Promise<PrincipalPolicyMutationResponse> {\n const { context } = input;\n assertProjectionVerificationCurrent(context.stillCurrent);\n const [signer] = await resolveRequiredUserIdentities({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n userIds: [input.signerUserId],\n });\n if (!signer) throw new Error(\"Group policy signer is unavailable\");\n const member = input.member\n ? await prepareChange(input.member, signer)\n : null;\n const { expectedHead, prepared } = await prepareChange(\n input,\n signer,\n member?.preceding,\n );\n const organizationRequest = await prepareDirectory(\n input,\n expectedHead,\n member?.expectedHead,\n );\n assertProjectionVerificationCurrent(context.stillCurrent);\n const response = await submitGroupPolicyCommit({\n apiClient: input.apiClient,\n groupId: input.groupId,\n organizationId: input.organizationId,\n request: input.request,\n organizationRequest,\n memberRequest: input.member?.request,\n // A compound retry must rebuild both batches' shared speculative heads.\n // Refuse the whole transaction if a damaged-key repair needs extra rekeys;\n // ordinary adds preserve key epochs and need no descendant carry retry.\n carryDescendantRekeys: member ? undefined : prepared.carry,\n stillCurrent: context.stillCurrent,\n });\n if (!response) throw new Error(\"Group policy update failed\");\n assertProjectionVerificationCurrent(context.stillCurrent);\n await assertAuthoredPrincipalMutationReceipt(\n {\n groupPolicy: input.request,\n organizationPolicy: organizationRequest,\n ...(input.member ? { memberPolicy: input.member.request } : {}),\n },\n response,\n );\n await context.retainAcknowledged({\n additionalGroups:\n input.member && response.memberPolicy\n ? [\n {\n ...input.member.context.groupRetention,\n request: input.member.request,\n response: response.memberPolicy,\n retiredContainerIds: member?.prepared.retiredContainerIds,\n },\n ]\n : [],\n request: input.request,\n organizationRequest,\n response,\n retiredContainerIds: prepared.retiredContainerIds,\n });\n if (member && response.memberPolicy) {\n await member.prepared.acknowledge(\n response.memberPolicy.containerMutations,\n context.stillCurrent,\n );\n }\n await prepared.acknowledge(\n response.groupPolicy.containerMutations,\n context.stillCurrent,\n );\n assertProjectionVerificationCurrent(context.stillCurrent);\n return response.groupPolicy;\n}\n\nasync function prepareChange(\n change: GroupPolicyChange,\n signer: Awaited<ReturnType<typeof resolveRequiredUserIdentities>>[number],\n preceding?: PrincipalRematerializationPredecessor,\n) {\n const expectedHead = await groupPolicyMutationHead(change.request);\n const nextPolicy = await prepareAuthoredGroupPolicy({\n verifiedCurrentPolicy: change.context.verifiedCurrentPolicy,\n expectedHead,\n request: change.request,\n signerPublicKeys: [signer],\n externalAuthority: change.context.externalAuthority,\n localPolicyCheckpoint: change.context.localPolicyCheckpoint,\n stillCurrent: change.context.stillCurrent,\n });\n const prepared = await change.prepareContainerMutations(\n nextPolicy,\n preceding,\n );\n change.request.containerMutations = [...prepared.requests];\n return {\n expectedHead,\n prepared,\n preceding: prepared.preceding\n ? {\n ...prepared.preceding,\n authored: [\n ...(preceding?.authored ?? []),\n {\n organizationId:\n change.context.organizationDescriptor.organizationId,\n policy: nextPolicy,\n dependencies: [\n change.context.organizationCurrent.policy,\n change.context.adminCurrent.policy,\n ],\n stillCurrent: change.context.stillCurrent,\n },\n ],\n }\n : undefined,\n };\n}\n\nasync function prepareDirectory(\n input: CommitInput,\n expectedHead: Awaited<ReturnType<typeof groupPolicyMutationHead>>,\n memberHead: Awaited<ReturnType<typeof groupPolicyMutationHead>> | undefined,\n) {\n const { context } = input;\n if (\n input.member &&\n (input.member.context.currentPolicy.currentState.principalId !==\n context.memberGroupId ||\n input.member.context.organizationCurrent.current.currentState\n .stateHash !==\n context.organizationCurrent.current.currentState.stateHash)\n )\n throw new Error(\n \"Roster and group changes must share the same organization policy\",\n );\n let groupHeads = replaceOrganizationGroupHead({\n descriptor: context.organizationDescriptor,\n nextHead: expectedHead,\n });\n if (memberHead)\n groupHeads = replaceOrganizationGroupHead({\n descriptor: { ...context.organizationDescriptor, groupHeads },\n nextHead: memberHead,\n });\n const adminProjection = context.isOrganizationAdminsGroup\n ? input.request.projection\n : context.adminCurrent.current.currentProjection;\n const adminUsers = await resolveRequiredUserIdentities({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n userIds: projectionUserIds(adminProjection),\n });\n return buildOrganizationGroupDirectoryPolicyRequest({\n adminProjection,\n adminUsers,\n currentPolicy: context.organizationCurrent.current,\n descriptor: context.organizationDescriptor,\n groupHeads,\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"file":"commitCurrentGroupPolicyMutation.js","sourceRoot":"","sources":["commitCurrentGroupPolicyMutation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n SigningKeyPair,\n VerifiedPrincipalPolicyCurrent,\n} from \"@tearleads/crypto\";\nimport type { PutPrincipalPolicyRequest } from \"@tearleads/validators/request\";\nimport type { PrincipalPolicyMutationResponse } from \"@tearleads/validators/response\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport type { TrustedUserIdentityResolver } from \"../../../data/trustedUserIdentity\";\nimport type {\n PreparedPrincipalContainerRematerializationBatch,\n PrincipalRematerializationPredecessor,\n} from \"../../containers/rematerialization\";\nimport {\n buildOrganizationGroupDirectoryPolicyRequest,\n replaceOrganizationGroupHead,\n} from \"../groups/organizationGroupDirectory\";\nimport { assertAuthoredPrincipalMutationReceipt } from \"../principalMutations/principalMutationReceipt\";\nimport type { RuntimeCurrentGroupMutationContext } from \"../principalMutations/runtimeCurrentGroupMutation\";\nimport {\n projectionUserIds,\n resolveRequiredUserIdentities,\n} from \"../trustedOrganizationUsers\";\nimport { prepareAuthoredGroupPolicy } from \"./groupPolicyMutationAcknowledgement\";\nimport {\n type PrincipalPolicyReadWriteApi,\n submitGroupPolicyCommit,\n} from \"./groupPolicyMutationContext\";\nimport { groupPolicyMutationHead } from \"./groupPolicyMutationHead\";\n\ninterface GroupPolicyChange {\n readonly context: RuntimeCurrentGroupMutationContext;\n readonly request: PutPrincipalPolicyRequest;\n readonly prepareContainerMutations: (\n nextPolicy: VerifiedPrincipalPolicyCurrent,\n preceding?: PrincipalRematerializationPredecessor | undefined,\n ) => Promise<PreparedPrincipalContainerRematerializationBatch>;\n}\n\ninterface CommitInput extends GroupPolicyChange {\n readonly member?: GroupPolicyChange | undefined;\n readonly apiClient: PrincipalPolicyReadWriteApi;\n readonly groupId: string;\n readonly organizationId: string;\n readonly signerUserId: string;\n readonly signingFingerprint: string;\n readonly signingKeyPair: SigningKeyPair;\n readonly resolveTrustedUserIdentity: TrustedUserIdentityResolver;\n}\n\n/** Commit and retain the group, optional roster enrollment and directory together. */\nexport async function commitCurrentGroupPolicyMutation(\n input: CommitInput,\n): Promise<PrincipalPolicyMutationResponse> {\n const { context } = input;\n assertProjectionVerificationCurrent(context.stillCurrent);\n const [signer] = await resolveRequiredUserIdentities({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n userIds: [input.signerUserId],\n });\n if (!signer) throw new Error(\"Group policy signer is unavailable\");\n const member = input.member\n ? await prepareChange(input.member, signer)\n : null;\n const { expectedHead, prepared } = await prepareChange(\n input,\n signer,\n member?.preceding,\n );\n const organizationRequest = await prepareDirectory(\n input,\n expectedHead,\n member?.expectedHead,\n );\n assertProjectionVerificationCurrent(context.stillCurrent);\n const response = await submitGroupPolicyCommit({\n apiClient: input.apiClient,\n groupId: input.groupId,\n organizationId: input.organizationId,\n request: input.request,\n organizationRequest,\n memberRequest: input.member?.request,\n // A compound retry must rebuild both batches' shared speculative heads.\n // Refuse the whole transaction if a damaged-key repair needs extra rekeys;\n // ordinary adds preserve key epochs and need no descendant carry retry.\n carryDescendantRekeys: member ? undefined : prepared.carry,\n stillCurrent: context.stillCurrent,\n });\n if (!response) throw new Error(\"Group policy update failed\");\n assertProjectionVerificationCurrent(context.stillCurrent);\n await assertAuthoredPrincipalMutationReceipt(\n {\n groupPolicy: input.request,\n organizationPolicy: organizationRequest,\n ...(input.member ? { memberPolicy: input.member.request } : {}),\n },\n response,\n );\n await context.retainAcknowledged({\n additionalGroups:\n input.member && response.memberPolicy\n ? [\n {\n ...input.member.context.groupRetention,\n request: input.member.request,\n response: response.memberPolicy,\n retiredContainerIds: member?.prepared.retiredContainerIds,\n },\n ]\n : [],\n request: input.request,\n organizationRequest,\n response,\n retiredContainerIds: prepared.retiredContainerIds,\n });\n if (member && response.memberPolicy) {\n await member.prepared.acknowledge(\n response.memberPolicy.containerMutations,\n context.stillCurrent,\n );\n }\n await prepared.acknowledge(\n response.groupPolicy.containerMutations,\n context.stillCurrent,\n );\n assertProjectionVerificationCurrent(context.stillCurrent);\n return response.groupPolicy;\n}\n\nasync function prepareChange(\n change: GroupPolicyChange,\n signer: Awaited<ReturnType<typeof resolveRequiredUserIdentities>>[number],\n preceding?: PrincipalRematerializationPredecessor,\n) {\n const expectedHead = await groupPolicyMutationHead(change.request);\n const nextPolicy = await prepareAuthoredGroupPolicy({\n verifiedCurrentPolicy: change.context.verifiedCurrentPolicy,\n expectedHead,\n request: change.request,\n signerPublicKeys: [signer],\n externalAuthority: change.context.externalAuthority,\n localPolicyCheckpoint: change.context.localPolicyCheckpoint,\n stillCurrent: change.context.stillCurrent,\n });\n const authored = [\n ...(preceding?.authored ?? []),\n {\n organizationId: change.context.organizationDescriptor.organizationId,\n policy: nextPolicy,\n dependencies: [\n change.context.organizationCurrent.policy,\n change.context.adminCurrent.policy,\n ],\n stillCurrent: change.context.stillCurrent,\n },\n ];\n // A level the batch plans under its own rotation cites this successor\n // before the transaction commits, so the batch resolves it as authored,\n // exactly as the next group in a compound transaction does (#2646).\n const prepared = await change.prepareContainerMutations(nextPolicy, {\n policies: preceding?.policies ?? [],\n projections: preceding?.projections ?? [],\n knownContainerKeks: preceding?.knownContainerKeks ?? new Map(),\n authored,\n });\n change.request.containerMutations = [...prepared.requests];\n return {\n expectedHead,\n prepared,\n preceding: prepared.preceding\n ? { ...prepared.preceding, authored }\n : undefined,\n };\n}\n\nasync function prepareDirectory(\n input: CommitInput,\n expectedHead: Awaited<ReturnType<typeof groupPolicyMutationHead>>,\n memberHead: Awaited<ReturnType<typeof groupPolicyMutationHead>> | undefined,\n) {\n const { context } = input;\n if (\n input.member &&\n (input.member.context.currentPolicy.currentState.principalId !==\n context.memberGroupId ||\n input.member.context.organizationCurrent.current.currentState\n .stateHash !==\n context.organizationCurrent.current.currentState.stateHash)\n )\n throw new Error(\n \"Roster and group changes must share the same organization policy\",\n );\n let groupHeads = replaceOrganizationGroupHead({\n descriptor: context.organizationDescriptor,\n nextHead: expectedHead,\n });\n if (memberHead)\n groupHeads = replaceOrganizationGroupHead({\n descriptor: { ...context.organizationDescriptor, groupHeads },\n nextHead: memberHead,\n });\n const adminProjection = context.isOrganizationAdminsGroup\n ? input.request.projection\n : context.adminCurrent.current.currentProjection;\n const adminUsers = await resolveRequiredUserIdentities({\n resolveTrustedUserIdentity: input.resolveTrustedUserIdentity,\n userIds: projectionUserIds(adminProjection),\n });\n return buildOrganizationGroupDirectoryPolicyRequest({\n adminProjection,\n adminUsers,\n currentPolicy: context.organizationCurrent.current,\n descriptor: context.organizationDescriptor,\n groupHeads,\n signerUserId: input.signerUserId,\n signingFingerprint: input.signingFingerprint,\n signingKeyPair: input.signingKeyPair,\n });\n}\n"]}
|
|
@@ -40,8 +40,8 @@ export async function commitCurrentShareGrant(input) {
|
|
|
40
40
|
signingFingerprint: share.author.signerKeyFingerprint,
|
|
41
41
|
signingKeyPair,
|
|
42
42
|
resolveTrustedUserIdentity: share.resolveTrustedUserIdentity,
|
|
43
|
-
prepareContainerMutations: async (nextPolicy) => {
|
|
44
|
-
prepared.batch = await prepareCurrentShareGrantBatch(share, context, nextPolicy, input.recitationStillCurrent);
|
|
43
|
+
prepareContainerMutations: async (nextPolicy, preceding) => {
|
|
44
|
+
prepared.batch = await prepareCurrentShareGrantBatch(share, context, { nextPolicy, preceding }, input.recitationStillCurrent);
|
|
45
45
|
return prepared.batch;
|
|
46
46
|
},
|
|
47
47
|
});
|
|
@@ -66,9 +66,10 @@ async function assertCurrentShareGrantName(runtime, share, context, expectedName
|
|
|
66
66
|
throw new GroupShareNameMismatchError("Container share group name does not match the signed group policy");
|
|
67
67
|
assertProjectionVerificationCurrent(context.stillCurrent);
|
|
68
68
|
}
|
|
69
|
-
function prepareCurrentShareGrantBatch(share, context, nextPolicy, recitationStillCurrent) {
|
|
69
|
+
function prepareCurrentShareGrantBatch(share, context, { nextPolicy, preceding, }, recitationStillCurrent) {
|
|
70
70
|
return preparePrincipalContainerRematerializationBatch({
|
|
71
71
|
...share,
|
|
72
|
+
preceding,
|
|
72
73
|
grants: [
|
|
73
74
|
...new Map([...context.currentPolicy.currentGrants, ...nextPolicy.grants].map((grant) => [grant.containerId, grant])).values(),
|
|
74
75
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"currentShareGrantMutation.js","sourceRoot":"","sources":["currentShareGrantMutation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mCAAmC,EAAE,MAAM,kDAAkD,CAAC;AACvG,OAAO,EAEL,+CAA+C,GAChD,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,gCAAgC,EAAE,MAAM,iDAAiD,CAAC;AACnG,OAAO,EAAE,wCAAwC,EAAE,MAAM,oCAAoC,CAAC;AAK9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAGrE,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,KAS7C;IACC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAC7C,IAAI,YAAY,KAAK,IAAI;QACvB,MAAM,IAAI,KAAK,CACb,8GAA8G,CAC/G,CAAC;IACJ,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;IAC5C,IAAI,CAAC,cAAc;QACjB,MAAM,IAAI,KAAK,CACb,iEAAiE,CAClE,CAAC;IACJ,OAAO,KAAK,CAAC,MAAM,CACjB;QACE,OAAO,EAAE,KAAK,CAAC,gBAAgB;QAC/B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;QAC3C,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;QACvC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KACjD,EACD,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,MAAM,2BAA2B,CAC/B,KAAK,CAAC,OAAO,EACb,KAAK,EACL,OAAO,EACP,YAAY,CACb,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,wCAAwC,CAAC;YAC7D,GAAG,OAAO;YACV,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;YACvC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB;YACrD,cAAc;SACf,CAAC,CAAC;QACH,MAAM,QAAQ,GAEV,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CAAC;YACtD,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO;YACP,OAAO,EAAE,KAAK,CAAC,gBAAgB;YAC/B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;YAC3C,OAAO;YACP,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;YACvC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB;YACrD,cAAc;YACd,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;YAC5D,yBAAyB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE;
|
|
1
|
+
{"version":3,"file":"currentShareGrantMutation.js","sourceRoot":"","sources":["currentShareGrantMutation.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mCAAmC,EAAE,MAAM,kDAAkD,CAAC;AACvG,OAAO,EAEL,+CAA+C,GAChD,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,gCAAgC,EAAE,MAAM,uCAAuC,CAAC;AACzF,OAAO,EAAE,gCAAgC,EAAE,MAAM,iDAAiD,CAAC;AACnG,OAAO,EAAE,wCAAwC,EAAE,MAAM,oCAAoC,CAAC;AAK9F,OAAO,EAAE,uBAAuB,EAAE,MAAM,2CAA2C,CAAC;AAEpF,OAAO,EAAE,2BAA2B,EAAE,MAAM,wBAAwB,CAAC;AAGrE,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,KAS7C;IACC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1B,MAAM,YAAY,GAAG,KAAK,CAAC,iBAAiB,CAAC;IAC7C,IAAI,YAAY,KAAK,IAAI;QACvB,MAAM,IAAI,KAAK,CACb,8GAA8G,CAC/G,CAAC;IACJ,MAAM,cAAc,GAAG,KAAK,CAAC,cAAc,CAAC;IAC5C,IAAI,CAAC,cAAc;QACjB,MAAM,IAAI,KAAK,CACb,iEAAiE,CAClE,CAAC;IACJ,OAAO,KAAK,CAAC,MAAM,CACjB;QACE,OAAO,EAAE,KAAK,CAAC,gBAAgB;QAC/B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;QAC3C,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;QACvC,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;KACjD,EACD,KAAK,EAAE,OAAO,EAAE,EAAE;QAChB,MAAM,2BAA2B,CAC/B,KAAK,CAAC,OAAO,EACb,KAAK,EACL,OAAO,EACP,YAAY,CACb,CAAC;QACF,MAAM,OAAO,GAAG,MAAM,wCAAwC,CAAC;YAC7D,GAAG,OAAO;YACV,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;YACvC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB;YACrD,cAAc;SACf,CAAC,CAAC;QACH,MAAM,QAAQ,GAEV,EAAE,CAAC;QACP,MAAM,QAAQ,GAAG,MAAM,gCAAgC,CAAC;YACtD,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,OAAO;YACP,OAAO,EAAE,KAAK,CAAC,gBAAgB;YAC/B,cAAc,EAAE,KAAK,CAAC,MAAM,CAAC,cAAc;YAC3C,OAAO;YACP,YAAY,EAAE,KAAK,CAAC,MAAM,CAAC,YAAY;YACvC,kBAAkB,EAAE,KAAK,CAAC,MAAM,CAAC,oBAAoB;YACrD,cAAc;YACd,0BAA0B,EAAE,KAAK,CAAC,0BAA0B;YAC5D,yBAAyB,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE;gBACzD,QAAQ,CAAC,KAAK,GAAG,MAAM,6BAA6B,CAClD,KAAK,EACL,OAAO,EACP,EAAE,UAAU,EAAE,SAAS,EAAE,EACzB,KAAK,CAAC,sBAAsB,CAC7B,CAAC;gBACF,OAAO,QAAQ,CAAC,KAAK,CAAC;YACxB,CAAC;SACF,CAAC,CAAC;QACH,MAAM,KAAK,GACT,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,SAAS,CAC7B,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,WAAW,KAAK,KAAK,CAAC,WAAW,CAC5D,IAAI,CAAC,CAAC,CAAC;QACV,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,eAAe,GAAG,QAAQ,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC3D,IAAI,CAAC,IAAI,IAAI,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YACjD,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,OAAO;YACL,YAAY,EAAE,IAAI,CAAC,YAAY;YAC/B,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ,EAAE,eAAe;SAC1B,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,SAAS,WAAW,CAClB,IAAuE;IAEvE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,KAAK,iBAAiB,CAAC;AACxD,CAAC;AAED,KAAK,UAAU,2BAA2B,CACxC,OAAuE,EACvE,KAA0D,EAC1D,OAA2C,EAC3C,YAAoB;IAEpB,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAC5C,OAAO,CAAC,aAAa,EACrB,YAAY,EACZ,gCAAgC,CAC9B,OAAO,EACP,KAAK,CAAC,MAAM,CAAC,cAAc,EAC3B,OAAO,CAAC,YAAY,EACpB,OAAO,CAAC,uBAAuB,CAChC,CAAC,QAAQ,CACX,CAAC;IACF,IAAI,QAAQ;QACV,MAAM,IAAI,2BAA2B,CACnC,mEAAmE,CACpE,CAAC;IACJ,mCAAmC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;AAC5D,CAAC;AAED,SAAS,6BAA6B,CACpC,KAA0D,EAC1D,OAA2C,EAC3C,EACE,UAAU,EACV,SAAS,GAIV,EACD,sBAAsC;IAEtC,OAAO,+CAA+C,CAAC;QACrD,GAAG,KAAK;QACR,SAAS;QACT,MAAM,EAAE;YACN,GAAG,IAAI,GAAG,CACR,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,aAAa,EAAE,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,GAAG,CAChE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAU,CAC/C,CACF,CAAC,MAAM,EAAE;SACX;QACD,OAAO,EAAE,KAAK,CAAC,gBAAgB;QAC/B,UAAU;QACV,+BAA+B,EAAE,OAAO,CAAC,+BAA+B;QACxE,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,sBAAsB;KACvB,CAAC,CAAC;AACL,CAAC","sourcesContent":["import type { MaterializedContainerSharePlan } from \"../../../data/containers/shared/types\";\nimport { assertProjectionVerificationCurrent } from \"../../../data/keyingProjectionVerification/types\";\nimport {\n type PreparedPrincipalContainerRematerializationBatch,\n preparePrincipalContainerRematerializationBatch,\n} from \"../../containers/rematerialization\";\nimport { createRuntimeGroupMetadataAccess } from \"../groupMetadata/groupMetadataRuntime\";\nimport { commitCurrentGroupPolicyMutation } from \"../groupPolicy/commitCurrentGroupPolicyMutation\";\nimport { buildSetGroupContainerGrantPolicyRequest } from \"../groupPolicy/groupPolicyRequests\";\nimport type {\n createRuntimeCurrentGroupMutation,\n RuntimeCurrentGroupMutationContext,\n} from \"../principalMutations/runtimeCurrentGroupMutation\";\nimport { groupPolicyNameMismatch } from \"../principalPolicy/principalPolicyRequest\";\nimport type { createRuntimeCurrentSharePrincipalPolicy } from \"./currentSharePrincipalPolicy\";\nimport { GroupShareNameMismatchError } from \"./sharePrincipalPolicy\";\nimport type { shareRemoteContainerWithGroup } from \"./shareWithGroup\";\n\n/** Fresh mutation authority rechecks the chosen name before authoring a grant. */\nexport async function commitCurrentShareGrant(input: {\n readonly runtime: Parameters<\n typeof createRuntimeCurrentSharePrincipalPolicy\n >[0];\n readonly share: Parameters<typeof shareRemoteContainerWithGroup>[0];\n readonly recitationStillCurrent?: (() => boolean) | undefined;\n readonly mutate: NonNullable<\n ReturnType<typeof createRuntimeCurrentGroupMutation>\n >;\n}): ReturnType<typeof shareRemoteContainerWithGroup> {\n const share = input.share;\n const expectedName = share.expectedGroupName;\n if (expectedName === null)\n throw new Error(\n \"Minting a group grant requires the chosen group name; only a re-wrap of an existing signed grant may omit it\",\n );\n const signingKeyPair = share.signingKeyPair;\n if (!signingKeyPair)\n throw new Error(\n \"Container group share requires principal policy signing context\",\n );\n return input.mutate(\n {\n groupId: share.recipientGroupId,\n organizationId: share.author.organizationId,\n signerUserId: share.author.signerUserId,\n stillCurrent: share.stillCurrent ?? (() => true),\n },\n async (context) => {\n await assertCurrentShareGrantName(\n input.runtime,\n share,\n context,\n expectedName,\n );\n const request = await buildSetGroupContainerGrantPolicyRequest({\n ...context,\n accessLevel: share.accessLevel,\n containerId: share.containerId,\n signerUserId: share.author.signerUserId,\n signingFingerprint: share.author.signerKeyFingerprint,\n signingKeyPair,\n });\n const prepared: {\n batch?: PreparedPrincipalContainerRematerializationBatch;\n } = {};\n const response = await commitCurrentGroupPolicyMutation({\n apiClient: share.apiClient,\n context,\n groupId: share.recipientGroupId,\n organizationId: share.author.organizationId,\n request,\n signerUserId: share.author.signerUserId,\n signingFingerprint: share.author.signerKeyFingerprint,\n signingKeyPair,\n resolveTrustedUserIdentity: share.resolveTrustedUserIdentity,\n prepareContainerMutations: async (nextPolicy, preceding) => {\n prepared.batch = await prepareCurrentShareGrantBatch(\n share,\n context,\n { nextPolicy, preceding },\n input.recitationStillCurrent,\n );\n return prepared.batch;\n },\n });\n const index =\n prepared.batch?.plans.findIndex(\n (planned) => planned.plan.containerId === share.containerId,\n ) ?? -1;\n const plan = prepared.batch?.plans[index];\n const acknowledgement = response.containerMutations[index];\n if (!plan || !acknowledgement || !isSharePlan(plan))\n throw new Error(\"Container group share acknowledgement is incomplete\");\n return {\n containerKey: plan.containerKey,\n plan: plan.plan,\n response: acknowledgement,\n };\n },\n );\n}\n\nfunction isSharePlan(\n plan: PreparedPrincipalContainerRematerializationBatch[\"plans\"][number],\n): plan is MaterializedContainerSharePlan {\n return plan.plan.body.eventType === \"container.grant\";\n}\n\nasync function assertCurrentShareGrantName(\n runtime: Parameters<typeof createRuntimeCurrentSharePrincipalPolicy>[0],\n share: Parameters<typeof shareRemoteContainerWithGroup>[0],\n context: RuntimeCurrentGroupMutationContext,\n expectedName: string,\n) {\n const mismatch = await groupPolicyNameMismatch(\n context.currentPolicy,\n expectedName,\n createRuntimeGroupMetadataAccess(\n runtime,\n share.author.organizationId,\n context.stillCurrent,\n context.verifyMetadataContainer,\n ).readName,\n );\n if (mismatch)\n throw new GroupShareNameMismatchError(\n \"Container share group name does not match the signed group policy\",\n );\n assertProjectionVerificationCurrent(context.stillCurrent);\n}\n\nfunction prepareCurrentShareGrantBatch(\n share: Parameters<typeof shareRemoteContainerWithGroup>[0],\n context: RuntimeCurrentGroupMutationContext,\n {\n nextPolicy,\n preceding,\n }: Pick<\n Parameters<typeof preparePrincipalContainerRematerializationBatch>[0],\n \"nextPolicy\" | \"preceding\"\n >,\n recitationStillCurrent?: () => boolean,\n) {\n return preparePrincipalContainerRematerializationBatch({\n ...share,\n preceding,\n grants: [\n ...new Map(\n [...context.currentPolicy.currentGrants, ...nextPolicy.grants].map(\n (grant) => [grant.containerId, grant] as const,\n ),\n ).values(),\n ],\n groupId: share.recipientGroupId,\n nextPolicy,\n resolveAuthoredPolicyReferences: context.resolveAuthoredPolicyReferences,\n stillCurrent: context.stillCurrent,\n recitationStillCurrent,\n });\n}\n"]}
|