@voltro/protocol 0.74.0 → 0.76.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 { I as e, L as t } from "./scopes-Dj7KCJab.js";
1
+ import { I as e, L as t } from "./scopes-D2dnEr4U.js";
2
2
  import { C as n, S as r, T as i, _ as a, a as o, c as s, d as c, f as l, i as u, l as d, n as f, o as p, r as m, s as h, t as g, u as _, v, w as y } from "./restFormat-ChSVyufA.js";
3
3
  import { Effect as b, ParseResult as x, Schema as S } from "effect";
4
4
  import * as C from "effect/SchemaAST";
@@ -63,7 +63,7 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
63
63
  tenantId: n.Null,
64
64
  scopes: c,
65
65
  metadata: n.optional(s)
66
- }), ee = n.Union(l, u, d, f, p), m = n.Union(l.omit("scopes"), u.omit("scopes"), d.omit("scopes"), f, p.omit("scopes")), h = (e) => {
66
+ }), m = n.Union(l, u, d, f, p), h = n.Union(l.omit("scopes"), u.omit("scopes"), d.omit("scopes"), f, p.omit("scopes")), ee = (e) => {
67
67
  if (e.type === "anonymous") return e;
68
68
  let { scopes: t, ...n } = e;
69
69
  return n;
@@ -72,32 +72,35 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
72
72
  id: null,
73
73
  tenantId: e,
74
74
  ...t === void 0 ? {} : { credentialRejected: t }
75
- }), te = (e, t = ["admin:full"]) => ({
75
+ }), v = (e, t = ["admin:full"]) => ({
76
76
  type: "system",
77
77
  id: e,
78
78
  tenantId: null,
79
79
  scopes: t
80
- }), v = (e) => {
80
+ }), y = (e) => {
81
81
  if (e.type === "system") return null;
82
82
  if (e.type === "serviceAccount" && e.auditActorId !== void 0) return e.auditActorId;
83
83
  if (e.type !== "apiKey") return e.id;
84
84
  let t = e.metadata?.userId;
85
85
  return typeof t == "string" && t !== "" ? t : e.id;
86
- }, ne = (e, t) => {
86
+ }, te = (e, t) => {
87
87
  let n = e;
88
88
  return {
89
89
  type: "serviceAccount",
90
90
  id: e.id ?? "system",
91
91
  tenantId: t,
92
- auditActorId: v(e),
92
+ auditActorId: y(e),
93
93
  scopes: g(e),
94
94
  ...n.metadata === void 0 ? {} : { metadata: n.metadata }
95
95
  };
96
- }, re = (e) => e.type === "system", ie = "impersonation", ae = (e) => e.metadata?.impersonation ?? null, y = class extends e.Tag("@voltro/Subject")() {}, b = class extends e.Tag("@voltro/ConnectionInfo")() {}, oe = class extends r.Tag()("@voltro/AuthMiddleware", { provides: y }) {}, x = class extends r.Tag()("@voltro/ConnectionInfoMiddleware", { provides: b }) {}, S = (e) => typeof e.mountRoutes == "function", se = (e) => Array.isArray(e) ? {
96
+ }, ne = (e) => e.type === "system", b = "impersonation", x = (e) => e.metadata?.impersonation ?? null, S = class extends e.Tag("@voltro/Subject")() {}, C = class extends e.Tag("@voltro/ConnectionInfo")() {}, w = class extends n.TaggedError()("Unauthenticated", { reason: n.optional(n.String) }) {}, T = class extends r.Tag()("@voltro/AuthMiddleware", {
97
+ provides: S,
98
+ failure: w
99
+ }) {}, re = class extends r.Tag()("@voltro/ConnectionInfoMiddleware", { provides: C }) {}, ie = (e) => typeof e.mountRoutes == "function", ae = (e) => Array.isArray(e) ? {
97
100
  kind: "grant",
98
101
  scopes: e
99
- } : e, C = (e, t) => {
100
- if (t.kind === "vetoed") throw new A({ reason: `${t.code}: ${t.message}` });
102
+ } : e, E = (e, t) => {
103
+ if (t.kind === "vetoed") throw new w({ reason: `${t.code}: ${t.message}` });
101
104
  if (e.type === "anonymous") return {
102
105
  subject: e,
103
106
  removed: []
@@ -125,13 +128,13 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
125
128
  },
126
129
  removed: i
127
130
  };
