@voltro/protocol 0.70.0 → 0.71.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 +1289 -111
- package/dist/apikey.d.ts +5 -0
- package/dist/index.d.ts +450 -12
- package/dist/index.js +598 -558
- package/dist/inspect.d.ts +100 -0
- package/dist/inspect.js +160 -0
- package/dist/jwt.d.ts +5 -0
- package/dist/rest.d.ts +111 -6
- package/dist/rest.js +310 -221
- package/dist/{restFormat-Bnngx-zI.js → restFormat-ChSVyufA.js} +93 -38
- package/dist/{scopes-DVtiKKsm.js → scopes-CW9_LbDO.js} +69 -40
- package/dist/session.d.ts +11 -0
- package/dist/session.js +6 -6
- package/package.json +9 -4
|
@@ -51,13 +51,68 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
51
51
|
get message() {
|
|
52
52
|
return `a request with this idempotency key is still in flight — replay the same key after ${this.retryAfterMs}ms`;
|
|
53
53
|
}
|
|
54
|
-
}, d = 1e3, f =
|
|
55
|
-
|
|
54
|
+
}, d = 1e3, f = (e) => typeof e == "object" && !!e && typeof e._tag == "string", p = 64, m = (e, t = 0) => {
|
|
55
|
+
if (!f(e)) return String(e);
|
|
56
|
+
if (t >= p) return "…";
|
|
57
|
+
let n = t + 1, r = (t) => m(e[t], n), i = (t) => Array.isArray(e[t]) ? e[t] : [];
|
|
58
|
+
switch (e._tag) {
|
|
59
|
+
case "Transformation": return `T(${r("from")}->${r("to")})`;
|
|
60
|
+
case "Refinement": return `R(${r("from")})`;
|
|
61
|
+
case "Suspend": return "S(…)";
|
|
62
|
+
case "TypeLiteral": {
|
|
63
|
+
let e = i("propertySignatures").map((e) => {
|
|
64
|
+
let t = e;
|
|
65
|
+
return `${String(t.name)}${t.isOptional === !0 ? "?" : ""}:${m(t.type, n)}`;
|
|
66
|
+
}).join(","), t = i("indexSignatures").map((e) => {
|
|
67
|
+
let t = e;
|
|
68
|
+
return `[${m(t.parameter, n)}]:${m(t.type, n)}`;
|
|
69
|
+
}).join(",");
|
|
70
|
+
return t === "" ? `{${e}}` : `{${e};${t}}`;
|
|
71
|
+
}
|
|
72
|
+
case "Union": return `U(${i("types").map((e) => m(e, n)).join("|")})`;
|
|
73
|
+
case "TupleType": {
|
|
74
|
+
let e = i("elements").map((e) => {
|
|
75
|
+
let t = e;
|
|
76
|
+
return `${m(t.type, n)}${t.isOptional === !0 ? "?" : ""}`;
|
|
77
|
+
}).join(","), t = i("rest").map((e) => m(e.type, n)).join(",");
|
|
78
|
+
return `A(${e}${t === "" ? "" : `...${t}`})`;
|
|
79
|
+
}
|
|
80
|
+
case "Declaration": return `D(${i("typeParameters").map((e) => m(e, n)).join(",")})`;
|
|
81
|
+
default: return String(e);
|
|
82
|
+
}
|
|
83
|
+
}, h = (e) => {
|
|
84
|
+
let t = 2166136261;
|
|
85
|
+
for (let n = 0; n < e.length; n++) t ^= e.charCodeAt(n), t = Math.imul(t, 16777619) >>> 0;
|
|
86
|
+
return t.toString(16).padStart(8, "0");
|
|
87
|
+
}, g = (e) => h([
|
|
88
|
+
m(e.payloadSchema?.ast),
|
|
89
|
+
m(e.successSchema?.ast),
|
|
90
|
+
m(e.errorSchema?.ast)
|
|
91
|
+
].join("\0")), _ = (e) => {
|
|
92
|
+
let t = {}, n = e.requests, r = n instanceof Map ? n.entries() : Array.isArray(n) ? n.map((e, t) => [t, e]) : [];
|
|
93
|
+
for (let [, e] of r) {
|
|
94
|
+
if (typeof e != "object" && typeof e != "function" || e === null) continue;
|
|
95
|
+
let n = e;
|
|
96
|
+
typeof n._tag == "string" && (t[n._tag] = g(n));
|
|
97
|
+
}
|
|
98
|
+
return t;
|
|
99
|
+
}, v = (e, t) => {
|
|
100
|
+
let n = [], r = [];
|
|
101
|
+
for (let [i, a] of Object.entries(t)) {
|
|
102
|
+
let t = e[i];
|
|
103
|
+
t === void 0 ? r.push(i) : t !== a && n.push(i);
|
|
104
|
+
}
|
|
105
|
+
return {
|
|
106
|
+
differing: n.sort(),
|
|
107
|
+
missingHere: r.sort()
|
|
108
|
+
};
|
|
109
|
+
}, y = /* @__PURE__ */ new Set(), b = (e) => {
|
|
110
|
+
for (let t of y) try {
|
|
56
111
|
t(e);
|
|
57
112
|
} catch {}
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
}),
|
|
113
|
+
}, x = (e) => (y.add(e), () => {
|
|
114
|
+
y.delete(e);
|
|
115
|
+
}), S = {
|
|
61
116
|
rpc: {
|
|
62
117
|
name: "rpc",
|
|
63
118
|
dates: "epoch-ms",
|
|
@@ -91,16 +146,16 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
91
146
|
naming: "camelCase",
|
|
92
147
|
etag: !0
|
|
93
148
|
}
|
|
94
|
-
},
|
|
149
|
+
}, C = [
|
|
95
150
|
"rpc",
|
|
96
151
|
"standard",
|
|
97
152
|
"jsonapi"
|
|
98
|
-
],
|
|
153
|
+
], w = (e, t = void 0) => {
|
|
99
154
|
let n = (e) => {
|
|
100
155
|
if (e?.profile !== void 0) {
|
|
101
156
|
if (typeof e.profile == "string") {
|
|
102
|
-
let t =
|
|
103
|
-
if (t === void 0) throw Error(`publicApi.profile: unknown profile '${String(e.profile)}' — one of ${
|
|
157
|
+
let t = S[e.profile];
|
|
158
|
+
if (t === void 0) throw Error(`publicApi.profile: unknown profile '${String(e.profile)}' — one of ${C.join(", ")}, or a RestFormat object`);
|
|
104
159
|
return t;
|
|
105
160
|
}
|
|
106
161
|
return e.profile;
|
|
@@ -115,14 +170,14 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
115
170
|
...t.cursorParam === void 0 ? {} : { cursorParam: t.cursorParam },
|
|
116
171
|
...t.naming === void 0 ? {} : { naming: t.naming },
|
|
117
172
|
...t.etag === void 0 ? {} : { etag: t.etag }
|
|
118
|
-
}, i = r(n(e) ??
|
|
173
|
+
}, i = r(n(e) ?? S.rpc, e);
|
|
119
174
|
return r(n(t) ?? i, t);
|
|
120
|
-
},
|
|
175
|
+
}, T = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase(), E = (e, t) => {
|
|
121
176
|
if (typeof e != "object" || !e || Array.isArray(e)) return e;
|
|
122
177
|
let n = {};
|
|
123
178
|
for (let [r, i] of Object.entries(e)) n[t(r)] = i;
|
|
124
179
|
return n;
|
|
125
|
-
},
|
|
180
|
+
}, D = (e) => n.getOrUndefined(t.getIdentifierAnnotation(e)), O = (n, r) => {
|
|
126
181
|
if (r.dates === "epoch-ms" && r.naming === "camelCase") return n;
|
|
127
182
|
let i = /* @__PURE__ */ new Map(), a = (e) => {
|
|
128
183
|
let t = i.get(e);
|
|
@@ -132,7 +187,7 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
132
187
|
}, o = (n) => {
|
|
133
188
|
switch (n._tag) {
|
|
134
189
|
case "Transformation":
|
|
135
|
-
if (r.dates === "iso" &&
|
|
190
|
+
if (r.dates === "iso" && D(n) === "DateFromNumber") {
|
|
136
191
|
let r = e.DateFromString.ast;
|
|
137
192
|
return new t.Transformation(r.from, r.to, r.transformation, {
|
|
138
193
|
...r.annotations,
|
|
@@ -150,43 +205,43 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
150
205
|
case "TupleType": return new t.TupleType(n.elements.map((e) => new t.OptionalType(a(e.type), e.isOptional, e.annotations)), n.rest.map((e) => new t.Type(a(e.type), e.annotations)), n.isReadonly, n.annotations);
|
|
151
206
|
case "Suspend": return new t.Suspend(() => a(n.f()), n.annotations);
|
|
152
207
|
case "TypeLiteral": {
|
|
153
|
-
let i = n.propertySignatures.map((e) => new t.PropertySignature(e.name, a(e.type), e.isOptional, e.isReadonly, e.annotations)), o = new t.TypeLiteral(i,
|
|
154
|
-
if (r.naming !== "snake_case") return
|
|
155
|
-
let
|
|
156
|
-
if (
|
|
157
|
-
let
|
|
158
|
-
return e.transform(e.make(
|
|
208
|
+
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);
|
|
209
|
+
if (r.naming !== "snake_case") return s;
|
|
210
|
+
let c = i.map((e) => typeof e.name == "string" ? T(e.name) : e.name);
|
|
211
|
+
if (c.every((e, t) => e === i[t].name)) return s;
|
|
212
|
+
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])]));
|
|
213
|
+
return e.transform(e.make(l), e.make(s), {
|
|
159
214
|
strict: !1,
|
|
160
|
-
decode: (e) =>
|
|
161
|
-
encode: (e) =>
|
|
215
|
+
decode: (e) => E(e, (e) => u.get(e) ?? e),
|
|
216
|
+
encode: (e) => E(e, (e) => d.get(e) ?? e)
|
|
162
217
|
}).ast;
|
|
163
218
|
}
|
|
164
219
|
default: return n;
|
|
165
220
|
}
|
|
166
221
|
};
|
|
167
222
|
return e.make(a(n.ast));
|
|
168
|
-
},
|
|
169
|
-
type:
|
|
170
|
-
title:
|
|
223
|
+
}, k = (e) => `urn:voltro:error:${e}`, A = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1 $2").replace(/([A-Z])([A-Z][a-z])/g, "$1 $2"), j = (e) => ({
|
|
224
|
+
type: k(e.tag),
|
|
225
|
+
title: A(e.tag),
|
|
171
226
|
status: e.status,
|
|
172
227
|
...e.message.length > 0 ? { detail: e.message } : {},
|
|
173
228
|
...e.fields
|
|
174
|
-
}),
|
|
229
|
+
}), M = "application/problem+json; charset=utf-8", N = "application/vnd.api+json; charset=utf-8", P = (e, t, n) => e.encodeError === void 0 ? e.errors === "problem-details" ? e.envelope === "jsonapi" ? {
|
|
175
230
|
body: { errors: [{
|
|
176
231
|
status: String(t.status),
|
|
177
232
|
code: t.tag,
|
|
178
|
-
title:
|
|
233
|
+
title: A(t.tag),
|
|
179
234
|
...t.message.length > 0 ? { detail: t.message } : {},
|
|
180
235
|
...Object.keys(t.fields).length > 0 ? { meta: t.fields } : {}
|
|
181
236
|
}] },
|
|
182
|
-
contentType:
|
|
237
|
+
contentType: N
|
|
183
238
|
} : {
|
|
184
|
-
body:
|
|
185
|
-
contentType:
|
|
239
|
+
body: j(t),
|
|
240
|
+
contentType: M
|
|
186
241
|
} : { body: {
|
|
187
242
|
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,
|
|
188
243
|
...t.fields
|
|
189
|
-
} } : e.encodeError(t, n),
|
|
244
|
+
} } : e.encodeError(t, n), F = (e, t) => {
|
|
190
245
|
if (typeof e != "object" || !e || Array.isArray(e)) return {
|
|
191
246
|
cursor: void 0,
|
|
192
247
|
rest: e
|
|
@@ -199,10 +254,10 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
199
254
|
cursor: String(n),
|
|
200
255
|
rest: e
|
|
201
256
|
};
|
|
202
|
-
},
|
|
257
|
+
}, I = (e, t, n) => {
|
|
203
258
|
let r = new URLSearchParams(e.query);
|
|
204
259
|
return r.set(n, t), `<${e.path}?${r.toString()}>; rel="next"`;
|
|
205
|
-
},
|
|
260
|
+
}, L = (e, t) => {
|
|
206
261
|
if (typeof e != "object" || !e || Array.isArray(e)) return e;
|
|
207
262
|
let { id: n, ...r } = e;
|
|
208
263
|
return {
|
|
@@ -210,9 +265,9 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
210
265
|
...n === void 0 ? {} : { id: String(n) },
|
|
211
266
|
attributes: r
|
|
212
267
|
};
|
|
213
|
-
},
|
|
268
|
+
}, R = (e, t, n) => {
|
|
214
269
|
if (e.encodeSuccess !== void 0) return e.encodeSuccess(t, n);
|
|
215
|
-
let { cursor: r } =
|
|
270
|
+
let { cursor: r } = F(t, e.cursorField), i = e.pagination === "link-header" && r !== void 0 ? { Link: I(n, r, e.cursorParam) } : void 0, a = (e, t) => ({
|
|
216
271
|
body: e,
|
|
217
272
|
...i ? { headers: i } : {},
|
|
218
273
|
...t ? { contentType: t } : {}
|
|
@@ -224,9 +279,9 @@ var r = (e, t, n) => `${e ?? "(global)"}|${t.toUpperCase()}|${n}`, i = (e, t, n,
|
|
|
224
279
|
});
|
|
225
280
|
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;
|
|
226
281
|
return a({
|
|
227
|
-
data: s === void 0 ?
|
|
228
|
-
...r === void 0 ? {} : { links: { next:
|
|
229
|
-
},
|
|
282
|
+
data: s === void 0 ? L(t, o) : s.map((e) => L(e, o)),
|
|
283
|
+
...r === void 0 ? {} : { links: { next: I(n, r, e.cursorParam).replace(/^<|>; rel="next"$/g, "") } }
|
|
284
|
+
}, N);
|
|
230
285
|
};
|
|
231
286
|
//#endregion
|
|
232
|
-
export { i as
|
|
287
|
+
export { c as C, i as D, l as E, o as S, r as T, m as _, R as a, a as b, k as c, T as d, b as f, g, _ as h, P as i, w as l, v as m, M as n, I as o, x as p, C as r, j as s, N as t, O as u, h as v, s as w, u as x, d as y };
|
|
@@ -20,6 +20,7 @@ var i = n.Record({
|
|
|
20
20
|
type: n.Literal("serviceAccount"),
|
|
21
21
|
id: n.String,
|
|
22
22
|
tenantId: n.String,
|
|
23
|
+
auditActorId: n.optionalWith(n.NullOr(n.String), { exact: !0 }),
|
|
23
24
|
scopes: a,
|
|
24
25
|
metadata: n.optional(i)
|
|
25
26
|
}), l = n.Struct({
|
|
@@ -42,24 +43,31 @@ var i = n.Record({
|
|
|
42
43
|
id: null,
|
|
43
44
|
tenantId: e,
|
|
44
45
|
...t === void 0 ? {} : { credentialRejected: t }
|
|
45
|
-
}),
|
|
46
|
+
}), g = (e, t = ["admin:full"]) => ({
|
|
46
47
|
type: "system",
|
|
47
48
|
id: e,
|
|
48
49
|
tenantId: null,
|
|
49
50
|
scopes: t
|
|
50
|
-
}),
|
|
51
|
+
}), _ = (e) => {
|
|
52
|
+
if (e.type === "system") return null;
|
|
53
|
+
if (e.type === "serviceAccount" && e.auditActorId !== void 0) return e.auditActorId;
|
|
54
|
+
if (e.type !== "apiKey") return e.id;
|
|
55
|
+
let t = e.metadata?.userId;
|
|
56
|
+
return typeof t == "string" && t !== "" ? t : e.id;
|
|
57
|
+
}, ee = (e, t) => {
|
|
51
58
|
let n = e;
|
|
52
59
|
return {
|
|
53
60
|
type: "serviceAccount",
|
|
54
61
|
id: e.id ?? "system",
|
|
55
62
|
tenantId: t,
|
|
56
|
-
|
|
63
|
+
auditActorId: _(e),
|
|
64
|
+
scopes: m(e),
|
|
57
65
|
...n.metadata === void 0 ? {} : { metadata: n.metadata }
|
|
58
66
|
};
|
|
59
|
-
},
|
|
67
|
+
}, te = (e) => e.type === "system", ne = "impersonation", v = (e) => e.metadata?.impersonation ?? null, y = class extends e.Tag("@voltro/Subject")() {}, b = class extends e.Tag("@voltro/ConnectionInfo")() {}, x = class extends r.Tag()("@voltro/AuthMiddleware", { provides: y }) {}, S = class extends r.Tag()("@voltro/ConnectionInfoMiddleware", { provides: b }) {}, C = (e) => typeof e.mountRoutes == "function", w = (e) => Array.isArray(e) ? {
|
|
60
68
|
kind: "grant",
|
|
61
69
|
scopes: e
|
|
62
|
-
} : e,
|
|
70
|
+
} : e, T = (e, t) => {
|
|
63
71
|
if (t.kind === "vetoed") throw new k({ reason: `${t.code}: ${t.message}` });
|
|
64
72
|
if (e.type === "anonymous") return {
|
|
65
73
|
subject: e,
|
|
@@ -88,13 +96,13 @@ var i = n.Record({
|
|
|
88
96
|
},
|
|
89
97
|
removed: i
|
|
90
98
|
};
|
|
91
|
-
}, re = 3e4, ie = 1e4,
|
|
99
|
+
}, re = 3e4, ie = 1e4, E = (e) => `${e.type}\u0000${e.tenantId ?? ""}\u0000${e.id ?? ""}`, ae = () => {
|
|
92
100
|
if (typeof process > "u") return;
|
|
93
101
|
let e = process.env.VOLTRO_AUTH_SCOPE_CACHE_TTL_MS;
|
|
94
102
|
if (e === void 0 || e === "") return;
|
|
95
103
|
let t = Number(e);
|
|
96
104
|
return Number.isFinite(t) && t >= 0 ? t : void 0;
|
|
97
|
-
},
|
|
105
|
+
}, D = (e = {}) => {
|
|
98
106
|
let t = e.ttlMs ?? ae() ?? 3e4, n = e.maxEntries ?? 1e4, r = e.now ?? Date.now, i = /* @__PURE__ */ new Map(), a = () => {
|
|
99
107
|
if (i.size <= n) return;
|
|
100
108
|
let e = r();
|
|
@@ -134,21 +142,21 @@ var i = n.Record({
|
|
|
134
142
|
}, oe = (e) => typeof e.resolve == "function", se = (e) => {
|
|
135
143
|
let t = e.authorization ?? e.Authorization;
|
|
136
144
|
if (t !== void 0) return /^Bearer\s+(.+)$/i.exec(t.trim())?.[1]?.trim();
|
|
137
|
-
},
|
|
145
|
+
}, O = (e, t) => {
|
|
138
146
|
let n = se(t);
|
|
139
147
|
if (n === void 0) return e;
|
|
140
148
|
let r = e.filter((e) => e.claimsBearerPrefix !== void 0 && e.claimsBearerPrefix !== "" && n.startsWith(e.claimsBearerPrefix));
|
|
141
149
|
if (r.length === 0) return e;
|
|
142
150
|
let i = new Set(r);
|
|
143
151
|
return [...r, ...e.filter((e) => !i.has(e))];
|
|
144
|
-
},
|
|
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 :
|
|
152
|
+
}, ce = (e, t) => {
|
|
153
|
+
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 : D(t?.scopeCache ?? {});
|
|
146
154
|
return async (o) => {
|
|
147
155
|
let s = t?.getStore?.(), c = s === void 0 ? o : {
|
|
148
156
|
...o,
|
|
149
157
|
store: s
|
|
150
158
|
}, l;
|
|
151
|
-
for (let o of
|
|
159
|
+
for (let o of O(e, c.headers)) {
|
|
152
160
|
let e = await o.resolve(c);
|
|
153
161
|
if (e.kind === "matched") {
|
|
154
162
|
let s = e.subject;
|
|
@@ -157,9 +165,9 @@ var i = n.Record({
|
|
|
157
165
|
let t = n === void 0 ? {
|
|
158
166
|
kind: "grant",
|
|
159
167
|
scopes: []
|
|
160
|
-
} :
|
|
168
|
+
} : w(await n(e.subject, c));
|
|
161
169
|
if (t.kind === "unavailable" || r.length === 0) return t;
|
|
162
|
-
let i =
|
|
170
|
+
let i = T(e.subject, t).subject, a = {
|
|
163
171
|
origin: "request",
|
|
164
172
|
headers: c.headers,
|
|
165
173
|
clientId: c.clientId,
|
|
@@ -177,7 +185,7 @@ var i = n.Record({
|
|
|
177
185
|
}, { decision: l, fresh: u } = a === null ? {
|
|
178
186
|
decision: await i(),
|
|
179
187
|
fresh: !0
|
|
180
|
-
} : await a.resolve(
|
|
188
|
+
} : await a.resolve(E(e.subject), i);
|
|
181
189
|
if (l.kind === "vetoed") {
|
|
182
190
|
let e = `${l.code}: ${l.message}`;
|
|
183
191
|
throw t?.onStrategyFailed?.({
|
|
@@ -192,7 +200,7 @@ var i = n.Record({
|
|
|
192
200
|
reason: e
|
|
193
201
|
}), new k({ reason: e });
|
|
194
202
|
}
|
|
195
|
-
let d =
|
|
203
|
+
let d = T(e.subject, l);
|
|
196
204
|
u && d.removed.length > 0 && t?.onScopesNarrowed?.({
|
|
197
205
|
strategyId: o.id,
|
|
198
206
|
subjectType: e.subject.type,
|
|
@@ -245,9 +253,24 @@ var i = n.Record({
|
|
|
245
253
|
}, H = (e, n) => B(e, n) ? t.void : t.fail(new F({
|
|
246
254
|
required: n,
|
|
247
255
|
message: `missing required scope '${n}'`
|
|
248
|
-
})), U = (e
|
|
256
|
+
})), U = (e, t) => {
|
|
257
|
+
let n;
|
|
258
|
+
try {
|
|
259
|
+
n = typeof e.action == "function" ? e.action(t) : e.action;
|
|
260
|
+
} catch {
|
|
261
|
+
throw new F({
|
|
262
|
+
required: e.resourceType,
|
|
263
|
+
message: "policy action selector failed"
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
if (typeof n != "string" || n.trim() === "") throw new F({
|
|
267
|
+
required: e.resourceType,
|
|
268
|
+
message: "policy action selector returned no action"
|
|
269
|
+
});
|
|
270
|
+
return n;
|
|
271
|
+
}, 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, le = (e) => ({ open: e }), q = (e) => typeof e == "string" ? [e] : e, J, ue = (e) => {
|
|
249
272
|
J = e;
|
|
250
|
-
},
|
|
273
|
+
}, Y = (e) => J === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !W(e) && e.resource !== void 0)).map((e) => e.tag) : [], de = (e) => [
|
|
251
274
|
`${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
|
|
252
275
|
...e.slice(0, 10).map((e) => ` ${e}`),
|
|
253
276
|
...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
|
|
@@ -261,9 +284,9 @@ var i = n.Record({
|
|
|
261
284
|
" • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
|
|
262
285
|
" subject hold `req.scope` on `req.resource`\" from your own tables.",
|
|
263
286
|
" • Drop the `resource` extractor if a global scope check is what you meant."
|
|
264
|
-
].join("\n"),
|
|
265
|
-
|
|
266
|
-
},
|
|
287
|
+
].join("\n"), fe = () => J, X, pe = (e) => {
|
|
288
|
+
X = e;
|
|
289
|
+
}, me = () => X, Z = (e) => new F({
|
|
267
290
|
required: "access-decision",
|
|
268
291
|
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>'\`.`
|
|
269
292
|
}), Q = (e, t) => {
|
|
@@ -272,15 +295,15 @@ var i = n.Record({
|
|
|
272
295
|
}, $ = (e, t, n) => {
|
|
273
296
|
if (!t || t.length === 0) return n?.defaultDeny === !0 ? Z(n.procedure) : null;
|
|
274
297
|
for (let n of t) {
|
|
275
|
-
if (
|
|
276
|
-
if (
|
|
298
|
+
if (G(n)) continue;
|
|
299
|
+
if (K(n)) {
|
|
277
300
|
if (e.id !== null && e.id !== void 0) continue;
|
|
278
301
|
return Q(e, new F({
|
|
279
302
|
required: "authenticated",
|
|
280
303
|
message: "this procedure requires an authenticated caller"
|
|
281
304
|
}));
|
|
282
305
|
}
|
|
283
|
-
if (
|
|
306
|
+
if (W(n)) {
|
|
284
307
|
if (B(e, "admin:full")) continue;
|
|
285
308
|
return Q(e, new F({
|
|
286
309
|
required: `${n.resourceType}:${n.action}`,
|
|
@@ -299,36 +322,42 @@ var i = n.Record({
|
|
|
299
322
|
}
|
|
300
323
|
}
|
|
301
324
|
return null;
|
|
302
|
-
},
|
|
303
|
-
let i
|
|
304
|
-
|
|
325
|
+
}, he = (e, n, r) => {
|
|
326
|
+
let i;
|
|
327
|
+
try {
|
|
328
|
+
i = U(n, r);
|
|
329
|
+
} catch (e) {
|
|
330
|
+
return t.succeed(e);
|
|
331
|
+
}
|
|
332
|
+
let a = (e) => new F({
|
|
333
|
+
required: `${n.resourceType}:${i}`,
|
|
305
334
|
message: e
|
|
306
335
|
});
|
|
307
336
|
if (B(e, "admin:full")) return t.succeed(null);
|
|
308
|
-
let
|
|
309
|
-
if (
|
|
310
|
-
let
|
|
311
|
-
return
|
|
337
|
+
let o = X;
|
|
338
|
+
if (o === void 0) return t.succeed(a(`no policy resolver registered — cannot authorize '${i}' on '${n.resourceType}'`));
|
|
339
|
+
let s = n.resource(r);
|
|
340
|
+
return s === void 0 || s === "" ? t.succeed(a(`input does not identify a '${n.resourceType}' to authorize`)) : t.suspend(() => o({
|
|
312
341
|
subject: e,
|
|
313
|
-
action:
|
|
342
|
+
action: i,
|
|
314
343
|
resourceType: n.resourceType,
|
|
315
|
-
resourceId:
|
|
316
|
-
})).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((e) => e ? null :
|
|
317
|
-
},
|
|
344
|
+
resourceId: s
|
|
345
|
+
})).pipe(t.catchAllCause(() => t.succeed(!1)), t.map((e) => e ? null : a(`no '${i}' relation on ${n.resourceType}:${s}`)));
|
|
346
|
+
}, ge = (e, n, r, i) => {
|
|
318
347
|
if (!n || n.length === 0) return t.succeed($(e, n, i));
|
|
319
348
|
let a = J;
|
|
320
|
-
return !n.some(
|
|
349
|
+
return !n.some(W) && (!a || !n.some((e) => e.resource !== void 0)) ? t.succeed($(e, n, i)) : t.gen(function* () {
|
|
321
350
|
for (let i of n) {
|
|
322
|
-
if (
|
|
323
|
-
if (
|
|
351
|
+
if (G(i)) continue;
|
|
352
|
+
if (K(i)) {
|
|
324
353
|
if (e.id !== null && e.id !== void 0) continue;
|
|
325
354
|
return Q(e, new F({
|
|
326
355
|
required: "authenticated",
|
|
327
356
|
message: "this procedure requires an authenticated caller"
|
|
328
357
|
}));
|
|
329
358
|
}
|
|
330
|
-
if (
|
|
331
|
-
let t = yield*
|
|
359
|
+
if (W(i)) {
|
|
360
|
+
let t = yield* he(e, i, r);
|
|
332
361
|
if (t) return t;
|
|
333
362
|
continue;
|
|
334
363
|
}
|
|
@@ -362,4 +391,4 @@ var i = n.Record({
|
|
|
362
391
|
});
|
|
363
392
|
};
|
|
364
393
|
//#endregion
|
|
365
|
-
export {
|
|
394
|
+
export { re as A, C as B, pe as C, b as D, x as E, k as F, E as G, D as H, h as I, g as J, _ as K, T as L, d as M, f as N, S as O, y as P, A as R, R as S, I as T, O as U, te as V, v as W, ee as Y, W as _, F as a, H as b, ge as c, me as d, fe as f, G as g, K as h, M as i, ne as j, ie as k, z as l, V as m, N as n, de as o, B as p, p as q, P as r, $ as s, j as t, Y as u, Z as v, ue as w, U as x, le as y, ce as z };
|
package/dist/session.d.ts
CHANGED
|
@@ -176,6 +176,9 @@ declare const SessionPayload_2: Schema.Struct<{
|
|
|
176
176
|
id: typeof Schema.String;
|
|
177
177
|
tenantId: typeof Schema.String;
|
|
178
178
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
179
|
+
auditActorId: Schema.optionalWith<Schema.NullOr<typeof Schema.String>, {
|
|
180
|
+
exact: true;
|
|
181
|
+
}>;
|
|
179
182
|
}>, Schema.Struct<{
|
|
180
183
|
type: Schema.Literal<["anonymous"]>;
|
|
181
184
|
id: typeof Schema.Null;
|
|
@@ -274,6 +277,11 @@ declare const Subject: Schema.Union<[Schema.Struct<{
|
|
|
274
277
|
type: Schema.Literal<["serviceAccount"]>;
|
|
275
278
|
id: typeof Schema.String;
|
|
276
279
|
tenantId: typeof Schema.String;
|
|
280
|
+
/** Application actor used for audit columns; null means machine work with
|
|
281
|
+
* no application actor. Identity only, never a permission grant. */
|
|
282
|
+
auditActorId: Schema.optionalWith<Schema.NullOr<typeof Schema.String>, {
|
|
283
|
+
exact: true;
|
|
284
|
+
}>;
|
|
277
285
|
scopes: Schema.optional<Schema.Array$<typeof Schema.String>>;
|
|
278
286
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
279
287
|
}>, Schema.Struct<{
|
|
@@ -322,6 +330,9 @@ declare const SubjectIdentity: Schema.Union<[Schema.Struct<{
|
|
|
322
330
|
id: typeof Schema.String;
|
|
323
331
|
tenantId: typeof Schema.String;
|
|
324
332
|
metadata: Schema.optional<Schema.Record$<typeof Schema.String, typeof Schema.Unknown>>;
|
|
333
|
+
auditActorId: Schema.optionalWith<Schema.NullOr<typeof Schema.String>, {
|
|
334
|
+
exact: true;
|
|
335
|
+
}>;
|
|
325
336
|
}>, Schema.Struct<{
|
|
326
337
|
type: Schema.Literal<["anonymous"]>;
|
|
327
338
|
id: typeof Schema.Null;
|
package/dist/session.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { N as e, T as t, q as n } from "./scopes-CW9_LbDO.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:
|
|
8
|
+
subject: e,
|
|
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 = (
|
|
41
|
+
} : e, D = (e, 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 =
|
|
45
|
-
if (o.length > 0) throw Error(`signSession: refusing to mint a session cookie for a ${
|
|
44
|
+
let o = t(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.`);
|
|
46
46
|
let s = i.ttlSeconds ?? C, c = Math.floor((i.now ?? Date.now)() / 1e3), l = {
|
|
47
47
|
v: 2,
|
|
48
|
-
subject: e
|
|
48
|
+
subject: n(e),
|
|
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.
|
|
3
|
+
"version": "0.71.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",
|
|
@@ -48,7 +48,12 @@
|
|
|
48
48
|
"import": "./dist/identity.js",
|
|
49
49
|
"default": "./dist/identity.js"
|
|
50
50
|
},
|
|
51
|
-
"./package.json": "./package.json"
|
|
51
|
+
"./package.json": "./package.json",
|
|
52
|
+
"./inspect": {
|
|
53
|
+
"types": "./dist/inspect.d.ts",
|
|
54
|
+
"import": "./dist/inspect.js",
|
|
55
|
+
"default": "./dist/inspect.js"
|
|
56
|
+
}
|
|
52
57
|
},
|
|
53
58
|
"main": "./dist/index.js",
|
|
54
59
|
"module": "./dist/index.js",
|
|
@@ -59,8 +64,8 @@
|
|
|
59
64
|
},
|
|
60
65
|
"dependencies": {
|
|
61
66
|
"@effect/sql": "^0.52.1",
|
|
62
|
-
"@voltro/database": "0.
|
|
63
|
-
"@voltro/logger": "0.
|
|
67
|
+
"@voltro/database": "0.71.0",
|
|
68
|
+
"@voltro/logger": "0.71.0",
|
|
64
69
|
"jose": "^6.2.10"
|
|
65
70
|
},
|
|
66
71
|
"peerDependencies": {
|