@authyon/auth 0.2.0-beta.14 → 0.2.0-beta.16

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 CHANGED
@@ -227,18 +227,34 @@ Métodos de sessão/auth ficam soltos no client; os que giram em torno de um rec
227
227
 
228
228
  ### `authyon.organization`
229
229
 
230
- | Método | Endpoint |
231
- | ----------------------------------------------------- | ---------------------------------------------- |
232
- | `organization.list({ search?, skip?, take? })` | `GET /auth/tenants` |
233
- | `organization.create(params?)` | `POST /auth/tenants` |
234
- | `organization.get(organizationId)` | `GET /auth/tenants/{id}` |
235
- | `organization.rename(organizationId, name)` | `PATCH /auth/tenants/{id}` |
236
- | `organization.switch(slug)` | `POST /auth/switch-tenant` |
237
- | `organization.current()` | — (lê `activeOrganization` da sessão em cache) |
238
- | `organization.members.list(organizationId, params?)` | `GET /auth/tenants/{id}/members` |
239
- | `organization.members.invite(organizationId, params)` | `POST /auth/tenants/{id}/members` |
240
- | `organization.members.remove(organizationId, userId)` | `DELETE /auth/tenants/{id}/members/{userId}` |
241
- | `organization.roles.list(organizationId)` | `GET /auth/tenants/{id}/roles` |
230
+ | Método | Endpoint |
231
+ | ---------------------------------------------------------------- | --------------------------------------------------- |
232
+ | `organization.list({ search?, skip?, take? })` | `GET /auth/tenants` |
233
+ | `organization.create(params?)` | `POST /auth/tenants` |
234
+ | `organization.get(organizationId)` | `GET /auth/tenants/{id}` |
235
+ | `organization.rename(organizationId, name)` | `PATCH /auth/tenants/{id}` |
236
+ | `organization.switch(slug)` | `POST /auth/switch-tenant` |
237
+ | `organization.current()` | — (lê `activeOrganization` da sessão em cache) |
238
+ | `organization.members.list(organizationId, params?)` | `GET /auth/tenants/{id}/members` |
239
+ | `organization.members.invite(organizationId, params)` | `POST /auth/tenants/{id}/members` |
240
+ | `organization.members.remove(organizationId, userId)` | `DELETE /auth/tenants/{id}/members/{userId}` |
241
+ | `organization.roles.list(organizationId)` | `GET /auth/tenants/{id}/roles` |
242
+ | `organization.invites.list(organizationId)` | `GET /auth/tenants/{id}/invites` |
243
+ | `organization.invites.create(organizationId, params)` | `POST /auth/tenants/{id}/invites` |
244
+ | `organization.invites.resend(organizationId, inviteId, params?)` | `POST /auth/tenants/{id}/invites/{inviteId}/resend` |
245
+ | `organization.invites.revoke(organizationId, inviteId)` | `DELETE /auth/tenants/{id}/invites/{inviteId}` |
246
+ | `organization.invites.preview(token)` | `POST /auth/tenant-invites/preview` (público) |
247
+ | `organization.invites.accept(params)` | `POST /auth/tenant-invites/accept` (público) |
248
+
249
+ `organization.members.invite` adiciona um usuário que já existe no ambiente. Para convidar
250
+ um e-mail que talvez ainda não tenha conta, use `organization.invites.create`: a resposta
251
+ sempre traz o `acceptUrl` completo e `sendEmail: false` só gera o link, sem enviar e-mail.
252
+ O link vale 7 dias, uma única vez, e não pode ser lido de novo depois. Na página de aceite,
253
+ leia o `token` da URL, chame `preview(token)` e, se `accountExists` for falso, peça senha
254
+ (e usuário quando `usernameRequired`) antes de `accept`. Aceitar não faz login.
255
+ Passe `redirectUri` no `create` para indicar para onde mandar a pessoa depois do aceite: ele
256
+ precisa estar cadastrado (match exato) nos redirect URIs do ambiente e volta em `preview` e
257
+ `accept` — a página hospedada da Authyon redireciona sozinha; numa página própria, é com você.
242
258
 
243
259
  ### `authyon.twoFactor`
244
260
 
@@ -273,26 +289,29 @@ Métodos de sessão/auth ficam soltos no client; os que giram em torno de um rec
273
289
  | `sso.startUrl(provider, params)` | monta a URL de `GET /auth/sso/{provider}/start` (não faz a chamada — navegue até ela) |
274
290
  | `sso.exchange(code)` | `POST /auth/sso/exchange` |
275
291
 
276
- ### `authyon.financialAuthorizations` (confirmação de transações)
292
+ ### `authyon.security` (aprovação com OTP/passkey)
277
293
 
278
- O cliente aprova uma transação criada pelo seu backend com o código do app autenticador
279
- ou a passkey. Guia completo: [`docs/financialStepUp.md`](../../docs/financialStepUp.md).
294
+ `security.approvals`: o cliente aprova o que o seu backend pediu
295
+ (`@authyon/server` → `security.approvals.create`, com um `payload` livre) usando o código
296
+ do app autenticador ou a passkey. Para só validar um código, use `security.otp.check` no
297
+ `@authyon/server`. Guia completo: [`docs/security-otp-approvals.md`](../../docs/security-otp-approvals.md).
280
298
 
281
299
  ```ts
282
- const pending = await authyon.financialAuthorizations.get(authorizationId);
283
- // mostre pending.amount, pending.currency e pending.beneficiary ao cliente
284
- await authyon.financialAuthorizations.confirm(authorizationId, {
300
+ const pending = await authyon.security.approvals.get(approvalId);
301
+ // mostre pending.payload ao cliente
302
+ await authyon.security.approvals.confirm(approvalId, {
285
303
  method: "authenticator",
286
304
  code: "123456",
287
305
  });
288
306
  ```
289
307
 
290
- | Método | Endpoint |
291
- | --------------------------------------------- | ------------------------------------------------- |
292
- | `financialAuthorizations.get(id)` | `GET /auth/authorizations/{id}` |
293
- | `financialAuthorizations.webauthnOptions(id)` | `POST /auth/authorizations/{id}/webauthn/options` |
294
- | `financialAuthorizations.confirm(id, input?)` | `POST /auth/authorizations/{id}/confirm` |
295
- | `financialAuthorizations.reject(id)` | `POST /auth/authorizations/{id}/reject` |
308
+ | Método | Endpoint |
309
+ | ---------------------------------------- | ------------------------------------------------- |
310
+ | `security.methods()` | `GET /auth/me` (campo `security`) |
311
+ | `security.approvals.get(id)` | `GET /auth/authorizations/{id}` |
312
+ | `security.approvals.webauthnOptions(id)` | `POST /auth/authorizations/{id}/webauthn/options` |
313
+ | `security.approvals.confirm(id, input?)` | `POST /auth/authorizations/{id}/confirm` |
314
+ | `security.approvals.reject(id)` | `POST /auth/authorizations/{id}/reject` |
296
315
 
297
316
  ## Invalidação de token
298
317
 
@@ -1,24 +1,34 @@
1
- /** Lifecycle of a transaction-bound financial authorization. */
2
- type FinancialAuthorizationStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
3
1
  /**
4
- * The transaction the customer approves. The API hashes a canonical form of
5
- * these fields; `consume()` must resend exactly the same values (amount is
6
- * normalized to four decimal places, metadata keys are sorted).
2
+ * Security methods active on the user's account, as returned in the
3
+ * `security` field of `GET /auth/me` and `POST /auth/validate`.
7
4
  */
8
- interface FinancialTransaction {
9
- /** Business action, e.g. `"pix.transfer"`. Max 100 characters. */
10
- action: string;
11
- /** Positive amount, up to 15 integer digits and 4 decimal places. */
12
- amount: number;
13
- /** ISO 4217 currency code, e.g. `"BRL"`. */
14
- currency: string;
15
- /** Human-readable beneficiary shown to the customer. Max 256 characters. */
16
- beneficiary: string;
17
- /** Optional JSON object bound into the hash (max 16 KiB). */
18
- metadata?: Record<string, unknown>;
19
- }
5
+ interface SecurityMethods {
6
+ /** A password is set (false for accounts created only through SSO or magic link). */
7
+ password: boolean;
8
+ /** Authenticator app (TOTP one-time codes). */
9
+ authenticator: boolean;
10
+ /** One-time codes sent by email. */
11
+ emailCode: boolean;
12
+ /** At least one passkey registered. */
13
+ passkey: boolean;
14
+ passkeyCount: number;
15
+ /** Unused recovery codes left. */
16
+ recoveryCodes: number;
17
+ /** SSO providers linked to the account, e.g. `["google", "github"]`. */
18
+ sso: string[];
19
+ /** Any second factor is active (authenticator, email code or passkey). */
20
+ twoFactor: boolean;
21
+ }
22
+ /** Lifecycle of an approval. */
23
+ type ApprovalStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
24
+ /**
25
+ * Free-form JSON object describing what the customer approves (up to 16 KiB).
26
+ * The API stores it, shows it back to the customer and binds its canonical
27
+ * hash (keys sorted) to the approval.
28
+ */
29
+ type ApprovalPayload = Record<string, unknown>;
20
30
  /** Evidence of how the customer proved their identity when approving. */
