@classytic/arc 2.22.0 → 2.23.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/dist/{BaseController-C6FlRWxF.mjs → BaseController-BQ8KNvWC.mjs} +3 -2
- package/dist/{ResourceRegistry-7RnrEWNP.mjs → ResourceRegistry-y9Hnypus.mjs} +1 -0
- package/dist/{actionPermissions-ze70xXJi.mjs → actionPermissions-lszoJle1.mjs} +1 -1
- package/dist/applyPermissionResult-Tw4iXtlf.mjs +264 -0
- package/dist/audit/index.d.mts +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +2 -2
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/cli/index.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +3 -3
- package/dist/{core-b6fgFgnd.mjs → core-DQ6rDTyH.mjs} +10 -9
- package/dist/{createActionRouter-h1cEEaEX.mjs → createActionRouter-BuOv-m4Y.mjs} +3 -3
- package/dist/{createAggregationRouter-B1C0kvTL.mjs → createAggregationRouter-CgJv_BU_.mjs} +1 -1
- package/dist/{createApp-Ci7yG5gv.mjs → createApp-CjOeWJ9_.mjs} +11 -2
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/{errorHandler-BTzXSwIg.mjs → errorHandler-Bq2OeEQL.mjs} +10 -7
- package/dist/events/index.mjs +5 -2
- package/dist/factory/index.d.mts +20 -4
- package/dist/factory/index.mjs +31 -11
- package/dist/{fastify-augmentation-9_fuetB4.d.mts → fastify-augmentation-g_f9omSc.d.mts} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +7 -0
- package/dist/idempotency/index.mjs +5 -17
- package/dist/{index-DbtgCOCj.d.mts → index-BBsvQt7U.d.mts} +26 -4
- package/dist/{index-BEu4wjbL.d.mts → index-Ba10fdKp.d.mts} +11 -2
- package/dist/{index-D8MKYGDa.d.mts → index-CC5ruDGh.d.mts} +2 -2
- package/dist/{index-ogIHvOjo.d.mts → index-wMoWBLkn.d.mts} +67 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +6 -5
- package/dist/{init-DleK3p9f.mjs → init-CjO4p_q1.mjs} +5 -2
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +66 -3
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/webhooks.d.mts +123 -3
- package/dist/integrations/webhooks.mjs +160 -5
- package/dist/interface-n5hpKg1d.mjs +16 -0
- package/dist/{loadResourcesFromEntry-OMCvIEE7.mjs → loadResourcesFromEntry-kvGT6EcO.mjs} +1 -1
- package/dist/{mcpPlugin-ByA2tf6D.mjs → mcpPlugin-BtzIL_kM.mjs} +308 -39
- package/dist/middleware/index.d.mts +1 -1
- package/dist/{openapi-BRpMZD7C.mjs → openapi-jSDx-VDv.mjs} +3 -3
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +3 -2
- package/dist/{permissions-BJMuKMl7.mjs → permissions-tbxFHxjZ.mjs} +77 -264
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +6 -6
- package/dist/plugins/index.mjs +5 -4
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +1 -1
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/search.d.mts +1 -1
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-gw0ciIUD.mjs → presets-BOe4Ugkl.mjs} +1 -1
- package/dist/realtime-I8OrfnMR.mjs +375 -0
- package/dist/{registerRoute-xHc42fwB.mjs → registerRoute-CWO6mdYe.mjs} +1 -1
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +1 -1
- package/dist/{schemaConverter-Ds5reSGs.mjs → schemaConverter-DJvodiHj.mjs} +4 -1
- package/dist/{schemaIR-B-6SPe7g.mjs → schemaIR-Ca7ySNPx.mjs} +1 -1
- package/dist/scope/index.mjs +1 -1
- package/dist/scope-LONQ3mfZ.mjs +37 -0
- package/dist/simpleEqualityMatcher-Cg05HPsn.mjs +68 -0
- package/dist/{sse-CfUjwjDk.mjs → sse-0u4P4-OI.mjs} +7 -30
- package/dist/sseStream-BQ7Qaynp.mjs +57 -0
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +2 -2
- package/dist/types/index.d.mts +1 -1
- package/dist/{types-Bc42CUyk.d.mts → types-5OuqeTDX.d.mts} +37 -2
- package/dist/utils/index.d.mts +62 -2
- package/dist/utils/index.mjs +5 -3
- package/dist/{utils-FhJ88TJE.mjs → utils-CZyeRXTh.mjs} +21 -69
- package/dist/{versioning-DLwklPlG.d.mts → versioning-D6PvCwpq.d.mts} +43 -4
- package/package.json +64 -4
- package/skills/arc/references/production.md +734 -696
- package/dist/scope-k15RXfcq.mjs +0 -64
|
@@ -3,269 +3,6 @@ import { C as isService, S as isOrgInScope, a as getDPoPJkt, b as isElevated, d
|
|
|
3
3
|
import { t as getUserRoles } from "./types-XTApa8b6.mjs";
|
|
4
4
|
import { t as MemoryCacheStore } from "./memory-CLXA2VeJ.mjs";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
|
-
//#region src/permissions/fields.ts
|
|
7
|
-
/**
|
|
8
|
-
* Field-Level Permissions
|
|
9
|
-
*
|
|
10
|
-
* Control field visibility and writability per role.
|
|
11
|
-
* Integrated into the response path (read) and sanitization path (write).
|
|
12
|
-
*
|
|
13
|
-
* @example
|
|
14
|
-
* ```typescript
|
|
15
|
-
* import { fields, defineResource } from '@classytic/arc';
|
|
16
|
-
*
|
|
17
|
-
* const userResource = defineResource({
|
|
18
|
-
* name: 'user',
|
|
19
|
-
* adapter: userAdapter,
|
|
20
|
-
* fields: {
|
|
21
|
-
* salary: fields.visibleTo(['admin', 'hr']),
|
|
22
|
-
* internalNotes: fields.writableBy(['admin']),
|
|
23
|
-
* email: fields.redactFor(['viewer']),
|
|
24
|
-
* password: fields.hidden(),
|
|
25
|
-
* },
|
|
26
|
-
* });
|
|
27
|
-
* ```
|
|
28
|
-
*/
|
|
29
|
-
/** Type guard for Mongoose-like documents with toObject() */
|
|
30
|
-
function isMongooseDoc(obj) {
|
|
31
|
-
return !!obj && typeof obj === "object" && "toObject" in obj && typeof obj.toObject === "function";
|
|
32
|
-
}
|
|
33
|
-
const fields = {
|
|
34
|
-
/**
|
|
35
|
-
* Field is never included in responses. Not writable via API.
|
|
36
|
-
*
|
|
37
|
-
* @example
|
|
38
|
-
* ```typescript
|
|
39
|
-
* fields: { password: fields.hidden() }
|
|
40
|
-
* ```
|
|
41
|
-
*/
|
|
42
|
-
hidden() {
|
|
43
|
-
return { _type: "hidden" };
|
|
44
|
-
},
|
|
45
|
-
/**
|
|
46
|
-
* Field is only visible to users with specified roles.
|
|
47
|
-
* Other users don't see the field at all.
|
|
48
|
-
*
|
|
49
|
-
* @example
|
|
50
|
-
* ```typescript
|
|
51
|
-
* fields: { salary: fields.visibleTo(['admin', 'hr']) }
|
|
52
|
-
* ```
|
|
53
|
-
*/
|
|
54
|
-
visibleTo(roles) {
|
|
55
|
-
return {
|
|
56
|
-
_type: "visibleTo",
|
|
57
|
-
roles
|
|
58
|
-
};
|
|
59
|
-
},
|
|
60
|
-
/**
|
|
61
|
-
* Field is only writable by users with specified roles.
|
|
62
|
-
* All users can still read the field. Users without the role
|
|
63
|
-
* have the field silently stripped from write operations.
|
|
64
|
-
*
|
|
65
|
-
* @example
|
|
66
|
-
* ```typescript
|
|
67
|
-
* fields: { role: fields.writableBy(['admin']) }
|
|
68
|
-
* ```
|
|
69
|
-
*/
|
|
70
|
-
writableBy(roles) {
|
|
71
|
-
return {
|
|
72
|
-
_type: "writableBy",
|
|
73
|
-
roles
|
|
74
|
-
};
|
|
75
|
-
},
|
|
76
|
-
/**
|
|
77
|
-
* Field is redacted (replaced with a placeholder) for specified roles.
|
|
78
|
-
* Other users see the real value.
|
|
79
|
-
*
|
|
80
|
-
* @param roles - Roles that see the redacted value
|
|
81
|
-
* @param redactValue - Replacement value (default: '***')
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* ```typescript
|
|
85
|
-
* fields: {
|
|
86
|
-
* email: fields.redactFor(['viewer']),
|
|
87
|
-
* ssn: fields.redactFor(['basic'], '***-**-****'),
|
|
88
|
-
* }
|
|
89
|
-
* ```
|
|
90
|
-
*/
|
|
91
|
-
redactFor(roles, redactValue = "***") {
|
|
92
|
-
return {
|
|
93
|
-
_type: "redactFor",
|
|
94
|
-
roles,
|
|
95
|
-
redactValue
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
};
|
|
99
|
-
/**
|
|
100
|
-
* Apply field-level READ permissions to a response object.
|
|
101
|
-
* Strips hidden fields, enforces visibility, and applies redaction.
|
|
102
|
-
*
|
|
103
|
-
* @param data - The response object (mutated in place for performance)
|
|
104
|
-
* @param fieldPermissions - Field permission map from resource config
|
|
105
|
-
* @param userRoles - Current user's roles (empty array for unauthenticated)
|
|
106
|
-
* @returns The filtered object
|
|
107
|
-
*/
|
|
108
|
-
function applyFieldReadPermissions(data, fieldPermissions, userRoles) {
|
|
109
|
-
if (!data || typeof data !== "object") return data;
|
|
110
|
-
const result = { ...isMongooseDoc(data) ? data.toObject() : data };
|
|
111
|
-
for (const [field, perm] of Object.entries(fieldPermissions)) switch (perm._type) {
|
|
112
|
-
case "hidden":
|
|
113
|
-
delete result[field];
|
|
114
|
-
break;
|
|
115
|
-
case "visibleTo":
|
|
116
|
-
if (!perm.roles?.some((r) => userRoles.includes(r))) delete result[field];
|
|
117
|
-
break;
|
|
118
|
-
case "redactFor":
|
|
119
|
-
if (perm.roles?.some((r) => userRoles.includes(r))) result[field] = perm.redactValue ?? "***";
|
|
120
|
-
break;
|
|
121
|
-
case "writableBy": break;
|
|
122
|
-
}
|
|
123
|
-
return result;
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* Apply field-level WRITE permissions to request body.
|
|
127
|
-
*
|
|
128
|
-
* Returns both the filtered body and the list of denied fields. Callers are
|
|
129
|
-
* expected to reject the request when `deniedFields.length > 0` — silently
|
|
130
|
-
* stripping fields hides misconfigurations and real attacks. See
|
|
131
|
-
* `BodySanitizer` for the default policy.
|
|
132
|
-
*
|
|
133
|
-
* @param body - The request body (returns a new filtered copy)
|
|
134
|
-
* @param fieldPermissions - Field permission map from resource config
|
|
135
|
-
* @param userRoles - Current user's roles
|
|
136
|
-
*/
|
|
137
|
-
function applyFieldWritePermissions(body, fieldPermissions, userRoles) {
|
|
138
|
-
const result = { ...body };
|
|
139
|
-
const deniedFields = [];
|
|
140
|
-
for (const [field, perm] of Object.entries(fieldPermissions)) switch (perm._type) {
|
|
141
|
-
case "hidden":
|
|
142
|
-
if (field in result) {
|
|
143
|
-
deniedFields.push(field);
|
|
144
|
-
delete result[field];
|
|
145
|
-
}
|
|
146
|
-
break;
|
|
147
|
-
case "writableBy":
|
|
148
|
-
if (field in result && !perm.roles?.some((r) => userRoles.includes(r))) {
|
|
149
|
-
deniedFields.push(field);
|
|
150
|
-
delete result[field];
|
|
151
|
-
}
|
|
152
|
-
break;
|
|
153
|
-
}
|
|
154
|
-
return {
|
|
155
|
-
body: result,
|
|
156
|
-
deniedFields
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
/**
|
|
160
|
-
* Resolve effective roles by merging global user roles with org-level roles.
|
|
161
|
-
*
|
|
162
|
-
* Global roles come from `req.user.role` (normalized via getUserRoles()).
|
|
163
|
-
* Org roles come from `req.context.orgRoles` (set by BA adapter's org bridge).
|
|
164
|
-
*
|
|
165
|
-
* When no org context exists, returns global roles only — backward compatible.
|
|
166
|
-
*/
|
|
167
|
-
function resolveEffectiveRoles(userRoles, orgRoles) {
|
|
168
|
-
if (orgRoles.length === 0) return [...userRoles];
|
|
169
|
-
if (userRoles.length === 0) return [...orgRoles];
|
|
170
|
-
return [.../* @__PURE__ */ new Set([...userRoles, ...orgRoles])];
|
|
171
|
-
}
|
|
172
|
-
//#endregion
|
|
173
|
-
//#region src/permissions/applyPermissionResult.ts
|
|
174
|
-
/**
|
|
175
|
-
* Normalize a permission check return value (`boolean | PermissionResult`)
|
|
176
|
-
* into a concrete `PermissionResult`. This is the only place in Arc that
|
|
177
|
-
* promotes booleans to results — keeps the type narrowing honest everywhere.
|
|
178
|
-
*/
|
|
179
|
-
function normalizePermissionResult(result) {
|
|
180
|
-
if (typeof result === "boolean") return { granted: result };
|
|
181
|
-
return result;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* Apply a granted `PermissionResult` to a Fastify request — merges row-level
|
|
185
|
-
* filters into `_policyFilters` and conditionally installs the scope.
|
|
186
|
-
*
|
|
187
|
-
* **Scope install rule:** only writes `scope` when the current request scope
|
|
188
|
-
* is absent or `public`. This prevents downgrading an already-authenticated
|
|
189
|
-
* request (e.g. Better Auth set `member`, then a permission check returns a
|
|
190
|
-
* narrower `service` scope — the original `member` wins because it came from
|
|
191
|
-
* a more authoritative source).
|
|
192
|
-
*
|
|
193
|
-
* Safe to call with a non-granted result — it simply no-ops. Callers should
|
|
194
|
-
* still check `result.granted` and send an error response before reaching here,
|
|
195
|
-
* but this function tolerates the misuse defensively.
|
|
196
|
-
*/
|
|
197
|
-
function applyPermissionResult(result, request) {
|
|
198
|
-
if (!result.granted) return;
|
|
199
|
-
if (result.filters) request._policyFilters = {
|
|
200
|
-
...request._policyFilters ?? {},
|
|
201
|
-
...result.filters
|
|
202
|
-
};
|
|
203
|
-
if (result.scope) {
|
|
204
|
-
const current = request.scope;
|
|
205
|
-
if (!current || current.kind === "public") request.scope = result.scope;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Max length of a `PermissionResult.reason` string before we fall back to the
|
|
210
|
-
* generic default message. Upstream checks can return arbitrary strings; we
|
|
211
|
-
* clamp to prevent accidental leakage of internal diagnostics or oversized
|
|
212
|
-
* payloads via the 4xx response body.
|
|
213
|
-
*/
|
|
214
|
-
const MAX_DENIAL_REASON_LENGTH = 100;
|
|
215
|
-
/**
|
|
216
|
-
* End-to-end evaluator: runs the permission check, catches throws, normalizes
|
|
217
|
-
* the result, sends a 401/403 response on denial, and applies side-effects on
|
|
218
|
-
* grant. Returns `true` if the caller should continue, `false` if a response
|
|
219
|
-
* has been sent and the caller should return.
|
|
220
|
-
*
|
|
221
|
-
* This is the single source of truth for the 5-step sequence shared by the
|
|
222
|
-
* CRUD router, action router, and MCP tool handlers:
|
|
223
|
-
*
|
|
224
|
-
* 1. `try { await check(ctx) } catch { reply 403 }`
|
|
225
|
-
* 2. `normalizePermissionResult(result)`
|
|
226
|
-
* 3. If denied → 401 (no user) or 403 (user) with clamped reason
|
|
227
|
-
* 4. If granted → `applyPermissionResult` (filters + scope)
|
|
228
|
-
* 5. Return true/false so the caller knows whether to keep going
|
|
229
|
-
*
|
|
230
|
-
* Context construction, pre-check auth gating, and success-path handler
|
|
231
|
-
* invocation stay at the callsite — those are genuinely different per router
|
|
232
|
-
* and don't belong here.
|
|
233
|
-
*
|
|
234
|
-
* @returns `true` if authorized (caller continues), `false` if a response was sent
|
|
235
|
-
*/
|
|
236
|
-
async function evaluateAndApplyPermission(check, context, request, reply, opts) {
|
|
237
|
-
let result;
|
|
238
|
-
try {
|
|
239
|
-
result = await check(context);
|
|
240
|
-
} catch (err) {
|
|
241
|
-
request.log?.warn?.({
|
|
242
|
-
err,
|
|
243
|
-
resource: context.resource,
|
|
244
|
-
action: context.action
|
|
245
|
-
}, "Permission check threw");
|
|
246
|
-
reply.code(403).send({
|
|
247
|
-
code: "arc.forbidden",
|
|
248
|
-
message: "Permission denied",
|
|
249
|
-
status: 403
|
|
250
|
-
});
|
|
251
|
-
return false;
|
|
252
|
-
}
|
|
253
|
-
const permResult = normalizePermissionResult(result);
|
|
254
|
-
if (!permResult.granted) {
|
|
255
|
-
const defaultMsg = opts?.defaultDenialMessage?.(context.user) ?? (context.user ? "Permission denied" : "Authentication required");
|
|
256
|
-
const reason = permResult.reason && permResult.reason.length <= MAX_DENIAL_REASON_LENGTH ? permResult.reason : defaultMsg;
|
|
257
|
-
const status = context.user ? 403 : 401;
|
|
258
|
-
reply.code(status).send({
|
|
259
|
-
code: context.user ? "arc.forbidden" : "arc.unauthorized",
|
|
260
|
-
message: reason,
|
|
261
|
-
status
|
|
262
|
-
});
|
|
263
|
-
return false;
|
|
264
|
-
}
|
|
265
|
-
applyPermissionResult(permResult, request);
|
|
266
|
-
return true;
|
|
267
|
-
}
|
|
268
|
-
//#endregion
|
|
269
6
|
//#region src/permissions/agent.ts
|
|
270
7
|
/**
|
|
271
8
|
* Agent-Auth Permission Helpers — DPoP + capability mandates for AI-agent flows
|
|
@@ -1315,6 +1052,82 @@ function createDynamicPermissionMatrix(config) {
|
|
|
1315
1052
|
};
|
|
1316
1053
|
}
|
|
1317
1054
|
//#endregion
|
|
1055
|
+
//#region src/permissions/grants.ts
|
|
1056
|
+
/**
|
|
1057
|
+
* The grant-mode lattice, weakest → strongest. Holding a mode satisfies
|
|
1058
|
+
* every mode at or below it (`write` ⊇ `read` ⊇ `list` ⊇ `see`); `manage`
|
|
1059
|
+
* (grant/revoke rights) satisfies everything. Same semantics as Puter's
|
|
1060
|
+
* `see < list < read < write` hierarchy with `manage` folded into the
|
|
1061
|
+
* lattice top instead of a separate string namespace.
|
|
1062
|
+
*/
|
|
1063
|
+
const GRANT_MODES = [
|
|
1064
|
+
"see",
|
|
1065
|
+
"list",
|
|
1066
|
+
"read",
|
|
1067
|
+
"write",
|
|
1068
|
+
"manage"
|
|
1069
|
+
];
|
|
1070
|
+
/**
|
|
1071
|
+
* Does a HELD mode satisfy a REQUIRED mode? Lattice implication —
|
|
1072
|
+
* `modeSatisfies('write', 'read') === true`, `modeSatisfies('see', 'read')
|
|
1073
|
+
* === false`. Unknown strings (a corrupted grant row) never satisfy
|
|
1074
|
+
* anything: fail-closed.
|
|
1075
|
+
*/
|
|
1076
|
+
function modeSatisfies(held, required) {
|
|
1077
|
+
if (held === void 0) return false;
|
|
1078
|
+
const heldRank = GRANT_MODES.indexOf(held);
|
|
1079
|
+
if (heldRank === -1) return false;
|
|
1080
|
+
return heldRank >= GRANT_MODES.indexOf(required);
|
|
1081
|
+
}
|
|
1082
|
+
/**
|
|
1083
|
+
* Per-record grant gate. Same combinator tier as `requireOwnership` —
|
|
1084
|
+
* compose with `anyOf`/`allOf` like any other `PermissionCheck`.
|
|
1085
|
+
*
|
|
1086
|
+
* Fail-closed contract: resolver throws → denied (logged via
|
|
1087
|
+
* `ctx.request.log`); resolution carries neither `mode` nor `filters` →
|
|
1088
|
+
* denied; unknown/corrupted mode strings → denied.
|
|
1089
|
+
*/
|
|
1090
|
+
function requireGrant(options) {
|
|
1091
|
+
const { mode: required, resolve, bypassRoles } = options;
|
|
1092
|
+
return async (ctx) => {
|
|
1093
|
+
if (bypassRoles && ctx.user && getUserRoles(ctx.user).some((r) => bypassRoles.includes(r))) return true;
|
|
1094
|
+
let resolution;
|
|
1095
|
+
try {
|
|
1096
|
+
resolution = await resolve(ctx);
|
|
1097
|
+
} catch (err) {
|
|
1098
|
+
ctx.request.log?.warn?.({
|
|
1099
|
+
err,
|
|
1100
|
+
resource: ctx.resource,
|
|
1101
|
+
action: ctx.action
|
|
1102
|
+
}, "requireGrant: resolve threw — denying (fail-closed)");
|
|
1103
|
+
return {
|
|
1104
|
+
granted: false,
|
|
1105
|
+
reason: "Grant lookup failed"
|
|
1106
|
+
};
|
|
1107
|
+
}
|
|
1108
|
+
if (typeof resolution === "boolean") return resolution;
|
|
1109
|
+
const { mode: held, filters, reason } = resolution;
|
|
1110
|
+
if (held !== void 0) {
|
|
1111
|
+
if (!modeSatisfies(held, required)) return {
|
|
1112
|
+
granted: false,
|
|
1113
|
+
...reason ? { reason } : {}
|
|
1114
|
+
};
|
|
1115
|
+
return {
|
|
1116
|
+
granted: true,
|
|
1117
|
+
...filters ? { filters } : {}
|
|
1118
|
+
};
|
|
1119
|
+
}
|
|
1120
|
+
if (filters !== void 0) return {
|
|
1121
|
+
granted: true,
|
|
1122
|
+
filters
|
|
1123
|
+
};
|
|
1124
|
+
return {
|
|
1125
|
+
granted: false,
|
|
1126
|
+
...reason ? { reason } : {}
|
|
1127
|
+
};
|
|
1128
|
+
};
|
|
1129
|
+
}
|
|
1130
|
+
//#endregion
|
|
1318
1131
|
//#region src/permissions/roleHierarchy.ts
|
|
1319
1132
|
/**
|
|
1320
1133
|
* Create a role hierarchy from a parent → children map.
|
|
@@ -1530,4 +1343,4 @@ function readOnly(overrides) {
|
|
|
1530
1343
|
}, overrides);
|
|
1531
1344
|
}
|
|
1532
1345
|
//#endregion
|
|
1533
|
-
export {
|
|
1346
|
+
export { roles as A, allowPublic as C, requireAuth as D, not as E, requireAgentScope as M, requireDPoP as N, requireOwnership as O, requireMandate as P, allOf as S, denyAll as T, requireOrgMembership as _, permissionMatrix as a, requireServiceScope as b, publicReadAdminWrite as c, GRANT_MODES as d, modeSatisfies as f, requireOrgInScope as g, createOrgPermissions as h, ownerWithAdminBypass as i, when as j, requireRoles as k, readOnly as l, createDynamicPermissionMatrix as m, authenticated as n, presets_exports as o, requireGrant as p, fullPublic as r, publicRead as s, adminOnly as t, createRoleHierarchy as u, requireOrgRole as v, anyOf as w, requireTeamMembership as x, requireScopeContext as y };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ct as PipelineStep, Rt as IControllerResponse, St as PipelineContext, _t as Guard, bt as OperationFilter, vt as Interceptor, wt as Transform, xt as PipelineConfig, yt as NextFunction } from "../index-
|
|
1
|
+
import { Ct as PipelineStep, Rt as IControllerResponse, St as PipelineContext, _t as Guard, bt as OperationFilter, vt as Interceptor, wt as Transform, xt as PipelineConfig, yt as NextFunction } from "../index-BBsvQt7U.mjs";
|
|
2
2
|
//#region src/pipeline/guard.d.ts
|
|
3
3
|
interface GuardOptions {
|
|
4
4
|
operations?: OperationFilter;
|
package/dist/plugins/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { At as RouteDefinition, J as PresetHook,
|
|
1
|
+
import { At as RouteDefinition, J as PresetHook, Jt as AnyRecord, Q as MiddlewareConfig, et as RouteSchemaOptions } from "../index-BBsvQt7U.mjs";
|
|
2
2
|
import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-C6yv4ZTW.mjs";
|
|
3
|
-
import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-
|
|
4
|
-
import { _ as
|
|
3
|
+
import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as PluginMeta, t as ArcCore } from "../fastify-augmentation-g_f9omSc.mjs";
|
|
4
|
+
import { C as healthPlugin, S as _default$3, _ as CachingRule, a as MetricsCollector, b as HealthCheck, c as metricsPlugin, d as _default$5, f as realtimePlugin, g as CachingOptions, h as ssePlugin, i as MetricEntry, l as ChangeOperation, m as _default$8, n as _default$9, o as MetricsOptions, p as SSEOptions, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as RealtimeOptions, v as _default$1, x as HealthOptions, y as cachingPlugin } from "../versioning-D6PvCwpq.mjs";
|
|
5
5
|
import { t as TracingOptions } from "../tracing-CsGKQJGg.mjs";
|
|
6
6
|
import { PaginatedResult } from "@classytic/repo-core/pagination";
|
|
7
7
|
import { FastifyInstance, FastifyPluginAsync } from "fastify";
|
|
@@ -163,7 +163,7 @@ declare function createRequestIdGenerator(opts?: Pick<RequestIdOptions, "header"
|
|
|
163
163
|
headers: Record<string, string | string[] | undefined>;
|
|
164
164
|
}) => string;
|
|
165
165
|
declare const requestIdPlugin: FastifyPluginAsync<RequestIdOptions>;
|
|
166
|
-
declare const _default$
|
|
166
|
+
declare const _default$6: FastifyPluginAsync<RequestIdOptions>;
|
|
167
167
|
//#endregion
|
|
168
168
|
//#region src/plugins/schedules.d.ts
|
|
169
169
|
/**
|
|
@@ -236,6 +236,6 @@ declare module "fastify" {
|
|
|
236
236
|
}
|
|
237
237
|
}
|
|
238
238
|
declare const schedulesPlugin: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
239
|
-
declare const _default$
|
|
239
|
+
declare const _default$7: FastifyPluginAsync<SchedulesPluginOptions>;
|
|
240
240
|
//#endregion
|
|
241
|
-
export { type ArcCore, type ArcCorePluginOptions, type ArcPlugin, type CachingOptions, type CachingRule, type CreatePluginDefinition, type ErrorHandlerOptions, type ErrorMapper, type GracefulShutdownOptions, type HealthCheck, type HealthOptions, type MetricEntry, type MetricsCollector, type MetricsOptions, type PluginMeta, type PluginResourceResult, type RequestIdOptions, type SSEOptions, type ScheduleDefinition, type ScheduleLockLike, type ScheduleStats, type SchedulesPluginOptions, type TracingOptions, type VersioningOptions, _default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, _default$1 as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, createRequestIdGenerator, defaultIsDuplicateKeyError, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, _default$2 as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, _default$3 as healthPlugin, healthPlugin as healthPluginFn, _default$4 as metricsPlugin, metricsPlugin as metricsPluginFn, replyHelpersPlugin, _default$
|
|
241
|
+
export { type ArcCore, type ArcCorePluginOptions, type ArcPlugin, type CachingOptions, type CachingRule, type ChangeOperation, type CreatePluginDefinition, type ErrorHandlerOptions, type ErrorMapper, type GracefulShutdownOptions, type HealthCheck, type HealthOptions, type MetricEntry, type MetricsCollector, type MetricsOptions, type PluginMeta, type PluginResourceResult, type RealtimeOptions, type RequestIdOptions, type SSEOptions, type ScheduleDefinition, type ScheduleLockLike, type ScheduleStats, type SchedulesPluginOptions, type TracingOptions, type VersioningOptions, _default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, _default$1 as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, createRequestIdGenerator, defaultIsDuplicateKeyError, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, _default$2 as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, _default$3 as healthPlugin, healthPlugin as healthPluginFn, _default$4 as metricsPlugin, metricsPlugin as metricsPluginFn, _default$5 as realtimePlugin, realtimePlugin as realtimePluginFn, replyHelpersPlugin, _default$6 as requestIdPlugin, requestIdPlugin as requestIdPluginFn, sanitizeRequestId, _default$7 as schedulesPlugin, schedulesPlugin as schedulesPluginFn, _default$8 as ssePlugin, ssePlugin as ssePluginFn, _default$9 as versioningPlugin, versioningPlugin as versioningPluginFn };
|
package/dist/plugins/index.mjs
CHANGED
|
@@ -3,14 +3,15 @@ import { c as getOrgId } from "../types-bHblZ9YN.mjs";
|
|
|
3
3
|
import { n as requestContext } from "../requestContext-BZKOr13H.mjs";
|
|
4
4
|
import { t as hasEvents } from "../typeGuards-C9KXUly6.mjs";
|
|
5
5
|
import { t as HookSystem } from "../HookSystem-C1vB_Gc9.mjs";
|
|
6
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
6
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-y9Hnypus.mjs";
|
|
7
7
|
import { i as sanitizeRequestId, n as requestIdPlugin, r as requestId_default, t as createRequestIdGenerator } from "../requestId-5BhTVzBv.mjs";
|
|
8
8
|
import { n as health_default, t as healthPlugin } from "../health-ScyjIVo5.mjs";
|
|
9
9
|
import { n as caching_default, t as cachingPlugin } from "../caching-_NJeDd1_.mjs";
|
|
10
|
-
import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-
|
|
10
|
+
import { n as errorHandlerPlugin, t as defaultIsDuplicateKeyError } from "../errorHandler-Bq2OeEQL.mjs";
|
|
11
11
|
import { n as metrics_default, t as metricsPlugin } from "../metrics-fdxI5mn_.mjs";
|
|
12
|
+
import { n as realtime_default, t as realtimePlugin } from "../realtime-I8OrfnMR.mjs";
|
|
12
13
|
import { t as replyHelpersPlugin } from "../replyHelpers-67tRawQZ.mjs";
|
|
13
|
-
import { n as sse_default, t as ssePlugin } from "../sse-
|
|
14
|
+
import { n as sse_default, t as ssePlugin } from "../sse-0u4P4-OI.mjs";
|
|
14
15
|
import { n as versioning_default, t as versioningPlugin } from "../versioning-Dk-71iIz.mjs";
|
|
15
16
|
import fp from "fastify-plugin";
|
|
16
17
|
//#region src/core/arcCorePlugin.ts
|
|
@@ -287,4 +288,4 @@ var schedules_default = fp(schedulesPlugin, {
|
|
|
287
288
|
fastify: "5.x"
|
|
288
289
|
});
|
|
289
290
|
//#endregion
|
|
290
|
-
export { arcCorePlugin_default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, caching_default as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, createRequestIdGenerator, defaultIsDuplicateKeyError, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, gracefulShutdown_default as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, health_default as healthPlugin, healthPlugin as healthPluginFn, metrics_default as metricsPlugin, metricsPlugin as metricsPluginFn, replyHelpersPlugin, requestId_default as requestIdPlugin, requestIdPlugin as requestIdPluginFn, sanitizeRequestId, schedules_default as schedulesPlugin, schedulesPlugin as schedulesPluginFn, sse_default as ssePlugin, ssePlugin as ssePluginFn, versioning_default as versioningPlugin, versioningPlugin as versioningPluginFn };
|
|
291
|
+
export { arcCorePlugin_default as arcCorePlugin, arcCorePlugin as arcCorePluginFn, caching_default as cachingPlugin, cachingPlugin as cachingPluginFn, createPlugin, createRequestIdGenerator, defaultIsDuplicateKeyError, errorHandlerPlugin, errorHandlerPlugin as errorHandlerPluginFn, gracefulShutdown_default as gracefulShutdownPlugin, gracefulShutdownPlugin as gracefulShutdownPluginFn, health_default as healthPlugin, healthPlugin as healthPluginFn, metrics_default as metricsPlugin, metricsPlugin as metricsPluginFn, realtime_default as realtimePlugin, realtimePlugin as realtimePluginFn, replyHelpersPlugin, requestId_default as requestIdPlugin, requestIdPlugin as requestIdPluginFn, sanitizeRequestId, schedules_default as schedulesPlugin, schedulesPlugin as schedulesPluginFn, sse_default as ssePlugin, ssePlugin as ssePluginFn, versioning_default as versioningPlugin, versioningPlugin as versioningPluginFn };
|
|
@@ -58,7 +58,7 @@ try {
|
|
|
58
58
|
function createTracerProvider(options) {
|
|
59
59
|
if (!isAvailable || !NodeTracerProvider || !BatchSpanProcessor || !OTLPTraceExporter) return null;
|
|
60
60
|
const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
|
|
61
|
-
const resolvedVersion = serviceVersion ?? "2.
|
|
61
|
+
const resolvedVersion = serviceVersion ?? "2.23.0";
|
|
62
62
|
const exporter = new OTLPTraceExporter({ url: exporterUrl });
|
|
63
63
|
const provider = new NodeTracerProvider({ resource: { attributes: {
|
|
64
64
|
"service.name": serviceName,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Y as PresetResult } from "../index-
|
|
1
|
+
import { Y as PresetResult } from "../index-BBsvQt7U.mjs";
|
|
2
2
|
import { i as RequestScope } from "../types-DH0GupI7.mjs";
|
|
3
3
|
import { t as PermissionCheck } from "../types-Csxga7d3.mjs";
|
|
4
4
|
import { a as StorageReadResult, i as StorageReadRange, n as StorageContext, o as StorageUploadInput, r as StorageFile, t as Storage } from "../storage-DLUZ04kK.mjs";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { i as NotFoundError, u as ValidationError } from "../errors-DkO8Nk6-.mjs";
|
|
2
2
|
import { c as getOrgId, g as getUserId } from "../types-bHblZ9YN.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { C as allowPublic, D as requireAuth } from "../permissions-tbxFHxjZ.mjs";
|
|
4
4
|
import { t as multipartBody } from "../multipartBody-CHEQSZ6G.mjs";
|
|
5
5
|
//#region src/presets/filesUpload.ts
|
|
6
6
|
const DEFAULT_FIELD_NAME = "file";
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Rt as IControllerResponse, U as ResourceConfig, Y as PresetResult, d as PaginationResult,
|
|
1
|
+
import { Jt as AnyRecord, Rt as IControllerResponse, U as ResourceConfig, Y as PresetResult, d as PaginationResult, zt as IRequestContext } from "../index-BBsvQt7U.mjs";
|
|
2
2
|
import { FilesUploadPresetOptions, FilesUploadPresetPermissions, FilesUploadPresetRoutes, filesUploadPreset } from "./filesUpload.mjs";
|
|
3
3
|
import { MultiTenantOptions, TenantFieldSpec, multiTenantPreset } from "./multiTenant.mjs";
|
|
4
4
|
import { SearchHandler, SearchPresetOptions, SearchRouteConfig, searchPreset } from "./search.mjs";
|
package/dist/presets/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { multiTenantPreset } from "./multiTenant.mjs";
|
|
2
|
-
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-
|
|
2
|
+
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-BOe4Ugkl.mjs";
|
|
3
3
|
import { filesUploadPreset } from "./filesUpload.mjs";
|
|
4
4
|
import { searchPreset } from "./search.mjs";
|
|
5
5
|
export { applyPresets, auditedPreset, bulkPreset, filesUploadPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, searchPreset, slugLookupPreset, softDeletePreset, treePreset };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { X as CrudRouteKey, Y as PresetResult } from "../index-
|
|
1
|
+
import { X as CrudRouteKey, Y as PresetResult } from "../index-BBsvQt7U.mjs";
|
|
2
2
|
//#region src/presets/multiTenant.d.ts
|
|
3
3
|
/**
|
|
4
4
|
* One tenant dimension for multi-field filtering. Discriminated by source:
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { At as RouteDefinition, Pt as ControllerHandler, Y as PresetResult, jt as RouteMcpConfig } from "../index-
|
|
1
|
+
import { At as RouteDefinition, Pt as ControllerHandler, Y as PresetResult, jt as RouteMcpConfig } from "../index-BBsvQt7U.mjs";
|
|
2
2
|
import { t as PermissionCheck } from "../types-Csxga7d3.mjs";
|
|
3
3
|
//#region src/presets/search.d.ts
|
|
4
4
|
/**
|
package/dist/presets/search.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { b as isElevated, n as PUBLIC_SCOPE } from "./types-bHblZ9YN.mjs";
|
|
2
|
-
import { E as requireRoles, b as allowPublic, w as requireAuth } from "./permissions-BJMuKMl7.mjs";
|
|
3
2
|
import { multiTenantPreset } from "./presets/multiTenant.mjs";
|
|
3
|
+
import { C as allowPublic, D as requireAuth, k as requireRoles } from "./permissions-tbxFHxjZ.mjs";
|
|
4
4
|
//#region src/presets/ownedByUser.ts
|
|
5
5
|
/**
|
|
6
6
|
* Create ownership check middleware.
|