@substrat-run/vertical-auth 0.13.2 → 0.14.1

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.
@@ -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,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClG,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,oBAAoB,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,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOlG,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,kBAAkB,EAClB,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,oBAAoB,CAAC"}
package/dist/index.js CHANGED
@@ -4,5 +4,11 @@ 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 { invitePath, mintOwnerClaimLink, ownerClaimPath, sha256Hex } from './owner-claim-link.js';
7
+ // `mountInviteRoutes` is deliberately NOT re-exported here. It is the one module in this
8
+ // package that imports `hono` at runtime, and a barrel re-export would make every
9
+ // `import '@substrat-run/vertical-auth'` evaluate it — so a consumer that wants only an
10
+ // `AuthProvider` or the OIDC helpers would resolve a peer it never uses. It lives on the
11
+ // `@substrat-run/vertical-auth/invite-routes` subpath, beside `./provider` and `./oidc`,
12
+ // for the same reason those do.
7
13
  export { AUTH_CONFIG_KEY, AuthConfigError, authChoice, authorizationServersOf, instanceAuthFor, parseAuthChoice, selectAuthProvider, } from './instance-auth.js';
8
14
  //# 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,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClG,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,kBAAkB,GAGnB,MAAM,oBAAoB,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,UAAU,EAAE,kBAAkB,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAClG,yFAAyF;AACzF,kFAAkF;AAClF,wFAAwF;AACxF,yFAAyF;AACzF,yFAAyF;AACzF,gCAAgC;AAChC,OAAO,EACL,eAAe,EACf,eAAe,EACf,UAAU,EACV,sBAAsB,EACtB,eAAe,EACf,eAAe,EACf,kBAAkB,GAGnB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * The MEMBER INVITE routes a vertical mounts — the post-setup join path (#1150).
