@voltro/protocol 0.85.0 → 0.86.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.
Files changed (61) hide show
  1. package/CHANGELOG.md +666 -0
  2. package/README.md +14 -0
  3. package/THIRD-PARTY-NOTICES.md +5 -33
  4. package/dist/approval.js +64 -0
  5. package/dist/approvalDescriptors.js +26 -0
  6. package/dist/auth.js +369 -0
  7. package/dist/boundedRing.js +27 -0
  8. package/dist/businessRule.js +11 -0
  9. package/dist/connection.js +73 -0
  10. package/dist/devActivity.js +4 -0
  11. package/dist/errorValue.js +21 -0
  12. package/dist/event.js +104 -0
  13. package/dist/idempotency.js +66 -0
  14. package/dist/identity.js +5 -9
  15. package/dist/index.d.ts +225 -21
  16. package/dist/index.js +42 -1700
  17. package/dist/inspect.js +14 -240
  18. package/dist/inspectBackfill.js +52 -0
  19. package/dist/inspectCommandRejection.js +21 -0
  20. package/dist/inspectProjection.js +133 -0
  21. package/dist/inspectStorageProjection.js +86 -0
  22. package/dist/inspectValueIdentity.js +4 -0
  23. package/dist/inspectWorkflowExecution.js +34 -0
  24. package/dist/inspectWorkflowQueuedStart.js +31 -0
  25. package/dist/jsonSchema.js +54 -0
  26. package/dist/outbox.js +10 -0
  27. package/dist/pairing.js +75 -0
  28. package/dist/plugin.js +61 -0
  29. package/dist/pluginNaming.js +32 -0
  30. package/dist/procedure.js +262 -0
  31. package/dist/publicApi.js +344 -0
  32. package/dist/reactivityChannel.js +34 -0
  33. package/dist/rest.d.ts +33 -0
  34. package/dist/rest.js +213 -470
  35. package/dist/restFormat.js +163 -0
  36. package/dist/rowEquality.js +31 -0
  37. package/dist/rowPatch.js +182 -0
  38. package/dist/schemaShape.js +67 -0
  39. package/dist/scopes.js +240 -0
  40. package/dist/serverErrorBus.js +15 -0
  41. package/dist/serviceCall.js +14 -0
  42. package/dist/session.js +13 -15
  43. package/dist/{sessionHeader-DriTZhmv.js → sessionHeader.js} +1 -1
  44. package/dist/storageAccess.js +14 -0
  45. package/dist/storeErrors.js +66 -0
  46. package/dist/storeScreenshots.js +90 -0
  47. package/dist/strictInput.js +27 -0
  48. package/dist/subscriptionEvent.js +37 -0
  49. package/dist/tenantSelection.js +40 -0
  50. package/dist/time.js +7 -0
  51. package/dist/undo.js +38 -0
  52. package/dist/validation.js +39 -0
  53. package/dist/webSocketGateway.js +10 -0
  54. package/dist/workflow.js +297 -0
  55. package/dist/workflowAccess.js +61 -0
  56. package/dist/workflowRestart.js +45 -0
  57. package/dist/workflowRetry.js +44 -0
  58. package/dist/workflowStartOutcome.js +30 -0
  59. package/package.json +3 -3
  60. package/dist/restFormat-BlgTLxm1.js +0 -298
  61. package/dist/scopes-ClywBij8.js +0 -548
