@classytic/arc 2.34.0 → 2.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{BaseController-CbkuhNI2.mjs → BaseController-CTJKm6Cb.mjs} +95 -14
- package/dist/{EventTransport-tq4CEB-q.mjs → EventTransport-D23Uvhg4.mjs} +1 -1
- package/dist/{HookSystem-DqXkMXkB.mjs → HookSystem-DgwxNZTx.mjs} +6 -4
- package/dist/{ResourceRegistry-DoALUlOO.mjs → ResourceRegistry-DNuYVbmv.mjs} +2 -2
- package/dist/{pipeline-q69DZzgG.mjs → actionPermissions-D97DniUQ.mjs} +30 -7
- package/dist/audit/index.d.mts +2 -2
- package/dist/audit/index.mjs +2 -2
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +2 -2
- package/dist/auth/index.mjs +6 -6
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-CMMLWmuZ.mjs → authorizationDecision-EsiY3nUu.mjs} +2 -2
- package/dist/{base-Csjc2oF-.d.mts → base-C-NL2fTi.d.mts} +16 -1
- package/dist/{buildHandler-BrdYrG_1.mjs → buildHandler-Dohd2JuY.mjs} +4 -4
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-BcGmvnHh.mjs → caching-CP3GLJ7U.mjs} +2 -2
- package/dist/cleanup/index.d.mts +2 -2
- package/dist/cleanup/index.mjs +4 -4
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +3 -3
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -2
- package/dist/cli/commands/init.mjs +2 -2
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-BxCoxmiN.mjs → constants-DUoKAGYD.mjs} +1 -1
- package/dist/context/index.d.mts +16 -1
- package/dist/context/index.mjs +64 -4
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +7 -8
- package/dist/{core-BYKa8wHu.mjs → core-DTXsiNTJ.mjs} +3 -3
- package/dist/{createActionRouter-D6T0jWhS.mjs → createActionRouter-CZz6JO93.mjs} +27 -64
- package/dist/{createAggregationRouter-QLV2PrWP.mjs → createAggregationRouter-DKrGv_EC.mjs} +7 -7
- package/dist/defineAggregation-CpQfcM8R.mjs +25 -0
- package/dist/{defineResource-ZhuLonLm.mjs → defineResource-DWzjyxb2.mjs} +62 -66
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +3 -3
- package/dist/{elevation-B0tlY8y1.mjs → elevation-D_cmo80j.mjs} +4 -4
- package/dist/encryption/index.mjs +3 -3
- package/dist/{errorHandler-C7xBqHsI.mjs → errorHandler-2RT0hLSI.mjs} +3 -3
- package/dist/{errors-Cd_yy7aW.mjs → errors-DDKni6Tz.mjs} +1 -1
- package/dist/{eventPlugin-DSNEZWfV.d.mts → eventPlugin-B47sfCJ8.d.mts} +1 -1
- package/dist/{eventPlugin-Dar8qRaj.mjs → eventPlugin-c3YwGzz9.mjs} +5 -5
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +5 -5
- package/dist/events/transports/redis-stream-entry.mjs +1 -1
- package/dist/events/transports/redis.mjs +1 -1
- package/dist/factory/index.d.mts +5 -5
- package/dist/factory/index.mjs +5 -6
- package/dist/{fastify-augmentation-DVsTAy6X.d.mts → fastify-augmentation-Bk_9PoiV.d.mts} +3 -3
- package/dist/{fields-CojeUkS4.mjs → fields-DdP225wt.mjs} +1 -1
- package/dist/{generate-DiB0nHPR.mjs → generate-B1bKdcV9.mjs} +2 -2
- package/dist/{headers-CveNO9gR.mjs → headers-DKslnhey.mjs} +2 -2
- package/dist/{health-CasG2A28.mjs → health-k6NODS8f.mjs} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +2 -2
- package/dist/idempotency/index.mjs +22 -56
- package/dist/idempotency/redis.mjs +1 -1
- package/dist/{index-B-DvUzsr.d.mts → index-BtYoMip1.d.mts} +21 -3
- package/dist/{index-BcR2bFZQ.d.mts → index-C01wWGJt.d.mts} +33 -105
- package/dist/{index-C5NnMEKF.d.mts → index-C50BUxKs.d.mts} +1 -1
- package/dist/{index-CFAJEWCX.d.mts → index-RdpLP71b.d.mts} +7 -30
- package/dist/{index-ugr1tQlW.d.mts → index-eyg5WEcy.d.mts} +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +11 -12
- package/dist/{init-mdJ-v4Xp.mjs → init-LuGxIbQ_.mjs} +1 -1
- package/dist/integrations/event-gateway.mjs +2 -2
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +2 -2
- package/dist/integrations/mcp/index.d.mts +4 -4
- package/dist/integrations/mcp/index.mjs +2 -2
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +3 -3
- package/dist/integrations/streamline.mjs +3 -3
- package/dist/integrations/webhooks.d.mts +4 -2
- package/dist/integrations/webhooks.mjs +28 -27
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.mjs +1 -1
- package/dist/{interface-DznJrm9R.mjs → interface-B7awDx3b.mjs} +1 -1
- package/dist/{jsonBody-CfGH-GxO.mjs → jsonBody-CiHih3ZU.mjs} +2 -2
- package/dist/{keys-WeKvY1dE.mjs → keys-BcNl12HN.mjs} +1 -1
- package/dist/{loadResources-Bj-aSsXi.mjs → loadResources-DGlfRQc9.mjs} +2 -2
- package/dist/{loadResourcesFromEntry-DwaxNcE2.mjs → loadResourcesFromEntry-VYPGSas8.mjs} +2 -2
- package/dist/logger/index.d.mts +23 -4
- package/dist/logger/index.mjs +50 -7
- package/dist/{mcpPlugin-DX3PHD7K.mjs → mcpPlugin-NxSlc-Ks.mjs} +15 -16
- package/dist/{memory-qYSB7rMQ.mjs → memory-BU-C-MV3.mjs} +2 -2
- package/dist/{metrics-D7uchLjN.mjs → metrics-7_1GbJpl.mjs} +2 -2
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.mjs +7 -4
- package/dist/{module-CwKsgZXp.mjs → module-CQNHzE7g.mjs} +1 -1
- package/dist/{multipartBody-4w-S3-PU.mjs → multipartBody-Bi5yqW0M.mjs} +1 -1
- package/dist/{openapi-CkV5mQ53.mjs → openapi-RpNbPBL-.mjs} +6 -6
- package/dist/outbox-admin/index.d.mts +2 -2
- package/dist/outbox-admin/index.mjs +4 -4
- package/dist/{outbox-module-D1QfHqO4.mjs → outbox-module-ClcFrq98.mjs} +6 -4
- package/dist/{outbox-module-C1Bs_FXF.d.mts → outbox-module-b1TyDGGi.d.mts} +24 -1
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +5 -5
- package/dist/{permissions-CP47jdi7.mjs → permissions-DgPrZsJh.mjs} +36 -9
- package/dist/{pipe-BzzoEhHj.mjs → pipe-Cjy1UiXX.mjs} +2 -2
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +2 -2
- package/dist/plugins/index.d.mts +92 -7
- package/dist/plugins/index.mjs +168 -17
- package/dist/plugins/response-cache.mjs +2 -2
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-B7xf8qZF.mjs → pluralize-B7m0dPm8.mjs} +1 -1
- package/dist/{preloadResources-g07ldtzh.d.mts → preloadResources-BuutdWgr.d.mts} +54 -270
- package/dist/{createApp-zR-DEesr.mjs → preloadResources-CjnW4iIX.mjs} +170 -34
- package/dist/presets/filesUpload.d.mts +3 -3
- package/dist/presets/filesUpload.mjs +5 -5
- package/dist/presets/index.d.mts +2 -2
- package/dist/presets/index.mjs +2 -2
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +3 -3
- package/dist/presets/search.d.mts +9 -47
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-BAPijK_A.mjs → presets-CsGg8B58.mjs} +4 -4
- package/dist/{projection-BKM0Ui-s.mjs → projection-koISNyQo.mjs} +2 -2
- package/dist/{queryCachePlugin-DhsZ0ZIc.mjs → queryCachePlugin-DHueQT9O.mjs} +5 -5
- package/dist/{rateLimitKey-XngqVNEV.mjs → rateLimitKey-Bma8VXDO.mjs} +1 -1
- package/dist/{realtime-G1TC6Yzc.mjs → realtime-BBoC91Bz.mjs} +9 -9
- package/dist/{rateLimit-D4-ASwsI.mjs → registerRoute-BTgORTlR.mjs} +114 -3
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +3 -3
- package/dist/{registry-CLxCR5LF.mjs → registry-BzvRCYS6.mjs} +15 -56
- package/dist/{renewingLease-BnWtbA2U.mjs → renewingLease-CgIGh0Ab.mjs} +14 -2
- package/dist/{replyHelpers-BSBVCwL3.mjs → replyHelpers-BN16KPHr.mjs} +2 -2
- package/dist/{requestContext-uYE35JxI.mjs → requestContext-B93dmpf0.mjs} +1 -1
- package/dist/{rolldown-runtime-DNg-KNCk.mjs → rolldown-runtime-JJWfp8rp.mjs} +1 -1
- package/dist/{runtimeCapabilities-Dm88DaTW.mjs → runtimeCapabilities-jK99Ciw_.mjs} +1 -1
- package/dist/{schedules-CAcZgia0.mjs → schedules-CKKEL21P.mjs} +6 -4
- package/dist/{schemaConverter-XH1RZRyu.mjs → schemaConverter-gg0_aUPF.mjs} +19 -32
- package/dist/{schemaIR-CDvclAew.mjs → schemaIR-CngYvpCF.mjs} +2 -2
- package/dist/schemas/index.mjs +1 -1
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +1 -1
- package/dist/scope/index.mjs +5 -5
- package/dist/{scope-BaWcqBvr.mjs → scope-B1RsHdjF.mjs} +4 -4
- package/dist/simpleEqualityMatcher-_9NAMHUD.mjs +43 -0
- package/dist/{sse-Cf0jUHsh.mjs → sse-Bxt03Hk5.mjs} +5 -5
- package/dist/{sseStream-Bvpi-UXQ.mjs → sseStream-BMHTLlhR.mjs} +2 -2
- package/dist/{store-helpers-B88p99Z2.mjs → store-helpers-Brt8OxWZ.mjs} +1 -1
- package/dist/{streaming-DsT1B5zJ.mjs → streaming-CiTJW8kZ.mjs} +1 -1
- package/dist/{subscribe-helpers-CLIOHsOK.mjs → subscribe-helpers-B4fNHRNc.mjs} +21 -49
- package/dist/sync/changelog.mjs +1 -1
- package/dist/testing/cleanupStoreContract.mjs +1 -1
- package/dist/testing/index.d.mts +6 -6
- package/dist/testing/index.mjs +10 -11
- package/dist/testing/outboxStoreContract.mjs +1 -1
- package/dist/testing/storageContract.mjs +1 -1
- package/dist/{transactionContext-BYtWnwAS.mjs → transactionContext-D2HwJM2z.mjs} +1 -1
- package/dist/{typeGuards-jjKJDN13.mjs → typeGuards-IE1laMDf.mjs} +1 -1
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-CoqIRrkY.mjs → types-B8lwJv9Q.mjs} +10 -53
- package/dist/{types-BfC83KsP.d.mts → types-BXnTOsXP.d.mts} +1 -1
- package/dist/{types-BcTumAz_.d.mts → types-DDD5RKTu.d.mts} +30 -87
- package/dist/{types-ChuShpCP.d.mts → types-Ddl9OjmE.d.mts} +18 -121
- package/dist/usage/index.d.mts +2 -2
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-CWF5pbZD.mjs → userHelpers-xQAi5bPF.mjs} +1 -1
- package/dist/utils/index.d.mts +16 -42
- package/dist/utils/index.mjs +11 -11
- package/dist/{utils-h1V_sT-t.mjs → utils-DgNFsJ2c.mjs} +3 -3
- package/dist/{validate-CdQlz52F.mjs → validate-DI3L5V9w.mjs} +2 -2
- package/dist/{versioning-rZbyLVD-.mjs → versioning-COpAyfpZ.mjs} +3 -3
- package/package.json +8 -8
- package/dist/actionPermissions-CUeCmpUd.mjs +0 -25
- package/dist/defineAggregation-Nv-DwfOf.mjs +0 -48
- package/dist/preloadResources-BkyqeTDz.mjs +0 -46
- package/dist/registerRoute-Ba8v0PCa.mjs +0 -113
- package/dist/repositoryFilter-BANpz6BX.mjs +0 -78
- package/dist/simpleEqualityMatcher-Se8VrsaP.mjs +0 -69
|
@@ -1,61 +1,27 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { r as createEvent } from "./EventTransport-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { r as createEvent } from "./EventTransport-D23Uvhg4.mjs";
|
|
3
3
|
//#region src/events/defineEvent.ts
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* Typed event declarations, a registry for introspection, and `.create()` to
|
|
6
|
+
* build a `DomainEvent` with generated metadata.
|
|
6
7
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* The built-in validator checks: object type, required fields, and top-level
|
|
13
|
-
* property types. It does NOT recurse into nested objects, validate arrays,
|
|
14
|
-
* enums, patterns, formats, or $ref. This is intentional — it's a lightweight
|
|
15
|
-
* guard, not a full JSON Schema engine.
|
|
16
|
-
*
|
|
17
|
-
* For full validation, pass a custom `validate` function to `createEventRegistry()`:
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* ```typescript
|
|
21
|
-
* import Ajv from 'ajv';
|
|
22
|
-
* const ajv = new Ajv();
|
|
23
|
-
*
|
|
24
|
-
* const registry = createEventRegistry({
|
|
25
|
-
* validate: (schema, payload) => {
|
|
26
|
-
* const valid = ajv.validate(schema, payload);
|
|
27
|
-
* return valid
|
|
28
|
-
* ? { valid: true }
|
|
29
|
-
* : { valid: false, errors: ajv.errorsText().split(', ') };
|
|
30
|
-
* },
|
|
31
|
-
* });
|
|
32
|
-
* ```
|
|
8
|
+
* The BUILT-IN validator is deliberately shallow: object type, required
|
|
9
|
+
* fields, and top-level property types only. It does not recurse, nor handle
|
|
10
|
+
* arrays, enums, patterns, formats, or `$ref` — it is a guard, not a JSON
|
|
11
|
+
* Schema engine. Pass `validate` to `createEventRegistry()` to delegate to AJV
|
|
12
|
+
* or similar when you need the real thing.
|
|
33
13
|
*
|
|
34
14
|
* @example
|
|
35
15
|
* ```typescript
|
|
36
|
-
* import { defineEvent, createEventRegistry } from '@classytic/arc/events';
|
|
37
|
-
*
|
|
38
16
|
* const OrderCreated = defineEvent({
|
|
39
17
|
* name: 'order.created',
|
|
40
18
|
* version: 1,
|
|
41
|
-
* schema: {
|
|
42
|
-
*
|
|
43
|
-
* properties: {
|
|
44
|
-
* orderId: { type: 'string' },
|
|
45
|
-
* total: { type: 'number' },
|
|
46
|
-
* },
|
|
47
|
-
* required: ['orderId', 'total'],
|
|
48
|
-
* },
|
|
19
|
+
* schema: { type: 'object', properties: { orderId: { type: 'string' } },
|
|
20
|
+
* required: ['orderId'] },
|
|
49
21
|
* });
|
|
50
22
|
*
|
|
51
|
-
*
|
|
52
|
-
* const event = OrderCreated.create({ orderId: 'o-1', total: 100 });
|
|
23
|
+
* const event = OrderCreated.create({ orderId: 'o-1' });
|
|
53
24
|
* await fastify.events.publish(event.type, event.payload, event.meta);
|
|
54
|
-
*
|
|
55
|
-
* // Registry for introspection + validation
|
|
56
|
-
* const registry = createEventRegistry();
|
|
57
|
-
* registry.register(OrderCreated);
|
|
58
|
-
* const result = registry.validate('order.created', payload);
|
|
59
25
|
* ```
|
|
60
26
|
*/
|
|
61
27
|
/**
|
|
@@ -171,9 +137,15 @@ function validatePayload(payload, schema) {
|
|
|
171
137
|
if (expectedType) {
|
|
172
138
|
const value = record[key];
|
|
173
139
|
const actualType = Array.isArray(value) ? "array" : typeof value;
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
140
|
+
/**
|
|
141
|
+
* `type` may be a UNION (`['string','null']`) — that is how every
|
|
142
|
+
* nullable field compiles. Comparing the array to a `typeof` string
|
|
143
|
+
* is never equal, so a union-typed field failed for EVERY value it
|
|
144
|
+
* allows, and the array stringified into the message as the
|
|
145
|
+
* self-contradictory "expected string,null, got string".
|
|
146
|
+
*/
|
|
147
|
+
const allowed = Array.isArray(expectedType) ? expectedType : [expectedType];
|
|
148
|
+
if (!allowed.some((t) => t === "integer" ? actualType === "number" && Number.isInteger(value) : t === actualType)) errors.push(`Field '${key}': expected ${allowed.join(" | ")}, got ${actualType}`);
|
|
177
149
|
}
|
|
178
150
|
}
|
|
179
151
|
}
|
package/dist/sync/changelog.mjs
CHANGED
package/dist/testing/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { l as PermissionCheck, t as AnyRecord } from "../base-
|
|
4
|
-
import { V as ResourceDefinition } from "../index-
|
|
5
|
-
import { n as ArcModuleInput, o as ModuleDisposer, s as ModuleSetupContext } from "../types-
|
|
6
|
-
import "../index-
|
|
7
|
-
import { n as preloadResourcesAsync, r as CreateAppOptions, t as preloadResources } from "../preloadResources-
|
|
2
|
+
import { i as RequestScope } from "../types-Ddl9OjmE.mjs";
|
|
3
|
+
import { l as PermissionCheck, t as AnyRecord } from "../base-C-NL2fTi.mjs";
|
|
4
|
+
import { V as ResourceDefinition } from "../index-C01wWGJt.mjs";
|
|
5
|
+
import { n as ArcModuleInput, o as ModuleDisposer, s as ModuleSetupContext } from "../types-DDD5RKTu.mjs";
|
|
6
|
+
import "../index-C50BUxKs.mjs";
|
|
7
|
+
import { n as preloadResourcesAsync, r as CreateAppOptions, t as preloadResources } from "../preloadResources-BuutdWgr.mjs";
|
|
8
8
|
import { StorageContractSetup, StorageContractSetupResult, runStorageContract } from "./storageContract.mjs";
|
|
9
9
|
import { StandardRepo } from "@classytic/repo-core/repository";
|
|
10
10
|
import { FastifyInstance, FastifyServerOptions } from "fastify";
|
package/dist/testing/index.mjs
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as CRUD_OPERATIONS } from "../constants-
|
|
3
|
-
import { g as getUserId } from "../types-
|
|
4
|
-
import { t as BaseController } from "../BaseController-
|
|
5
|
-
import { t as defineResource } from "../defineResource-
|
|
6
|
-
import { t as defineAggregation } from "../defineAggregation-
|
|
7
|
-
import { E as requireOrgRole } from "../permissions-
|
|
8
|
-
import {
|
|
9
|
-
import { n as getModuleExports } from "../module-
|
|
10
|
-
import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-BkyqeTDz.mjs";
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as CRUD_OPERATIONS } from "../constants-DUoKAGYD.mjs";
|
|
3
|
+
import { g as getUserId } from "../types-B8lwJv9Q.mjs";
|
|
4
|
+
import { t as BaseController } from "../BaseController-CTJKm6Cb.mjs";
|
|
5
|
+
import { t as defineResource } from "../defineResource-DWzjyxb2.mjs";
|
|
6
|
+
import { t as defineAggregation } from "../defineAggregation-CpQfcM8R.mjs";
|
|
7
|
+
import { E as requireOrgRole } from "../permissions-DgPrZsJh.mjs";
|
|
8
|
+
import { a as createApp, n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-CjnW4iIX.mjs";
|
|
9
|
+
import { n as getModuleExports } from "../module-CQNHzE7g.mjs";
|
|
11
10
|
import { runStorageContract } from "./storageContract.mjs";
|
|
12
11
|
import Fastify from "fastify";
|
|
13
12
|
import { afterAll, describe, expect, it, vi } from "vitest";
|
|
@@ -1505,7 +1504,7 @@ function pickDefaultAuth(authMode, callerAuth) {
|
|
|
1505
1504
|
};
|
|
1506
1505
|
}
|
|
1507
1506
|
async function createTestApp(options = {}) {
|
|
1508
|
-
const { createApp } = await import("../
|
|
1507
|
+
const { createApp } = await import("../preloadResources-CjnW4iIX.mjs").then((n) => n.o);
|
|
1509
1508
|
const { resources = [], db = "in-memory", connectMongoose = false, authMode = "jwt", defaultOrgId, plugins, auth: callerAuth, ...appOptions } = options;
|
|
1510
1509
|
let dbHandle;
|
|
1511
1510
|
let dbUri;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
2
|
import { OutboxOwnershipError } from "@classytic/primitives/outbox";
|
|
3
3
|
import { afterAll, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
|
4
4
|
//#region src/testing/outboxStoreContract.ts
|
package/dist/types/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { a as UserLike, c as DataPolicy, d as UserBase, i as ObjectId, l as PermissionCheck, n as ArcRequest, o as UserOrganization, r as JWTPayload, s as AuthorizationDecision, t as AnyRecord, u as PermissionContext } from "../base-
|
|
4
|
-
import { $ as OpenApiSchemas, A as RequestIdOptions, An as WriteVerbKey, At as RouteDefinition, C as RequestContext, D as HealthCheck, Dn as MutationWriteContext, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Fn as IControllerResponse, Ft as AuthPluginOptions, G as OnTenantDeleteConfig, H as CrudController, I as MiddlewareHandler, In as IRequestContext, It as Authenticator, J as PresetHook, K as ResolvedTenantPurge, L as RequestWithExtras, Ln as RawRouteHandler, Lt as AuthenticatorContext, M as EventsDecorator, Mn as ControllerLike, Mt as RouteMethod, N as FastifyRequestExtras, Nn as FastifyHandler, Nt as RateLimitConfig, O as HealthOptions, On as ResourceWrites, Ot as ActionHandlerFn, P as FastifyWithAuth, Pn as IController, Pt as AuthHelpers, Q as MiddlewareConfig, Rn as RouteHandler, Rt as JwtContext, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, W as ResourcePermissions, X as CrudRouteKey, Y as PresetResult, Z as CrudSchemas, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jn as ControllerHandler, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kn as WriteContext, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, xn as BaseControllerOptions, y as OwnershipCheck, zt as TokenPair } from "../index-
|
|
2
|
+
import { i as RequestScope } from "../types-Ddl9OjmE.mjs";
|
|
3
|
+
import { a as UserLike, c as DataPolicy, d as UserBase, i as ObjectId, l as PermissionCheck, n as ArcRequest, o as UserOrganization, r as JWTPayload, s as AuthorizationDecision, t as AnyRecord, u as PermissionContext } from "../base-C-NL2fTi.mjs";
|
|
4
|
+
import { $ as OpenApiSchemas, A as RequestIdOptions, An as WriteVerbKey, At as RouteDefinition, C as RequestContext, D as HealthCheck, Dn as MutationWriteContext, Dt as ActionEntry, E as GracefulShutdownOptions, Et as ActionDefinition, F as FastifyWithDecorators, Fn as IControllerResponse, Ft as AuthPluginOptions, G as OnTenantDeleteConfig, H as CrudController, I as MiddlewareHandler, In as IRequestContext, It as Authenticator, J as PresetHook, K as ResolvedTenantPurge, L as RequestWithExtras, Ln as RawRouteHandler, Lt as AuthenticatorContext, M as EventsDecorator, Mn as ControllerLike, Mt as RouteMethod, N as FastifyRequestExtras, Nn as FastifyHandler, Nt as RateLimitConfig, O as HealthOptions, On as ResourceWrites, Ot as ActionHandlerFn, P as FastifyWithAuth, Pn as IController, Pt as AuthHelpers, Q as MiddlewareConfig, Rn as RouteHandler, Rt as JwtContext, S as QueryParserInterface, T as CrudRouterOptions, Tt as ResourceCacheConfig, U as ResourceConfig, W as ResourcePermissions, X as CrudRouteKey, Y as PresetResult, Z as CrudSchemas, _ as ControllerQueryOptions, a as InferAdapterDoc, at as ResourceExtensions, b as ParsedQuery, c as TypedController, d as PaginationResult, et as RouteSchemaOptions, f as IntrospectionData, g as ArcInternalMetadata, h as ResourceMetadata, i as ValidationResult, it as ResourceHooks, j as ArcDecorator, jn as ControllerHandler, jt as RouteMcpConfig, k as IntrospectionPluginOptions, kn as WriteContext, kt as ActionsMap, l as TypedRepository, m as RegistryStats, n as ConfigError, nt as FieldRule, o as InferDocType, ot as EventDefinition, p as RegistryEntry, q as PresetFunction, r as ValidateOptions, rt as ResourceHookContext, s as InferResourceDoc, t as RouteHandlerMethod, tt as ArcFieldRule, u as TypedResourceConfig, v as LookupOption, w as ServiceContext, x as PopulateOption, xn as BaseControllerOptions, y as OwnershipCheck, zt as TokenPair } from "../index-C01wWGJt.mjs";
|
|
5
5
|
import { n as ElevationOptions, t as ElevationEvent } from "../elevation-BXCfVcNG.mjs";
|
|
6
6
|
export type { ActionDefinition, ActionEntry, ActionHandlerFn, ActionsMap, AnyRecord, ArcDecorator, ArcFieldRule, ArcInternalMetadata, ArcRequest, AuthHelpers, AuthPluginOptions, Authenticator, AuthenticatorContext, AuthorizationDecision, BaseControllerOptions, ConfigError, ControllerHandler, ControllerLike, ControllerQueryOptions, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, DataPolicy, ElevationEvent, ElevationOptions, EventDefinition, EventsDecorator, FastifyHandler, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, IController, IControllerResponse, IRequestContext, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, JwtContext, LookupOption, MiddlewareConfig, MiddlewareHandler, MutationWriteContext, ObjectId, OnTenantDeleteConfig, OpenApiSchemas, OwnershipCheck, PaginationResult, ParsedQuery, PermissionCheck, PermissionContext, PopulateOption, PresetFunction, PresetHook, PresetResult, QueryParserInterface, RateLimitConfig, RawRouteHandler, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestScope, RequestWithExtras, ResolvedTenantPurge, ResourceCacheConfig, ResourceConfig, ResourceExtensions, ResourceHookContext, ResourceHooks, ResourceMetadata, ResourcePermissions, ResourceWrites, RouteDefinition, RouteHandler, RouteHandlerMethod, RouteMcpConfig, RouteMethod, RouteSchemaOptions, ServiceContext, TokenPair, TypedController, TypedRepository, TypedResourceConfig, UserBase, UserLike, UserOrganization, ValidateOptions, ValidationResult, WriteContext, WriteVerbKey };
|
package/dist/types/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
2
|
export {};
|
package/dist/types/storage.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
2
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { l as UnauthorizedError, o as OrgRequiredError } from "./errors-
|
|
3
|
-
import { n as requireSingleHeaderValue } from "./headers-
|
|
4
|
-
import { t as getUserId$1 } from "./userHelpers-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { l as UnauthorizedError, o as OrgRequiredError } from "./errors-DDKni6Tz.mjs";
|
|
3
|
+
import { n as requireSingleHeaderValue } from "./headers-DKslnhey.mjs";
|
|
4
|
+
import { t as getUserId$1 } from "./userHelpers-xQAi5bPF.mjs";
|
|
5
5
|
//#region src/scope/types.ts
|
|
6
6
|
/**
|
|
7
7
|
* Request Scope — The One Standard
|
|
@@ -50,36 +50,10 @@ function getOrgId(scope) {
|
|
|
50
50
|
if (scope.kind === "elevated") return scope.organizationId;
|
|
51
51
|
}
|
|
52
52
|
/**
|
|
53
|
-
*
|
|
54
|
-
* walking the canonical sources in order: `request.scope` → `x-organization-id`
|
|
55
|
-
* header. Returns `{ organizationId, source }` so callers can log or branch
|
|
56
|
-
* on which path won.
|
|
53
|
+
* Tenant id for a request, from its scope.
|
|
57
54
|
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
* tenant injected by `BaseCrudController`. Bridges arc's HTTP shape to
|
|
61
|
-
* the mongokit/kit-side tenant context (e.g. `createTenantContext().run`).
|
|
62
|
-
*
|
|
63
|
-
* Header fallback is intentional: matches `resolveOrgFromHeader` semantics
|
|
64
|
-
* for hosts that select an org via header instead of session/scope. Don't
|
|
65
|
-
* reach for this when `getOrgId(scope)` alone is enough — for standard
|
|
66
|
-
* authenticated routes the scope is already authoritative.
|
|
67
|
-
*
|
|
68
|
-
* @example
|
|
69
|
-
* ```typescript
|
|
70
|
-
* import { getTenantFromRequest } from '@classytic/arc/scope';
|
|
71
|
-
* import { tenantContext } from './lib/mongokit.js';
|
|
72
|
-
*
|
|
73
|
-
* fastify.post('/statements/batch', async (req, reply) => {
|
|
74
|
-
* const { organizationId } = getTenantFromRequest(req);
|
|
75
|
-
* if (!organizationId) {
|
|
76
|
-
* return reply.code(400).send({ error: 'organizationId required' });
|
|
77
|
-
* }
|
|
78
|
-
* await tenantContext.run({ tenantId: organizationId }, async () => {
|
|
79
|
-
* await statementRepository.create(req.body);
|
|
80
|
-
* });
|
|
81
|
-
* });
|
|
82
|
-
* ```
|
|
55
|
+
* Reads the SCOPE, never `request.user` — the two drift once elevation or a
|
|
56
|
+
* service token is involved, and the scope is the resolved answer.
|
|
83
57
|
*/
|
|
84
58
|
function getTenantFromRequest(req, options = {}) {
|
|
85
59
|
if (req.scope) {
|
|
@@ -374,27 +348,10 @@ function getOrgContext(request) {
|
|
|
374
348
|
};
|
|
375
349
|
}
|
|
376
350
|
/**
|
|
377
|
-
* Read `request.scope
|
|
378
|
-
* Falls back to `PUBLIC_SCOPE` when the field is absent or undefined.
|
|
379
|
-
*
|
|
380
|
-
* This is the canonical way for permission checks, presets, and middleware
|
|
381
|
-
* to read scope — never access `request.scope` directly because it can be
|
|
382
|
-
* `undefined` on requests that haven't been touched by an auth adapter yet.
|
|
351
|
+
* Read `request.scope`, falling back to `PUBLIC_SCOPE`.
|
|
383
352
|
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
* dragging in the Fastify type. The actual runtime is identical.
|
|
387
|
-
*
|
|
388
|
-
* @example
|
|
389
|
-
* ```typescript
|
|
390
|
-
* import { getRequestScope } from '@classytic/arc/scope';
|
|
391
|
-
*
|
|
392
|
-
* function myCheck(ctx: PermissionContext) {
|
|
393
|
-
* const scope = getRequestScope(ctx.request);
|
|
394
|
-
* if (isElevated(scope)) return true;
|
|
395
|
-
* // ...
|
|
396
|
-
* }
|
|
397
|
-
* ```
|
|
353
|
+
* Never returns undefined: an absent scope means an unauthenticated request,
|
|
354
|
+
* not a missing one, and callers must not have to distinguish those.
|
|
398
355
|
*/
|
|
399
356
|
function getRequestScope(request) {
|
|
400
357
|
return request.scope ?? PUBLIC_SCOPE;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { V as ResourceDefinition } from "./index-
|
|
2
|
+
import { V as ResourceDefinition } from "./index-C01wWGJt.mjs";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
//#region src/integrations/mcp/types.d.ts
|
|
5
5
|
/** Behavioral hints for MCP clients (tool annotations per MCP spec) */
|
|
@@ -446,52 +446,23 @@ interface ArcModule<TExports = unknown> {
|
|
|
446
446
|
*/
|
|
447
447
|
readonly dependsOn?: readonly string[];
|
|
448
448
|
/**
|
|
449
|
-
* Infra SETUP
|
|
450
|
-
*
|
|
451
|
-
* module infra can build on app foundations like a DB connection) and in
|
|
452
|
-
* `dependsOn` order, but BEFORE any module `bootstrap` — so engines
|
|
453
|
-
* initialised in `bootstrap` can rely on what's registered here.
|
|
454
|
-
*
|
|
455
|
-
* ## ⚠ This is NOT itself a Fastify plugin
|
|
456
|
-
*
|
|
457
|
-
* Despite the name, arc CALLS this function directly — it is never handed
|
|
458
|
-
* to `fastify.register()`. Two consequences, both of which bite module
|
|
459
|
-
* authors coming from ordinary Fastify plugins:
|
|
460
|
-
*
|
|
461
|
-
* - **You must register plugins yourself.** `await fastify.register(x)`,
|
|
462
|
-
* not `return x`. A returned function is read as a DISPOSER (below),
|
|
463
|
-
* so returning a plugin silently registers nothing and then invokes
|
|
464
|
-
* your plugin as a teardown callback. Arc detects the `fastify-plugin`
|
|
465
|
-
* case and throws; the bare-function case warns.
|
|
466
|
-
* - **There is no encapsulation and no prefix here.** Decorators and
|
|
467
|
-
* hooks you add land on the instance arc passes you — the same
|
|
468
|
-
* instance every other module sees. Fastify's encapsulation applies
|
|
469
|
-
* only inside a `register()` call you make yourself. See
|
|
470
|
-
* https://fastify.dev/docs/latest/Reference/Plugins/
|
|
449
|
+
* Infra SETUP — the module analog of the app's `plugins()`. Runs after the
|
|
450
|
+
* app's own `plugins()`, in `dependsOn` order, before any module `bootstrap`.
|
|
471
451
|
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* },
|
|
478
|
-
* ```
|
|
452
|
+
* ⚠ NOT a Fastify plugin: arc CALLS it, never `register()`s it. So you
|
|
453
|
+
* register your own (`await fastify.register(x)`, not `return x` — a
|
|
454
|
+
* returned function is read as a DISPOSER), and there is no encapsulation
|
|
455
|
+
* or prefix: decorators land on the shared instance. Returning an `fp()`
|
|
456
|
+
* plugin throws; a bare multi-arg function warns.
|
|
479
457
|
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
*
|
|
483
|
-
* Separating this from `bootstrap` keeps lifecycle intent explicit for
|
|
484
|
-
* published ecosystem packages: `plugins` = "register infra"; `bootstrap` =
|
|
485
|
-
* "initialise engines (and return the public export)". Registering a plugin
|
|
486
|
-
* inside `bootstrap` still works — this slot just makes the two distinct.
|
|
487
|
-
*
|
|
488
|
-
* Receives `{ defer }` to register teardown for anything it acquires, and
|
|
489
|
-
* may RETURN a single disposer as shorthand for the one-resource case:
|
|
458
|
+
* Receives `{ defer }` for teardown, or return one disposer as shorthand.
|
|
459
|
+
* v3 renames this slot to `setup` with no alias (v3.md).
|
|
490
460
|
*
|
|
491
461
|
* ```ts
|
|
492
462
|
* plugins: async (fastify) => {
|
|
463
|
+
* await fastify.register(somePlugin, { prefix: '/x' });
|
|
493
464
|
* const conn = await connect();
|
|
494
|
-
* return () => conn.close();
|
|
465
|
+
* return () => conn.close();
|
|
495
466
|
* },
|
|
496
467
|
* ```
|
|
497
468
|
*/
|
|
@@ -550,53 +521,25 @@ interface ArcModule<TExports = unknown> {
|
|
|
550
521
|
*/
|
|
551
522
|
bootstrap?: (fastify: FastifyInstance, context: ModuleSetupContext) => TExports | Promise<TExports>;
|
|
552
523
|
/**
|
|
553
|
-
* App-level resource NAMES this module
|
|
554
|
-
*
|
|
555
|
-
*
|
|
556
|
-
*
|
|
557
|
-
*
|
|
558
|
-
*
|
|
559
|
-
*
|
|
560
|
-
*
|
|
561
|
-
*
|
|
562
|
-
*
|
|
563
|
-
*
|
|
564
|
-
*
|
|
565
|
-
*
|
|
566
|
-
*
|
|
567
|
-
*
|
|
568
|
-
*
|
|
569
|
-
*
|
|
570
|
-
*
|
|
571
|
-
*
|
|
572
|
-
* resources this module actually returned, so the claim and the reality
|
|
573
|
-
* cannot disagree:
|
|
574
|
-
*
|
|
575
|
-
* ```ts
|
|
576
|
-
* defineModule({ name: "order", owns: "provided", resources: () => [...] })
|
|
577
|
-
* ```
|
|
578
|
-
*
|
|
579
|
-
* That is the whole arm for most modules. Resources are resolved exactly
|
|
580
|
-
* once, names are validated (duplicates within a module are rejected), the
|
|
581
|
-
* effective `owns` is derived, and supersession runs afterward — one atomic
|
|
582
|
-
* phase arc owns, rather than a rule each module re-states.
|
|
583
|
-
*
|
|
584
|
-
* **The explicit-array form is ENFORCED at boot: if you `owns` a name,
|
|
585
|
-
* PROVIDE it** — in THIS module's own `resources`. Arc fails boot when a
|
|
586
|
-
* claimed name is not among them, naming the module, the unmet names, and
|
|
587
|
-
* what it did supply. Without that check, a typo or a resource deleted
|
|
588
|
-
* without updating the list booted "successfully" with the app's route
|
|
589
|
-
* silently removed and nothing serving it. Two real cases, both silent 404s:
|
|
590
|
-
* a POS module claiming a checkout resource it mounted only when the host
|
|
591
|
-
* supplied a pipeline, and a device gateway claiming a name it never
|
|
592
|
-
* provided at all.
|
|
593
|
-
*
|
|
594
|
-
* Keep the explicit array only when the list is genuinely NOT the module's
|
|
595
|
-
* own resource set — e.g. pre-declaring a name before the fork exists.
|
|
596
|
-
*
|
|
597
|
-
* A sibling module supplying the name does NOT satisfy the claim — ownership
|
|
598
|
-
* is local to the module that declares it, which is the colocation this arm
|
|
599
|
-
* exists for.
|
|
524
|
+
* App-level resource NAMES this module SUPERSEDES. When the host lists (or
|
|
525
|
+
* discovers) a resource of the same name, arc drops the app copy and
|
|
526
|
+
* registers this module's — so the host maintains no "which resources did
|
|
527
|
+
* modules take over" filter set.
|
|
528
|
+
*
|
|
529
|
+
* PREFER `owns: "provided"`: arc derives the list from the resources the
|
|
530
|
+
* module actually returned, so the claim cannot disagree with reality.
|
|
531
|
+
* Resources resolve once, names are validated, `owns` is derived, and
|
|
532
|
+
* supersession runs after — one phase arc owns.
|
|
533
|
+
*
|
|
534
|
+
* The explicit array is ENFORCED at boot: a claimed name must appear in THIS
|
|
535
|
+
* module's own `resources`, or boot fails naming the unmet names. Without
|
|
536
|
+
* that, a typo or a deleted resource booted "successfully" with the app's
|
|
537
|
+
* route removed and nothing serving it. A sibling module providing the name
|
|
538
|
+
* does NOT satisfy the claim — ownership is local to its declarer.
|
|
539
|
+
*
|
|
540
|
+
* It only filters the APP list, never the module's own resources; an entry
|
|
541
|
+
* matching no app resource is a silent no-op (a module may pre-declare a
|
|
542
|
+
* name before any fork exists). Collected across modules as a union.
|
|
600
543
|
*/
|
|
601
544
|
readonly owns?: readonly string[] | "provided";
|
|
602
545
|
/**
|
|
@@ -36,48 +36,17 @@ declare function requireSingleHeaderValue(headers: ArcHeaders | Record<string, s
|
|
|
36
36
|
//#endregion
|
|
37
37
|
//#region src/scope/types.d.ts
|
|
38
38
|
/**
|
|
39
|
-
* A capability mandate —
|
|
40
|
-
*
|
|
39
|
+
* A capability mandate — time-boxed, optionally cap-bounded authorization for
|
|
40
|
+
* ONE high-value action by an agent or service.
|
|
41
41
|
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
42
|
+
* Where OAuth scopes answer "what may this client EVER do?", a mandate answers
|
|
43
|
+
* "what is THIS request authorized to do right now?" — narrower in capability,
|
|
44
|
+
* time, and value. Shape follows the 2025 agent-authorization conventions
|
|
45
|
+
* (AP2, x402, MCP authorization: RFC 9728/9700/9449).
|
|
46
46
|
*
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
* Arc does **not** parse mandate JWTs / Verifiable Credentials — your
|
|
52
|
-
* authenticate callback does (one `jose.jwtVerify()` or `did-jwt-vc.verify()`
|
|
53
|
-
* call) and populates this object. Arc's `requireMandate(capability, opts)`
|
|
54
|
-
* permission helper reads it and validates the action against the mandate's
|
|
55
|
-
* declared bounds.
|
|
56
|
-
*
|
|
57
|
-
* @example
|
|
58
|
-
* ```typescript
|
|
59
|
-
* // Inbound: Authorization: Mandate eyJhbGc...
|
|
60
|
-
* authenticate: async (request) => {
|
|
61
|
-
* const proof = request.headers['authorization']?.replace(/^Mandate /, '');
|
|
62
|
-
* const claims = await verifyMandate(proof); // host's verifier
|
|
63
|
-
* request.scope = {
|
|
64
|
-
* kind: 'service',
|
|
65
|
-
* clientId: claims.iss,
|
|
66
|
-
* organizationId: claims.org,
|
|
67
|
-
* scopes: claims.scope?.split(' '),
|
|
68
|
-
* mandate: {
|
|
69
|
-
* id: claims.jti,
|
|
70
|
-
* capability: claims.cap, // 'payment.charge' / 'inbox.send' / ...
|
|
71
|
-
* cap: claims.amount, // numeric ceiling
|
|
72
|
-
* expiresAt: claims.exp * 1000,
|
|
73
|
-
* parent: claims.parent, // delegated mandate chain
|
|
74
|
-
* audience: claims.aud, // resource id mandate is bound to
|
|
75
|
-
* },
|
|
76
|
-
* dpopJkt: claims.cnf?.jkt, // RFC 7638 — sender-constrained
|
|
77
|
-
* };
|
|
78
|
-
* return { id: claims.iss };
|
|
79
|
-
* };
|
|
80
|
-
* ```
|
|
47
|
+
* Arc does NOT verify mandate JWTs or VCs. The host's `authenticate` callback
|
|
48
|
+
* verifies and populates this object; `requireMandate(capability, opts)` then
|
|
49
|
+
* validates the action against its bounds.
|
|
81
50
|
*/
|
|
82
51
|
interface Mandate {
|
|
83
52
|
/** Mandate identifier — typically the JWT `jti` claim. */
|
|
@@ -252,36 +221,10 @@ declare function isAuthenticated(scope: RequestScope): boolean;
|
|
|
252
221
|
/** Get organizationId from scope (member, service, or elevated — undefined otherwise) */
|
|
253
222
|
declare function getOrgId(scope: RequestScope): string | undefined;
|
|
254
223
|
/**
|
|
255
|
-
*
|
|
256
|
-
* walking the canonical sources in order: `request.scope` → `x-organization-id`
|
|
257
|
-
* header. Returns `{ organizationId, source }` so callers can log or branch
|
|
258
|
-
* on which path won.
|
|
259
|
-
*
|
|
260
|
-
* Use in custom handlers that bypass arc's auto-CRUD path (worker routes,
|
|
261
|
-
* batch importers, cross-engine subscribers) and therefore don't get the
|
|
262
|
-
* tenant injected by `BaseCrudController`. Bridges arc's HTTP shape to
|
|
263
|
-
* the mongokit/kit-side tenant context (e.g. `createTenantContext().run`).
|
|
224
|
+
* Tenant id for a request, from its scope.
|
|
264
225
|
*
|
|
265
|
-
*
|
|
266
|
-
*
|
|
267
|
-
* reach for this when `getOrgId(scope)` alone is enough — for standard
|
|
268
|
-
* authenticated routes the scope is already authoritative.
|
|
269
|
-
*
|
|
270
|
-
* @example
|
|
271
|
-
* ```typescript
|
|
272
|
-
* import { getTenantFromRequest } from '@classytic/arc/scope';
|
|
273
|
-
* import { tenantContext } from './lib/mongokit.js';
|
|
274
|
-
*
|
|
275
|
-
* fastify.post('/statements/batch', async (req, reply) => {
|
|
276
|
-
* const { organizationId } = getTenantFromRequest(req);
|
|
277
|
-
* if (!organizationId) {
|
|
278
|
-
* return reply.code(400).send({ error: 'organizationId required' });
|
|
279
|
-
* }
|
|
280
|
-
* await tenantContext.run({ tenantId: organizationId }, async () => {
|
|
281
|
-
* await statementRepository.create(req.body);
|
|
282
|
-
* });
|
|
283
|
-
* });
|
|
284
|
-
* ```
|
|
226
|
+
* Reads the SCOPE, never `request.user` — the two drift once elevation or a
|
|
227
|
+
* service token is involved, and the scope is the resolved answer.
|
|
285
228
|
*/
|
|
286
229
|
declare function getTenantFromRequest(req: {
|
|
287
230
|
scope?: RequestScope;
|
|
@@ -510,27 +453,10 @@ declare function getOrgContext(request: {
|
|
|
510
453
|
orgRoles: string[];
|
|
511
454
|
};
|
|
512
455
|
/**
|
|
513
|
-
* Read `request.scope
|
|
514
|
-
* Falls back to `PUBLIC_SCOPE` when the field is absent or undefined.
|
|
515
|
-
*
|
|
516
|
-
* This is the canonical way for permission checks, presets, and middleware
|
|
517
|
-
* to read scope — never access `request.scope` directly because it can be
|
|
518
|
-
* `undefined` on requests that haven't been touched by an auth adapter yet.
|
|
519
|
-
*
|
|
520
|
-
* Accepts a structural shape (`{ scope?: RequestScope }`) instead of the
|
|
521
|
-
* full Fastify request type so it can be called from any layer without
|
|
522
|
-
* dragging in the Fastify type. The actual runtime is identical.
|
|
456
|
+
* Read `request.scope`, falling back to `PUBLIC_SCOPE`.
|
|
523
457
|
*
|
|
524
|
-
*
|
|
525
|
-
*
|
|
526
|
-
* import { getRequestScope } from '@classytic/arc/scope';
|
|
527
|
-
*
|
|
528
|
-
* function myCheck(ctx: PermissionContext) {
|
|
529
|
-
* const scope = getRequestScope(ctx.request);
|
|
530
|
-
* if (isElevated(scope)) return true;
|
|
531
|
-
* // ...
|
|
532
|
-
* }
|
|
533
|
-
* ```
|
|
458
|
+
* Never returns undefined: an absent scope means an unauthenticated request,
|
|
459
|
+
* not a missing one, and callers must not have to distinguish those.
|
|
534
460
|
*/
|
|
535
461
|
declare function getRequestScope(request: {
|
|
536
462
|
scope?: RequestScope;
|
|
@@ -576,38 +502,9 @@ interface ScopeFirstCtxRequest {
|
|
|
576
502
|
headers?: ArcHeaders | undefined;
|
|
577
503
|
}
|
|
578
504
|
/**
|
|
579
|
-
*
|
|
580
|
-
*
|
|
581
|
-
*
|
|
582
|
-
* 1. `request.scope` (arc's validated `RequestScope`, set by auth adapters):
|
|
583
|
-
* `userId` (human) or `clientId` (service) → `actorId`; `getOrgId(scope)`
|
|
584
|
-
* → `organizationId`.
|
|
585
|
-
* 2. The `x-organization-id` header — ONLY when the scope carries no org.
|
|
586
|
-
* This is the bridge for custom-auth/public routes where arc leaves scope
|
|
587
|
-
* unpopulated; it never overrides a validated scope.
|
|
588
|
-
*
|
|
589
|
-
* Replaces per-package hand-rolled clones of
|
|
590
|
-
* `req.user?._id ?? req.user?.id ?? headers['x-organization-id']` — that
|
|
591
|
-
* pattern re-implements (and drifts from) arc's canonical resolution. A
|
|
592
|
-
* package's `ctxOf(req)` should call this for the shared
|
|
593
|
-
* `{ actorId, organizationId }` and only ADD its kernel-specific fields
|
|
594
|
-
* (`actorKind` / `correlationId` / `roles` / `idempotencyKey`).
|
|
595
|
-
*
|
|
596
|
-
* Structural request shape — works on a raw `FastifyRequest` AND on arc's
|
|
597
|
-
* `IRequestContext` (see {@link ScopeFirstCtxRequest}: the discriminated
|
|
598
|
-
* `RequestScope` and the flat controller projection are both understood).
|
|
599
|
-
*
|
|
600
|
-
* @example
|
|
601
|
-
* ```typescript
|
|
602
|
-
* import { scopeFirstCtx } from '@classytic/arc/scope';
|
|
603
|
-
*
|
|
604
|
-
* // Guaranteed actor (kernel context requires one):
|
|
605
|
-
* const { actorId, organizationId } = scopeFirstCtx(req, { fallbackActorId: 'system' });
|
|
606
|
-
*
|
|
607
|
-
* // Optional actor (package applies its own policy):
|
|
608
|
-
* const ctx = scopeFirstCtx(req);
|
|
609
|
-
* if (ctx.actorId) audit.record({ actor: ctx.actorId });
|
|
610
|
-
* ```
|
|
505
|
+
* Build a scope-first context for permission checks outside a Fastify request
|
|
506
|
+
* (jobs, MCP tools, workers). `scope` is the identity channel; `user` is
|
|
507
|
+
* derived for legacy checks that still read it.
|
|
611
508
|
*/
|
|
612
509
|
declare function scopeFirstCtx(req: ScopeFirstCtxRequest, options: ScopeFirstCtxOptions & {
|
|
613
510
|
fallbackActorId: string;
|
package/dist/usage/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import { i as RequestScope } from "../types-
|
|
3
|
-
import { l as PermissionCheck, u as PermissionContext } from "../base-
|
|
2
|
+
import { i as RequestScope } from "../types-Ddl9OjmE.mjs";
|
|
3
|
+
import { l as PermissionCheck, u as PermissionContext } from "../base-C-NL2fTi.mjs";
|
|
4
4
|
import { UsageBucket, UsageStore, usagePeriod } from "@classytic/repo-core/usage";
|
|
5
5
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
6
6
|
//#region src/usage/requireQuota.d.ts
|