@tearleads/client-sdk 0.1.100 → 0.1.101

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.
@@ -1 +1 @@
1
- {"version":3,"file":"mutationFailures.js","sourceRoot":"","sources":["mutationFailures.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AAQxC,MAAM,UAAU,0BAA0B,CACxC,OAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAC1E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,6BAA6B,CACpC,OAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,gCAAgC,CAC5E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAiC;IAEjC,OAAO,CACL,0BAA0B,CAAC,OAAO,CAAC;QACnC,6BAA6B,CAAC,OAAO,CAAC,CACvC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,OAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG;QACtB,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAAC,WAAW,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC/C,OAAuC;IAEvC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG;QACtB,CAAC,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAAC,UAAU;YACzD,OAAO,CAAC,IAAI,KAAK,yBAAyB,CAAC,UAAU,CAAC,CACzD,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wCAAwC,CACtD,OAAuC;IAEvC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG;QACtB,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAAC,qBAAqB,CACtE,CAAC;AACJ,CAAC","sourcesContent":["import {\n CONTAINER_MUTATION_ERROR_CODES,\n CONTAINER_NOT_FOUND_ERROR_CODE,\n CONTAINER_UNAVAILABLE_ERROR_CODE,\n DOCUMENT_SYNC_ERROR_CODES,\n} from \"@tearleads/validators/response\";\nimport type { ContainerMutationSubmitFailure } from \"./types\";\n\ninterface ContainerBehaviorFailure {\n readonly code?: string | undefined;\n readonly status: number | null;\n}\n\nexport function isContainerNotFoundFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n failure.status === 404 && failure.code === CONTAINER_NOT_FOUND_ERROR_CODE\n );\n}\n\n/**\n * A mutation cited a container path element whose live row is gone: the\n * server retained its manifest head (so the reference resolved) but the\n * container was deleted before the commit. Container ids are immutable, so\n * this never heals by retrying the same request.\n */\nfunction isContainerUnavailableFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n failure.status === 409 && failure.code === CONTAINER_UNAVAILABLE_ERROR_CODE\n );\n}\n\n/**\n * Both server-verified proofs that a cited container no longer exists: the\n * coded projection 404 (fetched before the mutation) and the coded commit 409\n * (the container vanished between fetch and commit). Uncoded 404s and 409s\n * are excluded on purpose — they may be transient.\n */\nexport function isVanishedContainerFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n isContainerNotFoundFailure(failure) ||\n isContainerUnavailableFailure(failure)\n );\n}\n\n/**\n * The server refused a create or move for exceeding the readable path length.\n * Final: resubmitting the same request never succeeds.\n */\nexport function isContainerPathTooDeepFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n failure.status === 409 &&\n failure.code === CONTAINER_MUTATION_ERROR_CODES.pathTooDeep\n );\n}\n\nexport function isStaleParentContainerPathFailure(\n failure: ContainerMutationSubmitFailure,\n): boolean {\n return (\n failure.status === 409 &&\n (failure.code === CONTAINER_MUTATION_ERROR_CODES.stateStale ||\n failure.code === DOCUMENT_SYNC_ERROR_CODES.stateStale)\n );\n}\n\n/**\n * A create whose response was lost re-sends the same stable container id; the\n * server then reports that the container manifest already exists. That proves\n * the first attempt committed, so the caller can await remote hydration.\n *\n * A metadata-document conflict is deliberately excluded. The compound server\n * transaction can create the container and then roll everything back when the\n * metadata document already exists, so that code alone does not prove the\n * container exists remotely.\n */\nexport function isContainerManifestAlreadyExistsConflict(\n failure: ContainerMutationSubmitFailure,\n): boolean {\n return (\n failure.status === 409 &&\n failure.code === CONTAINER_MUTATION_ERROR_CODES.manifestAlreadyExists\n );\n}\n"]}
1
+ {"version":3,"file":"mutationFailures.js","sourceRoot":"","sources":["mutationFailures.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,EAC9B,gCAAgC,EAChC,yBAAyB,GAC1B,MAAM,gCAAgC,CAAC;AAQxC,MAAM,UAAU,0BAA0B,CACxC,OAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAC1E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAS,6BAA6B,CACpC,OAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,CAAC,IAAI,KAAK,gCAAgC,CAC5E,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAiC;IAEjC,OAAO,CACL,0BAA0B,CAAC,OAAO,CAAC;QACnC,6BAA6B,CAAC,OAAO,CAAC,CACvC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,6BAA6B,CAC3C,OAAiC;IAEjC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG;QACtB,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAAC,WAAW,CAC5D,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iCAAiC,CAC/C,OAAgE;IAEhE,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG;QACtB,CAAC,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAAC,UAAU;YACzD,OAAO,CAAC,IAAI,KAAK,yBAAyB,CAAC,UAAU,CAAC,CACzD,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,wCAAwC,CACtD,OAAuC;IAEvC,OAAO,CACL,OAAO,CAAC,MAAM,KAAK,GAAG;QACtB,OAAO,CAAC,IAAI,KAAK,8BAA8B,CAAC,qBAAqB,CACtE,CAAC;AACJ,CAAC","sourcesContent":["import {\n CONTAINER_MUTATION_ERROR_CODES,\n CONTAINER_NOT_FOUND_ERROR_CODE,\n CONTAINER_UNAVAILABLE_ERROR_CODE,\n DOCUMENT_SYNC_ERROR_CODES,\n} from \"@tearleads/validators/response\";\nimport type { ContainerMutationSubmitFailure } from \"./types\";\n\ninterface ContainerBehaviorFailure {\n readonly code?: string | undefined;\n readonly status: number | null;\n}\n\nexport function isContainerNotFoundFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n failure.status === 404 && failure.code === CONTAINER_NOT_FOUND_ERROR_CODE\n );\n}\n\n/**\n * A mutation cited a container path element whose live row is gone: the\n * server retained its manifest head (so the reference resolved) but the\n * container was deleted before the commit. Container ids are immutable, so\n * this never heals by retrying the same request.\n */\nfunction isContainerUnavailableFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n failure.status === 409 && failure.code === CONTAINER_UNAVAILABLE_ERROR_CODE\n );\n}\n\n/**\n * Both server-verified proofs that a cited container no longer exists: the\n * coded projection 404 (fetched before the mutation) and the coded commit 409\n * (the container vanished between fetch and commit). Uncoded 404s and 409s\n * are excluded on purpose — they may be transient.\n */\nexport function isVanishedContainerFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n isContainerNotFoundFailure(failure) ||\n isContainerUnavailableFailure(failure)\n );\n}\n\n/**\n * The server refused a create or move for exceeding the readable path length.\n * Final: resubmitting the same request never succeeds.\n */\nexport function isContainerPathTooDeepFailure(\n failure: ContainerBehaviorFailure,\n): boolean {\n return (\n failure.status === 409 &&\n failure.code === CONTAINER_MUTATION_ERROR_CODES.pathTooDeep\n );\n}\n\nexport function isStaleParentContainerPathFailure(\n failure: Pick<ContainerMutationSubmitFailure, \"code\" | \"status\">,\n): boolean {\n return (\n failure.status === 409 &&\n (failure.code === CONTAINER_MUTATION_ERROR_CODES.stateStale ||\n failure.code === DOCUMENT_SYNC_ERROR_CODES.stateStale)\n );\n}\n\n/**\n * A create whose response was lost re-sends the same stable container id; the\n * server then reports that the container manifest already exists. That proves\n * the first attempt committed, so the caller can await remote hydration.\n *\n * A metadata-document conflict is deliberately excluded. The compound server\n * transaction can create the container and then roll everything back when the\n * metadata document already exists, so that code alone does not prove the\n * container exists remotely.\n */\nexport function isContainerManifestAlreadyExistsConflict(\n failure: ContainerMutationSubmitFailure,\n): boolean {\n return (\n failure.status === 409 &&\n failure.code === CONTAINER_MUTATION_ERROR_CODES.manifestAlreadyExists\n );\n}\n"]}
@@ -91,6 +91,9 @@ export interface ContainerCreateApi {
91
91
  export interface ContainerShareApi extends ContainerReciteApi {
92
92
  getContainerWriterProjection(containerId: string): Promise<ContainerWriterProjectionResponse | null>;
93
93
  shareContainer(containerId: string, input: ContainerMutationRequest, options?: ContainerMutationRequestOptions): Promise<ContainerMutationResponse | null>;
94
+ /** Tells a stale path, which a fresh projection clears, from a refusal. */
95
+ shareContainerResult?(containerId: string, input: ContainerMutationRequest, options?: ContainerMutationRequestOptions): Promise<ContainerMutationSubmitResult<ContainerMutationResponse>>;
96
+ evictContainerWriterProjection?(containerId: string): void;
94
97
  }
95
98
  /**
96
99
  * A status-bearing rotation outcome. A refusal that names
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n AccessEvent,\n AccessManifest,\n ContainerAccessManifestState,\n ContainerCreateAccessEventBody,\n ContainerDirectGrant,\n ContainerGrantAccessEventBody,\n ContainerGrantPrincipalHead,\n ContainerKekKeyring,\n ContainerKekRecipientTarget,\n ContainerKeyEpoch,\n ContainerKeyWrap,\n ContainerMoveAccessEventBody,\n ContainerRekeyAccessEventBody,\n ContainerRevokeAccessEventBody,\n ContainerUserRecipientKey,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWire,\n ContainerCreateWithMetadataDocumentRequest,\n ContainerMutationRequest,\n ContainerRotationRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n ContainerCreateWithMetadataDocumentResponse,\n ContainerKekResponse,\n ContainerMutationResponse,\n ContainerRotationResponse,\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport type { ContainerMutationRequestOptions } from \"./mutationRequestOptions\";\nimport type { ContainerReciteApi } from \"./reciteApi\";\n\nexport interface ContainerMutationAuthor {\n organizationId: string;\n signerDeviceId: string;\n signerKeyFingerprint: string;\n signerPrivateKey: Uint8Array;\n signerUserId: string;\n}\n\nexport interface BuildContainerCreatePlanInput {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey: Uint8Array;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n /**\n * Optional group grant to bake into the\n * create manifest, wrapping the new container key to that principal in\n * addition to the normal parent-inheritance wrap. Used to birth a child\n * container that is directly readable by a group — e.g. the org public\n * metadata container granted to the reserved Members group. The principal's\n * verified policy must also be supplied via `principalPolicies` so the server\n * can derive the recipient target.\n */\n managedPrincipalGrant?:\n | {\n accessLevel: ContainerDirectGrant[\"accessLevel\"];\n principalEncapsulationPublicKey: string;\n principalHead: ContainerGrantPrincipalHead;\n }\n | undefined;\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies?: readonly PrincipalPolicyCurrentEvidence[] | undefined;\n signedAt?: string | undefined;\n}\n\nexport interface ContainerCreatePlan {\n body: ContainerCreateAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyEpochHash: string;\n keyTargetHash: string;\n manifest: AccessManifest;\n manifestHash: string;\n metadataDocumentId: string;\n parentContainerId: string | null;\n parentManifestHash: string | null;\n recipientTargets: ContainerKekRecipientTarget[];\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerCreatePlan {\n containerKey: Uint8Array;\n plan: ContainerCreatePlan;\n}\n\nexport interface ContainerCreatePlanContext\n extends BuildContainerCreatePlanInput {\n containerKeyPublicKey: string;\n containerId: string;\n containerKeyEpochId: string;\n eventId: string;\n metadataDocumentId: string;\n parent: ParentContainerCreateContext;\n signedAt: string;\n}\n\nexport interface ContainerMutationSubmitFailure {\n readonly code?: string | undefined;\n readonly message: string;\n readonly ok: false;\n readonly report: () => void;\n readonly stalePrincipalHeads?:\n | readonly ReferencedPrincipalStateResponse[]\n | undefined;\n readonly status: number | null;\n}\n\nexport type ContainerMutationSubmitResult<T> =\n | {\n readonly data: T;\n readonly ok: true;\n }\n | ContainerMutationSubmitFailure;\n\nexport interface ContainerCreateApi {\n createContainerResult(\n input: ContainerMutationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerMutationSubmitResult<ContainerMutationResponse>>;\n createContainerWithMetadataDocumentResult(\n input: ContainerCreateWithMetadataDocumentRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<\n ContainerMutationSubmitResult<ContainerCreateWithMetadataDocumentResponse>\n >;\n evictContainerWriterProjection(containerId: string): void;\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport interface ContainerShareApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n shareContainer(\n containerId: string,\n input: ContainerMutationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerMutationResponse | null>;\n}\n\n/**\n * A status-bearing rotation outcome. A refusal that names\n * `requiredContainerIds` is answerable: sign those descendant rekeys and\n * resubmit with them carried.\n */\nexport type ContainerRotationResult =\n | { readonly ok: true; readonly data: ContainerRotationResponse }\n | {\n readonly ok: false;\n readonly code?: string | undefined;\n /** Surface a failure that was submitted with `reportErrors: false`. */\n readonly report?: (() => void) | undefined;\n readonly requiredContainerIds?: readonly string[] | undefined;\n readonly status: number | null;\n };\n\nexport interface ContainerMoveApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n moveContainer(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResponse | null>;\n /** Optional status-bearing variant; without it nothing can be carried. */\n moveContainerResult?(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResult>;\n}\n\nexport interface ContainerRevokeApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n revokeContainer(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResponse | null>;\n /** Optional status-bearing variant; without it nothing can be carried. */\n revokeContainerResult?(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResult>;\n}\n\nexport interface CreateRemoteContainerResult {\n containerKey: Uint8Array;\n containerId: string;\n metadataDocumentId: string;\n plan: ContainerCreatePlan;\n response: ContainerMutationResponse;\n}\n\nexport interface ContainerSharePlan {\n body: ContainerGrantAccessEventBody;\n /** The unchanged epoch's stored keyring, echoed back by the server. */\n previousKeyring?: Record<string, unknown> | null | undefined;\n containerId: string;\n event: AccessEvent;\n eventHash: string;\n grant: ContainerDirectGrant;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n recipientTarget: ContainerKekRecipientTarget;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerSharePlan {\n containerKey: Uint8Array;\n plan: ContainerSharePlan;\n}\n\nexport interface ContainerRevokePlan {\n body: ContainerRevokeAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerRevokePlan {\n containerKey: Uint8Array;\n plan: ContainerRevokePlan;\n}\n\nexport interface ContainerRekeyPlan {\n body: ContainerRekeyAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerRekeyPlan {\n containerKey: Uint8Array;\n plan: ContainerRekeyPlan;\n writerProjection: ContainerWriterProjectionResponse;\n}\n\nexport interface ContainerRekeyApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n rekeyContainer(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResponse | null>;\n /** Optional status-bearing variant; see DocumentSyncApi. */\n rekeyContainerResult?(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResult>;\n}\n\nexport interface ContainerMovePlan {\n body: ContainerMoveAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerMovePlan {\n containerKey: Uint8Array;\n plan: ContainerMovePlan;\n}\n\nexport interface BuildMaterializedContainerMovePlanInput {\n author: ContainerMutationAuthor;\n containerKeyEpochId?: string | undefined;\n destinationParentProjection: ContainerWriterProjectionResponse;\n eventId?: string | undefined;\n execSql: ExecSql;\n previousProjection: ContainerWriterProjectionResponse;\n signedAt?: string | undefined;\n targetSecretKey: Uint8Array;\n}\n\nexport interface ParentContainerCreateContext {\n manifest: ContainerWriterProjectionResponse[\"path\"][number];\n kek: ContainerKekResponse;\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["types.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n AccessEvent,\n AccessManifest,\n ContainerAccessManifestState,\n ContainerCreateAccessEventBody,\n ContainerDirectGrant,\n ContainerGrantAccessEventBody,\n ContainerGrantPrincipalHead,\n ContainerKekKeyring,\n ContainerKekRecipientTarget,\n ContainerKeyEpoch,\n ContainerKeyWrap,\n ContainerMoveAccessEventBody,\n ContainerRekeyAccessEventBody,\n ContainerRevokeAccessEventBody,\n ContainerUserRecipientKey,\n} from \"@tearleads/crypto\";\nimport type {\n AccessManifestBundleWire,\n ContainerCreateWithMetadataDocumentRequest,\n ContainerMutationRequest,\n ContainerRotationRequest,\n} from \"@tearleads/validators/request\";\nimport type {\n ContainerCreateWithMetadataDocumentResponse,\n ContainerKekResponse,\n ContainerMutationResponse,\n ContainerRotationResponse,\n ContainerWriterProjectionResponse,\n ReferencedPrincipalStateResponse,\n} from \"@tearleads/validators/response\";\nimport type { PrincipalPolicyCurrentEvidence } from \"../../principals/principalPolicyEvidence\";\nimport type { ExecSql } from \"../../sqlite/sqlSchema\";\nimport type { ContainerMutationRequestOptions } from \"./mutationRequestOptions\";\nimport type { ContainerReciteApi } from \"./reciteApi\";\n\nexport interface ContainerMutationAuthor {\n organizationId: string;\n signerDeviceId: string;\n signerKeyFingerprint: string;\n signerPrivateKey: Uint8Array;\n signerUserId: string;\n}\n\nexport interface BuildContainerCreatePlanInput {\n author: ContainerMutationAuthor;\n containerId?: string | undefined;\n containerKey: Uint8Array;\n containerKeyEpochId?: string | undefined;\n eventId?: string | undefined;\n /**\n * Optional group grant to bake into the\n * create manifest, wrapping the new container key to that principal in\n * addition to the normal parent-inheritance wrap. Used to birth a child\n * container that is directly readable by a group — e.g. the org public\n * metadata container granted to the reserved Members group. The principal's\n * verified policy must also be supplied via `principalPolicies` so the server\n * can derive the recipient target.\n */\n managedPrincipalGrant?:\n | {\n accessLevel: ContainerDirectGrant[\"accessLevel\"];\n principalEncapsulationPublicKey: string;\n principalHead: ContainerGrantPrincipalHead;\n }\n | undefined;\n metadataDocumentId?: string | undefined;\n systemSlot?: string | null | undefined;\n parentProjection: ContainerWriterProjectionResponse;\n principalPolicies?: readonly PrincipalPolicyCurrentEvidence[] | undefined;\n signedAt?: string | undefined;\n}\n\nexport interface ContainerCreatePlan {\n body: ContainerCreateAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyEpochHash: string;\n keyTargetHash: string;\n manifest: AccessManifest;\n manifestHash: string;\n metadataDocumentId: string;\n parentContainerId: string | null;\n parentManifestHash: string | null;\n recipientTargets: ContainerKekRecipientTarget[];\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerCreatePlan {\n containerKey: Uint8Array;\n plan: ContainerCreatePlan;\n}\n\nexport interface ContainerCreatePlanContext\n extends BuildContainerCreatePlanInput {\n containerKeyPublicKey: string;\n containerId: string;\n containerKeyEpochId: string;\n eventId: string;\n metadataDocumentId: string;\n parent: ParentContainerCreateContext;\n signedAt: string;\n}\n\nexport interface ContainerMutationSubmitFailure {\n readonly code?: string | undefined;\n readonly message: string;\n readonly ok: false;\n readonly report: () => void;\n readonly stalePrincipalHeads?:\n | readonly ReferencedPrincipalStateResponse[]\n | undefined;\n readonly status: number | null;\n}\n\nexport type ContainerMutationSubmitResult<T> =\n | {\n readonly data: T;\n readonly ok: true;\n }\n | ContainerMutationSubmitFailure;\n\nexport interface ContainerCreateApi {\n createContainerResult(\n input: ContainerMutationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerMutationSubmitResult<ContainerMutationResponse>>;\n createContainerWithMetadataDocumentResult(\n input: ContainerCreateWithMetadataDocumentRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<\n ContainerMutationSubmitResult<ContainerCreateWithMetadataDocumentResponse>\n >;\n evictContainerWriterProjection(containerId: string): void;\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n}\n\nexport interface ContainerShareApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n shareContainer(\n containerId: string,\n input: ContainerMutationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerMutationResponse | null>;\n /** Tells a stale path, which a fresh projection clears, from a refusal. */\n shareContainerResult?(\n containerId: string,\n input: ContainerMutationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerMutationSubmitResult<ContainerMutationResponse>>;\n evictContainerWriterProjection?(containerId: string): void;\n}\n\n/**\n * A status-bearing rotation outcome. A refusal that names\n * `requiredContainerIds` is answerable: sign those descendant rekeys and\n * resubmit with them carried.\n */\nexport type ContainerRotationResult =\n | { readonly ok: true; readonly data: ContainerRotationResponse }\n | {\n readonly ok: false;\n readonly code?: string | undefined;\n /** Surface a failure that was submitted with `reportErrors: false`. */\n readonly report?: (() => void) | undefined;\n readonly requiredContainerIds?: readonly string[] | undefined;\n readonly status: number | null;\n };\n\nexport interface ContainerMoveApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n moveContainer(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResponse | null>;\n /** Optional status-bearing variant; without it nothing can be carried. */\n moveContainerResult?(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResult>;\n}\n\nexport interface ContainerRevokeApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n revokeContainer(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResponse | null>;\n /** Optional status-bearing variant; without it nothing can be carried. */\n revokeContainerResult?(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResult>;\n}\n\nexport interface CreateRemoteContainerResult {\n containerKey: Uint8Array;\n containerId: string;\n metadataDocumentId: string;\n plan: ContainerCreatePlan;\n response: ContainerMutationResponse;\n}\n\nexport interface ContainerSharePlan {\n body: ContainerGrantAccessEventBody;\n /** The unchanged epoch's stored keyring, echoed back by the server. */\n previousKeyring?: Record<string, unknown> | null | undefined;\n containerId: string;\n event: AccessEvent;\n eventHash: string;\n grant: ContainerDirectGrant;\n keyEpoch: ContainerKeyEpoch;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n recipientTarget: ContainerKekRecipientTarget;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerSharePlan {\n containerKey: Uint8Array;\n plan: ContainerSharePlan;\n}\n\nexport interface ContainerRevokePlan {\n body: ContainerRevokeAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerRevokePlan {\n containerKey: Uint8Array;\n plan: ContainerRevokePlan;\n}\n\nexport interface ContainerRekeyPlan {\n body: ContainerRekeyAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n userRecipientKeys: ContainerUserRecipientKey[];\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerRekeyPlan {\n containerKey: Uint8Array;\n plan: ContainerRekeyPlan;\n writerProjection: ContainerWriterProjectionResponse;\n}\n\nexport interface ContainerRekeyApi extends ContainerReciteApi {\n getContainerWriterProjection(\n containerId: string,\n ): Promise<ContainerWriterProjectionResponse | null>;\n rekeyContainer(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResponse | null>;\n /** Optional status-bearing variant; see DocumentSyncApi. */\n rekeyContainerResult?(\n containerId: string,\n input: ContainerRotationRequest,\n options?: ContainerMutationRequestOptions,\n ): Promise<ContainerRotationResult>;\n}\n\nexport interface ContainerMovePlan {\n body: ContainerMoveAccessEventBody;\n containerId: string;\n containerKeyEpochId: string;\n event: AccessEvent;\n eventHash: string;\n keyEpoch: ContainerKeyEpoch;\n keyring: ContainerKekKeyring;\n manifest: AccessManifest;\n manifestHash: string;\n previousManifest: AccessManifestBundleWire;\n request: ContainerMutationRequest;\n state: ContainerAccessManifestState;\n wraps: ContainerKeyWrap[];\n}\n\nexport interface MaterializedContainerMovePlan {\n containerKey: Uint8Array;\n plan: ContainerMovePlan;\n}\n\nexport interface BuildMaterializedContainerMovePlanInput {\n author: ContainerMutationAuthor;\n containerKeyEpochId?: string | undefined;\n destinationParentProjection: ContainerWriterProjectionResponse;\n eventId?: string | undefined;\n execSql: ExecSql;\n previousProjection: ContainerWriterProjectionResponse;\n signedAt?: string | undefined;\n targetSecretKey: Uint8Array;\n}\n\nexport interface ParentContainerCreateContext {\n manifest: ContainerWriterProjectionResponse[\"path\"][number];\n kek: ContainerKekResponse;\n}\n"]}
@@ -3060,6 +3060,8 @@ export declare class ApiClient {
3060
3060
  };
3061
3061
  systemSlot?: string | null | undefined;
3062
3062
  } | null>;
3063
+ /** Status-bearing share: a stale path is retryable, a refusal is not. */
3064
+ shareContainerResult(containerId: string, input: ContainerMutationRequest, options?: RequestResultOptions): Promise<RequestResult<ContainerMutationResponse>>;
3063
3065
  revokeContainer(containerId: string, input: ContainerRotationRequest, options?: RequestResultOptions): Promise<{
3064
3066
  createdAt: string;
3065
3067
  manifestHead: {
@@ -31,6 +31,7 @@ import { CitingProjectionCache, evictWriterProjectionsCiting, } from "./writerPr
31
31
  import { primeWriterProjectionSlot } from "./writerProjectionPrime.js";
32
32
  import { writerProjectionRequests } from "./writerProjectionRequests.js";
33
33
  /** The rotations that may carry descendant rekeys, each with its operation. */
34
+ const dataOrNull = (result) => result.ok ? result.data : null;
34
35
  const CONTAINER_ROTATIONS = {
35
36
  move: { operation: moveContainerOperation, route: containerMove },
36
37
  rekey: { operation: rekeyContainerOperation, route: containerRekey },
@@ -580,19 +581,22 @@ export class ApiClient {
580
581
  return this.requestResult(containerCreateWithMetadataDocument.path, containerCreateWithMetadataDocument.isResponse, containerCreateWithMetadataDocument.method, JSON.stringify(input), options, createContainerWithMetadataDocumentOperation);
581
582
  }
582
583
  shareContainer(containerId, input, options = {}) {
583
- return this.request(containerShare.path(containerId), containerShare.isResponse, containerShare.method, JSON.stringify(input), options, shareContainerOperation).finally(() => {
584
+ return this.shareContainerResult(containerId, input, options).then(dataOrNull);
585
+ }
586
+ /** Status-bearing share: a stale path is retryable, a refusal is not. */
587
+ async shareContainerResult(containerId, input, options = {}) {
588
+ try {
589
+ return await this.requestResult(containerShare.path(containerId), containerShare.isResponse, containerShare.method, JSON.stringify(input), options, shareContainerOperation);
590
+ }
591
+ finally {
584
592
  this.clearWriterProjectionCaches();
585
- });
593
+ }
586
594
  }
587
595
  revokeContainer(containerId, input, options = {}) {
588
- return this.request(containerRevoke.path(containerId), containerRevoke.isResponse, containerRevoke.method, JSON.stringify(input), options, revokeContainerOperation).finally(() => {
589
- this.clearWriterProjectionCaches();
590
- });
596
+ return this.rotationResult("revoke", containerId, input, options).then(dataOrNull);
591
597
  }
592
598
  rekeyContainer(containerId, input, options = {}) {
593
- return this.request(containerRekey.path(containerId), containerRekey.isResponse, containerRekey.method, JSON.stringify(input), options, rekeyContainerOperation).finally(() => {
594
- this.clearWriterProjectionCaches();
595
- });
599
+ return this.rotationResult("rekey", containerId, input, options).then(dataOrNull);
596
600
  }
597
601
  /**
598
602
  * Status-bearing rotations: a caller that must tell a permanent refusal (403
@@ -623,9 +627,7 @@ export class ApiClient {
623
627
  return this.request(containerRecite.path(containerId), containerRecite.isResponse, containerRecite.method, JSON.stringify(input), options, reciteContainerOperation).finally(() => this.clearWriterProjectionCaches());
624
628
  }
625
629
  moveContainer(containerId, input, options = {}) {
626
- return this.request(containerMove.path(containerId), containerMove.isResponse, containerMove.method, JSON.stringify(input), options, moveContainerOperation).finally(() => {
627
- this.clearWriterProjectionCaches();
628
- });
630
+ return this.rotationResult("move", containerId, input, options).then(dataOrNull);
629
631
  }
630
632
  async deleteContainer(containerId, options = {}) {
631
633
  const result = await this.deleteContainerResult(containerId, options);