@classytic/arc 2.6.2 → 2.7.1
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/README.md +95 -1
- package/dist/{BaseController-AbbRx3e0.mjs → BaseController-CpMfCXdn.mjs} +214 -16
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-CTn28N4y.mjs → adapters-BxGgSHjj.mjs} +7 -13
- package/dist/applyPermissionResult-D6GPMsvh.mjs +37 -0
- package/dist/audit/index.d.mts +1 -1
- package/dist/audit/index.mjs +1 -1
- package/dist/audit/mongodb.d.mts +1 -1
- package/dist/audit/mongodb.mjs +1 -1
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/index.mjs +7 -6
- package/dist/auth/mongoose.d.mts +191 -0
- package/dist/auth/mongoose.mjs +73 -0
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-lz0IRbXJ.mjs → betterAuthOpenApi-CCw3YX0g.mjs} +1 -1
- package/dist/cache/index.d.mts +2 -2
- package/dist/cache/index.mjs +2 -2
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +7 -5
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-C1XCMtqM.mjs → core-BWekSEju.mjs} +41 -13
- package/dist/{createApp-D2w0LdYJ.mjs → createApp-B_nvKNAQ.mjs} +11 -11
- package/dist/{defineResource-Ckxg6HrZ.mjs → defineResource-DZzyl4a4.mjs} +73 -56
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/dynamic/index.d.mts +2 -2
- package/dist/dynamic/index.mjs +2 -2
- package/dist/{elevation-BEdACOLB.mjs → elevation-By_p2lnn.mjs} +1 -1
- package/dist/elevation-Dm-HTBCt.d.mts +23 -0
- package/dist/{errorHandler-Do4vVQ1f.d.mts → errorHandler-COa51ho_.d.mts} +1 -1
- package/dist/{errorHandler-r2595m8T.mjs → errorHandler-DXUttWEO.mjs} +1 -1
- package/dist/{eventPlugin-DW45v4V5.d.mts → eventPlugin-BgLxJkIB.d.mts} +1 -1
- package/dist/{eventPlugin-Ba00swHF.mjs → eventPlugin-DsaNNXzZ.mjs} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +1 -1
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/mongodb.d.mts +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/index-BYpRGXif.d.mts +640 -0
- package/dist/{index-B4uZm82R.d.mts → index-KXM8_JmQ.d.mts} +47 -4
- package/dist/{index-DrCqa3Jq.d.mts → index-StgFaQKD.d.mts} +3 -3
- package/dist/index.d.mts +8 -8
- package/dist/index.mjs +10 -9
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +2 -2
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/{interface-CrN45qz1.d.mts → interface-Dwzqt4mn.d.mts} +204 -18
- package/dist/{mongodb-pMvOlR5_.d.mts → mongodb-Bq90j-Uj.d.mts} +1 -1
- package/dist/{mongodb-kltrBPa1.d.mts → mongodb-DdyYlIXg.d.mts} +1 -1
- package/dist/{openapi-CBmZ6EQN.mjs → openapi-C5UhIeWu.mjs} +1 -1
- package/dist/org/index.d.mts +2 -2
- package/dist/org/index.mjs +1 -1
- package/dist/permissions/index.d.mts +4 -4
- package/dist/permissions/index.mjs +3 -2
- package/dist/{permissions-C8ImI8gC.mjs → permissions-CH4cNwJi.mjs} +358 -64
- package/dist/plugins/index.d.mts +4 -4
- package/dist/plugins/index.mjs +10 -10
- package/dist/plugins/response-cache.mjs +1 -1
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/policies/index.d.mts +1 -1
- package/dist/presets/index.d.mts +3 -3
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +53 -3
- package/dist/presets/multiTenant.mjs +89 -47
- package/dist/{presets-BMfdy34e.mjs → presets-BFrGvvjL.mjs} +2 -2
- package/dist/{queryCachePlugin-DcmETvcB.d.mts → queryCachePlugin-Bw8XyJpX.d.mts} +1 -1
- package/dist/{queryCachePlugin-XtFplYO9.mjs → queryCachePlugin-CwTpR04-.mjs} +2 -2
- package/dist/{redis-D0Qc-9EW.d.mts → redis-CyCntzTO.d.mts} +1 -1
- package/dist/{redis-stream-BW9UKLZM.d.mts → redis-stream-We_Ucl9-.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-DH3c3e-T.mjs → resourceToTools-CkVSSzKg.mjs} +313 -33
- package/dist/rpc/index.d.mts +1 -1
- package/dist/rpc/index.mjs +1 -1
- package/dist/scope/index.d.mts +3 -2
- package/dist/scope/index.mjs +4 -3
- package/dist/{sse-BF7GR7IB.mjs → sse-Bp3dabF1.mjs} +2 -2
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +4 -3
- package/dist/types/index.mjs +1 -1
- package/dist/types-AOD8fxIw.mjs +229 -0
- package/dist/types-CNEbix8T.d.mts +286 -0
- package/dist/{types-DurlBP2N.d.mts → types-ClmkMDK1.d.mts} +1 -1
- package/dist/{types-C1Z28coa.d.mts → types-D0qf0Mf4.d.mts} +9 -9
- package/dist/types-DPsC0taJ.d.mts +178 -0
- package/dist/utils/index.d.mts +3 -3
- package/dist/utils/index.mjs +5 -5
- package/package.json +34 -22
- package/skills/arc/SKILL.md +278 -6
- package/skills/arc/references/multi-tenancy.md +208 -0
- package/dist/elevation-C_taLQrM.d.mts +0 -147
- package/dist/index-NGZksqM5.d.mts +0 -398
- package/dist/types-BNUccdcf.d.mts +0 -101
- package/dist/types-BhtYdxZU.mjs +0 -91
- /package/dist/{EventTransport-wc5hSLik.d.mts → EventTransport-CUpRK_Lg.d.mts} +0 -0
- /package/dist/{HookSystem-COkyWztM.mjs → HookSystem-D7lfx--K.mjs} +0 -0
- /package/dist/{ResourceRegistry-C6ngvOnn.mjs → ResourceRegistry-DsHiG9cL.mjs} +0 -0
- /package/dist/{caching-BSXB-Xr7.mjs → caching-5DtLwIqb.mjs} +0 -0
- /package/dist/{circuitBreaker-JP2GdJ4b.d.mts → circuitBreaker-DwxrljLB.d.mts} +0 -0
- /package/dist/{circuitBreaker-BOBOpN2w.mjs → circuitBreaker-l18oRgL5.mjs} +0 -0
- /package/dist/{errors-CcVbl1-T.d.mts → errors-CCSsMpXE.d.mts} +0 -0
- /package/dist/{errors-NoQKsbAT.mjs → errors-Cg58SLNi.mjs} +0 -0
- /package/dist/{externalPaths-DpO-s7r8.d.mts → externalPaths-Dg7OLsKo.d.mts} +0 -0
- /package/dist/{fields-DFwdaWCq.d.mts → fields-CYuLMJPD.d.mts} +0 -0
- /package/dist/{interface-gr-7qo9j.d.mts → interface-B9rHWPxD.d.mts} +0 -0
- /package/dist/{interface-D_BWALyZ.d.mts → interface-CnluRL4_.d.mts} +0 -0
- /package/dist/{logger-Dz3j1ItV.mjs → logger-DLg8-Ueg.mjs} +0 -0
- /package/dist/{memory-BFAYkf8H.mjs → memory-Cp7_cAko.mjs} +0 -0
- /package/dist/{metrics-Csh4nsvv.mjs → metrics-Qnvwc-LQ.mjs} +0 -0
- /package/dist/{mongodb-BuQ7fNTg.mjs → mongodb-mlgxkYI3.mjs} +0 -0
- /package/dist/{pluralize-CcT6qF0a.mjs → pluralize-COpOVar8.mjs} +0 -0
- /package/dist/{registry-I-ogLgL9.mjs → registry-B3lRFBWo.mjs} +0 -0
- /package/dist/{requestContext-DYtmNpm5.mjs → requestContext-xHIKedG6.mjs} +0 -0
- /package/dist/{schemaConverter-DjzHpFam.mjs → schemaConverter-0TyONAwM.mjs} +0 -0
- /package/dist/{sessionManager-wbkYj2HL.d.mts → sessionManager-IW4sbIea.d.mts} +0 -0
- /package/dist/{tracing-bz_U4EM1.d.mts → tracing-65B51Dw3.d.mts} +0 -0
- /package/dist/{typeGuards-Cj5Rgvlg.mjs → typeGuards-CcFZXgU7.mjs} +0 -0
- /package/dist/{utils-Dc0WhlIl.mjs → utils-B-l6410F.mjs} +0 -0
- /package/dist/{versioning-BzfeHmhj.mjs → versioning-aUUVziBY.mjs} +0 -0
|
@@ -44,7 +44,7 @@ try {
|
|
|
44
44
|
function createTracerProvider(options) {
|
|
45
45
|
if (!isAvailable) return null;
|
|
46
46
|
const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
|
|
47
|
-
const resolvedVersion = serviceVersion ?? "2.
|
|
47
|
+
const resolvedVersion = serviceVersion ?? "2.7.1";
|
|
48
48
|
const exporter = new OTLPTraceExporter({ url: exporterUrl });
|
|
49
49
|
const provider = new NodeTracerProvider({ resource: { attributes: {
|
|
50
50
|
"service.name": serviceName,
|
package/dist/presets/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { MultiTenantOptions, multiTenantPreset } from "./multiTenant.mjs";
|
|
1
|
+
import { Gt as PaginatedResult, It as IControllerResponse, Lt as IRequestContext, Z as PresetResult, ot as ResourceConfig, u as AnyRecord } from "../interface-Dwzqt4mn.mjs";
|
|
2
|
+
import { MultiTenantOptions, TenantFieldSpec, multiTenantPreset } from "./multiTenant.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/presets/ownedByUser.d.ts
|
|
5
5
|
interface OwnedByUserOptions {
|
|
@@ -271,4 +271,4 @@ type PresetInput = string | PresetResult | {
|
|
|
271
271
|
*/
|
|
272
272
|
declare function applyPresets<TDoc = AnyRecord>(config: ResourceConfig<TDoc>, presets?: PresetInput[]): ResourceConfig<TDoc>;
|
|
273
273
|
//#endregion
|
|
274
|
-
export { type AuditedPresetOptions, type BulkOperation, type BulkPresetOptions, type IAuditedPreset, type IMultiTenantPreset, type IOwnedByUserPreset, type IPresetController, type ISlugLookupController, type ISoftDeleteController, type ITreeController, type MultiTenantOptions, type OwnedByUserOptions, type SlugLookupOptions, type TreeOptions, applyPresets, auditedPreset, bulkPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
|
|
274
|
+
export { type AuditedPresetOptions, type BulkOperation, type BulkPresetOptions, type IAuditedPreset, type IMultiTenantPreset, type IOwnedByUserPreset, type IPresetController, type ISlugLookupController, type ISoftDeleteController, type ITreeController, type MultiTenantOptions, type OwnedByUserOptions, type SlugLookupOptions, type TenantFieldSpec, type TreeOptions, applyPresets, auditedPreset, bulkPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
|
package/dist/presets/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { multiTenantPreset } from "./multiTenant.mjs";
|
|
2
|
-
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-
|
|
2
|
+
import { a as registerPreset, c as auditedPreset, d as ownedByUserPreset, i as getPreset, l as softDeletePreset, n as flexibleMultiTenantPreset, o as treePreset, r as getAvailablePresets, s as bulkPreset, t as applyPresets, u as slugLookupPreset } from "../presets-BFrGvvjL.mjs";
|
|
3
3
|
export { applyPresets, auditedPreset, bulkPreset, flexibleMultiTenantPreset, getAvailablePresets, getPreset, multiTenantPreset, ownedByUserPreset, registerPreset, slugLookupPreset, softDeletePreset, treePreset };
|
|
@@ -1,9 +1,59 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as CrudRouteKey, Z as PresetResult } from "../interface-Dwzqt4mn.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/presets/multiTenant.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* One tenant dimension for multi-field filtering. Discriminated by source:
|
|
6
|
+
* - `type: 'org'` → reads `getOrgId(scope)`
|
|
7
|
+
* - `type: 'team'` → reads `getTeamId(scope)`
|
|
8
|
+
* - `contextKey` → reads `getScopeContext(scope, contextKey)` (any custom dimension)
|
|
9
|
+
*/
|
|
10
|
+
type TenantFieldSpec = {
|
|
11
|
+
field: string;
|
|
12
|
+
type: "org";
|
|
13
|
+
} | {
|
|
14
|
+
field: string;
|
|
15
|
+
type: "team";
|
|
16
|
+
} | {
|
|
17
|
+
field: string;
|
|
18
|
+
contextKey: string;
|
|
19
|
+
};
|
|
4
20
|
interface MultiTenantOptions {
|
|
5
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Single-field form: name of the database field to filter by.
|
|
23
|
+
* Reads `getOrgId(scope)` as the value source.
|
|
24
|
+
*
|
|
25
|
+
* Mutually exclusive with `tenantFields` — pass one or the other, not both.
|
|
26
|
+
*
|
|
27
|
+
* @default 'organizationId'
|
|
28
|
+
*/
|
|
6
29
|
tenantField?: string;
|
|
30
|
+
/**
|
|
31
|
+
* Multi-field form (2.7.1+): list of tenant dimensions to filter by in
|
|
32
|
+
* lockstep. Use this when a resource is scoped by more than just
|
|
33
|
+
* organization — e.g. organization + branch, organization + project,
|
|
34
|
+
* or organization + team + workspace.
|
|
35
|
+
*
|
|
36
|
+
* Each entry is a discriminated `TenantFieldSpec` declaring where the
|
|
37
|
+
* value comes from. Use `type: 'org'` / `type: 'team'` for built-in scope
|
|
38
|
+
* fields, or `contextKey: '...'` to read from `scope.context` (set by
|
|
39
|
+
* your auth function).
|
|
40
|
+
*
|
|
41
|
+
* Fail-closed: if any required dimension is missing, the request is
|
|
42
|
+
* rejected. Elevated scopes apply whatever resolves and skip the rest.
|
|
43
|
+
*
|
|
44
|
+
* Mutually exclusive with `tenantField`.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* multiTenantPreset({
|
|
49
|
+
* tenantFields: [
|
|
50
|
+
* { field: 'organizationId', type: 'org' },
|
|
51
|
+
* { field: 'branchId', contextKey: 'branchId' },
|
|
52
|
+
* ],
|
|
53
|
+
* })
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
tenantFields?: readonly TenantFieldSpec[];
|
|
7
57
|
/**
|
|
8
58
|
* Routes that allow public access (no auth required)
|
|
9
59
|
* When a route is in this array:
|
|
@@ -18,4 +68,4 @@ interface MultiTenantOptions {
|
|
|
18
68
|
}
|
|
19
69
|
declare function multiTenantPreset(options?: MultiTenantOptions): PresetResult;
|
|
20
70
|
//#endregion
|
|
21
|
-
export { MultiTenantOptions, multiTenantPreset };
|
|
71
|
+
export { MultiTenantOptions, TenantFieldSpec, multiTenantPreset };
|
|
@@ -1,31 +1,59 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import "../constants-Cxde4rpC.mjs";
|
|
2
|
+
import { _ as isElevated, c as getRequestScope, f as getTeamId, h as hasOrgAccess, l as getScopeContext, o as getOrgId } from "../types-AOD8fxIw.mjs";
|
|
3
3
|
//#region src/presets/multiTenant.ts
|
|
4
|
-
/**
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Resolve a single TenantFieldSpec against the current scope.
|
|
6
|
+
* Returns `undefined` if the source value isn't present on the scope.
|
|
7
|
+
*/
|
|
8
|
+
function resolveSpec(scope, spec) {
|
|
9
|
+
if ("contextKey" in spec) return getScopeContext(scope, spec.contextKey);
|
|
10
|
+
if (spec.type === "org") return getOrgId(scope);
|
|
11
|
+
if (spec.type === "team") return getTeamId(scope);
|
|
12
|
+
}
|
|
13
|
+
/** Resolve every spec — returns the partial map of fields that have a value. */
|
|
14
|
+
function resolveAll(scope, specs) {
|
|
15
|
+
const resolved = {};
|
|
16
|
+
const missing = [];
|
|
17
|
+
for (const spec of specs) {
|
|
18
|
+
const value = resolveSpec(scope, spec);
|
|
19
|
+
if (value !== void 0) resolved[spec.field] = value;
|
|
20
|
+
else missing.push(spec.field);
|
|
21
|
+
}
|
|
22
|
+
return {
|
|
23
|
+
resolved,
|
|
24
|
+
missing
|
|
25
|
+
};
|
|
7
26
|
}
|
|
8
27
|
/**
|
|
9
|
-
* Create tenant filter middleware
|
|
10
|
-
*
|
|
11
|
-
*
|
|
28
|
+
* Create tenant filter middleware (strict).
|
|
29
|
+
* Walks the configured tenant fields and applies all of them in lockstep.
|
|
30
|
+
* Fails closed if any non-elevated caller is missing a required dimension.
|
|
12
31
|
*/
|
|
13
|
-
function createTenantFilter(
|
|
32
|
+
function createTenantFilter(specs) {
|
|
14
33
|
return async (request, reply) => {
|
|
15
|
-
const scope =
|
|
34
|
+
const scope = getRequestScope(request);
|
|
16
35
|
if (isElevated(scope)) {
|
|
17
|
-
const
|
|
18
|
-
if (
|
|
36
|
+
const { resolved } = resolveAll(scope, specs);
|
|
37
|
+
if (Object.keys(resolved).length > 0) request._policyFilters = {
|
|
19
38
|
...request._policyFilters ?? {},
|
|
20
|
-
|
|
39
|
+
...resolved
|
|
21
40
|
};
|
|
22
41
|
return;
|
|
23
42
|
}
|
|
24
|
-
if (
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
43
|
+
if (hasOrgAccess(scope)) {
|
|
44
|
+
const { resolved, missing } = resolveAll(scope, specs);
|
|
45
|
+
if (missing.length === 0) {
|
|
46
|
+
request._policyFilters = {
|
|
47
|
+
...request._policyFilters ?? {},
|
|
48
|
+
...resolved
|
|
49
|
+
};
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
reply.code(403).send({
|
|
53
|
+
success: false,
|
|
54
|
+
error: "Forbidden",
|
|
55
|
+
message: `Tenant context incomplete — missing: ${missing.join(", ")}`
|
|
56
|
+
});
|
|
29
57
|
return;
|
|
30
58
|
}
|
|
31
59
|
if (scope.kind === "public") {
|
|
@@ -44,57 +72,71 @@ function createTenantFilter(tenantField) {
|
|
|
44
72
|
};
|
|
45
73
|
}
|
|
46
74
|
/**
|
|
47
|
-
* Create flexible tenant filter middleware
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* Org context present = require auth and apply filter
|
|
75
|
+
* Create flexible tenant filter middleware (allowPublic).
|
|
76
|
+
* Same policy as the strict variant for authenticated callers, but
|
|
77
|
+
* allows public/unauthenticated requests through without filtering.
|
|
51
78
|
*/
|
|
52
|
-
function createFlexibleTenantFilter(
|
|
53
|
-
return async (request,
|
|
54
|
-
const scope =
|
|
79
|
+
function createFlexibleTenantFilter(specs) {
|
|
80
|
+
return async (request, reply) => {
|
|
81
|
+
const scope = getRequestScope(request);
|
|
55
82
|
if (isElevated(scope)) {
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
83
|
+
const { resolved } = resolveAll(scope, specs);
|
|
84
|
+
if (Object.keys(resolved).length > 0) request._policyFilters = {
|
|
58
85
|
...request._policyFilters ?? {},
|
|
59
|
-
|
|
86
|
+
...resolved
|
|
60
87
|
};
|
|
61
88
|
return;
|
|
62
89
|
}
|
|
63
|
-
if (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
90
|
+
if (hasOrgAccess(scope)) {
|
|
91
|
+
const { resolved, missing } = resolveAll(scope, specs);
|
|
92
|
+
if (missing.length === 0) {
|
|
93
|
+
request._policyFilters = {
|
|
94
|
+
...request._policyFilters ?? {},
|
|
95
|
+
...resolved
|
|
96
|
+
};
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
reply.code(403).send({
|
|
100
|
+
success: false,
|
|
101
|
+
error: "Forbidden",
|
|
102
|
+
message: `Tenant context incomplete — missing: ${missing.join(", ")}`
|
|
103
|
+
});
|
|
68
104
|
return;
|
|
69
105
|
}
|
|
70
106
|
};
|
|
71
107
|
}
|
|
72
108
|
/**
|
|
73
|
-
* Create tenant injection middleware
|
|
74
|
-
*
|
|
75
|
-
*
|
|
109
|
+
* Create tenant injection middleware.
|
|
110
|
+
* Walks the configured tenant fields and writes each into the request body.
|
|
111
|
+
* Fails closed if any required dimension is missing for non-elevated callers.
|
|
76
112
|
*/
|
|
77
|
-
function createTenantInjection(
|
|
113
|
+
function createTenantInjection(specs) {
|
|
78
114
|
return async (request, reply) => {
|
|
79
|
-
const scope =
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (
|
|
115
|
+
const scope = getRequestScope(request);
|
|
116
|
+
if (isElevated(scope) && !getOrgId(scope)) return;
|
|
117
|
+
const { resolved, missing } = resolveAll(scope, specs);
|
|
118
|
+
if (missing.length > 0) {
|
|
83
119
|
reply.code(403).send({
|
|
84
120
|
success: false,
|
|
85
121
|
error: "Forbidden",
|
|
86
|
-
message:
|
|
122
|
+
message: `Tenant context incomplete — missing: ${missing.join(", ")}`
|
|
87
123
|
});
|
|
88
124
|
return;
|
|
89
125
|
}
|
|
90
|
-
if (request.body) request.body
|
|
126
|
+
if (request.body) Object.assign(request.body, resolved);
|
|
91
127
|
};
|
|
92
128
|
}
|
|
93
129
|
function multiTenantPreset(options = {}) {
|
|
94
|
-
const { tenantField
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
130
|
+
const { tenantField, tenantFields, allowPublic = [] } = options;
|
|
131
|
+
if (tenantField !== void 0 && tenantFields !== void 0) throw new Error("multiTenantPreset: pass either `tenantField` (single-field) or `tenantFields` (multi-field), not both");
|
|
132
|
+
const specs = tenantFields ?? [{
|
|
133
|
+
field: tenantField ?? "organizationId",
|
|
134
|
+
type: "org"
|
|
135
|
+
}];
|
|
136
|
+
if (specs.length === 0) throw new Error("multiTenantPreset: `tenantFields` must contain at least one entry");
|
|
137
|
+
const strictTenantFilter = createTenantFilter(specs);
|
|
138
|
+
const flexibleTenantFilter = createFlexibleTenantFilter(specs);
|
|
139
|
+
const tenantInjection = createTenantInjection(specs);
|
|
98
140
|
const getFilter = (route) => allowPublic.includes(route) ? flexibleTenantFilter : strictTenantFilter;
|
|
99
141
|
return {
|
|
100
142
|
name: "multiTenant",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { _ as isElevated, n as PUBLIC_SCOPE } from "./types-AOD8fxIw.mjs";
|
|
2
2
|
import { multiTenantPreset } from "./presets/multiTenant.mjs";
|
|
3
|
-
import {
|
|
3
|
+
import { f as requireRoles, n as allowPublic, s as requireAuth } from "./permissions-CH4cNwJi.mjs";
|
|
4
4
|
//#region src/presets/ownedByUser.ts
|
|
5
5
|
/**
|
|
6
6
|
* Create ownership check middleware.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
2
|
import { i as versionKey, r as tagVersionKey } from "./keys-qcD-TVJl.mjs";
|
|
3
|
-
import { t as hasEvents } from "./typeGuards-
|
|
4
|
-
import { t as MemoryCacheStore } from "./memory-
|
|
3
|
+
import { t as hasEvents } from "./typeGuards-CcFZXgU7.mjs";
|
|
4
|
+
import { t as MemoryCacheStore } from "./memory-Cp7_cAko.mjs";
|
|
5
5
|
import fp from "fastify-plugin";
|
|
6
6
|
//#region src/cache/QueryCache.ts
|
|
7
7
|
var QueryCache = class {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-
|
|
1
|
+
import { i as EventTransport, n as EventHandler, r as EventLogger, t as DomainEvent } from "./EventTransport-CUpRK_Lg.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/events/transports/redis-stream.d.ts
|
|
4
4
|
interface RedisStreamLike {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Bt as ResourceRegistry, R as IntrospectionPluginOptions, zt as RegisterOptions } from "../interface-Dwzqt4mn.mjs";
|
|
2
2
|
import { FastifyPluginAsync } from "fastify";
|
|
3
3
|
|
|
4
4
|
//#region src/registry/introspectionPlugin.d.ts
|
package/dist/registry/index.mjs
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as introspectionPlugin_default, t as introspectionPlugin } from "../registry-
|
|
2
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
1
|
+
import { n as introspectionPlugin_default, t as introspectionPlugin } from "../registry-B3lRFBWo.mjs";
|
|
2
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-DsHiG9cL.mjs";
|
|
3
3
|
export { ResourceRegistry, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
|