@asturiu/v0-sdk 0.0.0-stage → 1.0.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/CHANGELOG.md +42 -0
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/README.md +82 -2
- package/contract/assertion-vectors.json +90 -0
- package/contract/schemas/branding.schema.json +46 -0
- package/contract/schemas/definitions.schema.json +376 -0
- package/contract/schemas/portal.schema.json +56 -0
- package/contract/tenant-api-routes.json +165 -0
- package/dist/branding.d.ts +131 -0
- package/dist/branding.d.ts.map +1 -0
- package/dist/branding.js +206 -0
- package/dist/branding.js.map +1 -0
- package/dist/changesets.d.ts +58 -0
- package/dist/changesets.d.ts.map +1 -0
- package/dist/changesets.js +18 -0
- package/dist/changesets.js.map +1 -0
- package/dist/cli/bin.d.ts +3 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +12 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/changesets.d.ts +14 -0
- package/dist/cli/changesets.d.ts.map +1 -0
- package/dist/cli/changesets.js +252 -0
- package/dist/cli/changesets.js.map +1 -0
- package/dist/cli/cli.d.ts +37 -0
- package/dist/cli/cli.d.ts.map +1 -0
- package/dist/cli/cli.js +415 -0
- package/dist/cli/cli.js.map +1 -0
- package/dist/cli/context.d.ts +147 -0
- package/dist/cli/context.d.ts.map +1 -0
- package/dist/cli/context.js +258 -0
- package/dist/cli/context.js.map +1 -0
- package/dist/cli/engine.d.ts +59 -0
- package/dist/cli/engine.d.ts.map +1 -0
- package/dist/cli/engine.js +85 -0
- package/dist/cli/engine.js.map +1 -0
- package/dist/cli/feedback.d.ts +40 -0
- package/dist/cli/feedback.d.ts.map +1 -0
- package/dist/cli/feedback.js +420 -0
- package/dist/cli/feedback.js.map +1 -0
- package/dist/cli/files.d.ts +83 -0
- package/dist/cli/files.d.ts.map +1 -0
- package/dist/cli/files.js +389 -0
- package/dist/cli/files.js.map +1 -0
- package/dist/cli/index.d.ts +8 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/overview.d.ts +6 -0
- package/dist/cli/overview.d.ts.map +1 -0
- package/dist/cli/overview.js +379 -0
- package/dist/cli/overview.js.map +1 -0
- package/dist/cli/parts.d.ts +5 -0
- package/dist/cli/parts.d.ts.map +1 -0
- package/dist/cli/parts.js +414 -0
- package/dist/cli/parts.js.map +1 -0
- package/dist/cli/sources.d.ts +37 -0
- package/dist/cli/sources.d.ts.map +1 -0
- package/dist/cli/sources.js +91 -0
- package/dist/cli/sources.js.map +1 -0
- package/dist/cli/terminal.d.ts +135 -0
- package/dist/cli/terminal.d.ts.map +1 -0
- package/dist/cli/terminal.js +353 -0
- package/dist/cli/terminal.js.map +1 -0
- package/dist/cli/ui-page.d.ts +8 -0
- package/dist/cli/ui-page.d.ts.map +1 -0
- package/dist/cli/ui-page.js +216 -0
- package/dist/cli/ui-page.js.map +1 -0
- package/dist/cli/ui.d.ts +54 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +251 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/client.d.ts +88 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +165 -0
- package/dist/client.js.map +1 -0
- package/dist/contacts.d.ts +43 -0
- package/dist/contacts.d.ts.map +1 -0
- package/dist/contacts.js +46 -0
- package/dist/contacts.js.map +1 -0
- package/dist/definition-set.d.ts +731 -0
- package/dist/definition-set.d.ts.map +1 -0
- package/dist/definition-set.js +659 -0
- package/dist/definition-set.js.map +1 -0
- package/dist/definitions.d.ts +42 -0
- package/dist/definitions.d.ts.map +1 -0
- package/dist/definitions.js +154 -0
- package/dist/definitions.js.map +1 -0
- package/dist/enrolment.d.ts +9 -0
- package/dist/enrolment.d.ts.map +1 -0
- package/dist/enrolment.js +8 -0
- package/dist/enrolment.js.map +1 -0
- package/dist/fill.d.ts +73 -0
- package/dist/fill.d.ts.map +1 -0
- package/dist/fill.js +46 -0
- package/dist/fill.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/notifications.d.ts +33 -0
- package/dist/notifications.d.ts.map +1 -0
- package/dist/notifications.js +36 -0
- package/dist/notifications.js.map +1 -0
- package/dist/oidc.d.ts +122 -0
- package/dist/oidc.d.ts.map +1 -0
- package/dist/oidc.js +150 -0
- package/dist/oidc.js.map +1 -0
- package/dist/overlay.d.ts +109 -0
- package/dist/overlay.d.ts.map +1 -0
- package/dist/overlay.js +58 -0
- package/dist/overlay.js.map +1 -0
- package/dist/passes.d.ts +95 -0
- package/dist/passes.d.ts.map +1 -0
- package/dist/passes.js +140 -0
- package/dist/passes.js.map +1 -0
- package/dist/portal-options.d.ts +65 -0
- package/dist/portal-options.d.ts.map +1 -0
- package/dist/portal-options.js +120 -0
- package/dist/portal-options.js.map +1 -0
- package/dist/reads.d.ts +41 -0
- package/dist/reads.d.ts.map +1 -0
- package/dist/reads.js +44 -0
- package/dist/reads.js.map +1 -0
- package/dist/recovery-words.d.ts +8 -0
- package/dist/recovery-words.d.ts.map +1 -0
- package/dist/recovery-words.js +136 -0
- package/dist/recovery-words.js.map +1 -0
- package/dist/recovery.d.ts +198 -0
- package/dist/recovery.d.ts.map +1 -0
- package/dist/recovery.js +112 -0
- package/dist/recovery.js.map +1 -0
- package/dist/reveal.d.ts +35 -0
- package/dist/reveal.d.ts.map +1 -0
- package/dist/reveal.js +66 -0
- package/dist/reveal.js.map +1 -0
- package/dist/seal.d.ts +15 -0
- package/dist/seal.d.ts.map +1 -0
- package/dist/seal.js +0 -0
- package/dist/seal.js.map +1 -0
- package/dist/session.d.ts +66 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +61 -0
- package/dist/session.js.map +1 -0
- package/dist/signing-in-mark.d.ts +14 -0
- package/dist/signing-in-mark.d.ts.map +1 -0
- package/dist/signing-in-mark.js +24 -0
- package/dist/signing-in-mark.js.map +1 -0
- package/dist/signing-in.d.ts +22 -0
- package/dist/signing-in.d.ts.map +1 -0
- package/dist/signing-in.js +203 -0
- package/dist/signing-in.js.map +1 -0
- package/dist/tags.d.ts +96 -0
- package/dist/tags.d.ts.map +1 -0
- package/dist/tags.js +88 -0
- package/dist/tags.js.map +1 -0
- package/dist/tenant-subscription.d.ts +47 -0
- package/dist/tenant-subscription.d.ts.map +1 -0
- package/dist/tenant-subscription.js +7 -0
- package/dist/tenant-subscription.js.map +1 -0
- package/dist/testing/index.d.ts +125 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +320 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/theme.d.ts +237 -0
- package/dist/theme.d.ts.map +1 -0
- package/dist/theme.js +504 -0
- package/dist/theme.js.map +1 -0
- package/dist/tickets.d.ts +152 -0
- package/dist/tickets.d.ts.map +1 -0
- package/dist/tickets.js +65 -0
- package/dist/tickets.js.map +1 -0
- package/dist/tiers.d.ts +168 -0
- package/dist/tiers.d.ts.map +1 -0
- package/dist/tiers.js +341 -0
- package/dist/tiers.js.map +1 -0
- package/dist/types.d.ts +885 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +12 -0
- package/dist/types.js.map +1 -0
- package/dist/urlid.d.ts +50 -0
- package/dist/urlid.d.ts.map +1 -0
- package/dist/urlid.js +78 -0
- package/dist/urlid.js.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +15 -0
- package/dist/version.js.map +1 -0
- package/make/asturiu.mk +43 -0
- package/package.json +63 -4
- package/src/branding.ts +221 -0
- package/src/changesets.ts +61 -0
- package/src/cli/bin.ts +12 -0
- package/src/cli/changesets.ts +233 -0
- package/src/cli/cli.ts +425 -0
- package/src/cli/context.ts +299 -0
- package/src/cli/engine.ts +112 -0
- package/src/cli/feedback.ts +406 -0
- package/src/cli/files.ts +371 -0
- package/src/cli/index.ts +7 -0
- package/src/cli/overview.ts +343 -0
- package/src/cli/parts.ts +371 -0
- package/src/cli/sources.ts +111 -0
- package/src/cli/terminal.ts +384 -0
- package/src/cli/ui-page.ts +215 -0
- package/src/cli/ui.ts +266 -0
- package/src/client.ts +202 -0
- package/src/contacts.ts +61 -0
- package/src/definition-set.ts +965 -0
- package/src/definitions.ts +156 -0
- package/src/enrolment.ts +10 -0
- package/src/fill.ts +83 -0
- package/src/index.ts +38 -0
- package/src/notifications.ts +55 -0
- package/src/oidc.ts +199 -0
- package/src/overlay.ts +137 -0
- package/src/passes.ts +168 -0
- package/src/portal-options.ts +125 -0
- package/src/reads.ts +71 -0
- package/src/recovery-words.ts +137 -0
- package/src/recovery.ts +269 -0
- package/src/reveal.ts +72 -0
- package/src/seal.ts +0 -0
- package/src/session.ts +93 -0
- package/src/signing-in-mark.ts +23 -0
- package/src/signing-in.ts +213 -0
- package/src/tags.ts +146 -0
- package/src/tenant-subscription.ts +44 -0
- package/src/testing/index.ts +337 -0
- package/src/theme.ts +628 -0
- package/src/tickets.ts +195 -0
- package/src/tiers.ts +397 -0
- package/src/types.ts +847 -0
- package/src/urlid.ts +77 -0
- package/src/version.ts +15 -0
- package/templates/asturiu/branding.json +4 -0
- package/templates/asturiu/definitions.json +23 -0
- package/templates/asturiu/portal.json +16 -0
package/dist/oidc.d.ts
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC helpers for the Frontend layer (components/02-customer-ui-web.md §Login
|
|
3
|
+
* completion; flows/authentication.md). Dependency-free: Web Crypto only, so
|
|
4
|
+
* the same code runs in a Next.js route handler, an edge runtime or Node.
|
|
5
|
+
*/
|
|
6
|
+
/** Authentik OIDC endpoints for an Application slug, relative to a base URL. */
|
|
7
|
+
export declare function oidcEndpoints(base: string, slug: string): {
|
|
8
|
+
issuer: string;
|
|
9
|
+
authorize: string;
|
|
10
|
+
token: string;
|
|
11
|
+
userinfo: string;
|
|
12
|
+
jwks: string;
|
|
13
|
+
endSession: string;
|
|
14
|
+
/** The Tenant's authentication, enrolment and recovery flows (components/11-authentik.md §One Application per Tenant). */
|
|
15
|
+
authentication: string;
|
|
16
|
+
enrollment: string;
|
|
17
|
+
recovery: string;
|
|
18
|
+
/** The step-up flows (ADR-018): confirm the password, or the password and a second factor, on the live Authentik session. */
|
|
19
|
+
stepUpPassword: string;
|
|
20
|
+
stepUp2fa: string;
|
|
21
|
+
/** Change the password (ADR-022); ends in a fresh authorization request. */
|
|
22
|
+
passwordChange: string;
|
|
23
|
+
/** Register with the Tenant using an existing shared account: its own sign-in, then a review (ADR-043, ADR-051); `shared` Tenants only. */
|
|
24
|
+
join: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* The message of a Tenant sign-in that refuses an account outside the Tenant
|
|
28
|
+
* (ADR-051): the Operations API's blueprint gives its deny stage this text,
|
|
29
|
+
* and the Customer Portal recognises it to show its own "register first" step.
|
|
30
|
+
* Readable as it is, for any page that shows Authentik's own words.
|
|
31
|
+
*/
|
|
32
|
+
export declare const NOT_REGISTERED_DENIAL = "This account is not registered here yet. Register first, then sign in.";
|
|
33
|
+
/**
|
|
34
|
+
* The message of a sign-up form that refuses an e-mail address another account
|
|
35
|
+
* has (ADR-053): the Operations API's blueprint gives the enrolment prompt's
|
|
36
|
+
* validation policy this text, and the Customer Portal recognises it to show
|
|
37
|
+
* it in the page's language. It says nothing about who has the address.
|
|
38
|
+
*/
|
|
39
|
+
export declare const EMAIL_NOT_ALLOWED = "This e-mail address is not allowed.";
|
|
40
|
+
/** Every flow the Operations API provisions per Tenant, named `<slug>-<kind>` (components/11-authentik.md). */
|
|
41
|
+
export declare const TENANT_FLOW_KINDS: readonly ["authentication", "enrollment", "recovery", "invalidation", "stepup-password", "stepup-2fa", "password-change", "source-enrollment", "source-authentication", "join"];
|
|
42
|
+
/** The platform's account Application's flows (ADR-022, ADR-032; the step-ups since ADR-022 build note 1). */
|
|
43
|
+
export declare const ACCOUNT_FLOW_KINDS: readonly ["authentication", "recovery", "invalidation", "password-change", "stepup-password", "stepup-2fa"];
|
|
44
|
+
/** The administrative Application's flows (ADR-032). */
|
|
45
|
+
export declare const ADMIN_FLOW_KINDS: readonly ["authentication", "invalidation"];
|
|
46
|
+
export type TenantFlowKind = (typeof TENANT_FLOW_KINDS)[number];
|
|
47
|
+
/** A flow slug: `<slug>-<kind>`, as the Operations API names every flow it provisions. */
|
|
48
|
+
export declare function tenantFlowSlug(slug: string, kind: TenantFlowKind): string;
|
|
49
|
+
/**
|
|
50
|
+
* The exact flow slugs an Application owns (ADR-032). A sign-in host runs
|
|
51
|
+
* these and nothing else; a prefix would not do, because slugs contain
|
|
52
|
+
* hyphens — `acme-` also matches `acme-labs-…`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function flowSlugsOf(slug: string, kinds?: readonly TenantFlowKind[]): string[];
|
|
55
|
+
/**
|
|
56
|
+
* Run a Tenant flow first, then the authorization request: Authentik executes
|
|
57
|
+
* the flow and, when its last stage is done, continues to `next` — the
|
|
58
|
+
* authorization request — so the Web UI's callback completes as usual. Used
|
|
59
|
+
* for enrolment (a session exists once the login stage ran) and for step-up
|
|
60
|
+
* (the session's login event is fresh, so the token proves what just happened).
|
|
61
|
+
*/
|
|
62
|
+
export declare function buildFlowUrl(flowEndpoint: string, authorizeUrl: string): string;
|
|
63
|
+
/** Start enrolment instead of login (see `buildFlowUrl`). */
|
|
64
|
+
export declare function buildEnrollmentUrl(enrollmentEndpoint: string, authorizeUrl: string): string;
|
|
65
|
+
export type OidcEndpoints = ReturnType<typeof oidcEndpoints>;
|
|
66
|
+
export declare const OIDC_SCOPE = "openid email profile";
|
|
67
|
+
export declare function randomToken(bytes?: number): string;
|
|
68
|
+
export interface Pkce {
|
|
69
|
+
verifier: string;
|
|
70
|
+
challenge: string;
|
|
71
|
+
method: "S256";
|
|
72
|
+
}
|
|
73
|
+
/** A fresh PKCE pair per login attempt (RFC 7636, S256). */
|
|
74
|
+
export declare function createPkce(): Promise<Pkce>;
|
|
75
|
+
export interface AuthorizeRequest {
|
|
76
|
+
authorizeEndpoint: string;
|
|
77
|
+
clientId: string;
|
|
78
|
+
redirectUri: string;
|
|
79
|
+
state: string;
|
|
80
|
+
codeChallenge: string;
|
|
81
|
+
scope?: string;
|
|
82
|
+
/** Passed through to Authentik as-is (`prompt`, `login_hint`, …). */
|
|
83
|
+
extra?: Record<string, string>;
|
|
84
|
+
}
|
|
85
|
+
/** The authorization-code request the Web UI starts; PKCE and `state` are mandatory. */
|
|
86
|
+
export declare function buildAuthorizeUrl(r: AuthorizeRequest): string;
|
|
87
|
+
export interface TokenResponse {
|
|
88
|
+
access_token: string;
|
|
89
|
+
id_token?: string;
|
|
90
|
+
token_type?: string;
|
|
91
|
+
expires_in?: number;
|
|
92
|
+
scope?: string;
|
|
93
|
+
}
|
|
94
|
+
export declare class OidcError extends Error {
|
|
95
|
+
readonly code: string;
|
|
96
|
+
readonly description?: string | undefined;
|
|
97
|
+
readonly status?: number | undefined;
|
|
98
|
+
constructor(code: string, description?: string | undefined, status?: number | undefined);
|
|
99
|
+
}
|
|
100
|
+
export interface CodeExchange {
|
|
101
|
+
tokenEndpoint: string;
|
|
102
|
+
clientId: string;
|
|
103
|
+
code: string;
|
|
104
|
+
redirectUri: string;
|
|
105
|
+
codeVerifier: string;
|
|
106
|
+
/** Confidential clients only; Tenant Providers are public clients. */
|
|
107
|
+
clientSecret?: string;
|
|
108
|
+
fetch?: typeof fetch;
|
|
109
|
+
timeoutMs?: number;
|
|
110
|
+
}
|
|
111
|
+
/** Back-channel code exchange with the PKCE verifier. The token is exchanged for a session and then discarded. */
|
|
112
|
+
export declare function exchangeCode(x: CodeExchange): Promise<TokenResponse>;
|
|
113
|
+
/**
|
|
114
|
+
* Where to send the browser after the Engine session is gone, so Authentik's
|
|
115
|
+
* own session ends too. Authentik (2025.10) does not read
|
|
116
|
+
* `post_logout_redirect_uri`: the Tenant's invalidation flow signs the person
|
|
117
|
+
* out and redirects to the Tenant's site (`branding.product_url`,
|
|
118
|
+
* components/11-authentik.md §No portal for customers). The parameter is kept
|
|
119
|
+
* for a conforming provider.
|
|
120
|
+
*/
|
|
121
|
+
export declare function buildEndSessionUrl(endSessionEndpoint: string, postLogoutRedirectUri?: string): string;
|
|
122
|
+
//# sourceMappingURL=oidc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.d.ts","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"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"}
|
package/dist/oidc.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OIDC helpers for the Frontend layer (components/02-customer-ui-web.md §Login
|
|
3
|
+
* completion; flows/authentication.md). Dependency-free: Web Crypto only, so
|
|
4
|
+
* the same code runs in a Next.js route handler, an edge runtime or Node.
|
|
5
|
+
*/
|
|
6
|
+
/** Authentik OIDC endpoints for an Application slug, relative to a base URL. */
|
|
7
|
+
export function oidcEndpoints(base, slug) {
|
|
8
|
+
const b = base.replace(/\/+$/, "");
|
|
9
|
+
return {
|
|
10
|
+
issuer: `${b}/application/o/${slug}/`,
|
|
11
|
+
authorize: `${b}/application/o/authorize/`,
|
|
12
|
+
token: `${b}/application/o/token/`,
|
|
13
|
+
userinfo: `${b}/application/o/userinfo/`,
|
|
14
|
+
jwks: `${b}/application/o/${slug}/jwks/`,
|
|
15
|
+
endSession: `${b}/application/o/${slug}/end-session/`,
|
|
16
|
+
/** The Tenant's authentication, enrolment and recovery flows (components/11-authentik.md §One Application per Tenant). */
|
|
17
|
+
authentication: `${b}/if/flow/${tenantFlowSlug(slug, "authentication")}/`,
|
|
18
|
+
enrollment: `${b}/if/flow/${tenantFlowSlug(slug, "enrollment")}/`,
|
|
19
|
+
recovery: `${b}/if/flow/${tenantFlowSlug(slug, "recovery")}/`,
|
|
20
|
+
/** The step-up flows (ADR-018): confirm the password, or the password and a second factor, on the live Authentik session. */
|
|
21
|
+
stepUpPassword: `${b}/if/flow/${tenantFlowSlug(slug, "stepup-password")}/`,
|
|
22
|
+
stepUp2fa: `${b}/if/flow/${tenantFlowSlug(slug, "stepup-2fa")}/`,
|
|
23
|
+
/** Change the password (ADR-022); ends in a fresh authorization request. */
|
|
24
|
+
passwordChange: `${b}/if/flow/${tenantFlowSlug(slug, "password-change")}/`,
|
|
25
|
+
/** Register with the Tenant using an existing shared account: its own sign-in, then a review (ADR-043, ADR-051); `shared` Tenants only. */
|
|
26
|
+
join: `${b}/if/flow/${tenantFlowSlug(slug, "join")}/`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* The message of a Tenant sign-in that refuses an account outside the Tenant
|
|
31
|
+
* (ADR-051): the Operations API's blueprint gives its deny stage this text,
|
|
32
|
+
* and the Customer Portal recognises it to show its own "register first" step.
|
|
33
|
+
* Readable as it is, for any page that shows Authentik's own words.
|
|
34
|
+
*/
|
|
35
|
+
export const NOT_REGISTERED_DENIAL = "This account is not registered here yet. Register first, then sign in.";
|
|
36
|
+
/**
|
|
37
|
+
* The message of a sign-up form that refuses an e-mail address another account
|
|
38
|
+
* has (ADR-053): the Operations API's blueprint gives the enrolment prompt's
|
|
39
|
+
* validation policy this text, and the Customer Portal recognises it to show
|
|
40
|
+
* it in the page's language. It says nothing about who has the address.
|
|
41
|
+
*/
|
|
42
|
+
export const EMAIL_NOT_ALLOWED = "This e-mail address is not allowed.";
|
|
43
|
+
/** Every flow the Operations API provisions per Tenant, named `<slug>-<kind>` (components/11-authentik.md). */
|
|
44
|
+
export const TENANT_FLOW_KINDS = ["authentication", "enrollment", "recovery", "invalidation", "stepup-password", "stepup-2fa", "password-change", "source-enrollment", "source-authentication", "join"];
|
|
45
|
+
/** The platform's account Application's flows (ADR-022, ADR-032; the step-ups since ADR-022 build note 1). */
|
|
46
|
+
export const ACCOUNT_FLOW_KINDS = ["authentication", "recovery", "invalidation", "password-change", "stepup-password", "stepup-2fa"];
|
|
47
|
+
/** The administrative Application's flows (ADR-032). */
|
|
48
|
+
export const ADMIN_FLOW_KINDS = ["authentication", "invalidation"];
|
|
49
|
+
/** A flow slug: `<slug>-<kind>`, as the Operations API names every flow it provisions. */
|
|
50
|
+
export function tenantFlowSlug(slug, kind) {
|
|
51
|
+
return `${slug}-${kind}`;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The exact flow slugs an Application owns (ADR-032). A sign-in host runs
|
|
55
|
+
* these and nothing else; a prefix would not do, because slugs contain
|
|
56
|
+
* hyphens — `acme-` also matches `acme-labs-…`.
|
|
57
|
+
*/
|
|
58
|
+
export function flowSlugsOf(slug, kinds = TENANT_FLOW_KINDS) {
|
|
59
|
+
return kinds.map((k) => tenantFlowSlug(slug, k));
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Run a Tenant flow first, then the authorization request: Authentik executes
|
|
63
|
+
* the flow and, when its last stage is done, continues to `next` — the
|
|
64
|
+
* authorization request — so the Web UI's callback completes as usual. Used
|
|
65
|
+
* for enrolment (a session exists once the login stage ran) and for step-up
|
|
66
|
+
* (the session's login event is fresh, so the token proves what just happened).
|
|
67
|
+
*/
|
|
68
|
+
export function buildFlowUrl(flowEndpoint, authorizeUrl) {
|
|
69
|
+
const url = new URL(flowEndpoint);
|
|
70
|
+
const authorize = new URL(authorizeUrl);
|
|
71
|
+
// Authentik accepts `next` as a path on its own host (the form its own redirects use); an absolute URL is not carried through the flow.
|
|
72
|
+
url.searchParams.set("next", authorize.origin === url.origin ? `${authorize.pathname}${authorize.search}` : authorizeUrl);
|
|
73
|
+
return url.toString();
|
|
74
|
+
}
|
|
75
|
+
/** Start enrolment instead of login (see `buildFlowUrl`). */
|
|
76
|
+
export function buildEnrollmentUrl(enrollmentEndpoint, authorizeUrl) {
|
|
77
|
+
return buildFlowUrl(enrollmentEndpoint, authorizeUrl);
|
|
78
|
+
}
|
|
79
|
+
export const OIDC_SCOPE = "openid email profile";
|
|
80
|
+
function b64url(bytes) {
|
|
81
|
+
let s = "";
|
|
82
|
+
for (const b of bytes)
|
|
83
|
+
s += String.fromCharCode(b);
|
|
84
|
+
const base64 = typeof btoa === "function" ? btoa(s) : Buffer.from(bytes).toString("base64");
|
|
85
|
+
return base64.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
86
|
+
}
|
|
87
|
+
export function randomToken(bytes = 32) {
|
|
88
|
+
const out = new Uint8Array(bytes);
|
|
89
|
+
crypto.getRandomValues(out);
|
|
90
|
+
return b64url(out);
|
|
91
|
+
}
|
|
92
|
+
/** A fresh PKCE pair per login attempt (RFC 7636, S256). */
|
|
93
|
+
export async function createPkce() {
|
|
94
|
+
const verifier = randomToken(48);
|
|
95
|
+
const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(verifier));
|
|
96
|
+
return { verifier, challenge: b64url(new Uint8Array(digest)), method: "S256" };
|
|
97
|
+
}
|
|
98
|
+
/** The authorization-code request the Web UI starts; PKCE and `state` are mandatory. */
|
|
99
|
+
export function buildAuthorizeUrl(r) {
|
|
100
|
+
const url = new URL(r.authorizeEndpoint);
|
|
101
|
+
url.searchParams.set("response_type", "code");
|
|
102
|
+
url.searchParams.set("client_id", r.clientId);
|
|
103
|
+
url.searchParams.set("redirect_uri", r.redirectUri);
|
|
104
|
+
url.searchParams.set("scope", r.scope ?? OIDC_SCOPE);
|
|
105
|
+
url.searchParams.set("state", r.state);
|
|
106
|
+
url.searchParams.set("code_challenge", r.codeChallenge);
|
|
107
|
+
url.searchParams.set("code_challenge_method", "S256");
|
|
108
|
+
for (const [k, v] of Object.entries(r.extra ?? {}))
|
|
109
|
+
url.searchParams.set(k, v);
|
|
110
|
+
return url.toString();
|
|
111
|
+
}
|
|
112
|
+
export class OidcError extends Error {
|
|
113
|
+
code;
|
|
114
|
+
description;
|
|
115
|
+
status;
|
|
116
|
+
constructor(code, description, status) {
|
|
117
|
+
super(description ? `${code}: ${description}` : code);
|
|
118
|
+
this.code = code;
|
|
119
|
+
this.description = description;
|
|
120
|
+
this.status = status;
|
|
121
|
+
this.name = "OidcError";
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/** Back-channel code exchange with the PKCE verifier. The token is exchanged for a session and then discarded. */
|
|
125
|
+
export async function exchangeCode(x) {
|
|
126
|
+
const form = new URLSearchParams({ grant_type: "authorization_code", client_id: x.clientId, code: x.code, redirect_uri: x.redirectUri, code_verifier: x.codeVerifier });
|
|
127
|
+
if (x.clientSecret)
|
|
128
|
+
form.set("client_secret", x.clientSecret);
|
|
129
|
+
const f = x.fetch ?? ((input, init) => globalThis.fetch(input, init)); // called on the global, never as a detached method
|
|
130
|
+
const res = await f(x.tokenEndpoint, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded", accept: "application/json" }, body: form, signal: AbortSignal.timeout(x.timeoutMs ?? 15000) });
|
|
131
|
+
const json = (await res.json().catch(() => ({})));
|
|
132
|
+
if (!res.ok || !json.access_token)
|
|
133
|
+
throw new OidcError(json.error ?? `http_${res.status}`, json.error_description, res.status);
|
|
134
|
+
return json;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Where to send the browser after the Engine session is gone, so Authentik's
|
|
138
|
+
* own session ends too. Authentik (2025.10) does not read
|
|
139
|
+
* `post_logout_redirect_uri`: the Tenant's invalidation flow signs the person
|
|
140
|
+
* out and redirects to the Tenant's site (`branding.product_url`,
|
|
141
|
+
* components/11-authentik.md §No portal for customers). The parameter is kept
|
|
142
|
+
* for a conforming provider.
|
|
143
|
+
*/
|
|
144
|
+
export function buildEndSessionUrl(endSessionEndpoint, postLogoutRedirectUri) {
|
|
145
|
+
const url = new URL(endSessionEndpoint);
|
|
146
|
+
if (postLogoutRedirectUri)
|
|
147
|
+
url.searchParams.set("post_logout_redirect_uri", postLogoutRedirectUri);
|
|
148
|
+
return url.toString();
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=oidc.js.map
|
package/dist/oidc.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oidc.js","sourceRoot":"","sources":["../src/oidc.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet overlays (ADR-028): a Customer's renames, layout and custom fields
|
|
3
|
+
* for one Wallet. Shared by the Engine (validation, the reveal gate) and every
|
|
4
|
+
* frontend (forms, labels): pure and dependency-free so the Frontend kit can
|
|
5
|
+
* carry it.
|
|
6
|
+
*/
|
|
7
|
+
import { type RevealLevel } from "./reveal.js";
|
|
8
|
+
import type { EntryDefinitionDetail, EntryDefinitionField, FieldValueType } from "./types.js";
|
|
9
|
+
import type { FillMode, LocatorRule } from "./fill.js";
|
|
10
|
+
/** The key of a custom field: `x_` and a ULID, generated by the Engine. */
|
|
11
|
+
export declare const CUSTOM_FIELD_ID: RegExp;
|
|
12
|
+
export declare function isCustomFieldId(value: unknown): value is string;
|
|
13
|
+
/** How strict a reveal level is: a higher rank asks more of the person. `null` (a plain field) ranks lowest. */
|
|
14
|
+
export declare function revealRank(level: RevealLevel | null | undefined): number;
|
|
15
|
+
/** One custom field of a Wallet overlay. */
|
|
16
|
+
export interface CustomFieldSpec {
|
|
17
|
+
id: string;
|
|
18
|
+
/** The Entry type it applies to (`edf` ARID). */
|
|
19
|
+
entry_definition: string;
|
|
20
|
+
label: string;
|
|
21
|
+
description?: string;
|
|
22
|
+
value_type: FieldValueType;
|
|
23
|
+
validation?: {
|
|
24
|
+
pattern?: string;
|
|
25
|
+
min?: number;
|
|
26
|
+
max?: number;
|
|
27
|
+
min_length?: number;
|
|
28
|
+
max_length?: number;
|
|
29
|
+
enum?: (string | number | boolean)[];
|
|
30
|
+
};
|
|
31
|
+
/** Required on Entries created after it was added, and wherever it holds a value. */
|
|
32
|
+
required: boolean;
|
|
33
|
+
secret: boolean;
|
|
34
|
+
/** Only with `secret`; `click` when absent. Never below the Entry type's `secret_reveal_min`. */
|
|
35
|
+
reveal?: RevealLevel;
|
|
36
|
+
searchable: boolean;
|
|
37
|
+
/** ADR-046, as on a FieldDefinition: the modes allowed (absent: what the Entry type's `custom_filled_by` allows), what an internal reference may point at, the locator rule. */
|
|
38
|
+
filled_by?: FillMode[];
|
|
39
|
+
targets?: string[];
|
|
40
|
+
target_definitions?: string[];
|
|
41
|
+
locator?: LocatorRule;
|
|
42
|
+
}
|
|
43
|
+
/** Order and hidden Tenant fields for one Entry type. `order` lists field keys: `fdf` ARIDs and `x_` ids. */
|
|
44
|
+
export interface OverlayLayout {
|
|
45
|
+
order?: string[];
|
|
46
|
+
hidden?: string[];
|
|
47
|
+
}
|
|
48
|
+
/** The document `PUT /v0/wallets/{arid}/overlay` takes. A new custom field omits `id`. */
|
|
49
|
+
export interface WalletOverlayInput {
|
|
50
|
+
renames?: Record<string, string>;
|
|
51
|
+
layout?: Record<string, OverlayLayout>;
|
|
52
|
+
fields?: (Omit<CustomFieldSpec, "id" | "required" | "secret" | "searchable"> & {
|
|
53
|
+
id?: string;
|
|
54
|
+
required?: boolean;
|
|
55
|
+
secret?: boolean;
|
|
56
|
+
searchable?: boolean;
|
|
57
|
+
})[];
|
|
58
|
+
}
|
|
59
|
+
/** What the Wallet owner's subscription level allows, and what the overlay uses of it. */
|
|
60
|
+
export interface OverlayAllowance {
|
|
61
|
+
level: string;
|
|
62
|
+
rename: boolean;
|
|
63
|
+
arrange: boolean;
|
|
64
|
+
secret_fields: boolean;
|
|
65
|
+
extra_fields: {
|
|
66
|
+
max: number;
|
|
67
|
+
used: number;
|
|
68
|
+
};
|
|
69
|
+
searchable_fields: {
|
|
70
|
+
max: number;
|
|
71
|
+
used: number;
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** `GET /v0/wallets/{arid}/overlay`. `arid` and `version` are `null` until the Wallet is first customised. */
|
|
75
|
+
export interface WalletOverlay {
|
|
76
|
+
wallet: string;
|
|
77
|
+
arid: string | null;
|
|
78
|
+
version: number | null;
|
|
79
|
+
renames: Record<string, string>;
|
|
80
|
+
layout: Record<string, OverlayLayout>;
|
|
81
|
+
fields: CustomFieldSpec[];
|
|
82
|
+
allowance: OverlayAllowance;
|
|
83
|
+
}
|
|
84
|
+
/** One field of a form or a view, Tenant or custom, as the overlay presents it. */
|
|
85
|
+
export interface FormField {
|
|
86
|
+
/** `fdf` ARID for a Tenant field, `x_` id for a custom one. */
|
|
87
|
+
key: string;
|
|
88
|
+
custom: boolean;
|
|
89
|
+
label: string;
|
|
90
|
+
description?: string;
|
|
91
|
+
value_type?: FieldValueType;
|
|
92
|
+
secret: boolean;
|
|
93
|
+
reveal?: RevealLevel;
|
|
94
|
+
searchable: boolean;
|
|
95
|
+
required: boolean;
|
|
96
|
+
hidden: boolean;
|
|
97
|
+
/** The Tenant's declaration, for a Tenant field. */
|
|
98
|
+
definition?: EntryDefinitionField;
|
|
99
|
+
/** The overlay's spec, for a custom field. */
|
|
100
|
+
spec?: CustomFieldSpec;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The fields of an Entry type in the order and with the names this Wallet's
|
|
104
|
+
* overlay gives them: the overlay's `order` first, then the remaining Tenant
|
|
105
|
+
* fields in the Tenant's order, then the remaining custom fields. Hidden
|
|
106
|
+
* fields are included and marked; leaving them out is the frontend's choice.
|
|
107
|
+
*/
|
|
108
|
+
export declare function orderedFormFields(def: Pick<EntryDefinitionDetail, "arid" | "fields">, overlay: Pick<WalletOverlay, "renames" | "layout" | "fields"> | null | undefined): FormField[];
|
|
109
|
+
//# sourceMappingURL=overlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.d.ts","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"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"}
|
package/dist/overlay.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wallet overlays (ADR-028): a Customer's renames, layout and custom fields
|
|
3
|
+
* for one Wallet. Shared by the Engine (validation, the reveal gate) and every
|
|
4
|
+
* frontend (forms, labels): pure and dependency-free so the Frontend kit can
|
|
5
|
+
* carry it.
|
|
6
|
+
*/
|
|
7
|
+
import { REVEAL_LEVELS } from "./reveal.js";
|
|
8
|
+
/** The key of a custom field: `x_` and a ULID, generated by the Engine. */
|
|
9
|
+
export const CUSTOM_FIELD_ID = /^x_[0-9A-HJKMNP-TV-Z]{26}$/;
|
|
10
|
+
export function isCustomFieldId(value) {
|
|
11
|
+
return typeof value === "string" && CUSTOM_FIELD_ID.test(value);
|
|
12
|
+
}
|
|
13
|
+
/** How strict a reveal level is: a higher rank asks more of the person. `null` (a plain field) ranks lowest. */
|
|
14
|
+
export function revealRank(level) {
|
|
15
|
+
return level ? REVEAL_LEVELS.indexOf(level) : -1;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The fields of an Entry type in the order and with the names this Wallet's
|
|
19
|
+
* overlay gives them: the overlay's `order` first, then the remaining Tenant
|
|
20
|
+
* fields in the Tenant's order, then the remaining custom fields. Hidden
|
|
21
|
+
* fields are included and marked; leaving them out is the frontend's choice.
|
|
22
|
+
*/
|
|
23
|
+
export function orderedFormFields(def, overlay) {
|
|
24
|
+
const tenant = def.fields
|
|
25
|
+
.map((f, i) => ({ f, i }))
|
|
26
|
+
.sort((a, b) => (a.f.order ?? a.i) - (b.f.order ?? b.i) || a.i - b.i)
|
|
27
|
+
.map(({ f }) => ({
|
|
28
|
+
key: f.definition.arid,
|
|
29
|
+
custom: false,
|
|
30
|
+
label: overlay?.renames?.[f.definition.arid] ?? f.label ?? f.name ?? f.definition.arid,
|
|
31
|
+
value_type: f.value_type,
|
|
32
|
+
secret: !!f.secret,
|
|
33
|
+
reveal: f.reveal,
|
|
34
|
+
searchable: !!f.searchable,
|
|
35
|
+
required: f.required,
|
|
36
|
+
hidden: false,
|
|
37
|
+
definition: f,
|
|
38
|
+
}));
|
|
39
|
+
const custom = (overlay?.fields ?? [])
|
|
40
|
+
.filter((s) => s.entry_definition === def.arid)
|
|
41
|
+
.map((s) => ({ key: s.id, custom: true, label: s.label, description: s.description, value_type: s.value_type, secret: s.secret, reveal: s.secret ? s.reveal ?? "click" : undefined, searchable: s.searchable, required: s.required, hidden: false, spec: s }));
|
|
42
|
+
const layout = overlay?.layout?.[def.arid];
|
|
43
|
+
const hidden = new Set(layout?.hidden ?? []);
|
|
44
|
+
const byKey = new Map([...tenant, ...custom].map((f) => [f.key, f]));
|
|
45
|
+
const out = [];
|
|
46
|
+
for (const k of layout?.order ?? []) {
|
|
47
|
+
const f = byKey.get(k);
|
|
48
|
+
if (f) {
|
|
49
|
+
out.push(f);
|
|
50
|
+
byKey.delete(k);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
for (const f of [...tenant, ...custom])
|
|
54
|
+
if (byKey.has(f.key))
|
|
55
|
+
out.push(f);
|
|
56
|
+
return out.map((f) => ({ ...f, hidden: !f.custom && !f.required && hidden.has(f.key) }));
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=overlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"overlay.js","sourceRoot":"","sources":["../src/overlay.ts"],"names":[],"mappings":"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"}
|
package/dist/passes.d.ts
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guest passes (ADR-040): the kinds and states of a pass, the code a person
|
|
3
|
+
* types, and what a Tenant switches on for its customers' passes. Pure and
|
|
4
|
+
* dependency-free: the Engine validates with these lists, the Customer
|
|
5
|
+
* Portal, the Admin UI and a Tenant's app read with them.
|
|
6
|
+
*/
|
|
7
|
+
/** `bearer`: a link for anyone, the token in the link. `email`: a code sent to one address, typed on the pass page. */
|
|
8
|
+
export declare const PASS_KINDS: readonly ["bearer", "email"];
|
|
9
|
+
export type PassKind = (typeof PASS_KINDS)[number];
|
|
10
|
+
/** What is stored; `ended`, `expired` and `exhausted` are derived when read (`passState`). */
|
|
11
|
+
export declare const PASS_STORED_STATES: readonly ["active", "locked", "revoked"];
|
|
12
|
+
export type PassStoredState = (typeof PASS_STORED_STATES)[number];
|
|
13
|
+
export declare const PASS_STATES: readonly ["active", "locked", "revoked", "ended", "expired", "exhausted"];
|
|
14
|
+
export type PassState = (typeof PASS_STATES)[number];
|
|
15
|
+
/** A link for anyone opens at once or behind a captcha; an e-mail pass always asks for its code. */
|
|
16
|
+
export declare const PASS_GATES: readonly ["none", "captcha", "code"];
|
|
17
|
+
export type PassGate = (typeof PASS_GATES)[number];
|
|
18
|
+
/** Where an e-mail pass is opened: the Customer Portal's pass page, or the Tenant's own app. */
|
|
19
|
+
export declare const PASS_PAGES: readonly ["portal", "app"];
|
|
20
|
+
export type PassPage = (typeof PASS_PAGES)[number];
|
|
21
|
+
export declare const PASS_LIMITS: {
|
|
22
|
+
readonly label: 120;
|
|
23
|
+
readonly message: 1000;
|
|
24
|
+
readonly appUrl: 2000;
|
|
25
|
+
readonly codeFailuresMin: 3;
|
|
26
|
+
readonly codeFailuresMax: 20;
|
|
27
|
+
readonly sessionsMax: 50;
|
|
28
|
+
readonly lifetimeDaysMax: 3650;
|
|
29
|
+
readonly passesPerLevelMax: 1000;
|
|
30
|
+
readonly opensMax: 100000;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* The derived state of a pass. Terminal states come first, so a pass that is
|
|
34
|
+
* both expired and locked reads `expired`: only an `active` pass opens.
|
|
35
|
+
*/
|
|
36
|
+
export declare function passState(p: {
|
|
37
|
+
stored: PassStoredState;
|
|
38
|
+
not_after?: string | Date | null;
|
|
39
|
+
opens: number;
|
|
40
|
+
max_opens?: number | null;
|
|
41
|
+
bound?: boolean;
|
|
42
|
+
}, now?: number): PassState;
|
|
43
|
+
/** 32 capital letters and digits without 0, 1, I and O, so a code read aloud or typed again is not mistaken. */
|
|
44
|
+
export declare const PASS_CODE_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
|
|
45
|
+
/** 8 characters from 32: 40 bits, safe only behind the attempt limit (ADR-040 §6). */
|
|
46
|
+
export declare const PASS_CODE_LENGTH = 8;
|
|
47
|
+
/** What a person typed, as the Engine compares it: capitals, with spaces, dashes and dots dropped. */
|
|
48
|
+
export declare function normalizePassCode(input: string): string;
|
|
49
|
+
export declare function isPassCode(value: string): boolean;
|
|
50
|
+
/** `ABCDEFGH` → `ABCD-EFGH`, the way the code is shown in the e-mail. */
|
|
51
|
+
export declare function formatPassCode(code: string): string;
|
|
52
|
+
/** `Tenant.passes` (ADR-040 §10), every key filled. */
|
|
53
|
+
export interface TenantPassOptions {
|
|
54
|
+
bearer: boolean;
|
|
55
|
+
email: boolean;
|
|
56
|
+
page: PassPage;
|
|
57
|
+
/** The Tenant app's pass page: links for anyone, the handover, and `page: app`. */
|
|
58
|
+
app_url: string | null;
|
|
59
|
+
/** The latest end date a pass may have, in days; `null` also allows passes without an end date. */
|
|
60
|
+
max_lifetime_days: number | null;
|
|
61
|
+
code_failure_limit: number;
|
|
62
|
+
/** The ceiling for live guest sessions per pass. */
|
|
63
|
+
max_sessions: number;
|
|
64
|
+
}
|
|
65
|
+
export declare function defaultPassOptions(): TenantPassOptions;
|
|
66
|
+
/** An http(s) URL without credentials, as a pass may point to; null otherwise. */
|
|
67
|
+
export declare function passAppUrl(v: unknown): string | null;
|
|
68
|
+
/**
|
|
69
|
+
* The rules a set of pass options must keep beyond its shape: an app address
|
|
70
|
+
* while either kind is on. One entry per problem, with
|
|
71
|
+
* its path under `passes`; the Engine's Tenant schema reports them as `422`.
|
|
72
|
+
*/
|
|
73
|
+
export declare function passOptionProblems(raw: unknown): {
|
|
74
|
+
path: (string | number)[];
|
|
75
|
+
message: string;
|
|
76
|
+
}[];
|
|
77
|
+
/**
|
|
78
|
+
* Stored or presented options as every reader takes them: anything missing or
|
|
79
|
+
* odd back to its default, so an older record or Interface API never breaks a
|
|
80
|
+
* page. Passes stay off unless a kind is on and the app address is good.
|
|
81
|
+
*/
|
|
82
|
+
export declare function resolvePassOptions(raw: unknown): TenantPassOptions;
|
|
83
|
+
/** What the portal needs from `Tenant.passes`, on the public presentation. */
|
|
84
|
+
export interface PassPresentation {
|
|
85
|
+
email: boolean;
|
|
86
|
+
page: PassPage;
|
|
87
|
+
app_url: string | null;
|
|
88
|
+
}
|
|
89
|
+
/** The latest end date a new pass may have, or `null` when passes without an end date are allowed. */
|
|
90
|
+
export declare function passLatestEnd(options: TenantPassOptions, now?: number): Date | null;
|
|
91
|
+
/** The address a link for anyone carries: the app's pass page with the token in the fragment, never sent to a server. */
|
|
92
|
+
export declare function bearerPassUrl(appUrl: string, token: string): string;
|
|
93
|
+
/** The app's pass page with one query parameter added (`handover`, or `pass` for a handle). */
|
|
94
|
+
export declare function passAppTarget(appUrl: string, key: "handover" | "pass", value: string): string;
|
|
95
|
+
//# sourceMappingURL=passes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passes.d.ts","sourceRoot":"","sources":["../src/passes.ts"],"names":[],"mappings":"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"}
|