128
- }, w = 3e4, T = 1e4, E = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ce = () => {
131
+ }, oe = 3e4, se = 1e4, D = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ce = () => {
129
132
  if (typeof process > "u") return;
130
133
  let e = process.env.VOLTRO_AUTH_SCOPE_CACHE_TTL_MS;
131
134
  if (e === void 0 || e === "") return;
132
135
  let t = Number(e);
133
136
  return Number.isFinite(t) && t >= 0 ? t : void 0;
134
- }, D = (e = {}) => {
137
+ }, O = (e = {}) => {
135
138
  let t = e.ttlMs ?? ce() ?? 3e4, n = e.maxEntries ?? 1e4, r = e.now ?? Date.now, i = /* @__PURE__ */ new Map(), a = () => {
136
139
  if (i.size <= n) return;
137
140
  let e = r();
@@ -200,40 +203,40 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
200
203
  }
201
204
  return e;
202
205
  }
203
- }, O = (e, t) => {
206
+ }, k = (e, t) => {
204
207
  let n = ue(t);
205
208
  if (n === void 0) return e;
206
209
  let r = e.filter((e) => e.claimsBearerPrefix !== void 0 && e.claimsBearerPrefix !== "" && n.startsWith(e.claimsBearerPrefix));
207
210
  if (r.length === 0) return e;
208
211
  let i = new Set(r);
209
212
  return [...r, ...e.filter((e) => !i.has(e))];
210
- }, k = (e, t) => {
213
+ }, A = (e, t) => {
211
214
  let n = t?.resolveScopes, r = t?.subjectGuards ?? [];
212
215
  if (t?.memberships === void 0 != (t?.tenantSelection === void 0)) throw Error("composeAuthStrategies: `memberships` and `tenantSelection` come together — a tenant selection is verified against the memberships and read from the store; configure both or neither.");
213
216
  let i = t?.memberships !== void 0 && t.tenantSelection !== void 0 ? {
214
217
  memberships: t.memberships,
215
218
  store: t.tenantSelection
216
- } : void 0, a = n !== void 0 || r.length > 0, o = !a || t?.scopeCache === !1 ? null : t?.scopeCache !== void 0 && le(t.scopeCache) ? t.scopeCache : D(t?.scopeCache ?? {});
219
+ } : void 0, a = n !== void 0 || r.length > 0, o = !a || t?.scopeCache === !1 ? null : t?.scopeCache !== void 0 && le(t.scopeCache) ? t.scopeCache : O(t?.scopeCache ?? {});
217
220
  return async (s) => {
218
221
  let c = t?.getStore?.(), l = c === void 0 ? s : {
219
222
  ...s,
220
223
  store: c
221
224
  }, u;
222
- for (let s of O(e, l.headers)) {
225
+ for (let s of k(e, l.headers)) {
223
226
  let e = await s.resolve(l);
224
227
  if (e.kind === "matched") {
225
228
  let c = i === void 0 ? e.subject : await de(e.subject, l, i, (e) => (t?.onStrategyFailed?.({
226
229
  strategyId: s.id,
227
230
  reason: e
228
- }), new A({ reason: e }))), u = c;
231
+ }), new w({ reason: e }))), u = c;
229
232
  if (a) {
230
233
  let e = async () => {
231
234
  let e = n === void 0 ? {
232
235
  kind: "grant",
233
236
  scopes: []
234
- } : se(await n(c, l));
237
+ } : ae(await n(c, l));
235
238
  if (e.kind === "unavailable" || r.length === 0) return e;
236
- let t = C(c, e).subject, i = {
239
+ let t = E(c, e).subject, i = {
237
240
  origin: "request",
238
241
  headers: l.headers,
239
242
  clientId: l.clientId,
@@ -251,22 +254,22 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
251
254
  }, { decision: i, fresh: a } = o === null ? {
252
255
  decision: await e(),
253
256
  fresh: !0
254
- } : await o.resolve(E(c), e);
257
+ } : await o.resolve(D(c), e);
255
258
  if (i.kind === "vetoed") {
256
259
  let e = `${i.code}: ${i.message}`;
257
260
  throw t?.onStrategyFailed?.({
258
261
  strategyId: s.id,
259
262
  reason: e
260
- }), new A({ reason: e });
263
+ }), new w({ reason: e });
261
264
  }
