@classytic/arc 2.28.0 → 2.31.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/LICENSE +1 -1
- package/README.md +7 -0
- package/TRADEMARK.md +22 -0
- package/dist/{BaseController-B65zbz9m.mjs → BaseController-De7GqHck.mjs} +25 -24
- package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
- package/dist/EventTransport-9mlTgqzE.mjs +104 -0
- package/dist/{HookSystem-C1vB_Gc9.mjs → HookSystem-BcmPyq5I.mjs} +16 -35
- package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
- package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-qq0mn2s9.mjs} +3 -2
- package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-BE5NwaQk.mjs} +1 -0
- package/dist/audit/index.d.mts +3 -2
- package/dist/audit/index.mjs +3 -2
- package/dist/auth/audit.d.mts +1 -0
- package/dist/auth/audit.mjs +1 -0
- package/dist/auth/index.d.mts +5 -4
- package/dist/auth/index.mjs +6 -5
- package/dist/auth/redis-session.d.mts +2 -1
- package/dist/auth/redis-session.mjs +1 -0
- package/dist/authorizationDecision-ChvUQGG1.mjs +266 -0
- package/dist/{buildHandler-Dtwd8fdz.mjs → buildHandler-CDrCJzmB.mjs} +34 -7
- package/dist/cache/index.d.mts +4 -3
- package/dist/cache/index.mjs +4 -3
- package/dist/{caching-_NJeDd1_.mjs → caching-BFHA6Scf.mjs} +2 -1
- package/dist/cleanup/index.d.mts +4 -3
- package/dist/cleanup/index.mjs +9 -13
- package/dist/cli/commands/describe.d.mts +2 -1
- package/dist/cli/commands/describe.mjs +3 -2
- package/dist/cli/commands/docs.d.mts +1 -0
- package/dist/cli/commands/docs.mjs +3 -2
- package/dist/cli/commands/doctor.d.mts +1 -0
- package/dist/cli/commands/doctor.mjs +1 -0
- package/dist/cli/commands/generate.d.mts +2 -1
- package/dist/cli/commands/generate.mjs +2 -1
- package/dist/cli/commands/init.d.mts +2 -1
- package/dist/cli/commands/init.mjs +2 -1
- package/dist/cli/commands/introspect.d.mts +1 -0
- package/dist/cli/commands/introspect.mjs +2 -1
- package/dist/cli/index.d.mts +3 -2
- package/dist/cli/index.mjs +3 -2
- package/dist/{constants-DNre0wRg.mjs → constants-D3Dv4LAV.mjs} +1 -0
- package/dist/context/index.d.mts +1 -0
- package/dist/context/index.mjs +3 -2
- package/dist/core/index.d.mts +3 -2
- package/dist/core/index.mjs +7 -5
- package/dist/{core-BGa8TXJR.mjs → core-BGpIxINN.mjs} +4 -49
- package/dist/{createActionRouter-C-N7z2EL.mjs → createActionRouter-CDXEdasl.mjs} +8 -7
- package/dist/{createAggregationRouter-wzwFa_dW.mjs → createAggregationRouter-KrQDzx-k.mjs} +10 -22
- package/dist/{createApp-Du5G54TM.mjs → createApp-Df89BEni.mjs} +505 -209
- package/dist/defineAggregation-DbPPS8RI.mjs +48 -0
- package/dist/{defineResource-2zvVVpxg.mjs → defineResource-Bv6EtN1x.mjs} +90 -72
- package/dist/discovery/index.d.mts +1 -0
- package/dist/discovery/index.mjs +1 -0
- package/dist/docs/index.d.mts +3 -2
- package/dist/docs/index.mjs +3 -2
- package/dist/{elevation-C9s5hFP_.d.mts → elevation-BXCfVcNG.d.mts} +1 -0
- package/dist/{elevation-CIz1GjGm.mjs → elevation-D2l1mh4g.mjs} +4 -3
- package/dist/encryption/index.d.mts +2 -1
- package/dist/encryption/index.mjs +3 -2
- package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-C5NeD6bT.mjs} +3 -2
- package/dist/{errorHandler-C6yv4ZTW.d.mts → errorHandler-CpYUJmPA.d.mts} +1 -0
- package/dist/{errors-DHcHVAgk.d.mts → errors-BGdVwP25.d.mts} +1 -0
- package/dist/{errors-DkO8Nk6-.mjs → errors-Cj42AntO.mjs} +1 -0
- package/dist/{eventPlugin-DrQ_FesK.mjs → eventPlugin-CkffEihm.mjs} +6 -106
- package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
- package/dist/events/index.d.mts +4 -3
- package/dist/events/index.mjs +17 -340
- package/dist/events/transports/redis-stream-entry.d.mts +2 -1
- package/dist/events/transports/redis-stream-entry.mjs +1 -0
- package/dist/events/transports/redis.d.mts +2 -1
- package/dist/events/transports/redis.mjs +1 -0
- package/dist/{externalPaths-BE6wFpYv.d.mts → externalPaths-CmGOxOtD.d.mts} +1 -0
- package/dist/factory/index.d.mts +9 -5
- package/dist/factory/index.mjs +7 -6
- package/dist/{fastify-augmentation-OzYGIiU1.d.mts → fastify-augmentation-zh0_AYHa.d.mts} +13 -4
- package/dist/{applyPermissionResult-BnyVE9eD.mjs → fields-CB5Cuzk9.mjs} +2 -107
- package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
- package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
- package/dist/{generate-D0wZupBg.mjs → generate-EcA6ui4i.mjs} +2 -1
- package/dist/{headers-BvlQSDMB.mjs → headers-3zvE0rM3.mjs} +2 -1
- package/dist/{health-CB_m4S32.mjs → health-DjZYjM7H.mjs} +1 -0
- package/dist/hooks/index.d.mts +2 -1
- package/dist/hooks/index.mjs +2 -1
- package/dist/idempotency/index.d.mts +3 -2
- package/dist/idempotency/index.mjs +5 -4
- package/dist/idempotency/redis.d.mts +2 -1
- package/dist/idempotency/redis.mjs +1 -0
- package/dist/{index-CjVg-Epg.d.mts → index-Bc2ox8_U.d.mts} +6 -5
- package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
- package/dist/{index-BMnbzvtO.d.mts → index-CEJNZFtX.d.mts} +242 -24
- package/dist/index-CFThn1K9.d.mts +224 -0
- package/dist/{index-DPRH0Cme.d.mts → index-CpzxqePp.d.mts} +203 -97
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +11 -9
- package/dist/{init-tlRSt667.mjs → init-BEiNZBsJ.mjs} +19 -23
- package/dist/{init-BPEu8cs-.d.mts → init-Cscs4lab.d.mts} +1 -0
- package/dist/integrations/event-gateway.d.mts +3 -2
- package/dist/integrations/event-gateway.mjs +2 -1
- package/dist/integrations/index.d.mts +4 -3
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs/index.d.mts +2 -1
- package/dist/integrations/jobs/index.mjs +108 -32
- package/dist/integrations/mcp/index.d.mts +9 -9
- package/dist/integrations/mcp/index.mjs +2 -1
- package/dist/integrations/mcp/testing.d.mts +3 -2
- package/dist/integrations/mcp/testing.mjs +2 -2
- package/dist/integrations/streamline.d.mts +1 -0
- package/dist/integrations/streamline.mjs +3 -2
- package/dist/integrations/webhooks.d.mts +1 -0
- package/dist/integrations/webhooks.mjs +1 -0
- package/dist/integrations/websocket-pushref-redis.d.mts +2 -1
- package/dist/integrations/websocket-pushref-redis.mjs +1 -0
- package/dist/integrations/websocket-redis.d.mts +2 -1
- package/dist/integrations/websocket-redis.mjs +1 -0
- package/dist/integrations/websocket.d.mts +3 -2
- package/dist/integrations/websocket.mjs +1 -0
- package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
- package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
- package/dist/{interface-n5hpKg1d.mjs → interface-DYzM0q-u.mjs} +1 -0
- package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-BYbLDi5D.mjs} +2 -1
- package/dist/{keys-Cd316u_y.mjs → keys-C0_pa1tY.mjs} +1 -0
- package/dist/{loadResources-DpU8pfjV.mjs → loadResources-yawi9tAE.mjs} +2 -1
- package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-BAjYZonx.mjs} +2 -1
- package/dist/logger/index.d.mts +1 -0
- package/dist/logger/index.mjs +1 -0
- package/dist/{mcpPlugin-Cs6nRGCt.mjs → mcpPlugin-B_es0hiF.mjs} +52 -60
- package/dist/{memory-CmnzXE5Z.mjs → memory-DR6wpa9F.mjs} +2 -1
- package/dist/{metrics-fdxI5mn_.mjs → metrics-CUdw_wLB.mjs} +2 -1
- package/dist/middleware/index.d.mts +2 -1
- package/dist/middleware/index.mjs +3 -2
- package/dist/migrations/index.d.mts +1 -3
- package/dist/migrations/index.mjs +2 -4
- package/dist/module-0pFJA6YW.mjs +78 -0
- package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-wOgj_fnj.mjs} +1 -0
- package/dist/{openapi-BLV4OMXb.mjs → openapi-B2L4js1v.mjs} +6 -5
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +6 -4
- package/dist/{permissions-BrtiBKGs.mjs → permissions-L--QDAir.mjs} +518 -316
- package/dist/{pipe-BOLmGIxa.mjs → pipe-DRDNsI2T.mjs} +2 -1
- package/dist/pipeline/index.d.mts +2 -1
- package/dist/pipeline/index.mjs +2 -1
- package/dist/{pipeline-BGRnV-To.mjs → pipeline-UPQFatit.mjs} +7 -20
- package/dist/plugins/index.d.mts +8 -7
- package/dist/plugins/index.mjs +16 -15
- package/dist/plugins/response-cache.d.mts +1 -0
- package/dist/plugins/response-cache.mjs +2 -1
- package/dist/plugins/tracing-entry.d.mts +2 -1
- package/dist/plugins/tracing-entry.mjs +2 -1
- package/dist/{pluralize-BhrgwZb9.mjs → pluralize-O0FZgESl.mjs} +1 -0
- package/dist/{preloadResources-CM4uUaFv.d.mts → preloadResources-CyoJMSiO.d.mts} +117 -12
- package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-Dz6BjzM6.mjs} +1 -0
- package/dist/presets/filesUpload.d.mts +6 -5
- package/dist/presets/filesUpload.mjs +9 -11
- package/dist/presets/index.d.mts +15 -2
- package/dist/presets/index.mjs +2 -1
- package/dist/presets/multiTenant.d.mts +2 -1
- package/dist/presets/multiTenant.mjs +3 -2
- package/dist/presets/search.d.mts +3 -2
- package/dist/presets/search.mjs +2 -1
- package/dist/{presets-DwFDVKP0.mjs → presets-C4-g4_4P.mjs} +27 -10
- package/dist/projection-BHw6xlOQ.mjs +18 -0
- package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
- package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-BZr8v46E.mjs} +5 -4
- package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
- package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-CMPY5Qms.mjs} +7 -3
- package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-Dn5JNmkj.mjs} +1 -0
- package/dist/{realtime-DEuDu9io.mjs → realtime-C5NoxWFY.mjs} +20 -8
- package/dist/{redis-UDtLaNj6.d.mts → redis-CduhKsJi.d.mts} +2 -1
- package/dist/{redis-stream-uIaauNpZ.d.mts → redis-stream-qN6A-RFv.d.mts} +2 -1
- package/dist/{registerRoute-DTp18Ah_.mjs → registerRoute-CBN84fc7.mjs} +5 -2
- package/dist/registry/index.d.mts +3 -2
- package/dist/registry/index.mjs +3 -2
- package/dist/{registry-9km_w1aP.mjs → registry-4213U4zb.mjs} +3 -2
- package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-Dll8mGgc.mjs} +1 -0
- package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DIiZKGUt.mjs} +2 -1
- package/dist/repositoryFilter-f9eAfq_l.mjs +45 -0
- package/dist/{requestContext-MrlJwECf.mjs → requestContext-2TxXOJ7T.mjs} +1 -0
- package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-CUsjNX9R.mjs} +1 -0
- package/dist/{schedules-CjOd2MG9.mjs → schedules-DdtlICTf.mjs} +3 -2
- package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-D--wdJM-.mjs} +70 -17
- package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-Bm2enbnh.mjs} +2 -1
- package/dist/schemas/index.d.mts +1 -0
- package/dist/schemas/index.mjs +1 -0
- package/dist/scim/index.d.mts +1 -0
- package/dist/scim/index.mjs +2 -1
- package/dist/scope/index.d.mts +3 -2
- package/dist/scope/index.mjs +5 -4
- package/dist/{scope-DfaPntpo.mjs → scope-DHx5Fous.mjs} +4 -3
- package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
- package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-DjQJ7FKA.mjs} +1 -0
- package/dist/{sse-BQ1w0dfl.mjs → sse-CUTo9y0X.mjs} +5 -4
- package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B_5XcVVd.mjs} +2 -1
- package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
- package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-D1MP_gRG.mjs} +1 -0
- package/dist/{streaming-BQcW6_Kq.mjs → streaming-PSZwi8JV.mjs} +1 -0
- package/dist/subscribe-helpers-C0Tb2aUp.mjs +340 -0
- package/dist/sync/changelog.d.mts +1 -0
- package/dist/sync/changelog.mjs +1 -0
- package/dist/testing/cleanupStoreContract.d.mts +2 -1
- package/dist/testing/cleanupStoreContract.mjs +1 -0
- package/dist/testing/index.d.mts +167 -12
- package/dist/testing/index.mjs +522 -205
- package/dist/testing/outboxStoreContract.d.mts +1 -0
- package/dist/testing/outboxStoreContract.mjs +1 -0
- package/dist/testing/storageContract.d.mts +2 -1
- package/dist/testing/storageContract.mjs +1 -0
- package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
- package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-dAfBVUrk.mjs} +1 -0
- package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B0ryPo3I.mjs} +1 -0
- package/dist/types/index.d.mts +6 -5
- package/dist/types/index.mjs +1 -0
- package/dist/types/storage.d.mts +2 -1
- package/dist/types/storage.mjs +1 -0
- package/dist/{types-Dmw-6Qeo.d.mts → types-B7XeLEgK.d.mts} +127 -90
- package/dist/{types-Cc91nXuA.d.mts → types-ByHn9rEO.d.mts} +1 -0
- package/dist/{types-C_ZZRcD6.d.mts → types-C4QE8qnm.d.mts} +1 -0
- package/dist/{types-Cu6vVJmh.d.mts → types-CBgvkp8O.d.mts} +82 -12
- package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
- package/dist/{types-QFGc3Cjv.d.mts → types-CwcUQ610.d.mts} +2 -6
- package/dist/{types-CSyCxl2V.mjs → types-Cys0ko9Z.mjs} +4 -3
- package/dist/usage/index.d.mts +3 -2
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-Cg_y3fBz.mjs → userHelpers-ChYJ6CdK.mjs} +1 -0
- package/dist/utils/index.d.mts +16 -10
- package/dist/utils/index.mjs +10 -9
- package/dist/{utils-taUVD4p3.mjs → utils-vL8BrDE2.mjs} +3 -2
- package/dist/{validate-Bk44F2yT.mjs → validate-_KbifpHF.mjs} +2 -1
- package/dist/{versioning-gKWyryT3.mjs → versioning-CHDTor3P.mjs} +3 -2
- package/dist/{versioning-DXgY5BUm.d.mts → versioning-D_rhHfZm.d.mts} +5 -2
- package/dist/{websocket-_Pd0CgR0.d.mts → websocket-BOXVggMf.d.mts} +2 -1
- package/package.json +15 -7
- package/skills/arc/SKILL.md +22 -8
- package/skills/arc/references/api-reference.md +4 -0
- package/skills/arc/references/auth.md +3 -0
- package/skills/arc/references/integrations.md +33 -0
- package/skills/arc/references/mcp.md +6 -7
- package/skills/arc/references/production.md +24 -25
- package/skills/arc-code-review/references/anti-patterns.md +3 -3
- package/dist/index-CZY4EGga.d.mts +0 -107
- package/dist/module-_-M7C5ES.mjs +0 -29
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { arcLog } from "./logger/index.mjs";
|
|
3
|
+
import { t as ArcError } from "./errors-Cj42AntO.mjs";
|
|
4
|
+
//#region src/permissions/filter-merge.ts
|
|
5
|
+
/**
|
|
6
|
+
* Policy-filter composition — logical AND, never last-writer-wins.
|
|
7
|
+
*
|
|
8
|
+
* Row-level policy filters can arrive from several INDEPENDENT sources for one
|
|
9
|
+
* request: a tenant preset, an `ownedByUser` grant, an `allOf(...)` branch, a
|
|
10
|
+
* host permission check. Every one of them is a RESTRICTION the row must
|
|
11
|
+
* satisfy, so composing them is logical AND.
|
|
12
|
+
*
|
|
13
|
+
* The historical `{ ...base, ...incoming }` shallow spread did NOT implement AND:
|
|
14
|
+
* when two sources constrained the SAME key with different values, the later one
|
|
15
|
+
* silently REPLACED the earlier one — widening (or erasing) a restriction another
|
|
16
|
+
* layer deliberately imposed. That is a defense-in-depth defect, not a
|
|
17
|
+
* refinement. "Later can refine" is only sound when the refinement is provably
|
|
18
|
+
* narrower, and a bare overwrite proves nothing.
|
|
19
|
+
*
|
|
20
|
+
* {@link conjoinPolicyFilters} composes with AND semantics while preserving the
|
|
21
|
+
* common case byte-for-byte:
|
|
22
|
+
*
|
|
23
|
+
* - key present on only one side → carried through flat. Non-overlapping
|
|
24
|
+
* filters (the ~99% case) produce exactly the same object the old spread did,
|
|
25
|
+
* so there is ZERO behavior change for them.
|
|
26
|
+
* - same key, deep-equal value → kept once (idempotent — e.g. two checks
|
|
27
|
+
* both pinning the same `organizationId`).
|
|
28
|
+
* - same key, DIFFERENT value → BOTH constraints are preserved under an
|
|
29
|
+
* `$and`, so a row must satisfy both. For flat equality that conjunction is
|
|
30
|
+
* unsatisfiable, so the query returns nothing — the safe, correct outcome for
|
|
31
|
+
* contradictory policies (deny), and the earlier restriction is never dropped.
|
|
32
|
+
*
|
|
33
|
+
* Adapter safety: mongokit / sqlitekit compile `$and` natively at the DB layer,
|
|
34
|
+
* and arc's in-memory `simpleEqualityMatcher` (AccessControl.checkPolicyFilters)
|
|
35
|
+
* already fail-closes on operator-shaped filters. So a produced `$and` is either
|
|
36
|
+
* evaluated correctly by the DB or rejected fail-closed in memory — both safe.
|
|
37
|
+
*
|
|
38
|
+
* This is the pragmatic, adapter-neutral form of the AND semantics. A canonical
|
|
39
|
+
* filter IR in `repo-core` (nested and/or/not nodes each adapter compiles) is the
|
|
40
|
+
* fuller design, but this closes the security defect without one.
|
|
41
|
+
*/
|
|
42
|
+
/**
|
|
43
|
+
* Validate + return a `$and` operand's fragment array. A security-policy
|
|
44
|
+
* normalizer must NEVER silently drop a malformed constraint — a non-array
|
|
45
|
+
* `$and` (e.g. `{ $and: { organizationId: "a" } }`) is a policy bug, so fail
|
|
46
|
+
* loud (fail-closed) rather than discard the restriction it was meant to carry.
|
|
47
|
+
*/
|
|
48
|
+
function coercePolicyAnd(value) {
|
|
49
|
+
if (!Array.isArray(value)) throw new Error(`conjoinPolicyFilters: malformed '$and' — expected an array of filter fragments, got ${value === null ? "null" : typeof value}. A policy filter constraint must not be silently dropped.`);
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
/** Are two flat policy-filter values equivalent for conjunction purposes? */
|
|
53
|
+
function filterValueEqual(a, b) {
|
|
54
|
+
if (Object.is(a, b)) return true;
|
|
55
|
+
if (a !== null && b !== null && typeof a === "object" && typeof b === "object") try {
|
|
56
|
+
return JSON.stringify(a) === JSON.stringify(b);
|
|
57
|
+
} catch {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Conjoin two policy-filter maps with AND semantics. Never silently overwrites a
|
|
64
|
+
* same-key constraint with a different value — conflicting keys are preserved
|
|
65
|
+
* under `$and`. See the module doc for the full contract.
|
|
66
|
+
*/
|
|
67
|
+
function conjoinPolicyFilters(base, incoming) {
|
|
68
|
+
const baseEmpty = !base || Object.keys(base).length === 0;
|
|
69
|
+
const incomingEmpty = !incoming || Object.keys(incoming).length === 0;
|
|
70
|
+
if (baseEmpty) return incomingEmpty ? {} : { ...incoming };
|
|
71
|
+
if (incomingEmpty) return { ...base };
|
|
72
|
+
const result = {};
|
|
73
|
+
const andParts = [];
|
|
74
|
+
const baseAnd = base.$and;
|
|
75
|
+
if (baseAnd !== void 0) andParts.push(...coercePolicyAnd(baseAnd));
|
|
76
|
+
for (const [key, value] of Object.entries(base)) {
|
|
77
|
+
if (key === "$and") continue;
|
|
78
|
+
result[key] = value;
|
|
79
|
+
}
|
|
80
|
+
for (const [key, value] of Object.entries(incoming)) {
|
|
81
|
+
if (key === "$and") {
|
|
82
|
+
andParts.push(...coercePolicyAnd(value));
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
if (!(key in result)) {
|
|
86
|
+
result[key] = value;
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (filterValueEqual(result[key], value)) continue;
|
|
90
|
+
andParts.push({ [key]: result[key] }, { [key]: value });
|
|
91
|
+
delete result[key];
|
|
92
|
+
}
|
|
93
|
+
if (andParts.length > 0) result.$and = andParts;
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/permissions/authorizationDecision.ts
|
|
98
|
+
const log = arcLog("permissions:enforce");
|
|
99
|
+
/**
|
|
100
|
+
* Normalize a check return into the canonical {@link AuthorizationDecision}.
|
|
101
|
+
* A boolean promotes to `{ effect: "allow" | "deny" }`; a decision passes
|
|
102
|
+
* through. This is the ONE place booleans are promoted, so the rest of the
|
|
103
|
+
* pipeline only ever handles decisions.
|
|
104
|
+
*/
|
|
105
|
+
function normalizeToDecision(result) {
|
|
106
|
+
if (typeof result === "boolean") return { effect: result ? "allow" : "deny" };
|
|
107
|
+
/**
|
|
108
|
+
* A returned object MUST carry an `effect`. Without this guard a foreign shape — the
|
|
109
|
+
* pre-2.30 `{ granted: true }`, a hand-rolled `{ allowed: true }`, a stray Promise
|
|
110
|
+
* someone forgot to await — passed through as a decision with no effect and was read
|
|
111
|
+
* as DENY. A gate that says yes and is silently overruled is the worst available
|
|
112
|
+
* failure: nine `@classytic/arc-*` test suites went red at once and every symptom
|
|
113
|
+
* pointed at authentication rather than at the return shape.
|
|
114
|
+
*
|
|
115
|
+
* Throwing lands in `failed` (fail-closed, still a denial), so behaviour is unchanged
|
|
116
|
+
* for anything already correct — but the reason now names itself instead of hiding.
|
|
117
|
+
*/
|
|
118
|
+
const effect = result?.effect;
|
|
119
|
+
if (result === null || typeof result !== "object" || effect !== "allow" && effect !== "deny") throw new Error(`[arc] a permission check returned an unrecognized shape: ${JSON.stringify(result)}. Return a boolean or an AuthorizationDecision ({ effect: 'allow' | 'deny', ... }). The pre-2.30 { granted } shape is no longer accepted — it normalized to a silent deny.`);
|
|
120
|
+
return result;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Run a permission check once and classify the result. The single source of the
|
|
124
|
+
* try/normalize/catch sequence — see {@link PermissionOutcome}. Non-`ArcError`
|
|
125
|
+
* throws are logged once here through arc's namespaced logger (a deliberate
|
|
126
|
+
* `ArcError` denial is expected control-flow, not a warning). Pure w.r.t. the
|
|
127
|
+
* request — neither reads a reply nor mutates the request.
|
|
128
|
+
*/
|
|
129
|
+
async function evaluatePermissionOutcome(check, context) {
|
|
130
|
+
try {
|
|
131
|
+
return {
|
|
132
|
+
status: "decided",
|
|
133
|
+
decision: normalizeToDecision(await check(context))
|
|
134
|
+
};
|
|
135
|
+
} catch (err) {
|
|
136
|
+
if (err instanceof ArcError) return {
|
|
137
|
+
status: "structured",
|
|
138
|
+
error: err
|
|
139
|
+
};
|
|
140
|
+
log.warn({
|
|
141
|
+
err,
|
|
142
|
+
resource: context.resource,
|
|
143
|
+
action: context.action
|
|
144
|
+
}, "Permission check threw — denying (fail-closed)");
|
|
145
|
+
return {
|
|
146
|
+
status: "failed",
|
|
147
|
+
error: err
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Run a permission check and return a canonical {@link AuthorizationDecision} —
|
|
153
|
+
* the transport-neutral PDP (HTTP, aggregation, MCP, and any future transport).
|
|
154
|
+
* A thin mapper over {@link evaluatePermissionOutcome}:
|
|
155
|
+
*
|
|
156
|
+
* - a structured `ArcError` is RE-THROWN so the transport surfaces it verbatim
|
|
157
|
+
* (e.g. a tier gate throwing `arc.tier_required` with machine-readable meta);
|
|
158
|
+
* - any OTHER throw is fail-closed to a `deny` decision (a broken check must
|
|
159
|
+
* never fall open to a 500 that skips authorization).
|
|
160
|
+
*
|
|
161
|
+
* Pure w.r.t. the request — it neither reads a reply nor mutates the request.
|
|
162
|
+
* Callers translate the returned decision into their own response mechanism and
|
|
163
|
+
* apply side-effects via {@link applyAuthorizationDecision}. HTTP additionally
|
|
164
|
+
* hardens a *thrown* check to 403-even-when-anonymous — that transport-specific
|
|
165
|
+
* nuance lives in {@link evaluateAndApplyPermission}, not here.
|
|
166
|
+
*/
|
|
167
|
+
async function evaluatePermissionDecision(check, context) {
|
|
168
|
+
const outcome = await evaluatePermissionOutcome(check, context);
|
|
169
|
+
switch (outcome.status) {
|
|
170
|
+
case "decided": return outcome.decision;
|
|
171
|
+
case "structured": throw outcome.error;
|
|
172
|
+
case "failed": return { effect: "deny" };
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Apply an allowed {@link AuthorizationDecision} to a Fastify request — conjoins
|
|
177
|
+
* the decision's row-level `policy` into `_policyFilters` and conditionally
|
|
178
|
+
* installs the `scope`.
|
|
179
|
+
*
|
|
180
|
+
* **Scope install rule:** only writes `scope` when the current request scope
|
|
181
|
+
* is absent or `public`. This prevents downgrading an already-authenticated
|
|
182
|
+
* request (e.g. Better Auth set `member`, then a permission check returns a
|
|
183
|
+
* narrower `service` scope — the original `member` wins because it came from
|
|
184
|
+
* a more authoritative source).
|
|
185
|
+
*
|
|
186
|
+
* Safe to call with a denied decision — it simply no-ops. Callers should still
|
|
187
|
+
* check `decision.effect` and send an error response before reaching here, but
|
|
188
|
+
* this function tolerates the misuse defensively.
|
|
189
|
+
*
|
|
190
|
+
* This is the enforcement point (PEP) — the ONE place scope + data policy are
|
|
191
|
+
* installed (and the obligation seam lives).
|
|
192
|
+
*/
|
|
193
|
+
function applyAuthorizationDecision(decision, request) {
|
|
194
|
+
if (decision.effect !== "allow") return;
|
|
195
|
+
if (decision.policy) request._policyFilters = conjoinPolicyFilters(request._policyFilters, decision.policy);
|
|
196
|
+
if (decision.scope) {
|
|
197
|
+
const current = request.scope;
|
|
198
|
+
if (!current || current.kind === "public") request.scope = decision.scope;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Max length of a decision `reason` string before we fall back to the
|
|
203
|
+
* generic default message. Upstream checks can return arbitrary strings; we
|
|
204
|
+
* clamp to prevent accidental leakage of internal diagnostics or oversized
|
|
205
|
+
* payloads via the 4xx response body.
|
|
206
|
+
*/
|
|
207
|
+
const MAX_DENIAL_REASON_LENGTH = 100;
|
|
208
|
+
/**
|
|
209
|
+
* End-to-end HTTP PEP: evaluates the check through the shared
|
|
210
|
+
* {@link evaluatePermissionOutcome} core, sends a 401/403 response on denial,
|
|
211
|
+
* and applies side-effects on grant. Returns `true` if the caller should
|
|
212
|
+
* continue, `false` if a response has been sent and the caller should return.
|
|
213
|
+
*
|
|
214
|
+
* The HTTP specialization of the ONE evaluation core — it does NOT re-run or
|
|
215
|
+
* re-normalize the check; it only maps the classified outcome onto Fastify:
|
|
216
|
+
*
|
|
217
|
+
* - `structured` (thrown `ArcError`) → surface verbatim, byte-compatible with
|
|
218
|
+
* the global error handler (`code`/`message`/`status` + `meta`);
|
|
219
|
+
* - `failed` (other throw) → 403 EVEN WHEN ANONYMOUS (a broken check is a hard
|
|
220
|
+
* denial, not a "please authenticate");
|
|
221
|
+
* - `decided` → allow, or a returned deny → 401 (no user) / 403 (user) with a
|
|
222
|
+
* clamped `reason`.
|
|
223
|
+
*
|
|
224
|
+
* Context construction, pre-check auth gating, and success-path handler
|
|
225
|
+
* invocation stay at the callsite — those are genuinely different per router
|
|
226
|
+
* and don't belong here.
|
|
227
|
+
*
|
|
228
|
+
* @returns `true` if authorized (caller continues), `false` if a response was sent
|
|
229
|
+
*/
|
|
230
|
+
async function evaluateAndApplyPermission(check, context, request, reply, opts) {
|
|
231
|
+
const outcome = await evaluatePermissionOutcome(check, context);
|
|
232
|
+
if (outcome.status === "structured") {
|
|
233
|
+
const err = outcome.error;
|
|
234
|
+
reply.code(err.status).send({
|
|
235
|
+
code: err.code,
|
|
236
|
+
message: err.message,
|
|
237
|
+
status: err.status,
|
|
238
|
+
...err.meta ? { meta: err.meta } : {}
|
|
239
|
+
});
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
if (outcome.status === "failed") {
|
|
243
|
+
reply.code(403).send({
|
|
244
|
+
code: "arc.forbidden",
|
|
245
|
+
message: "Permission denied",
|
|
246
|
+
status: 403
|
|
247
|
+
});
|
|
248
|
+
return false;
|
|
249
|
+
}
|
|
250
|
+
const { decision } = outcome;
|
|
251
|
+
if (decision.effect !== "allow") {
|
|
252
|
+
const defaultMsg = opts?.defaultDenialMessage?.(context.user) ?? (context.user ? "Permission denied" : "Authentication required");
|
|
253
|
+
const reason = decision.reason && decision.reason.length <= MAX_DENIAL_REASON_LENGTH ? decision.reason : defaultMsg;
|
|
254
|
+
const status = context.user ? 403 : 401;
|
|
255
|
+
reply.code(status).send({
|
|
256
|
+
code: context.user ? "arc.forbidden" : "arc.unauthorized",
|
|
257
|
+
message: reason,
|
|
258
|
+
status
|
|
259
|
+
});
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
applyAuthorizationDecision(decision, request);
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
265
|
+
//#endregion
|
|
266
|
+
export { conjoinPolicyFilters as a, normalizeToDecision as i, evaluateAndApplyPermission as n, evaluatePermissionDecision as r, applyAuthorizationDecision as t };
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as conjoinPolicyFilters } from "./authorizationDecision-ChvUQGG1.mjs";
|
|
3
|
+
import { t as toRepositoryFilter } from "./repositoryFilter-f9eAfq_l.mjs";
|
|
4
|
+
import { i as compileAggRequest, t as adapterSupportsAggregate } from "./validate-_KbifpHF.mjs";
|
|
2
5
|
//#region src/core/aggregation/buildHandler.ts
|
|
3
6
|
/**
|
|
4
7
|
* Framework-agnostic aggregation execution. Runs safety guards,
|
|
@@ -18,13 +21,13 @@ async function executeAggregation(normalized, deps, ctx) {
|
|
|
18
21
|
const { repo } = deps;
|
|
19
22
|
const config = normalized.base;
|
|
20
23
|
const aggregationName = normalized.name;
|
|
21
|
-
const { query, tenantOptions } = ctx;
|
|
24
|
+
const { query, tenantOptions, policyFilter } = ctx;
|
|
22
25
|
const guardError = checkRequestGuards(query, config);
|
|
23
26
|
if (guardError) return {
|
|
24
27
|
status: 400,
|
|
25
28
|
body: guardError
|
|
26
29
|
};
|
|
27
|
-
const aggReq = compileAggRequest(normalized, extractCallerFilter(query), tenantOptions, query);
|
|
30
|
+
const aggReq = compileAggRequest(normalized, conjoinPolicyFilters(extractCallerFilter(query), policyFilter), tenantOptions, query);
|
|
28
31
|
if (config.materialized) {
|
|
29
32
|
const matCtx = {
|
|
30
33
|
filter: aggReq.filter,
|
|
@@ -51,9 +54,13 @@ async function executeAggregation(normalized, deps, ctx) {
|
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
};
|
|
57
|
+
const aggReqForRepo = aggReq.filter && typeof aggReq.filter === "object" ? {
|
|
58
|
+
...aggReq,
|
|
59
|
+
filter: toRepositoryFilter(aggReq.filter)
|
|
60
|
+
} : aggReq;
|
|
54
61
|
let result;
|
|
55
62
|
try {
|
|
56
|
-
result = await repo.aggregate(
|
|
63
|
+
result = await repo.aggregate(aggReqForRepo, tenantOptions);
|
|
57
64
|
} catch (err) {
|
|
58
65
|
return mapAggregateError(err, aggregationName);
|
|
59
66
|
}
|
|
@@ -95,9 +102,13 @@ async function executeAggregation(normalized, deps, ctx) {
|
|
|
95
102
|
function buildAggregationHandler(normalized, deps) {
|
|
96
103
|
const { buildOptions } = deps;
|
|
97
104
|
return async (request, reply) => {
|
|
105
|
+
const query = request.query ?? {};
|
|
106
|
+
const tenantOptions = buildOptions(request);
|
|
107
|
+
const policyFilter = request._policyFilters;
|
|
98
108
|
const result = await executeAggregation(normalized, deps, {
|
|
99
|
-
query
|
|
100
|
-
tenantOptions
|
|
109
|
+
query,
|
|
110
|
+
tenantOptions,
|
|
111
|
+
policyFilter
|
|
101
112
|
});
|
|
102
113
|
reply.status(result.status);
|
|
103
114
|
if (result.headers) for (const [k, v] of Object.entries(result.headers)) reply.header(k, v);
|
|
@@ -199,6 +210,20 @@ const SHORTHAND_RANGE_OPS = /* @__PURE__ */ new Set([
|
|
|
199
210
|
"lt",
|
|
200
211
|
"lte"
|
|
201
212
|
]);
|
|
213
|
+
/**
|
|
214
|
+
* Operators whose operand MUST be a list. A URL carries `priority[in]=high,urgent`
|
|
215
|
+
* as ONE string, and `$in` against a non-array is invalid — MongoDB rejects it,
|
|
216
|
+
* and the portable Filter IR would spread the string into characters. Split it
|
|
217
|
+
* the same way `ArcQueryParser` does for the CRUD list route, which is the
|
|
218
|
+
* contract this expansion claims to match.
|
|
219
|
+
*/
|
|
220
|
+
const SHORTHAND_LIST_OPS = /* @__PURE__ */ new Set(["in", "nin"]);
|
|
221
|
+
/** Normalize a list-operator operand to an array (URL string → split on commas). */
|
|
222
|
+
function toOperandList(value) {
|
|
223
|
+
if (Array.isArray(value)) return value;
|
|
224
|
+
if (typeof value === "string") return value.split(",").map((v) => v.trim()).filter((v) => v.length > 0);
|
|
225
|
+
return [value];
|
|
226
|
+
}
|
|
202
227
|
const ISO_DATE_RE = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
|
|
203
228
|
function tryCoerceDate(v) {
|
|
204
229
|
if (typeof v !== "string" || !ISO_DATE_RE.test(v)) return v;
|
|
@@ -222,7 +247,9 @@ function expandShorthandOperators(value) {
|
|
|
222
247
|
for (const [op, opVal] of Object.entries(nested)) {
|
|
223
248
|
const mongoOp = OPERATOR_SHORTHAND[op];
|
|
224
249
|
if (!mongoOp) continue;
|
|
225
|
-
|
|
250
|
+
if (SHORTHAND_RANGE_OPS.has(op)) expanded[mongoOp] = tryCoerceDate(opVal);
|
|
251
|
+
else if (SHORTHAND_LIST_OPS.has(op)) expanded[mongoOp] = toOperandList(opVal);
|
|
252
|
+
else expanded[mongoOp] = opVal;
|
|
226
253
|
}
|
|
227
254
|
return expanded;
|
|
228
255
|
}
|
package/dist/cache/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { i as
|
|
1
|
+
|
|
2
|
+
import { n as CacheStats, r as CacheStore, t as CacheLogger } from "../interface-BOk3YnTz.mjs";
|
|
3
|
+
import { a as QueryCacheConfig, i as QueryCache, n as CacheResult, r as CacheStatus, t as CacheEnvelope } from "../QueryCache-DFA-QrU9.mjs";
|
|
4
|
+
import { i as queryCachePlugin, n as QueryCacheDefaults, r as QueryCachePluginOptions, t as CrossResourceRule } from "../queryCachePlugin-BzqxconG.mjs";
|
|
4
5
|
//#region src/cache/keys.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* Cache Key Utilities
|
package/dist/cache/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { i as versionKey, n as hashParams, r as tagVersionKey, t as buildQueryKey } from "../keys-C0_pa1tY.mjs";
|
|
3
|
+
import { t as MemoryCacheStore } from "../memory-DR6wpa9F.mjs";
|
|
4
|
+
import { r as QueryCache, t as queryCachePlugin } from "../queryCachePlugin-BZr8v46E.mjs";
|
|
4
5
|
//#region src/cache/redis.ts
|
|
5
6
|
/**
|
|
6
7
|
* Redis-backed cache store.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-CUsjNX9R.mjs";
|
|
2
3
|
import fp from "fastify-plugin";
|
|
3
4
|
//#region src/plugins/caching.ts
|
|
4
5
|
var caching_exports = /* @__PURE__ */ __exportAll({
|
package/dist/cleanup/index.d.mts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
1
|
+
|
|
2
|
+
import { L as RequestWithExtras } from "../index-CpzxqePp.mjs";
|
|
3
|
+
import { A as CleanupWriteFence, C as CleanupResult, D as CleanupRunStore, E as CleanupRunStatus, F as PurgeStrategyKind, I as PurgeVerificationSummary, L as VerificationCheck, M as PurgeActor, N as PurgeEvidence, O as CleanupRunTransitionPatch, P as PurgeResourceResult, R as VerificationResult, S as CleanupRecipe, T as CleanupRunCreateResult, _ as CleanupPermissions, a as CleanupEvidenceStore, b as CleanupPlanItem, c as CleanupInput, d as CleanupLease, f as CleanupLimits, g as CleanupPermissionCheck, h as CleanupOutcomeStatus, i as CleanupContext, j as DEFAULT_CLEANUP_LIMITS, k as CleanupStepResult, l as CleanupJob, m as CleanupManifest, n as CLEANUP_TERMINAL_STATUSES, o as CleanupExecutionContext, p as CleanupLogger, r as CleanupCancelRequest, s as CleanupFinalizationPayload, t as Availability, u as CleanupJobQueue, v as CleanupPlan, w as CleanupRun, x as CleanupProgressSummary, y as CleanupPlanDraft } from "../types-C4QE8qnm.mjs";
|
|
4
|
+
import { t as ArcModule } from "../types-CBgvkp8O.mjs";
|
|
4
5
|
import { PurgeStrategyKind as PurgeStrategyKind$1 } from "@classytic/primitives/retention";
|
|
5
6
|
import { canonicalJson } from "@classytic/primitives/canonical";
|
|
6
7
|
import { CleanupStep } from "@classytic/repo-core/cleanup";
|
package/dist/cleanup/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { g as getUserId } from "../types-Cys0ko9Z.mjs";
|
|
3
|
+
import { t as defineResource } from "../defineResource-Bv6EtN1x.mjs";
|
|
4
|
+
import { t as defineModule } from "../module-0pFJA6YW.mjs";
|
|
4
5
|
import { createPurgeEvidence } from "@classytic/primitives/retention";
|
|
5
6
|
import { canonicalJson, sha256Hex } from "@classytic/primitives/canonical";
|
|
6
7
|
//#region src/cleanup/errors.ts
|
|
@@ -1175,8 +1176,7 @@ function createDataCleanupModule(deps) {
|
|
|
1175
1176
|
path: "/recipes",
|
|
1176
1177
|
summary: "List available cleanup recipes",
|
|
1177
1178
|
permissions: view,
|
|
1178
|
-
|
|
1179
|
-
handler: async (_req, reply) => {
|
|
1179
|
+
rawHandler: async (_req, reply) => {
|
|
1180
1180
|
return reply.send({ recipes: registry.introspect() });
|
|
1181
1181
|
}
|
|
1182
1182
|
},
|
|
@@ -1185,9 +1185,8 @@ function createDataCleanupModule(deps) {
|
|
|
1185
1185
|
path: "/preview",
|
|
1186
1186
|
summary: "Preview a cleanup plan (no mutation)",
|
|
1187
1187
|
permissions: view,
|
|
1188
|
-
raw: true,
|
|
1189
1188
|
schema: { body: previewBodySchema },
|
|
1190
|
-
|
|
1189
|
+
rawHandler: async (req, reply) => {
|
|
1191
1190
|
const r = req;
|
|
1192
1191
|
const body = req.body;
|
|
1193
1192
|
const plan = await service.preview({
|
|
@@ -1204,9 +1203,8 @@ function createDataCleanupModule(deps) {
|
|
|
1204
1203
|
path: "/runs",
|
|
1205
1204
|
summary: "Execute a confirmed cleanup plan",
|
|
1206
1205
|
permissions: execute,
|
|
1207
|
-
raw: true,
|
|
1208
1206
|
schema: { body: runsBodySchema },
|
|
1209
|
-
|
|
1207
|
+
rawHandler: async (req, reply) => {
|
|
1210
1208
|
const r = req;
|
|
1211
1209
|
const body = req.body;
|
|
1212
1210
|
const run = await service.execute({
|
|
@@ -1226,9 +1224,8 @@ function createDataCleanupModule(deps) {
|
|
|
1226
1224
|
path: "/runs/:id",
|
|
1227
1225
|
summary: "Observe a cleanup run",
|
|
1228
1226
|
permissions: view,
|
|
1229
|
-
raw: true,
|
|
1230
1227
|
schema: { params: runIdParamsSchema },
|
|
1231
|
-
|
|
1228
|
+
rawHandler: async (req, reply) => {
|
|
1232
1229
|
const { id } = req.params;
|
|
1233
1230
|
return reply.send(await service.getRun(id));
|
|
1234
1231
|
}
|
|
@@ -1238,12 +1235,11 @@ function createDataCleanupModule(deps) {
|
|
|
1238
1235
|
path: "/runs/:id/action",
|
|
1239
1236
|
summary: "Cancel or retry a cleanup run",
|
|
1240
1237
|
permissions: manage,
|
|
1241
|
-
raw: true,
|
|
1242
1238
|
schema: {
|
|
1243
1239
|
params: runIdParamsSchema,
|
|
1244
1240
|
body: actionBodySchema
|
|
1245
1241
|
},
|
|
1246
|
-
|
|
1242
|
+
rawHandler: async (req, reply) => {
|
|
1247
1243
|
const actionActor = resolveActor(req);
|
|
1248
1244
|
const { id } = req.params;
|
|
1249
1245
|
const { action, reason } = req.body;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { Nt as RateLimitConfig, V as ResourceDefinition, et as RouteSchemaOptions } from "../../index-CpzxqePp.mjs";
|
|
2
3
|
//#region src/cli/commands/describe.d.ts
|
|
3
4
|
interface DescribedResource {
|
|
4
5
|
name: string;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as CRUD_OPERATIONS } from "../../constants-D3Dv4LAV.mjs";
|
|
3
|
+
import { n as stringifyMeasureMap } from "../../ResourceRegistry-qq0mn2s9.mjs";
|
|
3
4
|
import { resolve } from "node:path";
|
|
4
5
|
import { pathToFileURL } from "node:url";
|
|
5
6
|
//#region src/cli/commands/describe.ts
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as buildOpenApiSpec } from "../../openapi-B2L4js1v.mjs";
|
|
3
|
+
import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-BAjYZonx.mjs";
|
|
3
4
|
import { dirname, resolve } from "node:path";
|
|
4
5
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
5
6
|
//#region src/cli/commands/docs.ts
|
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { a as ProjectConfig, i as PackageManager, n as DependencyManifest, r as InitOptions, t as init } from "../../init-Cscs4lab.mjs";
|
|
2
3
|
export { type DependencyManifest, type InitOptions, type PackageManager, type ProjectConfig, init };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as loadResourcesFromEntry } from "../../loadResourcesFromEntry-BAjYZonx.mjs";
|
|
2
3
|
//#region src/cli/commands/introspect.ts
|
|
3
4
|
function describePermission(value) {
|
|
4
5
|
if (!value) return "none";
|
package/dist/cli/index.d.mts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
|
|
1
2
|
import { describe } from "./commands/describe.mjs";
|
|
2
3
|
import { exportDocs } from "./commands/docs.mjs";
|
|
3
4
|
import { doctor } from "./commands/doctor.mjs";
|
|
4
|
-
import { n as generate } from "../generate-
|
|
5
|
-
import { t as init } from "../init-
|
|
5
|
+
import { n as generate } from "../generate-DCGuEbqI.mjs";
|
|
6
|
+
import { t as init } from "../init-Cscs4lab.mjs";
|
|
6
7
|
import { introspect } from "./commands/introspect.mjs";
|
|
7
8
|
export { describe, doctor, exportDocs, generate, init, introspect };
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
1
2
|
import { describe } from "./commands/describe.mjs";
|
|
2
3
|
import { exportDocs } from "./commands/docs.mjs";
|
|
3
4
|
import { doctor } from "./commands/doctor.mjs";
|
|
4
|
-
import { t as generate } from "../generate-
|
|
5
|
-
import { t as init } from "../init-
|
|
5
|
+
import { t as generate } from "../generate-EcA6ui4i.mjs";
|
|
6
|
+
import { t as init } from "../init-BEiNZBsJ.mjs";
|
|
6
7
|
import { introspect } from "./commands/introspect.mjs";
|
|
7
8
|
export { describe, doctor, exportDocs, generate, init, introspect };
|
package/dist/context/index.d.mts
CHANGED
package/dist/context/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.31.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as requestContext, t as getTraceHeaders } from "../requestContext-2TxXOJ7T.mjs";
|
|
3
|
+
import { t as transactionContext } from "../transactionContext-dAfBVUrk.mjs";
|
|
3
4
|
export { getTraceHeaders, requestContext, transactionContext };
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
1
|
+
|
|
2
|
+
import { $t as TreeMixin, An as BaseControllerOptions, B as defineResource, Fn as BodySanitizerConfig, Mn as ControllerConstructionOptions, Nn as ListResult, Pn as BodySanitizer, Qt as TreeExt, V as ResourceDefinition, Xt as SoftDeleteExt, Yt as BaseController, Zt as SoftDeleteMixin, an as QueryResolver, cn as AccessControlConfig, ct as AggMeasureShorthand, dt as AggregationDateRangeRequirement, en as SlugExt, ft as AggregationIndexHint, gt as AggregationsMap, ht as AggregationRateLimit, in as BaseCrudController, jn as ControllerConfigurableOptions, lt as AggregationCacheConfig, mt as AggregationMaterializedResult, nn as BulkExt, on as QueryResolverConfig, pt as AggregationMaterializedContext, rn as BulkMixin, sn as AccessControl, st as AggMeasureInput, tn as SlugMixin, ut as AggregationConfig } from "../index-CpzxqePp.mjs";
|
|
3
|
+
import { A as DEFAULT_ID_FIELD, B as MAX_FILTER_DEPTH, C as DefineActionConfig, D as defineAggregation, E as createPermissionMiddleware, F as DEFAULT_UPDATE_METHOD, G as RESERVED_QUERY_PARAMS, H as MAX_SEARCH_LENGTH, I as HOOK_OPERATIONS, K as SYSTEM_FIELDS, L as HOOK_PHASES, M as DEFAULT_MAX_LIMIT, N as DEFAULT_SORT, O as CRUD_OPERATIONS, P as DEFAULT_TENANT_FIELD, R as HookOperation, S as mergeResourceConfig, T as createCrudRouter, U as MUTATION_OPERATIONS, V as MAX_REGEX_LENGTH, W as MutationOperation, _ as getEntityQuery, a as formatValidationErrors, b as ResourceSeams, c as isFieldReadable, d as createRequestContext, f as getControllerContext, g as getEntityIdField, h as getEntityId, i as assertValidConfig, j as DEFAULT_LIMIT, k as CrudOperation, l as createCrudHandlers, m as sendControllerResponse, n as ValidateOptions, o as validateResourceConfig, p as getControllerScope, r as ValidationResult, s as collectReadBlockedFields, t as ConfigError, u as createFastifyHandler, v as defineResourceVariants, w as defineAction, x as SeamedResourceConfig, y as AdapterLike, z as HookPhase } from "../index-Bc2ox8_U.mjs";
|
|
3
4
|
export { AccessControl, type AccessControlConfig, type AdapterLike, type AggMeasureInput, type AggMeasureShorthand, type AggregationCacheConfig, type AggregationConfig, type AggregationDateRangeRequirement, type AggregationIndexHint, type AggregationMaterializedContext, type AggregationMaterializedResult, type AggregationRateLimit, type AggregationsMap, BaseController, type BaseControllerOptions, BaseCrudController, BodySanitizer, type BodySanitizerConfig, type BulkExt, BulkMixin, CRUD_OPERATIONS, type ConfigError, type ControllerConfigurableOptions, type ControllerConstructionOptions, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DefineActionConfig, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, type ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, type QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, type ResourceSeams, SYSTEM_FIELDS, type SeamedResourceConfig, type SlugExt, SlugMixin, type SoftDeleteExt, SoftDeleteMixin, type TreeExt, TreeMixin, type ValidateOptions, type ValidationResult, assertValidConfig, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, formatValidationErrors, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, mergeResourceConfig, sendControllerResponse, validateResourceConfig };
|