@voltro/plugin-auth 0.5.0 → 0.7.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/plugin.d.ts CHANGED
@@ -7,9 +7,21 @@ import { VoltroPlugin } from '@voltro/protocol';
7
7
  import { YieldableError } from 'effect/Cause';
8
8
 
9
9
  declare interface AuthConfig {
10
- readonly secret: string;
10
+ /**
11
+ * The session-signing key. OMIT IT and the value is read from
12
+ * `VOLTRO_SESSION_SECRET` when a request is actually handled.
13
+ *
14
+ * Omitting is the better default: `app.config.ts` is evaluated before the
15
+ * environment gate runs (and before `voltro dev` mints a project-local
16
+ * secret), so reading `process.env` here to pass a value is precisely what
17
+ * pushes apps into shipping a hardcoded fallback. Deferring the read means
18
+ * there is nothing to fall back TO.
19
+ *
20
+ * Pass one explicitly only when the key does not come from the environment.
21
+ */
22
+ readonly secret?: string;
11
23
  /** Explicit keyed secret set for zero-downtime rotation. When absent,
12
- * the set is derived from `secret` (current) + the
24
+ * the set is derived from `secret` (or `VOLTRO_SESSION_SECRET`) plus the
13
25
  * `VOLTRO_SESSION_SECRET_PREVIOUS` / `VOLTRO_SESSION_KID*` env vars —
14
26
  * so env-var rotation works without setting this. Cookies are always
15
27
  * SIGNED with the current key; verification also accepts `previous`. */
@@ -191,10 +203,32 @@ declare interface SessionRevocationOptions {
191
203
  * framework never reads it, but app code + the switch-tenant menu do).
192
204
  * Pass an explicit `tenantId` to make the ACTIVE tenant differ from the
193
205
  * user's home tenant (post switch-tenant rebind).
206
+ *
207
+ * `metadata` carries anything else the app needs on the Subject — most
208
+ * often a provider credential captured at login and read back by a
209
+ * plugin's `credentialsResolver` (`subject.metadata.jiraToken` for
210
+ * `@voltro/plugin-atlassian`, say). Without it an app that needs such a
211
+ * credential could not adopt this helper at all: building the Subject by
212
+ * hand was the only way to keep the value.
213
+ *
214
+ * **Precedence, when a `memberships` key appears in BOTH:** the dedicated
215
+ * `memberships` option wins. It is the specific, typed input and it is
216
+ * projected to the `{ tenantId, role }` shape `subjectMemberships` reads,
217
+ * so letting a free-form bag silently shadow it would break the
218
+ * switch-tenant menu in a way nothing type-checks. A `memberships` key
219
+ * inside `metadata` is passed through UNCHANGED when the option is absent
220
+ * — no reshaping, no validation.
221
+ *
222
+ * Note this only stamps the metadata slot at CONSTRUCTION. The sign-in /
223
+ * sign-up / magic-link / passkey handlers later merge `sessionId` (and
224
+ * the password strategy merges `provider`) onto whatever is here, so keys
225
+ * set through this option survive those paths — unless you name a key
226
+ * `sessionId` or `provider`, which those merges overwrite by design.
194
227
  */
195
228
  declare const subjectFromUser: (user: UserRecord, options?: {
196
229
  readonly tenantId?: string;
197
230
  readonly memberships?: ReadonlyArray<MembershipRecord>;
231
+ readonly metadata?: Record<string, unknown>;
198
232
  }) => Subject;
199
233
 