262
265
  if (i.kind === "unavailable") {
263
266
  let e = `scope resolution unavailable: ${i.reason}`;
264
267
  throw t?.onStrategyFailed?.({
265
268
  strategyId: s.id,
266
269
  reason: e
267
- }), new A({ reason: e });
270
+ }), new w({ reason: e });
268
271
  }
269
- let d = C(c, i);
272
+ let d = E(c, i);
270
273
  a && d.removed.length > 0 && t?.onScopesNarrowed?.({
271
274
  strategyId: s.id,
272
275
  subjectType: c.type,
@@ -295,14 +298,14 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
295
298
  credentialRejected: u
296
299
  } : e };
297
300
  }
298
- if (u !== void 0) throw new A({ reason: `credential rejected: ${u}` });
301
+ if (u !== void 0) throw new w({ reason: `credential rejected: ${u}` });
299
302
  if (t?.anonymousTenantId !== void 0) return { subject: _(t.anonymousTenantId) };
300
303
  let d = l.headers["x-tenant"] ?? null;
301
- if (d === null && t?.anonymousTenantRequired === !0) throw new A({ reason: "tenant required (x-tenant header missing)" });
304
+ if (d === null && t?.anonymousTenantRequired === !0) throw new w({ reason: "tenant required (x-tenant header missing)" });
302
305
  return { subject: _(d) };
303
306
  };
