@voltro/protocol 0.80.0 → 0.82.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/CHANGELOG.md +1610 -6
- package/dist/apikey.d.ts +10 -2
- package/dist/index.d.ts +949 -76
- package/dist/index.js +904 -634
- package/dist/inspect.d.ts +67 -1
- package/dist/inspect.js +95 -61
- package/dist/jwt.d.ts +9 -1
- package/dist/rest.d.ts +121 -19
- package/dist/rest.js +255 -214
- package/dist/{restFormat-ChSVyufA.js → restFormat-EZ8k9ZcQ.js} +77 -60
- package/dist/{scopes-BbIyym8y.js → scopes-Di756ENh.js} +153 -102
- package/dist/session.d.ts +31 -0
- package/dist/session.js +49 -48
- package/dist/sessionHeader-DriTZhmv.js +7 -0
- package/package.json +3 -3
|
@@ -63,49 +63,62 @@ 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
|
-
}), m = n.
|
|
66
|
+
}), m = n.Struct({
|
|
67
|
+
type: n.Literal("service"),
|
|
68
|
+
id: n.String,
|
|
69
|
+
service: n.String,
|
|
70
|
+
tenantId: n.Null,
|
|
71
|
+
scopes: c,
|
|
72
|
+
metadata: n.optional(s)
|
|
73
|
+
}), ee = n.Union(l, u, d, f, p, m), te = n.Union(l.omit("scopes"), u.omit("scopes"), d.omit("scopes"), f, p.omit("scopes"), m.omit("scopes")), ne = (e) => {
|
|
67
74
|
if (e.type === "anonymous") return e;
|
|
68
75
|
let { scopes: t, ...n } = e;
|
|
69
76
|
return n;
|
|
70
|
-
},
|
|
77
|
+
}, h = (e) => e.scopes ?? [], g = (e, t) => ({
|
|
71
78
|
type: "anonymous",
|
|
72
79
|
id: null,
|
|
73
80
|
tenantId: e,
|
|
74
81
|
...t === void 0 ? {} : { credentialRejected: t }
|
|
75
|
-
}),
|
|
82
|
+
}), re = (e, t = ["admin:full"]) => ({
|
|
76
83
|
type: "system",
|
|
77
84
|
id: e,
|
|
78
85
|
tenantId: null,
|
|
79
86
|
scopes: t
|
|
80
|
-
}),
|
|
87
|
+
}), ie = (e) => ({
|
|
88
|
+
type: "service",
|
|
89
|
+
id: `service:${e}`,
|
|
90
|
+
service: e,
|
|
91
|
+
tenantId: null,
|
|
92
|
+
scopes: []
|
|
93
|
+
}), ae = (e) => e.type === "service", oe = (e) => e.type === "system" || e.type === "service", _ = (e) => {
|
|
81
94
|
if (e.type === "system") return null;
|
|
82
95
|
if (e.type === "serviceAccount" && e.auditActorId !== void 0) return e.auditActorId;
|
|
83
96
|
if (e.type !== "apiKey") return e.id;
|
|
84
97
|
let t = e.metadata?.userId;
|
|
85
98
|
return typeof t == "string" && t !== "" ? t : e.id;
|
|
86
|
-
},
|
|
99
|
+
}, v = (e, t) => {
|
|
87
100
|
let n = e;
|
|
88
101
|
return {
|
|
89
102
|
type: "serviceAccount",
|
|
90
103
|
id: e.id ?? "system",
|
|
91
104
|
tenantId: t,
|
|
92
|
-
auditActorId:
|
|
93
|
-
scopes:
|
|
105
|
+
auditActorId: _(e),
|
|
106
|
+
scopes: h(e),
|
|
94
107
|
...n.metadata === void 0 ? {} : { metadata: n.metadata }
|
|
95
108
|
};
|
|
96
|
-
},
|
|
97
|
-
provides:
|
|
98
|
-
failure:
|
|
99
|
-
}) {},
|
|
109
|
+
}, se = (e) => e.type === "system", ce = "impersonation", le = (e) => e.metadata?.impersonation ?? null, y = class extends e.Tag("@voltro/Subject")() {}, b = class extends e.Tag("@voltro/ConnectionInfo")() {}, x = class extends n.TaggedError()("Unauthenticated", { reason: n.optional(n.String) }) {}, ue = class extends r.Tag()("@voltro/AuthMiddleware", {
|
|
110
|
+
provides: y,
|
|
111
|
+
failure: x
|
|
112
|
+
}) {}, de = class extends r.Tag()("@voltro/ConnectionInfoMiddleware", { provides: b }) {}, fe = (e) => typeof e.mountRoutes == "function", pe = (e) => Array.isArray(e) ? {
|
|
100
113
|
kind: "grant",
|
|
101
114
|
scopes: e
|
|
102
|
-
} : e,
|
|
103
|
-
if (t.kind === "vetoed") throw new
|
|
115
|
+
} : e, S = (e, t) => {
|
|
116
|
+
if (t.kind === "vetoed") throw new x({ reason: `${t.code}: ${t.message}` });
|
|
104
117
|
if (e.type === "anonymous") return {
|
|
105
118
|
subject: e,
|
|
106
119
|
removed: []
|
|
107
120
|
};
|
|
108
|
-
let n =
|
|
121
|
+
let n = h(e);
|
|
109
122
|
if (t.kind === "grant") {
|
|
110
123
|
if (t.scopes.length === 0) return {
|
|
111
124
|
subject: e,
|
|
@@ -128,14 +141,14 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
128
141
|
},
|
|
129
142
|
removed: i
|
|
130
143
|
};
|
|
131
|
-
},
|
|
144
|
+
}, me = 3e4, he = 1e4, C = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ge = () => {
|
|
132
145
|
if (typeof process > "u") return;
|
|
133
146
|
let e = process.env.VOLTRO_AUTH_SCOPE_CACHE_TTL_MS;
|
|
134
147
|
if (e === void 0 || e === "") return;
|
|
135
148
|
let t = Number(e);
|
|
136
149
|
return Number.isFinite(t) && t >= 0 ? t : void 0;
|
|
137
|
-
},
|
|
138
|
-
let t = e.ttlMs ??
|
|
150
|
+
}, w = (e = {}) => {
|
|
151
|
+
let t = e.ttlMs ?? ge() ?? 3e4, n = e.maxEntries ?? 1e4, r = e.now ?? Date.now, i = /* @__PURE__ */ new Map(), a = () => {
|
|
139
152
|
if (i.size <= n) return;
|
|
140
153
|
let e = r();
|
|
141
154
|
for (let [t, n] of i) n.freshUntil <= e && i.delete(t);
|
|
@@ -171,10 +184,10 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
171
184
|
};
|
|
172
185
|
}
|
|
173
186
|
};
|
|
174
|
-
},
|
|
187
|
+
}, _e = (e) => typeof e.resolve == "function", ve = (e) => {
|
|
175
188
|
let t = e.authorization ?? e.Authorization;
|
|
176
189
|
if (t !== void 0) return /^Bearer\s+(.+)$/i.exec(t.trim())?.[1]?.trim();
|
|
177
|
-
},
|
|
190
|
+
}, ye = async (e, t, n, r) => {
|
|
178
191
|
if (!i(e)) return e;
|
|
179
192
|
let s = {
|
|
180
193
|
type: e.type,
|
|
@@ -203,40 +216,52 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
203
216
|
}
|
|
204
217
|
return e;
|
|
205
218
|
}
|
|
206
|
-
},
|
|
207
|
-
let n =
|
|
219
|
+
}, T = (e, t) => {
|
|
220
|
+
let n = ve(t);
|
|
208
221
|
if (n === void 0) return e;
|
|
209
222
|
let r = e.filter((e) => e.claimsBearerPrefix !== void 0 && e.claimsBearerPrefix !== "" && n.startsWith(e.claimsBearerPrefix));
|
|
210
223
|
if (r.length === 0) return e;
|
|
211
224
|
let i = new Set(r);
|
|
212
225
|
return [...r, ...e.filter((e) => !i.has(e))];
|
|
213
|
-
},
|
|
226
|
+
}, be = (e, t) => {
|
|
227
|
+
if (e === "refuse") throw new x({ reason: "anonymous callers are refused" });
|
|
228
|
+
if (e === "no-tenant") return "";
|
|
229
|
+
if (e === "header") {
|
|
230
|
+
if (t === void 0 || t === "") throw new x({ reason: "tenant required (x-tenant header missing)" });
|
|
231
|
+
return t;
|
|
232
|
+
}
|
|
233
|
+
return "tenantId" in e ? e.tenantId : t !== void 0 && t !== "" ? t : e.headerOrTenant;
|
|
234
|
+
}, E = (e, t) => {
|
|
214
235
|
let n = t?.resolveScopes, r = t?.subjectGuards ?? [];
|
|
215
236
|
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.");
|
|
216
237
|
let i = t?.memberships !== void 0 && t.tenantSelection !== void 0 ? {
|
|
217
238
|
memberships: t.memberships,
|
|
218
239
|
store: t.tenantSelection
|
|
219
|
-
} : void 0, a = n !== void 0 || r.length > 0, o = !a || t?.scopeCache === !1 ? null : t?.scopeCache !== void 0 &&
|
|
240
|
+
} : void 0, a = n !== void 0 || r.length > 0, o = !a || t?.scopeCache === !1 ? null : t?.scopeCache !== void 0 && _e(t.scopeCache) ? t.scopeCache : w(t?.scopeCache ?? {});
|
|
220
241
|
return async (s) => {
|
|
221
242
|
let c = t?.getStore?.(), l = c === void 0 ? s : {
|
|
222
243
|
...s,
|
|
223
244
|
store: c
|
|
224
245
|
}, u;
|
|
225
|
-
for (let s of
|
|
246
|
+
for (let s of T(e, l.headers)) {
|
|
226
247
|
let e = await s.resolve(l);
|
|
227
248
|
if (e.kind === "matched") {
|
|
228
|
-
|
|
249
|
+
if (e.subject.type === "service") return { subject: {
|
|
250
|
+
...e.subject,
|
|
251
|
+
scopes: []
|
|
252
|
+
} };
|
|
253
|
+
let c = i === void 0 ? e.subject : await ye(e.subject, l, i, (e) => (t?.onStrategyFailed?.({
|
|
229
254
|
strategyId: s.id,
|
|
230
255
|
reason: e
|
|
231
|
-
}), new
|
|
256
|
+
}), new x({ reason: e }))), u = c;
|
|
232
257
|
if (a) {
|
|
233
258
|
let e = async () => {
|
|
234
259
|
let e = n === void 0 ? {
|
|
235
260
|
kind: "grant",
|
|
236
261
|
scopes: []
|
|
237
|
-
} :
|
|
262
|
+
} : pe(await n(c, l));
|
|
238
263
|
if (e.kind === "unavailable" || r.length === 0) return e;
|
|
239
|
-
let t =
|
|
264
|
+
let t = S(c, e).subject, i = {
|
|
240
265
|
origin: "request",
|
|
241
266
|
headers: l.headers,
|
|
242
267
|
clientId: l.clientId,
|
|
@@ -254,22 +279,22 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
254
279
|
}, { decision: i, fresh: a } = o === null ? {
|
|
255
280
|
decision: await e(),
|
|
256
281
|
fresh: !0
|
|
257
|
-
} : await o.resolve(
|
|
282
|
+
} : await o.resolve(C(c), e);
|
|
258
283
|
if (i.kind === "vetoed") {
|
|
259
284
|
let e = `${i.code}: ${i.message}`;
|
|
260
285
|
throw t?.onStrategyFailed?.({
|
|
261
286
|
strategyId: s.id,
|
|
262
287
|
reason: e
|
|
263
|
-
}), new
|
|
288
|
+
}), new x({ reason: e });
|
|
264
289
|
}
|
|
265
290
|
if (i.kind === "unavailable") {
|
|
266
291
|
let e = `scope resolution unavailable: ${i.reason}`;
|
|
267
292
|
throw t?.onStrategyFailed?.({
|
|
268
293
|
strategyId: s.id,
|
|
269
294
|
reason: e
|
|
270
|
-
}), new
|
|
295
|
+
}), new x({ reason: e });
|
|
271
296
|
}
|
|
272
|
-
let d =
|
|
297
|
+
let d = S(c, i);
|
|
273
298
|
a && d.removed.length > 0 && t?.onScopesNarrowed?.({
|
|
274
299
|
strategyId: s.id,
|
|
275
300
|
subjectType: c.type,
|
|
@@ -298,52 +323,63 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
298
323
|
credentialRejected: u
|
|
299
324
|
} : e };
|
|
300
325
|
}
|
|
301
|
-
if (u !== void 0) throw new
|
|
302
|
-
|
|
303
|
-
let d = l.headers["x-tenant"] ?? t?.anonymousTenantDefault ?? null;
|
|
304
|
-
if (d === null && t?.anonymousTenantRequired === !0) throw new w({ reason: "tenant required (x-tenant header missing)" });
|
|
305
|
-
return { subject: _(d) };
|
|
326
|
+
if (u !== void 0) throw new x({ reason: `credential rejected: ${u}` });
|
|
327
|
+
return { subject: g(be(t?.anonymous ?? "no-tenant", l.headers["x-tenant"])) };
|
|
306
328
|
};
|
|
307
|
-
},
|
|
308
|
-
if (e.type === "anonymous") throw new
|
|
309
|
-
},
|
|
329
|
+
}, D = (e, t) => {
|
|
330
|
+
if (e.type === "anonymous") throw new x(t === void 0 ? {} : { reason: t });
|
|
331
|
+
}, O = "admin:full", k = "apikeys:issue:self", A = "apikeys:issue:org", j = "apikeys:issue:other", M = "devices:manage", N = class extends n.TaggedError()("ScopeError", {
|
|
310
332
|
required: n.String,
|
|
311
333
|
message: n.String
|
|
312
|
-
}) {},
|
|
313
|
-
|
|
314
|
-
|
|
334
|
+
}) {}, P = class extends n.TaggedError()("NoSuchResource", {
|
|
335
|
+
resourceType: n.NullOr(n.String),
|
|
336
|
+
resourceId: n.String,
|
|
337
|
+
message: n.String
|
|
338
|
+
}) {}, F = (e) => "scopes" in e && e.scopes ? e.scopes : [], I = /* @__PURE__ */ new WeakMap(), xe = (e, t) => {
|
|
339
|
+
typeof e == "object" && e && I.set(e, t);
|
|
340
|
+
}, L = (e) => {
|
|
315
341
|
if (typeof e == "object" && e) {
|
|
316
|
-
let t =
|
|
342
|
+
let t = I.get(e);
|
|
317
343
|
if (t) return t;
|
|
318
344
|
}
|
|
319
|
-
return
|
|
320
|
-
},
|
|
321
|
-
let n =
|
|
345
|
+
return F(e);
|
|
346
|
+
}, R = (e, t) => {
|
|
347
|
+
let n = L(e);
|
|
322
348
|
return n.includes("admin:full") || n.includes(t);
|
|
323
|
-
},
|
|
324
|
-
let n =
|
|
349
|
+
}, Se = (e, t) => {
|
|
350
|
+
let n = F(e);
|
|
325
351
|
return n.includes("admin:full") || n.includes(t);
|
|
326
|
-
},
|
|
352
|
+
}, Ce = (e, n) => R(e, n) ? t.void : t.fail(new N({
|
|
327
353
|
required: n,
|
|
328
354
|
message: `missing required scope '${n}'`
|
|
329
|
-
})),
|
|
355
|
+
})), z = (e, t) => {
|
|
330
356
|
let n;
|
|
331
357
|
try {
|
|
332
358
|
n = typeof e.action == "function" ? e.action(t) : e.action;
|
|
333
359
|
} catch {
|
|
334
|
-
throw new
|
|
360
|
+
throw new N({
|
|
335
361
|
required: e.resourceType,
|
|
336
362
|
message: "policy action selector failed"
|
|
337
363
|
});
|
|
338
364
|
}
|
|
339
|
-
if (typeof n != "string" || n.trim() === "") throw new
|
|
365
|
+
if (typeof n != "string" || n.trim() === "") throw new N({
|
|
340
366
|
required: e.resourceType,
|
|
341
367
|
message: "policy action selector returned no action"
|
|
342
368
|
});
|
|
343
369
|
return n;
|
|
344
|
-
},
|
|
345
|
-
|
|
346
|
-
|
|
370
|
+
}, B = (e) => (typeof e.action == "string" || typeof e.action == "function") && typeof e.resourceType == "string", we = (e) => e !== void 0 && e.some((e) => B(e) || typeof e.resource == "function"), V = (e) => typeof e.open == "string", H = (e) => Array.isArray(e.service), Te = (e) => ({ service: [...e] }), U = (e) => e?.find(H)?.service, W = (e, t) => {
|
|
371
|
+
let n = U(t);
|
|
372
|
+
if (e.type === "service") return n !== void 0 && n.includes(e.service) ? null : new N({
|
|
373
|
+
required: "service-procedure",
|
|
374
|
+
message: n === void 0 ? `service '${e.service}' may only call procedures that declare it in \`service: { callers }\`` : `service '${e.service}' is not among this procedure's callers [${n.join(", ")}]`
|
|
375
|
+
});
|
|
376
|
+
if (n !== void 0) return Z(e, new N({
|
|
377
|
+
required: `service:${n.join("|")}`,
|
|
378
|
+
message: `this procedure is callable only by the service${n.length === 1 ? "" : "s"} [${n.join(", ")}]`
|
|
379
|
+
}));
|
|
380
|
+
}, G = (e) => e.authenticated === !0, Ee = (e) => ({ open: e }), K = (e) => typeof e == "string" ? [e] : e, q, De = (e) => {
|
|
381
|
+
q = e;
|
|
382
|
+
}, Oe = (e) => q === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !B(e) && e.resource !== void 0)).map((e) => e.tag) : [], ke = (e) => [
|
|
347
383
|
`${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
|
|
348
384
|
...e.slice(0, 10).map((e) => ` ${e}`),
|
|
349
385
|
...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
|
|
@@ -357,57 +393,59 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
357
393
|
" • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
|
|
358
394
|
" subject hold `req.scope` on `req.resource`\" from your own tables.",
|
|
359
395
|
" • Drop the `resource` extractor if a global scope check is what you meant."
|
|
360
|
-
].join("\n"),
|
|
361
|
-
|
|
362
|
-
},
|
|
396
|
+
].join("\n"), Ae = () => q, J, je = (e) => {
|
|
397
|
+
J = e;
|
|
398
|
+
}, Y = () => J, X = (e) => new N({
|
|
363
399
|
required: "access-decision",
|
|
364
400
|
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>'\`.`
|
|
365
|
-
}),
|
|
401
|
+
}), Z = (e, t) => {
|
|
366
402
|
let n = e.credentialRejected;
|
|
367
|
-
return n === void 0 ? t : new
|
|
368
|
-
},
|
|
369
|
-
|
|
403
|
+
return n === void 0 ? t : new x({ 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.` });
|
|
404
|
+
}, Q = (e, t, n) => {
|
|
405
|
+
let r = W(e, t);
|
|
406
|
+
if (r !== void 0) return r;
|
|
407
|
+
if (!t || t.length === 0) return n?.defaultDeny === !0 ? X(n.procedure) : null;
|
|
370
408
|
for (let n of t) {
|
|
371
|
-
if (
|
|
372
|
-
if (
|
|
409
|
+
if (V(n) || H(n)) continue;
|
|
410
|
+
if (G(n)) {
|
|
373
411
|
if (e.id !== null && e.id !== void 0) continue;
|
|
374
|
-
return
|
|
412
|
+
return Z(e, new N({
|
|
375
413
|
required: "authenticated",
|
|
376
414
|
message: "this procedure requires an authenticated caller"
|
|
377
415
|
}));
|
|
378
416
|
}
|
|
379
|
-
if (
|
|
380
|
-
if (
|
|
381
|
-
return
|
|
417
|
+
if (B(n)) {
|
|
418
|
+
if (R(e, "admin:full")) continue;
|
|
419
|
+
return Z(e, new N({
|
|
382
420
|
required: `${n.resourceType}:${n.action}`,
|
|
383
421
|
message: `relationship guard '${n.action}' on '${n.resourceType}' cannot be checked synchronously`
|
|
384
422
|
}));
|
|
385
423
|
}
|
|
386
|
-
let t =
|
|
424
|
+
let t = K(n.scope);
|
|
387
425
|
if (t.length === 0) continue;
|
|
388
|
-
let r = t.filter((t) =>
|
|
426
|
+
let r = t.filter((t) => R(e, t));
|
|
389
427
|
if (!((n.mode ?? "all") === "any" ? r.length > 0 : r.length === t.length)) {
|
|
390
|
-
let r = (n.mode ?? "all") === "any" ? t[0] : t.find((t) => !
|
|
391
|
-
return
|
|
428
|
+
let r = (n.mode ?? "all") === "any" ? t[0] : t.find((t) => !R(e, t));
|
|
429
|
+
return Z(e, new N({
|
|
392
430
|
required: r,
|
|
393
431
|
message: (n.mode ?? "all") === "any" ? `missing all of required scopes [${t.join(", ")}]` : `missing required scope '${r}'`
|
|
394
432
|
}));
|
|
395
433
|
}
|
|
396
434
|
}
|
|
397
435
|
return null;
|
|
398
|
-
},
|
|
436
|
+
}, Me = (e, n, r) => {
|
|
399
437
|
let i;
|
|
400
438
|
try {
|
|
401
|
-
i =
|
|
439
|
+
i = z(n, r);
|
|
402
440
|
} catch (e) {
|
|
403
441
|
return t.succeed(e);
|
|
404
442
|
}
|
|
405
|
-
let a = (e) => new
|
|
443
|
+
let a = (e) => new N({
|
|
406
444
|
required: `${n.resourceType}:${i}`,
|
|
407
445
|
message: e
|
|
408
446
|
});
|
|
409
|
-
if (
|
|
410
|
-
let o =
|
|
447
|
+
if (R(e, "admin:full")) return t.succeed(null);
|
|
448
|
+
let o = J;
|
|
411
449
|
if (o === void 0) return t.succeed(a(`no policy resolver registered — cannot authorize '${i}' on '${n.resourceType}'`));
|
|
412
450
|
let s = n.resource(r);
|
|
413
451
|
return s === void 0 || s === "" ? t.succeed(a(`input does not identify a '${n.resourceType}' to authorize`)) : t.suspend(() => o({
|
|
@@ -415,48 +453,61 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
415
453
|
action: i,
|
|
416
454
|
resourceType: n.resourceType,
|
|
417
455
|
resourceId: s
|
|
418
|
-
})).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((
|
|
419
|
-
},
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
456
|
+
})).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((t) => $(e, t, n.resourceType, s, () => a(`no '${i}' relation on ${n.resourceType}:${s}`))));
|
|
457
|
+
}, $ = (e, t, n, r, i) => t === !0 ? null : t === "missing" && e.id !== null && e.id !== void 0 ? new P({
|
|
458
|
+
resourceType: n,
|
|
459
|
+
resourceId: r,
|
|
460
|
+
message: n === null ? `no such resource '${r}'` : `no such ${n} '${r}'`
|
|
461
|
+
}) : i(), Ne = (e, n, r, i) => {
|
|
462
|
+
let a = W(e, n);
|
|
463
|
+
if (a !== void 0) return t.succeed(a);
|
|
464
|
+
if (!n || n.length === 0) return t.succeed(Q(e, n, i));
|
|
465
|
+
let o = q;
|
|
466
|
+
return !n.some(B) && (!o || !n.some((e) => e.resource !== void 0)) ? t.succeed(Q(e, n, i)) : t.gen(function* () {
|
|
423
467
|
for (let i of n) {
|
|
424
|
-
if (
|
|
425
|
-
if (
|
|
468
|
+
if (V(i) || H(i)) continue;
|
|
469
|
+
if (G(i)) {
|
|
426
470
|
if (e.id !== null && e.id !== void 0) continue;
|
|
427
|
-
return
|
|
471
|
+
return Z(e, new N({
|
|
428
472
|
required: "authenticated",
|
|
429
473
|
message: "this procedure requires an authenticated caller"
|
|
430
474
|
}));
|
|
431
475
|
}
|
|
432
|
-
if (
|
|
433
|
-
let t = yield*
|
|
476
|
+
if (B(i)) {
|
|
477
|
+
let t = yield* Me(e, i, r);
|
|
434
478
|
if (t) return t;
|
|
435
479
|
continue;
|
|
436
480
|
}
|
|
437
|
-
let n =
|
|
481
|
+
let n = K(i.scope);
|
|
438
482
|
if (n.length === 0) continue;
|
|
439
|
-
let
|
|
483
|
+
let a = i.resource ? i.resource(r) : void 0, s = [], c = !1;
|
|
440
484
|
for (let r of n) {
|
|
441
|
-
if (
|
|
485
|
+
if (R(e, r)) {
|
|
442
486
|
s.push(!0);
|
|
443
487
|
continue;
|
|
444
488
|
}
|
|
445
|
-
if (
|
|
446
|
-
let n = yield* t.suspend(() =>
|
|
489
|
+
if (a !== void 0 && o !== void 0) {
|
|
490
|
+
let n = yield* t.suspend(() => o({
|
|
447
491
|
subject: e,
|
|
448
492
|
scope: r,
|
|
449
|
-
resource:
|
|
493
|
+
resource: a
|
|
450
494
|
})).pipe(t.catchAllCause(() => t.succeed(!1)));
|
|
451
|
-
s.push(n);
|
|
495
|
+
n === "missing" && (c = !0), s.push(n === !0);
|
|
452
496
|
} else s.push(!1);
|
|
453
497
|
}
|
|
454
|
-
let
|
|
455
|
-
if (!(
|
|
456
|
-
let
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
498
|
+
let l = i.mode ?? "all";
|
|
499
|
+
if (!(l === "any" ? s.some(Boolean) : s.every(Boolean))) {
|
|
500
|
+
let t = l === "any" ? n[0] : n[n.findIndex((e, t) => !s[t])];
|
|
501
|
+
if (c && a !== void 0) {
|
|
502
|
+
let n = $(e, "missing", null, a, () => new N({
|
|
503
|
+
required: t,
|
|
504
|
+
message: `missing required scope '${t}' on resource '${a}'`
|
|
505
|
+
}));
|
|
506
|
+
if (n !== null) return n;
|
|
507
|
+
}
|
|
508
|
+
return new N({
|
|
509
|
+
required: t,
|
|
510
|
+
message: l === "any" ? `missing all of required scopes [${n.join(", ")}]` : `missing required scope '${t}'` + (a === void 0 ? "" : ` on resource '${a}'`)
|
|
460
511
|
});
|
|
461
512
|
}
|
|
462
513
|
}
|
|
@@ -464,4 +515,4 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
464
515
|
});
|
|
465
516
|
};
|
|
466
517
|
//#endregion
|
|
467
|
-
export {
|
|
518
|
+
export { C as $, De as A, y as B, Ee as C, U as D, Te as E, he as F, E as G, g as H, me as I, ae as J, fe as K, ce as L, ue as M, b as N, xe as O, de as P, le as Q, ee as R, X as S, z as T, S as U, x as V, D as W, w as X, se as Y, T as Z, Se as _, M as a, a as at, B as b, ke as c, we as d, ie as et, L as f, R as g, Ae as h, k as i, v as it, F as j, je as k, Q as l, Y as m, A as n, ne as nt, P as o, i as ot, Oe as p, oe as q, j as r, re as rt, N as s, o as st, O as t, _ as tt, Ne as u, G as v, Ce as w, H as x, V as y, te as z };
|
package/dist/session.d.ts
CHANGED
|
@@ -74,6 +74,14 @@ export declare const MIN_SESSION_SECRET_LENGTH: 32;
|
|
|
74
74
|
*/
|
|
75
75
|
export declare const readCookie: (header: string | undefined, name: string) => string | undefined;
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* The session value this request presents — the `x-voltro-session` header a
|
|
79
|
+
* cookie-less client (React Native, a desktop shell) sets on every rpc frame,
|
|
80
|
+
* or the session cookie a browser carries. See `./sessionHeader.ts` for why
|
|
81
|
+
* it is a dedicated header and why the header wins.
|
|
82
|
+
*/
|
|
83
|
+
export declare const readSessionValue: (headers: Readonly<Record<string, string | undefined>>, cookieName?: string) => string | undefined;
|
|
84
|
+
|
|
77
85
|
/**
|
|
78
86
|
* Reset the once-per-process warning latch. Tests only — the latch is what
|
|
79
87
|
* makes the diagnostic readable in production and unobservable in a second
|
|
@@ -125,6 +133,9 @@ export declare const resolveSessionSecrets: () => SessionSecrets;
|
|
|
125
133
|
*/
|
|
126
134
|
export declare const SESSION_COOKIE_NAME: string;
|
|
127
135
|
|
|
136
|
+
/** The request header carrying a framework session value outside a cookie. */
|
|
137
|
+
export declare const SESSION_HEADER_NAME: "x-voltro-session";
|
|
138
|
+
|
|
128
139
|
/**
|
|
129
140
|
* The session payload format this build mints and accepts.
|
|
130
141
|
*
|
|
@@ -189,6 +200,12 @@ declare const SessionPayload_2: Schema.Struct<{
|
|
|
189
200
|
id: typeof Schema.String;
|
|
190
201
|
tenantId: typeof Schema.Null;
|
|
191
202
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
203
|
+
}>, Schema.Struct<{
|
|
204
|
+
type: Schema.Literal<["service"]>;
|
|
205
|
+
id: typeof Schema.String;
|
|
206
|
+
tenantId: typeof Schema.Null;
|
|
207
|
+
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
208
|
+
service: typeof Schema.String;
|
|
192
209
|
}>]>;
|
|
193
210
|
/** Unix seconds when this session expires. Verify rejects past expiry. */
|
|
194
211
|
exp: typeof Schema.Number;
|
|
@@ -311,6 +328,14 @@ declare const Subject: Schema.Union<[Schema.Struct<{
|
|
|
311
328
|
tenantId: typeof Schema.Null;
|
|
312
329
|
scopes: Schema.optional<Schema.Array$<typeof Schema.String>>;
|
|
313
330
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
331
|
+
}>, Schema.Struct<{
|
|
332
|
+
type: Schema.Literal<["service"]>;
|
|
333
|
+
id: typeof Schema.String;
|
|
334
|
+
/** The calling app's name, as the callee lists it in `serviceCallers`. */
|
|
335
|
+
service: typeof Schema.String;
|
|
336
|
+
tenantId: typeof Schema.Null;
|
|
337
|
+
scopes: Schema.optional<Schema.Array$<typeof Schema.String>>;
|
|
338
|
+
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
314
339
|
}>]>;
|
|
315
340
|
|
|
316
341
|
declare type Subject = typeof Subject.Type;
|
|
@@ -359,6 +384,12 @@ declare const SubjectIdentity: Schema.Union<[Schema.Struct<{
|
|
|
359
384
|
id: typeof Schema.String;
|
|
360
385
|
tenantId: typeof Schema.Null;
|
|
361
386
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
387
|
+
}>, Schema.Struct<{
|
|
388
|
+
type: Schema.Literal<["service"]>;
|
|
389
|
+
id: typeof Schema.String;
|
|
390
|
+
tenantId: typeof Schema.Null;
|
|
391
|
+
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
392
|
+
service: typeof Schema.String;
|
|
362
393
|
}>]>;
|
|
363
394
|
|
|
364
395
|
declare type SubjectIdentity = typeof SubjectIdentity.Type;
|