3
+ *
4
+ * Three demo workers carried these four routes verbatim: list the open invites, create
5
+ * one, revoke one, and accept one. The copies agreed byte-for-byte on the parts that
6
+ * matter — the token shape, that only its HASH is stored, that the role is granted BEFORE
7
+ * the invite is recorded, the status codes and the messages — and nothing but a diff held
8
+ * them in step. So the routes live here once, and a vertical supplies only what is its own:
9
+ * how a request resolves to a scope, who counts as an admin, which roles a teammate may be
10
+ * invited at, and the host that grants the role.
11
+ *
12
+ * What an invite IS does not change by moving here. Creating one pre-mints a member
13
+ * principal, grants it the chosen role at scope level (a real grant — the principal can
14
+ * act the moment somebody binds to it), and records the invite in the tenant's identity
15
+ * directory keyed by the token's SHA-256; the plaintext token rides only in the returned
16
+ * accept link. Accepting binds the invitee's verified subject to that pre-minted principal,
17
+ * and the directory then resolves them as that member. Revoking removes the invite row;
18
+ * the scope-level grant on a principal nobody was ever bound to is inert.
19
+ *
20
+ * Deliberately NOT here: the dashboard-side members view over an installed vertical's
21
+ * directory — that widens the platform's reach into a vertical's identity and is a
22
+ * separate decision — and the richer invite a support desk runs (contact-bound roles,
23
+ * staff profiles), which is a different flow rather than this one with more fields.
24
+ */
25
+ import type { Context, Hono } from 'hono';
26
+ import { z, type PrincipalId } from '@substrat-run/contracts';
27
+ import type { IdentityStub } from './identity-do.js';
28
+ import type { AuthProvider } from './provider.js';
29
+ /** The slice of the identity directory the invite routes touch. */
30
+ export type InviteDirectory = Pick<IdentityStub, 'listInvites' | 'createInvite' | 'revokeInvite' | 'claimInvite'>;
31
+ /** The body `POST /api/invites` takes. */
32
+ export declare const inviteBody: z.ZodObject<{
33
+ email: z.ZodOptional<z.ZodString>;
34
+ roleKey: z.ZodString;
35
+ }, z.core.$strip>;
36
+ /** The body `POST /api/accept-invite` takes. */
37
+ export declare const acceptInviteBody: z.ZodObject<{
38
+ token: z.ZodString;
39
+ }, z.core.$strip>;
40
+ /**
41
+ * What the vertical supplies. `E` is its worker's bindings; `N` is whatever it resolves a
42
+ * request to — the routes only read `scopeId` off it, and hand the whole node back to
43
+ * `directory`, so a vertical whose node carries more (a tenant, a site) loses nothing.
44
+ */
45
+ export interface InviteRouteDeps<E extends object, N extends {
46
+ scopeId: string;
47
+ }> {
48
+ /** The (tenant, scope) this request addresses — behind the router, from the assertion. */
49
+ nodeFor: (req: Request, env: E) => N | Promise<N>;
50
+ /**
51
+ * Gate the three admin routes: throw 401 for nobody, 403 for a caller who may not manage
52
+ * members. The vertical decides what "admin" means — a role, a permission, a whoami.
53
+ */
54
+ requireAdmin: (c: Context<{
55
+ Bindings: E;
56
+ }>) => Promise<unknown>;
57
+ /** The role keys a teammate may be invited at — the vertical's own ROLES. */
58
+ roles: readonly string[];
59
+ /** The tenant's identity directory — the invite rows and the sub → principal binding. */
60
+ directory: (env: E, node: N) => InviteDirectory;
61
+ /** Grant the pre-minted principal its role at scope level — the host's `assignScopeRole`. */
62
+ assignScopeRole: (env: E, scopeId: N['scopeId'], principal: PrincipalId, roleKey: string) => Promise<void>;
63
+ /**
64
+ * Take that grant back — the host's `revokeScopeRole`. The grant and the invite row live
65
+ * in two different Durable Objects, so the create has no transaction across them: when
66
+ * the row cannot be written after the role was granted, this is what puts the scope back
67
+ * where it was, rather than leaving a principal nobody can ever bind to holding a role.
68
+ */
69
+ revokeScopeRole: (env: E, scopeId: N['scopeId'], principal: PrincipalId, roleKey: string) => Promise<unknown>;
70
+ /** The configured `AuthProvider` — who is accepting. Resolved per request, as the vertical does. */
71
+ authProvider: (env: E, req: Request) => Promise<AuthProvider>;
72
+ /**
73
+ * The origin the accept link is built on. Defaults to the request's own. A trailing
74
+ * slash is tolerated — `mintOwnerClaimLink` strips one the same way — so a vertical that
75
+ * hands over a configured `https://host/` does not send invitees to `https://host//`.
76
+ */
77
+ origin?: (req: Request) => string;
78
+ }
79
+ /**
80
+ * Mount the four invite routes on a vertical's Hono app:
81
+ *
82
+ * GET /api/invites → { roles, invites } (admin)
83
+ * POST /api/invites → 201 { principal, roleKey, email, acceptUrl } (admin)
84
+ * POST /api/invites/:principal/revoke → 204 (admin)
85
+ * POST /api/accept-invite → { ok: true, principal } (any signed-in subject)
86
+ *
87
+ * Every error these routes raise themselves is an `HTTPException` — a body that is not
88
+ * JSON or does not fit its schema included, which `bodyOf` turns into a 400 rather than
89
+ * letting a `SyntaxError` or `ZodError` out — so the vertical's own `onError`, or the
90
+ * envelope `mountPlatformSurface` installs, renders them exactly as it renders its own,
91
+ * and needs no branch for this mount. What the vertical's OWN deps throw (`requireAdmin`,
92
+ * the directory, the host) is passed through untouched: those are its errors to shape.
93
+ */
94
+ export declare function mountInviteRoutes<E extends object, N extends {
95
+ scopeId: string;
96
+ }>(app: Hono<{
97
+ Bindings: E;
98
+ }>, deps: InviteRouteDeps<E, N>): void;
99
+ //# sourceMappingURL=invite-routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-routes.d.ts","sourceRoot":"","sources":["../src/invite-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,EAAe,CAAC,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,mEAAmE;AACnE,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,EAAE,aAAa,GAAG,cAAc,GAAG,cAAc,GAAG,aAAa,CAAC,CAAC;AAElH,0CAA0C;AAC1C,eAAO,MAAM,UAAU;;;iBAIrB,CAAC;AAEH,gDAAgD;AAChD,eAAO,MAAM,gBAAgB;;iBAAyC,CAAC;AAEvE;;;;GAIG;AACH,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE;IAC9E,0FAA0F;IAC1F,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAClD;;;OAGG;IACH,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC;QAAE,QAAQ,EAAE,CAAC,CAAA;KAAE,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAChE,6EAA6E;IAC7E,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,yFAAyF;IACzF,SAAS,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,eAAe,CAAC;IAChD,6FAA6F;IAC7F,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3G;;;;;OAKG;IACH,eAAe,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9G,oGAAoG;IACpG,YAAY,EAAE,CAAC,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;IAC9D;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;CACnC;AA2BD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EAC/E,GAAG,EAAE,IAAI,CAAC;IAAE,QAAQ,EAAE,CAAC,CAAA;CAAE,CAAC,EAC1B,IAAI,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,GAC1B,IAAI,CAkDN"}
@@ -0,0 +1,128 @@
1
+ /**
2
+ * The MEMBER INVITE routes a vertical mounts — the post-setup join path (#1150).
3
+ *
4
+ * Three demo workers carried these four routes verbatim: list the open invites, create
5
+ * one, revoke one, and accept one. The copies agreed byte-for-byte on the parts that
6
+ * matter — the token shape, that only its HASH is stored, that the role is granted BEFORE
7
+ * the invite is recorded, the status codes and the messages — and nothing but a diff held
8
+ * them in step. So the routes live here once, and a vertical supplies only what is its own:
9
+ * how a request resolves to a scope, who counts as an admin, which roles a teammate may be
10
+ * invited at, and the host that grants the role.
11
+ *
12
+ * What an invite IS does not change by moving here. Creating one pre-mints a member
13
+ * principal, grants it the chosen role at scope level (a real grant — the principal can
14
+ * act the moment somebody binds to it), and records the invite in the tenant's identity
15
+ * directory keyed by the token's SHA-256; the plaintext token rides only in the returned
16
+ * accept link. Accepting binds the invitee's verified subject to that pre-minted principal,
17
+ * and the directory then resolves them as that member. Revoking removes the invite row;
18
+ * the scope-level grant on a principal nobody was ever bound to is inert.
19
+ *
20
+ * Deliberately NOT here: the dashboard-side members view over an installed vertical's
21
+ * directory — that widens the platform's reach into a vertical's identity and is a
22
+ * separate decision — and the richer invite a support desk runs (contact-bound roles,
23
+ * staff profiles), which is a different flow rather than this one with more fields.
24
+ */
25
+ import { HTTPException } from 'hono/http-exception';
26
+ import { principalId, z } from '@substrat-run/contracts';
27
+ import { ulid } from '@substrat-run/kernel';
28
+ import { claimToken, invitePath, sha256Hex } from './owner-claim-link.js';
29
+ /** The body `POST /api/invites` takes. */
30
+ export const inviteBody = z.object({
31
+ email: z.string().email().optional(),
32
+ /** One of the vertical's roles — validated against `roles` below. */
33
+ roleKey: z.string().min(1),
34
+ });
35
+ /** The body `POST /api/accept-invite` takes. */
36
+ export const acceptInviteBody = z.object({ token: z.string().min(1) });
37
+ /**
38
+ * The request body, parsed against the route's schema — or a 400 that names what was
39
+ * wrong. Both failure shapes are turned into an `HTTPException` here so the promise
40
+ * `mountInviteRoutes` makes holds: a body that is not JSON would otherwise surface as the
41
+ * `SyntaxError` `c.req.json()` throws (a 500 under any `onError` that does not know it),
42
+ * and a body that does not fit the schema as a `ZodError` the vertical would have to map
43
+ * itself. The issue list is written into the message rather than a structured body
44
+ * because the vertical's own envelope decides the body shape, and a message is the one
45
+ * thing every envelope carries through.
46
+ */
47
+ async function bodyOf(c, schema) {
48
+ let raw;
49
+ try {
50
+ raw = await c.req.json();
51
+ }
52
+ catch {
53
+ throw new HTTPException(400, { message: 'the request body must be JSON' });
54
+ }
55
+ const parsed = schema.safeParse(raw);
56
+ if (!parsed.success) {
57
+ const issues = parsed.error.issues.map((i) => `${i.path.join('.') || 'body'}: ${i.message}`).join('; ');
58
+ throw new HTTPException(400, { message: `invalid request body — ${issues}` });
59
+ }
60
+ return parsed.data;
61
+ }
62
+ /**
63
+ * Mount the four invite routes on a vertical's Hono app:
64
+ *
65
+ * GET /api/invites → { roles, invites } (admin)
66
+ * POST /api/invites → 201 { principal, roleKey, email, acceptUrl } (admin)
67
+ * POST /api/invites/:principal/revoke → 204 (admin)
68
+ * POST /api/accept-invite → { ok: true, principal } (any signed-in subject)
69
+ *
70
+ * Every error these routes raise themselves is an `HTTPException` — a body that is not
71
+ * JSON or does not fit its schema included, which `bodyOf` turns into a 400 rather than
72
+ * letting a `SyntaxError` or `ZodError` out — so the vertical's own `onError`, or the
73
+ * envelope `mountPlatformSurface` installs, renders them exactly as it renders its own,
74
+ * and needs no branch for this mount. What the vertical's OWN deps throw (`requireAdmin`,
75
+ * the directory, the host) is passed through untouched: those are its errors to shape.
76
+ */
77
+ export function mountInviteRoutes(app, deps) {
78
+ const originOf = (req) => (deps.origin?.(req) ?? new URL(req.url).origin).replace(/\/$/, '');
79
+ app.get('/api/invites', async (c) => {
80
+ const node = await deps.nodeFor(c.req.raw, c.env);
81
+ await deps.requireAdmin(c);
82
+ return c.json({ roles: [...deps.roles], invites: await deps.directory(c.env, node).listInvites(node.scopeId) });
83
+ });
84
+ app.post('/api/invites', async (c) => {
85
+ const node = await deps.nodeFor(c.req.raw, c.env);
86
+ await deps.requireAdmin(c);
87
+ const { email, roleKey } = await bodyOf(c, inviteBody);
88
+ if (!deps.roles.includes(roleKey))
89
+ throw new HTTPException(400, { message: `unknown role '${roleKey}'` });
90
+ const principal = principalId.parse(ulid());
91
+ // A long, URL-safe token; only its hash is stored. Two UUIDs = 256 bits of entropy.
92
+ const token = claimToken();
93
+ // The grant first: an invite row whose principal holds nothing is a link that binds a
94
+ // teammate to no access, whereas a grant with no row is inert — nobody can bind to it.
95
+ await deps.assignScopeRole(c.env, node.scopeId, principal, roleKey);
96
+ try {
97
+ await deps.directory(c.env, node).createInvite(node.scopeId, principal, roleKey, email ?? null, await sha256Hex(token));
98
+ }
99
+ catch (err) {
100
+ // Two Durable Objects, no transaction between them. Inert is not the same as
101
+ // harmless: every retry of a failing create would mint another principal with a
102
+ // role and no row, so the grant is taken back before the failure is reported. If
103
+ // the revoke fails too, the ORIGINAL failure is what the caller hears — it is the
104
+ // one that explains the request — and the orphan is the state this comment names.
105
+ await deps.revokeScopeRole(c.env, node.scopeId, principal, roleKey).catch(() => undefined);
106
+ throw err;
107
+ }
108
+ return c.json({ principal, roleKey, email: email ?? null, acceptUrl: `${originOf(c.req.raw)}${invitePath(token)}` }, 201);
109
+ });
110
+ app.post('/api/invites/:principal/revoke', async (c) => {
111
+ const node = await deps.nodeFor(c.req.raw, c.env);
112
+ await deps.requireAdmin(c);
113
+ await deps.directory(c.env, node).revokeInvite(node.scopeId, c.req.param('principal'));
114
+ return c.body(null, 204);
115
+ });
116
+ app.post('/api/accept-invite', async (c) => {
117
+ const node = await deps.nodeFor(c.req.raw, c.env);
118
+ const subject = await (await deps.authProvider(c.env, c.req.raw)).resolve(c.req.raw.headers);
119
+ if (!subject)
120
+ throw new HTTPException(401, { message: 'sign in before accepting an invite' });
121
+ const { token } = await bodyOf(c, acceptInviteBody);
122
+ const principal = await deps.directory(c.env, node).claimInvite(node.scopeId, subject.sub, await sha256Hex(token));
123
+ if (!principal)
124
+ throw new HTTPException(400, { message: 'this invite is invalid or already used' });
125
+ return c.json({ ok: true, principal });
126
+ });
127
+ }
128
+ //# sourceMappingURL=invite-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-routes.js","sourceRoot":"","sources":["../src/invite-routes.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.13.2",
3
+ "version": "0.14.1",
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": {
@@ -31,6 +31,10 @@
31
31
  "./oidc-rp-provider": {
32
32
  "types": "./dist/oidc-rp-provider.d.ts",
33
33
  "default": "./dist/oidc-rp-provider.js"
34
+ },
35
+ "./invite-routes": {
36
+ "types": "./dist/invite-routes.d.ts",
37
+ "default": "./dist/invite-routes.js"
34
38
  }
35
39
  },
36
40
  "files": [
@@ -40,14 +44,19 @@
40
44
  "better-auth": "^1.7.1",
41
45
  "drizzle-orm": "^0.45.2",
42
46
  "jose": "^6.2.3",
43
- "@substrat-run/contracts": "^0.110.0",
44
- "@substrat-run/psl": "^0.2.4",
45
- "@substrat-run/oidc-rp": "^0.9.0"
47
+ "@substrat-run/contracts": "^0.112.0",
48
+ "@substrat-run/oidc-rp": "^0.9.0",
49
+ "@substrat-run/kernel": "^0.112.0",
50
+ "@substrat-run/psl": "^0.2.5"
51
+ },
52
+ "peerDependencies": {
53
+ "hono": "^4.6.0"
46
54
  },
47
55
  "devDependencies": {
48
56
  "@cloudflare/workers-types": "^4.20250109.0",
49
57
  "@types/better-sqlite3": "^9.6.0",
50
58
  "better-sqlite3": "^13.0.3",
59
+ "hono": "^4.6.0",
51
60
  "typescript": "^7.0.0",
52
61
  "vitest": "^3.2.7"
53
62
  },