@finueva/auth 0.28.0 → 0.30.0
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/README.md +5 -0
- package/dist/server.d.ts +248 -1
- package/dist/server.js +557 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -446,6 +446,7 @@ Long-form task guides are maintained with the Auth source:
|
|
|
446
446
|
- [CLI and native applications](https://github.com/Ifkafin/auth/blob/main/apps/developer/docs/sdk/device.md)
|
|
447
447
|
- [Social ID-token sign-in](https://github.com/Ifkafin/auth/blob/main/apps/developer/docs/sdk/social-sign-in.md)
|
|
448
448
|
- [Organizations and invitations](https://github.com/Ifkafin/auth/blob/main/apps/developer/docs/sdk/organizations.md)
|
|
449
|
+
- [Organization admission](https://github.com/Ifkafin/auth/blob/main/apps/developer/docs/sdk/organization-admission.md)
|
|
449
450
|
- [Drive credentials](https://github.com/Ifkafin/auth/blob/main/apps/developer/docs/sdk/drive-credentials.md)
|
|
450
451
|
- [Errors and recovery](https://github.com/Ifkafin/auth/blob/main/apps/developer/docs/sdk/errors-and-recovery.md)
|
|
451
452
|
|
|
@@ -454,3 +455,7 @@ These links track current source and can describe a newer SDK version. Check the
|
|
|
454
455
|
### Organization presence authorization candidate
|
|
455
456
|
|
|
456
457
|
The request-scoped server method `authorizeOrganizationPresence(organizationId, { applicationId, userIds }, serviceAssertion, { applicationCredential })` forwards fresh actor, application and registered service proofs. The exact ordered selection contains 1 to 50 Auth User IDs. The supplied application credential remains untrusted proof. Auth checks its signature and exact current actor session. The result binds the actor, organization, application and selected IDs; its observation time is not an authority lease. Your application must enforce its own disclosure and visibility policies. Browser and device clients have no direct service facade. This source candidate requires release and registration qualification before use.
|
|
458
|
+
|
|
459
|
+
### Organization admission candidate
|
|
460
|
+
|
|
461
|
+
Import `createOrganizationAdmissionAuth`, `createOrganizationAdmissionBillingAuth`, and `createOrganizationAdmissionDirectoryAuth` from `@finueva/auth/server`. These separate clients expose actor setup operations, private billing attestations, and the pending setup directory. Actor operations require a current incoming request and a separate service assertion. Use `organizationAdmissionBodyDigest(operation, input)` and the client's `audience(operation)` when signing each fresh assertion. A pending setup grants no organization membership or Drive authority. This source candidate requires release and hosted qualification before use.
|
package/dist/server.d.ts
CHANGED
|
@@ -28,6 +28,190 @@ interface FinuevaOrganizationDirectoryAuth {
|
|
|
28
28
|
/** Server-only directory. A directory entry identifies an incarnation; it grants no membership or billing authority. */
|
|
29
29
|
declare function createOrganizationDirectoryAuth(options: OrganizationDirectoryAuthOptions): FinuevaOrganizationDirectoryAuth;
|
|
30
30
|
//#endregion
|
|
31
|
+
//#region src/organization-admission/types.d.ts
|
|
32
|
+
/** Hidden setup identity. This is not organization membership or admission authority. */
|
|
33
|
+
interface OrganizationAdmissionSetup {
|
|
34
|
+
setupId: string;
|
|
35
|
+
applicationId: string;
|
|
36
|
+
organizationId: string;
|
|
37
|
+
organizationGeneration: string;
|
|
38
|
+
kind: "new" | "existing";
|
|
39
|
+
status: "reserved" | "activating" | "activated" | "recovery_required";
|
|
40
|
+
name: string;
|
|
41
|
+
slug: string;
|
|
42
|
+
createdAt: number;
|
|
43
|
+
activatedAt: number | null;
|
|
44
|
+
displayRevision: number;
|
|
45
|
+
amendable: boolean;
|
|
46
|
+
}
|
|
47
|
+
interface OrganizationAdmission {
|
|
48
|
+
applicationId: string;
|
|
49
|
+
organizationId: string;
|
|
50
|
+
organizationGeneration: string;
|
|
51
|
+
state: "pending" | "active";
|
|
52
|
+
basis: "coverage" | "grandfathered" | null;
|
|
53
|
+
policyRevision: number;
|
|
54
|
+
}
|
|
55
|
+
interface OrganizationAdmissionSetupInput {
|
|
56
|
+
applicationId: string;
|
|
57
|
+
setupId: string;
|
|
58
|
+
}
|
|
59
|
+
interface ReserveOrganizationAdmissionInput {
|
|
60
|
+
applicationId: string;
|
|
61
|
+
idempotencyKey: string;
|
|
62
|
+
target: {
|
|
63
|
+
kind: "new";
|
|
64
|
+
name: string;
|
|
65
|
+
slug: string;
|
|
66
|
+
} | {
|
|
67
|
+
kind: "existing";
|
|
68
|
+
organizationId: string;
|
|
69
|
+
organizationGeneration: string;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
interface AmendOrganizationAdmissionInput extends OrganizationAdmissionSetupInput {
|
|
73
|
+
expectedDisplayRevision: number;
|
|
74
|
+
name: string;
|
|
75
|
+
slug: string;
|
|
76
|
+
}
|
|
77
|
+
interface OrganizationAdmissionPageInput {
|
|
78
|
+
applicationId: string;
|
|
79
|
+
cursor?: string;
|
|
80
|
+
limit?: number;
|
|
81
|
+
}
|
|
82
|
+
interface OrganizationAdmissionPage {
|
|
83
|
+
setups: OrganizationAdmissionSetup[];
|
|
84
|
+
/** Only null proves that this collection is exhausted. */
|
|
85
|
+
nextCursor: string | null;
|
|
86
|
+
}
|
|
87
|
+
interface CurrentOrganizationAdmissionInput {
|
|
88
|
+
applicationId: string;
|
|
89
|
+
organizationId: string;
|
|
90
|
+
organizationGeneration?: string;
|
|
91
|
+
}
|
|
92
|
+
interface OrganizationAdmissionIdentityInput {
|
|
93
|
+
applicationId: string;
|
|
94
|
+
organizationId: string;
|
|
95
|
+
}
|
|
96
|
+
/** Exact current organization incarnation only. This grants neither admission nor membership. */
|
|
97
|
+
interface OrganizationAdmissionIdentity {
|
|
98
|
+
organizationId: string;
|
|
99
|
+
organizationGeneration: string;
|
|
100
|
+
}
|
|
101
|
+
interface OrganizationAdmissionCreator {
|
|
102
|
+
/** Private application-scoped binding. Never expose it in the Ops pending projection. */
|
|
103
|
+
userId: string;
|
|
104
|
+
userGeneration: string;
|
|
105
|
+
}
|
|
106
|
+
interface OrganizationAdmissionBillingSetup extends OrganizationAdmissionSetup {
|
|
107
|
+
creator: OrganizationAdmissionCreator;
|
|
108
|
+
}
|
|
109
|
+
interface OrganizationAdmissionSelection {
|
|
110
|
+
revision: number;
|
|
111
|
+
digest: string;
|
|
112
|
+
planId: string;
|
|
113
|
+
priceId: string;
|
|
114
|
+
seats: number;
|
|
115
|
+
}
|
|
116
|
+
interface AttestOrganizationAdmissionInput extends OrganizationAdmissionSetupInput {
|
|
117
|
+
organizationId: string;
|
|
118
|
+
organizationGeneration: string;
|
|
119
|
+
creator: OrganizationAdmissionCreator;
|
|
120
|
+
selection: OrganizationAdmissionSelection;
|
|
121
|
+
receipt: {
|
|
122
|
+
id: string;
|
|
123
|
+
revision: number;
|
|
124
|
+
source: "paid" | "trial" | "complimentary";
|
|
125
|
+
observedPriceId: string | null;
|
|
126
|
+
observedAt: number;
|
|
127
|
+
validUntil: number;
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
interface OrganizationAdmissionReceipt {
|
|
131
|
+
id: string;
|
|
132
|
+
revision: number;
|
|
133
|
+
state: "accepted" | "withdrawn" | "activated";
|
|
134
|
+
}
|
|
135
|
+
interface WithdrawOrganizationAdmissionInput extends OrganizationAdmissionSetupInput {
|
|
136
|
+
selectionDigest: string;
|
|
137
|
+
receiptId: string;
|
|
138
|
+
receiptRevision: number;
|
|
139
|
+
}
|
|
140
|
+
interface FinalizeOrganizationAdmissionInput extends OrganizationAdmissionSetupInput {
|
|
141
|
+
receiptId: string;
|
|
142
|
+
receiptRevision: number;
|
|
143
|
+
}
|
|
144
|
+
interface FinalizedOrganizationAdmission {
|
|
145
|
+
setup: OrganizationAdmissionSetup;
|
|
146
|
+
admission: OrganizationAdmission & {
|
|
147
|
+
state: "active";
|
|
148
|
+
basis: "coverage";
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
type OrganizationAdmissionActorOperation = "reserve" | "read" | "list" | "amend" | "finalize";
|
|
152
|
+
type OrganizationAdmissionOperation = OrganizationAdmissionActorOperation | "current" | "identity" | "lookup" | "attest" | "withdraw" | "pending";
|
|
153
|
+
interface OrganizationAdmissionAuthOptions {
|
|
154
|
+
authOrigin: string;
|
|
155
|
+
fetch?: typeof globalThis.fetch;
|
|
156
|
+
timeoutMs?: number;
|
|
157
|
+
}
|
|
158
|
+
/** Request-scoped actor authority, separate from the application service assertion. */
|
|
159
|
+
interface OrganizationAdmissionActorProof {
|
|
160
|
+
serviceAssertion: string;
|
|
161
|
+
request: Request;
|
|
162
|
+
/** Trusted configured application Origin; never derive it from an untrusted header. */
|
|
163
|
+
appOrigin: string;
|
|
164
|
+
}
|
|
165
|
+
interface FinuevaOrganizationAdmissionAuth {
|
|
166
|
+
audience(operation: OrganizationAdmissionActorOperation | "current" | "identity"): string;
|
|
167
|
+
getOrganizationIdentity(input: OrganizationAdmissionIdentityInput, serviceAssertion: string): Promise<OrganizationAdmissionIdentity | null>;
|
|
168
|
+
amendSetup(input: AmendOrganizationAdmissionInput, proof: OrganizationAdmissionActorProof): Promise<OrganizationAdmissionSetup>;
|
|
169
|
+
reserveSetup(input: ReserveOrganizationAdmissionInput, proof: OrganizationAdmissionActorProof): Promise<OrganizationAdmissionSetup>;
|
|
170
|
+
readSetup(input: OrganizationAdmissionSetupInput, proof: OrganizationAdmissionActorProof): Promise<OrganizationAdmissionSetup | null>;
|
|
171
|
+
listSetups(input: OrganizationAdmissionPageInput, proof: OrganizationAdmissionActorProof): Promise<OrganizationAdmissionPage>;
|
|
172
|
+
getCurrentAdmission(input: CurrentOrganizationAdmissionInput, serviceAssertion: string): Promise<OrganizationAdmission | null>;
|
|
173
|
+
finalizeSetup(input: FinalizeOrganizationAdmissionInput, proof: OrganizationAdmissionActorProof): Promise<FinalizedOrganizationAdmission>;
|
|
174
|
+
}
|
|
175
|
+
interface FinuevaOrganizationAdmissionBillingAuth {
|
|
176
|
+
audience(operation: "lookup" | "attest" | "withdraw"): string;
|
|
177
|
+
lookupSetup(input: OrganizationAdmissionSetupInput, serviceAssertion: string): Promise<OrganizationAdmissionBillingSetup | null>;
|
|
178
|
+
attestCoverage(input: AttestOrganizationAdmissionInput, serviceAssertion: string): Promise<{
|
|
179
|
+
setup: OrganizationAdmissionSetup;
|
|
180
|
+
receipt: OrganizationAdmissionReceipt;
|
|
181
|
+
}>;
|
|
182
|
+
withdrawCoverage(input: WithdrawOrganizationAdmissionInput, serviceAssertion: string): Promise<{
|
|
183
|
+
outcome: "withdrawn" | "already_activated";
|
|
184
|
+
setup: OrganizationAdmissionSetup;
|
|
185
|
+
}>;
|
|
186
|
+
}
|
|
187
|
+
interface FinuevaOrganizationAdmissionDirectoryAuth {
|
|
188
|
+
audience(operation: "pending"): string;
|
|
189
|
+
listPendingSetups(input: OrganizationAdmissionPageInput, serviceAssertion: string): Promise<OrganizationAdmissionPage>;
|
|
190
|
+
}
|
|
191
|
+
//#endregion
|
|
192
|
+
//#region src/organization-admission/index.d.ts
|
|
193
|
+
interface OrganizationAdmissionInputs {
|
|
194
|
+
amend: AmendOrganizationAdmissionInput;
|
|
195
|
+
reserve: ReserveOrganizationAdmissionInput;
|
|
196
|
+
read: OrganizationAdmissionSetupInput;
|
|
197
|
+
list: OrganizationAdmissionPageInput;
|
|
198
|
+
current: CurrentOrganizationAdmissionInput;
|
|
199
|
+
identity: OrganizationAdmissionIdentityInput;
|
|
200
|
+
lookup: OrganizationAdmissionSetupInput;
|
|
201
|
+
pending: OrganizationAdmissionPageInput;
|
|
202
|
+
attest: AttestOrganizationAdmissionInput;
|
|
203
|
+
withdraw: WithdrawOrganizationAdmissionInput;
|
|
204
|
+
finalize: FinalizeOrganizationAdmissionInput;
|
|
205
|
+
}
|
|
206
|
+
/** Hash the strict normalized operation input before signing its bodyDigest claim. No authority is created. */
|
|
207
|
+
declare function organizationAdmissionBodyDigest<Operation extends OrganizationAdmissionOperation>(operation: Operation, input: OrganizationAdmissionInputs[Operation]): Promise<string>;
|
|
208
|
+
/** Server-only actor and current-admission client. Each call needs a fresh exact-body service assertion. */
|
|
209
|
+
declare function createOrganizationAdmissionAuth(options: OrganizationAdmissionAuthOptions): FinuevaOrganizationAdmissionAuth;
|
|
210
|
+
/** Server-only billing capability. It never forwards actor session headers. */
|
|
211
|
+
declare function createOrganizationAdmissionBillingAuth(options: OrganizationAdmissionAuthOptions): FinuevaOrganizationAdmissionBillingAuth;
|
|
212
|
+
/** Server-only pending projection. It contains no creator binding and grants no organization authority. */
|
|
213
|
+
declare function createOrganizationAdmissionDirectoryAuth(options: OrganizationAdmissionAuthOptions): FinuevaOrganizationAdmissionDirectoryAuth;
|
|
214
|
+
//#endregion
|
|
31
215
|
//#region src/product-operations/types.d.ts
|
|
32
216
|
type AccountProductOperationPhase = "snapshot" | "consume" | "receipt";
|
|
33
217
|
interface AccountProductOperationProof {
|
|
@@ -258,6 +442,69 @@ interface FinuevaDriveProvisioningAuth {
|
|
|
258
442
|
/** Service authority only. Never pass an incoming User request or session to this client. */
|
|
259
443
|
declare function createDriveProvisioningAuth(options: DriveProvisioningAuthOptions): FinuevaDriveProvisioningAuth;
|
|
260
444
|
//#endregion
|
|
445
|
+
//#region src/user-directory.d.ts
|
|
446
|
+
interface UserDirectoryEntry {
|
|
447
|
+
applicationId: string;
|
|
448
|
+
/** Opaque application-scoped identifier. This is not the canonical Auth User ID. */
|
|
449
|
+
userId: string;
|
|
450
|
+
/** Immutable application-scoped incarnation. A replacement User cannot inherit it. */
|
|
451
|
+
userGeneration: string;
|
|
452
|
+
lifecycle: "active" | "suspended" | "deleted";
|
|
453
|
+
}
|
|
454
|
+
interface UserDirectoryLookupInput {
|
|
455
|
+
applicationId: string;
|
|
456
|
+
userId: string;
|
|
457
|
+
userGeneration: string;
|
|
458
|
+
}
|
|
459
|
+
interface UserDirectoryListInput {
|
|
460
|
+
applicationId: string;
|
|
461
|
+
limit?: number;
|
|
462
|
+
cursor?: string;
|
|
463
|
+
}
|
|
464
|
+
interface UserDirectoryMembersInput extends UserDirectoryListInput {
|
|
465
|
+
organizationId: string;
|
|
466
|
+
organizationGeneration: string;
|
|
467
|
+
}
|
|
468
|
+
interface UserDirectoryResolveInput {
|
|
469
|
+
applicationId: string;
|
|
470
|
+
authUserId: string;
|
|
471
|
+
}
|
|
472
|
+
interface UserDirectoryPage {
|
|
473
|
+
users: UserDirectoryEntry[];
|
|
474
|
+
/** Only null means the collection is exhausted. */ nextCursor: string | null;
|
|
475
|
+
}
|
|
476
|
+
interface UserDirectoryMember {
|
|
477
|
+
user: UserDirectoryEntry;
|
|
478
|
+
role: "owner" | "admin" | "member";
|
|
479
|
+
membershipStatus: "active" | "suspended";
|
|
480
|
+
}
|
|
481
|
+
interface UserDirectoryMembersPage {
|
|
482
|
+
applicationId: string;
|
|
483
|
+
organizationId: string;
|
|
484
|
+
organizationGeneration: string;
|
|
485
|
+
members: UserDirectoryMember[];
|
|
486
|
+
nextCursor: string | null;
|
|
487
|
+
}
|
|
488
|
+
/** Private service authority. Never forward this object to an operator or browser. */
|
|
489
|
+
interface UserDirectoryBinding {
|
|
490
|
+
user: UserDirectoryEntry;
|
|
491
|
+
authUserId: string;
|
|
492
|
+
}
|
|
493
|
+
interface UserDirectoryAuthOptions {
|
|
494
|
+
authOrigin: string;
|
|
495
|
+
fetch?: typeof globalThis.fetch;
|
|
496
|
+
timeoutMs?: number;
|
|
497
|
+
}
|
|
498
|
+
interface FinuevaUserDirectoryAuth {
|
|
499
|
+
listUsers(input: UserDirectoryListInput, assertion: string): Promise<UserDirectoryPage>;
|
|
500
|
+
lookupUser(input: UserDirectoryLookupInput, assertion: string): Promise<UserDirectoryEntry | null>;
|
|
501
|
+
listOrganizationMembers(input: UserDirectoryMembersInput, assertion: string): Promise<UserDirectoryMembersPage>;
|
|
502
|
+
resolveUser(input: UserDirectoryResolveInput, assertion: string): Promise<UserDirectoryEntry | null>;
|
|
503
|
+
resolveUserBinding(input: UserDirectoryLookupInput, assertion: string): Promise<UserDirectoryBinding | null>;
|
|
504
|
+
}
|
|
505
|
+
/** Server-only service assertions. This client has no session authority and performs no automatic retry. */
|
|
506
|
+
declare function createUserDirectoryAuth(options: UserDirectoryAuthOptions): FinuevaUserDirectoryAuth;
|
|
507
|
+
//#endregion
|
|
261
508
|
//#region src/server.d.ts
|
|
262
509
|
interface ServerAuthOptions {
|
|
263
510
|
authOrigin: string;
|
|
@@ -322,4 +569,4 @@ interface FinuevaServerAuth {
|
|
|
322
569
|
}
|
|
323
570
|
declare function createServerAuth(options: ServerAuthOptions): FinuevaServerAuth;
|
|
324
571
|
//#endregion
|
|
325
|
-
export { type AcceptInvitationInput, type AccountProductOperationAuthOptions, type AccountProductOperationConsumer, type AccountProductOperationInput, type AccountProductOperationPhase, type AccountProductOperationProof, type AccountProductOperationReceipt, type AccountProductOperationSnapshot, type AccountProductOperationSnapshotInput, type AddedOrganizationTeamMember, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthSession, type AuthUser, type CanceledOrganizationInvitation, type CompleteGoogleAccountRecoveryInput, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type DeclineInvitationInput, type DeletedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type DriveProvisioningAuthOptions, type DriveProvisioningCredential, type DriveRecipient, type DriveRecipientAuthOptions, type FinuevaDriveProvisioningAuth, type FinuevaDriveRecipientAuth, type FinuevaIdentityResolverAuth, type FinuevaMembershipResolverAuth, type FinuevaOrganizationDirectoryAuth, FinuevaServerAuth, type GoogleAccountRecovery, type GoogleAccountRecoveryInput, type IdentityResolverAuthOptions, type InvitationAcceptance, type InvitationDecline, type MembershipResolverAuthOptions, type OrganizationApplicationRegistration, type OrganizationDeparture, type OrganizationDirectoryAuthOptions, type OrganizationDirectoryEntry, type OrganizationDirectoryLookupInput, type OrganizationDirectoryPage, type OrganizationDirectorySearchInput, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberApplicationAccess, type OrganizationMemberApplicationAccessInput, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationMemberPageInput, type OrganizationPage, type OrganizationPageInput, type OrganizationPresenceAuthorization, type OrganizationPresenceInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, type OrganizationWorkspaceSelection, type PersonalWorkspaceSelection, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RegisterOrganizationApplicationInput, type RegisteredOrganizationApplication, type RemovedOrganizationMember, type RemovedOrganizationTeamMember, type ResentOrganizationInvitation, type ResolveDriveRecipientInput, type ResolveIdentityInput, type ResolveMembershipBatchInput, type ResolveMembershipInput, type ResolvedIdentity, type ResolvedMembership, type ResolvedMembershipBatch, type ResolvedMembershipRole, ServerAuthOptions, ServerInvitationAcceptance, ServerSignOutResult, ServerSocialIdTokenSession, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UserApiCredential, type UserApiCredentialInput, type UserApiIdentity, type UserApiVerifierOptions, type WorkspaceSelection, createAccountProductOperationAuth, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createOrganizationDirectoryAuth, createServerAuth, createUserApiVerifier };
|
|
572
|
+
export { type AcceptInvitationInput, type AccountProductOperationAuthOptions, type AccountProductOperationConsumer, type AccountProductOperationInput, type AccountProductOperationPhase, type AccountProductOperationProof, type AccountProductOperationReceipt, type AccountProductOperationSnapshot, type AccountProductOperationSnapshotInput, type AddedOrganizationTeamMember, type AmendOrganizationAdmissionInput, type AttestOrganizationAdmissionInput, AuthError, type AuthErrorCode, type AuthErrorStatus, type AuthOrganization, type AuthSession, type AuthUser, type CanceledOrganizationInvitation, type CompleteGoogleAccountRecoveryInput, type CreateOrganizationMemberInvitationInput, type CreatedOrganization, type CreatedOrganizationMemberInvitation, type CreatedOrganizationTeam, type CurrentOrganizationAdmissionInput, type DeclineInvitationInput, type DeletedOrganizationTeam, type DriveCredential, type DriveCredentialInput, type DriveProvisioningAuthOptions, type DriveProvisioningCredential, type DriveRecipient, type DriveRecipientAuthOptions, type FinalizeOrganizationAdmissionInput, type FinalizedOrganizationAdmission, type FinuevaDriveProvisioningAuth, type FinuevaDriveRecipientAuth, type FinuevaIdentityResolverAuth, type FinuevaMembershipResolverAuth, type FinuevaOrganizationAdmissionAuth, type FinuevaOrganizationAdmissionBillingAuth, type FinuevaOrganizationAdmissionDirectoryAuth, type FinuevaOrganizationDirectoryAuth, FinuevaServerAuth, type FinuevaUserDirectoryAuth, type GoogleAccountRecovery, type GoogleAccountRecoveryInput, type IdentityResolverAuthOptions, type InvitationAcceptance, type InvitationDecline, type MembershipResolverAuthOptions, type OrganizationAdmission, type OrganizationAdmissionActorOperation, type OrganizationAdmissionActorProof, type OrganizationAdmissionAuthOptions, type OrganizationAdmissionBillingSetup, type OrganizationAdmissionCreator, type OrganizationAdmissionIdentity, type OrganizationAdmissionIdentityInput, type OrganizationAdmissionInputs, type OrganizationAdmissionOperation, type OrganizationAdmissionPage, type OrganizationAdmissionPageInput, type OrganizationAdmissionReceipt, type OrganizationAdmissionSelection, type OrganizationAdmissionSetup, type OrganizationAdmissionSetupInput, type OrganizationApplicationRegistration, type OrganizationDeparture, type OrganizationDirectoryAuthOptions, type OrganizationDirectoryEntry, type OrganizationDirectoryLookupInput, type OrganizationDirectoryPage, type OrganizationDirectorySearchInput, type OrganizationDisplay, type OrganizationInvitation, type OrganizationInvitationPage, type OrganizationMember, type OrganizationMemberApplicationAccess, type OrganizationMemberApplicationAccessInput, type OrganizationMemberAuthority, type OrganizationMemberPage, type OrganizationMemberPageInput, type OrganizationPage, type OrganizationPageInput, type OrganizationPresenceAuthorization, type OrganizationPresenceInput, type OrganizationTeam, type OrganizationTeamDisplay, type OrganizationTeamMemberPage, type OrganizationTeamPage, type OrganizationWorkspaceSelection, type PersonalWorkspaceSelection, type ReceivedOrganizationInvitation, type ReceivedOrganizationInvitationPage, type RegisterOrganizationApplicationInput, type RegisteredOrganizationApplication, type RemovedOrganizationMember, type RemovedOrganizationTeamMember, type ResentOrganizationInvitation, type ReserveOrganizationAdmissionInput, type ResolveDriveRecipientInput, type ResolveIdentityInput, type ResolveMembershipBatchInput, type ResolveMembershipInput, type ResolvedIdentity, type ResolvedMembership, type ResolvedMembershipBatch, type ResolvedMembershipRole, ServerAuthOptions, ServerInvitationAcceptance, ServerSignOutResult, ServerSocialIdTokenSession, type SocialIdTokenInput, type SocialIdTokenProvider, type UpdateOrganizationDisplayInput, type UpdateOrganizationTeamDisplayInput, type UserApiCredential, type UserApiCredentialInput, type UserApiIdentity, type UserApiVerifierOptions, type UserDirectoryAuthOptions, type UserDirectoryBinding, type UserDirectoryEntry, type UserDirectoryListInput, type UserDirectoryLookupInput, type UserDirectoryMember, type UserDirectoryMembersInput, type UserDirectoryMembersPage, type UserDirectoryPage, type UserDirectoryResolveInput, type WithdrawOrganizationAdmissionInput, type WorkspaceSelection, createAccountProductOperationAuth, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createOrganizationAdmissionAuth, createOrganizationAdmissionBillingAuth, createOrganizationAdmissionDirectoryAuth, createOrganizationDirectoryAuth, createServerAuth, createUserApiVerifier, createUserDirectoryAuth, organizationAdmissionBodyDigest };
|
package/dist/server.js
CHANGED
|
@@ -1397,6 +1397,400 @@ function createOrganizationDirectoryAuth(options) {
|
|
|
1397
1397
|
};
|
|
1398
1398
|
}
|
|
1399
1399
|
//#endregion
|
|
1400
|
+
//#region src/organization-admission/contract.ts
|
|
1401
|
+
const invalid$1 = () => new AuthError("invalid_request", 400);
|
|
1402
|
+
const positive = (value) => typeof value === "number" && Number.isSafeInteger(value) && value > 0 && value < Number.MAX_SAFE_INTEGER;
|
|
1403
|
+
const timestamp$1 = (value) => typeof value === "number" && Number.isSafeInteger(value) && value >= 0 && value <= 864e13;
|
|
1404
|
+
const digest$2 = (value) => typeof value === "string" && /^[a-f0-9]{64}$(?![\s\S])/.test(value);
|
|
1405
|
+
const text = (value) => typeof value === "string" && value.length > 0 && new TextEncoder().encode(value).byteLength <= 255;
|
|
1406
|
+
const slug = (value) => typeof value === "string" && /^[a-z0-9-]{1,128}$(?![\s\S])/.test(value);
|
|
1407
|
+
function setupInput(input, additional = []) {
|
|
1408
|
+
if (!exact$6(input, [
|
|
1409
|
+
"applicationId",
|
|
1410
|
+
"setupId",
|
|
1411
|
+
...additional
|
|
1412
|
+
]) || !directoryId(input.applicationId) || !directoryGeneration(input.setupId)) throw invalid$1();
|
|
1413
|
+
}
|
|
1414
|
+
function pageInput$1(input) {
|
|
1415
|
+
if (!record$1(input) || Object.keys(input).some((key) => ![
|
|
1416
|
+
"applicationId",
|
|
1417
|
+
"cursor",
|
|
1418
|
+
"limit"
|
|
1419
|
+
].includes(key)) || !directoryId(input.applicationId) || input.cursor !== void 0 && (typeof input.cursor !== "string" || input.cursor.length < 1 || input.cursor.length > 2048) || input.limit !== void 0 && (!positive(input.limit) || input.limit > 50)) throw invalid$1();
|
|
1420
|
+
}
|
|
1421
|
+
const setupKeys = [
|
|
1422
|
+
"setupId",
|
|
1423
|
+
"applicationId",
|
|
1424
|
+
"organizationId",
|
|
1425
|
+
"organizationGeneration",
|
|
1426
|
+
"kind",
|
|
1427
|
+
"status",
|
|
1428
|
+
"name",
|
|
1429
|
+
"slug",
|
|
1430
|
+
"createdAt",
|
|
1431
|
+
"activatedAt",
|
|
1432
|
+
"displayRevision",
|
|
1433
|
+
"amendable"
|
|
1434
|
+
];
|
|
1435
|
+
function setup(value, applicationId, setupId) {
|
|
1436
|
+
if (!exact$6(value, setupKeys) || !directoryGeneration(value.setupId) || setupId !== void 0 && value.setupId !== setupId || value.applicationId !== applicationId || !directoryId(value.organizationId) || !directoryGeneration(value.organizationGeneration) || value.kind !== "new" && value.kind !== "existing" || ![
|
|
1437
|
+
"reserved",
|
|
1438
|
+
"activating",
|
|
1439
|
+
"activated",
|
|
1440
|
+
"recovery_required"
|
|
1441
|
+
].includes(String(value.status)) || !text(value.name) || !slug(value.slug) || !timestamp$1(value.createdAt) || !positive(value.displayRevision) || typeof value.amendable !== "boolean" || value.amendable && (value.kind !== "new" || value.status === "activated" || value.status === "activating") || value.activatedAt !== null && (!timestamp$1(value.activatedAt) || value.activatedAt < value.createdAt) || value.status === "activated" !== (value.activatedAt !== null)) throw authorityUnavailable();
|
|
1442
|
+
return {
|
|
1443
|
+
setupId: value.setupId,
|
|
1444
|
+
applicationId,
|
|
1445
|
+
organizationId: value.organizationId,
|
|
1446
|
+
organizationGeneration: value.organizationGeneration,
|
|
1447
|
+
kind: value.kind,
|
|
1448
|
+
status: value.status,
|
|
1449
|
+
name: value.name,
|
|
1450
|
+
slug: value.slug,
|
|
1451
|
+
createdAt: value.createdAt,
|
|
1452
|
+
activatedAt: value.activatedAt,
|
|
1453
|
+
displayRevision: value.displayRevision,
|
|
1454
|
+
amendable: value.amendable
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
function billingSetup(value, applicationId, setupId) {
|
|
1458
|
+
if (!exact$6(value, [...setupKeys, "creator"]) || !exact$6(value.creator, ["userId", "userGeneration"]) || !directoryGeneration(value.creator.userId) || !directoryGeneration(value.creator.userGeneration)) throw authorityUnavailable();
|
|
1459
|
+
const { creator: _creator, ...projection } = value;
|
|
1460
|
+
return {
|
|
1461
|
+
...setup(projection, applicationId, setupId),
|
|
1462
|
+
creator: {
|
|
1463
|
+
userId: value.creator.userId,
|
|
1464
|
+
userGeneration: value.creator.userGeneration
|
|
1465
|
+
}
|
|
1466
|
+
};
|
|
1467
|
+
}
|
|
1468
|
+
function page(value, input, pending = false) {
|
|
1469
|
+
if (!exact$6(value, ["setups", "nextCursor"]) || !Array.isArray(value.setups) || value.setups.length > (input.limit ?? 25) || value.nextCursor !== null && (typeof value.nextCursor !== "string" || !value.nextCursor.length || value.nextCursor.length > 2048 || value.nextCursor === input.cursor)) throw authorityUnavailable();
|
|
1470
|
+
const setups = value.setups.map((item) => setup(item, input.applicationId));
|
|
1471
|
+
if (new Set(setups.map((item) => item.setupId)).size !== setups.length || pending && setups.some((item) => item.status === "activated")) throw authorityUnavailable();
|
|
1472
|
+
return {
|
|
1473
|
+
setups,
|
|
1474
|
+
nextCursor: value.nextCursor
|
|
1475
|
+
};
|
|
1476
|
+
}
|
|
1477
|
+
function admission(value, applicationId, organizationId, generation) {
|
|
1478
|
+
if (!exact$6(value, [
|
|
1479
|
+
"applicationId",
|
|
1480
|
+
"organizationId",
|
|
1481
|
+
"organizationGeneration",
|
|
1482
|
+
"state",
|
|
1483
|
+
"basis",
|
|
1484
|
+
"policyRevision"
|
|
1485
|
+
]) || value.applicationId !== applicationId || value.organizationId !== organizationId || !directoryGeneration(value.organizationGeneration) || generation !== void 0 && value.organizationGeneration !== generation || !positive(value.policyRevision) || value.state !== "pending" && value.state !== "active" || (value.state === "pending" ? value.basis !== null : value.basis !== "coverage" && value.basis !== "grandfathered")) throw authorityUnavailable();
|
|
1486
|
+
return {
|
|
1487
|
+
applicationId,
|
|
1488
|
+
organizationId,
|
|
1489
|
+
organizationGeneration: value.organizationGeneration,
|
|
1490
|
+
state: value.state,
|
|
1491
|
+
basis: value.basis,
|
|
1492
|
+
policyRevision: value.policyRevision
|
|
1493
|
+
};
|
|
1494
|
+
}
|
|
1495
|
+
//#endregion
|
|
1496
|
+
//#region src/organization-admission/transport.ts
|
|
1497
|
+
function actorHeaders(proof) {
|
|
1498
|
+
if (!exact$6(proof, [
|
|
1499
|
+
"serviceAssertion",
|
|
1500
|
+
"request",
|
|
1501
|
+
"appOrigin"
|
|
1502
|
+
]) || !(proof.request instanceof Request)) throw invalid$1();
|
|
1503
|
+
const authorization = proof.request.headers.get("authorization");
|
|
1504
|
+
if (authorization !== null) {
|
|
1505
|
+
if (new TextEncoder().encode(authorization).byteLength > 16 * 1024 || /[^\x20-\x7e]/.test(authorization) || !/^Bearer [^\s,]+$/i.test(authorization) || /^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$/.test(authorization.slice(7))) throw new AuthError("authentication_required", 401);
|
|
1506
|
+
return { authorization };
|
|
1507
|
+
}
|
|
1508
|
+
const cookie = (proof.request.headers.get("cookie") ?? "").split(";").map((entry) => entry.trim()).filter((entry) => {
|
|
1509
|
+
const separator = entry.indexOf("=");
|
|
1510
|
+
const name = entry.slice(0, separator);
|
|
1511
|
+
return separator > 0 && (name.startsWith("better-auth.") || name.startsWith("__Secure-better-auth."));
|
|
1512
|
+
}).join("; ");
|
|
1513
|
+
if (!cookie || new TextEncoder().encode(cookie).byteLength > 16 * 1024) throw new AuthError("authentication_required", 401);
|
|
1514
|
+
const origin = normalizeOrigin(proof.appOrigin, "appOrigin");
|
|
1515
|
+
if (proof.request.headers.get("origin") !== origin) throw new AuthError("request_origin_denied", 403);
|
|
1516
|
+
return {
|
|
1517
|
+
cookie,
|
|
1518
|
+
origin
|
|
1519
|
+
};
|
|
1520
|
+
}
|
|
1521
|
+
function transport(options, operations) {
|
|
1522
|
+
const base = joinURL(normalizeOrigin(options.authOrigin, "authOrigin"), "api/v1/auth/organization-admission");
|
|
1523
|
+
const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
1524
|
+
if (typeof fetchImpl !== "function") throw new TypeError("fetch is required");
|
|
1525
|
+
const timeoutMs = normalizeTimeout(options.timeoutMs);
|
|
1526
|
+
let inFlight = 0;
|
|
1527
|
+
function audience(operation) {
|
|
1528
|
+
if (!operations.includes(operation)) throw invalid$1();
|
|
1529
|
+
return joinURL(base, operation);
|
|
1530
|
+
}
|
|
1531
|
+
async function exchange(operation, body, assertion, actor) {
|
|
1532
|
+
const url = audience(operation);
|
|
1533
|
+
if (typeof assertion !== "string" || assertion.length > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/.test(assertion) || new TextEncoder().encode(JSON.stringify(body)).byteLength > 8192) throw invalid$1();
|
|
1534
|
+
const headers = actor ? actorHeaders(actor) : {};
|
|
1535
|
+
if (inFlight >= 4) throw new AuthError("state_conflict", 409);
|
|
1536
|
+
inFlight += 1;
|
|
1537
|
+
const controller = new AbortController();
|
|
1538
|
+
let timer;
|
|
1539
|
+
const deadline = new Promise((_, reject) => {
|
|
1540
|
+
timer = setTimeout(() => {
|
|
1541
|
+
reject(authorityUnavailable());
|
|
1542
|
+
controller.abort();
|
|
1543
|
+
}, timeoutMs);
|
|
1544
|
+
});
|
|
1545
|
+
try {
|
|
1546
|
+
return await Promise.race([requestJson(url, {
|
|
1547
|
+
fetch: fetchImpl,
|
|
1548
|
+
timeoutMs,
|
|
1549
|
+
method: "POST",
|
|
1550
|
+
credentials: "omit",
|
|
1551
|
+
cache: "no-store",
|
|
1552
|
+
signal: controller.signal,
|
|
1553
|
+
maxResponseBytes: 64 * 1024,
|
|
1554
|
+
headers: {
|
|
1555
|
+
...headers,
|
|
1556
|
+
"x-finueva-service-assertion": assertion,
|
|
1557
|
+
"content-type": "application/json",
|
|
1558
|
+
accept: "application/json"
|
|
1559
|
+
},
|
|
1560
|
+
body,
|
|
1561
|
+
mapError: (_value, status, retryAfter) => {
|
|
1562
|
+
if (status === 400) return invalid$1();
|
|
1563
|
+
if (status === 401) return new AuthError("authentication_required", 401);
|
|
1564
|
+
if (status === 403) return new AuthError("access_denied", 403);
|
|
1565
|
+
if (status === 409) return new AuthError("state_conflict", 409);
|
|
1566
|
+
if (status === 429 && retryAfter !== null && /^(?:[1-9]|[1-5][0-9]|60)$/.test(retryAfter)) return new AuthError("auth_request_rate_limited", 429, Number(retryAfter));
|
|
1567
|
+
return authorityUnavailable();
|
|
1568
|
+
}
|
|
1569
|
+
}).finally(() => {
|
|
1570
|
+
inFlight -= 1;
|
|
1571
|
+
}), deadline]);
|
|
1572
|
+
} finally {
|
|
1573
|
+
clearTimeout(timer);
|
|
1574
|
+
controller.abort();
|
|
1575
|
+
}
|
|
1576
|
+
}
|
|
1577
|
+
return {
|
|
1578
|
+
audience,
|
|
1579
|
+
exchange
|
|
1580
|
+
};
|
|
1581
|
+
}
|
|
1582
|
+
//#endregion
|
|
1583
|
+
//#region src/organization-admission/index.ts
|
|
1584
|
+
function validate(operation, input) {
|
|
1585
|
+
if (operation === "reserve") {
|
|
1586
|
+
if (!exact$6(input, [
|
|
1587
|
+
"applicationId",
|
|
1588
|
+
"idempotencyKey",
|
|
1589
|
+
"target"
|
|
1590
|
+
]) || !directoryId(input.applicationId) || typeof input.idempotencyKey !== "string" || !/^[A-Za-z0-9_-]{16,128}$(?![\s\S])/.test(input.idempotencyKey) || !record$1(input.target)) throw invalid$1();
|
|
1591
|
+
const target = input.target;
|
|
1592
|
+
if (target.kind === "new" ? !exact$6(target, [
|
|
1593
|
+
"kind",
|
|
1594
|
+
"name",
|
|
1595
|
+
"slug"
|
|
1596
|
+
]) || !text(target.name) || !slug(target.slug) : target.kind !== "existing" || !exact$6(target, [
|
|
1597
|
+
"kind",
|
|
1598
|
+
"organizationId",
|
|
1599
|
+
"organizationGeneration"
|
|
1600
|
+
]) || !directoryId(target.organizationId) || !directoryGeneration(target.organizationGeneration)) throw invalid$1();
|
|
1601
|
+
} else if (operation === "list" || operation === "pending") {
|
|
1602
|
+
pageInput$1(input);
|
|
1603
|
+
return {
|
|
1604
|
+
...input,
|
|
1605
|
+
limit: input.limit ?? 25
|
|
1606
|
+
};
|
|
1607
|
+
} else if (operation === "identity") {
|
|
1608
|
+
if (!exact$6(input, ["applicationId", "organizationId"]) || !directoryId(input.applicationId) || !directoryId(input.organizationId)) throw invalid$1();
|
|
1609
|
+
} else if (operation === "current") {
|
|
1610
|
+
if (!record$1(input) || Object.keys(input).some((key) => ![
|
|
1611
|
+
"applicationId",
|
|
1612
|
+
"organizationId",
|
|
1613
|
+
"organizationGeneration"
|
|
1614
|
+
].includes(key)) || !directoryId(input.applicationId) || !directoryId(input.organizationId) || input.organizationGeneration !== void 0 && !directoryGeneration(input.organizationGeneration)) throw invalid$1();
|
|
1615
|
+
} else if (operation === "amend") {
|
|
1616
|
+
setupInput(input, [
|
|
1617
|
+
"expectedDisplayRevision",
|
|
1618
|
+
"name",
|
|
1619
|
+
"slug"
|
|
1620
|
+
]);
|
|
1621
|
+
if (!positive(input.expectedDisplayRevision) || !text(input.name) || !slug(input.slug)) throw invalid$1();
|
|
1622
|
+
} else if (operation === "read" || operation === "lookup") setupInput(input);
|
|
1623
|
+
else if (operation === "finalize" || operation === "withdraw") {
|
|
1624
|
+
setupInput(input, [
|
|
1625
|
+
"receiptId",
|
|
1626
|
+
"receiptRevision",
|
|
1627
|
+
...operation === "withdraw" ? ["selectionDigest"] : []
|
|
1628
|
+
]);
|
|
1629
|
+
if (!directoryId(input.receiptId) || !positive(input.receiptRevision) || operation === "withdraw" && !digest$2(input.selectionDigest)) throw invalid$1();
|
|
1630
|
+
} else if (operation === "attest") {
|
|
1631
|
+
setupInput(input, [
|
|
1632
|
+
"organizationId",
|
|
1633
|
+
"organizationGeneration",
|
|
1634
|
+
"creator",
|
|
1635
|
+
"selection",
|
|
1636
|
+
"receipt"
|
|
1637
|
+
]);
|
|
1638
|
+
const { creator, selection, receipt } = input;
|
|
1639
|
+
if (!directoryId(input.organizationId) || !directoryGeneration(input.organizationGeneration) || !exact$6(creator, ["userId", "userGeneration"]) || !directoryGeneration(creator.userId) || !directoryGeneration(creator.userGeneration) || !exact$6(selection, [
|
|
1640
|
+
"revision",
|
|
1641
|
+
"digest",
|
|
1642
|
+
"planId",
|
|
1643
|
+
"priceId",
|
|
1644
|
+
"seats"
|
|
1645
|
+
]) || !positive(selection.revision) || !digest$2(selection.digest) || !directoryId(selection.planId) || !directoryId(selection.priceId) || !positive(selection.seats) || selection.seats > 1e4 || !exact$6(receipt, [
|
|
1646
|
+
"id",
|
|
1647
|
+
"revision",
|
|
1648
|
+
"source",
|
|
1649
|
+
"observedPriceId",
|
|
1650
|
+
"observedAt",
|
|
1651
|
+
"validUntil"
|
|
1652
|
+
]) || !directoryId(receipt.id) || !positive(receipt.revision) || ![
|
|
1653
|
+
"paid",
|
|
1654
|
+
"trial",
|
|
1655
|
+
"complimentary"
|
|
1656
|
+
].includes(String(receipt.source)) || !timestamp$1(receipt.observedAt) || !timestamp$1(receipt.validUntil) || receipt.validUntil <= receipt.observedAt || receipt.validUntil - receipt.observedAt > 6e4 || (receipt.source === "complimentary" ? receipt.observedPriceId !== null : receipt.observedPriceId !== selection.priceId)) throw invalid$1();
|
|
1657
|
+
} else throw invalid$1();
|
|
1658
|
+
return input;
|
|
1659
|
+
}
|
|
1660
|
+
function canonical(value) {
|
|
1661
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
1662
|
+
if (record$1(value)) return `{${Object.keys(value).filter((key) => value[key] !== void 0).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`;
|
|
1663
|
+
return JSON.stringify(value);
|
|
1664
|
+
}
|
|
1665
|
+
async function organizationAdmissionBodyDigest(operation, input) {
|
|
1666
|
+
const bytes = new TextEncoder().encode(canonical(validate(operation, input)));
|
|
1667
|
+
if (bytes.byteLength > 8192) throw invalid$1();
|
|
1668
|
+
return Array.from(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes)), (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
1669
|
+
}
|
|
1670
|
+
function createOrganizationAdmissionAuth(options) {
|
|
1671
|
+
const { audience, exchange } = transport(options, [
|
|
1672
|
+
"reserve",
|
|
1673
|
+
"read",
|
|
1674
|
+
"list",
|
|
1675
|
+
"amend",
|
|
1676
|
+
"current",
|
|
1677
|
+
"identity",
|
|
1678
|
+
"finalize"
|
|
1679
|
+
]);
|
|
1680
|
+
return {
|
|
1681
|
+
audience,
|
|
1682
|
+
async getOrganizationIdentity(input, assertion) {
|
|
1683
|
+
const value = await exchange("identity", validate("identity", input), assertion);
|
|
1684
|
+
if (!exact$6(value, ["organization"])) throw authorityUnavailable();
|
|
1685
|
+
if (value.organization === null) return null;
|
|
1686
|
+
if (!exact$6(value.organization, ["organizationId", "organizationGeneration"]) || value.organization.organizationId !== input.organizationId || !directoryGeneration(value.organization.organizationGeneration)) throw authorityUnavailable();
|
|
1687
|
+
return {
|
|
1688
|
+
organizationId: input.organizationId,
|
|
1689
|
+
organizationGeneration: value.organization.organizationGeneration
|
|
1690
|
+
};
|
|
1691
|
+
},
|
|
1692
|
+
async amendSetup(input, proof) {
|
|
1693
|
+
const value = await exchange("amend", validate("amend", input), proof.serviceAssertion, proof);
|
|
1694
|
+
if (!exact$6(value, ["setup"])) throw authorityUnavailable();
|
|
1695
|
+
const result = setup(value.setup, input.applicationId, input.setupId);
|
|
1696
|
+
if (result.kind !== "new" || result.name !== input.name || result.slug !== input.slug || result.displayRevision !== input.expectedDisplayRevision + 1) throw authorityUnavailable();
|
|
1697
|
+
return result;
|
|
1698
|
+
},
|
|
1699
|
+
async reserveSetup(input, proof) {
|
|
1700
|
+
const body = validate("reserve", input);
|
|
1701
|
+
const value = await exchange("reserve", body, proof.serviceAssertion, proof);
|
|
1702
|
+
if (!exact$6(value, ["setup"])) throw authorityUnavailable();
|
|
1703
|
+
const result = setup(value.setup, input.applicationId);
|
|
1704
|
+
if (result.kind !== input.target.kind || (input.target.kind === "new" ? result.displayRevision === 1 && (result.name !== input.target.name || result.slug !== input.target.slug) : result.organizationId !== input.target.organizationId || result.organizationGeneration !== input.target.organizationGeneration)) throw authorityUnavailable();
|
|
1705
|
+
return result;
|
|
1706
|
+
},
|
|
1707
|
+
async readSetup(input, proof) {
|
|
1708
|
+
const value = await exchange("read", validate("read", input), proof.serviceAssertion, proof);
|
|
1709
|
+
if (!exact$6(value, ["setup"])) throw authorityUnavailable();
|
|
1710
|
+
return value.setup === null ? null : setup(value.setup, input.applicationId, input.setupId);
|
|
1711
|
+
},
|
|
1712
|
+
async listSetups(input, proof) {
|
|
1713
|
+
return page(await exchange("list", validate("list", input), proof.serviceAssertion, proof), input);
|
|
1714
|
+
},
|
|
1715
|
+
async getCurrentAdmission(input, assertion) {
|
|
1716
|
+
const value = await exchange("current", validate("current", input), assertion);
|
|
1717
|
+
if (!exact$6(value, ["admission"])) throw authorityUnavailable();
|
|
1718
|
+
return value.admission === null ? null : admission(value.admission, input.applicationId, input.organizationId, input.organizationGeneration);
|
|
1719
|
+
},
|
|
1720
|
+
async finalizeSetup(input, proof) {
|
|
1721
|
+
const value = await exchange("finalize", validate("finalize", input), proof.serviceAssertion, proof);
|
|
1722
|
+
if (!exact$6(value, ["setup", "admission"])) throw authorityUnavailable();
|
|
1723
|
+
const result = setup(value.setup, input.applicationId, input.setupId);
|
|
1724
|
+
const active = admission(value.admission, input.applicationId, result.organizationId, result.organizationGeneration);
|
|
1725
|
+
if (result.status !== "activated" || active.state !== "active" || active.basis !== "coverage") throw authorityUnavailable();
|
|
1726
|
+
return {
|
|
1727
|
+
setup: result,
|
|
1728
|
+
admission: {
|
|
1729
|
+
...active,
|
|
1730
|
+
state: "active",
|
|
1731
|
+
basis: "coverage"
|
|
1732
|
+
}
|
|
1733
|
+
};
|
|
1734
|
+
}
|
|
1735
|
+
};
|
|
1736
|
+
}
|
|
1737
|
+
function createOrganizationAdmissionBillingAuth(options) {
|
|
1738
|
+
const { audience, exchange } = transport(options, [
|
|
1739
|
+
"lookup",
|
|
1740
|
+
"attest",
|
|
1741
|
+
"withdraw"
|
|
1742
|
+
]);
|
|
1743
|
+
return {
|
|
1744
|
+
audience,
|
|
1745
|
+
async lookupSetup(input, assertion) {
|
|
1746
|
+
const value = await exchange("lookup", validate("lookup", input), assertion);
|
|
1747
|
+
if (!exact$6(value, ["setup"])) throw authorityUnavailable();
|
|
1748
|
+
return value.setup === null ? null : billingSetup(value.setup, input.applicationId, input.setupId);
|
|
1749
|
+
},
|
|
1750
|
+
async attestCoverage(input, assertion) {
|
|
1751
|
+
const value = await exchange("attest", validate("attest", input), assertion);
|
|
1752
|
+
if (!exact$6(value, ["setup", "receipt"]) || !exact$6(value.receipt, [
|
|
1753
|
+
"id",
|
|
1754
|
+
"revision",
|
|
1755
|
+
"state"
|
|
1756
|
+
]) || value.receipt.id !== input.receipt.id || value.receipt.revision !== input.receipt.revision || ![
|
|
1757
|
+
"accepted",
|
|
1758
|
+
"withdrawn",
|
|
1759
|
+
"activated"
|
|
1760
|
+
].includes(String(value.receipt.state))) throw authorityUnavailable();
|
|
1761
|
+
const result = setup(value.setup, input.applicationId, input.setupId);
|
|
1762
|
+
if (result.organizationId !== input.organizationId || result.organizationGeneration !== input.organizationGeneration || value.receipt.state === "activated" !== (result.status === "activated")) throw authorityUnavailable();
|
|
1763
|
+
return {
|
|
1764
|
+
setup: result,
|
|
1765
|
+
receipt: {
|
|
1766
|
+
id: input.receipt.id,
|
|
1767
|
+
revision: input.receipt.revision,
|
|
1768
|
+
state: value.receipt.state
|
|
1769
|
+
}
|
|
1770
|
+
};
|
|
1771
|
+
},
|
|
1772
|
+
async withdrawCoverage(input, assertion) {
|
|
1773
|
+
const value = await exchange("withdraw", validate("withdraw", input), assertion);
|
|
1774
|
+
if (!exact$6(value, ["setup", "outcome"]) || value.outcome !== "withdrawn" && value.outcome !== "already_activated") throw authorityUnavailable();
|
|
1775
|
+
const result = setup(value.setup, input.applicationId, input.setupId);
|
|
1776
|
+
if (value.outcome === "already_activated" !== (result.status === "activated")) throw authorityUnavailable();
|
|
1777
|
+
return {
|
|
1778
|
+
setup: result,
|
|
1779
|
+
outcome: value.outcome
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
function createOrganizationAdmissionDirectoryAuth(options) {
|
|
1785
|
+
const { audience, exchange } = transport(options, ["pending"]);
|
|
1786
|
+
return {
|
|
1787
|
+
audience,
|
|
1788
|
+
async listPendingSetups(input, assertion) {
|
|
1789
|
+
return page(await exchange("pending", validate("pending", input), assertion), input, true);
|
|
1790
|
+
}
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
//#endregion
|
|
1400
1794
|
//#region src/product-operations/contract.ts
|
|
1401
1795
|
const id$2 = /^[A-Za-z0-9_-]{1,128}$(?![\s\S])/;
|
|
1402
1796
|
const digest$1 = /^[a-f0-9]{64}$(?![\s\S])/;
|
|
@@ -3475,6 +3869,168 @@ function createDriveProvisioningAuth(options) {
|
|
|
3475
3869
|
} };
|
|
3476
3870
|
}
|
|
3477
3871
|
//#endregion
|
|
3872
|
+
//#region src/user-directory.ts
|
|
3873
|
+
function user(value, applicationId) {
|
|
3874
|
+
if (!exact$6(value, [
|
|
3875
|
+
"applicationId",
|
|
3876
|
+
"userId",
|
|
3877
|
+
"userGeneration",
|
|
3878
|
+
"lifecycle"
|
|
3879
|
+
]) || value.applicationId !== applicationId || !directoryGeneration(value.userId) || !directoryGeneration(value.userGeneration) || ![
|
|
3880
|
+
"active",
|
|
3881
|
+
"suspended",
|
|
3882
|
+
"deleted"
|
|
3883
|
+
].includes(String(value.lifecycle))) throw authorityUnavailable();
|
|
3884
|
+
return {
|
|
3885
|
+
applicationId,
|
|
3886
|
+
userId: value.userId,
|
|
3887
|
+
userGeneration: value.userGeneration,
|
|
3888
|
+
lifecycle: value.lifecycle
|
|
3889
|
+
};
|
|
3890
|
+
}
|
|
3891
|
+
function exactInput(input) {
|
|
3892
|
+
if (!exact$6(input, [
|
|
3893
|
+
"applicationId",
|
|
3894
|
+
"userId",
|
|
3895
|
+
"userGeneration"
|
|
3896
|
+
]) || !directoryId(input.applicationId) || !directoryGeneration(input.userId) || !directoryGeneration(input.userGeneration)) throw new AuthError("invalid_request", 400);
|
|
3897
|
+
}
|
|
3898
|
+
function pageInput(input, members = false) {
|
|
3899
|
+
if (!record$1(input) || Object.keys(input).some((key) => ![
|
|
3900
|
+
"applicationId",
|
|
3901
|
+
"limit",
|
|
3902
|
+
"cursor",
|
|
3903
|
+
...members ? ["organizationId", "organizationGeneration"] : []
|
|
3904
|
+
].includes(key)) || !directoryId(input.applicationId) || input.limit !== void 0 && (!Number.isInteger(input.limit) || input.limit < 1 || input.limit > 100) || input.cursor !== void 0 && (typeof input.cursor !== "string" || input.cursor.length < 1 || input.cursor.length > 2048) || members && (!directoryId(input.organizationId) || !directoryGeneration(input.organizationGeneration))) throw new AuthError("invalid_request", 400);
|
|
3905
|
+
}
|
|
3906
|
+
function nextCursor(value) {
|
|
3907
|
+
if (value !== null && (typeof value !== "string" || !value.length || value.length > 2048)) throw authorityUnavailable();
|
|
3908
|
+
return value;
|
|
3909
|
+
}
|
|
3910
|
+
function selectedUser(value, input) {
|
|
3911
|
+
const normalized = user(value, input.applicationId);
|
|
3912
|
+
if (normalized.userId !== input.userId || normalized.userGeneration !== input.userGeneration) throw authorityUnavailable();
|
|
3913
|
+
return normalized;
|
|
3914
|
+
}
|
|
3915
|
+
function createUserDirectoryAuth(options) {
|
|
3916
|
+
const origin = normalizeOrigin(options.authOrigin, "authOrigin");
|
|
3917
|
+
const fetchImpl = options.fetch ?? globalThis.fetch?.bind(globalThis);
|
|
3918
|
+
if (typeof fetchImpl !== "function") throw new TypeError("fetch is required");
|
|
3919
|
+
const timeoutMs = normalizeTimeout(options.timeoutMs);
|
|
3920
|
+
let inFlight = 0;
|
|
3921
|
+
async function exchange(operation, body, assertion) {
|
|
3922
|
+
if (typeof assertion !== "string" || assertion.length > 16 * 1024 || !/^[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+$(?![\s\S])/.test(assertion)) throw new AuthError("invalid_request", 400);
|
|
3923
|
+
if (inFlight >= 4) throw new AuthError("state_conflict", 409);
|
|
3924
|
+
inFlight += 1;
|
|
3925
|
+
const controller = new AbortController();
|
|
3926
|
+
let timer;
|
|
3927
|
+
const deadline = new Promise((_, reject) => {
|
|
3928
|
+
timer = setTimeout(() => {
|
|
3929
|
+
reject(authorityUnavailable());
|
|
3930
|
+
controller.abort();
|
|
3931
|
+
}, timeoutMs);
|
|
3932
|
+
});
|
|
3933
|
+
try {
|
|
3934
|
+
return await Promise.race([requestJson(joinURL(origin, "api/v1/auth/user-directory", operation), {
|
|
3935
|
+
fetch: fetchImpl,
|
|
3936
|
+
timeoutMs,
|
|
3937
|
+
method: "POST",
|
|
3938
|
+
credentials: "omit",
|
|
3939
|
+
cache: "no-store",
|
|
3940
|
+
headers: {
|
|
3941
|
+
"x-finueva-service-assertion": assertion,
|
|
3942
|
+
"content-type": "application/json",
|
|
3943
|
+
accept: "application/json"
|
|
3944
|
+
},
|
|
3945
|
+
body,
|
|
3946
|
+
maxResponseBytes: 128 * 1024,
|
|
3947
|
+
signal: controller.signal
|
|
3948
|
+
}).finally(() => {
|
|
3949
|
+
inFlight -= 1;
|
|
3950
|
+
}), deadline]);
|
|
3951
|
+
} catch (cause) {
|
|
3952
|
+
if (cause instanceof AuthError) throw cause;
|
|
3953
|
+
throw authorityUnavailable();
|
|
3954
|
+
} finally {
|
|
3955
|
+
clearTimeout(timer);
|
|
3956
|
+
controller.abort();
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
return {
|
|
3960
|
+
async listUsers(input, assertion) {
|
|
3961
|
+
pageInput(input);
|
|
3962
|
+
const value = await exchange("list", input, assertion);
|
|
3963
|
+
if (!exact$6(value, ["users", "nextCursor"]) || !Array.isArray(value.users) || value.users.length > (input.limit ?? 50)) throw authorityUnavailable();
|
|
3964
|
+
const users = value.users.map((item) => user(item, input.applicationId));
|
|
3965
|
+
if (users.some((item) => item.lifecycle === "deleted") || new Set(users.map((item) => item.userId)).size !== users.length) throw authorityUnavailable();
|
|
3966
|
+
return {
|
|
3967
|
+
users,
|
|
3968
|
+
nextCursor: nextCursor(value.nextCursor)
|
|
3969
|
+
};
|
|
3970
|
+
},
|
|
3971
|
+
async lookupUser(input, assertion) {
|
|
3972
|
+
exactInput(input);
|
|
3973
|
+
const value = await exchange("lookup", input, assertion);
|
|
3974
|
+
if (!exact$6(value, ["user"])) throw authorityUnavailable();
|
|
3975
|
+
return value.user === null ? null : selectedUser(value.user, input);
|
|
3976
|
+
},
|
|
3977
|
+
async listOrganizationMembers(input, assertion) {
|
|
3978
|
+
pageInput(input, true);
|
|
3979
|
+
const value = await exchange("members", input, assertion);
|
|
3980
|
+
if (!exact$6(value, [
|
|
3981
|
+
"applicationId",
|
|
3982
|
+
"organizationId",
|
|
3983
|
+
"organizationGeneration",
|
|
3984
|
+
"members",
|
|
3985
|
+
"nextCursor"
|
|
3986
|
+
]) || value.applicationId !== input.applicationId || value.organizationId !== input.organizationId || value.organizationGeneration !== input.organizationGeneration || !Array.isArray(value.members) || value.members.length > (input.limit ?? 50)) throw authorityUnavailable();
|
|
3987
|
+
const members = value.members.map((item) => {
|
|
3988
|
+
if (!exact$6(item, [
|
|
3989
|
+
"user",
|
|
3990
|
+
"role",
|
|
3991
|
+
"membershipStatus"
|
|
3992
|
+
]) || item.role !== "owner" && item.role !== "admin" && item.role !== "member" || item.membershipStatus !== "active" && item.membershipStatus !== "suspended") throw authorityUnavailable();
|
|
3993
|
+
const normalized = user(item.user, input.applicationId);
|
|
3994
|
+
if (normalized.lifecycle === "deleted") throw authorityUnavailable();
|
|
3995
|
+
return {
|
|
3996
|
+
user: normalized,
|
|
3997
|
+
role: item.role,
|
|
3998
|
+
membershipStatus: item.membershipStatus
|
|
3999
|
+
};
|
|
4000
|
+
});
|
|
4001
|
+
if (new Set(members.map((item) => item.user.userId)).size !== members.length) throw authorityUnavailable();
|
|
4002
|
+
return {
|
|
4003
|
+
applicationId: input.applicationId,
|
|
4004
|
+
organizationId: input.organizationId,
|
|
4005
|
+
organizationGeneration: input.organizationGeneration,
|
|
4006
|
+
members,
|
|
4007
|
+
nextCursor: nextCursor(value.nextCursor)
|
|
4008
|
+
};
|
|
4009
|
+
},
|
|
4010
|
+
async resolveUser(input, assertion) {
|
|
4011
|
+
if (!exact$6(input, ["applicationId", "authUserId"]) || !directoryId(input.applicationId) || !directoryId(input.authUserId)) throw new AuthError("invalid_request", 400);
|
|
4012
|
+
const value = await exchange("resolve", input, assertion);
|
|
4013
|
+
if (!exact$6(value, ["user"])) throw authorityUnavailable();
|
|
4014
|
+
const result = value.user === null ? null : user(value.user, input.applicationId);
|
|
4015
|
+
if (result?.lifecycle === "deleted") throw authorityUnavailable();
|
|
4016
|
+
return result;
|
|
4017
|
+
},
|
|
4018
|
+
async resolveUserBinding(input, assertion) {
|
|
4019
|
+
exactInput(input);
|
|
4020
|
+
const value = await exchange("binding", input, assertion);
|
|
4021
|
+
if (!exact$6(value, ["binding"])) throw authorityUnavailable();
|
|
4022
|
+
if (value.binding === null) return null;
|
|
4023
|
+
if (!exact$6(value.binding, ["user", "authUserId"]) || !directoryId(value.binding.authUserId)) throw authorityUnavailable();
|
|
4024
|
+
const result = selectedUser(value.binding.user, input);
|
|
4025
|
+
if (result.lifecycle === "deleted") throw authorityUnavailable();
|
|
4026
|
+
return {
|
|
4027
|
+
user: result,
|
|
4028
|
+
authUserId: value.binding.authUserId
|
|
4029
|
+
};
|
|
4030
|
+
}
|
|
4031
|
+
};
|
|
4032
|
+
}
|
|
4033
|
+
//#endregion
|
|
3478
4034
|
//#region src/server.ts
|
|
3479
4035
|
const MAX_AUTHORIZATION_BYTES = 16 * 1024;
|
|
3480
4036
|
function createServerAuth(options) {
|
|
@@ -4035,4 +4591,4 @@ function authAuthorizationHeader(value) {
|
|
|
4035
4591
|
return value;
|
|
4036
4592
|
}
|
|
4037
4593
|
//#endregion
|
|
4038
|
-
export { AuthError, createAccountProductOperationAuth, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createOrganizationDirectoryAuth, createServerAuth, createUserApiVerifier };
|
|
4594
|
+
export { AuthError, createAccountProductOperationAuth, createDriveProvisioningAuth, createDriveRecipientAuth, createIdentityResolverAuth, createMembershipResolverAuth, createOrganizationAdmissionAuth, createOrganizationAdmissionBillingAuth, createOrganizationAdmissionDirectoryAuth, createOrganizationDirectoryAuth, createServerAuth, createUserApiVerifier, createUserDirectoryAuth, organizationAdmissionBodyDigest };
|