@voltro/protocol 0.67.0 → 0.69.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/rest.js CHANGED
@@ -1,4 +1,4 @@
1
- import { F as e, P as t } from "./scopes-C86BDyNJ.js";
1
+ import { F as e, P as t } from "./scopes-DVtiKKsm.js";
2
2
  import { c as n, l as r, o as i, s as a, t as o } from "./serverErrorBus-BTnTpMqj.js";
3
3
  import { Effect as s, Schema as c } from "effect";
4
4
  //#region src/publicApi.ts
@@ -88,14 +88,14 @@ var i = n.Record({
88
88
  },
89
89
  removed: i
90
90
  };
91
- }, T = 3e4, re = 1e4, E = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ie = () => {
91
+ }, re = 3e4, ie = 1e4, T = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ae = () => {
92
92
  if (typeof process > "u") return;
93
93
  let e = process.env.VOLTRO_AUTH_SCOPE_CACHE_TTL_MS;
94
94
  if (e === void 0 || e === "") return;
95
95
  let t = Number(e);
96
96
  return Number.isFinite(t) && t >= 0 ? t : void 0;
97
- }, D = (e = {}) => {
98
- let t = e.ttlMs ?? ie() ?? 3e4, n = e.maxEntries ?? 1e4, r = e.now ?? Date.now, i = /* @__PURE__ */ new Map(), a = () => {
97
+ }, E = (e = {}) => {
98
+ let t = e.ttlMs ?? ae() ?? 3e4, n = e.maxEntries ?? 1e4, r = e.now ?? Date.now, i = /* @__PURE__ */ new Map(), a = () => {
99
99
  if (i.size <= n) return;
100
100
  let e = r();
101
101
  for (let [t, n] of i) n.freshUntil <= e && i.delete(t);
@@ -131,14 +131,24 @@ var i = n.Record({
131
131
  };
132
132
  }
133
133
  };
134
- }, ae = (e) => typeof e.resolve == "function", O = (e, t) => {
135
- let n = t?.resolveScopes, r = t?.subjectGuards ?? [], i = n !== void 0 || r.length > 0, a = !i || t?.scopeCache === !1 ? null : t?.scopeCache !== void 0 && ae(t.scopeCache) ? t.scopeCache : D(t?.scopeCache ?? {});
134
+ }, oe = (e) => typeof e.resolve == "function", se = (e) => {
135
+ let t = e.authorization ?? e.Authorization;
136
+ if (t !== void 0) return /^Bearer\s+(.+)$/i.exec(t.trim())?.[1]?.trim();
137
+ }, D = (e, t) => {
138
+ let n = se(t);
139
+ if (n === void 0) return e;
140
+ let r = e.filter((e) => e.claimsBearerPrefix !== void 0 && e.claimsBearerPrefix !== "" && n.startsWith(e.claimsBearerPrefix));
141
+ if (r.length === 0) return e;
142
+ let i = new Set(r);
143
+ return [...r, ...e.filter((e) => !i.has(e))];
144
+ }, O = (e, t) => {
145
+ let n = t?.resolveScopes, r = t?.subjectGuards ?? [], i = n !== void 0 || r.length > 0, a = !i || t?.scopeCache === !1 ? null : t?.scopeCache !== void 0 && oe(t.scopeCache) ? t.scopeCache : E(t?.scopeCache ?? {});
136
146
  return async (o) => {
137
147
  let s = t?.getStore?.(), c = s === void 0 ? o : {
138
148
  ...o,
139
149
  store: s
140
150
  }, l;
141
- for (let o of e) {
151
+ for (let o of D(e, c.headers)) {
142
152
  let e = await o.resolve(c);
143
153
  if (e.kind === "matched") {
144
154
  let s = e.subject;
@@ -167,7 +177,7 @@ var i = n.Record({
167
177
  }, { decision: l, fresh: u } = a === null ? {
168
178
  decision: await i(),
169
179
  fresh: !0
170
- } : await a.resolve(E(e.subject), i);
180
+ } : await a.resolve(T(e.subject), i);
171
181
  if (l.kind === "vetoed") {
172
182
  let e = `${l.code}: ${l.message}`;
173
183
  throw t?.onStrategyFailed?.({
@@ -235,9 +245,9 @@ var i = n.Record({
235
245
  }, H = (e, n) => B(e, n) ? t.void : t.fail(new F({
236
246
  required: n,
237
247
  message: `missing required scope '${n}'`
238
- })), U = (e) => typeof e.action == "string" && typeof e.resourceType == "string", W = (e) => typeof e.open == "string", G = (e) => e.authenticated === !0, K = (e) => ({ open: e }), q = (e) => typeof e == "string" ? [e] : e, J, oe = (e) => {
248
+ })), U = (e) => typeof e.action == "string" && typeof e.resourceType == "string", W = (e) => typeof e.open == "string", G = (e) => e.authenticated === !0, K = (e) => ({ open: e }), q = (e) => typeof e == "string" ? [e] : e, J, ce = (e) => {
239
249
  J = e;
240
- }, se = (e) => J === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !U(e) && e.resource !== void 0)).map((e) => e.tag) : [], ce = (e) => [
250
+ }, le = (e) => J === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !U(e) && e.resource !== void 0)).map((e) => e.tag) : [], ue = (e) => [
241
251
  `${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
242
252
  ...e.slice(0, 10).map((e) => ` ${e}`),
243
253
  ...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
@@ -251,9 +261,9 @@ var i = n.Record({
251
261
  " • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
252
262
  " subject hold `req.scope` on `req.resource`\" from your own tables.",
253
263
  " • Drop the `resource` extractor if a global scope check is what you meant."
254
- ].join("\n"), le = () => J, Y, X = (e) => {
264
+ ].join("\n"), de = () => J, Y, fe = (e) => {
255
265
  Y = e;
256
- }, ue = () => Y, Z = (e) => new F({
266
+ }, X = () => Y, Z = (e) => new F({
257
267
  required: "access-decision",
258
268
  message: `${e ?? "this procedure"} declares no access decision: it has neither \`guards:\` nor \`openAccess:\`, and the app runs with \`security.defaultDeny\`. Add the scope(s) a caller must hold (\`guards: [{ scope: '…' }]\`), or declare it open on purpose with \`openAccess: '<why anyone may call this>'\`.`
259
269
  }), Q = (e, t) => {
@@ -289,7 +299,7 @@ var i = n.Record({
289
299
  }
290
300
  }
291
301
  return null;
292
- }, de = (e, n, r) => {
302
+ }, pe = (e, n, r) => {
293
303
  let i = (e) => new F({
294
304
  required: `${n.resourceType}:${n.action}`,
295
305
  message: e
@@ -304,7 +314,7 @@ var i = n.Record({
304
314
  resourceType: n.resourceType,
305
315
  resourceId: o
306
316
  })).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((e) => e ? null : i(`no '${n.action}' relation on ${n.resourceType}:${o}`)));
307
- }, fe = (e, n, r, i) => {
317
+ }, me = (e, n, r, i) => {
308
318
  if (!n || n.length === 0) return t.succeed($(e, n, i));
309
319
  let a = J;
310
320
  return !n.some(U) && (!a || !n.some((e) => e.resource !== void 0)) ? t.succeed($(e, n, i)) : t.gen(function* () {
@@ -318,7 +328,7 @@ var i = n.Record({
318
328
  }));
319
329
  }
320
330
  if (U(i)) {
321
- let t = yield* de(e, i, r);
331
+ let t = yield* pe(e, i, r);
322
332
  if (t) return t;
323
333
  continue;
324
334
  }
@@ -352,4 +362,4 @@ var i = n.Record({
352
362
  });
353
363
  };
354
364
  //#endregion
355
- export { _ as A, g as B, oe as C, S as D, b as E, h as F, ee as G, v as H, w as I, te as K, A as L, f as M, y as N, re as O, k as P, O as R, X as S, x as T, E as U, D as V, p as W, U as _, F as a, H as b, fe as c, ue as d, le as f, W as g, G as h, M as i, d as j, T as k, z as l, V as m, N as n, ce as o, B as p, P as r, $ as s, j as t, se as u, Z as v, I as w, R as x, K as y, ne as z };
365
+ export { _ as A, g as B, ce as C, S as D, b as E, h as F, p as G, D as H, w as I, ee as K, A as L, f as M, y as N, ie as O, k as P, O as R, fe as S, x as T, v as U, E as V, T as W, U as _, F as a, H as b, me as c, X as d, de as f, W as g, G as h, M as i, d as j, re as k, z as l, V as m, N as n, ue as o, B as p, te as q, P as r, $ as s, j as t, le as u, Z as v, I as w, R as x, K as y, ne as z };
package/dist/session.js CHANGED
@@ -1,11 +1,11 @@
1
- import { M as e, W as t, w as n } from "./scopes-C86BDyNJ.js";
1
+ import { G as e, M as t, w as n } from "./scopes-DVtiKKsm.js";
2
2
  import { Schema as r } from "effect";
3
3
  import { createHmac as i, timingSafeEqual as a } from "node:crypto";
4
4
  import { createLogger as o } from "@voltro/logger";
5
5
  //#region src/session.ts
6
6
  var s = o({ scope: "@voltro/protocol:session" }), c = 2, l = r.Struct({
7
7
  v: r.Literal(2),
8
- subject: e,
8
+ subject: t,
9
9
  exp: r.Number,
10
10
  iat: r.Number,
11
11
  kid: r.optional(r.String)
@@ -38,14 +38,14 @@ var s = o({ scope: "@voltro/protocol:session" }), c = 2, l = r.Struct({
38
38
  }, C = 604800, w = .7, T = (e, t) => x(i("sha256", t).update(e).digest()), E = (e) => typeof e == "string" ? {
39
39
  kid: "k0",
40
40
  secret: e
41
- } : e, D = (e, r, i = {}) => {
41
+ } : e, D = (t, r, i = {}) => {
42
42
  let a = E(r);
43
43
  if (!a.secret) throw Error("signSession: secret must be a non-empty string");
44
- let o = n(e);
45
- if (o.length > 0) throw Error(`signSession: refusing to mint a session cookie for a ${e.type} subject carrying ${o.length} scope(s) (${o.slice(0, 5).join(", ")}). A session cookie carries IDENTITY only — authority is resolved per request, so that removing a role takes effect on the session that already exists instead of in up to 7 days. Mint the session from the identity and move the scopes into the auth.resolveScopes resolver, which runs on every request and can be invalidated the moment a role changes.`);
44
+ let o = n(t);
45
+ if (o.length > 0) throw Error(`signSession: refusing to mint a session cookie for a ${t.type} subject carrying ${o.length} scope(s) (${o.slice(0, 5).join(", ")}). A session cookie carries IDENTITY only — authority is resolved per request, so that removing a role takes effect on the session that already exists instead of in up to 7 days. Mint the session from the identity and move the scopes into the auth.resolveScopes resolver, which runs on every request and can be invalidated the moment a role changes.`);
46
46
  let s = i.ttlSeconds ?? C, c = Math.floor((i.now ?? Date.now)() / 1e3), l = {
47
47
  v: 2,
48
- subject: t(e),
48
+ subject: e(t),
49
49
  exp: c + s,
50
50
  iat: c,
51
51
  ...typeof r == "string" ? {} : { kid: a.kid }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/protocol",
3
- "version": "0.67.0",
3
+ "version": "0.69.0",
4
4
  "description": "The Voltro wire + plugin contract — defineQuery/Mutation/Action/Stream, definePlugin, sessions / JWT / API-keys, and the RPC protocol.",
5
5
  "keywords": [
6
6
  "voltro",
@@ -59,8 +59,8 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@effect/sql": "^0.52.1",
62
- "@voltro/database": "0.67.0",
63
- "@voltro/logger": "0.67.0",
62
+ "@voltro/database": "0.69.0",
63
+ "@voltro/logger": "0.69.0",
64
64
  "jose": "^6.2.10"
65
65
  },
66
66
  "peerDependencies": {