@substrat-run/vertical-auth 0.9.0 → 0.10.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/dist/index.d.ts CHANGED
@@ -5,4 +5,5 @@ export { IdentityDO, doAuthProvider, type IdentityDoEnv, type IdentityStub } fro
5
5
  export { resolveCookieDomain } from './cookie-domain.js';
6
6
  export { FIRST_SIGN_IN_WINDOW_MS, OWNER_CLAIM_TTL_MS, type OwnerSeat } from './owner-seat.js';
7
7
  export { mintOwnerClaimLink, ownerClaimPath, sha256Hex } from './owner-claim-link.js';
8
+ export { AUTH_CONFIG_KEY, AuthConfigError, authChoice, instanceAuthFor, parseAuthChoice, selectAuthProvider, type AuthChoice, type InstanceAuth, } from './instance-auth.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -4,4 +4,5 @@ export { IdentityDO, doAuthProvider } from './identity-do.js';
4
4
  export { resolveCookieDomain } from './cookie-domain.js';
5
5
  export { FIRST_SIGN_IN_WINDOW_MS, OWNER_CLAIM_TTL_MS } from './owner-seat.js';
6
6
  export { mintOwnerClaimLink, ownerClaimPath, sha256Hex } from './owner-claim-link.js';
7
+ export { AUTH_CONFIG_KEY, AuthConfigError, authChoice, instanceAuthFor, parseAuthChoice, selectAuthProvider, } from './instance-auth.js';
7
8
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAqB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAyC,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAkB,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAmB,MAAM,WAAW,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAqB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,UAAU,EAAE,cAAc,EAAyC,MAAM,kBAAkB,CAAC;AACrG,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,kBAAkB,EAAkB,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AACtF,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,eAAe,EACf,eAAe,EACf,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,102 @@
1
+ import { z, type EnvVarSpec } from '@substrat-run/contracts';
2
+ import type { IdentityStub } from './identity-do.js';
3
+ import type { AuthProvider } from './provider.js';
4
+ /**
5
+ * ONE instance's auth wiring — the composition every OIDC-only vertical was writing
6
+ * for itself (#972).
7
+ *
8
+ * Four demos carried a near-identical forty-line copy of "read the delivered config,
9
+ * parse `substrat:auth`, resolve the declared settings, pick a provider", and they had
10
+ * already drifted: manyfold's copy skipped `resolveScopedEnvSpec` entirely and read
11
+ * `env.OIDC_ISSUER`, so a per-instance issuer saved in the dashboard never reached it
12
+ * (the silent-defaults bug, #374/#398); meridian's fail-closed check on an unset issuer
13
+ * existed only in meridian. A rule that lives in four places is four chances to be
14
+ * wrong about it once. It lives here now.
15
+ */
16
+ /**
17
+ * The scope's DELIVERED auth choice (vertical-auth-detach.md §2.2/§2.3) — the
18
+ * `substrat:auth` entry the dashboard configured at install or in Settings.
19
+ *
20
+ * OIDC-only (oidc-only-demos.md): `oidc` is the only supported mode, so a `builtin` or
21
+ * malformed entry fails this parse and reads as "nothing delivered". That leniency is
22
+ * deliberate — a bad delivery falls back to the deployment default rather than locking
23
+ * an instance out of its own login.
24
+ */
25
+ export declare const authChoice: z.ZodObject<{
26
+ mode: z.ZodLiteral<"oidc">;
27
+ issuer: z.ZodOptional<z.ZodString>;
28
+ clientId: z.ZodOptional<z.ZodString>;
29
+ clientSecret: z.ZodOptional<z.ZodString>;
30
+ audience: z.ZodOptional<z.ZodString>;
31
+ cookieDomain: z.ZodOptional<z.ZodString>;
32
+ }, z.core.$strip>;
33
+ export type AuthChoice = z.infer<typeof authChoice>;
34
+ /** The delivered-config key the dashboard writes the identity choice to. */
35
+ export declare const AUTH_CONFIG_KEY = "substrat:auth";
36
+ /**
37
+ * An instance that cannot be given a provider, with the status to answer.
38
+ *
39
+ * A plain `Error` would arrive at a vertical's error envelope as a 500, which is the
40
+ * wrong answer for "nobody has configured this yet" — so the status travels with the
41
+ * throw and each worker re-raises it in its own framework's exception.
42
+ */
43
+ export declare class AuthConfigError extends Error {
44
+ readonly status: 500 | 503;
45
+ constructor(status: 500 | 503, message: string);
46
+ }
47
+ export interface InstanceAuth {
48
+ /** The parsed `substrat:auth` choice, or null when nothing usable was delivered. */
49
+ identity: AuthChoice | null;
50
+ /** The tenant's DO-minted session-signing secret. */
51
+ sessionSecret: string;
52
+ /** The declared settings, resolved delivered > binding > manifest default (#398). */
53
+ settings: Record<string, string | undefined>;
54
+ /** The whole delivered map — for a vertical's own non-declared keys. */
55
+ config: Record<string, string>;
56
+ /**
57
+ * The `AuthProvider` this instance's configuration selects. A function, not a field:
58
+ * a route that only wants `settings` must not fail because nobody has configured a
59
+ * login yet. Throws `AuthConfigError` when there is nothing to select.
60
+ */
61
+ provider(): AuthProvider;
62
+ }
63
+ /**
64
+ * Everything an instance was configured with, in ONE DO hop.
65
+ *
66
+ * `settings` comes from `resolveScopedEnvSpec` over the SAME delivered map the auth
67
+ * choice rides in — no second round-trip, and per-scope Env-tab value > worker binding >
68
+ * manifest default. Reading `env` directly instead is the bug this replaces: a spec
69
+ * `default` rides as a binding shared by every install of one serving script, so
70
+ * `env.OIDC_ISSUER` is the same string for every tenant no matter what any of them saved.
71
+ */
72
+ export declare function instanceAuthFor(opts: {
73
+ /** The tenant's identity DO stub. */
74
+ directory: Pick<IdentityStub, 'authWiring'>;
75
+ scopeId: string;
76
+ /** The vertical's declared env spec (`CALLOUT_ENV`, `TICKET0_ENV`, …). */
77
+ envSpec: EnvVarSpec[];
78
+ /** The worker's own environment — the binding layer under the delivered map. */
79
+ env: Record<string, unknown>;
80
+ }): Promise<InstanceAuth>;
81
+ /** The delivered `substrat:auth` entry, parsed leniently: anything unusable is null. */
82
+ export declare function parseAuthChoice(raw: string | undefined): AuthChoice | null;
83
+ /**
84
+ * The provider an instance's configuration selects — the whole point of the contract.
85
+ *
86
+ * Per-SCOPE first (hosted): a delivered `substrat:auth` builds the full relying-party
87
+ * provider (browser login at the issuer, cookie sessions signed with the tenant's
88
+ * DO-minted secret, bearer fallback for API clients) — one script, many issuers.
89
+ * Absent that, the DEPLOYMENT default: `AUTH_PROVIDER=oidc` verifies bearer tokens
90
+ * against a fixed issuer (standalone deploys). Anything else is unconfigured — fail
91
+ * closed. The app never learns which; it only ever holds an `AuthProvider`.
92
+ *
93
+ * `AUTH_PROVIDER=oidc` with no `OIDC_ISSUER` is a 500, not a 503: the deployment asked
94
+ * for a provider it did not finish configuring, which is an operator's mistake, not a
95
+ * tenant's missing choice.
96
+ */
97
+ export declare function selectAuthProvider(opts: {
98
+ identity: AuthChoice | null;
99
+ sessionSecret: string;
100
+ settings: Record<string, string | undefined>;
101
+ }): AuthProvider;
102
+ //# sourceMappingURL=instance-auth.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-auth.d.ts","sourceRoot":"","sources":["../src/instance-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAwB,CAAC,EAAE,KAAK,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAGnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD;;;;;;;;;;;GAWG;AAEH;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU;;;;;;;iBAQrB,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAC;AAEpD,4EAA4E;AAC5E,eAAO,MAAM,eAAe,kBAAkB,CAAC;AAE/C;;;;;;GAMG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IAEtC,QAAQ,CAAC,MAAM,EAAE,GAAG,GAAG,GAAG;IAD5B,YACW,MAAM,EAAE,GAAG,GAAG,GAAG,EAC1B,OAAO,EAAE,MAAM,EAIhB;CACF;AAED,MAAM,WAAW,YAAY;IAC3B,oFAAoF;IACpF,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,qDAAqD;IACrD,aAAa,EAAE,MAAM,CAAC;IACtB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B;;;;OAIG;IACH,QAAQ,IAAI,YAAY,CAAC;CAC1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE;IAC1C,qCAAqC;IACrC,SAAS,EAAE,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B,GAAG,OAAO,CAAC,YAAY,CAAC,CAWxB;AAED,wFAAwF;AACxF,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,IAAI,CAQ1E;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE;IACvC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC9C,GAAG,YAAY,CA+Bf"}
@@ -0,0 +1,124 @@
1
+ import { resolveScopedEnvSpec, z } from '@substrat-run/contracts';
2
+ import { oidcAuthProvider } from './oidc.js';
3
+ import { oidcRpAuthProvider } from './oidc-rp-provider.js';
4
+ /**
5
+ * ONE instance's auth wiring — the composition every OIDC-only vertical was writing
6
+ * for itself (#972).
7
+ *
8
+ * Four demos carried a near-identical forty-line copy of "read the delivered config,
9
+ * parse `substrat:auth`, resolve the declared settings, pick a provider", and they had
10
+ * already drifted: manyfold's copy skipped `resolveScopedEnvSpec` entirely and read
11
+ * `env.OIDC_ISSUER`, so a per-instance issuer saved in the dashboard never reached it
12
+ * (the silent-defaults bug, #374/#398); meridian's fail-closed check on an unset issuer
13
+ * existed only in meridian. A rule that lives in four places is four chances to be
14
+ * wrong about it once. It lives here now.
15
+ */
16
+ /**
17
+ * The scope's DELIVERED auth choice (vertical-auth-detach.md §2.2/§2.3) — the
18
+ * `substrat:auth` entry the dashboard configured at install or in Settings.
19
+ *
20
+ * OIDC-only (oidc-only-demos.md): `oidc` is the only supported mode, so a `builtin` or
21
+ * malformed entry fails this parse and reads as "nothing delivered". That leniency is
22
+ * deliberate — a bad delivery falls back to the deployment default rather than locking
23
+ * an instance out of its own login.
24
+ */
25
+ export const authChoice = z.object({
26
+ mode: z.literal('oidc'),
27
+ issuer: z.string().url().optional(),
28
+ clientId: z.string().min(1).optional(),
29
+ clientSecret: z.string().optional(),
30
+ audience: z.string().optional(),
31
+ /** Share the login across every surface under this parent domain (K-26 multi-surface). */
32
+ cookieDomain: z.string().min(1).optional(),
33
+ });
34
+ /** The delivered-config key the dashboard writes the identity choice to. */
35
+ export const AUTH_CONFIG_KEY = 'substrat:auth';
36
+ /**
37
+ * An instance that cannot be given a provider, with the status to answer.
38
+ *
39
+ * A plain `Error` would arrive at a vertical's error envelope as a 500, which is the
40
+ * wrong answer for "nobody has configured this yet" — so the status travels with the
41
+ * throw and each worker re-raises it in its own framework's exception.
42
+ */
43
+ export class AuthConfigError extends Error {
44
+ status;
45
+ constructor(status, message) {
46
+ super(message);
47
+ this.status = status;
48
+ this.name = 'AuthConfigError';
49
+ }
50
+ }
51
+ /**
52
+ * Everything an instance was configured with, in ONE DO hop.
53
+ *
54
+ * `settings` comes from `resolveScopedEnvSpec` over the SAME delivered map the auth
55
+ * choice rides in — no second round-trip, and per-scope Env-tab value > worker binding >
56
+ * manifest default. Reading `env` directly instead is the bug this replaces: a spec
57
+ * `default` rides as a binding shared by every install of one serving script, so
58
+ * `env.OIDC_ISSUER` is the same string for every tenant no matter what any of them saved.
59
+ */
60
+ export async function instanceAuthFor(opts) {
61
+ const wiring = await opts.directory.authWiring(opts.scopeId);
62
+ const identity = parseAuthChoice(wiring.config[AUTH_CONFIG_KEY]);
63
+ const settings = resolveScopedEnvSpec(opts.envSpec, opts.env, wiring.config).values;
64
+ return {
65
+ identity,
66
+ sessionSecret: wiring.sessionSecret,
67
+ settings,
68
+ config: wiring.config,
69
+ provider: () => selectAuthProvider({ identity, sessionSecret: wiring.sessionSecret, settings }),
70
+ };
71
+ }
72
+ /** The delivered `substrat:auth` entry, parsed leniently: anything unusable is null. */
73
+ export function parseAuthChoice(raw) {
74
+ if (!raw)
75
+ return null;
76
+ try {
77
+ const parsed = authChoice.safeParse(JSON.parse(raw));
78
+ return parsed.success ? parsed.data : null;
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ }
84
+ /**
85
+ * The provider an instance's configuration selects — the whole point of the contract.
86
+ *
87
+ * Per-SCOPE first (hosted): a delivered `substrat:auth` builds the full relying-party
88
+ * provider (browser login at the issuer, cookie sessions signed with the tenant's
89
+ * DO-minted secret, bearer fallback for API clients) — one script, many issuers.
90
+ * Absent that, the DEPLOYMENT default: `AUTH_PROVIDER=oidc` verifies bearer tokens
91
+ * against a fixed issuer (standalone deploys). Anything else is unconfigured — fail
92
+ * closed. The app never learns which; it only ever holds an `AuthProvider`.
93
+ *
94
+ * `AUTH_PROVIDER=oidc` with no `OIDC_ISSUER` is a 500, not a 503: the deployment asked
95
+ * for a provider it did not finish configuring, which is an operator's mistake, not a
96
+ * tenant's missing choice.
97
+ */
98
+ export function selectAuthProvider(opts) {
99
+ const { identity, settings } = opts;
100
+ if (identity?.mode === 'oidc') {
101
+ if (!identity.issuer || !identity.clientId) {
102
+ throw new AuthConfigError(503, "this instance's OIDC configuration is incomplete — set issuer and clientId");
103
+ }
104
+ return oidcRpAuthProvider({
105
+ issuer: identity.issuer,
106
+ clientId: identity.clientId,
107
+ clientSecret: identity.clientSecret ?? '',
108
+ sessionSecret: opts.sessionSecret,
109
+ ...(identity.audience ? { audience: identity.audience } : {}),
110
+ ...(identity.cookieDomain ? { cookieDomain: identity.cookieDomain } : {}),
111
+ });
112
+ }
113
+ if (settings.AUTH_PROVIDER === 'oidc') {
114
+ if (!settings.OIDC_ISSUER) {
115
+ throw new AuthConfigError(500, 'AUTH_PROVIDER=oidc but OIDC_ISSUER is unset');
116
+ }
117
+ return oidcAuthProvider({
118
+ issuer: settings.OIDC_ISSUER,
119
+ ...(settings.OIDC_AUDIENCE ? { audience: settings.OIDC_AUDIENCE } : {}),
120
+ });
121
+ }
122
+ throw new AuthConfigError(503, "this instance has no identity provider configured — deliver substrat:auth with mode 'oidc', or set AUTH_PROVIDER=oidc and OIDC_ISSUER");
123
+ }
124
+ //# sourceMappingURL=instance-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-auth.js","sourceRoot":"","sources":["../src/instance-auth.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@substrat-run/vertical-auth",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Pluggable auth for Substrat verticals — the AuthProvider contract, an OIDC provider (Supabase/Auth0/AuthHero/Keycloak), a full relying-party login flow, and a per-tenant identity Durable Object (Better Auth + sub→principal directory). Workers-targeted; the vertical worker bundles it.",
5
5
  "license": "AGPL-3.0-only",
6
6
  "repository": {
@@ -37,7 +37,8 @@
37
37
  "drizzle-orm": "^0.45.2",
38
38
  "jose": "^6.2.3",
39
39
  "@substrat-run/oidc-rp": "^0.5.1",
40
- "@substrat-run/psl": "^0.2.2"
40
+ "@substrat-run/contracts": "^0.94.0",
41
+ "@substrat-run/psl": "^0.2.4"
41
42
  },
42
43
  "devDependencies": {
43
44
  "@cloudflare/workers-types": "^4.20250109.0",