@tearleads/client-sdk 0.1.105 → 0.1.106
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/organizations/index.js +5 -2
- package/client/organizations/index.js.map +1 -1
- package/client/organizations/organizationMemberships.js +26 -18
- package/client/organizations/organizationMemberships.js.map +1 -1
- package/client/organizations/organizationReadModels.d.ts +9 -4
- package/client/organizations/organizationReadModels.js +20 -9
- package/client/organizations/organizationReadModels.js.map +1 -1
- package/internal/api-client/ApiClient.d.ts +7 -0
- package/internal/crypto/organizationLeaveRequest.d.ts +1 -1
- package/internal/crypto/organizationLeaveRequest.js +9 -2
- package/internal/crypto/organizationLeaveRequest.js.map +1 -1
- package/internal/validators/operation/organizationMemberships.d.ts +7 -0
- package/internal/validators/operation/organizations.d.ts +56 -0
- package/internal/validators/response/organization.d.ts +91 -0
- package/internal/validators/response/organizationReadModel.d.ts +70 -0
- package/internal/validators/util/index.d.ts +1 -1
- package/internal/validators/util/index.js.map +1 -1
- package/internal/validators/util/organizationLeaveRequest.d.ts +25 -2
- package/internal/validators/util/organizationLeaveRequest.js +19 -3
- package/internal/validators/util/organizationLeaveRequest.js.map +1 -1
- package/package.json +1 -1
- package/workflows/organizations/memberships/leaveRequest.d.ts +6 -2
- package/workflows/organizations/memberships/leaveRequest.js +20 -5
- package/workflows/organizations/memberships/leaveRequest.js.map +1 -1
- package/workflows/organizations/memberships/leaveRequestMembersEvidence.js +80 -0
- package/workflows/organizations/memberships/leaveRequestMembersEvidence.js.map +1 -0
- package/workflows/organizations/memberships/leaveRequestMembership.d.ts +24 -0
- package/workflows/organizations/memberships/leaveRequestMembership.js +65 -0
- package/workflows/organizations/memberships/leaveRequestMembership.js.map +1 -0
- package/workflows/organizations/memberships/leaveRequestVerification.d.ts +15 -7
- package/workflows/organizations/memberships/leaveRequestVerification.js +18 -11
- package/workflows/organizations/memberships/leaveRequestVerification.js.map +1 -1
|
@@ -3,7 +3,7 @@ import { cancelStripeSubscription, checkNativePurchaseEligibility, claimNativeOr
|
|
|
3
3
|
import { createOrganizationDataUsageCoordinator, } from "./organizationDataUsage.js";
|
|
4
4
|
import { loadOrganizationGroupPresentationDetails } from "./organizationGroupPresentation.js";
|
|
5
5
|
import { createOrganizationMemberships, } from "./organizationMemberships.js";
|
|
6
|
-
import { createOrganizationReadModelCoordinator,
|
|
6
|
+
import { createOrganizationReadModelCoordinator, leaveRequestVerifier, } from "./organizationReadModels.js";
|
|
7
7
|
import { authenticatedOrganizationId, runForOrganization, } from "./organizationWorkflowRuntime.js";
|
|
8
8
|
import { abandonPendingOrganizationPolicyMutation, discardUnreadableOrganizationPolicyMutation, readPendingOrganizationPolicyMutation, retryPendingOrganizationPolicyMutation, } from "./principalMutationRecovery.js";
|
|
9
9
|
import { currentOrganizationMutation } from "./principalMutationScope.js";
|
|
@@ -185,7 +185,10 @@ class OrganizationsService {
|
|
|
185
185
|
// Callers store this response as directory state, so its leave request
|
|
186
186
|
// passes the same check as one read from the read model.
|
|
187
187
|
return (user &&
|
|
188
|
-
withVerifiedDirectoryUser(organizationId, user,
|
|
188
|
+
withVerifiedDirectoryUser(organizationId, user, leaveRequestVerifier(this.runtimeService, runtime, {
|
|
189
|
+
organizationId,
|
|
190
|
+
userId: runtime.auth.userId ?? "",
|
|
191
|
+
})));
|
|
189
192
|
}
|
|
190
193
|
updateProfile(profileDocumentId) {
|
|
191
194
|
const runtime = this.runtimeService.workflowInput();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NativeSubscriptionStore } from \"@tearleads/validators/billing\";\nimport { runWithSecurityIncidentReporting } from \"../../data/keyingProjectionVerification/error\";\nimport {\n cancelStripeSubscription,\n checkNativePurchaseEligibility,\n claimNativeOrganizationSubscription,\n createStripeCheckout,\n createStripeCheckoutSession,\n importOrganizationUser,\n listLocalOrganizations,\n loadOrganizationBilling,\n loadOrganizationBillingHistory,\n loadOrganizationBillingManagementUrl,\n loadStripeCheckoutOptions,\n startOrganizationTrial,\n updateOrganizationProfile,\n updateOrganizationRosterEntry,\n withVerifiedDirectoryUser,\n} from \"../../workflows/organizations\";\nimport type { ContainerContents } from \"../containerContents\";\nimport type { InternalRuntime } from \"../runtime/workflowRuntime\";\nimport {\n createOrganizationDataUsageCoordinator,\n type OrganizationDataUsageCoordinator,\n} from \"./organizationDataUsage\";\nimport { loadOrganizationGroupPresentationDetails } from \"./organizationGroupPresentation\";\nimport {\n createOrganizationMemberships,\n type OrganizationContentReconciler,\n type OrganizationMemberships,\n} from \"./organizationMemberships\";\nimport {\n createOrganizationReadModelCoordinator,\n leaveRequestSignerResolver,\n type OrganizationReadModelCoordinator,\n} from \"./organizationReadModels\";\nimport type { Organizations } from \"./organizationsTypes\";\nimport {\n authenticatedOrganizationId,\n runForOrganization,\n} from \"./organizationWorkflowRuntime\";\nimport {\n type AbandonOrganizationPolicyMutationInput,\n abandonPendingOrganizationPolicyMutation,\n type DiscardUnreadableOrganizationPolicyMutationInput,\n discardUnreadableOrganizationPolicyMutation,\n readPendingOrganizationPolicyMutation,\n retryPendingOrganizationPolicyMutation,\n} from \"./principalMutationRecovery\";\nimport { currentOrganizationMutation } from \"./principalMutationScope\";\nimport {\n type AddOrganizationGroupUserInput,\n addUserToOrganizationGroup,\n createGroupForOrganization,\n deleteGroupForOrganization,\n type OrganizationGrantRef,\n type RemoveOrganizationGroupUserInput,\n removeUserFromOrganizationGroup,\n revokeOrganizationGrant,\n} from \"./principalMutations\";\n\nexport type {\n ImportedOrganizationUser,\n LocalOrganizationSummary,\n OrganizationBilling,\n OrganizationBillingHistory,\n OrganizationBillingHistoryEntry,\n OrganizationBillingManagementUrl,\n OrganizationBillingView,\n OrganizationContainerGrant,\n OrganizationContainerGrants,\n OrganizationDataUsage,\n OrganizationDirectory,\n OrganizationDirectoryAndGroups,\n OrganizationDirectoryUser,\n OrganizationGroupContainer,\n OrganizationGroupContainers,\n OrganizationGroupDetails,\n OrganizationGroupMember,\n OrganizationGroupMembers,\n OrganizationGroupPolicyHistory,\n OrganizationGroupSummary,\n OrganizationLeaveRequestResult,\n OrganizationMembership,\n OrganizationPolicyGrantChange,\n OrganizationPolicyGroupChange,\n OrganizationPolicyHistory,\n OrganizationPolicyHistoryEntry,\n OrganizationProfile,\n OrganizationSyncPauseResult,\n OrganizationUserDetail,\n} from \"../../workflows/organizations\";\nexport type {\n OrganizationContentReconciler,\n OrganizationMemberships,\n} from \"./organizationMemberships\";\nexport type {\n OrganizationGroupMutationReceipt,\n Organizations,\n} from \"./organizationsTypes\";\nexport type {\n AbandonOrganizationPolicyMutationInput,\n DiscardUnreadableOrganizationPolicyMutationInput,\n} from \"./principalMutationRecovery\";\nexport type {\n AddOrganizationGroupUserInput,\n OrganizationGrantRef,\n RemoveOrganizationGroupUserInput,\n} from \"./principalMutations\";\n\nexport function createOrganizations(\n runtime: InternalRuntime,\n containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n): Organizations {\n return new OrganizationsService(runtime, containerContents, openReconciler);\n}\n\nclass OrganizationsService implements Organizations {\n readonly memberships: OrganizationMemberships;\n private readonly dataUsageCoordinator: OrganizationDataUsageCoordinator;\n private readonly readModelCoordinator: OrganizationReadModelCoordinator;\n\n constructor(\n private readonly runtimeService: InternalRuntime,\n private readonly containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n ) {\n this.dataUsageCoordinator = createOrganizationDataUsageCoordinator(\n this.runtimeService,\n );\n this.readModelCoordinator = createOrganizationReadModelCoordinator(\n this.runtimeService,\n );\n this.memberships = createOrganizationMemberships(\n this.runtimeService,\n this.containerContents,\n openReconciler,\n );\n }\n\n async addUserToGroup(input: AddOrganizationGroupUserInput) {\n return addUserToOrganizationGroup({\n ...input,\n containerContents: this.containerContents,\n readModelCoordinator: this.readModelCoordinator,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n readPendingPolicyMutation(organizationId: string) {\n return readPendingOrganizationPolicyMutation(\n this.runtimeService,\n organizationId,\n );\n }\n\n discardUnreadablePolicyMutation(\n input: DiscardUnreadableOrganizationPolicyMutationInput,\n ) {\n return discardUnreadableOrganizationPolicyMutation(\n this.runtimeService,\n input,\n );\n }\n\n retryPendingPolicyMutation(organizationId: string) {\n return retryPendingOrganizationPolicyMutation(\n this.runtimeService,\n organizationId,\n );\n }\n\n abandonPendingPolicyMutation(input: AbandonOrganizationPolicyMutationInput) {\n return abandonPendingOrganizationPolicyMutation(this.runtimeService, input);\n }\n\n createGroup(name: string) {\n return createGroupForOrganization({\n name,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n deleteGroup(groupId: string) {\n return deleteGroupForOrganization({\n groupId,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n importUserById(userId: string) {\n const runtime = this.runtimeService.workflowInput();\n return importOrganizationUser({\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n userId,\n });\n }\n\n loadBilling() {\n return runForOrganization(this.runtimeService, loadOrganizationBilling);\n }\n\n loadBillingForOrganization(organizationId: string) {\n // Gated on an authenticated session rather than on the target being the\n // active org. The server still enforces membership, so an org the caller\n // cannot reach resolves to `null`.\n return runForOrganization(\n this.runtimeService,\n loadOrganizationBilling,\n organizationId,\n );\n }\n\n loadBillingHistory() {\n return runForOrganization(\n this.runtimeService,\n loadOrganizationBillingHistory,\n );\n }\n\n loadBillingManagementUrl() {\n return runForOrganization(\n this.runtimeService,\n loadOrganizationBillingManagementUrl,\n );\n }\n\n loadStripeCheckoutOptions(organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n loadStripeCheckoutOptions,\n organizationId,\n );\n }\n\n createStripeCheckout(organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n createStripeCheckout,\n organizationId,\n );\n }\n\n createStripeCheckoutSession(returnUrl: string, organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n (input) => createStripeCheckoutSession({ ...input, returnUrl }),\n organizationId,\n );\n }\n\n cancelStripeSubscription() {\n return runForOrganization(this.runtimeService, cancelStripeSubscription);\n }\n\n claimNativeSubscription(\n organizationId: string,\n store: NativeSubscriptionStore,\n ) {\n return runForOrganization(\n this.runtimeService,\n (input) => claimNativeOrganizationSubscription({ ...input, store }),\n organizationId,\n );\n }\n\n checkNativePurchaseEligibility(\n organizationId: string,\n store: NativeSubscriptionStore,\n ) {\n return runForOrganization(\n this.runtimeService,\n (input) => checkNativePurchaseEligibility({ ...input, store }),\n organizationId,\n );\n }\n\n loadDataUsage() {\n return this.dataUsageCoordinator.reconcile();\n }\n\n loadLocalDataUsage() {\n return this.dataUsageCoordinator.loadLocal();\n }\n\n loadDirectoryAndGroups() {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: runtime.auth.organizationId,\n objectKind: \"principal\",\n operation: \"organization.read_model.reconcile\",\n organizationId: runtime.auth.organizationId,\n },\n () => this.readModelCoordinator.reconcile(),\n );\n }\n\n loadDirectoryAndGroupsAfterMutation() {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: runtime.auth.organizationId,\n objectKind: \"principal\",\n operation: \"organization.read_model.reconcile_after_mutation\",\n organizationId: runtime.auth.organizationId,\n },\n () => this.readModelCoordinator.reconcileAfterMutation(),\n );\n }\n\n loadLocalDirectoryAndGroups() {\n return this.readModelCoordinator.loadLocal();\n }\n\n loadGroupMembers(groupId: string) {\n const runtime = this.runtimeService.workflowInput();\n const organizationId = authenticatedOrganizationId(runtime);\n if (!organizationId || groupId.length === 0) {\n return Promise.resolve(null);\n }\n\n return runtime.apiClient.listOrganizationGroupMembers(\n organizationId,\n groupId,\n );\n }\n\n loadGroupPresentationDetails(groupId: string, beforeVersion?: number) {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: groupId,\n objectKind: \"principal\",\n operation: \"group.presentation.load\",\n organizationId: runtime.auth.organizationId,\n },\n () =>\n loadOrganizationGroupPresentationDetails({\n groupId,\n beforeVersion,\n readModelCoordinator: this.readModelCoordinator,\n runtime,\n }),\n );\n }\n\n loadGrants() {\n return this.readModelCoordinator.loadLocalGrants();\n }\n\n loadGroupContainers(groupId: string) {\n return this.readModelCoordinator.loadLocalGroupContainers(groupId);\n }\n\n listLocalOrganizations() {\n const runtime = this.runtimeService.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") {\n return Promise.resolve([]);\n }\n\n return listLocalOrganizations({ execSql: runtime.infra.execSql });\n }\n\n loadPolicyHistory(beforeVersion?: number) {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: runtime.auth.organizationId,\n objectKind: \"principal\",\n operation: \"organization.policy_history.load\",\n organizationId: runtime.auth.organizationId,\n },\n () =>\n this.readModelCoordinator.loadOrganizationPolicyHistory(\n undefined,\n beforeVersion,\n ),\n );\n }\n\n loadUserDetail(userId: string) {\n return this.readModelCoordinator.loadLocalUserDetail(userId);\n }\n\n async updateRosterEntry(userId: string, profileDocumentId: string | null) {\n const runtime = this.runtimeService.workflowInput();\n const organizationId = authenticatedOrganizationId(runtime);\n if (!organizationId || userId.length === 0) {\n return null;\n }\n\n const user = await updateOrganizationRosterEntry({\n apiClient: runtime.apiClient,\n organizationId,\n profileDocumentId,\n userId,\n });\n // Callers store this response as directory state, so its leave request\n // passes the same check as one read from the read model.\n return (\n user &&\n withVerifiedDirectoryUser(\n organizationId,\n user,\n leaveRequestSignerResolver(this.runtimeService, runtime),\n )\n );\n }\n\n updateProfile(profileDocumentId: string | null) {\n const runtime = this.runtimeService.workflowInput();\n const organizationId = authenticatedOrganizationId(runtime);\n if (!organizationId) {\n return Promise.resolve(null);\n }\n\n return updateOrganizationProfile({\n apiClient: runtime.apiClient,\n organizationId,\n profileDocumentId,\n });\n }\n\n async removeUserFromGroup(input: RemoveOrganizationGroupUserInput) {\n return removeUserFromOrganizationGroup({\n ...input,\n containerContents: this.containerContents,\n readModelCoordinator: this.readModelCoordinator,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n async revokeGrant(grant: OrganizationGrantRef) {\n return revokeOrganizationGrant({\n ...grant,\n containerContents: this.containerContents,\n readModelCoordinator: this.readModelCoordinator,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n startTrial(organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n startOrganizationTrial,\n organizationId,\n );\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { NativeSubscriptionStore } from \"@tearleads/validators/billing\";\nimport { runWithSecurityIncidentReporting } from \"../../data/keyingProjectionVerification/error\";\nimport {\n cancelStripeSubscription,\n checkNativePurchaseEligibility,\n claimNativeOrganizationSubscription,\n createStripeCheckout,\n createStripeCheckoutSession,\n importOrganizationUser,\n listLocalOrganizations,\n loadOrganizationBilling,\n loadOrganizationBillingHistory,\n loadOrganizationBillingManagementUrl,\n loadStripeCheckoutOptions,\n startOrganizationTrial,\n updateOrganizationProfile,\n updateOrganizationRosterEntry,\n withVerifiedDirectoryUser,\n} from \"../../workflows/organizations\";\nimport type { ContainerContents } from \"../containerContents\";\nimport type { InternalRuntime } from \"../runtime/workflowRuntime\";\nimport {\n createOrganizationDataUsageCoordinator,\n type OrganizationDataUsageCoordinator,\n} from \"./organizationDataUsage\";\nimport { loadOrganizationGroupPresentationDetails } from \"./organizationGroupPresentation\";\nimport {\n createOrganizationMemberships,\n type OrganizationContentReconciler,\n type OrganizationMemberships,\n} from \"./organizationMemberships\";\nimport {\n createOrganizationReadModelCoordinator,\n leaveRequestVerifier,\n type OrganizationReadModelCoordinator,\n} from \"./organizationReadModels\";\nimport type { Organizations } from \"./organizationsTypes\";\nimport {\n authenticatedOrganizationId,\n runForOrganization,\n} from \"./organizationWorkflowRuntime\";\nimport {\n type AbandonOrganizationPolicyMutationInput,\n abandonPendingOrganizationPolicyMutation,\n type DiscardUnreadableOrganizationPolicyMutationInput,\n discardUnreadableOrganizationPolicyMutation,\n readPendingOrganizationPolicyMutation,\n retryPendingOrganizationPolicyMutation,\n} from \"./principalMutationRecovery\";\nimport { currentOrganizationMutation } from \"./principalMutationScope\";\nimport {\n type AddOrganizationGroupUserInput,\n addUserToOrganizationGroup,\n createGroupForOrganization,\n deleteGroupForOrganization,\n type OrganizationGrantRef,\n type RemoveOrganizationGroupUserInput,\n removeUserFromOrganizationGroup,\n revokeOrganizationGrant,\n} from \"./principalMutations\";\n\nexport type {\n ImportedOrganizationUser,\n LocalOrganizationSummary,\n OrganizationBilling,\n OrganizationBillingHistory,\n OrganizationBillingHistoryEntry,\n OrganizationBillingManagementUrl,\n OrganizationBillingView,\n OrganizationContainerGrant,\n OrganizationContainerGrants,\n OrganizationDataUsage,\n OrganizationDirectory,\n OrganizationDirectoryAndGroups,\n OrganizationDirectoryUser,\n OrganizationGroupContainer,\n OrganizationGroupContainers,\n OrganizationGroupDetails,\n OrganizationGroupMember,\n OrganizationGroupMembers,\n OrganizationGroupPolicyHistory,\n OrganizationGroupSummary,\n OrganizationLeaveRequestResult,\n OrganizationMembership,\n OrganizationPolicyGrantChange,\n OrganizationPolicyGroupChange,\n OrganizationPolicyHistory,\n OrganizationPolicyHistoryEntry,\n OrganizationProfile,\n OrganizationSyncPauseResult,\n OrganizationUserDetail,\n} from \"../../workflows/organizations\";\nexport type {\n OrganizationContentReconciler,\n OrganizationMemberships,\n} from \"./organizationMemberships\";\nexport type {\n OrganizationGroupMutationReceipt,\n Organizations,\n} from \"./organizationsTypes\";\nexport type {\n AbandonOrganizationPolicyMutationInput,\n DiscardUnreadableOrganizationPolicyMutationInput,\n} from \"./principalMutationRecovery\";\nexport type {\n AddOrganizationGroupUserInput,\n OrganizationGrantRef,\n RemoveOrganizationGroupUserInput,\n} from \"./principalMutations\";\n\nexport function createOrganizations(\n runtime: InternalRuntime,\n containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n): Organizations {\n return new OrganizationsService(runtime, containerContents, openReconciler);\n}\n\nclass OrganizationsService implements Organizations {\n readonly memberships: OrganizationMemberships;\n private readonly dataUsageCoordinator: OrganizationDataUsageCoordinator;\n private readonly readModelCoordinator: OrganizationReadModelCoordinator;\n\n constructor(\n private readonly runtimeService: InternalRuntime,\n private readonly containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n ) {\n this.dataUsageCoordinator = createOrganizationDataUsageCoordinator(\n this.runtimeService,\n );\n this.readModelCoordinator = createOrganizationReadModelCoordinator(\n this.runtimeService,\n );\n this.memberships = createOrganizationMemberships(\n this.runtimeService,\n this.containerContents,\n openReconciler,\n );\n }\n\n async addUserToGroup(input: AddOrganizationGroupUserInput) {\n return addUserToOrganizationGroup({\n ...input,\n containerContents: this.containerContents,\n readModelCoordinator: this.readModelCoordinator,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n readPendingPolicyMutation(organizationId: string) {\n return readPendingOrganizationPolicyMutation(\n this.runtimeService,\n organizationId,\n );\n }\n\n discardUnreadablePolicyMutation(\n input: DiscardUnreadableOrganizationPolicyMutationInput,\n ) {\n return discardUnreadableOrganizationPolicyMutation(\n this.runtimeService,\n input,\n );\n }\n\n retryPendingPolicyMutation(organizationId: string) {\n return retryPendingOrganizationPolicyMutation(\n this.runtimeService,\n organizationId,\n );\n }\n\n abandonPendingPolicyMutation(input: AbandonOrganizationPolicyMutationInput) {\n return abandonPendingOrganizationPolicyMutation(this.runtimeService, input);\n }\n\n createGroup(name: string) {\n return createGroupForOrganization({\n name,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n deleteGroup(groupId: string) {\n return deleteGroupForOrganization({\n groupId,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n importUserById(userId: string) {\n const runtime = this.runtimeService.workflowInput();\n return importOrganizationUser({\n resolveTrustedUserIdentity: runtime.resolveTrustedUserIdentity,\n userId,\n });\n }\n\n loadBilling() {\n return runForOrganization(this.runtimeService, loadOrganizationBilling);\n }\n\n loadBillingForOrganization(organizationId: string) {\n // Gated on an authenticated session rather than on the target being the\n // active org. The server still enforces membership, so an org the caller\n // cannot reach resolves to `null`.\n return runForOrganization(\n this.runtimeService,\n loadOrganizationBilling,\n organizationId,\n );\n }\n\n loadBillingHistory() {\n return runForOrganization(\n this.runtimeService,\n loadOrganizationBillingHistory,\n );\n }\n\n loadBillingManagementUrl() {\n return runForOrganization(\n this.runtimeService,\n loadOrganizationBillingManagementUrl,\n );\n }\n\n loadStripeCheckoutOptions(organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n loadStripeCheckoutOptions,\n organizationId,\n );\n }\n\n createStripeCheckout(organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n createStripeCheckout,\n organizationId,\n );\n }\n\n createStripeCheckoutSession(returnUrl: string, organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n (input) => createStripeCheckoutSession({ ...input, returnUrl }),\n organizationId,\n );\n }\n\n cancelStripeSubscription() {\n return runForOrganization(this.runtimeService, cancelStripeSubscription);\n }\n\n claimNativeSubscription(\n organizationId: string,\n store: NativeSubscriptionStore,\n ) {\n return runForOrganization(\n this.runtimeService,\n (input) => claimNativeOrganizationSubscription({ ...input, store }),\n organizationId,\n );\n }\n\n checkNativePurchaseEligibility(\n organizationId: string,\n store: NativeSubscriptionStore,\n ) {\n return runForOrganization(\n this.runtimeService,\n (input) => checkNativePurchaseEligibility({ ...input, store }),\n organizationId,\n );\n }\n\n loadDataUsage() {\n return this.dataUsageCoordinator.reconcile();\n }\n\n loadLocalDataUsage() {\n return this.dataUsageCoordinator.loadLocal();\n }\n\n loadDirectoryAndGroups() {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: runtime.auth.organizationId,\n objectKind: \"principal\",\n operation: \"organization.read_model.reconcile\",\n organizationId: runtime.auth.organizationId,\n },\n () => this.readModelCoordinator.reconcile(),\n );\n }\n\n loadDirectoryAndGroupsAfterMutation() {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: runtime.auth.organizationId,\n objectKind: \"principal\",\n operation: \"organization.read_model.reconcile_after_mutation\",\n organizationId: runtime.auth.organizationId,\n },\n () => this.readModelCoordinator.reconcileAfterMutation(),\n );\n }\n\n loadLocalDirectoryAndGroups() {\n return this.readModelCoordinator.loadLocal();\n }\n\n loadGroupMembers(groupId: string) {\n const runtime = this.runtimeService.workflowInput();\n const organizationId = authenticatedOrganizationId(runtime);\n if (!organizationId || groupId.length === 0) {\n return Promise.resolve(null);\n }\n\n return runtime.apiClient.listOrganizationGroupMembers(\n organizationId,\n groupId,\n );\n }\n\n loadGroupPresentationDetails(groupId: string, beforeVersion?: number) {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: groupId,\n objectKind: \"principal\",\n operation: \"group.presentation.load\",\n organizationId: runtime.auth.organizationId,\n },\n () =>\n loadOrganizationGroupPresentationDetails({\n groupId,\n beforeVersion,\n readModelCoordinator: this.readModelCoordinator,\n runtime,\n }),\n );\n }\n\n loadGrants() {\n return this.readModelCoordinator.loadLocalGrants();\n }\n\n loadGroupContainers(groupId: string) {\n return this.readModelCoordinator.loadLocalGroupContainers(groupId);\n }\n\n listLocalOrganizations() {\n const runtime = this.runtimeService.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") {\n return Promise.resolve([]);\n }\n\n return listLocalOrganizations({ execSql: runtime.infra.execSql });\n }\n\n loadPolicyHistory(beforeVersion?: number) {\n const runtime = this.runtimeService.workflowInput();\n return runWithSecurityIncidentReporting(\n runtime.util.reportSecurityIncident,\n {\n objectId: runtime.auth.organizationId,\n objectKind: \"principal\",\n operation: \"organization.policy_history.load\",\n organizationId: runtime.auth.organizationId,\n },\n () =>\n this.readModelCoordinator.loadOrganizationPolicyHistory(\n undefined,\n beforeVersion,\n ),\n );\n }\n\n loadUserDetail(userId: string) {\n return this.readModelCoordinator.loadLocalUserDetail(userId);\n }\n\n async updateRosterEntry(userId: string, profileDocumentId: string | null) {\n const runtime = this.runtimeService.workflowInput();\n const organizationId = authenticatedOrganizationId(runtime);\n if (!organizationId || userId.length === 0) {\n return null;\n }\n\n const user = await updateOrganizationRosterEntry({\n apiClient: runtime.apiClient,\n organizationId,\n profileDocumentId,\n userId,\n });\n // Callers store this response as directory state, so its leave request\n // passes the same check as one read from the read model.\n return (\n user &&\n withVerifiedDirectoryUser(\n organizationId,\n user,\n leaveRequestVerifier(this.runtimeService, runtime, {\n organizationId,\n userId: runtime.auth.userId ?? \"\",\n }),\n )\n );\n }\n\n updateProfile(profileDocumentId: string | null) {\n const runtime = this.runtimeService.workflowInput();\n const organizationId = authenticatedOrganizationId(runtime);\n if (!organizationId) {\n return Promise.resolve(null);\n }\n\n return updateOrganizationProfile({\n apiClient: runtime.apiClient,\n organizationId,\n profileDocumentId,\n });\n }\n\n async removeUserFromGroup(input: RemoveOrganizationGroupUserInput) {\n return removeUserFromOrganizationGroup({\n ...input,\n containerContents: this.containerContents,\n readModelCoordinator: this.readModelCoordinator,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n async revokeGrant(grant: OrganizationGrantRef) {\n return revokeOrganizationGrant({\n ...grant,\n containerContents: this.containerContents,\n readModelCoordinator: this.readModelCoordinator,\n ...currentOrganizationMutation(this.runtimeService),\n });\n }\n\n startTrial(organizationId?: string) {\n return runForOrganization(\n this.runtimeService,\n startOrganizationTrial,\n organizationId,\n );\n }\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { refreshOrganizationMemberships, setOrganizationLeaveRequested, setOrganizationSyncPaused, } from "../../workflows/organizations/index.js";
|
|
2
|
+
import { loadCurrentMembersHead } from "../../workflows/organizations/memberships/leaveRequestMembersEvidence.js";
|
|
2
3
|
import { getOrCreateOrganizationSyncPauses, hasDomainSyncCoordinatorPendingWork, requestAllDomainSyncLanes, subscribeToDomainSyncCoordinator, waitForDomainSyncCoordinatorToSettle, } from "../../workflows/sync/index.js";
|
|
3
4
|
import { carriesLocalWrites, } from "../containerContents/index.js";
|
|
4
5
|
// Long enough for a typical upload burst, short enough to answer a tap.
|
|
@@ -83,6 +84,30 @@ function canReachServer(runtime) {
|
|
|
83
84
|
runtime.auth.isAuthenticated &&
|
|
84
85
|
runtime.state.online);
|
|
85
86
|
}
|
|
87
|
+
function setLeaveRequestedFor(runtimeService, organizationId, requested) {
|
|
88
|
+
const runtime = runtimeService.workflowInput();
|
|
89
|
+
const { userId } = runtime.auth;
|
|
90
|
+
const { signingKeyPair } = runtime.crypto;
|
|
91
|
+
if (!canReachServer(runtime) || !userId || !signingKeyPair) {
|
|
92
|
+
return Promise.resolve({
|
|
93
|
+
httpStatus: null,
|
|
94
|
+
message: "Connect to ask to leave an organization.",
|
|
95
|
+
status: "failed",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
const { domainScope } = runtime.state;
|
|
99
|
+
return setOrganizationLeaveRequested({
|
|
100
|
+
apiClient: runtime.apiClient,
|
|
101
|
+
loadMembersHead: () => loadCurrentMembersHead({
|
|
102
|
+
organizationId,
|
|
103
|
+
runtime,
|
|
104
|
+
stillCurrent: () => runtimeService.workflowInput().state.domainScope === domainScope,
|
|
105
|
+
}),
|
|
106
|
+
organizationId,
|
|
107
|
+
requested,
|
|
108
|
+
signer: { signingKeyPair, userId },
|
|
109
|
+
});
|
|
110
|
+
}
|
|
86
111
|
export function createOrganizationMemberships(runtimeService, containerContents, openReconciler) {
|
|
87
112
|
const membershipInput = (runtime) => {
|
|
88
113
|
const { domainScope } = runtime.state;
|
|
@@ -123,24 +148,7 @@ export function createOrganizationMemberships(runtimeService, containerContents,
|
|
|
123
148
|
paused,
|
|
124
149
|
});
|
|
125
150
|
},
|
|
126
|
-
|
|
127
|
-
const runtime = runtimeService.workflowInput();
|
|
128
|
-
const { userId } = runtime.auth;
|
|
129
|
-
const { signingKeyPair } = runtime.crypto;
|
|
130
|
-
if (!canReachServer(runtime) || !userId || !signingKeyPair) {
|
|
131
|
-
return {
|
|
132
|
-
httpStatus: null,
|
|
133
|
-
message: "Connect to ask to leave an organization.",
|
|
134
|
-
status: "failed",
|
|
135
|
-
};
|
|
136
|
-
}
|
|
137
|
-
return setOrganizationLeaveRequested({
|
|
138
|
-
apiClient: runtime.apiClient,
|
|
139
|
-
organizationId,
|
|
140
|
-
requested,
|
|
141
|
-
signer: { signingKeyPair, userId },
|
|
142
|
-
});
|
|
143
|
-
},
|
|
151
|
+
setLeaveRequested: (organizationId, requested) => setLeaveRequestedFor(runtimeService, organizationId, requested),
|
|
144
152
|
async loadPausedOrganizationIds() {
|
|
145
153
|
const runtime = runtimeService.workflowInput();
|
|
146
154
|
if (runtime.infra.dbStatus !== "ready")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationMemberships.js","sourceRoot":"","sources":["organizationMemberships.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type OrganizationContentHost,\n type OrganizationLeaveRequestResult,\n type OrganizationMembership,\n type OrganizationSyncPauseResult,\n refreshOrganizationMemberships,\n setOrganizationLeaveRequested,\n setOrganizationSyncPaused,\n} from \"../../workflows/organizations\";\nimport {\n type DomainScope,\n getOrCreateOrganizationSyncPauses,\n hasDomainSyncCoordinatorPendingWork,\n requestAllDomainSyncLanes,\n subscribeToDomainSyncCoordinator,\n waitForDomainSyncCoordinatorToSettle,\n} from \"../../workflows/sync\";\nimport {\n type ContainerContents,\n carriesLocalWrites,\n} from \"../containerContents\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../runtime/workflowRuntime\";\n\n// Long enough for a typical upload burst, short enough to answer a tap.\nconst PAUSE_FLUSH_TIMEOUT_MS = 10_000;\n\n/** The user's own conduit to the organizations they belong to. */\nexport interface OrganizationMemberships {\n /**\n * Reads the user's memberships and applies their pause choices on this\n * device. Null when offline or the list could not be read.\n */\n refresh(): Promise<OrganizationMembership[] | null>;\n /** Pauses or resumes one organization for all of the user's devices. */\n setSyncPaused(\n organizationId: string,\n paused: boolean,\n ): Promise<OrganizationSyncPauseResult>;\n /**\n * Asks the organization's administrators to remove the user, or withdraws\n * that request. Signed with the user's identity key; an administrator still\n * has to approve it.\n */\n setLeaveRequested(\n organizationId: string,\n requested: boolean,\n ): Promise<OrganizationLeaveRequestResult>;\n /** The organizations paused on this device, read from local storage. */\n loadPausedOrganizationIds(): Promise<ReadonlySet<string>>;\n /** Notifies when the paused set for the current scope changes. */\n subscribeToSyncPauses(listener: () => void): () => void;\n /**\n * Hands each membership list a refresh reads for the current scope, so a\n * choice made on another device reaches every view of it.\n */\n subscribeToMemberships(\n listener: (memberships: readonly OrganizationMembership[]) => void,\n ): () => void;\n}\n\ntype MembershipsListener = (\n memberships: readonly OrganizationMembership[],\n) => void;\n\nconst membershipListenersByScope = new WeakMap<\n DomainScope,\n Set<MembershipsListener>\n>();\n\n/**\n * The scope's document reconciler. Containers it reconciled before a pause\n * stay marked as listed, so a resume has to forget that before reconciling.\n */\nexport interface OrganizationContentReconciler {\n resetDiscovered(): void;\n reconcileNow(options: { readonly freshListing: true }): Promise<void>;\n}\n\ninterface SettleRetry {\n retry: () => Promise<boolean>;\n running: boolean;\n unsubscribe: () => void;\n}\n\nconst settleRetriesByScope = new WeakMap<DomainScope, SettleRetry>();\n\n// One retry per scope: it runs whenever the scope's sync lanes go idle and\n// stops once it reports the work done.\nexport function retryWhenWritesSettle(\n domainScope: DomainScope,\n retry: () => Promise<boolean>,\n): void {\n const existing = settleRetriesByScope.get(domainScope);\n if (existing) {\n existing.retry = retry;\n return;\n }\n const entry: SettleRetry = { retry, running: false, unsubscribe: () => {} };\n settleRetriesByScope.set(domainScope, entry);\n const attempt = () => {\n if (entry.running || hasDomainSyncCoordinatorPendingWork(domainScope)) {\n return;\n }\n entry.running = true;\n void entry\n .retry()\n .then(\n (done) => {\n if (!done) return;\n entry.unsubscribe();\n settleRetriesByScope.delete(domainScope);\n },\n () => undefined,\n )\n .finally(() => {\n entry.running = false;\n });\n };\n entry.unsubscribe = subscribeToDomainSyncCoordinator(domainScope, attempt);\n // The lanes may already have gone idle before the subscription existed.\n attempt();\n}\n\n// Bound to the scope the operation started in: the tree is opened once, and\n// every action re-checks the scope so stale work never reaches another\n// identity's device state.\nfunction createOrganizationContentHost(\n runtime: InternalWorkflowRuntimeInput,\n containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n isCurrent: () => boolean,\n): OrganizationContentHost {\n const { domainScope } = runtime.state;\n const tree = containerContents.openTree();\n return {\n async forgetOrganizationContent(organizationId) {\n // A scope that ended has nothing left to retry.\n if (!isCurrent()) return true;\n return tree.forgetOrganizationContent(organizationId);\n },\n async hasUnsyncedOrganizationWrites(organizationId) {\n if (!isCurrent()) return true;\n const pending = await containerContents\n .documentQueries()\n .listPendingWrites();\n return pending.some(\n (item) =>\n item.organizationId === organizationId && carriesLocalWrites(item),\n );\n },\n async flushWrites() {\n requestAllDomainSyncLanes(domainScope);\n await waitForDomainSyncCoordinatorToSettle(domainScope, {\n timeoutMs: PAUSE_FLUSH_TIMEOUT_MS,\n });\n },\n async refetchContent() {\n if (!isCurrent()) return;\n // Re-lists the whole tree and every container's documents. The resumed\n // organization's folders were listed before the pause, and a hydration\n // may already have restored them, so they must be forgotten explicitly.\n // A sweep that started listing while paused would miss them, so this\n // one queues behind it rather than joining it.\n const reconciler = openReconciler();\n reconciler.resetDiscovered();\n await reconciler.reconcileNow({ freshListing: true });\n },\n retryWhenWritesSettle: (retry) => retryWhenWritesSettle(domainScope, retry),\n };\n}\n\nfunction canReachServer(runtime: InternalWorkflowRuntimeInput): boolean {\n return (\n runtime.infra.dbStatus === \"ready\" &&\n runtime.auth.isAuthenticated &&\n runtime.state.online\n );\n}\n\nexport function createOrganizationMemberships(\n runtimeService: InternalRuntime,\n containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n): OrganizationMemberships {\n const membershipInput = (runtime: InternalWorkflowRuntimeInput) => {\n const { domainScope } = runtime.state;\n const isCurrent = () =>\n runtimeService.workflowInput().state.domainScope === domainScope;\n return {\n apiClient: runtime.apiClient,\n domainScope,\n execSql: runtime.infra.execSql,\n host: createOrganizationContentHost(\n runtime,\n containerContents,\n openReconciler,\n isCurrent,\n ),\n isCurrent,\n };\n };\n return {\n async refresh() {\n const runtime = runtimeService.workflowInput();\n if (!canReachServer(runtime)) return null;\n const memberships = await refreshOrganizationMemberships(\n membershipInput(runtime),\n );\n const listeners = membershipListenersByScope.get(\n runtime.state.domainScope,\n );\n if (memberships && listeners) {\n for (const listener of [...listeners]) listener(memberships);\n }\n return memberships;\n },\n async setSyncPaused(organizationId, paused) {\n const runtime = runtimeService.workflowInput();\n if (!canReachServer(runtime)) {\n return {\n httpStatus: null,\n message: \"Connect to change sync for an organization.\",\n status: \"failed\",\n };\n }\n return setOrganizationSyncPaused({\n ...membershipInput(runtime),\n organizationId,\n paused,\n });\n },\n async setLeaveRequested(organizationId, requested) {\n const runtime = runtimeService.workflowInput();\n const { userId } = runtime.auth;\n const { signingKeyPair } = runtime.crypto;\n if (!canReachServer(runtime) || !userId || !signingKeyPair) {\n return {\n httpStatus: null,\n message: \"Connect to ask to leave an organization.\",\n status: \"failed\",\n };\n }\n return setOrganizationLeaveRequested({\n apiClient: runtime.apiClient,\n organizationId,\n requested,\n signer: { signingKeyPair, userId },\n });\n },\n async loadPausedOrganizationIds() {\n const runtime = runtimeService.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") return new Set<string>();\n const pauses = getOrCreateOrganizationSyncPauses(\n runtime.state.domainScope,\n );\n await pauses.load(runtime.infra.execSql);\n return pauses.pausedOrganizationIds();\n },\n subscribeToSyncPauses(listener) {\n return getOrCreateOrganizationSyncPauses(\n runtimeService.workflowInput().state.domainScope,\n ).subscribe(listener);\n },\n subscribeToMemberships(listener) {\n const { domainScope } = runtimeService.workflowInput().state;\n const listeners =\n membershipListenersByScope.get(domainScope) ?? new Set();\n membershipListenersByScope.set(domainScope, listeners);\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organizationMemberships.js","sourceRoot":"","sources":["organizationMemberships.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type OrganizationContentHost,\n type OrganizationLeaveRequestResult,\n type OrganizationMembership,\n type OrganizationSyncPauseResult,\n refreshOrganizationMemberships,\n setOrganizationLeaveRequested,\n setOrganizationSyncPaused,\n} from \"../../workflows/organizations\";\nimport { loadCurrentMembersHead } from \"../../workflows/organizations/memberships/leaveRequestMembersEvidence\";\nimport {\n type DomainScope,\n getOrCreateOrganizationSyncPauses,\n hasDomainSyncCoordinatorPendingWork,\n requestAllDomainSyncLanes,\n subscribeToDomainSyncCoordinator,\n waitForDomainSyncCoordinatorToSettle,\n} from \"../../workflows/sync\";\nimport {\n type ContainerContents,\n carriesLocalWrites,\n} from \"../containerContents\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../runtime/workflowRuntime\";\n\n// Long enough for a typical upload burst, short enough to answer a tap.\nconst PAUSE_FLUSH_TIMEOUT_MS = 10_000;\n\n/** The user's own conduit to the organizations they belong to. */\nexport interface OrganizationMemberships {\n /**\n * Reads the user's memberships and applies their pause choices on this\n * device. Null when offline or the list could not be read.\n */\n refresh(): Promise<OrganizationMembership[] | null>;\n /** Pauses or resumes one organization for all of the user's devices. */\n setSyncPaused(\n organizationId: string,\n paused: boolean,\n ): Promise<OrganizationSyncPauseResult>;\n /**\n * Asks the organization's administrators to remove the user, or withdraws\n * that request. Signed with the user's identity key; an administrator still\n * has to approve it.\n */\n setLeaveRequested(\n organizationId: string,\n requested: boolean,\n ): Promise<OrganizationLeaveRequestResult>;\n /** The organizations paused on this device, read from local storage. */\n loadPausedOrganizationIds(): Promise<ReadonlySet<string>>;\n /** Notifies when the paused set for the current scope changes. */\n subscribeToSyncPauses(listener: () => void): () => void;\n /**\n * Hands each membership list a refresh reads for the current scope, so a\n * choice made on another device reaches every view of it.\n */\n subscribeToMemberships(\n listener: (memberships: readonly OrganizationMembership[]) => void,\n ): () => void;\n}\n\ntype MembershipsListener = (\n memberships: readonly OrganizationMembership[],\n) => void;\n\nconst membershipListenersByScope = new WeakMap<\n DomainScope,\n Set<MembershipsListener>\n>();\n\n/**\n * The scope's document reconciler. Containers it reconciled before a pause\n * stay marked as listed, so a resume has to forget that before reconciling.\n */\nexport interface OrganizationContentReconciler {\n resetDiscovered(): void;\n reconcileNow(options: { readonly freshListing: true }): Promise<void>;\n}\n\ninterface SettleRetry {\n retry: () => Promise<boolean>;\n running: boolean;\n unsubscribe: () => void;\n}\n\nconst settleRetriesByScope = new WeakMap<DomainScope, SettleRetry>();\n\n// One retry per scope: it runs whenever the scope's sync lanes go idle and\n// stops once it reports the work done.\nexport function retryWhenWritesSettle(\n domainScope: DomainScope,\n retry: () => Promise<boolean>,\n): void {\n const existing = settleRetriesByScope.get(domainScope);\n if (existing) {\n existing.retry = retry;\n return;\n }\n const entry: SettleRetry = { retry, running: false, unsubscribe: () => {} };\n settleRetriesByScope.set(domainScope, entry);\n const attempt = () => {\n if (entry.running || hasDomainSyncCoordinatorPendingWork(domainScope)) {\n return;\n }\n entry.running = true;\n void entry\n .retry()\n .then(\n (done) => {\n if (!done) return;\n entry.unsubscribe();\n settleRetriesByScope.delete(domainScope);\n },\n () => undefined,\n )\n .finally(() => {\n entry.running = false;\n });\n };\n entry.unsubscribe = subscribeToDomainSyncCoordinator(domainScope, attempt);\n // The lanes may already have gone idle before the subscription existed.\n attempt();\n}\n\n// Bound to the scope the operation started in: the tree is opened once, and\n// every action re-checks the scope so stale work never reaches another\n// identity's device state.\nfunction createOrganizationContentHost(\n runtime: InternalWorkflowRuntimeInput,\n containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n isCurrent: () => boolean,\n): OrganizationContentHost {\n const { domainScope } = runtime.state;\n const tree = containerContents.openTree();\n return {\n async forgetOrganizationContent(organizationId) {\n // A scope that ended has nothing left to retry.\n if (!isCurrent()) return true;\n return tree.forgetOrganizationContent(organizationId);\n },\n async hasUnsyncedOrganizationWrites(organizationId) {\n if (!isCurrent()) return true;\n const pending = await containerContents\n .documentQueries()\n .listPendingWrites();\n return pending.some(\n (item) =>\n item.organizationId === organizationId && carriesLocalWrites(item),\n );\n },\n async flushWrites() {\n requestAllDomainSyncLanes(domainScope);\n await waitForDomainSyncCoordinatorToSettle(domainScope, {\n timeoutMs: PAUSE_FLUSH_TIMEOUT_MS,\n });\n },\n async refetchContent() {\n if (!isCurrent()) return;\n // Re-lists the whole tree and every container's documents. The resumed\n // organization's folders were listed before the pause, and a hydration\n // may already have restored them, so they must be forgotten explicitly.\n // A sweep that started listing while paused would miss them, so this\n // one queues behind it rather than joining it.\n const reconciler = openReconciler();\n reconciler.resetDiscovered();\n await reconciler.reconcileNow({ freshListing: true });\n },\n retryWhenWritesSettle: (retry) => retryWhenWritesSettle(domainScope, retry),\n };\n}\n\nfunction canReachServer(runtime: InternalWorkflowRuntimeInput): boolean {\n return (\n runtime.infra.dbStatus === \"ready\" &&\n runtime.auth.isAuthenticated &&\n runtime.state.online\n );\n}\n\nfunction setLeaveRequestedFor(\n runtimeService: InternalRuntime,\n organizationId: string,\n requested: boolean,\n): Promise<OrganizationLeaveRequestResult> {\n const runtime = runtimeService.workflowInput();\n const { userId } = runtime.auth;\n const { signingKeyPair } = runtime.crypto;\n if (!canReachServer(runtime) || !userId || !signingKeyPair) {\n return Promise.resolve({\n httpStatus: null,\n message: \"Connect to ask to leave an organization.\",\n status: \"failed\",\n });\n }\n const { domainScope } = runtime.state;\n return setOrganizationLeaveRequested({\n apiClient: runtime.apiClient,\n loadMembersHead: () =>\n loadCurrentMembersHead({\n organizationId,\n runtime,\n stillCurrent: () =>\n runtimeService.workflowInput().state.domainScope === domainScope,\n }),\n organizationId,\n requested,\n signer: { signingKeyPair, userId },\n });\n}\n\nexport function createOrganizationMemberships(\n runtimeService: InternalRuntime,\n containerContents: ContainerContents,\n openReconciler: () => OrganizationContentReconciler,\n): OrganizationMemberships {\n const membershipInput = (runtime: InternalWorkflowRuntimeInput) => {\n const { domainScope } = runtime.state;\n const isCurrent = () =>\n runtimeService.workflowInput().state.domainScope === domainScope;\n return {\n apiClient: runtime.apiClient,\n domainScope,\n execSql: runtime.infra.execSql,\n host: createOrganizationContentHost(\n runtime,\n containerContents,\n openReconciler,\n isCurrent,\n ),\n isCurrent,\n };\n };\n return {\n async refresh() {\n const runtime = runtimeService.workflowInput();\n if (!canReachServer(runtime)) return null;\n const memberships = await refreshOrganizationMemberships(\n membershipInput(runtime),\n );\n const listeners = membershipListenersByScope.get(\n runtime.state.domainScope,\n );\n if (memberships && listeners) {\n for (const listener of [...listeners]) listener(memberships);\n }\n return memberships;\n },\n async setSyncPaused(organizationId, paused) {\n const runtime = runtimeService.workflowInput();\n if (!canReachServer(runtime)) {\n return {\n httpStatus: null,\n message: \"Connect to change sync for an organization.\",\n status: \"failed\",\n };\n }\n return setOrganizationSyncPaused({\n ...membershipInput(runtime),\n organizationId,\n paused,\n });\n },\n setLeaveRequested: (organizationId, requested) =>\n setLeaveRequestedFor(runtimeService, organizationId, requested),\n async loadPausedOrganizationIds() {\n const runtime = runtimeService.workflowInput();\n if (runtime.infra.dbStatus !== \"ready\") return new Set<string>();\n const pauses = getOrCreateOrganizationSyncPauses(\n runtime.state.domainScope,\n );\n await pauses.load(runtime.infra.execSql);\n return pauses.pausedOrganizationIds();\n },\n subscribeToSyncPauses(listener) {\n return getOrCreateOrganizationSyncPauses(\n runtimeService.workflowInput().state.domainScope,\n ).subscribe(listener);\n },\n subscribeToMemberships(listener) {\n const { domainScope } = runtimeService.workflowInput().state;\n const listeners =\n membershipListenersByScope.get(domainScope) ?? new Set();\n membershipListenersByScope.set(domainScope, listeners);\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n"]}
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { type OrganizationContainerGrants, type OrganizationDirectoryAndGroups, type OrganizationGroupContainers, type OrganizationGroupMembers, type OrganizationGroupPolicyHistory, type OrganizationPolicyHistory, type OrganizationUserDetail } from "../../workflows/organizations/index.js";
|
|
2
|
+
import type { LeaveRequestVerifier } from "../../workflows/organizations/memberships/leaveRequestVerification.js";
|
|
2
3
|
import type { InternalRuntime, InternalWorkflowRuntimeInput } from "../runtime/workflowRuntime.js";
|
|
3
4
|
/**
|
|
4
|
-
*
|
|
5
|
-
* durable pin first, so a request already stored still verifies
|
|
6
|
-
* then a trusted remote resolution for a member not pinned yet.
|
|
5
|
+
* What one view's leave requests are checked against. The signer comes from
|
|
6
|
+
* the device's durable pin first, so a request already stored still verifies
|
|
7
|
+
* offline, then a trusted remote resolution for a member not pinned yet. The
|
|
8
|
+
* membership comes from this device's verified organization policy.
|
|
7
9
|
*/
|
|
8
|
-
export declare function
|
|
10
|
+
export declare function leaveRequestVerifier(runtimeService: InternalRuntime, runtime: InternalWorkflowRuntimeInput, organization: {
|
|
11
|
+
readonly organizationId: string;
|
|
12
|
+
readonly userId: string;
|
|
13
|
+
}): LeaveRequestVerifier;
|
|
9
14
|
export interface OrganizationReadModelCoordinator {
|
|
10
15
|
loadLocal(organizationId?: string | undefined): Promise<OrganizationDirectoryAndGroups | null>;
|
|
11
16
|
loadLocalGroupMembers(groupId: string, organizationId?: string | undefined): Promise<OrganizationGroupMembers | null>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { recoverOrganizationAccess } from "../../workflows/container-contents/recovery/accessRestoration.js";
|
|
2
2
|
import { loadLocalOrganizationContainerGrants, loadLocalOrganizationDirectoryAndGroups, loadLocalOrganizationGroupContainers, loadLocalOrganizationGroupMembers, loadLocalOrganizationUserDetail, reconcileOrganizationDirectoryAndGroups, withVerifiedLeaveRequests, withVerifiedUserLeaveRequest, } from "../../workflows/organizations/index.js";
|
|
3
|
+
import { createRuntimeLeaveRequestMembershipCheck } from "../../workflows/organizations/memberships/leaveRequestMembersEvidence.js";
|
|
3
4
|
import { organizationAccessScopeKey, wasOrganizationPresentationAccessDeniedByServer, } from "../../workflows/organizations/readModel/organizationPresentationAccessState.js";
|
|
4
5
|
import { loadBoundedOrganizationGroupHistory } from "./organizationGroupHistory.js";
|
|
5
6
|
import { hydrateOrganizationGroupNamesForRuntime } from "./organizationGroupNameHydration.js";
|
|
@@ -7,13 +8,23 @@ import { loadBoundedOrganizationHistory } from "./organizationHistory.js";
|
|
|
7
8
|
import { activeOrganizationDataRuntime, isOrganizationDataRuntimeCurrent, } from "./organizationWorkflowRuntime.js";
|
|
8
9
|
const coordinatorsByRuntime = new WeakMap();
|
|
9
10
|
/**
|
|
10
|
-
*
|
|
11
|
-
* durable pin first, so a request already stored still verifies
|
|
12
|
-
* then a trusted remote resolution for a member not pinned yet.
|
|
11
|
+
* What one view's leave requests are checked against. The signer comes from
|
|
12
|
+
* the device's durable pin first, so a request already stored still verifies
|
|
13
|
+
* offline, then a trusted remote resolution for a member not pinned yet. The
|
|
14
|
+
* membership comes from this device's verified organization policy.
|
|
13
15
|
*/
|
|
14
|
-
export function
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
export function leaveRequestVerifier(runtimeService, runtime, organization) {
|
|
17
|
+
const { domainScope } = runtime.state;
|
|
18
|
+
return {
|
|
19
|
+
resolveTrustedUserIdentity: async (userId) => (await runtimeService.identityLinks.resolvePinned(userId)) ??
|
|
20
|
+
runtime.resolveTrustedUserIdentity(userId),
|
|
21
|
+
membershipIsCurrent: createRuntimeLeaveRequestMembershipCheck({
|
|
22
|
+
currentUserId: organization.userId,
|
|
23
|
+
organizationId: organization.organizationId,
|
|
24
|
+
runtime,
|
|
25
|
+
stillCurrent: () => runtimeService.workflowInput().state.domainScope === domainScope,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
17
28
|
}
|
|
18
29
|
class OrganizationReadModelCoordinatorImpl {
|
|
19
30
|
runtimeService;
|
|
@@ -39,7 +50,7 @@ class OrganizationReadModelCoordinatorImpl {
|
|
|
39
50
|
currentUserId: active.userId,
|
|
40
51
|
execSql: active.runtime.infra.execSql,
|
|
41
52
|
organizationId: active.organizationId,
|
|
42
|
-
}),
|
|
53
|
+
}), leaveRequestVerifier(this.runtimeService, active.runtime, active));
|
|
43
54
|
}
|
|
44
55
|
async loadLocalGrants(organizationId) {
|
|
45
56
|
const active = activeOrganizationDataRuntime(this.runtimeService, organizationId);
|
|
@@ -110,7 +121,7 @@ class OrganizationReadModelCoordinatorImpl {
|
|
|
110
121
|
execSql: active.runtime.infra.execSql,
|
|
111
122
|
organizationId: active.organizationId,
|
|
112
123
|
userId,
|
|
113
|
-
}), active.organizationId,
|
|
124
|
+
}), active.organizationId, leaveRequestVerifier(this.runtimeService, active.runtime, active));
|
|
114
125
|
}
|
|
115
126
|
reconcile(organizationId) {
|
|
116
127
|
const active = activeOrganizationDataRuntime(this.runtimeService, organizationId);
|
|
@@ -162,7 +173,7 @@ class OrganizationReadModelCoordinatorImpl {
|
|
|
162
173
|
});
|
|
163
174
|
if (!stillCurrent())
|
|
164
175
|
return null;
|
|
165
|
-
return withVerifiedLeaveRequests(await hydrateOrganizationGroupNamesForRuntime(this.runtimeService, active, domainScope, directoryAndGroups),
|
|
176
|
+
return withVerifiedLeaveRequests(await hydrateOrganizationGroupNamesForRuntime(this.runtimeService, active, domainScope, directoryAndGroups), leaveRequestVerifier(this.runtimeService, active.runtime, active));
|
|
166
177
|
})
|
|
167
178
|
.finally(() => {
|
|
168
179
|
if (byKey.get(key) === reconciliation) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationReadModels.js","sourceRoot":"","sources":["organizationReadModels.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DomainScope } from \"../../data/shared/domainScope\";\nimport { recoverOrganizationAccess } from \"../../workflows/container-contents/recovery/accessRestoration\";\nimport {\n loadLocalOrganizationContainerGrants,\n loadLocalOrganizationDirectoryAndGroups,\n loadLocalOrganizationGroupContainers,\n loadLocalOrganizationGroupMembers,\n loadLocalOrganizationUserDetail,\n type OrganizationContainerGrants,\n type OrganizationDirectoryAndGroups,\n type OrganizationGroupContainers,\n type OrganizationGroupMembers,\n type OrganizationGroupPolicyHistory,\n type OrganizationPolicyHistory,\n type OrganizationUserDetail,\n reconcileOrganizationDirectoryAndGroups,\n withVerifiedLeaveRequests,\n withVerifiedUserLeaveRequest,\n} from \"../../workflows/organizations\";\nimport {\n organizationAccessScopeKey,\n wasOrganizationPresentationAccessDeniedByServer,\n} from \"../../workflows/organizations/readModel/organizationPresentationAccessState\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../runtime/workflowRuntime\";\nimport { loadBoundedOrganizationGroupHistory } from \"./organizationGroupHistory\";\nimport { hydrateOrganizationGroupNamesForRuntime } from \"./organizationGroupNameHydration\";\nimport { loadBoundedOrganizationHistory } from \"./organizationHistory\";\nimport {\n type ActiveOrganizationDataRuntime,\n activeOrganizationDataRuntime,\n isOrganizationDataRuntimeCurrent,\n} from \"./organizationWorkflowRuntime\";\n\nconst coordinatorsByRuntime = new WeakMap<\n InternalRuntime,\n OrganizationReadModelCoordinator\n>();\n\n/**\n * Resolves the identity a leave request is checked against: the device's\n * durable pin first, so a request already stored still verifies offline,\n * then a trusted remote resolution for a member not pinned yet.\n */\nexport function leaveRequestSignerResolver(\n runtimeService: InternalRuntime,\n runtime: InternalWorkflowRuntimeInput,\n): InternalWorkflowRuntimeInput[\"resolveTrustedUserIdentity\"] {\n return async (userId) =>\n (await runtimeService.identityLinks.resolvePinned(userId)) ??\n runtime.resolveTrustedUserIdentity(userId);\n}\n\nexport interface OrganizationReadModelCoordinator {\n loadLocal(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null>;\n loadLocalGroupMembers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupMembers | null>;\n loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationGroupPolicyHistory | null>;\n loadOrganizationPolicyHistory(\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationPolicyHistory | null>;\n loadLocalGrants(\n organizationId?: string | undefined,\n ): Promise<OrganizationContainerGrants | null>;\n loadLocalGroupContainers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupContainers | null>;\n loadLocalUserDetail(\n userId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationUserDetail | null>;\n /**\n * Resolves `undefined` when the runtime declines without I/O (offline,\n * database not ready, organization mismatch) or when the feed failed with\n * no locally retained projection — passes that must not count as caught\n * up; `null` when the reconcile completed but produced nothing presentable\n * — including an authoritative denial that purged the projection, which\n * consumers must repaint.\n */\n reconcile(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n reconcileAfterMutation(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n}\n\nclass OrganizationReadModelCoordinatorImpl\n implements OrganizationReadModelCoordinator\n{\n private readonly reconciliationsByScope = new WeakMap<\n DomainScope,\n Map<string, Promise<OrganizationDirectoryAndGroups | null | undefined>>\n >();\n constructor(private readonly runtimeService: InternalRuntime) {}\n\n private reconciliationMap(active: ActiveOrganizationDataRuntime) {\n const scope = active.runtime.state.domainScope;\n let byKey = this.reconciliationsByScope.get(scope);\n if (!byKey) {\n byKey = new Map();\n this.reconciliationsByScope.set(scope, byKey);\n }\n return byKey;\n }\n\n async loadLocal(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return withVerifiedLeaveRequests(\n await loadLocalOrganizationDirectoryAndGroups({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n }),\n leaveRequestSignerResolver(this.runtimeService, active.runtime),\n );\n }\n\n async loadLocalGrants(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return loadLocalOrganizationContainerGrants({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupContainers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupContainers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupMembers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupMembers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationGroupHistory({\n active,\n groupId,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadOrganizationPolicyHistory(\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) return null;\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationHistory({\n active,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadLocalUserDetail(userId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || userId.length === 0) {\n return null;\n }\n return withVerifiedUserLeaveRequest(\n await loadLocalOrganizationUserDetail({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n userId,\n }),\n active.organizationId,\n leaveRequestSignerResolver(this.runtimeService, active.runtime),\n );\n }\n\n reconcile(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return Promise.resolve(undefined);\n }\n\n const byKey = this.reconciliationMap(active);\n const key = organizationAccessScopeKey(\n active.organizationId,\n active.userId,\n );\n const existing = byKey.get(key);\n if (existing) {\n return existing;\n }\n\n // Snapshot the server-denied flag before reconciling. A reconcile that\n // flips it back to readable means org access was just restored (e.g. the\n // user was re-added to a group), and any write lanes idled by\n // permission-denied submissions have no self re-arm — regaining access is\n // their retry signal, mirroring how billing recovery re-requests all\n // lanes. Only a genuine server denial counts: a local session reset also\n // marks scopes denied, and re-arming on its first reconcile would race the\n // startup sync passes (e.g. pending-create adoption between panes).\n const accessWasDenied = wasOrganizationPresentationAccessDeniedByServer(\n {\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n requesterUserId: active.userId,\n },\n \"readModel\",\n );\n const domainScope = active.runtime.state.domainScope;\n const stillCurrent = () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n );\n\n const reconciliation = reconcileOrganizationDirectoryAndGroups({\n apiClient: active.runtime.apiClient,\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n logError: active.runtime.util.logError,\n organizationId: active.organizationId,\n })\n .then(async (directoryAndGroups) => {\n if (!stillCurrent()) return null;\n // Feed success restores retry eligibility even if name decryption fails.\n const accessWasRestored =\n accessWasDenied &&\n directoryAndGroups !== null &&\n directoryAndGroups !== undefined;\n if (accessWasRestored)\n await recoverOrganizationAccess({\n domainScope,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n stillCurrent,\n userId: active.userId,\n });\n if (!stillCurrent()) return null;\n return withVerifiedLeaveRequests(\n await hydrateOrganizationGroupNamesForRuntime(\n this.runtimeService,\n active,\n domainScope,\n directoryAndGroups,\n ),\n leaveRequestSignerResolver(this.runtimeService, active.runtime),\n );\n })\n .finally(() => {\n if (byKey.get(key) === reconciliation) {\n byKey.delete(key);\n }\n });\n byKey.set(key, reconciliation);\n return reconciliation;\n }\n\n async reconcileAfterMutation(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return undefined;\n }\n const existing = this.reconciliationMap(active).get(\n organizationAccessScopeKey(active.organizationId, active.userId),\n );\n if (existing) {\n await existing.catch(() => null);\n }\n return this.reconcile(active.organizationId);\n }\n}\n\nexport function createOrganizationReadModelCoordinator(\n runtimeService: InternalRuntime,\n): OrganizationReadModelCoordinator {\n const existing = coordinatorsByRuntime.get(runtimeService);\n if (existing) {\n return existing;\n }\n\n const coordinator = new OrganizationReadModelCoordinatorImpl(runtimeService);\n coordinatorsByRuntime.set(runtimeService, coordinator);\n return coordinator;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"organizationReadModels.js","sourceRoot":"","sources":["organizationReadModels.ts"],"names":[],"mappings":"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","sourcesContent":["import type { DomainScope } from \"../../data/shared/domainScope\";\nimport { recoverOrganizationAccess } from \"../../workflows/container-contents/recovery/accessRestoration\";\nimport {\n loadLocalOrganizationContainerGrants,\n loadLocalOrganizationDirectoryAndGroups,\n loadLocalOrganizationGroupContainers,\n loadLocalOrganizationGroupMembers,\n loadLocalOrganizationUserDetail,\n type OrganizationContainerGrants,\n type OrganizationDirectoryAndGroups,\n type OrganizationGroupContainers,\n type OrganizationGroupMembers,\n type OrganizationGroupPolicyHistory,\n type OrganizationPolicyHistory,\n type OrganizationUserDetail,\n reconcileOrganizationDirectoryAndGroups,\n withVerifiedLeaveRequests,\n withVerifiedUserLeaveRequest,\n} from \"../../workflows/organizations\";\nimport { createRuntimeLeaveRequestMembershipCheck } from \"../../workflows/organizations/memberships/leaveRequestMembersEvidence\";\nimport type { LeaveRequestVerifier } from \"../../workflows/organizations/memberships/leaveRequestVerification\";\nimport {\n organizationAccessScopeKey,\n wasOrganizationPresentationAccessDeniedByServer,\n} from \"../../workflows/organizations/readModel/organizationPresentationAccessState\";\nimport type {\n InternalRuntime,\n InternalWorkflowRuntimeInput,\n} from \"../runtime/workflowRuntime\";\nimport { loadBoundedOrganizationGroupHistory } from \"./organizationGroupHistory\";\nimport { hydrateOrganizationGroupNamesForRuntime } from \"./organizationGroupNameHydration\";\nimport { loadBoundedOrganizationHistory } from \"./organizationHistory\";\nimport {\n type ActiveOrganizationDataRuntime,\n activeOrganizationDataRuntime,\n isOrganizationDataRuntimeCurrent,\n} from \"./organizationWorkflowRuntime\";\n\nconst coordinatorsByRuntime = new WeakMap<\n InternalRuntime,\n OrganizationReadModelCoordinator\n>();\n\n/**\n * What one view's leave requests are checked against. The signer comes from\n * the device's durable pin first, so a request already stored still verifies\n * offline, then a trusted remote resolution for a member not pinned yet. The\n * membership comes from this device's verified organization policy.\n */\nexport function leaveRequestVerifier(\n runtimeService: InternalRuntime,\n runtime: InternalWorkflowRuntimeInput,\n organization: { readonly organizationId: string; readonly userId: string },\n): LeaveRequestVerifier {\n const { domainScope } = runtime.state;\n return {\n resolveTrustedUserIdentity: async (userId) =>\n (await runtimeService.identityLinks.resolvePinned(userId)) ??\n runtime.resolveTrustedUserIdentity(userId),\n membershipIsCurrent: createRuntimeLeaveRequestMembershipCheck({\n currentUserId: organization.userId,\n organizationId: organization.organizationId,\n runtime,\n stillCurrent: () =>\n runtimeService.workflowInput().state.domainScope === domainScope,\n }),\n };\n}\n\nexport interface OrganizationReadModelCoordinator {\n loadLocal(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null>;\n loadLocalGroupMembers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupMembers | null>;\n loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationGroupPolicyHistory | null>;\n loadOrganizationPolicyHistory(\n organizationId?: string | undefined,\n beforeVersion?: number | undefined,\n ): Promise<OrganizationPolicyHistory | null>;\n loadLocalGrants(\n organizationId?: string | undefined,\n ): Promise<OrganizationContainerGrants | null>;\n loadLocalGroupContainers(\n groupId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationGroupContainers | null>;\n loadLocalUserDetail(\n userId: string,\n organizationId?: string | undefined,\n ): Promise<OrganizationUserDetail | null>;\n /**\n * Resolves `undefined` when the runtime declines without I/O (offline,\n * database not ready, organization mismatch) or when the feed failed with\n * no locally retained projection — passes that must not count as caught\n * up; `null` when the reconcile completed but produced nothing presentable\n * — including an authoritative denial that purged the projection, which\n * consumers must repaint.\n */\n reconcile(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n reconcileAfterMutation(\n organizationId?: string | undefined,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined>;\n}\n\nclass OrganizationReadModelCoordinatorImpl\n implements OrganizationReadModelCoordinator\n{\n private readonly reconciliationsByScope = new WeakMap<\n DomainScope,\n Map<string, Promise<OrganizationDirectoryAndGroups | null | undefined>>\n >();\n constructor(private readonly runtimeService: InternalRuntime) {}\n\n private reconciliationMap(active: ActiveOrganizationDataRuntime) {\n const scope = active.runtime.state.domainScope;\n let byKey = this.reconciliationsByScope.get(scope);\n if (!byKey) {\n byKey = new Map();\n this.reconciliationsByScope.set(scope, byKey);\n }\n return byKey;\n }\n\n async loadLocal(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return withVerifiedLeaveRequests(\n await loadLocalOrganizationDirectoryAndGroups({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n }),\n leaveRequestVerifier(this.runtimeService, active.runtime, active),\n );\n }\n\n async loadLocalGrants(organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) {\n return null;\n }\n return loadLocalOrganizationContainerGrants({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupContainers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupContainers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadLocalGroupMembers(groupId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n return loadLocalOrganizationGroupMembers({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n groupId,\n organizationId: active.organizationId,\n });\n }\n\n async loadGroupPolicyHistory(\n groupId: string,\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || groupId.length === 0) {\n return null;\n }\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationGroupHistory({\n active,\n groupId,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadOrganizationPolicyHistory(\n organizationId?: string,\n beforeVersion?: number,\n ) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active) return null;\n const domainScope = active.runtime.state.domainScope;\n return loadBoundedOrganizationHistory({\n active,\n beforeVersion,\n stillCurrent: () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n ),\n });\n }\n\n async loadLocalUserDetail(userId: string, organizationId?: string) {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active || userId.length === 0) {\n return null;\n }\n return withVerifiedUserLeaveRequest(\n await loadLocalOrganizationUserDetail({\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n userId,\n }),\n active.organizationId,\n leaveRequestVerifier(this.runtimeService, active.runtime, active),\n );\n }\n\n reconcile(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return Promise.resolve(undefined);\n }\n\n const byKey = this.reconciliationMap(active);\n const key = organizationAccessScopeKey(\n active.organizationId,\n active.userId,\n );\n const existing = byKey.get(key);\n if (existing) {\n return existing;\n }\n\n // Snapshot the server-denied flag before reconciling. A reconcile that\n // flips it back to readable means org access was just restored (e.g. the\n // user was re-added to a group), and any write lanes idled by\n // permission-denied submissions have no self re-arm — regaining access is\n // their retry signal, mirroring how billing recovery re-requests all\n // lanes. Only a genuine server denial counts: a local session reset also\n // marks scopes denied, and re-arming on its first reconcile would race the\n // startup sync passes (e.g. pending-create adoption between panes).\n const accessWasDenied = wasOrganizationPresentationAccessDeniedByServer(\n {\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n requesterUserId: active.userId,\n },\n \"readModel\",\n );\n const domainScope = active.runtime.state.domainScope;\n const stillCurrent = () =>\n isOrganizationDataRuntimeCurrent(\n this.runtimeService,\n active,\n domainScope,\n );\n\n const reconciliation = reconcileOrganizationDirectoryAndGroups({\n apiClient: active.runtime.apiClient,\n currentUserId: active.userId,\n execSql: active.runtime.infra.execSql,\n logError: active.runtime.util.logError,\n organizationId: active.organizationId,\n })\n .then(async (directoryAndGroups) => {\n if (!stillCurrent()) return null;\n // Feed success restores retry eligibility even if name decryption fails.\n const accessWasRestored =\n accessWasDenied &&\n directoryAndGroups !== null &&\n directoryAndGroups !== undefined;\n if (accessWasRestored)\n await recoverOrganizationAccess({\n domainScope,\n execSql: active.runtime.infra.execSql,\n organizationId: active.organizationId,\n stillCurrent,\n userId: active.userId,\n });\n if (!stillCurrent()) return null;\n return withVerifiedLeaveRequests(\n await hydrateOrganizationGroupNamesForRuntime(\n this.runtimeService,\n active,\n domainScope,\n directoryAndGroups,\n ),\n leaveRequestVerifier(this.runtimeService, active.runtime, active),\n );\n })\n .finally(() => {\n if (byKey.get(key) === reconciliation) {\n byKey.delete(key);\n }\n });\n byKey.set(key, reconciliation);\n return reconciliation;\n }\n\n async reconcileAfterMutation(\n organizationId?: string,\n ): Promise<OrganizationDirectoryAndGroups | null | undefined> {\n const active = activeOrganizationDataRuntime(\n this.runtimeService,\n organizationId,\n );\n if (!active?.runtime.state.online) {\n return undefined;\n }\n const existing = this.reconciliationMap(active).get(\n organizationAccessScopeKey(active.organizationId, active.userId),\n );\n if (existing) {\n await existing.catch(() => null);\n }\n return this.reconcile(active.organizationId);\n }\n}\n\nexport function createOrganizationReadModelCoordinator(\n runtimeService: InternalRuntime,\n): OrganizationReadModelCoordinator {\n const existing = coordinatorsByRuntime.get(runtimeService);\n if (existing) {\n return existing;\n }\n\n const coordinator = new OrganizationReadModelCoordinatorImpl(runtimeService);\n coordinatorsByRuntime.set(runtimeService, coordinator);\n return coordinator;\n}\n"]}
|
|
@@ -2095,6 +2095,13 @@ export declare class ApiClient {
|
|
|
2095
2095
|
organizationId: string;
|
|
2096
2096
|
userId: string;
|
|
2097
2097
|
requestedAt: string;
|
|
2098
|
+
membersHead: {
|
|
2099
|
+
principalId: string;
|
|
2100
|
+
version: number;
|
|
2101
|
+
keyEpoch: number;
|
|
2102
|
+
stateHash: string;
|
|
2103
|
+
keyFingerprint: string;
|
|
2104
|
+
};
|
|
2098
2105
|
signature: string;
|
|
2099
2106
|
} | null;
|
|
2100
2107
|
profileDocumentId: string | null;
|
|
@@ -7,7 +7,7 @@ export declare function signOrganizationLeaveRequest(payload: LeaveRequestPayloa
|
|
|
7
7
|
/**
|
|
8
8
|
* Whether `value` is a well-formed leave request signed by the holder of
|
|
9
9
|
* `publicKey`. Callers still check that it names the organization and member
|
|
10
|
-
* they expect.
|
|
10
|
+
* they expect, and that the member has stayed in Members since the cited head.
|
|
11
11
|
*/
|
|
12
12
|
export declare function isValidOrganizationLeaveRequest(value: unknown, publicKey: Uint8Array): value is OrganizationLeaveRequest;
|
|
13
13
|
export {};
|
|
@@ -5,7 +5,14 @@ import { sign } from "./signing/sign.js";
|
|
|
5
5
|
import { verify } from "./signing/verify.js";
|
|
6
6
|
export function organizationLeaveRequestSigningBytes(payload) {
|
|
7
7
|
return new TextEncoder().encode(serializeKeyingCanonicalJson({
|
|
8
|
-
domain: "tearleads.organization-leave-request.
|
|
8
|
+
domain: "tearleads.organization-leave-request.v2",
|
|
9
|
+
membersHead: {
|
|
10
|
+
keyEpoch: payload.membersHead.keyEpoch,
|
|
11
|
+
keyFingerprint: payload.membersHead.keyFingerprint,
|
|
12
|
+
principalId: payload.membersHead.principalId,
|
|
13
|
+
stateHash: payload.membersHead.stateHash,
|
|
14
|
+
version: payload.membersHead.version,
|
|
15
|
+
},
|
|
9
16
|
organizationId: payload.organizationId,
|
|
10
17
|
requestedAt: payload.requestedAt,
|
|
11
18
|
userId: payload.userId,
|
|
@@ -21,7 +28,7 @@ export function signOrganizationLeaveRequest(payload, keys) {
|
|
|
21
28
|
/**
|
|
22
29
|
* Whether `value` is a well-formed leave request signed by the holder of
|
|
23
30
|
* `publicKey`. Callers still check that it names the organization and member
|
|
24
|
-
* they expect.
|
|
31
|
+
* they expect, and that the member has stayed in Members since the cited head.
|
|
25
32
|
*/
|
|
26
33
|
export function isValidOrganizationLeaveRequest(value, publicKey) {
|
|
27
34
|
const parsed = OrganizationLeaveRequestSchema.safeParse(value);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"organizationLeaveRequest.js","sourceRoot":"","sources":["organizationLeaveRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAEL,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C,MAAM,UAAU,oCAAoC,CAClD,OAA4B;IAE5B,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAC7B,4BAA4B,CAAC;QAC3B,MAAM,EAAE,yCAAyC;QACjD,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,4BAA4B,CAC1C,OAA4B,EAC5B,IAA+C;IAE/C,OAAO,8BAA8B,CAAC,KAAK,CAAC;QAC1C,GAAG,OAAO;QACV,SAAS,EAAE,aAAa,CACtB,IAAI,CACF,oCAAoC,CAAC,OAAO,CAAC,EAC7C,IAAI,CAAC,iBAAiB,CACvB,CACF;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,KAAc,EACd,SAAqB;IAErB,MAAM,MAAM,GAAG,8BAA8B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,SAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CACX,SAAS,EACT,oCAAoC,CAAC,MAAM,CAAC,IAAI,CAAC,EACjD,SAAS,CACV,CAAC;AACJ,CAAC","sourcesContent":["import { base64ToBytes, bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n type OrganizationLeaveRequest,\n OrganizationLeaveRequestSchema,\n} from \"@tearleads/validators/util\";\nimport { serializeKeyingCanonicalJson } from \"./keying/canonical\";\nimport type { SigningKeyPair } from \"./signing/generateKeyPair\";\nimport { sign } from \"./signing/sign\";\nimport { verify } from \"./signing/verify\";\n\ntype LeaveRequestPayload = Omit<OrganizationLeaveRequest, \"signature\">;\n\nexport function organizationLeaveRequestSigningBytes(\n payload: LeaveRequestPayload,\n): Uint8Array {\n return new TextEncoder().encode(\n serializeKeyingCanonicalJson({\n domain: \"tearleads.organization-leave-request.
|
|
1
|
+
{"version":3,"file":"organizationLeaveRequest.js","sourceRoot":"","sources":["organizationLeaveRequest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACnE,OAAO,EAEL,8BAA8B,GAC/B,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,4BAA4B,EAAE,MAAM,oBAAoB,CAAC;AAElE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1C,MAAM,UAAU,oCAAoC,CAClD,OAA4B;IAE5B,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAC7B,4BAA4B,CAAC;QAC3B,MAAM,EAAE,yCAAyC;QACjD,WAAW,EAAE;YACX,QAAQ,EAAE,OAAO,CAAC,WAAW,CAAC,QAAQ;YACtC,cAAc,EAAE,OAAO,CAAC,WAAW,CAAC,cAAc;YAClD,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,WAAW;YAC5C,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,SAAS;YACxC,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,OAAO;SACrC;QACD,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;KACvB,CAAC,CACH,CAAC;AACJ,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,4BAA4B,CAC1C,OAA4B,EAC5B,IAA+C;IAE/C,OAAO,8BAA8B,CAAC,KAAK,CAAC;QAC1C,GAAG,OAAO;QACV,SAAS,EAAE,aAAa,CACtB,IAAI,CACF,oCAAoC,CAAC,OAAO,CAAC,EAC7C,IAAI,CAAC,iBAAiB,CACvB,CACF;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAC7C,KAAc,EACd,SAAqB;IAErB,MAAM,MAAM,GAAG,8BAA8B,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/D,IAAI,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,KAAK,CAAC;IAClC,IAAI,SAAqB,CAAC;IAC1B,IAAI,CAAC;QACH,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CACX,SAAS,EACT,oCAAoC,CAAC,MAAM,CAAC,IAAI,CAAC,EACjD,SAAS,CACV,CAAC;AACJ,CAAC","sourcesContent":["import { base64ToBytes, bytesToBase64 } from \"@tearleads/encoding\";\nimport {\n type OrganizationLeaveRequest,\n OrganizationLeaveRequestSchema,\n} from \"@tearleads/validators/util\";\nimport { serializeKeyingCanonicalJson } from \"./keying/canonical\";\nimport type { SigningKeyPair } from \"./signing/generateKeyPair\";\nimport { sign } from \"./signing/sign\";\nimport { verify } from \"./signing/verify\";\n\ntype LeaveRequestPayload = Omit<OrganizationLeaveRequest, \"signature\">;\n\nexport function organizationLeaveRequestSigningBytes(\n payload: LeaveRequestPayload,\n): Uint8Array {\n return new TextEncoder().encode(\n serializeKeyingCanonicalJson({\n domain: \"tearleads.organization-leave-request.v2\",\n membersHead: {\n keyEpoch: payload.membersHead.keyEpoch,\n keyFingerprint: payload.membersHead.keyFingerprint,\n principalId: payload.membersHead.principalId,\n stateHash: payload.membersHead.stateHash,\n version: payload.membersHead.version,\n },\n organizationId: payload.organizationId,\n requestedAt: payload.requestedAt,\n userId: payload.userId,\n }),\n );\n}\n\n/** Signs a member's request to leave one organization. */\nexport function signOrganizationLeaveRequest(\n payload: LeaveRequestPayload,\n keys: Pick<SigningKeyPair, \"signingPrivateKey\">,\n): OrganizationLeaveRequest {\n return OrganizationLeaveRequestSchema.parse({\n ...payload,\n signature: bytesToBase64(\n sign(\n organizationLeaveRequestSigningBytes(payload),\n keys.signingPrivateKey,\n ),\n ),\n });\n}\n\n/**\n * Whether `value` is a well-formed leave request signed by the holder of\n * `publicKey`. Callers still check that it names the organization and member\n * they expect, and that the member has stayed in Members since the cited head.\n */\nexport function isValidOrganizationLeaveRequest(\n value: unknown,\n publicKey: Uint8Array,\n): value is OrganizationLeaveRequest {\n const parsed = OrganizationLeaveRequestSchema.safeParse(value);\n if (!parsed.success) return false;\n let signature: Uint8Array;\n try {\n signature = base64ToBytes(parsed.data.signature);\n } catch {\n return false;\n }\n return verify(\n signature,\n organizationLeaveRequestSigningBytes(parsed.data),\n publicKey,\n );\n}\n"]}
|
|
@@ -255,6 +255,13 @@ export declare const requestOrganizationLeaveOperation: Omit<{
|
|
|
255
255
|
organizationId: z.ZodCustom<string, string>;
|
|
256
256
|
userId: z.ZodCustom<string, string>;
|
|
257
257
|
requestedAt: z.ZodString;
|
|
258
|
+
membersHead: z.ZodObject<{
|
|
259
|
+
principalId: z.ZodCustom<string, string>;
|
|
260
|
+
version: z.ZodCustom<number, number>;
|
|
261
|
+
keyEpoch: z.ZodCustom<number, number>;
|
|
262
|
+
stateHash: z.ZodString;
|
|
263
|
+
keyFingerprint: z.ZodString;
|
|
264
|
+
}, z.core.$strict>;
|
|
258
265
|
signature: z.ZodString;
|
|
259
266
|
}, z.core.$strict>;
|
|
260
267
|
readonly failureResponses: {
|