@voltro/protocol 0.81.0 → 0.83.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 +1806 -6
- package/dist/apikey.d.ts +2 -2
- package/dist/index.d.ts +613 -69
- package/dist/index.js +881 -644
- package/dist/inspect.d.ts +85 -1
- package/dist/inspect.js +106 -61
- package/dist/jwt.d.ts +1 -1
- package/dist/rest.d.ts +40 -3
- package/dist/rest.js +191 -159
- package/dist/{restFormat-CzdGVkuB.js → restFormat-EZ8k9ZcQ.js} +38 -33
- package/dist/{scopes-CvU5QBQ4.js → scopes-Di756ENh.js} +126 -106
- package/dist/session.d.ts +11 -0
- package/dist/session.js +53 -52
- package/dist/sessionHeader-DriTZhmv.js +7 -0
- package/package.json +3 -3
|
@@ -118,13 +118,18 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
118
118
|
differing: n.sort(),
|
|
119
119
|
missingHere: r.sort()
|
|
120
120
|
};
|
|
121
|
-
}, S =
|
|
122
|
-
|
|
121
|
+
}, S = (e) => {
|
|
122
|
+
let t = e.error, n = t instanceof Error ? t.name : typeof t?._tag == "string" ? String(t._tag) : "Error", r = [e.name === void 0 ? e.source : `${e.source} '${e.name}'`, ...typeof e.fields?.runId == "string" ? [`run ${e.fields.runId}`] : []].join(", "), i = /* @__PURE__ */ Error(`[message withheld: ${r} is declared encrypted — read it where the run is shown]`);
|
|
123
|
+
i.name = n;
|
|
124
|
+
let a = t instanceof Error && typeof t.stack == "string" ? t.stack : "", o = a.search(/^\s+at /m);
|
|
125
|
+
return i.stack = `${n}: ${i.message}${o === -1 ? "" : `\n${a.slice(o)}`}`, i;
|
|
126
|
+
}, C = /* @__PURE__ */ new Set(), w = (e) => {
|
|
127
|
+
for (let t of C) try {
|
|
123
128
|
t(e);
|
|
124
129
|
} catch {}
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
}),
|
|
130
|
+
}, T = (e) => (C.add(e), () => {
|
|
131
|
+
C.delete(e);
|
|
132
|
+
}), E = {
|
|
128
133
|
rpc: {
|
|
129
134
|
name: "rpc",
|
|
130
135
|
dates: "epoch-ms",
|
|
@@ -158,16 +163,16 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
158
163
|
naming: "camelCase",
|
|
159
164
|
etag: !0
|
|
160
165
|
}
|
|
161
|
-
},
|
|
166
|
+
}, D = [
|
|
162
167
|
"rpc",
|
|
163
168
|
"standard",
|
|
164
169
|
"jsonapi"
|
|
165
|
-
],
|
|
170
|
+
], O = (e, t = void 0) => {
|
|
166
171
|
let n = (e) => {
|
|
167
172
|
if (e?.profile !== void 0) {
|
|
168
173
|
if (typeof e.profile == "string") {
|
|
169
|
-
let t =
|
|
170
|
-
if (t === void 0) throw Error(`publicApi.profile: unknown profile '${String(e.profile)}' — one of ${
|
|
174
|
+
let t = E[e.profile];
|
|
175
|
+
if (t === void 0) throw Error(`publicApi.profile: unknown profile '${String(e.profile)}' — one of ${D.join(", ")}, or a RestFormat object`);
|
|
171
176
|
return t;
|
|
172
177
|
}
|
|
173
178
|
return e.profile;
|
|
@@ -182,14 +187,14 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
182
187
|
...t.cursorParam === void 0 ? {} : { cursorParam: t.cursorParam },
|
|
183
188
|
...t.naming === void 0 ? {} : { naming: t.naming },
|
|
184
189
|
...t.etag === void 0 ? {} : { etag: t.etag }
|
|
185
|
-
}, i = r(n(e) ??
|
|
190
|
+
}, i = r(n(e) ?? E.rpc, e);
|
|
186
191
|
return r(n(t) ?? i, t);
|
|
187
|
-
},
|
|
192
|
+
}, k = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase(), A = (e, t) => {
|
|
188
193
|
if (typeof e != "object" || !e || Array.isArray(e)) return e;
|
|
189
194
|
let n = {};
|
|
190
195
|
for (let [r, i] of Object.entries(e)) n[t(r)] = i;
|
|
191
196
|
return n;
|
|
192
|
-
},
|
|
197
|
+
}, j = (e) => n.getOrUndefined(t.getIdentifierAnnotation(e)), M = (n, r) => {
|
|
193
198
|
if (r.dates === "epoch-ms" && r.naming === "camelCase") return n;
|
|
194
199
|
let i = /* @__PURE__ */ new Map(), a = (e) => {
|
|
195
200
|
let t = i.get(e);
|
|
@@ -199,7 +204,7 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
199
204
|
}, o = (n) => {
|
|
200
205
|
switch (n._tag) {
|
|
201
206
|
case "Transformation":
|
|
202
|
-
if (r.dates === "iso" &&
|
|
207
|
+
if (r.dates === "iso" && j(n) === "DateFromNumber") {
|
|
203
208
|
let r = e.DateFromString.ast;
|
|
204
209
|
return new t.Transformation(r.from, r.to, r.transformation, {
|
|
205
210
|
...r.annotations,
|
|
@@ -219,41 +224,41 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
219
224
|
case "TypeLiteral": {
|
|
220
225
|
let i = n.propertySignatures.map((e) => new t.PropertySignature(e.name, a(e.type), e.isOptional, e.isReadonly, e.annotations)), o = n.indexSignatures.map((e) => new t.IndexSignature(e.parameter, a(e.type), e.isReadonly)), s = new t.TypeLiteral(i, o, n.annotations);
|
|
221
226
|
if (r.naming !== "snake_case") return s;
|
|
222
|
-
let c = i.map((e) => typeof e.name == "string" ?
|
|
227
|
+
let c = i.map((e) => typeof e.name == "string" ? k(e.name) : e.name);
|
|
223
228
|
if (c.every((e, t) => e === i[t].name)) return s;
|
|
224
229
|
let l = new t.TypeLiteral(i.map((e, n) => new t.PropertySignature(c[n], t.encodedAST(e.type), e.isOptional, e.isReadonly, e.annotations)), o.map((e) => new t.IndexSignature(e.parameter, t.encodedAST(e.type), e.isReadonly)), n.annotations), u = new Map(i.map((e, t) => [String(c[t]), String(e.name)])), d = new Map(i.map((e, t) => [String(e.name), String(c[t])]));
|
|
225
230
|
return e.transform(e.make(l), e.make(s), {
|
|
226
231
|
strict: !1,
|
|
227
|
-
decode: (e) =>
|
|
228
|
-
encode: (e) =>
|
|
232
|
+
decode: (e) => A(e, (e) => u.get(e) ?? e),
|
|
233
|
+
encode: (e) => A(e, (e) => d.get(e) ?? e)
|
|
229
234
|
}).ast;
|
|
230
235
|
}
|
|
231
236
|
default: return n;
|
|
232
237
|
}
|
|
233
238
|
};
|
|
234
239
|
return e.make(a(n.ast));
|
|
235
|
-
},
|
|
236
|
-
type:
|
|
237
|
-
title:
|
|
240
|
+
}, N = (e) => `urn:voltro:error:${e}`, P = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z])([A-Z][a-z])/g, "$1 $2"), F = (e) => ({
|
|
241
|
+
type: N(e.tag),
|
|
242
|
+
title: P(e.tag),
|
|
238
243
|
status: e.status,
|
|
239
244
|
...e.message.length > 0 ? { detail: e.message } : {},
|
|
240
245
|
...e.fields
|
|
241
|
-
}),
|
|
246
|
+
}), I = "application/problem+json; charset=utf-8", L = "application/vnd.api+json; charset=utf-8", R = (e, t, n) => e.encodeError === void 0 ? e.errors === "problem-details" ? e.envelope === "jsonapi" ? {
|
|
242
247
|
body: { errors: [{
|
|
243
248
|
status: String(t.status),
|
|
244
249
|
code: t.tag,
|
|
245
|
-
title:
|
|
250
|
+
title: P(t.tag),
|
|
246
251
|
...t.message.length > 0 ? { detail: t.message } : {},
|
|
247
252
|
...Object.keys(t.fields).length > 0 ? { meta: t.fields } : {}
|
|
248
253
|
}] },
|
|
249
|
-
contentType:
|
|
254
|
+
contentType: L
|
|
250
255
|
} : {
|
|
251
|
-
body:
|
|
252
|
-
contentType:
|
|
256
|
+
body: F(t),
|
|
257
|
+
contentType: I
|
|
253
258
|
} : { body: {
|
|
254
259
|
error: t.tag === "InvalidRequest" || t.tag === "InternalServerError" || t.tag === "Unauthorized" || t.tag === "Forbidden" || t.tag === "Gone" || t.tag === "MethodNotAllowed" || t.tag === "Conflict" ? t.message : t.tag,
|
|
255
260
|
...t.fields
|
|
256
|
-
} } : e.encodeError(t, n),
|
|
261
|
+
} } : e.encodeError(t, n), z = (e, t) => {
|
|
257
262
|
if (typeof e != "object" || !e || Array.isArray(e)) return {
|
|
258
263
|
cursor: void 0,
|
|
259
264
|
rest: e
|
|
@@ -266,10 +271,10 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
266
271
|
cursor: String(n),
|
|
267
272
|
rest: e
|
|
268
273
|
};
|
|
269
|
-
},
|
|
274
|
+
}, B = (e, t, n) => {
|
|
270
275
|
let r = new URLSearchParams(e.query);
|
|
271
276
|
return r.set(n, t), `<${e.path}?${r.toString()}>; rel="next"`;
|
|
272
|
-
},
|
|
277
|
+
}, V = (e, t) => {
|
|
273
278
|
if (typeof e != "object" || !e || Array.isArray(e)) return e;
|
|
274
279
|
let { id: n, ...r } = e;
|
|
275
280
|
return {
|
|
@@ -277,9 +282,9 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
277
282
|
...n === void 0 ? {} : { id: String(n) },
|
|
278
283
|
attributes: r
|
|
279
284
|
};
|
|
280
|
-
},
|
|
285
|
+
}, H = (e, t, n) => {
|
|
281
286
|
if (e.encodeSuccess !== void 0) return e.encodeSuccess(t, n);
|
|
282
|
-
let { cursor: r } =
|
|
287
|
+
let { cursor: r } = z(t, e.cursorField), i = e.pagination === "link-header" && r !== void 0 ? { Link: B(n, r, e.cursorParam) } : void 0, a = (e, t) => ({
|
|
283
288
|
body: e,
|
|
284
289
|
...i ? { headers: i } : {},
|
|
285
290
|
...t ? { contentType: t } : {}
|
|
@@ -291,9 +296,9 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
291
296
|
});
|
|
292
297
|
let o = n.source ?? n.tag.split(".")[0] ?? "resource", s = Array.isArray(t) ? t : typeof t == "object" && t && Array.isArray(t.items) ? t.items : void 0;
|
|
293
298
|
return a({
|
|
294
|
-
data: s === void 0 ?
|
|
295
|
-
...r === void 0 ? {} : { links: { next:
|
|
296
|
-
},
|
|
299
|
+
data: s === void 0 ? V(t, o) : s.map((e) => V(e, o)),
|
|
300
|
+
...r === void 0 ? {} : { links: { next: B(n, r, e.cursorParam).replace(/^<|>; rel="next"$/g, "") } }
|
|
301
|
+
}, L);
|
|
297
302
|
};
|
|
298
303
|
//#endregion
|
|
299
|
-
export {
|
|
304
|
+
export { d as A, p as C, f as D, l as E, c as O, a as S, u as T, y as _, H as a, s as b, N as c, k as d, w as f, b as g, x as h, R as i, i as j, r as k, O as l, S as m, I as n, B as o, T as p, D as r, F as s, L as t, M as u, _ as v, o as w, m as x, v as y };
|
|
@@ -70,55 +70,55 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
70
70
|
tenantId: n.Null,
|
|
71
71
|
scopes: c,
|
|
72
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")),
|
|
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) => {
|
|
74
74
|
if (e.type === "anonymous") return e;
|
|
75
75
|
let { scopes: t, ...n } = e;
|
|
76
76
|
return n;
|
|
77
|
-
},
|
|
77
|
+
}, h = (e) => e.scopes ?? [], g = (e, t) => ({
|
|
78
78
|
type: "anonymous",
|
|
79
79
|
id: null,
|
|
80
80
|
tenantId: e,
|
|
81
81
|
...t === void 0 ? {} : { credentialRejected: t }
|
|
82
|
-
}),
|
|
82
|
+
}), re = (e, t = ["admin:full"]) => ({
|
|
83
83
|
type: "system",
|
|
84
84
|
id: e,
|
|
85
85
|
tenantId: null,
|
|
86
86
|
scopes: t
|
|
87
|
-
}),
|
|
87
|
+
}), ie = (e) => ({
|
|
88
88
|
type: "service",
|
|
89
89
|
id: `service:${e}`,
|
|
90
90
|
service: e,
|
|
91
91
|
tenantId: null,
|
|
92
92
|
scopes: []
|
|
93
|
-
}),
|
|
93
|
+
}), ae = (e) => e.type === "service", oe = (e) => e.type === "system" || e.type === "service", _ = (e) => {
|
|
94
94
|
if (e.type === "system") return null;
|
|
95
95
|
if (e.type === "serviceAccount" && e.auditActorId !== void 0) return e.auditActorId;
|
|
96
96
|
if (e.type !== "apiKey") return e.id;
|
|
97
97
|
let t = e.metadata?.userId;
|
|
98
98
|
return typeof t == "string" && t !== "" ? t : e.id;
|
|
99
|
-
},
|
|
99
|
+
}, v = (e, t) => {
|
|
100
100
|
let n = e;
|
|
101
101
|
return {
|
|
102
102
|
type: "serviceAccount",
|
|
103
103
|
id: e.id ?? "system",
|
|
104
104
|
tenantId: t,
|
|
105
|
-
auditActorId:
|
|
106
|
-
scopes:
|
|
105
|
+
auditActorId: _(e),
|
|
106
|
+
scopes: h(e),
|
|
107
107
|
...n.metadata === void 0 ? {} : { metadata: n.metadata }
|
|
108
108
|
};
|
|
109
|
-
},
|
|
110
|
-
provides:
|
|
111
|
-
failure:
|
|
112
|
-
}) {},
|
|
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) ? {
|
|
113
113
|
kind: "grant",
|
|
114
114
|
scopes: e
|
|
115
|
-
} : e,
|
|
116
|
-
if (t.kind === "vetoed") throw new
|
|
115
|
+
} : e, S = (e, t) => {
|
|
116
|
+
if (t.kind === "vetoed") throw new x({ reason: `${t.code}: ${t.message}` });
|
|
117
117
|
if (e.type === "anonymous") return {
|
|
118
118
|
subject: e,
|
|
119
119
|
removed: []
|
|
120
120
|
};
|
|
121
|
-
let n =
|
|
121
|
+
let n = h(e);
|
|
122
122
|
if (t.kind === "grant") {
|
|
123
123
|
if (t.scopes.length === 0) return {
|
|
124
124
|
subject: e,
|
|
@@ -141,14 +141,14 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
141
141
|
},
|
|
142
142
|
removed: i
|
|
143
143
|
};
|
|
144
|
-
},
|
|
144
|
+
}, me = 3e4, he = 1e4, C = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ge = () => {
|
|
145
145
|
if (typeof process > "u") return;
|
|
146
146
|
let e = process.env.VOLTRO_AUTH_SCOPE_CACHE_TTL_MS;
|
|
147
147
|
if (e === void 0 || e === "") return;
|
|
148
148
|
let t = Number(e);
|
|
149
149
|
return Number.isFinite(t) && t >= 0 ? t : void 0;
|
|
150
|
-
},
|
|
151
|
-
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 = () => {
|
|
152
152
|
if (i.size <= n) return;
|
|
153
153
|
let e = r();
|
|
154
154
|
for (let [t, n] of i) n.freshUntil <= e && i.delete(t);
|
|
@@ -184,10 +184,10 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
};
|
|
187
|
-
},
|
|
187
|
+
}, _e = (e) => typeof e.resolve == "function", ve = (e) => {
|
|
188
188
|
let t = e.authorization ?? e.Authorization;
|
|
189
189
|
if (t !== void 0) return /^Bearer\s+(.+)$/i.exec(t.trim())?.[1]?.trim();
|
|
190
|
-
},
|
|
190
|
+
}, ye = async (e, t, n, r) => {
|
|
191
191
|
if (!i(e)) return e;
|
|
192
192
|
let s = {
|
|
193
193
|
type: e.type,
|
|
@@ -216,44 +216,52 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
216
216
|
}
|
|
217
217
|
return e;
|
|
218
218
|
}
|
|
219
|
-
},
|
|
220
|
-
let n =
|
|
219
|
+
}, T = (e, t) => {
|
|
220
|
+
let n = ve(t);
|
|
221
221
|
if (n === void 0) return e;
|
|
222
222
|
let r = e.filter((e) => e.claimsBearerPrefix !== void 0 && e.claimsBearerPrefix !== "" && n.startsWith(e.claimsBearerPrefix));
|
|
223
223
|
if (r.length === 0) return e;
|
|
224
224
|
let i = new Set(r);
|
|
225
225
|
return [...r, ...e.filter((e) => !i.has(e))];
|
|
226
|
-
},
|
|
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) => {
|
|
227
235
|
let n = t?.resolveScopes, r = t?.subjectGuards ?? [];
|
|
228
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.");
|
|
229
237
|
let i = t?.memberships !== void 0 && t.tenantSelection !== void 0 ? {
|
|
230
238
|
memberships: t.memberships,
|
|
231
239
|
store: t.tenantSelection
|
|
232
|
-
} : 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 ?? {});
|
|
233
241
|
return async (s) => {
|
|
234
242
|
let c = t?.getStore?.(), l = c === void 0 ? s : {
|
|
235
243
|
...s,
|
|
236
244
|
store: c
|
|
237
245
|
}, u;
|
|
238
|
-
for (let s of
|
|
246
|
+
for (let s of T(e, l.headers)) {
|
|
239
247
|
let e = await s.resolve(l);
|
|
240
248
|
if (e.kind === "matched") {
|
|
241
249
|
if (e.subject.type === "service") return { subject: {
|
|
242
250
|
...e.subject,
|
|
243
251
|
scopes: []
|
|
244
252
|
} };
|
|
245
|
-
let c = i === void 0 ? e.subject : await
|
|
253
|
+
let c = i === void 0 ? e.subject : await ye(e.subject, l, i, (e) => (t?.onStrategyFailed?.({
|
|
246
254
|
strategyId: s.id,
|
|
247
255
|
reason: e
|
|
248
|
-
}), new
|
|
256
|
+
}), new x({ reason: e }))), u = c;
|
|
249
257
|
if (a) {
|
|
250
258
|
let e = async () => {
|
|
251
259
|
let e = n === void 0 ? {
|
|
252
260
|
kind: "grant",
|
|
253
261
|
scopes: []
|
|
254
|
-
} :
|
|
262
|
+
} : pe(await n(c, l));
|
|
255
263
|
if (e.kind === "unavailable" || r.length === 0) return e;
|
|
256
|
-
let t =
|
|
264
|
+
let t = S(c, e).subject, i = {
|
|
257
265
|
origin: "request",
|
|
258
266
|
headers: l.headers,
|
|
259
267
|
clientId: l.clientId,
|
|
@@ -271,22 +279,22 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
271
279
|
}, { decision: i, fresh: a } = o === null ? {
|
|
272
280
|
decision: await e(),
|
|
273
281
|
fresh: !0
|
|
274
|
-
} : await o.resolve(
|
|
282
|
+
} : await o.resolve(C(c), e);
|
|
275
283
|
if (i.kind === "vetoed") {
|
|
276
284
|
let e = `${i.code}: ${i.message}`;
|
|
277
285
|
throw t?.onStrategyFailed?.({
|
|
278
286
|
strategyId: s.id,
|
|
279
287
|
reason: e
|
|
280
|
-
}), new
|
|
288
|
+
}), new x({ reason: e });
|
|
281
289
|
}
|
|
282
290
|
if (i.kind === "unavailable") {
|
|
283
291
|
let e = `scope resolution unavailable: ${i.reason}`;
|
|
284
292
|
throw t?.onStrategyFailed?.({
|
|
285
293
|
strategyId: s.id,
|
|
286
294
|
reason: e
|
|
287
|
-
}), new
|
|
295
|
+
}), new x({ reason: e });
|
|
288
296
|
}
|
|
289
|
-
let d =
|
|
297
|
+
let d = S(c, i);
|
|
290
298
|
a && d.removed.length > 0 && t?.onScopesNarrowed?.({
|
|
291
299
|
strategyId: s.id,
|
|
292
300
|
subjectType: c.type,
|
|
@@ -315,62 +323,63 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
315
323
|
credentialRejected: u
|
|
316
324
|
} : e };
|
|
317
325
|
}
|
|
318
|
-
if (u !== void 0) throw new
|
|
319
|
-
|
|
320
|
-
let d = l.headers["x-tenant"] ?? t?.anonymousTenantDefault ?? null;
|
|
321
|
-
if (d === null && t?.anonymousTenantRequired === !0) throw new C({ reason: "tenant required (x-tenant header missing)" });
|
|
322
|
-
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"])) };
|
|
323
328
|
};
|
|
324
|
-
},
|
|
325
|
-
if (e.type === "anonymous") throw new
|
|
326
|
-
},
|
|
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", {
|
|
327
332
|
required: n.String,
|
|
328
333
|
message: n.String
|
|
329
|
-
}) {},
|
|
330
|
-
|
|
331
|
-
|
|
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) => {
|
|
332
341
|
if (typeof e == "object" && e) {
|
|
333
|
-
let t =
|
|
342
|
+
let t = I.get(e);
|
|
334
343
|
if (t) return t;
|
|
335
344
|
}
|
|
336
|
-
return
|
|
337
|
-
},
|
|
338
|
-
let n =
|
|
345
|
+
return F(e);
|
|
346
|
+
}, R = (e, t) => {
|
|
347
|
+
let n = L(e);
|
|
339
348
|
return n.includes("admin:full") || n.includes(t);
|
|
340
|
-
},
|
|
341
|
-
let n =
|
|
349
|
+
}, Se = (e, t) => {
|
|
350
|
+
let n = F(e);
|
|
342
351
|
return n.includes("admin:full") || n.includes(t);
|
|
343
|
-
},
|
|
352
|
+
}, Ce = (e, n) => R(e, n) ? t.void : t.fail(new N({
|
|
344
353
|
required: n,
|
|
345
354
|
message: `missing required scope '${n}'`
|
|
346
|
-
})),
|
|
355
|
+
})), z = (e, t) => {
|
|
347
356
|
let n;
|
|
348
357
|
try {
|
|
349
358
|
n = typeof e.action == "function" ? e.action(t) : e.action;
|
|
350
359
|
} catch {
|
|
351
|
-
throw new
|
|
360
|
+
throw new N({
|
|
352
361
|
required: e.resourceType,
|
|
353
362
|
message: "policy action selector failed"
|
|
354
363
|
});
|
|
355
364
|
}
|
|
356
|
-
if (typeof n != "string" || n.trim() === "") throw new
|
|
365
|
+
if (typeof n != "string" || n.trim() === "") throw new N({
|
|
357
366
|
required: e.resourceType,
|
|
358
367
|
message: "policy action selector returned no action"
|
|
359
368
|
});
|
|
360
369
|
return n;
|
|
361
|
-
},
|
|
362
|
-
let n =
|
|
363
|
-
if (e.type === "service") return n !== void 0 && n.includes(e.service) ? null : new
|
|
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({
|
|
364
373
|
required: "service-procedure",
|
|
365
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(", ")}]`
|
|
366
375
|
});
|
|
367
|
-
if (n !== void 0) return
|
|
376
|
+
if (n !== void 0) return Z(e, new N({
|
|
368
377
|
required: `service:${n.join("|")}`,
|
|
369
378
|
message: `this procedure is callable only by the service${n.length === 1 ? "" : "s"} [${n.join(", ")}]`
|
|
370
379
|
}));
|
|
371
|
-
},
|
|
372
|
-
|
|
373
|
-
},
|
|
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) => [
|
|
374
383
|
`${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
|
|
375
384
|
...e.slice(0, 10).map((e) => ` ${e}`),
|
|
376
385
|
...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
|
|
@@ -384,59 +393,59 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
384
393
|
" • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
|
|
385
394
|
" subject hold `req.scope` on `req.resource`\" from your own tables.",
|
|
386
395
|
" • Drop the `resource` extractor if a global scope check is what you meant."
|
|
387
|
-
].join("\n"),
|
|
388
|
-
|
|
389
|
-
},
|
|
396
|
+
].join("\n"), Ae = () => q, J, je = (e) => {
|
|
397
|
+
J = e;
|
|
398
|
+
}, Y = () => J, X = (e) => new N({
|
|
390
399
|
required: "access-decision",
|
|
391
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>'\`.`
|
|
392
|
-
}),
|
|
401
|
+
}), Z = (e, t) => {
|
|
393
402
|
let n = e.credentialRejected;
|
|
394
|
-
return n === void 0 ? t : new
|
|
395
|
-
},
|
|
396
|
-
let r =
|
|
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);
|
|
397
406
|
if (r !== void 0) return r;
|
|
398
|
-
if (!t || t.length === 0) return n?.defaultDeny === !0 ?
|
|
407
|
+
if (!t || t.length === 0) return n?.defaultDeny === !0 ? X(n.procedure) : null;
|
|
399
408
|
for (let n of t) {
|
|
400
|
-
if (
|
|
401
|
-
if (
|
|
409
|
+
if (V(n) || H(n)) continue;
|
|
410
|
+
if (G(n)) {
|
|
402
411
|
if (e.id !== null && e.id !== void 0) continue;
|
|
403
|
-
return
|
|
412
|
+
return Z(e, new N({
|
|
404
413
|
required: "authenticated",
|
|
405
414
|
message: "this procedure requires an authenticated caller"
|
|
406
415
|
}));
|
|
407
416
|
}
|
|
408
|
-
if (
|
|
409
|
-
if (
|
|
410
|
-
return
|
|
417
|
+
if (B(n)) {
|
|
418
|
+
if (R(e, "admin:full")) continue;
|
|
419
|
+
return Z(e, new N({
|
|
411
420
|
required: `${n.resourceType}:${n.action}`,
|
|
412
421
|
message: `relationship guard '${n.action}' on '${n.resourceType}' cannot be checked synchronously`
|
|
413
422
|
}));
|
|
414
423
|
}
|
|
415
|
-
let t =
|
|
424
|
+
let t = K(n.scope);
|
|
416
425
|
if (t.length === 0) continue;
|
|
417
|
-
let r = t.filter((t) =>
|
|
426
|
+
let r = t.filter((t) => R(e, t));
|
|
418
427
|
if (!((n.mode ?? "all") === "any" ? r.length > 0 : r.length === t.length)) {
|
|
419
|
-
let r = (n.mode ?? "all") === "any" ? t[0] : t.find((t) => !
|
|
420
|
-
return
|
|
428
|
+
let r = (n.mode ?? "all") === "any" ? t[0] : t.find((t) => !R(e, t));
|
|
429
|
+
return Z(e, new N({
|
|
421
430
|
required: r,
|
|
422
431
|
message: (n.mode ?? "all") === "any" ? `missing all of required scopes [${t.join(", ")}]` : `missing required scope '${r}'`
|
|
423
432
|
}));
|
|
424
433
|
}
|
|
425
434
|
}
|
|
426
435
|
return null;
|
|
427
|
-
},
|
|
436
|
+
}, Me = (e, n, r) => {
|
|
428
437
|
let i;
|
|
429
438
|
try {
|
|
430
|
-
i =
|
|
439
|
+
i = z(n, r);
|
|
431
440
|
} catch (e) {
|
|
432
441
|
return t.succeed(e);
|
|
433
442
|
}
|
|
434
|
-
let a = (e) => new
|
|
443
|
+
let a = (e) => new N({
|
|
435
444
|
required: `${n.resourceType}:${i}`,
|
|
436
445
|
message: e
|
|
437
446
|
});
|
|
438
|
-
if (
|
|
439
|
-
let o =
|
|
447
|
+
if (R(e, "admin:full")) return t.succeed(null);
|
|
448
|
+
let o = J;
|
|
440
449
|
if (o === void 0) return t.succeed(a(`no policy resolver registered — cannot authorize '${i}' on '${n.resourceType}'`));
|
|
441
450
|
let s = n.resource(r);
|
|
442
451
|
return s === void 0 || s === "" ? t.succeed(a(`input does not identify a '${n.resourceType}' to authorize`)) : t.suspend(() => o({
|
|
@@ -444,32 +453,36 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
444
453
|
action: i,
|
|
445
454
|
resourceType: n.resourceType,
|
|
446
455
|
resourceId: s
|
|
447
|
-
})).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((
|
|
448
|
-
},
|
|
449
|
-
|
|
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);
|
|
450
463
|
if (a !== void 0) return t.succeed(a);
|
|
451
|
-
if (!n || n.length === 0) return t.succeed(
|
|
452
|
-
let o =
|
|
453
|
-
return !n.some(
|
|
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* () {
|
|
454
467
|
for (let i of n) {
|
|
455
|
-
if (
|
|
456
|
-
if (
|
|
468
|
+
if (V(i) || H(i)) continue;
|
|
469
|
+
if (G(i)) {
|
|
457
470
|
if (e.id !== null && e.id !== void 0) continue;
|
|
458
|
-
return
|
|
471
|
+
return Z(e, new N({
|
|
459
472
|
required: "authenticated",
|
|
460
473
|
message: "this procedure requires an authenticated caller"
|
|
461
474
|
}));
|
|
462
475
|
}
|
|
463
|
-
if (
|
|
464
|
-
let t = yield*
|
|
476
|
+
if (B(i)) {
|
|
477
|
+
let t = yield* Me(e, i, r);
|
|
465
478
|
if (t) return t;
|
|
466
479
|
continue;
|
|
467
480
|
}
|
|
468
|
-
let n =
|
|
481
|
+
let n = K(i.scope);
|
|
469
482
|
if (n.length === 0) continue;
|
|
470
|
-
let a = i.resource ? i.resource(r) : void 0, s = [];
|
|
483
|
+
let a = i.resource ? i.resource(r) : void 0, s = [], c = !1;
|
|
471
484
|
for (let r of n) {
|
|
472
|
-
if (
|
|
485
|
+
if (R(e, r)) {
|
|
473
486
|
s.push(!0);
|
|
474
487
|
continue;
|
|
475
488
|
}
|
|
@@ -479,15 +492,22 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
479
492
|
scope: r,
|
|
480
493
|
resource: a
|
|
481
494
|
})).pipe(t.catchAllCause(() => t.succeed(!1)));
|
|
482
|
-
s.push(n);
|
|
495
|
+
n === "missing" && (c = !0), s.push(n === !0);
|
|
483
496
|
} else s.push(!1);
|
|
484
497
|
}
|
|
485
|
-
let
|
|
486
|
-
if (!(
|
|
487
|
-
let
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
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}'`)
|
|
491
511
|
});
|
|
492
512
|
}
|
|
493
513
|
}
|
|
@@ -495,4 +515,4 @@ var i = (e) => e.type === "user" || e.type === "apiKey" || e.type === "serviceAc
|
|
|
495
515
|
});
|
|
496
516
|
};
|
|
497
517
|
//#endregion
|
|
498
|
-
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
|
*
|