21
- interface FinancialAssurance {
31
+ interface ApprovalAssurance {
22
32
  /** `urn:authyon:loa:3` (passkey) or `urn:authyon:loa:2` (authenticator code). */
23
33
  acr: string;
24
34
  /** Authentication methods, e.g. `["pwd", "otp"]` or `["pwd", "webauthn"]`. */
@@ -26,28 +36,25 @@ interface FinancialAssurance {
26
36
  /** When the second factor was verified (ISO 8601). */
27
37
  authTime: string;
28
38
  }
29
- interface FinancialAuthorization {
39
+ /** A request for the customer to approve something with a second factor. */
40
+ interface Approval {
30
41
  id: string;
31
- status: FinancialAuthorizationStatus;
42
+ status: ApprovalStatus;
32
43
  subjectId: string;
33
44
  tenantId?: string | null;
34
- action: string;
35
- amount: number;
36
- currency: string;
37
- beneficiary: string;
38
- /** SHA-256 (hex) of the canonical transaction. */
39
- transactionHash: string;
45
+ /** The payload given to `create()`, with keys in canonical order. */
46
+ payload: ApprovalPayload;
47
+ /** SHA-256 (hex) of the canonical payload. */
48
+ payloadHash: string;
40
49
  createdAt: string;
41
50
  expiresAt: string;
42
51
  decidedAt?: string | null;
43
52
  consumedAt?: string | null;
44
- /** Full canonical transaction — returned only to the customer (subject) view. */
45
- transaction?: FinancialTransaction | null;
46
53
  /** Present once approved. */
47
- assurance?: FinancialAssurance | null;
54
+ assurance?: ApprovalAssurance | null;
48
55
  }
49
- /** Inline second factor sent with `confirm()`. */
50
- type ConfirmFinancialAuthorizationInput = {
56
+ /** Second factor sent with `confirm()`. */
57
+ type ConfirmApprovalInput = {
51
58
  method: "authenticator";
52
59
  /** Six-digit code from the customer's authenticator app. */
53
60
  code: string;
@@ -60,15 +67,13 @@ type ConfirmFinancialAuthorizationInput = {
60
67
  assertionJson: string;
61
68
  };
62
69
  };
63
- /** Passkey assertion options for approving one authorization. */
64
- interface FinancialWebAuthnOptions {
70
+ /** Passkey assertion options for approving one approval. */
71
+ interface ApprovalWebAuthnOptions {
65
72
  ceremonyToken: string;
66
73
  /** JSON `PublicKeyCredentialRequestOptions` to pass to `navigator.credentials.get()`. */
67
74
  optionsJson: string;
68
75
  }
69
76
 
70
- type QueryParams = object;
71
-
72
77
  interface HttpAdapterRequest {
73
78
  url: string;
74
79
  method: string;
@@ -126,35 +131,34 @@ declare class LoggingHttpAdapter implements HttpAdapter {
126
131
  private log;
127
132
  }
128
133
 
129
- type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
130
- interface JsonRequestOptions {
131
- method?: HttpMethod;
132
- body?: unknown;
133
- query?: QueryParams;
134
- headers?: Record<string, string>;
135
- }
136
-
137
- /** Sends a request already authenticated as the customer (end-user bearer). */
138
- type SubjectRequest = <T>(path: string, options?: JsonRequestOptions) => Promise<T>;
139
- /** Customer-side operations on a financial authorization (`/auth/authorizations`). */
140
- declare function subjectFinancialAuthorizations(request: SubjectRequest): {
141
- /** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
142
- get: (id: string) => Promise<FinancialAuthorization>;
143
- /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
144
- webauthnOptions: (id: string) => Promise<FinancialWebAuthnOptions>;
134
+ /** Customer-side operations on an approval (`/auth/authorizations`). */
135
+ interface SubjectApprovals {
136
+ /** GET /auth/authorizations/{id} — the pending payload, to show before asking for the code. */
137
+ get(id: string): Promise<Approval>;
138
+ /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving it. */
139
+ webauthnOptions(id: string): Promise<ApprovalWebAuthnOptions>;
145
140
  /**
146
- * POST /auth/authorizations/{id}/confirm — approves the transaction.
141
+ * POST /auth/authorizations/{id}/confirm — approves it.
147
142
  *
148
143
  * Pass the authenticator code or passkey assertion to verify the second
149
144
  * factor inline (recommended). Without `input`, the session itself must
150
145
  * have used a passkey or authenticator code within the last 5 minutes,
151
146
  * otherwise the API answers `step_up_required`.
152
147
  */
153
- confirm: (id: string, input?: ConfirmFinancialAuthorizationInput) => Promise<FinancialAuthorization>;
154
- /** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
155
- reject: (id: string) => Promise<FinancialAuthorization>;
156
- };
157
- type SubjectFinancialAuthorizations = ReturnType<typeof subjectFinancialAuthorizations>;
148
+ confirm(id: string, input?: ConfirmApprovalInput): Promise<Approval>;
149
+ /** POST /auth/authorizations/{id}/reject — the customer declines it. */
150
+ reject(id: string): Promise<Approval>;
151
+ }
152
+ /** The `security` namespace an end-user client exposes. */
153
+ interface SubjectSecurity {
154
+ /**
155
+ * GET /auth/me — which security methods the signed-in user has active
156
+ * (password, authenticator, email code, passkeys, recovery codes, SSO).
157
+ */
158
+ methods(): Promise<SecurityMethods>;
159
+ /** Approve or reject what your backend asked the customer to confirm. */
160
+ readonly approvals: SubjectApprovals;
161
+ }
158
162
 
159
163
  interface PaginationOptions {
160
164
  skip?: number;
@@ -220,6 +224,86 @@ interface InviteMemberInput {
220
224
  email: string;
221
225
  roles: string[];
222
226
  }
227
+ /**
228
+ * POST /auth/tenants/{organizationId}/invites — invite an address that may not
229
+ * have an account yet; accepting creates it. `sendEmail` defaults to `true`;
230
+ * `false` only returns the link, for delivery through your own channel.
231
+ */
232
+ interface OrganizationInviteInput {
233
+ email: string;
234
+ roles?: string[];
235
+ sendEmail?: boolean;
236
+ /**
237
+ * Where to send the invitee after they accept. Must be registered exactly in
238
+ * the environment's redirect URIs (the same list SSO and magic link use);
239
+ * otherwise the API rejects the invite. Comes back on `preview` and `accept`.
240
+ */
241
+ redirectUri?: string;
242
+ }
243
+ /** Returned when an invite is created or re-issued. `acceptUrl` is only ever
244
+ * readable here — the API keeps a hash of the token, not the token. */
245
+ interface OrganizationInviteIssued {
246
+ id: string;
247
+ tenantId: string;
248
+ email: string;
249
+ roles: string[];
250
+ acceptUrl: string;
251
+ expiresAt: string;
252
+ emailSent: boolean;
253
+ redirectUri: string | null;
254
+ }
255
+ type OrganizationInviteStatus = "pending" | "accepted" | "revoked" | "expired";
256
+ interface OrganizationInvite {
257
+ id: string;
258
+ tenantId: string;
259
+ email: string;
260
+ roles: string[];
261
+ status: OrganizationInviteStatus;
262
+ createdAt: string;
263
+ expiresAt: string;
264
+ emailSentAt: string | null;
265
+ acceptedAt: string | null;
266
+ acceptedByUserId: string | null;
267
+ revokedAt: string | null;
268
+ invitedByUserId: string | null;
269
+ redirectUri: string | null;
270
+ }
271
+ /** POST /auth/tenant-invites/preview — what an accept page shows before the invitee commits. */
272
+ interface OrganizationInvitePreview {
273
+ tenantId: string;
274
+ tenantName: string;
275
+ email: string;
276
+ roles: string[];
277
+ expiresAt: string;
278
+ /** True: accepting only needs the token. False: send a password (and a username when `usernameRequired`). */
279
+ accountExists: boolean;
280
+ usernameRequired: boolean;
281
+ /** Where the issuer asked to send the invitee after accepting, or `null`. */
282
+ redirectUri: string | null;
283
+ }
284
+ /** POST /auth/tenant-invites/accept — everything but `token` is ignored when the address already has an account. */
285
+ interface AcceptOrganizationInviteInput {
286
+ token: string;
287
+ username?: string;
288
+ password?: string;
289
+ firstName?: string;
290
+ lastName?: string;
291
+ /**
292
+ * @deprecated Use `publicMetadata` / `privateMetadata` through
293
+ * `@authyon/server` (`environment.tenants.invites.accept`), which runs on
294
+ * your backend with the environment credential. Still accepted for now.
295
+ */
296
+ customFields?: Record<string, unknown>;
297
+ }
298
+ interface OrganizationInviteAccepted {
299
+ tenantId: string;
300
+ tenantName: string;
301
+ userId: string;
302
+ /** True when accepting created the account (email already confirmed). The invitee still signs in normally. */
303
+ accountCreated: boolean;
304
+ /** Where the issuer asked to send the invitee, or `null`. Redirecting is up to the accept page. */
305
+ redirectUri: string | null;
306
+ }
223
307
  /** Authenticated user profile. */
224
308
  interface User {
225
309
  id: string;
@@ -236,6 +320,8 @@ interface User {
236
320
  activeOrganization?: Organization | null;
237
321
  /** Actions the user must complete before continuing (e.g. confirm e-mail). */
238
322
  pendencies?: string[];
323
+ /** Security methods active on the account (authenticator, email code, passkey, SSO…). */
324
+ security?: SecurityMethods;
239
325
  }
240
326
  /** Token pair issued by login / refresh / tenant switch. */
241
327
  interface Session {
@@ -565,11 +651,53 @@ declare class AuthyonClient {
565
651
  * (`user.activities()`, `@authyon/server`'s `environment.users.list()`).
566
652
  */
567
653
  list: (organizationId: string, params?: PaginationOptions) => Promise<Paged<OrganizationMember>>;
568
- /** POST /auth/tenants/{organizationId}/members — invite a member by e-mail. */
654
+ /**
655
+ * POST /auth/tenants/{organizationId}/members — add an existing
656
+ * environment user by e-mail (no e-mail is sent). To invite an address
657
+ * that may not have an account yet, use `organization.invites.create`.
658
+ */
569
659
  invite: (organizationId: string, params: InviteMemberInput) => Promise<void>;
570
660
  /** DELETE /auth/tenants/{organizationId}/members/{userId} — remove a member. */
571
661
  remove: (organizationId: string, userId: string) => Promise<void>;
572
662
  };
663
+ /**
664
+ * Invites by e-mail or by link. Managing them requires the
665
+ * `tenants:members:invite` permission on the organization; `preview` and
666
+ * `accept` are public — the token in the link is the credential.
667
+ */
668
+ invites: {
669
+ /** GET /auth/tenants/{organizationId}/invites — every invite with its status, newest first. */
670
+ list: (organizationId: string) => Promise<OrganizationInvite[]>;
671
+ /**
672
+ * POST /auth/tenants/{organizationId}/invites — invite an address.
673
+ * Always returns `acceptUrl`; with `sendEmail: false` Authyon does not
674
+ * mail it and you deliver the link yourself. The link is valid for 7
675
+ * days, once, and can't be read again later.
676
+ */
677
+ create: (organizationId: string, params: OrganizationInviteInput) => Promise<OrganizationInviteIssued>;
678
+ /**
679
+ * POST /auth/tenants/{organizationId}/invites/{inviteId}/resend — issue
680
+ * a new link (the previous one stops working), mailing it unless
681
+ * `sendEmail` is `false`.
682
+ */
683
+ resend: (organizationId: string, inviteId: string, params?: {
684
+ sendEmail?: boolean;
685
+ }) => Promise<OrganizationInviteIssued>;
686
+ /** DELETE /auth/tenants/{organizationId}/invites/{inviteId} — revoke a pending invite. */
687
+ revoke: (organizationId: string, inviteId: string) => Promise<void>;
688
+ /**
689
+ * POST /auth/tenant-invites/preview — public. Read the `token` query
690
+ * parameter of the invite link and pick the form: one click when
691
+ * `accountExists`, sign-up otherwise.
692
+ */
693
+ preview: (token: string) => Promise<OrganizationInvitePreview>;
694
+ /**
695
+ * POST /auth/tenant-invites/accept — public. Joins the organization; for
696
+ * an address with no account, also creates it (password required) with
697
+ * the e-mail already confirmed. Does not sign the user in.
698
+ */
699
+ accept: (params: AcceptOrganizationInviteInput) => Promise<OrganizationInviteAccepted>;
700
+ };
573
701
  roles: {
574
702
  /** GET /auth/tenants/{organizationId}/roles — roles available in the organization. */
575
703
  list: (organizationId: string) => Promise<Role[]>;
@@ -620,12 +748,12 @@ declare class AuthyonClient {
620
748
  };
621
749
  };
622
750
  /**
623
- * Transaction-bound approvals created by your backend
624
- * (`@authyon/server` → `environment.financialAuthorizations.create`).
625
- * Show the transaction with `get()`, then `confirm()` with the customer's
751
+ * `security.approvals`: approve or reject what your backend asked the
752
+ * customer to confirm (`@authyon/server` → `security.approvals.create`).
753
+ * Show the payload with `get()`, then `confirm()` with the customer's
626
754
  * authenticator code or passkey, or `reject()`.
627
755
  */
628
- readonly financialAuthorizations: SubjectFinancialAuthorizations;
756
+ readonly security: SubjectSecurity;
629
757
  /**
630
758
  * POST /auth/introspect — lightweight token introspection (RFC 7662).
631
759
  *
@@ -750,4 +878,4 @@ declare function hasPermissionGroup(source: AuthyonPermissionSource | readonly s
750
878
  /** Converts Authyon's `subject:action` permission strings to authorization rules. */
751
879
  declare function createAuthyonRules(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AbilityRule[];
752
880
 
753
- export { type User as $, AuthyonClient as A, type InviteMemberInput as B, type ConfirmFinancialAuthorizationInput as C, type LoginInput as D, type LoginResult as E, FetchHttpAdapter as F, type OrganizationMember as G, type HttpAdapter as H, type IntrospectResult as I, type PaginationOptions as J, type PermissionGroup as K, LoggingHttpAdapter as L, type Role as M, type SessionControllerOptions as N, type Organization as O, type Paged as P, type SessionInfo as Q, type RegisterInput as R, type Session as S, type TokenStorage as T, type SessionSnapshot as U, type SessionSnapshotListener as V, type SessionStatus as W, type SsoProvider as X, type TwoFactorChallenge as Y, type TwoFactorMethod as Z, type TwoFactorStatus as _, type HttpLoggerOptions as a, type ValidateResult as a0, type VerifyTwoFactorInput as a1, type WebAuthnAssertion as a2, type WebAuthnCeremonyStart as a3, type WebAuthnCredential as a4, createAuthyonAbility as a5, createAuthyonRules as a6, createClient as a7, hasPermission as a8, hasPermissionGroup as a9, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type Activity as g, type AuthEvent as h, type AuthState as i, type AuthStateListener as j, type AuthenticatorSetup as k, AuthyonAbility as l, AuthyonAbilityBuilder as m, type AuthyonAbilityOptions as n, type AuthyonClientOptions as o, type AuthyonPermissionSource as p, AuthyonSessionController as q, type CreateOrganizationInput as r, type FinancialAssurance as s, type FinancialAuthorization as t, type FinancialAuthorizationStatus as u, type FinancialTransaction as v, type FinancialWebAuthnOptions as w, type HttpAdapterRequest as x, type HttpLogEvent as y, type HttpLogger as z };
881
+ export { type SessionInfo as $, AuthyonClient as A, type HttpLogger as B, type ConfirmApprovalInput as C, type InviteMemberInput as D, type LoginInput as E, FetchHttpAdapter as F, type LoginResult as G, type HttpAdapter as H, type IntrospectResult as I, type OrganizationInvite as J, type OrganizationInviteAccepted as K, LoggingHttpAdapter as L, type OrganizationInviteInput as M, type OrganizationInviteIssued as N, type Organization as O, type OrganizationInvitePreview as P, type OrganizationInviteStatus as Q, type OrganizationMember as R, type Paged as S, type TokenStorage as T, type PaginationOptions as U, type PermissionGroup as V, type RegisterInput as W, type Role as X, type SecurityMethods as Y, type Session as Z, type SessionControllerOptions as _, type HttpLoggerOptions as a, type SessionSnapshot as a0, type SessionSnapshotListener as a1, type SessionStatus as a2, type SsoProvider as a3, type SubjectApprovals as a4, type SubjectSecurity as a5, type TwoFactorChallenge as a6, type TwoFactorMethod as a7, type TwoFactorStatus as a8, type User as a9, type ValidateResult as aa, type VerifyTwoFactorInput as ab, type WebAuthnAssertion as ac, type WebAuthnCeremonyStart as ad, type WebAuthnCredential as ae, createAuthyonAbility as af, createAuthyonRules as ag, createClient as ah, hasPermission as ai, hasPermissionGroup as aj, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type AcceptOrganizationInviteInput as g, type Activity as h, type Approval as i, type ApprovalAssurance as j, type ApprovalPayload as k, type ApprovalStatus as l, type ApprovalWebAuthnOptions as m, type AuthEvent as n, type AuthState as o, type AuthStateListener as p, type AuthenticatorSetup as q, AuthyonAbility as r, AuthyonAbilityBuilder as s, type AuthyonAbilityOptions as t, type AuthyonClientOptions as u, type AuthyonPermissionSource as v, AuthyonSessionController as w, type CreateOrganizationInput as x, type HttpAdapterRequest as y, type HttpLogEvent as z };
@@ -1,24 +1,34 @@
1
- /** Lifecycle of a transaction-bound financial authorization. */
2
- type FinancialAuthorizationStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
3
1
  /**
4
- * The transaction the customer approves. The API hashes a canonical form of
5
- * these fields; `consume()` must resend exactly the same values (amount is
6
- * normalized to four decimal places, metadata keys are sorted).
2
+ * Security methods active on the user's account, as returned in the
3
+ * `security` field of `GET /auth/me` and `POST /auth/validate`.
7
4
  */
8
- interface FinancialTransaction {
9
- /** Business action, e.g. `"pix.transfer"`. Max 100 characters. */
10
- action: string;
11
- /** Positive amount, up to 15 integer digits and 4 decimal places. */
12
- amount: number;
13
- /** ISO 4217 currency code, e.g. `"BRL"`. */
14
- currency: string;
15
- /** Human-readable beneficiary shown to the customer. Max 256 characters. */
16
- beneficiary: string;
17
- /** Optional JSON object bound into the hash (max 16 KiB). */
18
- metadata?: Record<string, unknown>;
19
- }
5
+ interface SecurityMethods {
6
+ /** A password is set (false for accounts created only through SSO or magic link). */
7
+ password: boolean;
8
+ /** Authenticator app (TOTP one-time codes). */
9
+ authenticator: boolean;
10
+ /** One-time codes sent by email. */
11
+ emailCode: boolean;
12
+ /** At least one passkey registered. */
13
+ passkey: boolean;
14
+ passkeyCount: number;
15
+ /** Unused recovery codes left. */
16
+ recoveryCodes: number;
17
+ /** SSO providers linked to the account, e.g. `["google", "github"]`. */
18
+ sso: string[];
19
+ /** Any second factor is active (authenticator, email code or passkey). */
20
+ twoFactor: boolean;
21
+ }
22
+ /** Lifecycle of an approval. */
23
+ type ApprovalStatus = "pending" | "approved" | "denied" | "consumed" | "expired";
24
+ /**
25
+ * Free-form JSON object describing what the customer approves (up to 16 KiB).
26
+ * The API stores it, shows it back to the customer and binds its canonical
27
+ * hash (keys sorted) to the approval.
28
+ */
29
+ type ApprovalPayload = Record<string, unknown>;
20
30
  /** Evidence of how the customer proved their identity when approving. */
21
- interface FinancialAssurance {
31
+ interface ApprovalAssurance {
22
32
  /** `urn:authyon:loa:3` (passkey) or `urn:authyon:loa:2` (authenticator code). */
23
33
  acr: string;
24
34
  /** Authentication methods, e.g. `["pwd", "otp"]` or `["pwd", "webauthn"]`. */
@@ -26,28 +36,25 @@ interface FinancialAssurance {
26
36
  /** When the second factor was verified (ISO 8601). */
27
37
  authTime: string;
28
38
  }
29
- interface FinancialAuthorization {
39
+ /** A request for the customer to approve something with a second factor. */
40
+ interface Approval {
30
41
  id: string;
31
- status: FinancialAuthorizationStatus;
42
+ status: ApprovalStatus;
32
43
  subjectId: string;
33
44
  tenantId?: string | null;
34
- action: string;
35
- amount: number;
36
- currency: string;
37
- beneficiary: string;
38
- /** SHA-256 (hex) of the canonical transaction. */
39
- transactionHash: string;
45
+ /** The payload given to `create()`, with keys in canonical order. */
46
+ payload: ApprovalPayload;
47
+ /** SHA-256 (hex) of the canonical payload. */
48
+ payloadHash: string;
40
49
  createdAt: string;
41
50
  expiresAt: string;
42
51
  decidedAt?: string | null;
43
52
  consumedAt?: string | null;
44
- /** Full canonical transaction — returned only to the customer (subject) view. */
45
- transaction?: FinancialTransaction | null;
46
53
  /** Present once approved. */
47
- assurance?: FinancialAssurance | null;
54
+ assurance?: ApprovalAssurance | null;
48
55
  }
49
- /** Inline second factor sent with `confirm()`. */
50
- type ConfirmFinancialAuthorizationInput = {
56
+ /** Second factor sent with `confirm()`. */
57
+ type ConfirmApprovalInput = {
51
58
  method: "authenticator";
52
59
  /** Six-digit code from the customer's authenticator app. */
53
60
  code: string;
@@ -60,15 +67,13 @@ type ConfirmFinancialAuthorizationInput = {
60
67
  assertionJson: string;
61
68
  };
62
69
  };
63
- /** Passkey assertion options for approving one authorization. */
64
- interface FinancialWebAuthnOptions {
70
+ /** Passkey assertion options for approving one approval. */
71
+ interface ApprovalWebAuthnOptions {
65
72
  ceremonyToken: string;
66
73
  /** JSON `PublicKeyCredentialRequestOptions` to pass to `navigator.credentials.get()`. */
67
74
  optionsJson: string;
68
75
  }
69
76
 
70
- type QueryParams = object;
71
-
72
77
  interface HttpAdapterRequest {
73
78
  url: string;
74
79
  method: string;
@@ -126,35 +131,34 @@ declare class LoggingHttpAdapter implements HttpAdapter {
126
131
  private log;
127
132
  }
128
133
 
129
- type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
130
- interface JsonRequestOptions {
131
- method?: HttpMethod;
132
- body?: unknown;
133
- query?: QueryParams;
134
- headers?: Record<string, string>;
135
- }
136
-
137
- /** Sends a request already authenticated as the customer (end-user bearer). */
138
- type SubjectRequest = <T>(path: string, options?: JsonRequestOptions) => Promise<T>;
139
- /** Customer-side operations on a financial authorization (`/auth/authorizations`). */
140
- declare function subjectFinancialAuthorizations(request: SubjectRequest): {
141
- /** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
142
- get: (id: string) => Promise<FinancialAuthorization>;
143
- /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
144
- webauthnOptions: (id: string) => Promise<FinancialWebAuthnOptions>;
134
+ /** Customer-side operations on an approval (`/auth/authorizations`). */
135
+ interface SubjectApprovals {
136
+ /** GET /auth/authorizations/{id} — the pending payload, to show before asking for the code. */
137
+ get(id: string): Promise<Approval>;
138
+ /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving it. */
139
+ webauthnOptions(id: string): Promise<ApprovalWebAuthnOptions>;
145
140
  /**
146
- * POST /auth/authorizations/{id}/confirm — approves the transaction.
141
+ * POST /auth/authorizations/{id}/confirm — approves it.
147
142
  *
148
143
  * Pass the authenticator code or passkey assertion to verify the second
149
144
  * factor inline (recommended). Without `input`, the session itself must
150
145
  * have used a passkey or authenticator code within the last 5 minutes,
151
146
  * otherwise the API answers `step_up_required`.
152
147
  */
153
- confirm: (id: string, input?: ConfirmFinancialAuthorizationInput) => Promise<FinancialAuthorization>;
154
- /** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
155
- reject: (id: string) => Promise<FinancialAuthorization>;
156
- };
157
- type SubjectFinancialAuthorizations = ReturnType<typeof subjectFinancialAuthorizations>;
148
+ confirm(id: string, input?: ConfirmApprovalInput): Promise<Approval>;
149
+ /** POST /auth/authorizations/{id}/reject — the customer declines it. */
150
+ reject(id: string): Promise<Approval>;
151
+ }
152
+ /** The `security` namespace an end-user client exposes. */
153
+ interface SubjectSecurity {
154
+ /**
155
+ * GET /auth/me — which security methods the signed-in user has active
156
+ * (password, authenticator, email code, passkeys, recovery codes, SSO).
157
+ */
158
+ methods(): Promise<SecurityMethods>;
159
+ /** Approve or reject what your backend asked the customer to confirm. */
160
+ readonly approvals: SubjectApprovals;
161
+ }
158
162
 
159
163
  interface PaginationOptions {
160
164
  skip?: number;
@@ -220,6 +224,86 @@ interface InviteMemberInput {
220
224
  email: string;
221
225
  roles: string[];
222
226
  }
227
+ /**
228
+ * POST /auth/tenants/{organizationId}/invites — invite an address that may not
229
+ * have an account yet; accepting creates it. `sendEmail` defaults to `true`;
230
+ * `false` only returns the link, for delivery through your own channel.
231
+ */
232
+ interface OrganizationInviteInput {
233
+ email: string;
234
+ roles?: string[];
235
+ sendEmail?: boolean;
236
+ /**
237
+ * Where to send the invitee after they accept. Must be registered exactly in
238
+ * the environment's redirect URIs (the same list SSO and magic link use);
239
+ * otherwise the API rejects the invite. Comes back on `preview` and `accept`.
240
+ */
241
+ redirectUri?: string;
242
+ }
243
+ /** Returned when an invite is created or re-issued. `acceptUrl` is only ever
244
+ * readable here — the API keeps a hash of the token, not the token. */
245
+ interface OrganizationInviteIssued {
246
+ id: string;
247
+ tenantId: string;
248
+ email: string;
249
+ roles: string[];
250
+ acceptUrl: string;
251
+ expiresAt: string;
252
+ emailSent: boolean;
253
+ redirectUri: string | null;
254
+ }
255
+ type OrganizationInviteStatus = "pending" | "accepted" | "revoked" | "expired";
256
+ interface OrganizationInvite {
257
+ id: string;
258
+ tenantId: string;
259
+ email: string;
260
+ roles: string[];
261
+ status: OrganizationInviteStatus;
262
+ createdAt: string;
263
+ expiresAt: string;
264
+ emailSentAt: string | null;
265
+ acceptedAt: string | null;
266
+ acceptedByUserId: string | null;
267
+ revokedAt: string | null;
268
+ invitedByUserId: string | null;
269
+ redirectUri: string | null;
270
+ }
271
+ /** POST /auth/tenant-invites/preview — what an accept page shows before the invitee commits. */
272
+ interface OrganizationInvitePreview {
273
+ tenantId: string;
274
+ tenantName: string;
275
+ email: string;
276
+ roles: string[];
277
+ expiresAt: string;
278
+ /** True: accepting only needs the token. False: send a password (and a username when `usernameRequired`). */
279
+ accountExists: boolean;
280
+ usernameRequired: boolean;
281
+ /** Where the issuer asked to send the invitee after accepting, or `null`. */
282
+ redirectUri: string | null;
283
+ }
284
+ /** POST /auth/tenant-invites/accept — everything but `token` is ignored when the address already has an account. */
285
+ interface AcceptOrganizationInviteInput {
286
+ token: string;
287
+ username?: string;
288
+ password?: string;
289
+ firstName?: string;
290
+ lastName?: string;
291
+ /**
292
+ * @deprecated Use `publicMetadata` / `privateMetadata` through
293
+ * `@authyon/server` (`environment.tenants.invites.accept`), which runs on
294
+ * your backend with the environment credential. Still accepted for now.
295
+ */
296
+ customFields?: Record<string, unknown>;
297
+ }
298
+ interface OrganizationInviteAccepted {
299
+ tenantId: string;
300
+ tenantName: string;
301
+ userId: string;
302
+ /** True when accepting created the account (email already confirmed). The invitee still signs in normally. */
303
+ accountCreated: boolean;
304
+ /** Where the issuer asked to send the invitee, or `null`. Redirecting is up to the accept page. */
305
+ redirectUri: string | null;
306
+ }
223
307
  /** Authenticated user profile. */
224
308
  interface User {
225
309
  id: string;
@@ -236,6 +320,8 @@ interface User {
236
320
  activeOrganization?: Organization | null;
237
321
  /** Actions the user must complete before continuing (e.g. confirm e-mail). */
238
322
  pendencies?: string[];
323
+ /** Security methods active on the account (authenticator, email code, passkey, SSO…). */
324
+ security?: SecurityMethods;
239
325
  }
240
326
  /** Token pair issued by login / refresh / tenant switch. */
241
327
  interface Session {
@@ -565,11 +651,53 @@ declare class AuthyonClient {
565
651
  * (`user.activities()`, `@authyon/server`'s `environment.users.list()`).
566
652
  */
567
653
  list: (organizationId: string, params?: PaginationOptions) => Promise<Paged<OrganizationMember>>;
568
- /** POST /auth/tenants/{organizationId}/members — invite a member by e-mail. */
654
+ /**
655
+ * POST /auth/tenants/{organizationId}/members — add an existing
656
+ * environment user by e-mail (no e-mail is sent). To invite an address
657
+ * that may not have an account yet, use `organization.invites.create`.
658
+ */
569
659
  invite: (organizationId: string, params: InviteMemberInput) => Promise<void>;
570
660
  /** DELETE /auth/tenants/{organizationId}/members/{userId} — remove a member. */
571
661
  remove: (organizationId: string, userId: string) => Promise<void>;
572
662
  };
663
+ /**
664
+ * Invites by e-mail or by link. Managing them requires the
665
+ * `tenants:members:invite` permission on the organization; `preview` and
666
+ * `accept` are public — the token in the link is the credential.
667
+ */
668
+ invites: {
669
+ /** GET /auth/tenants/{organizationId}/invites — every invite with its status, newest first. */
670
+ list: (organizationId: string) => Promise<OrganizationInvite[]>;
671
+ /**
672
+ * POST /auth/tenants/{organizationId}/invites — invite an address.
673
+ * Always returns `acceptUrl`; with `sendEmail: false` Authyon does not
674
+ * mail it and you deliver the link yourself. The link is valid for 7
675
+ * days, once, and can't be read again later.
676
+ */
677
+ create: (organizationId: string, params: OrganizationInviteInput) => Promise<OrganizationInviteIssued>;
678
+ /**
679
+ * POST /auth/tenants/{organizationId}/invites/{inviteId}/resend — issue
680
+ * a new link (the previous one stops working), mailing it unless
681
+ * `sendEmail` is `false`.
682
+ */
683
+ resend: (organizationId: string, inviteId: string, params?: {
684
+ sendEmail?: boolean;
685
+ }) => Promise<OrganizationInviteIssued>;
686
+ /** DELETE /auth/tenants/{organizationId}/invites/{inviteId} — revoke a pending invite. */
687
+ revoke: (organizationId: string, inviteId: string) => Promise<void>;
688
+ /**
689
+ * POST /auth/tenant-invites/preview — public. Read the `token` query
690
+ * parameter of the invite link and pick the form: one click when
691
+ * `accountExists`, sign-up otherwise.
692
+ */
693
+ preview: (token: string) => Promise<OrganizationInvitePreview>;
694
+ /**
695
+ * POST /auth/tenant-invites/accept — public. Joins the organization; for
696
+ * an address with no account, also creates it (password required) with
697
+ * the e-mail already confirmed. Does not sign the user in.
698
+ */
699
+ accept: (params: AcceptOrganizationInviteInput) => Promise<OrganizationInviteAccepted>;
700
+ };
573
701
  roles: {
574
702
  /** GET /auth/tenants/{organizationId}/roles — roles available in the organization. */
575
703
  list: (organizationId: string) => Promise<Role[]>;
@@ -620,12 +748,12 @@ declare class AuthyonClient {
620
748
  };
621
749
  };
622
750
  /**
623
- * Transaction-bound approvals created by your backend
624
- * (`@authyon/server` → `environment.financialAuthorizations.create`).
625
- * Show the transaction with `get()`, then `confirm()` with the customer's
751
+ * `security.approvals`: approve or reject what your backend asked the
752
+ * customer to confirm (`@authyon/server` → `security.approvals.create`).
753
+ * Show the payload with `get()`, then `confirm()` with the customer's
626
754
  * authenticator code or passkey, or `reject()`.
627
755
  */
628
- readonly financialAuthorizations: SubjectFinancialAuthorizations;
756
+ readonly security: SubjectSecurity;
629
757
  /**
630
758
  * POST /auth/introspect — lightweight token introspection (RFC 7662).
631
759
  *
@@ -750,4 +878,4 @@ declare function hasPermissionGroup(source: AuthyonPermissionSource | readonly s
750
878
  /** Converts Authyon's `subject:action` permission strings to authorization rules. */
751
879
  declare function createAuthyonRules(source?: AuthyonPermissionSource, options?: AuthyonAbilityOptions): AbilityRule[];
752
880
 
753
- export { type User as $, AuthyonClient as A, type InviteMemberInput as B, type ConfirmFinancialAuthorizationInput as C, type LoginInput as D, type LoginResult as E, FetchHttpAdapter as F, type OrganizationMember as G, type HttpAdapter as H, type IntrospectResult as I, type PaginationOptions as J, type PermissionGroup as K, LoggingHttpAdapter as L, type Role as M, type SessionControllerOptions as N, type Organization as O, type Paged as P, type SessionInfo as Q, type RegisterInput as R, type Session as S, type TokenStorage as T, type SessionSnapshot as U, type SessionSnapshotListener as V, type SessionStatus as W, type SsoProvider as X, type TwoFactorChallenge as Y, type TwoFactorMethod as Z, type TwoFactorStatus as _, type HttpLoggerOptions as a, type ValidateResult as a0, type VerifyTwoFactorInput as a1, type WebAuthnAssertion as a2, type WebAuthnCeremonyStart as a3, type WebAuthnCredential as a4, createAuthyonAbility as a5, createAuthyonRules as a6, createClient as a7, hasPermission as a8, hasPermissionGroup as a9, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type Activity as g, type AuthEvent as h, type AuthState as i, type AuthStateListener as j, type AuthenticatorSetup as k, AuthyonAbility as l, AuthyonAbilityBuilder as m, type AuthyonAbilityOptions as n, type AuthyonClientOptions as o, type AuthyonPermissionSource as p, AuthyonSessionController as q, type CreateOrganizationInput as r, type FinancialAssurance as s, type FinancialAuthorization as t, type FinancialAuthorizationStatus as u, type FinancialTransaction as v, type FinancialWebAuthnOptions as w, type HttpAdapterRequest as x, type HttpLogEvent as y, type HttpLogger as z };
881
+ export { type SessionInfo as $, AuthyonClient as A, type HttpLogger as B, type ConfirmApprovalInput as C, type InviteMemberInput as D, type LoginInput as E, FetchHttpAdapter as F, type LoginResult as G, type HttpAdapter as H, type IntrospectResult as I, type OrganizationInvite as J, type OrganizationInviteAccepted as K, LoggingHttpAdapter as L, type OrganizationInviteInput as M, type OrganizationInviteIssued as N, type Organization as O, type OrganizationInvitePreview as P, type OrganizationInviteStatus as Q, type OrganizationMember as R, type Paged as S, type TokenStorage as T, type PaginationOptions as U, type PermissionGroup as V, type RegisterInput as W, type Role as X, type SecurityMethods as Y, type Session as Z, type SessionControllerOptions as _, type HttpLoggerOptions as a, type SessionSnapshot as a0, type SessionSnapshotListener as a1, type SessionStatus as a2, type SsoProvider as a3, type SubjectApprovals as a4, type SubjectSecurity as a5, type TwoFactorChallenge as a6, type TwoFactorMethod as a7, type TwoFactorStatus as a8, type User as a9, type ValidateResult as aa, type VerifyTwoFactorInput as ab, type WebAuthnAssertion as ac, type WebAuthnCeremonyStart as ad, type WebAuthnCredential as ae, createAuthyonAbility as af, createAuthyonRules as ag, createClient as ah, hasPermission as ai, hasPermissionGroup as aj, type AbilityConditions as b, type AbilityEvent as c, type AbilityListener as d, type AbilityRule as e, type AbilitySubject as f, type AcceptOrganizationInviteInput as g, type Activity as h, type Approval as i, type ApprovalAssurance as j, type ApprovalPayload as k, type ApprovalStatus as l, type ApprovalWebAuthnOptions as m, type AuthEvent as n, type AuthState as o, type AuthStateListener as p, type AuthenticatorSetup as q, AuthyonAbility as r, AuthyonAbilityBuilder as s, type AuthyonAbilityOptions as t, type AuthyonClientOptions as u, type AuthyonPermissionSource as v, AuthyonSessionController as w, type CreateOrganizationInput as x, type HttpAdapterRequest as y, type HttpLogEvent as z };
package/dist/index.cjs CHANGED
@@ -40,29 +40,34 @@ __export(index_exports, {
40
40
  });
41
41
  module.exports = __toCommonJS(index_exports);
42
42
 
43
- // ../../internal/core/financial/subjectFinancialAuthorizations.ts
43
+ // ../../internal/core/security/approvals.ts
44
44
  function path(id, suffix = "") {
45
45
  if (typeof id !== "string" || !id.trim())
46
- throw new TypeError("Authyon: a financial authorization id is required.");
46
+ throw new TypeError("Authyon: an approval id is required.");
47
47
  return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
48
48
  }
49
- function subjectFinancialAuthorizations(request) {
49
+ var NO_METHODS = {
50
+ password: false,
51
+ authenticator: false,
52
+ emailCode: false,
53
+ passkey: false,
54
+ passkeyCount: 0,
55
+ recoveryCodes: 0,
56
+ sso: [],
57
+ twoFactor: false
58
+ };
59
+ function subjectSecurity(request) {
50
60
  return {
51
- /** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
52
- get: (id) => request(path(id)),
53
- /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
54
- webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
55
- /**
56
- * POST /auth/authorizations/{id}/confirm — approves the transaction.
57
- *
58
- * Pass the authenticator code or passkey assertion to verify the second
59
- * factor inline (recommended). Without `input`, the session itself must
60
- * have used a passkey or authenticator code within the last 5 minutes,
61
- * otherwise the API answers `step_up_required`.
62
- */
63
- confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
64
- /** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
65
- reject: (id) => request(path(id, "/reject"), { method: "POST" })
61
+ methods: async () => {
62
+ const me = await request("/auth/me");
63
+ return me.security ?? NO_METHODS;
64
+ },
65
+ approvals: {
66
+ get: (id) => request(path(id)),
67
+ webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
68
+ confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
69
+ reject: (id) => request(path(id, "/reject"), { method: "POST" })
70
+ }
66
71
  };
67
72
  }
68
73
 
@@ -83,10 +88,18 @@ var ErrorCodes = {
83
88
  InvalidSecondFactorCode: "invalid_code",
84
89
  VerificationAttemptsExhausted: "verification_attempts_exhausted",
85
90
  MethodNotEnrolled: "method_not_enrolled",
86
- InvalidAuthorizationState: "invalid_authorization_state",
87
- TransactionMismatch: "transaction_mismatch",
88
- AuthorizationNotConsumable: "authorization_not_consumable",
89
- IdempotencyConflict: "idempotency_conflict"
91
+ InvalidApprovalState: "invalid_authorization_state",
92
+ PayloadMismatch: "payload_mismatch",
93
+ ApprovalNotConsumable: "authorization_not_consumable",
94
+ IdempotencyConflict: "idempotency_conflict",
95
+ UserDisabled: "user_disabled",
96
+ UserNotFound: "user_not_found",
97
+ TemporarilyUnavailable: "temporarily_unavailable",
98
+ InsufficientScope: "insufficient_scope",
99
+ CredentialThrottled: "credential_throttled",
100
+ ApprovalNotFound: "authorization_not_found",
101
+ SessionRevoked: "session_revoked",
102
+ TwoFactorTooManyFailures: "user.2fa.too_many_failures"
90
103
  };
91
104
  var STANDARD_ERROR_FIELDS = /* @__PURE__ */ new Set([
92
105
  "type",
@@ -600,7 +613,11 @@ var AuthyonClient = class {
600
613
  appendQuery(`/auth/tenants/${encodeURIComponent(organizationId)}/members`, params),
601
614
  { bearer: true }
602
615
  ),
603
- /** POST /auth/tenants/{organizationId}/members — invite a member by e-mail. */
616
+ /**
617
+ * POST /auth/tenants/{organizationId}/members — add an existing
618
+ * environment user by e-mail (no e-mail is sent). To invite an address
619
+ * that may not have an account yet, use `organization.invites.create`.
620
+ */
604
621
  invite: (organizationId, params) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/members`, {
605
622
  method: "POST",
606
623
  bearer: true,
@@ -612,6 +629,59 @@ var AuthyonClient = class {
612
629
  { method: "DELETE", bearer: true }
613
630
  )
614
631
  },
632
+ /**
633
+ * Invites by e-mail or by link. Managing them requires the
634
+ * `tenants:members:invite` permission on the organization; `preview` and
635
+ * `accept` are public — the token in the link is the credential.
636
+ */
637
+ invites: {
638
+ /** GET /auth/tenants/{organizationId}/invites — every invite with its status, newest first. */
639
+ list: (organizationId) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/invites`, {
640
+ bearer: true
641
+ }),
642
+ /**
643
+ * POST /auth/tenants/{organizationId}/invites — invite an address.
644
+ * Always returns `acceptUrl`; with `sendEmail: false` Authyon does not
645
+ * mail it and you deliver the link yourself. The link is valid for 7
646
+ * days, once, and can't be read again later.
647
+ */
648
+ create: (organizationId, params) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/invites`, {
649
+ method: "POST",
650
+ bearer: true,
651
+ body: {
652
+ email: params.email,
653
+ roles: params.roles,
654
+ sendEmail: params.sendEmail ?? true,
655
+ redirectUri: params.redirectUri
656
+ }
657
+ }),
658
+ /**
659
+ * POST /auth/tenants/{organizationId}/invites/{inviteId}/resend — issue
660
+ * a new link (the previous one stops working), mailing it unless
661
+ * `sendEmail` is `false`.
662
+ */
663
+ resend: (organizationId, inviteId, params = {}) => this.request(
664
+ `/auth/tenants/${encodeURIComponent(organizationId)}/invites/${encodeURIComponent(inviteId)}/resend`,
665
+ { method: "POST", bearer: true, body: { sendEmail: params.sendEmail ?? true } }
666
+ ),
667
+ /** DELETE /auth/tenants/{organizationId}/invites/{inviteId} — revoke a pending invite. */
668
+ revoke: (organizationId, inviteId) => this.request(
669
+ `/auth/tenants/${encodeURIComponent(organizationId)}/invites/${encodeURIComponent(inviteId)}`,
670
+ { method: "DELETE", bearer: true }
671
+ ),
672
+ /**
673
+ * POST /auth/tenant-invites/preview — public. Read the `token` query
674
+ * parameter of the invite link and pick the form: one click when
675
+ * `accountExists`, sign-up otherwise.
676
+ */
677
+ preview: (token) => this.request("/auth/tenant-invites/preview", { method: "POST", body: { token } }),
678
+ /**
679
+ * POST /auth/tenant-invites/accept — public. Joins the organization; for
680
+ * an address with no account, also creates it (password required) with
681
+ * the e-mail already confirmed. Does not sign the user in.
682
+ */
683
+ accept: (params) => this.request("/auth/tenant-invites/accept", { method: "POST", body: params })
684
+ },
615
685
  roles: {
616
686
  /** GET /auth/tenants/{organizationId}/roles — roles available in the organization. */
617
687
  list: (organizationId) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/roles`, {
@@ -687,14 +757,14 @@ var AuthyonClient = class {
687
757
  })
688
758
  }
689
759
  };
690
- // ── Financial step-up (customer side) ────────────────────────────────────
760
+ // ── Security (customer side) ─────────────────────────────────────────────
691
761
  /**
692
- * Transaction-bound approvals created by your backend
693
- * (`@authyon/server` → `environment.financialAuthorizations.create`).
694
- * Show the transaction with `get()`, then `confirm()` with the customer's
762
+ * `security.approvals`: approve or reject what your backend asked the
763
+ * customer to confirm (`@authyon/server` → `security.approvals.create`).
764
+ * Show the payload with `get()`, then `confirm()` with the customer's
695
765
  * authenticator code or passkey, or `reject()`.
696
766
  */
697
- this.financialAuthorizations = subjectFinancialAuthorizations(
767
+ this.security = subjectSecurity(
698
768
  (path2, options) => this.request(path2, { ...options, bearer: true })
699
769
  );
700
770
  if (!options.envKey)
package/dist/index.d.cts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-DbnbsQEX.cjs';
2
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as ConfirmFinancialAuthorizationInput, r as CreateOrganizationInput, F as FetchHttpAdapter, s as FinancialAssurance, t as FinancialAuthorization, u as FinancialAuthorizationStatus, v as FinancialTransaction, w as FinancialWebAuthnOptions, x as HttpAdapterRequest, y as HttpLogEvent, z as HttpLogger, I as IntrospectResult, B as InviteMemberInput, L as LoggingHttpAdapter, D as LoginInput, E as LoginResult, O as Organization, G as OrganizationMember, P as Paged, J as PaginationOptions, K as PermissionGroup, R as RegisterInput, M as Role, S as Session, N as SessionControllerOptions, Q as SessionInfo, U as SessionSnapshot, V as SessionSnapshotListener, W as SessionStatus, X as SsoProvider, Y as TwoFactorChallenge, Z as TwoFactorMethod, _ as TwoFactorStatus, $ as User, a0 as ValidateResult, a1 as VerifyTwoFactorInput, a2 as WebAuthnAssertion, a3 as WebAuthnCeremonyStart, a4 as WebAuthnCredential, a5 as createAuthyonAbility, a6 as createAuthyonRules, a7 as createClient, a8 as hasPermission, a9 as hasPermissionGroup } from './ability-DbnbsQEX.cjs';
1
+ import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-Cp8ir5Gr.cjs';
2
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as AcceptOrganizationInviteInput, h as Activity, i as Approval, j as ApprovalAssurance, k as ApprovalPayload, l as ApprovalStatus, m as ApprovalWebAuthnOptions, n as AuthEvent, o as AuthState, p as AuthStateListener, q as AuthenticatorSetup, r as AuthyonAbility, s as AuthyonAbilityBuilder, t as AuthyonAbilityOptions, u as AuthyonClientOptions, v as AuthyonPermissionSource, w as AuthyonSessionController, C as ConfirmApprovalInput, x as CreateOrganizationInput, F as FetchHttpAdapter, y as HttpAdapterRequest, z as HttpLogEvent, B as HttpLogger, I as IntrospectResult, D as InviteMemberInput, L as LoggingHttpAdapter, E as LoginInput, G as LoginResult, O as Organization, J as OrganizationInvite, K as OrganizationInviteAccepted, M as OrganizationInviteInput, N as OrganizationInviteIssued, P as OrganizationInvitePreview, Q as OrganizationInviteStatus, R as OrganizationMember, S as Paged, U as PaginationOptions, V as PermissionGroup, W as RegisterInput, X as Role, Y as SecurityMethods, Z as Session, _ as SessionControllerOptions, $ as SessionInfo, a0 as SessionSnapshot, a1 as SessionSnapshotListener, a2 as SessionStatus, a3 as SsoProvider, a4 as SubjectApprovals, a5 as SubjectSecurity, a6 as TwoFactorChallenge, a7 as TwoFactorMethod, a8 as TwoFactorStatus, a9 as User, aa as ValidateResult, ab as VerifyTwoFactorInput, ac as WebAuthnAssertion, ad as WebAuthnCeremonyStart, ae as WebAuthnCredential, af as createAuthyonAbility, ag as createAuthyonRules, ah as createClient, ai as hasPermission, aj as hasPermissionGroup } from './ability-Cp8ir5Gr.cjs';
3
3
 
4
4
  declare const ErrorCodes: {
5
5
  readonly Unknown: "unknown";
@@ -17,10 +17,18 @@ declare const ErrorCodes: {
17
17
  readonly InvalidSecondFactorCode: "invalid_code";
18
18
  readonly VerificationAttemptsExhausted: "verification_attempts_exhausted";
19
19
  readonly MethodNotEnrolled: "method_not_enrolled";
20
- readonly InvalidAuthorizationState: "invalid_authorization_state";
21
- readonly TransactionMismatch: "transaction_mismatch";
22
- readonly AuthorizationNotConsumable: "authorization_not_consumable";
20
+ readonly InvalidApprovalState: "invalid_authorization_state";
21
+ readonly PayloadMismatch: "payload_mismatch";
22
+ readonly ApprovalNotConsumable: "authorization_not_consumable";
23
23
  readonly IdempotencyConflict: "idempotency_conflict";
24
+ readonly UserDisabled: "user_disabled";
25
+ readonly UserNotFound: "user_not_found";
26
+ readonly TemporarilyUnavailable: "temporarily_unavailable";
27
+ readonly InsufficientScope: "insufficient_scope";
28
+ readonly CredentialThrottled: "credential_throttled";
29
+ readonly ApprovalNotFound: "authorization_not_found";
30
+ readonly SessionRevoked: "session_revoked";
31
+ readonly TwoFactorTooManyFailures: "user.2fa.too_many_failures";
24
32
  };
25
33
  type KnownErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
26
34
  type AuthyonErrorCategory = "network" | "timeout" | "authentication" | "authorization" | "validation" | "not_found" | "conflict" | "rate_limit" | "server" | "unknown";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-DbnbsQEX.js';
2
- export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as Activity, h as AuthEvent, i as AuthState, j as AuthStateListener, k as AuthenticatorSetup, l as AuthyonAbility, m as AuthyonAbilityBuilder, n as AuthyonAbilityOptions, o as AuthyonClientOptions, p as AuthyonPermissionSource, q as AuthyonSessionController, C as ConfirmFinancialAuthorizationInput, r as CreateOrganizationInput, F as FetchHttpAdapter, s as FinancialAssurance, t as FinancialAuthorization, u as FinancialAuthorizationStatus, v as FinancialTransaction, w as FinancialWebAuthnOptions, x as HttpAdapterRequest, y as HttpLogEvent, z as HttpLogger, I as IntrospectResult, B as InviteMemberInput, L as LoggingHttpAdapter, D as LoginInput, E as LoginResult, O as Organization, G as OrganizationMember, P as Paged, J as PaginationOptions, K as PermissionGroup, R as RegisterInput, M as Role, S as Session, N as SessionControllerOptions, Q as SessionInfo, U as SessionSnapshot, V as SessionSnapshotListener, W as SessionStatus, X as SsoProvider, Y as TwoFactorChallenge, Z as TwoFactorMethod, _ as TwoFactorStatus, $ as User, a0 as ValidateResult, a1 as VerifyTwoFactorInput, a2 as WebAuthnAssertion, a3 as WebAuthnCeremonyStart, a4 as WebAuthnCredential, a5 as createAuthyonAbility, a6 as createAuthyonRules, a7 as createClient, a8 as hasPermission, a9 as hasPermissionGroup } from './ability-DbnbsQEX.js';
1
+ import { T as TokenStorage, H as HttpAdapter, a as HttpLoggerOptions, A as AuthyonClient } from './ability-Cp8ir5Gr.js';
2
+ export { b as AbilityConditions, c as AbilityEvent, d as AbilityListener, e as AbilityRule, f as AbilitySubject, g as AcceptOrganizationInviteInput, h as Activity, i as Approval, j as ApprovalAssurance, k as ApprovalPayload, l as ApprovalStatus, m as ApprovalWebAuthnOptions, n as AuthEvent, o as AuthState, p as AuthStateListener, q as AuthenticatorSetup, r as AuthyonAbility, s as AuthyonAbilityBuilder, t as AuthyonAbilityOptions, u as AuthyonClientOptions, v as AuthyonPermissionSource, w as AuthyonSessionController, C as ConfirmApprovalInput, x as CreateOrganizationInput, F as FetchHttpAdapter, y as HttpAdapterRequest, z as HttpLogEvent, B as HttpLogger, I as IntrospectResult, D as InviteMemberInput, L as LoggingHttpAdapter, E as LoginInput, G as LoginResult, O as Organization, J as OrganizationInvite, K as OrganizationInviteAccepted, M as OrganizationInviteInput, N as OrganizationInviteIssued, P as OrganizationInvitePreview, Q as OrganizationInviteStatus, R as OrganizationMember, S as Paged, U as PaginationOptions, V as PermissionGroup, W as RegisterInput, X as Role, Y as SecurityMethods, Z as Session, _ as SessionControllerOptions, $ as SessionInfo, a0 as SessionSnapshot, a1 as SessionSnapshotListener, a2 as SessionStatus, a3 as SsoProvider, a4 as SubjectApprovals, a5 as SubjectSecurity, a6 as TwoFactorChallenge, a7 as TwoFactorMethod, a8 as TwoFactorStatus, a9 as User, aa as ValidateResult, ab as VerifyTwoFactorInput, ac as WebAuthnAssertion, ad as WebAuthnCeremonyStart, ae as WebAuthnCredential, af as createAuthyonAbility, ag as createAuthyonRules, ah as createClient, ai as hasPermission, aj as hasPermissionGroup } from './ability-Cp8ir5Gr.js';
3
3
 
4
4
  declare const ErrorCodes: {
5
5
  readonly Unknown: "unknown";
@@ -17,10 +17,18 @@ declare const ErrorCodes: {
17
17
  readonly InvalidSecondFactorCode: "invalid_code";
18
18
  readonly VerificationAttemptsExhausted: "verification_attempts_exhausted";
19
19
  readonly MethodNotEnrolled: "method_not_enrolled";
20
- readonly InvalidAuthorizationState: "invalid_authorization_state";
21
- readonly TransactionMismatch: "transaction_mismatch";
22
- readonly AuthorizationNotConsumable: "authorization_not_consumable";
20
+ readonly InvalidApprovalState: "invalid_authorization_state";
21
+ readonly PayloadMismatch: "payload_mismatch";
22
+ readonly ApprovalNotConsumable: "authorization_not_consumable";
23
23
  readonly IdempotencyConflict: "idempotency_conflict";
24
+ readonly UserDisabled: "user_disabled";
25
+ readonly UserNotFound: "user_not_found";
26
+ readonly TemporarilyUnavailable: "temporarily_unavailable";
27
+ readonly InsufficientScope: "insufficient_scope";
28
+ readonly CredentialThrottled: "credential_throttled";
29
+ readonly ApprovalNotFound: "authorization_not_found";
30
+ readonly SessionRevoked: "session_revoked";
31
+ readonly TwoFactorTooManyFailures: "user.2fa.too_many_failures";
24
32
  };
25
33
  type KnownErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];
26
34
  type AuthyonErrorCategory = "network" | "timeout" | "authentication" | "authorization" | "validation" | "not_found" | "conflict" | "rate_limit" | "server" | "unknown";
package/dist/index.js CHANGED
@@ -8,29 +8,34 @@ import {
8
8
  hasPermissionGroup
9
9
  } from "./chunk-3XJY6BCI.js";
10
10
 
11
- // ../../internal/core/financial/subjectFinancialAuthorizations.ts
11
+ // ../../internal/core/security/approvals.ts
12
12
  function path(id, suffix = "") {
13
13
  if (typeof id !== "string" || !id.trim())
14
- throw new TypeError("Authyon: a financial authorization id is required.");
14
+ throw new TypeError("Authyon: an approval id is required.");
15
15
  return `/auth/authorizations/${encodeURIComponent(id)}${suffix}`;
16
16
  }
17
- function subjectFinancialAuthorizations(request) {
17
+ var NO_METHODS = {
18
+ password: false,
19
+ authenticator: false,
20
+ emailCode: false,
21
+ passkey: false,
22
+ passkeyCount: 0,
23
+ recoveryCodes: 0,
24
+ sso: [],
25
+ twoFactor: false
26
+ };
27
+ function subjectSecurity(request) {
18
28
  return {
19
- /** GET /auth/authorizations/{id} — the pending transaction, to show before asking for the code. */
20
- get: (id) => request(path(id)),
21
- /** POST /auth/authorizations/{id}/webauthn/options — passkey options for approving this authorization. */
22
- webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
23
- /**
24
- * POST /auth/authorizations/{id}/confirm — approves the transaction.
25
- *
26
- * Pass the authenticator code or passkey assertion to verify the second
27
- * factor inline (recommended). Without `input`, the session itself must
28
- * have used a passkey or authenticator code within the last 5 minutes,
29
- * otherwise the API answers `step_up_required`.
30
- */
31
- confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
32
- /** POST /auth/authorizations/{id}/reject — the customer declines the transaction. */
33
- reject: (id) => request(path(id, "/reject"), { method: "POST" })
29
+ methods: async () => {
30
+ const me = await request("/auth/me");
31
+ return me.security ?? NO_METHODS;
32
+ },
33
+ approvals: {
34
+ get: (id) => request(path(id)),
35
+ webauthnOptions: (id) => request(path(id, "/webauthn/options"), { method: "POST" }),
36
+ confirm: (id, input) => request(path(id, "/confirm"), { method: "POST", body: input }),
37
+ reject: (id) => request(path(id, "/reject"), { method: "POST" })
38
+ }
34
39
  };
35
40
  }
36
41
 
@@ -51,10 +56,18 @@ var ErrorCodes = {
51
56
  InvalidSecondFactorCode: "invalid_code",
52
57
  VerificationAttemptsExhausted: "verification_attempts_exhausted",
53
58
  MethodNotEnrolled: "method_not_enrolled",
54
- InvalidAuthorizationState: "invalid_authorization_state",
55
- TransactionMismatch: "transaction_mismatch",
56
- AuthorizationNotConsumable: "authorization_not_consumable",
57
- IdempotencyConflict: "idempotency_conflict"
59
+ InvalidApprovalState: "invalid_authorization_state",
60
+ PayloadMismatch: "payload_mismatch",
61
+ ApprovalNotConsumable: "authorization_not_consumable",
62
+ IdempotencyConflict: "idempotency_conflict",
63
+ UserDisabled: "user_disabled",
64
+ UserNotFound: "user_not_found",
65
+ TemporarilyUnavailable: "temporarily_unavailable",
66
+ InsufficientScope: "insufficient_scope",
67
+ CredentialThrottled: "credential_throttled",
68
+ ApprovalNotFound: "authorization_not_found",
69
+ SessionRevoked: "session_revoked",
70
+ TwoFactorTooManyFailures: "user.2fa.too_many_failures"
58
71
  };
59
72
  var STANDARD_ERROR_FIELDS = /* @__PURE__ */ new Set([
60
73
  "type",
@@ -568,7 +581,11 @@ var AuthyonClient = class {
568
581
  appendQuery(`/auth/tenants/${encodeURIComponent(organizationId)}/members`, params),
569
582
  { bearer: true }
570
583
  ),
571
- /** POST /auth/tenants/{organizationId}/members — invite a member by e-mail. */
584
+ /**
585
+ * POST /auth/tenants/{organizationId}/members — add an existing
586
+ * environment user by e-mail (no e-mail is sent). To invite an address
587
+ * that may not have an account yet, use `organization.invites.create`.
588
+ */
572
589
  invite: (organizationId, params) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/members`, {
573
590
  method: "POST",
574
591
  bearer: true,
@@ -580,6 +597,59 @@ var AuthyonClient = class {
580
597
  { method: "DELETE", bearer: true }
581
598
  )
582
599
  },
600
+ /**
601
+ * Invites by e-mail or by link. Managing them requires the
602
+ * `tenants:members:invite` permission on the organization; `preview` and
603
+ * `accept` are public — the token in the link is the credential.
604
+ */
605
+ invites: {
606
+ /** GET /auth/tenants/{organizationId}/invites — every invite with its status, newest first. */
607
+ list: (organizationId) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/invites`, {
608
+ bearer: true
609
+ }),
610
+ /**
611
+ * POST /auth/tenants/{organizationId}/invites — invite an address.
612
+ * Always returns `acceptUrl`; with `sendEmail: false` Authyon does not
613
+ * mail it and you deliver the link yourself. The link is valid for 7
614
+ * days, once, and can't be read again later.
615
+ */
616
+ create: (organizationId, params) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/invites`, {
617
+ method: "POST",
618
+ bearer: true,
619
+ body: {
620
+ email: params.email,
621
+ roles: params.roles,
622
+ sendEmail: params.sendEmail ?? true,
623
+ redirectUri: params.redirectUri
624
+ }
625
+ }),
626
+ /**
627
+ * POST /auth/tenants/{organizationId}/invites/{inviteId}/resend — issue
628
+ * a new link (the previous one stops working), mailing it unless
629
+ * `sendEmail` is `false`.
630
+ */
631
+ resend: (organizationId, inviteId, params = {}) => this.request(
632
+ `/auth/tenants/${encodeURIComponent(organizationId)}/invites/${encodeURIComponent(inviteId)}/resend`,
633
+ { method: "POST", bearer: true, body: { sendEmail: params.sendEmail ?? true } }
634
+ ),
635
+ /** DELETE /auth/tenants/{organizationId}/invites/{inviteId} — revoke a pending invite. */
636
+ revoke: (organizationId, inviteId) => this.request(
637
+ `/auth/tenants/${encodeURIComponent(organizationId)}/invites/${encodeURIComponent(inviteId)}`,
638
+ { method: "DELETE", bearer: true }
639
+ ),
640
+ /**
641
+ * POST /auth/tenant-invites/preview — public. Read the `token` query
642
+ * parameter of the invite link and pick the form: one click when
643
+ * `accountExists`, sign-up otherwise.
644
+ */
645
+ preview: (token) => this.request("/auth/tenant-invites/preview", { method: "POST", body: { token } }),
646
+ /**
647
+ * POST /auth/tenant-invites/accept — public. Joins the organization; for
648
+ * an address with no account, also creates it (password required) with
649
+ * the e-mail already confirmed. Does not sign the user in.
650
+ */
651
+ accept: (params) => this.request("/auth/tenant-invites/accept", { method: "POST", body: params })
652
+ },
583
653
  roles: {
584
654
  /** GET /auth/tenants/{organizationId}/roles — roles available in the organization. */
585
655
  list: (organizationId) => this.request(`/auth/tenants/${encodeURIComponent(organizationId)}/roles`, {
@@ -655,14 +725,14 @@ var AuthyonClient = class {
655
725
  })
656
726
  }
657
727
  };
658
- // ── Financial step-up (customer side) ────────────────────────────────────
728
+ // ── Security (customer side) ─────────────────────────────────────────────
659
729
  /**
660
- * Transaction-bound approvals created by your backend
661
- * (`@authyon/server` → `environment.financialAuthorizations.create`).
662
- * Show the transaction with `get()`, then `confirm()` with the customer's
730
+ * `security.approvals`: approve or reject what your backend asked the
731
+ * customer to confirm (`@authyon/server` → `security.approvals.create`).
732
+ * Show the payload with `get()`, then `confirm()` with the customer's
663
733
  * authenticator code or passkey, or `reject()`.
664
734
  */
665
- this.financialAuthorizations = subjectFinancialAuthorizations(
735
+ this.security = subjectSecurity(
666
736
  (path2, options) => this.request(path2, { ...options, bearer: true })
667
737
  );
668
738
  if (!options.envKey)
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { $ as User, N as SessionControllerOptions, A as AuthyonClient, U as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-DbnbsQEX.cjs';
4
- export { q as AuthyonSessionController, V as SessionSnapshotListener, W as SessionStatus } from '../ability-DbnbsQEX.cjs';
3
+ import { a9 as User, _ as SessionControllerOptions, A as AuthyonClient, a0 as SessionSnapshot, Z as Session, f as AbilitySubject, t as AuthyonAbilityOptions, r as AuthyonAbility } from '../ability-Cp8ir5Gr.cjs';
4
+ export { w as AuthyonSessionController, a1 as SessionSnapshotListener, a2 as SessionStatus } from '../ability-Cp8ir5Gr.cjs';
5
5
 
6
6
  interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
7
7
  client: AuthyonClient;
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactNode } from 'react';
3
- import { $ as User, N as SessionControllerOptions, A as AuthyonClient, U as SessionSnapshot, S as Session, f as AbilitySubject, n as AuthyonAbilityOptions, l as AuthyonAbility } from '../ability-DbnbsQEX.js';
4
- export { q as AuthyonSessionController, V as SessionSnapshotListener, W as SessionStatus } from '../ability-DbnbsQEX.js';
3
+ import { a9 as User, _ as SessionControllerOptions, A as AuthyonClient, a0 as SessionSnapshot, Z as Session, f as AbilitySubject, t as AuthyonAbilityOptions, r as AuthyonAbility } from '../ability-Cp8ir5Gr.js';
4
+ export { w as AuthyonSessionController, a1 as SessionSnapshotListener, a2 as SessionStatus } from '../ability-Cp8ir5Gr.js';
5
5
 
6
6
  interface AuthyonProviderProps<TUser extends User = User> extends SessionControllerOptions {
7
7
  client: AuthyonClient;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@authyon/auth",
3
- "version": "0.2.0-beta.14",
3
+ "version": "0.2.0-beta.16",
4
4
  "description": "Authyon SDK for browsers — auth, sessions, multi-tenant and 2FA for vanilla JS/TS.",
5
5
  "license": "MIT",
6
6
  "type": "module",