@@ -0,0 +1,163 @@
1
+ import { Schema as e, SchemaGetter as t, SchemaTransformation as n } from "effect";
2
+ import * as r from "effect/SchemaAST";
3
+ //#region src/restFormat.ts
4
+ var i = {
5
+ rpc: {
6
+ name: "rpc",
7
+ dates: "epoch-ms",
8
+ errors: "tagged",
9
+ envelope: "none",
10
+ pagination: "body-cursor",
11
+ cursorField: "nextCursor",
12
+ cursorParam: "cursor",
13
+ naming: "camelCase",
14
+ etag: !1
15
+ },
16
+ standard: {
17
+ name: "standard",
18
+ dates: "iso",
19
+ errors: "problem-details",
20
+ envelope: "none",
21
+ pagination: "link-header",
22
+ cursorField: "nextCursor",
23
+ cursorParam: "cursor",
24
+ naming: "camelCase",
25
+ etag: !0
26
+ },
27
+ jsonapi: {
28
+ name: "jsonapi",
29
+ dates: "iso",
30
+ errors: "problem-details",
31
+ envelope: "jsonapi",
32
+ pagination: "link-header",
33
+ cursorField: "nextCursor",
34
+ cursorParam: "cursor",
35
+ naming: "camelCase",
36
+ etag: !0
37
+ }
38
+ }, a = [
39
+ "rpc",
40
+ "standard",
41
+ "jsonapi"
42
+ ], o = (e, t = void 0) => {
43
+ let n = (e) => {
44
+ if (e?.profile !== void 0) {
45
+ if (typeof e.profile == "string") {
46
+ let t = i[e.profile];
47
+ if (t === void 0) throw Error(`publicApi.profile: unknown profile '${String(e.profile)}' — one of ${a.join(", ")}, or a RestFormat object`);
48
+ return t;
49
+ }
50
+ return e.profile;
51
+ }
52
+ }, r = (e, t) => t === void 0 ? e : {
53
+ ...e,
54
+ ...t.dates === void 0 ? {} : { dates: t.dates },
55
+ ...t.errors === void 0 ? {} : { errors: t.errors },
56
+ ...t.envelope === void 0 ? {} : { envelope: t.envelope },
57
+ ...t.pagination === void 0 ? {} : { pagination: t.pagination },
58
+ ...t.cursorField === void 0 ? {} : { cursorField: t.cursorField },
59
+ ...t.cursorParam === void 0 ? {} : { cursorParam: t.cursorParam },
60
+ ...t.naming === void 0 ? {} : { naming: t.naming },
61
+ ...t.etag === void 0 ? {} : { etag: t.etag }
62
+ }, o = r(n(e) ?? i.rpc, e);
63
+ return r(n(t) ?? o, t);
64
+ }, s = (e) => e.replace(/([a-z0-9])([A-Z])/g, "$1_$2").replace(/([A-Z])([A-Z][a-z])/g, "$1_$2").toLowerCase(), c = (e, t) => {
65
+ if (typeof e != "object" || !e || Array.isArray(e)) return e;
66
+ let n = {};
67
+ for (let [r, i] of Object.entries(e)) n[t(r)] = i;
68
+ return n;
69
+ }, l = (e) => r.isDeclaration(e) && e.encoding !== void 0 && e.annotations?.representation?.id === "effect/schema/Date" && r.isNumber(r.toEncoded(e)), u = e.String.annotate({
70
+ identifier: "DateFromString",
71
+ format: "date-time"
72
+ }).pipe(e.decodeTo(e.Date, n.dateFromString)), d = (n, i) => {
73
+ if (i.dates === "epoch-ms" && i.naming === "camelCase") return n;
74
+ let a = /* @__PURE__ */ new Map(), o = (e) => {
75
+ let t = a.get(e);
76
+ if (t !== void 0) return t;
77
+ let n = d(e);
78
+ return a.set(e, n), n;
79
+ }, d = (n) => {
80
+ if (i.dates === "iso" && l(n)) return u.annotate(n.annotations ?? {}).ast;
81
+ if (n.encoding !== void 0) return n;
82
+ if (r.isUnion(n)) return new r.Union(n.types.map(o), n.options, n.annotations, n.checks, void 0, n.context);
83
+ if (r.isArrays(n)) return new r.Arrays(n.isMutable, n.elements.map(o), n.rest.map(o), n.annotations, n.checks, void 0, n.context);
84
+ if (r.isSuspend(n)) return new r.Suspend(() => o(n.thunk()), n.annotations, n.checks, void 0, n.context);
85
+ if (r.isObjects(n)) {
86
+ let a = n.propertySignatures.map((e) => new r.PropertySignature(e.name, o(e.type))), l = n.indexSignatures.map((e) => new r.IndexSignature(e.parameter, o(e.type))), u = new r.Objects(a, l, n.annotations, n.checks, void 0, n.context);
87
+ if (i.naming !== "snake_case") return u;
88
+ let d = a.map((e) => typeof e.name == "string" ? s(e.name) : e.name);
89
+ if (d.every((e, t) => e === a[t].name)) return u;
90
+ let f = new r.Objects(a.map((e, t) => new r.PropertySignature(d[t], r.toEncoded(e.type))), l.map((e) => new r.IndexSignature(e.parameter, r.toEncoded(e.type))), n.annotations, void 0, void 0, n.context), p = new Map(a.map((e, t) => [String(d[t]), String(e.name)])), m = new Map(a.map((e, t) => [String(e.name), String(d[t])]));
91
+ return e.make(f).pipe(e.decodeTo(e.make(u), {
92
+ decode: t.transform((e) => c(e, (e) => p.get(e) ?? e)),
93
+ encode: t.transform((e) => c(e, (e) => m.get(e) ?? e))
94
+ })).ast;
95
+ }
96
+ return n;
97
+ };
98
+ return e.make(o(n.ast));
99
+ }, f = (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"), m = (e) => ({
100
+ type: f(e.tag),
101
+ title: p(e.tag),
102
+ status: e.status,
103
+ ...e.message.length > 0 ? { detail: e.message } : {},
104
+ ...e.fields
105
+ }), h = "application/problem+json; charset=utf-8", g = "application/vnd.api+json; charset=utf-8", _ = (e, t, n) => e.encodeError === void 0 ? e.errors === "problem-details" ? e.envelope === "jsonapi" ? {
106
+ body: { errors: [{
107
+ status: String(t.status),
108
+ code: t.tag,
109
+ title: p(t.tag),
110
+ ...t.message.length > 0 ? { detail: t.message } : {},
111
+ ...Object.keys(t.fields).length > 0 ? { meta: t.fields } : {}
112
+ }] },
113
+ contentType: g
114
+ } : {
115
+ body: m(t),
116
+ contentType: h
117
+ } : { body: {
118
+ 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,
119
+ ...t.fields
120
+ } } : e.encodeError(t, n), v = (e, t) => {
121
+ if (typeof e != "object" || !e || Array.isArray(e)) return {
122
+ cursor: void 0,
123
+ rest: e
124
+ };
125
+ let n = e[t];
126
+ return typeof n != "string" && typeof n != "number" ? {
127
+ cursor: void 0,
128
+ rest: e
129
+ } : {
130
+ cursor: String(n),
131
+ rest: e
132
+ };
133
+ }, y = (e, t, n) => {
134
+ let r = new URLSearchParams(e.query);
135
+ return r.set(n, t), `<${e.path}?${r.toString()}>; rel="next"`;
136
+ }, b = (e, t) => {
137
+ if (typeof e != "object" || !e || Array.isArray(e)) return e;
138
+ let { id: n, ...r } = e;
139
+ return {
140
+ type: t,
141
+ ...n === void 0 ? {} : { id: String(n) },
142
+ attributes: r
143
+ };
144
+ }, x = (e, t, n) => {
145
+ if (e.encodeSuccess !== void 0) return e.encodeSuccess(t, n);
146
+ let { cursor: r } = v(t, e.cursorField), i = e.pagination === "link-header" && r !== void 0 ? { Link: y(n, r, e.cursorParam) } : void 0, a = (e, t) => ({
147
+ body: e,
148
+ ...i ? { headers: i } : {},
149
+ ...t ? { contentType: t } : {}
150
+ });
151
+ if (e.envelope === "none") return a(t);
152
+ if (e.envelope === "data") return a({
153
+ data: t,
154
+ ...r !== void 0 && e.pagination === "link-header" ? { next: r } : {}
155
+ });
156
+ 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;
157
+ return a({
158
+ data: s === void 0 ? b(t, o) : s.map((e) => b(e, o)),
159
+ ...r === void 0 ? {} : { links: { next: y(n, r, e.cursorParam).replace(/^<|>; rel="next"$/g, "") } }
160
+ }, g);
161
+ };
162
+ //#endregion
163
+ 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,31 @@
1
+ //#region src/rowEquality.ts
2
+ var e = (e) => e instanceof Uint8Array && Object.getPrototypeOf(e) === Uint8Array.prototype && !("toJSON" in e) && Object.keys(e).length === e.length, t = (e) => {
3
+ let t = Object.getPrototypeOf(e);
4
+ return (t === null || t === Object.prototype) && !("toJSON" in e) && !("toJSON" in Object.prototype);
5
+ }, n = (t) => t == null || typeof t == "string" || typeof t == "boolean" || typeof t == "number" || e(t), r = (e, t) => {
6
+ let n = typeof e == "number" && !Number.isFinite(e) ? null : e, r = typeof t == "number" && !Number.isFinite(t) ? null : t;
7
+ if (n === r) return !0;
8
+ if (n instanceof Uint8Array && r instanceof Uint8Array) {
9
+ if (n.length !== r.length) return !1;
10
+ for (let e = 0; e < n.length; e++) if (n[e] !== r[e]) return !1;
11
+ return !0;
12
+ }
13
+ return !1;
14
+ }, i = (e, i) => {
15
+ if (!t(e) || !t(i)) return;
16
+ let a = Object.keys(e), o = e === i ? a : Object.keys(i);
17
+ if (a.length !== o.length) return;
18
+ let s = !0;
19
+ for (let t = 0; t < a.length; t++) {
20
+ let o = a[t];
21
+ if (o === "__proto__" || o in Object.prototype && Object.getOwnPropertyDescriptor(Object.prototype, o)?.set !== void 0) return;
22
+ let c = Object.getOwnPropertyDescriptor(e, o), l = e === i ? c : Object.getOwnPropertyDescriptor(i, o);
23
+ if (c === void 0 || l === void 0 || l.enumerable !== !0 || !("value" in c) || !("value" in l)) return;
24
+ let u = c.value, d = l.value;
25
+ if (!n(u) || !n(d)) return;
26
+ r(u, d) || (s = !1);
27
+ }
28
+ return s;
29
+ };
30
+ //#endregion
31
+ export { i as flatRowsEqual };
@@ -0,0 +1,182 @@
1
+ import { flatRowsEqual as e } from "./rowEquality.js";
2
+ import { Result as t, Schema as n, SchemaGetter as r } from "effect";
3
+ import * as i from "effect/encoding/Base64";
4
+ //#region src/rowPatch.ts
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
+ decode: r.transform((e) => {
7
+ if (!o(e)) return e;
8
+ let n = i.decode(e.$bytes);
9
+ return t.isSuccess(n) ? n.success : e;
10
+ }),
11
+ encode: r.transform((e) => e instanceof Uint8Array ? { $bytes: i.encode(e) } : e instanceof Date ? e.toISOString() : e)
12
+ })), c = n.Record(n.String, s).pipe(n.refine((e) => "id" in e, { message: "patch row must carry an id" })), l = n.Union([
13
+ n.Struct({
14
+ op: n.Literal("add"),
15
+ path: n.String,
16
+ value: c
17
+ }),
18
+ n.Struct({
19
+ op: n.Literal("replace"),
20
+ path: n.String,
21
+ value: c
22
+ }),
23
+ n.Struct({
24
+ op: n.Literal("remove"),
25
+ path: n.String
26
+ }),
27
+ n.Struct({
28
+ op: n.Literal("mergeCells"),
29
+ path: n.String,
30
+ value: n.Record(n.String, s)
31
+ })
32
+ ]), u = n.Struct({
33
+ ops: n.Array(l),
34
+ order: n.NullOr(n.Array(a))
35
+ }), d = (e) => `/${String(e).replace(/~/g, "~0").replace(/\//g, "~1")}`, f = (e) => (e.startsWith("/") ? e.slice(1) : e).replace(/~1/g, "/").replace(/~0/g, "~"), p = (e) => {
36
+ let t = Object.keys(e).sort(), n = {};
37
+ for (let r of t) n[r] = e[r];
38
+ return JSON.stringify(n);
39
+ }, m = (t, n) => e(t, n) ?? p(t) === p(n), h = (e, t) => {
40
+ if (e instanceof Uint8Array && t instanceof Uint8Array) {
41
+ if (e.length !== t.length) return !1;
42
+ for (let n = 0; n < e.length; n += 1) if (e[n] !== t[n]) return !1;
43
+ return !0;
44
+ }
45
+ return p({
46
+ id: 0,
47
+ v: e
48
+ }) === p({
49
+ id: 0,
50
+ v: t
51
+ });
52
+ }, g = (e, t, n = {}) => {
53
+ let r = /* @__PURE__ */ new Map();
54
+ for (let t of e) r.set(t.id, t);
55
+ let i = [], a = e.length === t.length && t.every((t, n) => t.id === e[n].id) ? null : [], o = /* @__PURE__ */ new Set(), s = n.crdt, c = (e, t) => {
56
+ if (s === void 0 || s.columns.size === 0) return;
57
+ let n = {}, r = !1;
58
+ for (let i of s.columns) {
59
+ if (!(i in t) || h(e[i], t[i])) continue;
60
+ let a = s.incremental(i, e[i], t[i]);
61
+ if (a === void 0) return;
62
+ n[i] = a, r = !0;
63
+ }
64
+ if (!r) return;
65
+ let i = {};
66
+ for (let [e, n] of Object.entries(t)) s.columns.has(e) || (i[e] = n);
67
+ return {
68
+ scalars: i,
69
+ merges: n
70
+ };
71
+ };
72
+ for (let e of t) {
73
+ a?.push(e.id), o.add(e.id);
74
+ let t = r.get(e.id);
75
+ if (t === void 0) i.push({
76
+ op: "add",
77
+ path: d(e.id),
78
+ value: e
79
+ });
80
+ else if (!m(t, e)) {
81
+ let n = c(t, e);
82
+ n === void 0 ? i.push({
83
+ op: "replace",
84
+ path: d(e.id),
85
+ value: e
86
+ }) : (m(Object.fromEntries(Object.entries(t).filter(([e]) => !s.columns.has(e))), n.scalars) || i.push({
87
+ op: "replace",
88
+ path: d(e.id),
89
+ value: n.scalars
90
+ }), i.push({
91
+ op: "mergeCells",
92
+ path: d(e.id),
93
+ value: n.merges
94
+ }));
95
+ }
96
+ }
97
+ for (let t of e) o.has(t.id) || i.push({
98
+ op: "remove",
99
+ path: d(t.id)
100
+ });
101
+ return {
102
+ ops: i,
103
+ order: a
104
+ };
105
+ }, _ = (e) => e.every((e) => {
106
+ let t = e.id;
107
+ return typeof t == "string" || typeof t == "number";
108
+ }), v = (e, t, n = {}) => {
109
+ let r = /* @__PURE__ */ new Map();
110
+ for (let t of e) r.set(t.id, t);
111
+ return y(e, t, n, r);
112
+ }, y = (e, t, n, r, i) => {
113
+ let a = /* @__PURE__ */ new Map();
114
+ for (let e of t.ops) e.op === "mergeCells" && a.set(f(e.path), Object.keys(e.value));
115
+ for (let e of t.ops) if (e.op === "mergeCells") {
116
+ let t = f(e.path), i = r.get(t) ?? r.get(Number(t)), a = r.has(t) ? t : Number(t);
117
+ if (i === void 0) continue;
118
+ let o = { ...i };
119
+ for (let [t, r] of Object.entries(e.value)) o[t] = n.mergeCell === void 0 ? r : n.mergeCell(t, i[t], r);
120
+ r.set(a, o);
121
+ } else if (e.op === "add" && (t.order !== null || r.has(e.value.id)) && r.set(e.value.id, e.value), e.op === "replace") {
122
+ let n = r.get(e.value.id), i = (n === void 0 ? [] : a.get(String(e.value.id)) ?? []).filter((t) => !(t in e.value) && t in n);
123
+ (t.order !== null || n !== void 0) && r.set(e.value.id, i.length === 0 ? e.value : {
124
+ ...e.value,
125
+ ...Object.fromEntries(i.map((e) => [e, n[e]]))
126
+ });
127
+ }
128
+ if (t.order === null && i !== void 0) {
129
+ let n = e.slice();
130
+ for (let e of t.ops) {
131
+ if (e.op === "remove") continue;
132
+ let t = e.op === "mergeCells" ? f(e.path) : void 0, a = e.op === "mergeCells" ? r.has(t) ? t : Number(t) : e.value.id, o = i.get(a), s = r.get(a);
133
+ o !== void 0 && s !== void 0 && (n[o] = s);
134
+ }
135
+ return n;
136
+ }
137
+ let o = [];
138
+ if (t.order === null) for (let t of e) {
139
+ let e = r.get(t.id);
140
+ e !== void 0 && o.push(e);
141
+ }
142
+ else for (let e of t.order) {
143
+ let t = r.get(e);
144
+ t !== void 0 && o.push(t);
145
+ }
146
+ return o;
147
+ }, b = () => {
148
+ let e, t, n, r = () => {
149
+ e = void 0, t = void 0, n = void 0;
150
+ }, i = (e) => {
151
+ let r = /* @__PURE__ */ new Map(), i = Object.getPrototypeOf(e) === Array.prototype;
152
+ for (let t = 0; t < e.length; t++) {
153
+ let n = e[t];
154
+ r.has(n.id) && (i = !1), r.set(n.id, t);
155
+ }
156
+ n = i ? r : void 0, t = i ? void 0 : new Map(e.map((e) => [e.id, e]));
157
+ };
158
+ return {
159
+ reset: r,
160
+ apply: (a, o, s = {}) => {
161
+ (a !== e || n === void 0 && t === void 0) && i(a);
162
+ try {
163
+ let r = n, c = /* @__PURE__ */ new Map(), l = y(a, o, s, r === void 0 ? t : {
164
+ get: (e) => {
165
+ if (c.has(e)) return c.get(e);
166
+ let t = r.get(e);
167
+ return t === void 0 ? void 0 : a[t];
168
+ },
169
+ has: (e) => c.has(e) || r.has(e),
170
+ set: (e, t) => {
171
+ c.set(e, t);
172
+ }
173
+ }, r);
174
+ return (o.order !== null || o.ops.some((e) => e.op === "mergeCells" && "id" in e.value)) && i(l), e = l, l;
175
+ } catch (e) {
176
+ throw r(), e;
177
+ }
178
+ }
179
+ };
180
+ };
181
+ //#endregion
182
+ 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 };
@@ -0,0 +1,67 @@
1
+ import { RpcSchema as e } from "effect/rpc";
2
+ //#region src/schemaShape.ts
3
+ var t = (e) => typeof e == "object" && !!e && typeof e._tag == "string", n = 64, r = (e, i = 0) => {
4
+ if (!t(e)) return String(e);
5
+ if (i >= n) return "…";
6
+ let a = i + 1, o = (t) => Array.isArray(e[t]) ? e[t] : [], s = o("encoding").map((e) => r(e.to, a)).join("->"), c = o("checks").length, l = (e) => t(e) && e.context?.isOptional === !0, u = () => {
7
+ switch (e._tag) {
8
+ case "Suspend": return "S(…)";
9
+ case "Objects": {
10
+ let e = o("propertySignatures").map((e) => {
11
+ let t = e;
12
+ return `${String(t.name)}${l(t.type) ? "?" : ""}:${r(t.type, a)}`;
13
+ }).join(","), t = o("indexSignatures").map((e) => {
14
+ let t = e;
15
+ return `[${r(t.parameter, a)}]:${r(t.type, a)}`;
16
+ }).join(",");
17
+ return t === "" ? `{${e}}` : `{${e};${t}}`;
18
+ }
19
+ case "Union": return `U(${o("types").map((e) => r(e, a)).join("|")})`;
20
+ case "Arrays": {
21
+ let e = o("elements").map((e) => `${r(e, a)}${l(e) ? "?" : ""}`).join(","), t = o("rest").map((e) => r(e, a)).join(",");
22
+ return `A(${e}${t === "" ? "" : `...${t}`})`;
23
+ }
24
+ case "Declaration": return `D(${o("typeParameters").map((e) => r(e, a)).join(",")})`;
25
+ case "Literal": return `L(${String(e.literal)})`;
26
+ case "Enum": return `E(${o("enums").map((e) => e.map(String).join("=")).join(",")})`;
27
+ case "TemplateLiteral": return `TL(${o("parts").map((e) => r(e, a)).join(",")})`;
28
+ case "UniqueSymbol": return `Y(${String(e.symbol)})`;
29
+ default: return String(e);
30
+ }
31
+ }, d = c > 0 ? `R${c}(${u()})` : u();
32
+ return s === "" ? d : `T(${s}->${d})`;
33
+ }, i = (e) => {
34
+ let t = 2166136261;
35
+ for (let n = 0; n < e.length; n++) t ^= e.charCodeAt(n), t = Math.imul(t, 16777619) >>> 0;
36
+ return t.toString(16).padStart(8, "0");
37
+ }, a = (t) => {
38
+ if (t !== void 0 && e.isStreamSchema(t)) {
39
+ let e = t;
40
+ return `S(${r(e.success.ast)}|${r(e.error.ast)})`;
41
+ }
42
+ return r(t?.ast);
43
+ }, o = (e) => i([
44
+ r(e.payloadSchema?.ast),
45
+ a(e.successSchema),
46
+ r(e.errorSchema?.ast)
47
+ ].join("\0")), s = (e) => {
48
+ let t = {}, n = e.requests, r = n instanceof Map ? n.entries() : Array.isArray(n) ? n.map((e, t) => [t, e]) : [];
49
+ for (let [, e] of r) {
50
+ if (typeof e != "object" && typeof e != "function" || e === null) continue;
51
+ let n = e;
52
+ typeof n._tag == "string" && (t[n._tag] = o(n));
53
+ }
54
+ return t;
55
+ }, c = (e, t) => {
56
+ let n = [], r = [];
57
+ for (let [i, a] of Object.entries(t)) {
58
+ let t = e[i];
59
+ t === void 0 ? r.push(i) : t !== a && n.push(i);
60
+ }
61
+ return {
62
+ differing: n.sort(),
63
+ missingHere: r.sort()
64
+ };
65
+ };
66
+ //#endregion
67
+ export { c as compareSurfaces, s as groupShapeDigests, o as procedureShapeDigest, r as schemaShape, i as shapeDigest };
package/dist/scopes.js ADDED
@@ -0,0 +1,240 @@
1
+ import { RequestedTenantRefused as e } from "./tenantSelection.js";
2
+ import { Unauthenticated as t, currentSubjectAuthority as n, reauthorizeSubject as r } from "./auth.js";
3
+ import { Effect as i, Schema as a } from "effect";
4
+ //#region src/scopes.ts
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
+ required: a.String,
7
+ message: a.String
8
+ }) {}, f = class extends a.TaggedError()("NoSuchResource", {
9
+ resourceType: a.NullOr(a.String),
10
+ resourceId: a.String,
11
+ message: a.String
12
+ }) {}, p = (e) => "scopes" in e && e.scopes ? e.scopes : [], m = /* @__PURE__ */ new WeakMap(), h = /* @__PURE__ */ new WeakMap(), g = (e, t) => {
13
+ h.set(e, t);
14
+ }, _ = async (e, t) => {
15
+ let n = h.get(e);
16
+ n !== void 0 && (await n(t), h.set(t, n));
17
+ }, v = (e, t) => {
18
+ typeof e == "object" && e && m.set(e, t);
19
+ }, y = (e) => {
20
+ if (e = n(e), typeof e == "object" && e) {
21
+ let t = m.get(e);
22
+ if (t) return t;
23
+ }
24
+ return p(e);
25
+ }, b = (e, t) => {
26
+ let n = y(e);
27
+ return n.includes("admin:full") || n.includes(t);
28
+ }, x = (e, t) => {
29
+ let n = p(e);
30
+ return n.includes("admin:full") || n.includes(t);
31
+ }, S = (e, t) => b(e, t) ? i.void : i.fail(new d({
32
+ required: t,
33
+ message: `missing required scope '${t}'`
34
+ })), C = (e, t) => {
35
+ let n;
36
+ try {
37
+ n = typeof e.action == "function" ? e.action(t) : e.action;
38
+ } catch {
39
+ throw new d({
40
+ required: e.resourceType,
41
+ message: "policy action selector failed"
42
+ });
43
+ }
44
+ if (typeof n != "string" || n.trim() === "") throw new d({
45
+ required: e.resourceType,
46
+ message: "policy action selector returned no action"
47
+ });
48
+ return n;
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
+ let n = k(t);
51
+ if (e.type === "service") return n !== void 0 && n.includes(e.service) ? null : new d({
52
+ required: "service-procedure",
53
+ 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
+ });
55
+ if (n !== void 0) return U(e, new d({
56
+ required: `service:${n.join("|")}`,
57
+ message: `this procedure is callable only by the service${n.length === 1 ? "" : "s"} [${n.join(", ")}]`
58
+ }));
59
+ }, j = (e) => e.authenticated === !0, M = (e) => ({ open: e }), N = (e) => typeof e == "string" ? [e] : e, P, F = (e) => {
60
+ P = e;
61
+ }, I = (e) => P === void 0 ? e.filter((e) => (e.guards ?? []).some((e) => !w(e) && e.resource !== void 0)).map((e) => e.tag) : [], L = (e) => [
62
+ `${e.length} procedure${e.length === 1 ? "" : "s"} declare a per-resource guard that nothing enforces:`,
63
+ ...e.slice(0, 10).map((e) => ` ${e}`),
64
+ ...e.length > 10 ? [` … and ${e.length - 10} more`] : [],
65
+ "",
66
+ " `guards: [{ scope, resource }]` reads as \"may you do this to THIS resource\",",
67
+ " but with no resource-scope resolver registered the extractor is advisory and",
68
+ " the check runs against the caller's GLOBAL scopes. For an app whose",
69
+ " authorization is per-resource, that guard passes callers it should refuse.",
70
+ "",
71
+ " Fix it one of two ways:",
72
+ " • setResourceScopeResolver((req) => Effect<boolean>) — answers \"does this",
73
+ " subject hold `req.scope` on `req.resource`\" from your own tables.",
74
+ " • Drop the `resource` extractor if a global scope check is what you meant."
75
+ ].join("\n"), R = () => P, z, B = (e) => {
76
+ z = e;
77
+ }, V = () => z, H = (e) => new d({
78
+ required: "access-decision",
79
+ 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
+ }), U = (e, n) => {
81
+ let r = e.credentialRejected;
82
+ 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
+ }, W = (e) => {
84
+ let t = Array.isArray(e), n = Object.getPrototypeOf(e);
85
+ if (t ? n !== Array.prototype : n !== Object.prototype && n !== null) return !1;
86
+ 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
+ return !0;
88
+ }, G = (e, t) => {
89
+ let n, r = 0, i, a = 0, o;
90
+ return (s) => {
91
+ 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 ??= W(c) && W(e) && W(t) && t.every((e) => W(e) && (!("scope" in e) || typeof e.scope == "string" || W(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
+ };
94
+ }, K = (e, t, n) => {
95
+ let r = A(e, t);
96
+ if (r !== void 0) return r;
97
+ if (!t || t.length === 0) return n?.defaultDeny === !0 ? H(n.procedure) : null;
98
+ let i = 0, a;
99
+ for (let n of t) {
100
+ if (E(n) || D(n)) continue;
101
+ if (j(n)) {
102
+ if (e.id !== null && e.id !== void 0) continue;
103
+ return U(e, new d({
104
+ required: "authenticated",
105
+ message: "this procedure requires an authenticated caller"
106
+ }));
107
+ }
108
+ if (w(n)) {
109
+ if (i++, a === void 0 && (t.length >= 512 || i >= 512) && (a = G(e, t)), a === void 0 ? b(e, "admin:full") : a("admin:full")) continue;
110
+ return U(e, new d({
111
+ required: `${n.resourceType}:${n.action}`,
112
+ message: `relationship guard '${n.action}' on '${n.resourceType}' cannot be checked synchronously`
113
+ }));
114
+ }
115
+ let r = N(n.scope);
116
+ if (n.resourceOnly === !0) return U(e, new d({
117
+ required: r[0] ?? "resource",
118
+ message: "resource-only guard cannot be checked synchronously"
119
+ }));
120
+ if (r.length === 0) continue;
121
+ i += r.length, a === void 0 && (t.length >= 512 || i >= 512) && (a = G(e, t));
122
+ let o = n.mode ?? "all", s;
123
+ if (o === "any") {
124
+ if (a === void 0 ? r.some((t) => b(e, t)) : r.some(a)) continue;
125
+ s = r[0];
126
+ } else {
127
+ let t = a === void 0 ? r.find((t) => !b(e, t)) : r.find((e) => !a(e));
128
+ if (t === void 0) continue;
129
+ s = t;
130
+ }
131
+ return U(e, new d({
132
+ required: s,
133
+ message: o === "any" ? `missing all of required scopes [${r.join(", ")}]` : `missing required scope '${s}'`
134
+ }));
135
+ }
136
+ return null;
137
+ }, q = (e, t, n) => {
138
+ let r;
139
+ try {
140
+ r = C(t, n);
141
+ } catch (e) {
142
+ return i.succeed(e);
143
+ }
144
+ let a = (e) => new d({
145
+ required: `${t.resourceType}:${r}`,
146
+ message: e
147
+ });
148
+ if (b(e, "admin:full")) return i.succeed(null);
149
+ let o = z;
150
+ if (o === void 0) return i.succeed(a(`no policy resolver registered — cannot authorize '${r}' on '${t.resourceType}'`));
151
+ let s = t.resource(n);
152
+ return s === void 0 || s === "" ? i.succeed(a(`input does not identify a '${t.resourceType}' to authorize`)) : i.suspend(() => o({
153
+ subject: e,
154
+ action: r,
155
+ resourceType: t.resourceType,
156
+ resourceId: s
157
+ })).pipe(i.catchCause(() => i.succeed(!1)), i.map((n) => J(e, n, t.resourceType, s, () => a(`no '${r}' relation on ${t.resourceType}:${s}`))));
158
+ }, J = (e, t, n, r, i) => t === !0 ? null : t === "missing" && e.id !== null && e.id !== void 0 ? new f({
159
+ resourceType: n,
160
+ resourceId: r,
161
+ message: n === null ? `no such resource '${r}'` : `no such ${n} '${r}'`
162
+ }) : i(), Y = (e, t, n, r) => {
163
+ let a = A(e, t);
164
+ if (a !== void 0) return i.succeed(a);
165
+ if (!t || t.length === 0) return i.succeed(K(e, t, r));
166
+ let o = P, s = t.some(w), c = t.some((e) => "scope" in e && e.resourceOnly === !0);
167
+ return !s && !c && (!o || !t.some((e) => e.resource !== void 0)) ? i.succeed(K(e, t, r)) : i.gen(function* () {
168
+ for (let r of t) {
169
+ if (E(r) || D(r)) continue;
170
+ if (j(r)) {
171
+ if (e.id !== null && e.id !== void 0) continue;
172
+ return U(e, new d({
173
+ required: "authenticated",
174
+ message: "this procedure requires an authenticated caller"
175
+ }));
176
+ }
177
+ if (w(r)) {
178
+ let t = yield* q(e, r, n);
179
+ if (t) return t;
180
+ continue;
181
+ }
182
+ let t = N(r.scope);
183
+ if (t.length === 0) {
184
+ if (r.resourceOnly === !0) return U(e, new d({
185
+ required: "resource",
186
+ message: "resource-only guard requires a non-empty scope list"
187
+ }));
188
+ continue;
189
+ }
190
+ let a;
191
+ try {
192
+ a = r.resource ? r.resource(n) : void 0;
193
+ } catch (n) {
194
+ if (r.resourceOnly !== !0) throw n;
195
+ return U(e, new d({
196
+ required: t[0],
197
+ message: "resource selector failed"
198
+ }));
199
+ }
200
+ if (r.resourceOnly === !0 && (o === void 0 || typeof a != "string" || a === "")) return U(e, new d({
201
+ required: t[0],
202
+ message: "resource-only guard requires a resolver and a non-empty resource id"
203
+ }));
204
+ let s = [], c = !1;
205
+ for (let n of t) if (r.resourceOnly !== !0 && b(e, n)) s.push(!0);
206
+ else if (a !== void 0 && o !== void 0) {
207
+ let t = yield* i.suspend(() => o({
208
+ subject: e,
209
+ scope: n,
210
+ resource: a
211
+ })).pipe(i.catchCause(() => i.succeed(!1)));
212
+ t === "missing" && (c = !0), s.push(t === !0);
213
+ } else s.push(!1);
214
+ let l = r.mode ?? "all";
215
+ if (!(l === "any" ? s.some(Boolean) : s.every(Boolean))) {
216
+ let n = l === "any" ? t[0] : t[t.findIndex((e, t) => !s[t])];
217
+ if (c && a !== void 0) {
218
+ let t = J(e, "missing", null, a, () => new d({
219
+ required: n,
220
+ message: `missing required scope '${n}' on resource '${a}'`
221
+ }));
222
+ if (t !== null) return t;
223
+ }
224
+ return new d({
225
+ required: n,
226
+ message: l === "any" ? `missing all of required scopes [${t.join(", ")}]` : `missing required scope '${n}'` + (a === void 0 ? "" : ` on resource '${a}'`)
227
+ });
228
+ }
229
+ }
230
+ return null;
231
+ });
232
+ }, X = (n, o, s, c) => i.tryPromise({
233
+ try: async () => r(n, (e) => _(n, e)),
234
+ catch: (e) => e
235
+ }).pipe(i.matchEffect({
236
+ onFailure: (n) => a.is(t)(n) || a.is(e)(n) ? i.succeed(n) : i.die(n),
237
+ onSuccess: (e) => Y(e, o, s, c)
238
+ }));
239
+ //#endregion
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 };