@classytic/arc 2.21.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-BnLYgE9A.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 +2 -2
- package/dist/auth/index.d.mts +30 -2
- package/dist/auth/index.mjs +6 -3
- 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-DZ6Xe1jR.mjs → core-DQ6rDTyH.mjs} +126 -68
- package/dist/{createActionRouter-BWMDW-dL.mjs → createActionRouter-BuOv-m4Y.mjs} +10 -6
- package/dist/{createAggregationRouter-l5mNdYrZ.mjs → createAggregationRouter-CgJv_BU_.mjs} +3 -3
- package/dist/{createApp-Bi61XxqU.mjs → createApp-CjOeWJ9_.mjs} +252 -57
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/encryption/index.mjs +9 -5
- package/dist/{errorHandler-Dxf6P_kV.mjs → errorHandler-Bq2OeEQL.mjs} +34 -10
- package/dist/{errorHandler-B0e-bq-O.d.mts → errorHandler-C6yv4ZTW.d.mts} +13 -0
- package/dist/events/index.mjs +5 -2
- package/dist/factory/index.d.mts +46 -9
- package/dist/factory/index.mjs +64 -13
- package/dist/{fastify-augmentation-DafigGQp.d.mts → fastify-augmentation-g_f9omSc.d.mts} +2 -2
- package/dist/fields-D3lhgzhD.d.mts +121 -0
- package/dist/health-ScyjIVo5.mjs +202 -0
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +7 -0
- package/dist/idempotency/index.mjs +7 -17
- package/dist/{index-Dtrj6XZk.d.mts → index-BBsvQt7U.d.mts} +1310 -1226
- package/dist/{types-DpxoNX5v.d.mts → index-Ba10fdKp.d.mts} +196 -66
- package/dist/{index-B5N-NaHs.d.mts → index-CC5ruDGh.d.mts} +3 -3
- package/dist/{index-B5PoNbfu.d.mts → index-wMoWBLkn.d.mts} +68 -2
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +6 -5
- package/dist/{init-0YhHkXGk.mjs → init-CjO4p_q1.mjs} +123 -4
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +67 -4
- 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 +131 -7
- package/dist/integrations/webhooks.mjs +169 -10
- package/dist/interface-n5hpKg1d.mjs +16 -0
- package/dist/jsonBody-BlzAoGCe.mjs +43 -0
- package/dist/{loadResourcesFromEntry-OMCvIEE7.mjs → loadResourcesFromEntry-kvGT6EcO.mjs} +1 -1
- package/dist/logger/index.d.mts +26 -1
- package/dist/logger/index.mjs +39 -1
- package/dist/{mcpPlugin-B9XjjNVG.mjs → mcpPlugin-BtzIL_kM.mjs} +312 -39
- package/dist/middleware/index.d.mts +1 -1
- package/dist/{module-WeuU5jfd.d.mts → module-B4u10iOJ.d.mts} +26 -1
- package/dist/{openapi-Kyod_di6.mjs → openapi-jSDx-VDv.mjs} +3 -3
- package/dist/permissions/index.d.mts +4 -3
- 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 +24 -7
- package/dist/plugins/index.mjs +14 -282
- package/dist/plugins/response-cache.mjs +1 -0
- package/dist/plugins/tracing-entry.mjs +7 -4
- package/dist/presets/filesUpload.d.mts +2 -2
- 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 +2 -2
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-gw0ciIUD.mjs → presets-BOe4Ugkl.mjs} +1 -1
- package/dist/rateLimitKey-BoWRH3e7.mjs +14 -0
- package/dist/realtime-I8OrfnMR.mjs +375 -0
- package/dist/{registerRoute-oGAl0oA8.mjs → registerRoute-CWO6mdYe.mjs} +38 -18
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +1 -1
- package/dist/requestId-5BhTVzBv.mjs +113 -0
- package/dist/schemaConverter-DJvodiHj.mjs +171 -0
- package/dist/{schemaIR-ajetw3Fv.mjs → schemaIR-Ca7ySNPx.mjs} +2 -2
- package/dist/scim/index.mjs +6 -7
- package/dist/scope/index.mjs +2 -76
- 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 +83 -3
- package/dist/testing/index.mjs +70 -3
- package/dist/types/index.d.mts +2 -2
- package/dist/{types-DRj-Ut4n.d.mts → types-5OuqeTDX.d.mts} +37 -2
- package/dist/{fields-BGqrAa_u.d.mts → types-Csxga7d3.d.mts} +1 -121
- package/dist/usage/index.d.mts +142 -0
- package/dist/usage/index.mjs +0 -0
- package/dist/utils/index.d.mts +101 -19
- package/dist/utils/index.mjs +5 -3
- package/dist/{utils-CO8a3B_1.mjs → utils-CZyeRXTh.mjs} +80 -82
- package/dist/{versioning-DQ4mCvg0.d.mts → versioning-D6PvCwpq.d.mts} +43 -9
- package/llms.txt +39 -0
- package/package.json +513 -447
- package/skills/arc/SKILL.md +14 -8
- package/skills/arc/references/api-reference.md +34 -0
- package/skills/arc/references/auth.md +21 -4
- package/skills/arc/references/mcp.md +1 -1
- package/skills/arc/references/production.md +734 -654
- package/skills/arc-code-review/SKILL.md +1 -1
- package/skills/arc-code-review/references/anti-patterns.md +71 -18
- package/skills/arc-code-review/references/arc-cheatsheet.md +15 -2
- package/skills/arc-code-review/references/migration-recipes.md +7 -7
- package/skills/arc-code-review/references/mongokit-migration.md +4 -3
- package/skills/arc-module-publishing/SKILL.md +2 -1
- package/skills/arc-module-publishing/references/authoring-modules.md +55 -0
- package/skills/arc-module-publishing/references/package-manifest.md +4 -2
- package/dist/preloadResources-CHw3_oA_.mjs +0 -45
- package/dist/schemaConverter-U0MnO9vd.mjs +0 -110
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Wt as Authenticator } from "./index-BBsvQt7U.mjs";
|
|
2
2
|
import { r as CacheStore } from "./interface-C1_WLTMK.mjs";
|
|
3
3
|
import { n as ElevationOptions } from "./elevation-C9s5hFP_.mjs";
|
|
4
4
|
import { a as EventTransport } from "./EventTransport-QmY7A258.mjs";
|
|
5
5
|
import { t as ExternalOpenApiPaths } from "./externalPaths-BE6wFpYv.mjs";
|
|
6
6
|
import { r as QueryCachePluginOptions } from "./queryCachePlugin-CfYWq-Ak.mjs";
|
|
7
|
-
import { t as ErrorHandlerOptions } from "./errorHandler-
|
|
8
|
-
import { l as ResourceLike, n as ArcModuleInput } from "./module-
|
|
7
|
+
import { t as ErrorHandlerOptions } from "./errorHandler-C6yv4ZTW.mjs";
|
|
8
|
+
import { l as ResourceLike, n as ArcModuleInput } from "./module-B4u10iOJ.mjs";
|
|
9
9
|
import { t as EventPluginOptions } from "./eventPlugin-A6EbthXR.mjs";
|
|
10
|
-
import {
|
|
10
|
+
import { g as CachingOptions, o as MetricsOptions, p as SSEOptions, t as VersioningOptions, u as RealtimeOptions, x as HealthOptions } from "./versioning-D6PvCwpq.mjs";
|
|
11
11
|
import { r as IdempotencyStore } from "./interface-Uk8ONJv7.mjs";
|
|
12
12
|
import { FastifyInstance, FastifyPluginAsync, FastifyReply, FastifyRequest, FastifyServerOptions } from "fastify";
|
|
13
13
|
//#region src/testing/preloadResources.d.ts
|
|
@@ -33,30 +33,7 @@ declare function preloadResources(globResult: EagerGlobResult): ResourceLike[];
|
|
|
33
33
|
*/
|
|
34
34
|
declare function preloadResourcesAsync(globResult: LazyGlobResult): Promise<ResourceLike[]>;
|
|
35
35
|
//#endregion
|
|
36
|
-
//#region src/factory/types.d.ts
|
|
37
|
-
type CorsOptions = Record<string, unknown> & {
|
|
38
|
-
origin?: unknown;
|
|
39
|
-
credentials?: boolean;
|
|
40
|
-
methods?: string[];
|
|
41
|
-
allowedHeaders?: string[];
|
|
42
|
-
};
|
|
43
|
-
type HelmetOptions = Record<string, unknown>;
|
|
44
|
-
type RateLimitOpts = Record<string, unknown> & {
|
|
45
|
-
max?: number;
|
|
46
|
-
timeWindow?: string | number;
|
|
47
|
-
/**
|
|
48
|
-
* Path patterns to exempt from rate limiting. Supports exact match
|
|
49
|
-
* (`/health`) or prefix match with trailing `*` (`/api/auth/*`).
|
|
50
|
-
*
|
|
51
|
-
* Implemented by synthesising a `@fastify/rate-limit` `allowList`
|
|
52
|
-
* function. When combined with a user-supplied `allowList`, both
|
|
53
|
-
* are OR-ed together (path OR ip/custom match skips the limit).
|
|
54
|
-
*
|
|
55
|
-
* Use this for endpoints that are hit frequently but independently
|
|
56
|
-
* of user traffic — session heartbeat, webhooks, health probes.
|
|
57
|
-
*/
|
|
58
|
-
skipPaths?: string[];
|
|
59
|
-
};
|
|
36
|
+
//#region src/factory/types/auth.d.ts
|
|
60
37
|
/**
|
|
61
38
|
* Arc's built-in JWT auth
|
|
62
39
|
*
|
|
@@ -161,13 +138,29 @@ interface JwtAuthOption {
|
|
|
161
138
|
* });
|
|
162
139
|
* ```
|
|
163
140
|
*/
|
|
141
|
+
/** The shape `createBetterAuthAdapter()` returns. */
|
|
142
|
+
interface BetterAuthAdapterResult {
|
|
143
|
+
plugin: FastifyPluginAsync;
|
|
144
|
+
openapi?: ExternalOpenApiPaths;
|
|
145
|
+
}
|
|
164
146
|
interface BetterAuthOption {
|
|
165
147
|
type: "betterAuth";
|
|
166
|
-
/**
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
148
|
+
/**
|
|
149
|
+
* Better Auth adapter — the result of `createBetterAuthAdapter()`, or a
|
|
150
|
+
* sync/async THUNK returning it (2.22). The thunk resolves during auth
|
|
151
|
+
* registration — AFTER `beforeBoot` — for adapters whose construction
|
|
152
|
+
* needs a live DB (Better Auth's `mongodbAdapter(mongoose.connection
|
|
153
|
+
* .getClient().db())` requires an OPEN connection, so an eager value
|
|
154
|
+
* forces hosts back into connect-before-createApp ordering dances):
|
|
155
|
+
*
|
|
156
|
+
* ```typescript
|
|
157
|
+
* createApp({
|
|
158
|
+
* beforeBoot: () => connectDatabase(),
|
|
159
|
+
* auth: { type: 'betterAuth', betterAuth: () => createBetterAuthAdapter({ auth: getAuth() }) },
|
|
160
|
+
* });
|
|
161
|
+
* ```
|
|
162
|
+
*/
|
|
163
|
+
betterAuth: BetterAuthAdapterResult | (() => BetterAuthAdapterResult | Promise<BetterAuthAdapterResult>);
|
|
171
164
|
}
|
|
172
165
|
/**
|
|
173
166
|
* Custom auth plugin — full control over authentication setup
|
|
@@ -234,6 +227,112 @@ interface CustomAuthenticatorOption {
|
|
|
234
227
|
* - `CustomAuthenticatorOption` — A bare authenticate function (`type: 'authenticator'`)
|
|
235
228
|
*/
|
|
236
229
|
type AuthOption = false | JwtAuthOption | BetterAuthOption | CustomPluginAuthOption | CustomAuthenticatorOption;
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/factory/types/plugin-options.d.ts
|
|
232
|
+
/**
|
|
233
|
+
* Plugin-specific option shapes for `createApp()` — under-pressure,
|
|
234
|
+
* multipart, and raw-body plugin configuration.
|
|
235
|
+
*/
|
|
236
|
+
interface UnderPressureOptions {
|
|
237
|
+
/** Expose `/_status` route for health checks (default: false) */
|
|
238
|
+
exposeStatusRoute?: boolean;
|
|
239
|
+
/** Event loop lag threshold in ms — requests rejected above this (default: 1000) */
|
|
240
|
+
maxEventLoopDelay?: number;
|
|
241
|
+
/** V8 heap usage threshold in bytes — requests rejected above this */
|
|
242
|
+
maxHeapUsedBytes?: number;
|
|
243
|
+
/** RSS memory threshold in bytes — requests rejected above this */
|
|
244
|
+
maxRssBytes?: number;
|
|
245
|
+
}
|
|
246
|
+
interface MultipartOptions {
|
|
247
|
+
limits?: {
|
|
248
|
+
/** Max file size in bytes (default: Fastify default ~1MB) */
|
|
249
|
+
fileSize?: number;
|
|
250
|
+
/** Max number of files per request */
|
|
251
|
+
files?: number;
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
interface RawBodyOptions {
|
|
255
|
+
/** Body field name to store raw body on (default: 'rawBody') */
|
|
256
|
+
field?: string;
|
|
257
|
+
/** Apply to all routes globally (default: false) */
|
|
258
|
+
global?: boolean;
|
|
259
|
+
/** Encoding for raw body string (default: 'utf8') */
|
|
260
|
+
encoding?: string;
|
|
261
|
+
/** Parse raw body before other parsers (default: false) */
|
|
262
|
+
runFirst?: boolean;
|
|
263
|
+
}
|
|
264
|
+
//#endregion
|
|
265
|
+
//#region src/factory/types/security.d.ts
|
|
266
|
+
/**
|
|
267
|
+
* Security-plugin option shapes — CORS / Helmet / rate-limit config for
|
|
268
|
+
* `createApp()`, including plan-aware rate limiting (2.22).
|
|
269
|
+
*/
|
|
270
|
+
type CorsOptions = Record<string, unknown> & {
|
|
271
|
+
origin?: unknown;
|
|
272
|
+
credentials?: boolean;
|
|
273
|
+
methods?: string[];
|
|
274
|
+
allowedHeaders?: string[];
|
|
275
|
+
};
|
|
276
|
+
type HelmetOptions = Record<string, unknown>;
|
|
277
|
+
type RateLimitOpts = Record<string, unknown> & {
|
|
278
|
+
max?: number;
|
|
279
|
+
timeWindow?: string | number;
|
|
280
|
+
/**
|
|
281
|
+
* Path patterns to exempt from rate limiting. Supports exact match
|
|
282
|
+
* (`/health`) or prefix match with trailing `*` (`/api/auth/*`).
|
|
283
|
+
*
|
|
284
|
+
* Implemented by synthesising a `@fastify/rate-limit` `allowList`
|
|
285
|
+
* function. When combined with a user-supplied `allowList`, both
|
|
286
|
+
* are OR-ed together (path OR ip/custom match skips the limit).
|
|
287
|
+
*
|
|
288
|
+
* Use this for endpoints that are hit frequently but independently
|
|
289
|
+
* of user traffic — session heartbeat, webhooks, health probes.
|
|
290
|
+
*/
|
|
291
|
+
skipPaths?: string[];
|
|
292
|
+
/**
|
|
293
|
+
* Plan-aware limits (2.22) — resolve the caller's plan per request and
|
|
294
|
+
* apply that plan's ceiling instead of the global `max`:
|
|
295
|
+
*
|
|
296
|
+
* ```typescript
|
|
297
|
+
* rateLimit: {
|
|
298
|
+
* timeWindow: '1 minute',
|
|
299
|
+
* plan: {
|
|
300
|
+
* resolve: (req) => lookupPlan(req), // 'free' | 'pro' | ...
|
|
301
|
+
* limits: { free: { max: 60 }, pro: { max: 1000 }, enterprise: false },
|
|
302
|
+
* default: 'free',
|
|
303
|
+
* },
|
|
304
|
+
* }
|
|
305
|
+
* ```
|
|
306
|
+
*
|
|
307
|
+
* `false` = effectively unlimited. When `plan` is set and no
|
|
308
|
+
* `keyGenerator` is supplied, arc defaults to the tenant key chain
|
|
309
|
+
* (org → user → client → IP) so buckets follow actors, not addresses.
|
|
310
|
+
*
|
|
311
|
+
* Timing caveat: the limiter runs before route-level auth, so
|
|
312
|
+
* `req.scope` may be unresolved for token-authenticated calls —
|
|
313
|
+
* `resolve` receives the RAW request and may need to derive the plan
|
|
314
|
+
* from its own header/token/session lookup. Same caveat as
|
|
315
|
+
* `createTenantKeyGenerator`'s IP fallback (documented there).
|
|
316
|
+
*/
|
|
317
|
+
plan?: RateLimitPlanConfig;
|
|
318
|
+
};
|
|
319
|
+
/** Plan-aware rate limiting (2.22) — see `rateLimit.plan` on CreateAppOptions. */
|
|
320
|
+
interface RateLimitPlanConfig {
|
|
321
|
+
/**
|
|
322
|
+
* Name the caller's plan from the raw request. Return `undefined` to
|
|
323
|
+
* fall back to `default`. Sync or async; a throwing resolver also
|
|
324
|
+
* falls back (limits must fail-safe, not fail-open to unlimited).
|
|
325
|
+
*/
|
|
326
|
+
resolve: (req: import("fastify").FastifyRequest) => string | undefined | Promise<string | undefined>;
|
|
327
|
+
/** Per-plan ceilings within the shared `timeWindow`. `false` = effectively unlimited. */
|
|
328
|
+
limits: Record<string, {
|
|
329
|
+
max: number;
|
|
330
|
+
} | false>;
|
|
331
|
+
/** Plan used when `resolve` returns undefined/unknown or throws. Default: fall back to the global `max`. */
|
|
332
|
+
default?: string;
|
|
333
|
+
}
|
|
334
|
+
//#endregion
|
|
335
|
+
//#region src/factory/types/app-options.d.ts
|
|
237
336
|
/**
|
|
238
337
|
* CreateApp Options
|
|
239
338
|
*
|
|
@@ -276,8 +375,18 @@ type AuthOption = false | JwtAuthOption | BetterAuthOption | CustomPluginAuthOpt
|
|
|
276
375
|
* ```
|
|
277
376
|
*/
|
|
278
377
|
interface CreateAppOptions {
|
|
279
|
-
/** Environment preset: 'production', 'development', 'testing', or '
|
|
280
|
-
preset?: "production" | "development" | "testing" | "edge";
|
|
378
|
+
/** Environment preset: 'production', 'development', 'testing', 'edge', or 'worker' */
|
|
379
|
+
preset?: "production" | "development" | "testing" | "edge" | "worker";
|
|
380
|
+
/**
|
|
381
|
+
* Route-mounting switch (2.23) — the worker-role primitive. `false`
|
|
382
|
+
* registers every resource's shared runtime state (registry metadata +
|
|
383
|
+
* adapter, hooks, cache-invalidation rules) WITHOUT mounting any routes,
|
|
384
|
+
* so headless processes keep tenant-purge cascade, per-resource audit,
|
|
385
|
+
* and events metadata intact. Set by `preset: 'worker'` /
|
|
386
|
+
* `createWorker()`; hosts composing a custom worker shape may set it
|
|
387
|
+
* directly. Default: true (routes mount).
|
|
388
|
+
*/
|
|
389
|
+
mountRoutes?: boolean;
|
|
281
390
|
/**
|
|
282
391
|
* Runtime profile for store backends.
|
|
283
392
|
* - 'memory' (default): Uses in-memory stores. Suitable for single-instance deployments.
|
|
@@ -324,10 +433,50 @@ interface CreateAppOptions {
|
|
|
324
433
|
* ```
|
|
325
434
|
*/
|
|
326
435
|
debug?: boolean | string;
|
|
327
|
-
/**
|
|
328
|
-
|
|
436
|
+
/**
|
|
437
|
+
* Trust proxy headers (X-Forwarded-For, etc.). Pass-through to Fastify's
|
|
438
|
+
* `trustProxy` server option — all its forms are supported, not just the
|
|
439
|
+
* boolean:
|
|
440
|
+
*
|
|
441
|
+
* - `true` — trust ALL proxies (only safe when the app is never directly
|
|
442
|
+
* reachable; a spoofed `X-Forwarded-For` otherwise forges `request.ip`,
|
|
443
|
+
* which feeds rate-limit keys and audit logs)
|
|
444
|
+
* - `1` — trust exactly one hop (typical single LB / reverse proxy)
|
|
445
|
+
* - `'10.0.0.0/8'` / `['10.0.0.0/8', '172.16.0.0/12']` — trust only these
|
|
446
|
+
* CIDR ranges
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* ```ts
|
|
450
|
+
* createApp({ preset: 'production', trustProxy: 1 }); // one LB hop
|
|
451
|
+
* createApp({ preset: 'production', trustProxy: '10.0.0.0/8' }); // VPC proxies
|
|
452
|
+
* ```
|
|
453
|
+
*/
|
|
454
|
+
trustProxy?: boolean | string | string[] | number;
|
|
329
455
|
/** Fastify plugin/onReady timeout in ms (default: 10_000). Raise for slow boot work (index materialisation, WAL replay, external warm-up). */
|
|
330
456
|
pluginTimeout?: number;
|
|
457
|
+
/**
|
|
458
|
+
* Max time in ms the server waits to RECEIVE an entire request
|
|
459
|
+
* (headers + body). Pass-through to Fastify's `requestTimeout` (Node's
|
|
460
|
+
* `server.requestTimeout`). Default `0` defers to Node's own 300s bound
|
|
461
|
+
* — slow-loris requests are already cut off there, so arc doesn't
|
|
462
|
+
* override; tighten (e.g. `30_000`) for APIs that never accept slow
|
|
463
|
+
* uploads. Response duration (SSE, streaming) is NOT affected.
|
|
464
|
+
*/
|
|
465
|
+
requestTimeout?: number;
|
|
466
|
+
/**
|
|
467
|
+
* Max time in ms to establish a connection before the socket is
|
|
468
|
+
* destroyed. Pass-through to Fastify's `connectionTimeout` (Node's
|
|
469
|
+
* `server.timeout`). Default `0` = no limit (Node's `headersTimeout`
|
|
470
|
+
* ~60s still bounds idle pre-request sockets).
|
|
471
|
+
*/
|
|
472
|
+
connectionTimeout?: number;
|
|
473
|
+
/**
|
|
474
|
+
* Keep-alive idle timeout in ms (Node's `server.keepAliveTimeout`,
|
|
475
|
+
* default 72_000). MUST be longer than the idle timeout of any load
|
|
476
|
+
* balancer in front of the app (ALB default 60s) or the LB reuses
|
|
477
|
+
* sockets the server just closed → intermittent 502s.
|
|
478
|
+
*/
|
|
479
|
+
keepAliveTimeout?: number;
|
|
331
480
|
/**
|
|
332
481
|
* Maximum JSON body size in bytes. Pass-through to Fastify's
|
|
333
482
|
* server-level `bodyLimit` option; default is Fastify's 1 MiB
|
|
@@ -523,6 +672,15 @@ interface CreateAppOptions {
|
|
|
523
672
|
* Requires emitEvents to be enabled (or events plugin registered).
|
|
524
673
|
*/
|
|
525
674
|
sse?: SSEOptions | boolean;
|
|
675
|
+
/**
|
|
676
|
+
* Realtime resource change feed (2.22) — `GET /realtime/:resource`
|
|
677
|
+
* streams that resource's created/updated/deleted events over SSE,
|
|
678
|
+
* gated by its own `list` permission with per-event row filtering,
|
|
679
|
+
* tenant scoping, and field-level masking. Default: false (opt-in).
|
|
680
|
+
* Set true for defaults, or pass RealtimeOptions (path, heartbeat,
|
|
681
|
+
* resource allowlist, operations). Requires events.
|
|
682
|
+
*/
|
|
683
|
+
realtime?: RealtimeOptions | boolean;
|
|
526
684
|
/**
|
|
527
685
|
* QueryCache — TanStack Query-inspired server cache with SWR.
|
|
528
686
|
* Default: false (opt-in). Set to true for memory store defaults.
|
|
@@ -933,33 +1091,5 @@ interface CreateAppOptions {
|
|
|
933
1091
|
/** Hook called when the app is shutting down */
|
|
934
1092
|
onClose?: (fastify: FastifyInstance) => void | Promise<void>;
|
|
935
1093
|
}
|
|
936
|
-
interface UnderPressureOptions {
|
|
937
|
-
/** Expose `/_status` route for health checks (default: false) */
|
|
938
|
-
exposeStatusRoute?: boolean;
|
|
939
|
-
/** Event loop lag threshold in ms — requests rejected above this (default: 1000) */
|
|
940
|
-
maxEventLoopDelay?: number;
|
|
941
|
-
/** V8 heap usage threshold in bytes — requests rejected above this */
|
|
942
|
-
maxHeapUsedBytes?: number;
|
|
943
|
-
/** RSS memory threshold in bytes — requests rejected above this */
|
|
944
|
-
maxRssBytes?: number;
|
|
945
|
-
}
|
|
946
|
-
interface MultipartOptions {
|
|
947
|
-
limits?: {
|
|
948
|
-
/** Max file size in bytes (default: Fastify default ~1MB) */
|
|
949
|
-
fileSize?: number;
|
|
950
|
-
/** Max number of files per request */
|
|
951
|
-
files?: number;
|
|
952
|
-
};
|
|
953
|
-
}
|
|
954
|
-
interface RawBodyOptions {
|
|
955
|
-
/** Body field name to store raw body on (default: 'rawBody') */
|
|
956
|
-
field?: string;
|
|
957
|
-
/** Apply to all routes globally (default: false) */
|
|
958
|
-
global?: boolean;
|
|
959
|
-
/** Encoding for raw body string (default: 'utf8') */
|
|
960
|
-
encoding?: string;
|
|
961
|
-
/** Parse raw body before other parsers (default: false) */
|
|
962
|
-
runFirst?: boolean;
|
|
963
|
-
}
|
|
964
1094
|
//#endregion
|
|
965
|
-
export {
|
|
1095
|
+
export { AuthOption as a, CustomPluginAuthOption as c, preloadResourcesAsync as d, UnderPressureOptions as i, JwtAuthOption as l, MultipartOptions as n, BetterAuthOption as o, RawBodyOptions as r, CustomAuthenticatorOption as s, CreateAppOptions as t, preloadResources as u };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { C as RequestContext, Et as
|
|
1
|
+
import { C as RequestContext, Et as ActionDefinition, F as FastifyWithDecorators, H as CrudController, Jt as AnyRecord, L as RequestWithExtras, Lt as IController, Rt as IControllerResponse, T as CrudRouterOptions, U as ResourceConfig, V as ResourceDefinition, et as RouteSchemaOptions, jt as RouteMcpConfig, tt as ArcFieldRule, ut as AggregationConfig, zt as IRequestContext } from "./index-BBsvQt7U.mjs";
|
|
2
2
|
import { i as RequestScope } from "./types-DH0GupI7.mjs";
|
|
3
|
-
import {
|
|
4
|
-
import "./fastify-augmentation-
|
|
3
|
+
import { t as PermissionCheck } from "./types-Csxga7d3.mjs";
|
|
4
|
+
import "./fastify-augmentation-g_f9omSc.mjs";
|
|
5
5
|
import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { DataAdapter } from "@classytic/repo-core/adapter";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as CacheStore, t as CacheLogger } from "./interface-C1_WLTMK.mjs";
|
|
2
2
|
import { i as RequestScope, n as Mandate } from "./types-DH0GupI7.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-Csxga7d3.mjs";
|
|
4
4
|
import { FastifyReply, FastifyRequest } from "fastify";
|
|
5
5
|
//#region src/permissions/agent.d.ts
|
|
6
6
|
/**
|
|
@@ -449,6 +449,72 @@ declare function createOrgPermissions(config: {
|
|
|
449
449
|
*/
|
|
450
450
|
declare function createDynamicPermissionMatrix(config: DynamicPermissionMatrixConfig): DynamicPermissionMatrix;
|
|
451
451
|
//#endregion
|
|
452
|
+
//#region src/permissions/grants.d.ts
|
|
453
|
+
/**
|
|
454
|
+
* The grant-mode lattice, weakest → strongest. Holding a mode satisfies
|
|
455
|
+
* every mode at or below it (`write` ⊇ `read` ⊇ `list` ⊇ `see`); `manage`
|
|
456
|
+
* (grant/revoke rights) satisfies everything. Same semantics as Puter's
|
|
457
|
+
* `see < list < read < write` hierarchy with `manage` folded into the
|
|
458
|
+
* lattice top instead of a separate string namespace.
|
|
459
|
+
*/
|
|
460
|
+
declare const GRANT_MODES: readonly ["see", "list", "read", "write", "manage"];
|
|
461
|
+
/** One mode from the {@link GRANT_MODES} lattice. */
|
|
462
|
+
type GrantMode = (typeof GRANT_MODES)[number];
|
|
463
|
+
/**
|
|
464
|
+
* Does a HELD mode satisfy a REQUIRED mode? Lattice implication —
|
|
465
|
+
* `modeSatisfies('write', 'read') === true`, `modeSatisfies('see', 'read')
|
|
466
|
+
* === false`. Unknown strings (a corrupted grant row) never satisfy
|
|
467
|
+
* anything: fail-closed.
|
|
468
|
+
*/
|
|
469
|
+
declare function modeSatisfies(held: string | undefined, required: GrantMode): boolean;
|
|
470
|
+
/**
|
|
471
|
+
* What a grant `resolve` callback may return:
|
|
472
|
+
*
|
|
473
|
+
* - `boolean` — the host did the whole check itself (already compared modes).
|
|
474
|
+
* - `{ mode }` — the strongest mode the caller holds on `ctx.resourceId`;
|
|
475
|
+
* the combinator applies the lattice against the required mode.
|
|
476
|
+
* - `{ filters }` — list-shaped resolution: row filters that scope the
|
|
477
|
+
* query to visible records (flows through `PermissionResult.filters` →
|
|
478
|
+
* `_policyFilters` → the repository query). Grants access with the
|
|
479
|
+
* filters attached.
|
|
480
|
+
* - `{ mode, filters }` — mode gates; filters ride along when it passes.
|
|
481
|
+
*
|
|
482
|
+
* An empty object (neither `mode` nor `filters`) and a thrown error both
|
|
483
|
+
* DENY — grant resolution is fail-closed, same stance as `isRevoked`.
|
|
484
|
+
*/
|
|
485
|
+
type GrantResolution = boolean | {
|
|
486
|
+
mode?: GrantMode | string;
|
|
487
|
+
filters?: Record<string, unknown>;
|
|
488
|
+
/** Optional denial reason surfaced on the 403 (clamped by the framework). */
|
|
489
|
+
reason?: string;
|
|
490
|
+
};
|
|
491
|
+
interface RequireGrantOptions {
|
|
492
|
+
/** The mode this operation needs (lattice-checked against the held mode). */
|
|
493
|
+
mode: GrantMode;
|
|
494
|
+
/**
|
|
495
|
+
* Look up the caller's grant. Receives the full `PermissionContext`
|
|
496
|
+
* (`resourceId` for single-record ops, `request` for headers/scope —
|
|
497
|
+
* e.g. a share-link token). May be sync or async.
|
|
498
|
+
*
|
|
499
|
+
* NOTE: unauthenticated callers are NOT rejected up front — share links
|
|
500
|
+
* grant access to anonymous callers by design. If your grants are
|
|
501
|
+
* session-only, return `false` when `ctx.user` is null (or compose with
|
|
502
|
+
* `requireAuth()` via `allOf`).
|
|
503
|
+
*/
|
|
504
|
+
resolve: (ctx: PermissionContext) => GrantResolution | Promise<GrantResolution>;
|
|
505
|
+
/** Roles that skip the grant check entirely (platform admins). */
|
|
506
|
+
bypassRoles?: readonly string[];
|
|
507
|
+
}
|
|
508
|
+
/**
|
|
509
|
+
* Per-record grant gate. Same combinator tier as `requireOwnership` —
|
|
510
|
+
* compose with `anyOf`/`allOf` like any other `PermissionCheck`.
|
|
511
|
+
*
|
|
512
|
+
* Fail-closed contract: resolver throws → denied (logged via
|
|
513
|
+
* `ctx.request.log`); resolution carries neither `mode` nor `filters` →
|
|
514
|
+
* denied; unknown/corrupted mode strings → denied.
|
|
515
|
+
*/
|
|
516
|
+
declare function requireGrant(options: RequireGrantOptions): PermissionCheck;
|
|
517
|
+
//#endregion
|
|
452
518
|
//#region src/permissions/roleHierarchy.d.ts
|
|
453
519
|
/**
|
|
454
520
|
* Role Hierarchy — Composable RBAC Inheritance
|
|
@@ -706,4 +772,4 @@ declare function fullPublic<TDoc = Record<string, unknown>>(overrides?: Permissi
|
|
|
706
772
|
*/
|
|
707
773
|
declare function readOnly<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
708
774
|
//#endregion
|
|
709
|
-
export {
|
|
775
|
+
export { allOf as A, applyPermissionResult as B, requireGrant as C, PermissionEventBus as D, DynamicPermissionMatrixConfig as E, requireAuth as F, requireDPoP as G, RequireAgentScopeOptions as H, requireOwnership as I, requireMandate as K, requireRoles as L, anyOf as M, denyAll as N, createDynamicPermissionMatrix as O, not as P, roles as R, modeSatisfies as S, DynamicPermissionMatrix as T, RequireMandateOptions as U, normalizePermissionResult as V, requireAgentScope as W, createRoleHierarchy as _, permissionMatrix as a, GrantResolution as b, publicReadAdminWrite as c, requireOrgMembership as d, requireOrgRole as f, RoleHierarchy as g, requireTeamMembership as h, ownerWithAdminBypass as i, allowPublic as j, createOrgPermissions as k, readOnly as l, requireServiceScope as m, authenticated as n, presets_d_exports as o, requireScopeContext as p, fullPublic as r, publicRead as s, adminOnly as t, requireOrgInScope as u, GRANT_MODES as v, ConnectEventsOptions as w, RequireGrantOptions as x, GrantMode as y, when as z };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import "./
|
|
4
|
-
import
|
|
5
|
-
import { A as
|
|
1
|
+
import { A as RequestIdOptions, B as defineResource, Bt as RouteHandler, C as RequestContext, D as HealthCheck, E as GracefulShutdownOptions, F as FastifyWithDecorators, Fn as ArcUpdateResult, Ft as ControllerLike, H as CrudController, In as BaseControllerOptions, Jt as AnyRecord, L as RequestWithExtras, Ln as ControllerConfigurableOptions, Lt as IController, Mn as ArcDeleteResult, N as FastifyRequestExtras, Nn as ArcGetResult, Nt as RateLimitConfig, O as HealthOptions, P as FastifyWithAuth, Pn as ArcListResult, Q as MiddlewareConfig, Rn as ControllerConstructionOptions, Rt as IControllerResponse, S as QueryParserInterface, T as CrudRouterOptions, U as ResourceConfig, Ut as AuthPluginOptions, V as ResourceDefinition, X as CrudRouteKey, Xt as ArcRequest, Y as PresetResult, Yt as ApiResponse, Z as CrudSchemas, Zt as JWTPayload, a as InferAdapterDoc, an as TreeMixin, c as TypedController, cn as BulkExt, ct as AggMeasureShorthand, d as PaginationResult, dt as AggregationDateRangeRequirement, en as UserOrganization, et as RouteSchemaOptions, f as IntrospectionData, ft as AggregationIndexHint, g as ArcInternalMetadata, gt as AggregationsMap, h as ResourceMetadata, ht as AggregationRateLimit, i as ValidationResult, in as TreeExt, jn as ArcCreateResult, k as IntrospectionPluginOptions, l as TypedRepository, ln as BulkMixin, lt as AggregationCacheConfig, m as RegistryStats, mt as AggregationMaterializedResult, n as ConfigError, nn as SoftDeleteExt, nt as FieldRule, o as InferDocType, on as SlugExt, ot as EventDefinition, p as RegistryEntry, pt as AggregationMaterializedContext, q as PresetFunction, r as ValidateOptions, rn as SoftDeleteMixin, s as InferResourceDoc, sn as SlugMixin, st as AggMeasureInput, t as RouteHandlerMethod, tn as BaseController, u as TypedResourceConfig, un as BaseCrudController, ut as AggregationConfig, w as ServiceContext, y as OwnershipCheck, zn as ListResult, zt as IRequestContext } from "./index-BBsvQt7U.mjs";
|
|
2
|
+
import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-Csxga7d3.mjs";
|
|
3
|
+
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-D3lhgzhD.mjs";
|
|
4
|
+
import "./fastify-augmentation-g_f9omSc.mjs";
|
|
5
|
+
import { A as HOOK_OPERATIONS, B as SYSTEM_FIELDS, C as CrudOperation, D as DEFAULT_SORT, E as DEFAULT_MAX_LIMIT, F as MAX_REGEX_LENGTH, I as MAX_SEARCH_LENGTH, L as MUTATION_OPERATIONS, M as HookOperation, N as HookPhase, O as DEFAULT_TENANT_FIELD, P as MAX_FILTER_DEPTH, R as MutationOperation, S as CRUD_OPERATIONS, T as DEFAULT_LIMIT, f as defineResourceVariants, g as mergeResourceConfig, h as SeamedResourceConfig, j as HOOK_PHASES, k as DEFAULT_UPDATE_METHOD, m as ResourceSeams, p as AdapterLike, s as getControllerScope, v as defineAction, w as DEFAULT_ID_FIELD, x as defineAggregation, z as RESERVED_QUERY_PARAMS } from "./index-CC5ruDGh.mjs";
|
|
6
|
+
import { A as allOf, E as DynamicPermissionMatrixConfig, F as requireAuth, I as requireOwnership, L as requireRoles, M as anyOf, N as denyAll, O as createDynamicPermissionMatrix, T as DynamicPermissionMatrix, c as publicReadAdminWrite, d as requireOrgMembership, f as requireOrgRole, h as requireTeamMembership, i as ownerWithAdminBypass, j as allowPublic, k as createOrgPermissions, l as readOnly, m as requireServiceScope, n as authenticated, o as presets_d_exports, p as requireScopeContext, r as fullPublic, s as publicRead, t as adminOnly, u as requireOrgInScope, z as when } from "./index-wMoWBLkn.mjs";
|
|
6
7
|
import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-DHcHVAgk.mjs";
|
|
7
8
|
//#region src/index.d.ts
|
|
8
9
|
declare const version: string;
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "./constants-DNre0wRg.mjs";
|
|
2
2
|
import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-DkO8Nk6-.mjs";
|
|
3
|
-
import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-
|
|
4
|
-
import {
|
|
5
|
-
import { a as
|
|
6
|
-
import { l as
|
|
3
|
+
import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-BQ8KNvWC.mjs";
|
|
4
|
+
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, o as fields } from "./applyPermissionResult-Tw4iXtlf.mjs";
|
|
5
|
+
import { a as defineResource, c as defineAction, d as defineAggregation, i as defineResourceVariants, o as ResourceDefinition, s as mergeResourceConfig } from "./core-DQ6rDTyH.mjs";
|
|
6
|
+
import { C as allowPublic, D as requireAuth, O as requireOwnership, S as allOf, T as denyAll, _ as requireOrgMembership, b as requireServiceScope, c as publicReadAdminWrite, g as requireOrgInScope, h as createOrgPermissions, i as ownerWithAdminBypass, j as when, k as requireRoles, l as readOnly, m as createDynamicPermissionMatrix, n as authenticated, o as presets_exports, r as fullPublic, s as publicRead, t as adminOnly, v as requireOrgRole, w as anyOf, x as requireTeamMembership, y as requireScopeContext } from "./permissions-tbxFHxjZ.mjs";
|
|
7
|
+
import { l as getControllerScope } from "./actionPermissions-lszoJle1.mjs";
|
|
7
8
|
//#region src/index.ts
|
|
8
|
-
const version = "2.
|
|
9
|
+
const version = "2.23.0";
|
|
9
10
|
//#endregion
|
|
10
11
|
export { ArcError, BaseController, BaseCrudController, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, NotFoundError, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, mergeResourceConfig, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
|