@classytic/arc 2.30.0 → 2.32.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-B5DwufbB.mjs → BaseController-Dk34dxhI.mjs} +21 -19
- package/dist/{EventTransport-QmY7A258.d.mts → EventTransport-2uVV34WU.d.mts} +1 -0
- package/dist/{EventTransport-C6YA8xY9.mjs → EventTransport-BV10D0oG.mjs} +1 -0
- package/dist/{HookSystem-WkIougo6.mjs → HookSystem-vimw5D7Z.mjs} +2 -1
- package/dist/{QueryCache-DOMT_iq7.d.mts → QueryCache-DFA-QrU9.d.mts} +2 -1
- package/dist/{ResourceRegistry-y9Hnypus.mjs → ResourceRegistry-BVr7PgA0.mjs} +18 -15
- package/dist/{actionPermissions-CAphcmUG.mjs → actionPermissions-Dti7ebyv.mjs} +1 -0
- package/dist/audit/index.d.mts +3 -2
- package/dist/audit/index.mjs +2 -1
- 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 +11 -9
- package/dist/auth/redis-session.d.mts +2 -1
- package/dist/auth/redis-session.mjs +1 -0
- package/dist/{applyPermissionResult-Cf6zUCvb.mjs → authorizationDecision-__T3EJDA.mjs} +19 -10
- package/dist/{buildHandler-BYS3Vkfz.mjs → buildHandler-Dn7rzUJo.mjs} +6 -4
- package/dist/cache/index.d.mts +4 -3
- package/dist/cache/index.mjs +4 -3
- package/dist/{caching-_NJeDd1_.mjs → caching-DFJqHyFs.mjs} +2 -1
- package/dist/cleanup/index.d.mts +39 -16
- package/dist/cleanup/index.mjs +50 -38
- package/dist/cli/commands/describe.d.mts +2 -1
- package/dist/cli/commands/describe.mjs +4 -5
- 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-J99LGTJI.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 -6
- package/dist/{core-poalJLvp.mjs → core-BwwmNSp7.mjs} +3 -2
- package/dist/{createActionRouter-BxuywVRB.mjs → createActionRouter-DkJZWo0m.mjs} +14 -10
- package/dist/{createAggregationRouter-BiY-lGdY.mjs → createAggregationRouter-B1exOVD8.mjs} +10 -7
- package/dist/{createApp-CXrKFciH.mjs → createApp-Bv0m-Q6_.mjs} +625 -229
- package/dist/{defineAggregation-ufWjUwml.mjs → defineAggregation-gX4No1gt.mjs} +1 -0
- package/dist/{defineResource-CxWqDCAy.mjs → defineResource-XFPPUu2c.mjs} +84 -50
- 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-DNXXxgjl.mjs} +4 -3
- package/dist/encryption/index.d.mts +2 -1
- package/dist/encryption/index.mjs +5 -3
- package/dist/{errorHandler-Bq2OeEQL.mjs → errorHandler-B2AZUJUj.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-Bh1KK5ps.mjs} +1 -0
- package/dist/{eventPlugin-D2NNR4py.mjs → eventPlugin-Dk_TyXeE.mjs} +8 -6
- package/dist/{eventPlugin-Bg3cP2_u.d.mts → eventPlugin-GF5nnBIq.d.mts} +2 -1
- package/dist/events/index.d.mts +112 -44
- package/dist/events/index.mjs +177 -141
- package/dist/events/transports/redis-stream-entry.d.mts +2 -1
- package/dist/events/transports/redis-stream-entry.mjs +14 -9
- 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 +131 -7
- package/dist/fastify-augmentation-BppG5bMT.d.mts +179 -0
- package/dist/{fields-CQ_7KQWw.mjs → fields-DEi65pGj.mjs} +6 -10
- package/dist/{fields-D3lhgzhD.d.mts → fields-I_EeRWND.d.mts} +1 -0
- package/dist/{generate-D0wZupBg.mjs → generate-CRSG0jTv.mjs} +2 -1
- package/dist/{generate-BnsL9GBm.d.mts → generate-DCGuEbqI.d.mts} +1 -0
- package/dist/{headers-BvlQSDMB.mjs → headers-BXjQYbeC.mjs} +2 -1
- package/dist/{health-CB_m4S32.mjs → health-5XnTa2uo.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 +8 -5
- package/dist/idempotency/redis.d.mts +2 -1
- package/dist/idempotency/redis.mjs +1 -0
- package/dist/{index-CG4yqMDB.d.mts → index-C-481Zf2.d.mts} +74 -18
- package/dist/{index-Q5gzEIWY.d.mts → index-CpzxqePp.d.mts} +107 -32
- package/dist/{index-Cx7bro4R.d.mts → index-DXlHwvuE.d.mts} +5 -4
- package/dist/index-ZWhLTp_s.d.mts +290 -0
- package/dist/{index-Ch16aAah.d.mts → index-zq6VrjaB.d.mts} +122 -15
- package/dist/index.d.mts +9 -8
- package/dist/index.mjs +11 -10
- package/dist/{init-tlRSt667.mjs → init-BbfP8aky.mjs} +25 -27
- 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 +109 -33
- package/dist/integrations/mcp/index.d.mts +6 -6
- 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 +38 -34
- package/dist/{interface-BGZCzOGL.d.mts → interface-BOk3YnTz.d.mts} +1 -0
- package/dist/{interface-n5hpKg1d.mjs → interface-BP4IJCBO.mjs} +1 -0
- package/dist/{interface-Uk8ONJv7.d.mts → interface-DEWNOMza.d.mts} +1 -0
- package/dist/{jsonBody-BlzAoGCe.mjs → jsonBody-DDSR2HFl.mjs} +2 -1
- package/dist/{keys-Cd316u_y.mjs → keys-B-HBTGXl.mjs} +1 -0
- package/dist/{loadResources-DpU8pfjV.mjs → loadResources-DisEAmkm.mjs} +4 -2
- package/dist/{loadResourcesFromEntry-kvGT6EcO.mjs → loadResourcesFromEntry-D1MJp13f.mjs} +2 -1
- package/dist/logger/index.d.mts +1 -0
- package/dist/logger/index.mjs +1 -0
- package/dist/{mcpPlugin-nRzm5g2s.mjs → mcpPlugin-CpfVpKHE.mjs} +38 -38
- package/dist/{memory-CmnzXE5Z.mjs → memory-DsuWnj4T.mjs} +5 -4
- package/dist/{metrics-fdxI5mn_.mjs → metrics-DdQL8syd.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 -0
- package/dist/migrations/index.mjs +3 -2
- package/dist/module-Br81am6m.mjs +78 -0
- package/dist/{multipartBody-D0eBvkeq.mjs → multipartBody-BnkBLN7v.mjs} +3 -2
- package/dist/{openapi-B8Vkbxbn.mjs → openapi-DIRzvxC0.mjs} +6 -5
- package/dist/outbox-admin/index.d.mts +85 -0
- package/dist/outbox-admin/index.mjs +115 -0
- package/dist/permissions/index.d.mts +5 -4
- package/dist/permissions/index.mjs +6 -5
- package/dist/{permissions-Bfu_8y1U.mjs → permissions-Dl_m0NCe.mjs} +308 -42
- package/dist/{pipe-BOLmGIxa.mjs → pipe-ELHCP3zj.mjs} +3 -4
- package/dist/pipeline/index.d.mts +2 -1
- package/dist/pipeline/index.mjs +2 -1
- package/dist/{pipeline-BJnpkY9i.mjs → pipeline-CPA-jx0M.mjs} +17 -14
- 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-C2ZkKbsn.mjs} +1 -0
- package/dist/{preloadResources-DSY5HGpS.mjs → preloadResources-CDs87fTw.mjs} +1 -0
- package/dist/{preloadResources-DCfa2egz.d.mts → preloadResources-T1hmlTEZ.d.mts} +117 -12
- package/dist/presets/filesUpload.d.mts +6 -5
- package/dist/presets/filesUpload.mjs +10 -12
- package/dist/presets/index.d.mts +3 -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-CJOEXLuk.mjs → presets-Dntd_pUO.mjs} +6 -4
- package/dist/{projection-UBDgfMwu.mjs → projection-CjHhM5W1.mjs} +2 -1
- package/dist/{pushref-registry-BbcnpNTm.d.mts → pushref-registry-Dov9l4qE.d.mts} +1 -0
- package/dist/{queryCachePlugin-br4otiqF.d.mts → queryCachePlugin-BzqxconG.d.mts} +3 -2
- package/dist/{queryCachePlugin-DSGuSVLW.mjs → queryCachePlugin-Dhps-Ldt.mjs} +6 -5
- package/dist/{rateLimit-DrED-C4v.mjs → rateLimit-C7mmAGs3.mjs} +7 -3
- package/dist/{rateLimitKey-BoWRH3e7.mjs → rateLimitKey-CccEFBfk.mjs} +1 -0
- package/dist/{realtime-B9nmIY5V.mjs → realtime-DVvVZZFz.mjs} +20 -9
- 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-JkxIEBJq.mjs → registerRoute-B_QrjYZS.mjs} +10 -7
- package/dist/registry/index.d.mts +3 -2
- package/dist/registry/index.mjs +3 -2
- package/dist/{registry-BYXUUg21.mjs → registry-DqUmzA9W.mjs} +2 -1
- package/dist/{renewingLease-3cuQH7h8.mjs → renewingLease-BpP9wwj7.mjs} +1 -0
- package/dist/{replyHelpers-67tRawQZ.mjs → replyHelpers-DS-P0b32.mjs} +2 -1
- package/dist/{repositoryFilter-Dz8k3S4P.mjs → repositoryFilter-DotlxG3L.mjs} +1 -0
- package/dist/{requestContext-MrlJwECf.mjs → requestContext-B6vQF-sy.mjs} +1 -0
- package/dist/{rolldown-runtime-8H4AJuhK.mjs → rolldown-runtime-BhflRrBs.mjs} +1 -0
- package/dist/{schedules-CjOd2MG9.mjs → schedules-C2Q3uv2d.mjs} +3 -2
- package/dist/{schemaConverter-DJvodiHj.mjs → schemaConverter-Crjvczi_.mjs} +70 -17
- package/dist/{schemaIR-Ca7ySNPx.mjs → schemaIR-CnyKK_1j.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-afz_Ieek.mjs} +4 -3
- package/dist/{sessionManager-BHOM3N_0.d.mts → sessionManager-qimlKV0P.d.mts} +1 -0
- package/dist/{simpleEqualityMatcher-Cg05HPsn.mjs → simpleEqualityMatcher-C4KiMWUa.mjs} +1 -0
- package/dist/{sse-BQ1w0dfl.mjs → sse-B9P4Y-UI.mjs} +7 -5
- package/dist/{sseStream-BQ7Qaynp.mjs → sseStream-B3zb_d1h.mjs} +2 -1
- package/dist/{storage-DLUZ04kK.d.mts → storage-Cx9Sz3Ou.d.mts} +1 -0
- package/dist/{store-helpers-DY6xq4sM.mjs → store-helpers-DmEMHlPQ.mjs} +1 -0
- package/dist/{streaming-BQcW6_Kq.mjs → streaming-DPZdQmDz.mjs} +1 -0
- package/dist/{subscribe-helpers-DfzsivM6.mjs → subscribe-helpers-sp5xTDVA.mjs} +2 -1
- 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 +10 -5
- package/dist/testing/index.d.mts +166 -12
- package/dist/testing/index.mjs +315 -43
- package/dist/testing/outboxStoreContract.d.mts +12 -2
- package/dist/testing/outboxStoreContract.mjs +110 -20
- package/dist/testing/storageContract.d.mts +2 -1
- package/dist/testing/storageContract.mjs +11 -5
- package/dist/{tracing-CsGKQJGg.d.mts → tracing-Dro5eH6j.d.mts} +1 -0
- package/dist/{transactionContext-PNdoyLLm.mjs → transactionContext-BvLKvOIL.mjs} +1 -0
- package/dist/{typeGuards-C9KXUly6.mjs → typeGuards-B_5-hKjJ.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-ChvvVNP8.d.mts → types-B7XeLEgK.d.mts} +34 -2
- 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-D_n8L6VY.d.mts → types-CT5vu6M0.d.mts} +132 -17
- package/dist/{types-DjC-KUCz.d.mts → types-ChuShpCP.d.mts} +1 -0
- package/dist/{types-Bmmn-fO0.d.mts → types-CwcUQ610.d.mts} +2 -6
- package/dist/{types-CSyCxl2V.mjs → types-DXYX7dIR.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-BNsOXzOd.mjs} +1 -0
- package/dist/utils/index.d.mts +16 -7
- package/dist/utils/index.mjs +10 -9
- package/dist/{utils-taUVD4p3.mjs → utils-BtOha_Sp.mjs} +3 -2
- package/dist/{validate-Bk44F2yT.mjs → validate-PMCPR9El.mjs} +2 -1
- package/dist/{versioning-gKWyryT3.mjs → versioning-CKv2jz_U.mjs} +4 -3
- 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 +557 -539
- 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/fastify-augmentation-0WhPnUH7.d.mts +0 -76
- package/dist/index-CCzVR-N3.d.mts +0 -107
- package/dist/module-_-M7C5ES.mjs +0 -29
|
@@ -1,18 +1,19 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { t as
|
|
8
|
-
import { t as
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { n as
|
|
12
|
-
import {
|
|
13
|
-
import { t as
|
|
14
|
-
import { t as
|
|
15
|
-
import {
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { r as evaluatePermissionDecision } from "./authorizationDecision-__T3EJDA.mjs";
|
|
3
|
+
import { p as isArcError, t as ArcError } from "./errors-Bh1KK5ps.mjs";
|
|
4
|
+
import { n as requireSingleHeaderValue } from "./headers-BXjQYbeC.mjs";
|
|
5
|
+
import { b as isElevated, c as getOrgId, g as getUserId, x as isMember } from "./types-DXYX7dIR.mjs";
|
|
6
|
+
import { t as BaseController } from "./BaseController-Dk34dxhI.mjs";
|
|
7
|
+
import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-DEi65pGj.mjs";
|
|
8
|
+
import { t as executePipeline } from "./pipe-ELHCP3zj.mjs";
|
|
9
|
+
import { t as buildRequestScopeProjection } from "./projection-CjHhM5W1.mjs";
|
|
10
|
+
import { r as resolvePipelineSteps } from "./pipeline-CPA-jx0M.mjs";
|
|
11
|
+
import { n as validateAggregations } from "./validate-PMCPR9El.mjs";
|
|
12
|
+
import { n as executeAggregation } from "./buildHandler-Dn7rzUJo.mjs";
|
|
13
|
+
import { t as pluralize } from "./pluralize-C2ZkKbsn.mjs";
|
|
14
|
+
import { t as resolveActionPermission } from "./actionPermissions-Dti7ebyv.mjs";
|
|
15
|
+
import { t as createIdempotencyResult } from "./interface-BP4IJCBO.mjs";
|
|
16
|
+
import { r as shouldRejectAdditionalProperties, t as normalizeSchemaIR } from "./schemaIR-CnyKK_1j.mjs";
|
|
16
17
|
import { isHttpError, toErrorContract } from "@classytic/repo-core/errors";
|
|
17
18
|
import { createHash, randomUUID } from "node:crypto";
|
|
18
19
|
import fp from "fastify-plugin";
|
|
@@ -366,12 +367,13 @@ function buildScope(auth) {
|
|
|
366
367
|
*/
|
|
367
368
|
async function evaluatePermission(check, session, resource, action, input) {
|
|
368
369
|
if (!check) return null;
|
|
370
|
+
const user = session ? {
|
|
371
|
+
id: session.userId,
|
|
372
|
+
_id: session.userId,
|
|
373
|
+
...session
|
|
374
|
+
} : null;
|
|
369
375
|
return evaluatePermissionDecision(check, {
|
|
370
|
-
user
|
|
371
|
-
id: session.userId,
|
|
372
|
-
_id: session.userId,
|
|
373
|
-
...session
|
|
374
|
-
} : null,
|
|
376
|
+
user,
|
|
375
377
|
scope: buildScope(session),
|
|
376
378
|
resource,
|
|
377
379
|
action,
|
|
@@ -464,13 +466,14 @@ function toCallToolSuccess(value) {
|
|
|
464
466
|
*/
|
|
465
467
|
function toCallToolError(input) {
|
|
466
468
|
let contract;
|
|
467
|
-
if (input instanceof Error)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
469
|
+
if (input instanceof Error) {
|
|
470
|
+
if (isArcError(input) || isHttpError(input)) contract = toErrorContract(input);
|
|
471
|
+
else contract = {
|
|
472
|
+
code: "arc.internal_error",
|
|
473
|
+
message: input.message || "Internal Server Error",
|
|
474
|
+
status: 500
|
|
475
|
+
};
|
|
476
|
+
} else contract = {
|
|
474
477
|
code: input.code,
|
|
475
478
|
message: input.message,
|
|
476
479
|
...input.status !== void 0 ? { status: input.status } : {},
|
|
@@ -587,7 +590,7 @@ function invocationFingerprint(resourceName, actionName, input, session) {
|
|
|
587
590
|
return `mcp:${resourceName}:${actionName}:${createHash("sha256").update(JSON.stringify(sortKeys(input))).digest("hex").substring(0, 16)}:u=${session?.userId ?? session?.clientId ?? "anon"}`;
|
|
588
591
|
}
|
|
589
592
|
/** TTLs matching the HTTP idempotency plugin's defaults. */
|
|
590
|
-
const MCP_IDEMPOTENCY_TTL_MS =
|
|
593
|
+
const MCP_IDEMPOTENCY_TTL_MS = 864e5;
|
|
591
594
|
const MCP_IDEMPOTENCY_LOCK_MS = 1e4;
|
|
592
595
|
/**
|
|
593
596
|
* Invoke a controller method through the MCP synthetic-context path.
|
|
@@ -1433,7 +1436,6 @@ function jsonSchemaPropertyToZod(prop) {
|
|
|
1433
1436
|
case "array": return applyDescription(arrayToZod(prop), prop);
|
|
1434
1437
|
case "object": return applyDescription(objectToZod(prop), prop);
|
|
1435
1438
|
case "null": continue;
|
|
1436
|
-
default: break;
|
|
1437
1439
|
}
|
|
1438
1440
|
return applyDescription(z.unknown(), prop);
|
|
1439
1441
|
}
|
|
@@ -1634,7 +1636,7 @@ function mapJsonSchemaTypeToArcType(jsonType) {
|
|
|
1634
1636
|
*
|
|
1635
1637
|
* 1. `mcpHandler` (full bypass) — caller-supplied function owns the whole
|
|
1636
1638
|
* tool result; pipeline is not invoked.
|
|
1637
|
-
* 2. Function handler
|
|
1639
|
+
* 2. Function in `handler` (the arc pipeline) — arc's pipeline wrapper
|
|
1638
1640
|
* runs normally, and the envelope is serialized into the tool result.
|
|
1639
1641
|
* 3. String handler — looks up a method on the controller by name.
|
|
1640
1642
|
*/
|
|
@@ -1872,10 +1874,10 @@ function resourceToTools(resource, config = {}) {
|
|
|
1872
1874
|
for (const route of resource.routes ?? []) {
|
|
1873
1875
|
if (route.mcp === false) continue;
|
|
1874
1876
|
const mcpHandler = route.mcpHandler;
|
|
1875
|
-
if (
|
|
1877
|
+
if (!(route.rawHandler === void 0) && !mcpHandler) continue;
|
|
1876
1878
|
if (!mcpHandler && typeof route.handler === "string" && !controller) continue;
|
|
1877
1879
|
const routeWithRef = route;
|
|
1878
|
-
let resolvedRouteHandler = route.handler;
|
|
1880
|
+
let resolvedRouteHandler = route.handler ?? route.rawHandler;
|
|
1879
1881
|
if (typeof routeWithRef.controllerMethod === "function" && !resolvedRouteHandler) {
|
|
1880
1882
|
if (!controller) continue;
|
|
1881
1883
|
const referenced = routeWithRef.controllerMethod(controller);
|
|
@@ -2060,7 +2062,7 @@ function getOps(r, override) {
|
|
|
2060
2062
|
}
|
|
2061
2063
|
//#endregion
|
|
2062
2064
|
//#region src/integrations/mcp/sessionCache.ts
|
|
2063
|
-
const DEFAULT_TTL_MS =
|
|
2065
|
+
const DEFAULT_TTL_MS = 18e5;
|
|
2064
2066
|
const DEFAULT_MAX_SESSIONS = 1e3;
|
|
2065
2067
|
var McpSessionCache = class {
|
|
2066
2068
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -2190,7 +2192,6 @@ const mcpPluginImpl = async (fastify, options) => {
|
|
|
2190
2192
|
}
|
|
2191
2193
|
const enabledResources = filterResourcesForMcp(options.resources, {
|
|
2192
2194
|
expose: options.expose,
|
|
2193
|
-
include: options.include,
|
|
2194
2195
|
exclude: options.exclude
|
|
2195
2196
|
});
|
|
2196
2197
|
const fastifyAny = fastify;
|
|
@@ -2465,11 +2466,10 @@ function registerStatefulRoutes(fastify, prefix, options, cache, createServer, T
|
|
|
2465
2466
|
* same precedence rules without duplicating them.
|
|
2466
2467
|
*/
|
|
2467
2468
|
function filterResourcesForMcp(resources, inputs) {
|
|
2468
|
-
const { expose,
|
|
2469
|
-
if (expose &&
|
|
2470
|
-
if (expose && exclude) throw new Error("mcpPlugin: `expose` is default-deny — `exclude` is redundant. Drop `exclude` or switch to `include`/`exclude` for default-allow semantics.");
|
|
2469
|
+
const { expose, exclude } = inputs;
|
|
2470
|
+
if (expose && exclude) throw new Error("mcpPlugin: `expose` is default-deny (an allowlist) — `exclude` is redundant alongside it. Use `expose` to name what to surface, OR `exclude` to drop specific resources from the default-allow set. Not both.");
|
|
2471
2471
|
const eligible = resources.filter((r) => r.mcp !== false);
|
|
2472
|
-
const allow = expose
|
|
2472
|
+
const allow = expose;
|
|
2473
2473
|
if (allow) {
|
|
2474
2474
|
const allowSet = new Set(allow);
|
|
2475
2475
|
return eligible.filter((r) => allowSet.has(r.name));
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
|
|
2
3
|
//#region src/cache/memory.ts
|
|
3
4
|
var memory_exports = /* @__PURE__ */ __exportAll({ MemoryCacheStore: () => MemoryCacheStore });
|
|
4
5
|
/**
|
|
@@ -25,11 +26,11 @@ var MemoryCacheStore = class {
|
|
|
25
26
|
constructor(options = {}) {
|
|
26
27
|
this.defaultTtlSeconds = options.defaultTtlSeconds ?? 60;
|
|
27
28
|
this.maxEntries = clamp(options.maxEntries ?? 1e3, 1, 1e5);
|
|
28
|
-
this.maxEntryBytes = clamp(options.maxEntryBytes ??
|
|
29
|
-
this.maxMemoryBytes = options.maxMemoryBytes ??
|
|
29
|
+
this.maxEntryBytes = clamp(options.maxEntryBytes ?? 262144, 1024, 10485760);
|
|
30
|
+
this.maxMemoryBytes = options.maxMemoryBytes ?? 52428800;
|
|
30
31
|
this.evictionWatermark = clamp(options.evictionWatermark ?? .9, .5, 1);
|
|
31
32
|
this.logger = options.logger ?? console;
|
|
32
|
-
const cleanupIntervalMs = clamp(options.cleanupIntervalMs ?? 3e4, 1e3,
|
|
33
|
+
const cleanupIntervalMs = clamp(options.cleanupIntervalMs ?? 3e4, 1e3, 6e5);
|
|
33
34
|
this.cleanupTimer = setInterval(() => this.cleanupExpired(), cleanupIntervalMs);
|
|
34
35
|
if (this.cleanupTimer.unref) this.cleanupTimer.unref();
|
|
35
36
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-BhflRrBs.mjs";
|
|
2
3
|
import fp from "fastify-plugin";
|
|
3
4
|
//#region src/plugins/metrics.ts
|
|
4
5
|
var metrics_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
|
+
import { I as MiddlewareHandler, L as RequestWithExtras, Q as MiddlewareConfig } from "../index-CpzxqePp.mjs";
|
|
2
3
|
import { RouteHandlerMethod } from "fastify";
|
|
3
4
|
//#region src/middleware/middleware.d.ts
|
|
4
5
|
interface NamedMiddleware {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as CRUD_OPERATIONS } from "../constants-J99LGTJI.mjs";
|
|
3
|
+
import { t as multipartBody } from "../multipartBody-BnkBLN7v.mjs";
|
|
3
4
|
//#region src/middleware/middleware.ts
|
|
4
5
|
/**
|
|
5
6
|
* Named Middleware — Priority-based, conditional middleware execution.
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as startRenewingLease } from "../renewingLease-BpP9wwj7.mjs";
|
|
2
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
3
4
|
//#region src/migrations/index.ts
|
|
4
5
|
/**
|
|
@@ -87,7 +88,7 @@ var MongoMigrationStore = class {
|
|
|
87
88
|
}
|
|
88
89
|
};
|
|
89
90
|
const MIGRATION_LOCK_NAME = "arc:migrations";
|
|
90
|
-
const DEFAULT_LOCK_LEASE_MS =
|
|
91
|
+
const DEFAULT_LOCK_LEASE_MS = 6e5;
|
|
91
92
|
/**
|
|
92
93
|
* Source checksum for drift detection — SHA-256 over the migration's
|
|
93
94
|
* `up`/`down` source. Stable for a given build; a transpile-target change
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
//#region src/factory/module/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Identity helper for authoring a typed module — mirrors `defineResource`.
|
|
5
|
+
* Gives inference + a single obvious construction site; does no work.
|
|
6
|
+
*
|
|
7
|
+
* `TExports` is inferred from the `bootstrap` return value, so a module
|
|
8
|
+
* author gets a typed public export for free:
|
|
9
|
+
*
|
|
10
|
+
* ```ts
|
|
11
|
+
* export const accountingModule = (deps: Deps) =>
|
|
12
|
+
* defineModule({
|
|
13
|
+
* name: "accounting",
|
|
14
|
+
* bootstrap: async () => createAccountingEngine(deps), // TExports inferred
|
|
15
|
+
* });
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
function defineModule(module) {
|
|
19
|
+
return module;
|
|
20
|
+
}
|
|
21
|
+
function getModuleExports(fastify, name) {
|
|
22
|
+
const recorded = readModuleExports(fastify, name);
|
|
23
|
+
if (recorded === ABSENT) {
|
|
24
|
+
const available = fastify.arc?.modules ? Object.keys(fastify.arc.modules) : [];
|
|
25
|
+
throw new Error(`[arc] no public export recorded for module "${name}".\nA module's export is its bootstrap() return value; it is readable only AFTER that module's bootstrap ran (dependsOn / list order = init order).\nModules with recorded exports: ${available.length ? available.join(", ") : "(none)"}.`);
|
|
26
|
+
}
|
|
27
|
+
return recorded;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Sentinel for "no entry recorded", distinct from a recorded `undefined`.
|
|
31
|
+
*
|
|
32
|
+
* registerResources never records an `undefined` export, so today the two
|
|
33
|
+
* cannot both happen — but encoding absence as `undefined` would make the
|
|
34
|
+
* optional/required accessors disagree the day that changes, and a required
|
|
35
|
+
* accessor that stops throwing is exactly the silent-null class of bug these
|
|
36
|
+
* helpers exist to remove.
|
|
37
|
+
*/
|
|
38
|
+
const ABSENT = Symbol("arc.module.absent");
|
|
39
|
+
/** The one honest read of the module-export map, shared by every accessor. */
|
|
40
|
+
function readModuleExports(fastify, name) {
|
|
41
|
+
const modules = fastify.arc?.modules;
|
|
42
|
+
if (!modules || !Object.hasOwn(modules, name)) return ABSENT;
|
|
43
|
+
return modules[name];
|
|
44
|
+
}
|
|
45
|
+
function getOptionalModuleExports(fastify, name) {
|
|
46
|
+
const recorded = readModuleExports(fastify, name);
|
|
47
|
+
return recorded === ABSENT ? void 0 : recorded;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Is a module's public export recorded yet? The predicate form of
|
|
51
|
+
* `getOptionalModuleExports`, for readiness gates (`ready: () => ...`) that
|
|
52
|
+
* should not have to reason about falsy-but-present exports.
|
|
53
|
+
*/
|
|
54
|
+
function hasModuleExports(fastify, name) {
|
|
55
|
+
return readModuleExports(fastify, name) !== ABSENT;
|
|
56
|
+
}
|
|
57
|
+
function lazyModuleExports(fastify, name) {
|
|
58
|
+
let resolved = ABSENT;
|
|
59
|
+
return () => {
|
|
60
|
+
if (resolved === ABSENT) resolved = readModuleExports(fastify, name);
|
|
61
|
+
return resolved === ABSENT ? void 0 : resolved;
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function lazyRequiredModuleExports(fastify, name) {
|
|
65
|
+
const states = fastify.arc?.moduleStates;
|
|
66
|
+
if (states !== void 0 && !Object.hasOwn(states, name)) {
|
|
67
|
+
const composed = Object.keys(states);
|
|
68
|
+
throw new Error(`[arc] lazyRequiredModuleExports("${name}"): module "${name}" is not in the composed module graph. A lazily-required module is still a HARD dependency — compose it (and declare it in the consumer's \`dependsOn\`), or use lazyModuleExports() if the integration is genuinely optional.
|
|
69
|
+
Composed modules: ${composed.length ? composed.join(", ") : "(none)"}.`);
|
|
70
|
+
}
|
|
71
|
+
let resolved = ABSENT;
|
|
72
|
+
return () => {
|
|
73
|
+
if (resolved === ABSENT) resolved = getModuleExports(fastify, name);
|
|
74
|
+
return resolved;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
//#endregion
|
|
78
|
+
export { lazyModuleExports as a, hasModuleExports as i, getModuleExports as n, lazyRequiredModuleExports as o, getOptionalModuleExports as r, defineModule as t };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
1
2
|
import sjson from "secure-json-parse";
|
|
2
3
|
//#region src/middleware/multipartBody.ts
|
|
3
|
-
const DEFAULT_MAX_FILE_SIZE =
|
|
4
|
+
const DEFAULT_MAX_FILE_SIZE = 10485760;
|
|
4
5
|
const DEFAULT_MAX_FILES = 5;
|
|
5
|
-
const DEFAULT_MAX_TOTAL_BYTES =
|
|
6
|
+
const DEFAULT_MAX_TOTAL_BYTES = 26214400;
|
|
6
7
|
const DEFAULT_FILES_KEY = "_files";
|
|
7
8
|
/**
|
|
8
9
|
* Build a matcher for MIME allow-lists that supports exact (e.g. `image/png`),
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import { n as
|
|
3
|
-
import {
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as getUserRoles } from "./userHelpers-BNsOXzOd.mjs";
|
|
3
|
+
import { n as convertRouteSchema } from "./schemaConverter-Crjvczi_.mjs";
|
|
4
|
+
import { t as pluralize } from "./pluralize-C2ZkKbsn.mjs";
|
|
5
|
+
import { t as resolveActionPermission } from "./actionPermissions-Dti7ebyv.mjs";
|
|
6
|
+
import { t as buildActionBodySchema } from "./createActionRouter-DkJZWo0m.mjs";
|
|
6
7
|
import fp from "fastify-plugin";
|
|
7
8
|
//#region src/docs/openapi/canonical-schemas.ts
|
|
8
9
|
/**
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
|
|
2
|
+
import { r as PermissionCheck } from "../types-B7XeLEgK.mjs";
|
|
3
|
+
import { t as ArcModule } from "../types-CT5vu6M0.mjs";
|
|
4
|
+
import { OutboxStore } from "@classytic/primitives/outbox";
|
|
5
|
+
//#region src/outbox-admin/module.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A store that can answer an operator's questions.
|
|
8
|
+
*
|
|
9
|
+
* Only the four reads this surface actually performs are required — `fail` and
|
|
10
|
+
* `purge` belong to the relay and retention, not here.
|
|
11
|
+
*/
|
|
12
|
+
type OutboxAdminStore = OutboxStore & Required<Pick<OutboxStore, "getDeadLettered" | "requeue" | "countByStatus" | "oldestPendingAgeMs">>;
|
|
13
|
+
interface OutboxAdminPermissions {
|
|
14
|
+
/**
|
|
15
|
+
* Reading health and the dead-letter list.
|
|
16
|
+
*
|
|
17
|
+
* MUST be platform-only — see `allowUnverifiedOperatorPermission`.
|
|
18
|
+
*/
|
|
19
|
+
view: PermissionCheck;
|
|
20
|
+
/**
|
|
21
|
+
* Replaying a dead-lettered event. Defaults to `view` when omitted — but
|
|
22
|
+
* replay RE-DELIVERS an event that already failed five times, so a
|
|
23
|
+
* deployment that separates read access from operational action should gate
|
|
24
|
+
* it distinctly. Also platform-only.
|
|
25
|
+
*/
|
|
26
|
+
replay?: PermissionCheck;
|
|
27
|
+
}
|
|
28
|
+
interface OutboxAdminModuleDeps {
|
|
29
|
+
store: OutboxAdminStore;
|
|
30
|
+
permissions: OutboxAdminPermissions;
|
|
31
|
+
/** Route prefix. Default `/admin/outbox`. */
|
|
32
|
+
prefix?: string;
|
|
33
|
+
/** Module name. Default `outbox-admin`. */
|
|
34
|
+
moduleName?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Name the outbox module was composed under, used to resolve the relay and
|
|
37
|
+
* declared as a `dependsOn` edge. Default `outbox`.
|
|
38
|
+
*/
|
|
39
|
+
outboxModuleName?: string;
|
|
40
|
+
/** Resource names this module supersedes. */
|
|
41
|
+
owns?: readonly string[];
|
|
42
|
+
/** Cap on `?limit`. Default 500 — a dead-letter list is for triage, not export. */
|
|
43
|
+
maxDeadLetterLimit?: number;
|
|
44
|
+
/**
|
|
45
|
+
* Accept gates arc cannot prove are platform-only.
|
|
46
|
+
*
|
|
47
|
+
* By default both gates must carry `_platformOnly` (i.e. come from
|
|
48
|
+
* `requirePlatformRole`), and boot FAILS otherwise. The reason is the same
|
|
49
|
+
* one that hardened `integrations/jobs` in 2.31: these routes are global by
|
|
50
|
+
* construction. `getDeadLettered(limit)` takes no filter and an outbox row
|
|
51
|
+
* carries no tenant identity, so there is nothing to scope by. A gate that
|
|
52
|
+
* grants per organization therefore READS as scoped while serving everyone —
|
|
53
|
+
* `requireOrgRole('manager')` would let org A's manager read org B's failed
|
|
54
|
+
* events. Neither returns a policy, so no per-request check can tell a real
|
|
55
|
+
* operator gate from an org one.
|
|
56
|
+
*
|
|
57
|
+
* Set this only for a custom check you have verified consults platform
|
|
58
|
+
* identity alone.
|
|
59
|
+
*/
|
|
60
|
+
allowUnverifiedOperatorPermission?: boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Include each dead-lettered event's domain PAYLOAD in the listing.
|
|
63
|
+
* Default `false`.
|
|
64
|
+
*
|
|
65
|
+
* The payload is the original event body — in an ERP that is order totals,
|
|
66
|
+
* customer records and payment references. Triage needs the id, the event
|
|
67
|
+
* name, the attempt count and why it failed; it does not need the contents.
|
|
68
|
+
* Opt in only where the surface is genuinely platform-operator-only and you
|
|
69
|
+
* accept that the response carries business data.
|
|
70
|
+
*/
|
|
71
|
+
exposePayload?: boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Include the failure STACK TRACE alongside the error message.
|
|
74
|
+
* Default `false` — a stack names internal paths and framework versions.
|
|
75
|
+
*/
|
|
76
|
+
exposeStack?: boolean;
|
|
77
|
+
/**
|
|
78
|
+
* Pending-event age (ms) past which the outbox reports unhealthy even with an
|
|
79
|
+
* empty dead-letter queue. Default 5 minutes.
|
|
80
|
+
*/
|
|
81
|
+
relayLagUnhealthyMs?: number;
|
|
82
|
+
}
|
|
83
|
+
declare function createOutboxAdminModule(deps: OutboxAdminModuleDeps): ArcModule<void>;
|
|
84
|
+
//#endregion
|
|
85
|
+
export { type OutboxAdminModuleDeps, type OutboxAdminPermissions, type OutboxAdminStore, createOutboxAdminModule };
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { i as NotFoundError, u as ValidationError } from "../errors-Bh1KK5ps.mjs";
|
|
3
|
+
import { t as defineResource } from "../defineResource-XFPPUu2c.mjs";
|
|
4
|
+
import { n as getModuleExports, t as defineModule } from "../module-Br81am6m.mjs";
|
|
5
|
+
//#region src/outbox-admin/module.ts
|
|
6
|
+
/**
|
|
7
|
+
* Strip the domain payload and the stack unless explicitly opted in.
|
|
8
|
+
*
|
|
9
|
+
* Triage is answered by WHICH event failed, HOW MANY times, WHEN and WHY. The
|
|
10
|
+
* payload answers none of those and carries the business record; the stack
|
|
11
|
+
* names internal paths. Both are off by default, on the same reasoning that
|
|
12
|
+
* made `exposeResult` / `exposeFailureReason` opt-in for jobs.
|
|
13
|
+
*/
|
|
14
|
+
function redactDeadLettered(e, opts) {
|
|
15
|
+
return {
|
|
16
|
+
event: {
|
|
17
|
+
type: e.event.type,
|
|
18
|
+
meta: e.event.meta,
|
|
19
|
+
...opts.exposePayload ? { payload: e.event.payload } : {}
|
|
20
|
+
},
|
|
21
|
+
error: {
|
|
22
|
+
message: e.error.message,
|
|
23
|
+
...e.error.code !== void 0 ? { code: e.error.code } : {},
|
|
24
|
+
...opts.exposeStack && e.error.stack !== void 0 ? { stack: e.error.stack } : {}
|
|
25
|
+
},
|
|
26
|
+
attempts: e.attempts,
|
|
27
|
+
firstFailedAt: e.firstFailedAt,
|
|
28
|
+
lastFailedAt: e.lastFailedAt,
|
|
29
|
+
...e.handlerName !== void 0 ? { handlerName: e.handlerName } : {}
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function createOutboxAdminModule(deps) {
|
|
33
|
+
const moduleName = deps.moduleName ?? "outbox-admin";
|
|
34
|
+
const outboxModuleName = deps.outboxModuleName ?? "outbox";
|
|
35
|
+
const maxLimit = deps.maxDeadLetterLimit ?? 500;
|
|
36
|
+
const view = deps.permissions.view;
|
|
37
|
+
const replay = deps.permissions.replay ?? deps.permissions.view;
|
|
38
|
+
const lagUnhealthyMs = deps.relayLagUnhealthyMs ?? 3e5;
|
|
39
|
+
if (!deps.allowUnverifiedOperatorPermission) {
|
|
40
|
+
for (const [label, gate] of [["view", view], ["replay", replay]]) if (!gate._platformOnly) throw new Error(`[arc/outbox-admin] permissions.${label} must be platform-only. These routes are global (an outbox row carries no tenant identity and getDeadLettered takes no filter), so an org-role gate would let a member of one organization read another's failed events and their payloads. Use requirePlatformRole('platform-ops') — or requireRoles([...], { includeOrgRoles: false }) with allowUnverifiedOperatorPermission: true if you have verified the check yourself.`);
|
|
41
|
+
}
|
|
42
|
+
const resource = defineResource({
|
|
43
|
+
name: moduleName,
|
|
44
|
+
displayName: "Outbox Admin",
|
|
45
|
+
tag: "Operations",
|
|
46
|
+
prefix: deps.prefix ?? "/admin/outbox",
|
|
47
|
+
customRoutesOnly: true,
|
|
48
|
+
routes: [
|
|
49
|
+
{
|
|
50
|
+
method: "GET",
|
|
51
|
+
path: "/health",
|
|
52
|
+
summary: "Outbox health — pending, dead-letter and relay lag",
|
|
53
|
+
permissions: view,
|
|
54
|
+
rawHandler: async (_req, reply) => {
|
|
55
|
+
const [pending, deadLetter, relayLagMs] = await Promise.all([
|
|
56
|
+
deps.store.countByStatus("pending"),
|
|
57
|
+
deps.store.countByStatus("dead_letter"),
|
|
58
|
+
deps.store.oldestPendingAgeMs()
|
|
59
|
+
]);
|
|
60
|
+
const healthy = deadLetter === 0 && (relayLagMs === null || relayLagMs < lagUnhealthyMs);
|
|
61
|
+
return reply.send({
|
|
62
|
+
pending,
|
|
63
|
+
deadLetter,
|
|
64
|
+
relayLagMs,
|
|
65
|
+
healthy
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
method: "GET",
|
|
71
|
+
path: "/dead-letter",
|
|
72
|
+
summary: "List dead-lettered events with their errors",
|
|
73
|
+
permissions: view,
|
|
74
|
+
rawHandler: async (req, reply) => {
|
|
75
|
+
const raw = req.query?.limit;
|
|
76
|
+
const parsed = Number(raw ?? 100);
|
|
77
|
+
const limit = Math.min(Math.max(Number.isFinite(parsed) ? parsed : 100, 1), maxLimit);
|
|
78
|
+
const events = await deps.store.getDeadLettered(limit);
|
|
79
|
+
return reply.send({
|
|
80
|
+
count: events.length,
|
|
81
|
+
limit,
|
|
82
|
+
events: events.map((e) => redactDeadLettered(e, deps))
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
method: "POST",
|
|
88
|
+
path: "/dead-letter/:id/replay",
|
|
89
|
+
summary: "Requeue a dead-lettered event and drain the relay",
|
|
90
|
+
permissions: replay,
|
|
91
|
+
rawHandler: async (req, reply) => {
|
|
92
|
+
const eventId = req.params?.id;
|
|
93
|
+
if (!eventId) throw new ValidationError("event id is required");
|
|
94
|
+
if (!await deps.store.requeue(eventId)) throw new NotFoundError(`Dead-lettered event "${eventId}" — not found, or not currently dead-lettered`);
|
|
95
|
+
const { relay } = getModuleExports(req.server, outboxModuleName);
|
|
96
|
+
const relayDelivered = await relay.relay();
|
|
97
|
+
return reply.send({
|
|
98
|
+
eventId,
|
|
99
|
+
requeued: true,
|
|
100
|
+
relayDelivered,
|
|
101
|
+
note: "relayDelivered counts the entire drained batch, not this event alone"
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
]
|
|
106
|
+
});
|
|
107
|
+
return defineModule({
|
|
108
|
+
name: moduleName,
|
|
109
|
+
dependsOn: [outboxModuleName],
|
|
110
|
+
...deps.owns ? { owns: [...deps.owns] } : {},
|
|
111
|
+
resources: () => [resource]
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
//#endregion
|
|
115
|
+
export { createOutboxAdminModule };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
import { a as
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
|
|
2
|
+
import { a as UserBase, c as normalizeRoles, i as PermissionContext, n as DataPolicy, r as PermissionCheck, s as getUserRoles, t as AuthorizationDecision } from "../types-B7XeLEgK.mjs";
|
|
3
|
+
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, r as FieldPermissionType, s as resolveEffectiveRoles, t as FieldPermission } from "../fields-I_EeRWND.mjs";
|
|
4
|
+
import { $ as requireAuth, A as RequireGrantOptions, B as ConnectEventsOptions, C as requireServiceScope, D as GRANT_MODES, E as createRoleHierarchy, F as PermissionRequirement, G as createOrgPermissions, H as DynamicPermissionMatrixConfig, I as collectPublicSurface, J as allowPublic, K as allOf, L as describePermission, M as requireGrant, N as conjoinPolicyFilters, O as GrantMode, P as AccessExplanation, Q as not, R as describePermissionMap, S as requireScopeContext, T as RoleHierarchy, U as PermissionEventBus, V as DynamicPermissionMatrix, W as createDynamicPermissionMatrix, X as deny, Y as anyOf, Z as denyAll, _ as publicReadAdminWrite, a as PermissionMatrixRegistry, at as scopeOf, b as requireOrgMembership, c as introspectModule, ct as evaluatePermissionDecision, d as authenticated, dt as RequireMandateOptions, et as requireOwnership, f as fullPublic, ft as requireAgentScope, g as publicRead, h as presets_d_exports, i as PermissionMatrixOptions, it as when, j as modeSatisfies, k as GrantResolution, l as introspectRegistry, lt as normalizeToDecision, m as permissionMatrix, mt as requireMandate, n as PermissionEntryType, nt as requireRoles, o as buildPermissionMatrix, ot as PermissionCheckReturn, p as ownerWithAdminBypass, pt as requireDPoP, q as allow, r as PermissionMatrix, rt as roles, s as introspectCheck, st as applyAuthorizationDecision, t as PermissionEntry, tt as requirePlatformRole, u as adminOnly, ut as RequireAgentScopeOptions, v as readOnly, w as requireTeamMembership, x as requireOrgRole, y as requireOrgInScope, z as explainAccess } from "../index-zq6VrjaB.mjs";
|
|
5
|
+
export { type AccessExplanation, type AuthorizationDecision, type ConnectEventsOptions, type DataPolicy, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type FieldPermission, type FieldPermissionMap, type FieldPermissionType, GRANT_MODES, type GrantMode, type GrantResolution, type PermissionCheck, type PermissionCheckReturn, type PermissionContext, type PermissionEntry, type PermissionEntryType, type PermissionEventBus, type PermissionMatrix, type PermissionMatrixOptions, type PermissionMatrixRegistry, type PermissionRequirement, type RequireAgentScopeOptions, type RequireGrantOptions, type RequireMandateOptions, type RoleHierarchy, type UserBase, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, buildPermissionMatrix, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, introspectCheck, introspectModule, introspectRegistry, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_d_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requirePlatformRole, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
import { a as
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
|
|
1
|
+
/*! @classytic/arc v2.32.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as conjoinPolicyFilters, i as normalizeToDecision, r as evaluatePermissionDecision, t as applyAuthorizationDecision } from "../authorizationDecision-__T3EJDA.mjs";
|
|
3
|
+
import { n as getUserRoles, r as normalizeRoles } from "../userHelpers-BNsOXzOd.mjs";
|
|
4
|
+
import { i as resolveEffectiveRoles, n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "../fields-DEi65pGj.mjs";
|
|
5
|
+
import { A as requireAgentScope, B as requireAuth, C as createOrgPermissions, D as requireScopeContext, E as requireOrgRole, F as allowPublic, G as when, H as requirePlatformRole, I as anyOf, K as scopeOf, L as deny, M as requireMandate, N as allOf, O as requireServiceScope, P as allow, R as denyAll, S as createDynamicPermissionMatrix, T as requireOrgMembership, U as requireRoles, V as requireOwnership, W as roles, _ as requireGrant, a as adminOnly, b as describePermissionMap, c as ownerWithAdminBypass, d as publicRead, f as publicReadAdminWrite, g as modeSatisfies, h as GRANT_MODES, i as introspectRegistry, j as requireDPoP, k as requireTeamMembership, l as permissionMatrix, m as createRoleHierarchy, n as introspectCheck, o as authenticated, p as readOnly, r as introspectModule, s as fullPublic, t as buildPermissionMatrix, u as presets_exports, v as collectPublicSurface, w as requireOrgInScope, x as explainAccess, y as describePermission, z as not } from "../permissions-Dl_m0NCe.mjs";
|
|
6
|
+
export { GRANT_MODES, adminOnly, allOf, allow, allowPublic, anyOf, applyAuthorizationDecision, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, buildPermissionMatrix, collectPublicSurface, conjoinPolicyFilters, createDynamicPermissionMatrix, createOrgPermissions, createRoleHierarchy, deny, denyAll, describePermission, describePermissionMap, evaluatePermissionDecision, explainAccess, fields, fullPublic, getUserRoles, introspectCheck, introspectModule, introspectRegistry, modeSatisfies, normalizeRoles, normalizeToDecision, not, ownerWithAdminBypass, permissionMatrix, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAgentScope, requireAuth, requireDPoP, requireGrant, requireMandate, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requirePlatformRole, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, resolveEffectiveRoles, roles, scopeOf, when };
|