200
234
  /**
package/dist/plugin.js CHANGED
@@ -1,4 +1,4 @@
1
1
  import "./session.js";
2
- import { n as e, t } from "./plugin-CRt-kdEA.js";
2
+ import { n as e, t } from "./plugin-CQ_NyxPr.js";
3
3
  import "./csrf.js";
4
4
  export { t as authRoutesPlugin, e as getAuthSessionStrategy };
package/dist/session.d.ts CHANGED
@@ -81,6 +81,4 @@ export declare const sessionSecretsOf: (secret: SessionSecretInput) => SessionSe
81
81
 
82
82
  export { VerifyResult }
83
83
 
84
- export declare const VOLTRO_DEV_SESSION_SECRET: "voltro-dev-session-secret-32b-DO-NOT-USE-IN-PROD";
85
-
86
84
  export { }
package/dist/session.js CHANGED
@@ -1,20 +1,20 @@
1
- import { DEFAULT_SESSION_KID as e, VOLTRO_DEV_SESSION_SECRET as t, buildSetCookie as n, readCookie as r, resolveSessionSecret as i, resolveSessionSecrets as a, signSession as o, timingSafeStringEqual as s, verifySessionKeyed as c } from "@voltro/protocol/session";
1
+ import { DEFAULT_SESSION_KID as e, buildSetCookie as t, readCookie as n, resolveOptionalSessionSecrets as r, resolveSessionSecret as i, resolveSessionSecrets as a, signSession as o, timingSafeStringEqual as s, verifySessionKeyed as c } from "@voltro/protocol/session";
2
2
  //#region src/session.ts
3
- var l = "voltro:session", u = 3600 * 24 * 7, d = t, f = i, p = a, m = (e) => typeof e == "string" ? e : e.current, h = (t) => {
3
+ var l = "voltro:session", u = 3600 * 24 * 7, d = i, f = a, p = (e) => typeof e == "string" ? e : e.current, m = (t) => {
4
4
  if (typeof t != "string") return t;
5
- let n = a(), r = {
6
- kid: s(n.current.secret, t) ? n.current.kid : e,
5
+ let n = r(), i = {
6
+ kid: n && s(n.current.secret, t) ? n.current.kid : e,
7
7
  secret: t
8
8
  };
9
- return n.previous ? {
10
- current: r,
9
+ return n?.previous ? {
10
+ current: i,
11
11
  previous: n.previous
12
- } : { current: r };
13
- }, g = (e, t, r = {}) => {
14
- let i = r.ttlSeconds ?? u, a = o(e, m(t), { ttlSeconds: i });
12
+ } : { current: i };
13
+ }, h = (e, n, r = {}) => {
14
+ let i = r.ttlSeconds ?? u, a = o(e, p(n), { ttlSeconds: i });
15
15
  return {
16
16
  value: a,
17
- setCookie: n(l, a, {
17
+ setCookie: t(l, a, {
18
18
  maxAgeSeconds: i,
19
19
  httpOnly: !0,
20
20
  sameSite: "lax",
@@ -23,10 +23,10 @@ var l = "voltro:session", u = 3600 * 24 * 7, d = t, f = i, p = a, m = (e) => typ
23
23
  path: "/"
24
24
  })
25
25
  };
26
- }, _ = (e, t) => v(e, t)?.subject ?? null, v = (e, t, n = {}) => {
27
- let i = r(e, l);
28
- return i ? c(i, h(t), n) : null;
29
- }, y = (e = {}) => n(l, "", {
26
+ }, g = (e, t) => _(e, t)?.subject ?? null, _ = (e, t, r = {}) => {
27
+ let i = n(e, l);
28
+ return i ? c(i, m(t), r) : null;
29
+ }, v = (e = {}) => t(l, "", {
30
30
  maxAgeSeconds: 0,
31
31
  httpOnly: !0,
32
32
  sameSite: "lax",
@@ -35,4 +35,4 @@ var l = "voltro:session", u = 3600 * 24 * 7, d = t, f = i, p = a, m = (e) => typ
35
35
  path: "/"
36
36
  });
37
37
  //#endregion
38
- export { l as SESSION_COOKIE_NAME, d as VOLTRO_DEV_SESSION_SECRET, y as clearSessionCookie, g as issueSession, _ as readSession, v as readSessionKeyed, f as resolveSessionSecret, p as resolveSessionSecrets, h as sessionSecretsOf };
38
+ export { l as SESSION_COOKIE_NAME, v as clearSessionCookie, h as issueSession, g as readSession, _ as readSessionKeyed, d as resolveSessionSecret, f as resolveSessionSecrets, m as sessionSecretsOf };
@@ -175,15 +175,18 @@ var s = 3e4, c = 1e4, l = (e, t = {}) => {
175
175
  }, !0);
176
176
  })
177
177
  };
178
- }, m = (e, t = {}) => ({
179
- type: "user",
180
- id: e.id,
181
- tenantId: t.tenantId ?? e.tenantId,
182
- ...t.memberships ? { metadata: { memberships: t.memberships.map((e) => ({
178
+ }, m = (e, t = {}) => {
179
+ let n = { ...t.metadata };
180
+ return t.memberships && (n.memberships = t.memberships.map((e) => ({
183
181
  tenantId: e.tenantId,
184
182
  role: e.role
185
- })) } } : {}
186
- }), h = (e) => {
183
+ }))), {
184
+ type: "user",
185
+ id: e.id,
186
+ tenantId: t.tenantId ?? e.tenantId,
187
+ ...Object.keys(n).length > 0 ? { metadata: n } : {}
188
+ };
189
+ }, h = (e) => {
187
190
  if (e.type !== "user") return null;
188
191
  let t = e.metadata?.sessionId;
189
192
  return typeof t == "string" && t.length > 0 ? t : null;
package/dist/strategy.js CHANGED
@@ -1,3 +1,3 @@
1
1
  import "./session.js";
2
- import { t as e } from "./strategy-CQ2YCIcr.js";
2
+ import { t as e } from "./strategy-D345j4df.js";
3
3
  export { e as voltroPasswordStrategy };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/plugin-auth",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "description": "Authentication primitives: password hashing, session creation, schema mixin + tables. Pairs with the `auth` app template for the UI; both independently usable. Server-side only (uses node:crypto).",
5
5
  "keywords": [
6
6
  "voltro",
@@ -78,8 +78,8 @@
78
78
  },
79
79
  "dependencies": {
80
80
  "@effect/sql": "^0.51.1",
81
- "@voltro/database": "0.5.0",
82
- "@voltro/protocol": "0.5.0"
81
+ "@voltro/database": "0.7.0",
82
+ "@voltro/protocol": "0.7.0"
83
83
  },
84
84
  "peerDependencies": {
85
85
  "effect": "^3.21.4",