@voltro/protocol 0.86.0 → 0.88.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 +5484 -0
- package/THIRD-PARTY-NOTICES.md +3 -227
- package/dist/apiRoleEndpoints.js +107 -0
- package/dist/apiRoleObservation.js +67 -0
- package/dist/apikey.d.ts +10 -0
- package/dist/apikey.js +1 -2
- package/dist/approval.js +1 -2
- package/dist/approvalDescriptors.js +1 -2
- package/dist/auth.js +40 -21
- package/dist/boundedRing.js +1 -2
- package/dist/businessRule.js +1 -2
- package/dist/canonicalJson.js +13 -0
- package/dist/connection.js +1 -2
- package/dist/devActivity.js +1 -2
- package/dist/errorSchema.js +23 -0
- package/dist/errorValue.js +1 -2
- package/dist/event.js +52 -47
- package/dist/formCapture.js +11 -0
- package/dist/httpStreamMaxDuration.js +8 -0
- package/dist/idempotency.js +89 -35
- package/dist/idempotencyInput.js +122 -0
- package/dist/identity.js +1 -2
- package/dist/index.d.ts +876 -124
- package/dist/index.js +51 -40
- package/dist/inspect.d.ts +1 -1
- package/dist/inspect.js +1 -2
- package/dist/inspectBackfill.js +1 -2
- package/dist/inspectCommandRejection.js +1 -2
- package/dist/inspectProjection.js +1 -2
- package/dist/inspectStorageProjection.js +1 -2
- package/dist/inspectValueIdentity.js +1 -2
- package/dist/inspectWorkflowExecution.js +1 -2
- package/dist/inspectWorkflowQueuedStart.js +1 -2
- package/dist/jsonSchema.js +1 -2
- package/dist/jwt.d.ts +10 -0
- package/dist/jwt.js +2 -3
- package/dist/outbox.js +1 -2
- package/dist/pairing.js +1 -2
- package/dist/plugin.js +44 -19
- package/dist/pluginAccountMerge.js +87 -0
- package/dist/pluginNaming.js +1 -2
- package/dist/pluginPrivacy.js +165 -0
- package/dist/procedure.js +115 -98
- package/dist/publicApi.js +191 -211
- package/dist/queryOptionalSources.js +13 -0
- package/dist/reactivityChannel.js +1 -2
- package/dist/rest.d.ts +227 -64
- package/dist/rest.js +296 -194
- package/dist/restFormat.js +1 -2
- package/dist/restReceipt.js +42 -0
- package/dist/revalidate.js +12 -0
- package/dist/rowEquality.js +1 -2
- package/dist/rowPatch.js +1 -2
- package/dist/schemaShape.js +1 -2
- package/dist/scopes.js +72 -40
- package/dist/secretWindows.js +70 -0
- package/dist/serverErrorBus.js +1 -2
- package/dist/serviceCall.js +1 -2
- package/dist/session.d.ts +89 -6
- package/dist/session.js +56 -56
- package/dist/sessionHeader.js +1 -2
- package/dist/ssrfPolicy.js +29 -0
- package/dist/storageAccess.js +1 -2
- package/dist/storeErrors.js +1 -2
- package/dist/storeScreenshots.js +1 -2
- package/dist/strictInput.js +1 -2
- package/dist/subscriptionEvent.js +1 -2
- package/dist/tenantSelection.js +1 -2
- package/dist/time.js +1 -2
- package/dist/undo.js +1 -2
- package/dist/validation.js +1 -2
- package/dist/webSocketGateway.js +8 -3
- package/dist/workflow.js +1 -2
- package/dist/workflowAccess.js +1 -2
- package/dist/workflowRestart.js +1 -2
- package/dist/workflowRetry.js +1 -2
- package/dist/workflowStartOutcome.js +1 -2
- package/package.json +7 -5
package/dist/restFormat.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Schema as e, SchemaGetter as t, SchemaTransformation as n } from "effect";
|
|
2
2
|
import * as r from "effect/SchemaAST";
|
|
3
|
-
|
|
3
|
+
// src/restFormat.ts
|
|
4
4
|
var i = {
|
|
5
5
|
rpc: {
|
|
6
6
|
name: "rpc",
|
|
@@ -159,5 +159,4 @@ var i = {
|
|
|
159
159
|
...r === void 0 ? {} : { links: { next: y(n, r, e.cursorParam).replace(/^<|>; rel="next"$/g, "") } }
|
|
160
160
|
}, g);
|
|
161
161
|
};
|
|
162
|
-
//#endregion
|
|
163
162
|
export { g as JSONAPI_MEDIA_TYPE, h as PROBLEM_JSON, a as REST_PROFILE_NAMES, _ as encodeRestError, x as encodeRestSuccess, y as nextLink, m as problemDetails, f as problemTypeOf, o as resolveRestFormat, d as restViewSchema, s as toSnakeCase };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Effect as e, Schema as t } from "effect";
|
|
2
|
+
// src/restReceipt.ts
|
|
3
|
+
var n = t.Struct({
|
|
4
|
+
_tag: t.Literal("VoltroRestOutput"),
|
|
5
|
+
version: t.Literal(1),
|
|
6
|
+
kind: t.Union([t.Literal("raw"), t.Literal("projection")]),
|
|
7
|
+
headers: t.optional(t.Record(t.String, t.Union([t.String, t.Array(t.String)]))),
|
|
8
|
+
contentType: t.optional(t.String)
|
|
9
|
+
}), r = (r, i) => {
|
|
10
|
+
let a = t.toCodecJson(r), o = t.encodeUnknownEffect(a), s = t.decodeUnknownEffect(a), c = t.decodeUnknownEffect(n), l = async (t) => {
|
|
11
|
+
let n = await e.runPromise(c(t.rest));
|
|
12
|
+
if (n.kind !== i) throw Error("REST receipt belongs to a different surface");
|
|
13
|
+
return {
|
|
14
|
+
body: await e.runPromise(s(t.body)),
|
|
15
|
+
headers: n.headers,
|
|
16
|
+
contentType: n.contentType
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
return {
|
|
20
|
+
read: l,
|
|
21
|
+
capture: async (r, a) => {
|
|
22
|
+
let s = await e.runPromise(o(r)), c = JSON.parse(JSON.stringify({
|
|
23
|
+
body: s,
|
|
24
|
+
rest: {
|
|
25
|
+
_tag: "VoltroRestOutput",
|
|
26
|
+
version: 1,
|
|
27
|
+
kind: i,
|
|
28
|
+
...a.headers === void 0 ? {} : { headers: a.headers },
|
|
29
|
+
...a.contentType === void 0 ? {} : { contentType: a.contentType }
|
|
30
|
+
}
|
|
31
|
+
})), u = await e.runPromise(t.decodeUnknownEffect(t.Struct({
|
|
32
|
+
body: t.optional(t.Unknown),
|
|
33
|
+
rest: n
|
|
34
|
+
}))(c)), d = {
|
|
35
|
+
body: u.body,
|
|
36
|
+
rest: u.rest
|
|
37
|
+
};
|
|
38
|
+
return await l(d), d;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
};
|
|
42
|
+
export { r as makeRestReceiptCodec };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/revalidate.ts
|
|
2
|
+
var e = (e) => {
|
|
3
|
+
if (typeof e == "number" && Number.isFinite(e) && e > 0) return e * 1e3;
|
|
4
|
+
if (typeof e != "string") return null;
|
|
5
|
+
let t = /^\s*(\d+)\s*(s|seconds?|m|minutes?|h|hours?|d|days?)\s*$/i.exec(e);
|
|
6
|
+
if (!t) return null;
|
|
7
|
+
let n = parseInt(t[1], 10);
|
|
8
|
+
if (!Number.isFinite(n) || n <= 0) return null;
|
|
9
|
+
let r = t[2].toLowerCase();
|
|
10
|
+
return r === "s" || r.startsWith("second") ? n * 1e3 : r === "m" || r.startsWith("minute") ? n * 6e4 : r === "h" || r.startsWith("hour") ? n * 36e5 : r === "d" || r.startsWith("day") ? n * 864e5 : null;
|
|
11
|
+
};
|
|
12
|
+
export { e as parseRevalidateMs };
|
package/dist/rowEquality.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/rowEquality.ts
|
|
2
2
|
var e = (e) => e instanceof Uint8Array && Object.getPrototypeOf(e) === Uint8Array.prototype && !("toJSON" in e) && Object.keys(e).length === e.length, t = (e) => {
|
|
3
3
|
let t = Object.getPrototypeOf(e);
|
|
4
4
|
return (t === null || t === Object.prototype) && !("toJSON" in e) && !("toJSON" in Object.prototype);
|
|
@@ -27,5 +27,4 @@ var e = (e) => e instanceof Uint8Array && Object.getPrototypeOf(e) === Uint8Arra
|
|
|
27
27
|
}
|
|
28
28
|
return s;
|
|
29
29
|
};
|
|
30
|
-
//#endregion
|
|
31
30
|
export { i as flatRowsEqual };
|
package/dist/rowPatch.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { flatRowsEqual as e } from "./rowEquality.js";
|
|
2
2
|
import { Result as t, Schema as n, SchemaGetter as r } from "effect";
|
|
3
3
|
import * as i from "effect/encoding/Base64";
|
|
4
|
-
|
|
4
|
+
// src/rowPatch.ts
|
|
5
5
|
var a = n.Union([n.String, n.Number]), o = (e) => typeof e == "object" && !!e && !Array.isArray(e) && Object.keys(e).length === 1 && typeof e.$bytes == "string", s = n.Unknown.pipe(n.decodeTo(n.Unknown, {
|
|
6
6
|
decode: r.transform((e) => {
|
|
7
7
|
if (!o(e)) return e;
|
|
@@ -178,5 +178,4 @@ var a = n.Union([n.String, n.Number]), o = (e) => typeof e == "object" && !!e &&
|
|
|
178
178
|
}
|
|
179
179
|
};
|
|
180
180
|
};
|
|
181
|
-
//#endregion
|
|
182
181
|
export { v as applyRowPatch, b as createRowPatchApplier, g as diffRows, d as idToPath, _ as isIdKeyed, s as patchCellSchema, f as pathToId, l as rowPatchOpSchema, u as rowPatchSchema };
|
package/dist/schemaShape.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RpcSchema as e } from "effect/rpc";
|
|
2
|
-
|
|
2
|
+
// src/schemaShape.ts
|
|
3
3
|
var t = (e) => typeof e == "object" && !!e && typeof e._tag == "string", n = 64, r = (e, i = 0) => {
|
|
4
4
|
if (!t(e)) return String(e);
|
|
5
5
|
if (i >= n) return "…";
|
|
@@ -63,5 +63,4 @@ var t = (e) => typeof e == "object" && !!e && typeof e._tag == "string", n = 64,
|
|
|
63
63
|
missingHere: r.sort()
|
|
64
64
|
};
|
|
65
65
|
};
|
|
66
|
-
//#endregion
|
|
67
66
|
export { c as compareSurfaces, s as groupShapeDigests, o as procedureShapeDigest, r as schemaShape, i as shapeDigest };
|
package/dist/scopes.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { RequestedTenantRefused as e } from "./tenantSelection.js";
|
|
2
2
|
import { Unauthenticated as t, currentSubjectAuthority as n, reauthorizeSubject as r } from "./auth.js";
|
|
3
3
|
import { Effect as i, Schema as a } from "effect";
|
|
4
|
-
|
|
4
|
+
// src/scopes.ts
|
|
5
5
|
var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "apikeys:issue:other", u = "devices:manage", d = class extends a.TaggedError()("ScopeError", {
|
|
6
6
|
required: a.String,
|
|
7
7
|
message: a.String
|
|
@@ -47,18 +47,41 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
47
47
|
});
|
|
48
48
|
return n;
|
|
49
49
|
}, w = (e) => (typeof e.action == "string" || typeof e.action == "function") && typeof e.resourceType == "string", T = (e) => e !== void 0 && e.some((e) => w(e) || typeof e.resource == "function"), E = (e) => typeof e.open == "string", D = (e) => Array.isArray(e.service), O = (e) => ({ service: [...e] }), k = (e) => e?.find(D)?.service, A = (e, t) => {
|
|
50
|
+
for (let n of t ?? []) {
|
|
51
|
+
let t = N(n);
|
|
52
|
+
if (t) return K(e, t);
|
|
53
|
+
}
|
|
54
|
+
if (t?.some(M)) {
|
|
55
|
+
let t = P(e);
|
|
56
|
+
if (t) return t;
|
|
57
|
+
}
|
|
50
58
|
let n = k(t);
|
|
51
59
|
if (e.type === "service") return n !== void 0 && n.includes(e.service) ? null : new d({
|
|
52
60
|
required: "service-procedure",
|
|
53
61
|
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(", ")}]`
|
|
54
62
|
});
|
|
55
|
-
if (n !== void 0) return
|
|
63
|
+
if (n !== void 0) return K(e, new d({
|
|
56
64
|
required: `service:${n.join("|")}`,
|
|
57
65
|
message: `this procedure is callable only by the service${n.length === 1 ? "" : "s"} [${n.join(", ")}]`
|
|
58
66
|
}));
|
|
59
|
-
}, j = (e) => e.authenticated === !0, M = (e) =>
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
}, j = (e) => e.authenticated === !0, M = (e) => e.upgraded === !0, N = (e) => typeof e != "object" || !e || !("upgraded" in e) || e.upgraded !== !0 ? null : [
|
|
68
|
+
"scope",
|
|
69
|
+
"mode",
|
|
70
|
+
"resource",
|
|
71
|
+
"action",
|
|
72
|
+
"resourceType",
|
|
73
|
+
"authenticated",
|
|
74
|
+
"open",
|
|
75
|
+
"service"
|
|
76
|
+
].some((t) => t in e) ? new d({
|
|
77
|
+
required: "guard-shape",
|
|
78
|
+
message: "An upgraded guard must be a separate entry; put each additional scope, policy or identity requirement in its own guard entry."
|
|
79
|
+
}) : null, P = (e) => e.type === "user" && e.kind !== "guest" ? null : K(e, new d({
|
|
80
|
+
required: "upgraded",
|
|
81
|
+
message: "this procedure requires a registered user account"
|
|
82
|
+
})), F = (e) => ({ open: e }), I = (e) => typeof e == "string" ? [e] : e, L, R = (e) => {
|
|
83
|
+
L = e;
|
|
84
|
+
}, z = (e) => L === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !w(e) && e.resource !== void 0)).map((e) => e.tag) : [], B = (e) => [
|
|
62
85
|
`${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
|
|
63
86
|
...e.slice(0, 10).map((e) => ` ${e}`),
|
|
64
87
|
...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
|
|
@@ -72,53 +95,58 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
72
95
|
" • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
|
|
73
96
|
" subject hold `req.scope` on `req.resource`\" from your own tables.",
|
|
74
97
|
" • Drop the `resource` extractor if a global scope check is what you meant."
|
|
75
|
-
].join("\n"),
|
|
76
|
-
|
|
77
|
-
},
|
|
98
|
+
].join("\n"), V = () => L, H, U = (e) => {
|
|
99
|
+
H = e;
|
|
100
|
+
}, W = () => H, G = (e) => new d({
|
|
78
101
|
required: "access-decision",
|
|
79
102
|
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>'\`.`
|
|
80
|
-
}),
|
|
103
|
+
}), K = (e, n) => {
|
|
81
104
|
let r = e.credentialRejected;
|
|
82
105
|
return r === void 0 ? n : new t({ reason: `${r} — the request carried a credential and it was REJECTED, so this caller resolved to anonymous. The guard then refused (${n.message}); the scope is not the problem. Re-authenticate and retry.` });
|
|
83
|
-
},
|
|
106
|
+
}, q = (e) => {
|
|
84
107
|
let t = Array.isArray(e), n = Object.getPrototypeOf(e);
|
|
85
108
|
if (t ? n !== Array.prototype : n !== Object.prototype && n !== null) return !1;
|
|
86
109
|
for (let n of Reflect.ownKeys(e)) if (t && (typeof n != "string" || n !== "length" && !/^(0|[1-9][0-9]*)$/.test(n)) || !("value" in Object.getOwnPropertyDescriptor(e, n))) return !1;
|
|
87
110
|
return !0;
|
|
88
|
-
},
|
|
111
|
+
}, J = (e, t) => {
|
|
89
112
|
let n, r = 0, i, a = 0, o;
|
|
90
113
|
return (s) => {
|
|
91
114
|
let c = y(e);
|
|
92
|
-
return (c !== n || c.length !== r) && (n = c, r = c.length, i = void 0, a = 0, o = void 0), i === void 0 && c.length >= 32 && ++a > 1 && (o ??=
|
|
115
|
+
return (c !== n || c.length !== r) && (n = c, r = c.length, i = void 0, a = 0, o = void 0), i === void 0 && c.length >= 32 && ++a > 1 && (o ??= q(c) && q(e) && q(t) && t.every((e) => q(e) && (!("scope" in e) || typeof e.scope == "string" || q(e.scope))), o && (i = new Set(c))), i === void 0 ? c.includes("admin:full") || c.includes(s) : i.has("admin:full") || i.has(s);
|
|
93
116
|
};
|
|
94
|
-
},
|
|
117
|
+
}, Y = (e, t, n) => {
|
|
95
118
|
let r = A(e, t);
|
|
96
119
|
if (r !== void 0) return r;
|
|
97
|
-
if (!t || t.length === 0) return n?.defaultDeny === !0 ?
|
|
120
|
+
if (!t || t.length === 0) return n?.defaultDeny === !0 ? G(n.procedure) : null;
|
|
98
121
|
let i = 0, a;
|
|
99
122
|
for (let n of t) {
|
|
100
123
|
if (E(n) || D(n)) continue;
|
|
124
|
+
if (M(n)) {
|
|
125
|
+
let t = P(e);
|
|
126
|
+
if (t) return t;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
101
129
|
if (j(n)) {
|
|
102
130
|
if (e.id !== null && e.id !== void 0) continue;
|
|
103
|
-
return
|
|
131
|
+
return K(e, new d({
|
|
104
132
|
required: "authenticated",
|
|
105
133
|
message: "this procedure requires an authenticated caller"
|
|
106
134
|
}));
|
|
107
135
|
}
|
|
108
136
|
if (w(n)) {
|
|
109
|
-
if (i++, a === void 0 && (t.length >= 512 || i >= 512) && (a =
|
|
110
|
-
return
|
|
137
|
+
if (i++, a === void 0 && (t.length >= 512 || i >= 512) && (a = J(e, t)), a === void 0 ? b(e, "admin:full") : a("admin:full")) continue;
|
|
138
|
+
return K(e, new d({
|
|
111
139
|
required: `${n.resourceType}:${n.action}`,
|
|
112
140
|
message: `relationship guard '${n.action}' on '${n.resourceType}' cannot be checked synchronously`
|
|
113
141
|
}));
|
|
114
142
|
}
|
|
115
|
-
let r =
|
|
116
|
-
if (n.resourceOnly === !0) return
|
|
143
|
+
let r = I(n.scope);
|
|
144
|
+
if (n.resourceOnly === !0) return K(e, new d({
|
|
117
145
|
required: r[0] ?? "resource",
|
|
118
146
|
message: "resource-only guard cannot be checked synchronously"
|
|
119
147
|
}));
|
|
120
148
|
if (r.length === 0) continue;
|
|
121
|
-
i += r.length, a === void 0 && (t.length >= 512 || i >= 512) && (a =
|
|
149
|
+
i += r.length, a === void 0 && (t.length >= 512 || i >= 512) && (a = J(e, t));
|
|
122
150
|
let o = n.mode ?? "all", s;
|
|
123
151
|
if (o === "any") {
|
|
124
152
|
if (a === void 0 ? r.some((t) => b(e, t)) : r.some(a)) continue;
|
|
@@ -128,13 +156,13 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
128
156
|
if (t === void 0) continue;
|
|
129
157
|
s = t;
|
|
130
158
|
}
|
|
131
|
-
return
|
|
159
|
+
return K(e, new d({
|
|
132
160
|
required: s,
|
|
133
161
|
message: o === "any" ? `missing all of required scopes [${r.join(", ")}]` : `missing required scope '${s}'`
|
|
134
162
|
}));
|
|
135
163
|
}
|
|
136
164
|
return null;
|
|
137
|
-
},
|
|
165
|
+
}, X = (e, t, n) => {
|
|
138
166
|
let r;
|
|
139
167
|
try {
|
|
140
168
|
r = C(t, n);
|
|
@@ -146,7 +174,7 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
146
174
|
message: e
|
|
147
175
|
});
|
|
148
176
|
if (b(e, "admin:full")) return i.succeed(null);
|
|
149
|
-
let o =
|
|
177
|
+
let o = H;
|
|
150
178
|
if (o === void 0) return i.succeed(a(`no policy resolver registered — cannot authorize '${r}' on '${t.resourceType}'`));
|
|
151
179
|
let s = t.resource(n);
|
|
152
180
|
return s === void 0 || s === "" ? i.succeed(a(`input does not identify a '${t.resourceType}' to authorize`)) : i.suspend(() => o({
|
|
@@ -154,34 +182,39 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
154
182
|
action: r,
|
|
155
183
|
resourceType: t.resourceType,
|
|
156
184
|
resourceId: s
|
|
157
|
-
})).pipe(i.catchCause(() => i.succeed(!1)), i.map((n) =>
|
|
158
|
-
},
|
|
185
|
+
})).pipe(i.catchCause(() => i.succeed(!1)), i.map((n) => Z(e, n, t.resourceType, s, () => a(`no '${r}' relation on ${t.resourceType}:${s}`))));
|
|
186
|
+
}, Z = (e, t, n, r, i) => t === !0 ? null : t === "missing" && e.id !== null && e.id !== void 0 ? new f({
|
|
159
187
|
resourceType: n,
|
|
160
188
|
resourceId: r,
|
|
161
189
|
message: n === null ? `no such resource '${r}'` : `no such ${n} '${r}'`
|
|
162
|
-
}) : i(),
|
|
190
|
+
}) : i(), Q = (e, t, n, r) => {
|
|
163
191
|
let a = A(e, t);
|
|
164
192
|
if (a !== void 0) return i.succeed(a);
|
|
165
|
-
if (!t || t.length === 0) return i.succeed(
|
|
166
|
-
let o =
|
|
167
|
-
return !s && !c && (!o || !t.some((e) => e.resource !== void 0)) ? i.succeed(
|
|
193
|
+
if (!t || t.length === 0) return i.succeed(Y(e, t, r));
|
|
194
|
+
let o = L, s = t.some(w), c = t.some((e) => "scope" in e && e.resourceOnly === !0);
|
|
195
|
+
return !s && !c && (!o || !t.some((e) => e.resource !== void 0)) ? i.succeed(Y(e, t, r)) : i.gen(function* () {
|
|
168
196
|
for (let r of t) {
|
|
169
197
|
if (E(r) || D(r)) continue;
|
|
198
|
+
if (M(r)) {
|
|
199
|
+
let t = P(e);
|
|
200
|
+
if (t) return t;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
170
203
|
if (j(r)) {
|
|
171
204
|
if (e.id !== null && e.id !== void 0) continue;
|
|
172
|
-
return
|
|
205
|
+
return K(e, new d({
|
|
173
206
|
required: "authenticated",
|
|
174
207
|
message: "this procedure requires an authenticated caller"
|
|
175
208
|
}));
|
|
176
209
|
}
|
|
177
210
|
if (w(r)) {
|
|
178
|
-
let t = yield*
|
|
211
|
+
let t = yield* X(e, r, n);
|
|
179
212
|
if (t) return t;
|
|
180
213
|
continue;
|
|
181
214
|
}
|
|
182
|
-
let t =
|
|
215
|
+
let t = I(r.scope);
|
|
183
216
|
if (t.length === 0) {
|
|
184
|
-
if (r.resourceOnly === !0) return
|
|
217
|
+
if (r.resourceOnly === !0) return K(e, new d({
|
|
185
218
|
required: "resource",
|
|
186
219
|
message: "resource-only guard requires a non-empty scope list"
|
|
187
220
|
}));
|
|
@@ -192,12 +225,12 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
192
225
|
a = r.resource ? r.resource(n) : void 0;
|
|
193
226
|
} catch (n) {
|
|
194
227
|
if (r.resourceOnly !== !0) throw n;
|
|
195
|
-
return
|
|
228
|
+
return K(e, new d({
|
|
196
229
|
required: t[0],
|
|
197
230
|
message: "resource selector failed"
|
|
198
231
|
}));
|
|
199
232
|
}
|
|
200
|
-
if (r.resourceOnly === !0 && (o === void 0 || typeof a != "string" || a === "")) return
|
|
233
|
+
if (r.resourceOnly === !0 && (o === void 0 || typeof a != "string" || a === "")) return K(e, new d({
|
|
201
234
|
required: t[0],
|
|
202
235
|
message: "resource-only guard requires a resolver and a non-empty resource id"
|
|
203
236
|
}));
|
|
@@ -215,7 +248,7 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
215
248
|
if (!(l === "any" ? s.some(Boolean) : s.every(Boolean))) {
|
|
216
249
|
let n = l === "any" ? t[0] : t[t.findIndex((e, t) => !s[t])];
|
|
217
250
|
if (c && a !== void 0) {
|
|
218
|
-
let t =
|
|
251
|
+
let t = Z(e, "missing", null, a, () => new d({
|
|
219
252
|
required: n,
|
|
220
253
|
message: `missing required scope '${n}' on resource '${a}'`
|
|
221
254
|
}));
|
|
@@ -229,12 +262,11 @@ var o = "admin:full", s = "apikeys:issue:self", c = "apikeys:issue:org", l = "ap
|
|
|
229
262
|
}
|
|
230
263
|
return null;
|
|
231
264
|
});
|
|
232
|
-
},
|
|
265
|
+
}, $ = (n, o, s, c) => i.tryPromise({
|
|
233
266
|
try: async () => r(n, (e) => _(n, e)),
|
|
234
267
|
catch: (e) => e
|
|
235
268
|
}).pipe(i.matchEffect({
|
|
236
269
|
onFailure: (n) => a.is(t)(n) || a.is(e)(n) ? i.succeed(n) : i.die(n),
|
|
237
|
-
onSuccess: (e) =>
|
|
270
|
+
onSuccess: (e) => Q(e, o, s, c)
|
|
238
271
|
}));
|
|
239
|
-
|
|
240
|
-
export { o as ADMIN_SCOPE, c as APIKEY_ISSUE_ORG_SCOPE, l as APIKEY_ISSUE_OTHER_SCOPE, s as APIKEY_ISSUE_SELF_SCOPE, u as DEVICES_MANAGE_SCOPE, f as NoSuchResource, d as ScopeError, L as advisoryResourceGuardWarning, K as checkGuards, Y as checkGuardsEffect, T as declaresResourceGuard, y as effectiveScopes, I as findAdvisoryResourceGuards, V as getPolicyGuardResolver, R as getResourceScopeResolver, b as hasEffectiveScope, x as hasScope, j as isAuthenticatedCheck, E as isOpenAccess, w as isPolicyCheck, D as isServiceAccess, H as missingAccessDecision, M as openAccessSpec, X as recheckGuardsEffect, _ as refreshEffectiveScopes, S as requireScope, C as resolvePolicyAction, O as serviceAccessSpec, k as serviceCallersOf, v as setEffectiveScopes, g as setEffectiveScopesRefresher, B as setPolicyGuardResolver, F as setResourceScopeResolver, p as subjectScopes };
|
|
272
|
+
export { o as ADMIN_SCOPE, c as APIKEY_ISSUE_ORG_SCOPE, l as APIKEY_ISSUE_OTHER_SCOPE, s as APIKEY_ISSUE_SELF_SCOPE, u as DEVICES_MANAGE_SCOPE, f as NoSuchResource, d as ScopeError, B as advisoryResourceGuardWarning, Y as checkGuards, Q as checkGuardsEffect, T as declaresResourceGuard, y as effectiveScopes, z as findAdvisoryResourceGuards, W as getPolicyGuardResolver, V as getResourceScopeResolver, b as hasEffectiveScope, x as hasScope, j as isAuthenticatedCheck, E as isOpenAccess, w as isPolicyCheck, D as isServiceAccess, M as isUpgradedCheck, G as missingAccessDecision, F as openAccessSpec, $ as recheckGuardsEffect, _ as refreshEffectiveScopes, S as requireScope, C as resolvePolicyAction, O as serviceAccessSpec, k as serviceCallersOf, v as setEffectiveScopes, g as setEffectiveScopesRefresher, U as setPolicyGuardResolver, R as setResourceScopeResolver, p as subjectScopes, N as upgradedGuardShapeError };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { createHash as e, createHmac as t, timingSafeEqual as n } from "node:crypto";
|
|
2
|
+
// src/secretWindows.ts
|
|
3
|
+
var r = (e) => t("sha256", e).update("voltro:secret-fingerprint:v1").digest("hex").slice(0, 16), i = Symbol.for("voltro.secretWindows"), a = () => {
|
|
4
|
+
let e = globalThis;
|
|
5
|
+
return e[i] ??= {
|
|
6
|
+
signed: /* @__PURE__ */ new Map(),
|
|
7
|
+
configured: /* @__PURE__ */ new Map(),
|
|
8
|
+
presented: /* @__PURE__ */ new Map(),
|
|
9
|
+
declared: /* @__PURE__ */ new Map(),
|
|
10
|
+
windows: /* @__PURE__ */ new Map()
|
|
11
|
+
}, e[i];
|
|
12
|
+
}, o = (e, t) => {
|
|
13
|
+
let n = e.get(t);
|
|
14
|
+
if (n !== void 0) return n;
|
|
15
|
+
let r = /* @__PURE__ */ new Map();
|
|
16
|
+
return e.set(t, r), r;
|
|
17
|
+
}, s = (e, t, n, i = Date.now()) => {
|
|
18
|
+
let s = o(a().signed, e), c = r(t), l = n ?? Infinity, u = s.get(c), d = Math.max(u?.longestMs ?? 0, l - i);
|
|
19
|
+
s.set(c, {
|
|
20
|
+
until: Math.max(u?.until ?? -Infinity, l),
|
|
21
|
+
longestMs: d
|
|
22
|
+
});
|
|
23
|
+
}, c = (e, t) => {
|
|
24
|
+
let n = a().declared;
|
|
25
|
+
n.set(e, Math.max(n.get(e) ?? 0, t));
|
|
26
|
+
}, l = (e, t, n) => {
|
|
27
|
+
a().configured.set(e, {
|
|
28
|
+
current: r(t),
|
|
29
|
+
previous: n === void 0 || n === "" || n === t ? null : r(n)
|
|
30
|
+
});
|
|
31
|
+
}, u = () => {
|
|
32
|
+
let e = a(), t = [...e.signed].flatMap(([e, t]) => [...t].map(([t, n]) => ({
|
|
33
|
+
purpose: e,
|
|
34
|
+
fingerprint: t,
|
|
35
|
+
signedUntil: n.until,
|
|
36
|
+
longestMs: n.longestMs
|
|
37
|
+
}))), n = [...e.presented].flatMap(([e, t]) => [...t].map(([t, n]) => ({
|
|
38
|
+
purpose: e,
|
|
39
|
+
fingerprint: t,
|
|
40
|
+
at: n
|
|
41
|
+
}))), r = [...e.configured].map(([e, t]) => ({
|
|
42
|
+
purpose: e,
|
|
43
|
+
...t
|
|
44
|
+
})), i = [...e.declared].map(([e, t]) => ({
|
|
45
|
+
purpose: e,
|
|
46
|
+
lifetimeMs: t
|
|
47
|
+
}));
|
|
48
|
+
return e.signed.clear(), e.presented.clear(), {
|
|
49
|
+
signed: t,
|
|
50
|
+
configured: r,
|
|
51
|
+
presented: n,
|
|
52
|
+
declared: i
|
|
53
|
+
};
|
|
54
|
+
}, d = (e) => {
|
|
55
|
+
let t = /* @__PURE__ */ new Map();
|
|
56
|
+
for (let n of e) o(t, n.purpose).set(n.fingerprint, n.closesAt);
|
|
57
|
+
a().windows = t;
|
|
58
|
+
}, f = (e, t, n) => {
|
|
59
|
+
o(a().windows, e).set(r(t), n);
|
|
60
|
+
}, p = () => {
|
|
61
|
+
let e = a();
|
|
62
|
+
e.windows = /* @__PURE__ */ new Map(), e.signed.clear(), e.configured.clear(), e.presented.clear(), e.declared.clear();
|
|
63
|
+
}, m = (e, t, n = Date.now()) => {
|
|
64
|
+
let i = a().windows.get(e)?.get(r(t));
|
|
65
|
+
return i == null || n <= i;
|
|
66
|
+
}, h = (t) => e("sha256").update(t).digest(), g = (e, t, i, s) => {
|
|
67
|
+
let c = h(t), l = i !== "" && n(c, h(i)), u = s !== void 0 && s !== "" && s !== i && n(c, h(s));
|
|
68
|
+
return l ? !0 : !u || !m(e, s) ? !1 : (o(a().presented, e).set(r(s), Date.now()), !0);
|
|
69
|
+
};
|
|
70
|
+
export { d as applySecretWindows, g as bearerMatches, p as clearSecretWindows, u as drainSecretActivity, l as noteConfigured, s as noteSigned, c as noteSigningLifetime, m as previousAccepted, r as secretFingerprint, f as setSecretWindow };
|
package/dist/serverErrorBus.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
// src/serverErrorBus.ts
|
|
2
2
|
var e = (e) => {
|
|
3
3
|
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]`);
|
|
4
4
|
i.name = n;
|
|
@@ -11,5 +11,4 @@ var e = (e) => {
|
|
|
11
11
|
}, r = (e) => (t.add(e), () => {
|
|
12
12
|
t.delete(e);
|
|
13
13
|
});
|
|
14
|
-
//#endregion
|
|
15
14
|
export { n as publishServerError, r as subscribeServerErrors, e as withheldServerError };
|
package/dist/serviceCall.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Schema as e } from "effect";
|
|
2
|
-
|
|
2
|
+
// src/serviceCall.ts
|
|
3
3
|
var t = class extends e.TaggedError()("ApiUnavailable", {
|
|
4
4
|
api: e.String,
|
|
5
5
|
tag: e.String,
|
|
@@ -10,5 +10,4 @@ var t = class extends e.TaggedError()("ApiUnavailable", {
|
|
|
10
10
|
]),
|
|
11
11
|
message: e.String
|
|
12
12
|
}) {}, n = (e) => typeof e == "object" && !!e && e._tag === "ApiUnavailable";
|
|
13
|
-
//#endregion
|
|
14
13
|
export { t as ApiUnavailable, n as isApiUnavailable };
|
package/dist/session.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { Schema } from 'effect';
|
|
2
2
|
|
|
3
|
+
/** Replace every recorded window with the boot's computed ones. */
|
|
4
|
+
export declare const applySecretWindows: (windows: ReadonlyArray<{
|
|
5
|
+
readonly purpose: string;
|
|
6
|
+
readonly fingerprint: string;
|
|
7
|
+
readonly closesAt: number | null;
|
|
8
|
+
}>) => void;
|
|
9
|
+
|
|
3
10
|
/**
|
|
4
11
|
* Fail-closed check that a real session secret is configured. Throws a plain
|
|
5
12
|
* `Error` (a fatal boot condition, not a wire error) when
|
|
@@ -8,6 +15,14 @@ import { Schema } from 'effect';
|
|
|
8
15
|
*/
|
|
9
16
|
export declare const assertProductionSessionSecret: (env?: NodeJS.ProcessEnv) => void;
|
|
10
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Does a presented bearer token match the current value or — during a
|
|
20
|
+
* rotation, while its window is open — the previous one? Both comparisons run,
|
|
21
|
+
* in constant time over digests, so neither which one matched nor a length
|
|
22
|
+
* leaks through timing. A match on the previous value is recorded.
|
|
23
|
+
*/
|
|
24
|
+
export declare const bearerMatches: (purpose: string, presented: string, current: string, previous?: string) => boolean;
|
|
25
|
+
|
|
11
26
|
/**
|
|
12
27
|
* Build a `Set-Cookie` header value. Pure helper — the caller adds it
|
|
13
28
|
* to the actual HTTP response. Used by the framework's login route
|
|
@@ -46,6 +61,9 @@ export declare const checkBearer: (headers: Readonly<Record<string, string | und
|
|
|
46
61
|
readonly openWhenUnset?: boolean;
|
|
47
62
|
}) => boolean;
|
|
48
63
|
|
|
64
|
+
/** Forget every record — a test seam, and a process that stops verifying. */
|
|
65
|
+
export declare const clearSecretWindows: () => void;
|
|
66
|
+
|
|
49
67
|
/** Key id assigned to `VOLTRO_SESSION_SECRET_PREVIOUS` when no explicit
|
|
50
68
|
* `VOLTRO_SESSION_KID_PREVIOUS` is set. The kid is a non-secret label —
|
|
51
69
|
* rotation works with just the `_PREVIOUS` secret var. */
|
|
@@ -56,6 +74,9 @@ export declare const DEFAULT_PREVIOUS_SESSION_KID: "k-previous";
|
|
|
56
74
|
* string produce the same label the resolver would. */
|
|
57
75
|
export declare const DEFAULT_SESSION_KID: "k0";
|
|
58
76
|
|
|
77
|
+
/** What this process signed, holds and was presented since the last drain — for the boot to persist. */
|
|
78
|
+
export declare const drainSecretActivity: () => SecretActivity;
|
|
79
|
+
|
|
59
80
|
/** A keyed signing secret. `kid` is stamped into the payload on sign and
|
|
60
81
|
* matched on verify; it's an opaque, non-secret label (e.g. `'2026-06'`). */
|
|
61
82
|
export declare interface KeyedSecret {
|
|
@@ -68,6 +89,31 @@ export declare interface KeyedSecret {
|
|
|
68
89
|
* placeholders, not real secrets. */
|
|
69
90
|
export declare const MIN_SESSION_SECRET_LENGTH: 32;
|
|
70
91
|
|
|
92
|
+
/** A resolver read `current` (and, during a rotation, `previous`) for `purpose`. */
|
|
93
|
+
export declare const noteConfigured: (purpose: string, current: string, previous: string | undefined) => void;
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* A signer signed something under `secret` that is valid until `expiresAtMs`
|
|
97
|
+
* (undefined: no expiry). The lifetime it signed with is recorded too: it is
|
|
98
|
+
* what bounds the tokens signed before anything was recorded.
|
|
99
|
+
*/
|
|
100
|
+
export declare const noteSigned: (purpose: string, secret: string, expiresAtMs: number | undefined, now?: number) => void;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* A configured signer can sign `purpose` tokens valid for up to `lifetimeMs` —
|
|
104
|
+
* declared when it is built, before it signs anything. The first rotation after
|
|
105
|
+
* an upgrade needs it: the previous value signed tokens nothing recorded, and
|
|
106
|
+
* only the configuration says how long they can live.
|
|
107
|
+
*/
|
|
108
|
+
export declare const noteSigningLifetime: (purpose: string, lifetimeMs: number) => void;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Is this previous value still accepted? Yes while its window is open, and
|
|
112
|
+
* when no window is recorded for it (nothing has decided otherwise). No once
|
|
113
|
+
* the latest expiry it signed has passed, or a compromise closed it.
|
|
114
|
+
*/
|
|
115
|
+
export declare const previousAccepted: (purpose: string, previous: string, now?: number) => boolean;
|
|
116
|
+
|
|
71
117
|
/**
|
|
72
118
|
* Read a cookie value by name from a `Cookie:` header string.
|
|
73
119
|
* Returns undefined if the cookie isn't present.
|
|
@@ -123,6 +169,37 @@ export declare const resolveSessionSecret: () => string;
|
|
|
123
169
|
*/
|
|
124
170
|
export declare const resolveSessionSecrets: () => SessionSecrets;
|
|
125
171
|
|
|
172
|
+
/** What a process recorded since the last drain: signatures, configured values, previous bearer values that answered. */
|
|
173
|
+
export declare interface SecretActivity {
|
|
174
|
+
/** Per purpose and fingerprint: the latest expiry signed and the longest lifetime signed with. */
|
|
175
|
+
readonly signed: ReadonlyArray<{
|
|
176
|
+
readonly purpose: string;
|
|
177
|
+
readonly fingerprint: string;
|
|
178
|
+
readonly signedUntil: number;
|
|
179
|
+
readonly longestMs: number;
|
|
180
|
+
}>;
|
|
181
|
+
/** Per purpose: the fingerprints of the current and the previous value this process holds. */
|
|
182
|
+
readonly configured: ReadonlyArray<{
|
|
183
|
+
readonly purpose: string;
|
|
184
|
+
readonly current: string;
|
|
185
|
+
readonly previous: string | null;
|
|
186
|
+
}>;
|
|
187
|
+
/** Per purpose: when a previous bearer value last answered. */
|
|
188
|
+
readonly presented: ReadonlyArray<{
|
|
189
|
+
readonly purpose: string;
|
|
190
|
+
readonly fingerprint: string;
|
|
191
|
+
readonly at: number;
|
|
192
|
+
}>;
|
|
193
|
+
/** Per purpose: the longest lifetime a configured signer declared. */
|
|
194
|
+
readonly declared: ReadonlyArray<{
|
|
195
|
+
readonly purpose: string;
|
|
196
|
+
readonly lifetimeMs: number;
|
|
197
|
+
}>;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
/** A non-reversible name for a secret value: 16 hex of an HMAC under a fixed label. */
|
|
201
|
+
export declare const secretFingerprint: (value: string) => string;
|
|
202
|
+
|
|
126
203
|
/**
|
|
127
204
|
* The cookie the framework's own session strategy writes and reads.
|
|
128
205
|
*
|
|
@@ -166,15 +243,16 @@ export declare const SESSION_PAYLOAD_VERSION: 2;
|
|
|
166
243
|
*/
|
|
167
244
|
export declare const sessionExpiryFromHeaders: (headers: Record<string, string | undefined>) => number | undefined;
|
|
168
245
|
|
|
169
|
-
export declare type SessionPayload = typeof
|
|
246
|
+
export declare type SessionPayload = typeof SessionPayloadSchema.Type;
|
|
170
247
|
|
|
171
|
-
declare const
|
|
248
|
+
declare const SessionPayloadSchema: Schema.Struct<{
|
|
172
249
|
/** Payload format version. Required and pinned — see the header. */
|
|
173
250
|
readonly v: Schema.Literal<2>;
|
|
174
251
|
/** WHO, never WHAT-THEY-MAY-DO. `SubjectIdentity` has no `scopes` field. */
|
|
175
252
|
readonly subject: Schema.Union<readonly [Schema.Struct<{
|
|
176
253
|
readonly type: Schema.Literal<"user">;
|
|
177
254
|
readonly id: Schema.String;
|
|
255
|
+
readonly kind: Schema.optional<Schema.Literal<"guest">>;
|
|
178
256
|
readonly tenantId: Schema.String;
|
|
179
257
|
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
180
258
|
}>, Schema.Struct<{
|
|
@@ -201,9 +279,9 @@ declare const SessionPayload_2: Schema.Struct<{
|
|
|
201
279
|
}>, Schema.Struct<{
|
|
202
280
|
readonly type: Schema.Literal<"service">;
|
|
203
281
|
readonly id: Schema.String;
|
|
282
|
+
readonly service: Schema.String;
|
|
204
283
|
readonly tenantId: Schema.Null;
|
|
205
284
|
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
206
|
-
readonly service: Schema.String;
|
|
207
285
|
}>]>;
|
|
208
286
|
/** Unix seconds when this session expires. Verify rejects past expiry. */
|
|
209
287
|
readonly exp: Schema.Number;
|
|
@@ -217,8 +295,6 @@ declare const SessionPayload_2: Schema.Struct<{
|
|
|
217
295
|
readonly kid: Schema.optional<Schema.String>;
|
|
218
296
|
}>;
|
|
219
297
|
|
|
220
|
-
declare type SessionPayload = typeof SessionPayload_2.Type;
|
|
221
|
-
|
|
222
298
|
/** The resolved secret set: `current` always signs; `previous` is accepted
|
|
223
299
|
* on verify during a rotation window. */
|
|
224
300
|
export declare interface SessionSecrets {
|
|
@@ -242,6 +318,9 @@ export declare interface SetCookieOptions {
|
|
|
242
318
|
readonly domain?: string;
|
|
243
319
|
}
|
|
244
320
|
|
|
321
|
+
/** Record one window by value — a test seam and a single-process embedder's. */
|
|
322
|
+
export declare const setSecretWindow: (purpose: string, previous: string, closesAt: number | null) => void;
|
|
323
|
+
|
|
245
324
|
export declare interface SignOptions {
|
|
246
325
|
/** TTL in seconds. Defaults to 7 days. */
|
|
247
326
|
readonly ttlSeconds?: number;
|
|
@@ -278,6 +357,9 @@ export declare const signSession: (subject: Subject | SubjectIdentity, secret: s
|
|
|
278
357
|
|
|
279
358
|
declare const Subject: Schema.Union<readonly [Schema.Struct<{
|
|
280
359
|
readonly type: Schema.Literal<"user">;
|
|
360
|
+
/** A guest has a stable identity but has not linked a registered account.
|
|
361
|
+
* This identity mark survives session signing; it never grants authority. */
|
|
362
|
+
readonly kind: Schema.optional<Schema.Literal<"guest">>;
|
|
281
363
|
readonly id: Schema.String;
|
|
282
364
|
readonly tenantId: Schema.String;
|
|
283
365
|
readonly scopes: Schema.optional<Schema.$Array<Schema.String>>;
|
|
@@ -339,6 +421,7 @@ declare type Subject = typeof Subject.Type;
|
|
|
339
421
|
declare const SubjectIdentity: Schema.Union<readonly [Schema.Struct<{
|
|
340
422
|
readonly type: Schema.Literal<"user">;
|
|
341
423
|
readonly id: Schema.String;
|
|
424
|
+
readonly kind: Schema.optional<Schema.Literal<"guest">>;
|
|
342
425
|
readonly tenantId: Schema.String;
|
|
343
426
|
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
344
427
|
}>, Schema.Struct<{
|
|
@@ -381,9 +464,9 @@ declare const SubjectIdentity: Schema.Union<readonly [Schema.Struct<{
|
|
|
381
464
|
}>, Schema.Struct<{
|
|
382
465
|
readonly type: Schema.Literal<"service">;
|
|
383
466
|
readonly id: Schema.String;
|
|
467
|
+
readonly service: Schema.String;
|
|
384
468
|
readonly tenantId: Schema.Null;
|
|
385
469
|
readonly metadata: Schema.optional<Schema.$Record<Schema.String, Schema.Unknown>>;
|
|
386
|
-
readonly service: Schema.String;
|
|
387
470
|
}>]>;
|
|
388
471
|
|
|
389
472
|
declare type SubjectIdentity = typeof SubjectIdentity.Type;
|