304
- }, A = class extends n.TaggedError()("Unauthenticated", { reason: n.optional(n.String) }) {}, j = (e, t) => {
305
- if (e.type === "anonymous") throw new A(t === void 0 ? {} : { reason: t });
307
+ }, j = (e, t) => {
308
+ if (e.type === "anonymous") throw new w(t === void 0 ? {} : { reason: t });
306
309
  }, M = "admin:full", N = "apikeys:issue:self", P = "apikeys:issue:org", F = "apikeys:issue:other", I = "devices:manage", L = class extends n.TaggedError()("ScopeError", {
307
310
  required: n.String,
308
311
  message: n.String
@@ -317,13 +320,13 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
317
320
  }, H = (e, t) => {
318
321
  let n = V(e);
319
322
  return n.includes("admin:full") || n.includes(t);
320
- }, U = (e, t) => {
323
+ }, fe = (e, t) => {
321
324
  let n = R(e);
322
325
  return n.includes("admin:full") || n.includes(t);
323
- }, fe = (e, n) => H(e, n) ? t.void : t.fail(new L({
326
+ }, pe = (e, n) => H(e, n) ? t.void : t.fail(new L({
324
327
  required: n,
325
328
  message: `missing required scope '${n}'`
326
- })), W = (e, t) => {
329
+ })), U = (e, t) => {
327
330
  let n;
328
331
  try {
329
332
  n = typeof e.action == "function" ? e.action(t) : e.action;
@@ -338,9 +341,9 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
338
341
  message: "policy action selector returned no action"
339
342
  });
340
343
  return n;
341
- }, G = (e) => (typeof e.action == "string" || typeof e.action == "function") && typeof e.resourceType == "string", K = (e) => typeof e.open == "string", q = (e) => e.authenticated === !0, pe = (e) => ({ open: e }), J = (e) => typeof e == "string" ? [e] : e, Y, me = (e) => {
342
- Y = e;
343
- }, he = (e) => Y === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !G(e) && e.resource !== void 0)).map((e) => e.tag) : [], ge = (e) => [
344
+ }, W = (e) => (typeof e.action == "string" || typeof e.action == "function") && typeof e.resourceType == "string", G = (e) => typeof e.open == "string", K = (e) => e.authenticated === !0, me = (e) => ({ open: e }), q = (e) => typeof e == "string" ? [e] : e, J, he = (e) => {
345
+ J = e;
346
+ }, ge = (e) => J === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !W(e) && e.resource !== void 0)).map((e) => e.tag) : [], _e = (e) => [
344
347
  `${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
345
348
  ...e.slice(0, 10).map((e) => ` ${e}`),
346
349
  ...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
@@ -354,33 +357,33 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
354
357
  " • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
355
358
  " subject hold `req.scope` on `req.resource`\" from your own tables.",
356
359
  " • Drop the `resource` extractor if a global scope check is what you meant."
357
- ].join("\n"), _e = () => Y, X, ve = (e) => {
358
- X = e;
359
- }, ye = () => X, Z = (e) => new L({
360
+ ].join("\n"), ve = () => J, Y, ye = (e) => {
361
+ Y = e;
362
+ }, X = () => Y, Z = (e) => new L({
360
363
  required: "access-decision",
361
364
  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>'\`.`
362
365
  }), Q = (e, t) => {
363
366
  let n = e.credentialRejected;
364
- return n === void 0 ? t : new A({ reason: `${n} — the request carried a credential and it was REJECTED, so this caller resolved to anonymous. The guard then refused (${t.message}); the scope is not the problem. Re-authenticate and retry.` });
367
+ return n === void 0 ? t : new w({ reason: `${n} — the request carried a credential and it was REJECTED, so this caller resolved to anonymous. The guard then refused (${t.message}); the scope is not the problem. Re-authenticate and retry.` });
365
368
  }, $ = (e, t, n) => {
366
369
  if (!t || t.length === 0) return n?.defaultDeny === !0 ? Z(n.procedure) : null;
367
370
  for (let n of t) {
368
- if (K(n)) continue;
369
- if (q(n)) {
371
+ if (G(n)) continue;
372
+ if (K(n)) {
370
373
  if (e.id !== null && e.id !== void 0) continue;
371
374
  return Q(e, new L({
372
375
  required: "authenticated",
373
376
  message: "this procedure requires an authenticated caller"
374
377
  }));
375
378
  }
376
- if (G(n)) {
379
+ if (W(n)) {
377
380
  if (H(e, "admin:full")) continue;
378
381
  return Q(e, new L({
379
382
  required: `${n.resourceType}:${n.action}`,
380
383
  message: `relationship guard '${n.action}' on '${n.resourceType}' cannot be checked synchronously`
381
384
  }));
382
385
  }
383
- let t = J(n.scope);
386
+ let t = q(n.scope);
384
387
  if (t.length === 0) continue;
385
388
  let r = t.filter((t) => H(e, t));
386
389
  if (!((n.mode ?? "all") === "any" ? r.length > 0 : r.length === t.length)) {
@@ -395,7 +398,7 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
395
398
  }, be = (e, n, r) => {
396
399
  let i;
397
400
  try {
398
- i = W(n, r);
401
+ i = U(n, r);
399
402
  } catch (e) {
400
403
  return t.succeed(e);
401
404
  }
@@ -404,7 +407,7 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
404
407
  message: e
405
408
  });
406
409
  if (H(e, "admin:full")) return t.succeed(null);
407
- let o = X;
410
+ let o = Y;
408
411
  if (o === void 0) return t.succeed(a(`no policy resolver registered — cannot authorize '${i}' on '${n.resourceType}'`));
409
412
  let s = n.resource(r);
410
413
  return s === void 0 || s === "" ? t.succeed(a(`input does not identify a '${n.resourceType}' to authorize`)) : t.suspend(() => o({
@@ -415,23 +418,23 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
415
418
  })).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((e) => e ? null : a(`no '${i}' relation on ${n.resourceType}:${s}`)));
416
419
  }, xe = (e, n, r, i) => {
417
420
  if (!n || n.length === 0) return t.succeed($(e, n, i));
418
- let a = Y;
419
- return !n.some(G) && (!a || !n.some((e) => e.resource !== void 0)) ? t.succeed($(e, n, i)) : t.gen(function* () {
421
+ let a = J;
422
+ return !n.some(W) && (!a || !n.some((e) => e.resource !== void 0)) ? t.succeed($(e, n, i)) : t.gen(function* () {
420
423
  for (let i of n) {
421
- if (K(i)) continue;
422
- if (q(i)) {
424
+ if (G(i)) continue;
425
+ if (K(i)) {
423
426
  if (e.id !== null && e.id !== void 0) continue;
424
427
  return Q(e, new L({
425
428
  required: "authenticated",
426
429
  message: "this procedure requires an authenticated caller"
427
430
  }));
428
431
  }
429
- if (G(i)) {
432
+ if (W(i)) {
430
433
  let t = yield* be(e, i, r);
431
434
  if (t) return t;
432
435
  continue;
433
436
  }
434
- let n = J(i.scope);
437
+ let n = q(i.scope);
435
438
  if (n.length === 0) continue;
436
439
  let o = i.resource ? i.resource(r) : void 0, s = [];
437
440
  for (let r of n) {
@@ -461,4 +464,4 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
461
464
  });
462
465
  };
463
466
  //#endregion
464
- export { o as $, T as A, k as B, B as C, oe as D, R as E, y as F, ae as G, re as H, A as I, h as J, E as K, _ as L, ie as M, ee as N, b as O, m as P, i as Q, C as R, W as S, me as T, D as U, S as V, O as W, ne as X, te as Y, a as Z, K as _, I as a, pe as b, $ as c, he as d, ye as f, q as g, U as h, N as i, w as j, x as k, xe as l, H as m, P as n, L as o, _e as p, v as q, F as r, ge as s, M as t, V as u, G as v, ve as w, fe as x, Z as y, j as z };
467
+ export { o as $, se as A, A as B, B as C, T as D, R as E, S as F, x as G, ne as H, w as I, ee as J, D as K, _ as L, b as M, m as N, C as O, h as P, i as Q, E as R, U as S, he as T, O as U, ie as V, k as W, te as X, v as Y, a as Z, G as _, I as a, me as b, $ as c, ge as d, X as f, K as g, fe as h, N as i, oe as j, re as k, xe as l, H as m, P as n, L as o, ve as p, y as q, F as r, _e as s, M as t, V as u, W as v, ye as w, pe as x, Z as y, j as z };
package/dist/session.js CHANGED
@@ -1,4 +1,4 @@
1
- import { E as e, J as t, P as n } from "./scopes-Dj7KCJab.js";
1
+ import { E as e, J as t, P as n } from "./scopes-D2dnEr4U.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";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voltro/protocol",
3
- "version": "0.74.0",
3
+ "version": "0.76.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",
@@ -65,14 +65,14 @@
65
65
  "dependencies": {
66
66
  "@effect/experimental": "^0.61.1",
67
67
  "@effect/sql": "^0.52.1",
68
- "@voltro/database": "0.74.0",
69
- "@voltro/logger": "0.74.0",
70
- "jose": "^6.2.10"
68
+ "@voltro/database": "0.76.0",
69
+ "@voltro/logger": "0.76.0",
70
+ "jose": "^6.2.12"
71
71
  },
72
72
  "peerDependencies": {
73
- "@effect/platform": "^0.97.1",
73
+ "@effect/platform": "^0.97.2",
74
74
  "@effect/rpc": "^0.76.2",
75
- "effect": "^3.22.1"
75
+ "effect": "^3.22.2"
76
76
  },
77
77
  "publishConfig": {
78
78
  "access": "public"