raffel 1.1.59-next.07e2952 → 1.1.59
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/middleware/policy/bootstrap.d.ts +0 -32
- package/dist/middleware/policy/bootstrap.d.ts.map +1 -1
- package/dist/middleware/policy/bootstrap.js +0 -11
- package/dist/middleware/policy/bootstrap.js.map +1 -1
- package/dist/server/builder.d.ts.map +1 -1
- package/dist/server/builder.js +306 -47
- package/dist/server/builder.js.map +1 -1
- package/dist/server/discovery-utils.d.ts +0 -11
- package/dist/server/discovery-utils.d.ts.map +1 -1
- package/dist/server/discovery-utils.js +50 -41
- package/dist/server/discovery-utils.js.map +1 -1
- package/dist/server/fs-routes/loader.d.ts.map +1 -1
- package/dist/server/fs-routes/loader.js +232 -2
- package/dist/server/fs-routes/loader.js.map +1 -1
- package/dist/ui/server/fs-routes/loader.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/middleware/policy/co-located-accumulator.d.ts +0 -63
- package/dist/middleware/policy/co-located-accumulator.d.ts.map +0 -1
- package/dist/middleware/policy/co-located-accumulator.js +0 -148
- package/dist/middleware/policy/co-located-accumulator.js.map +0 -1
- package/dist/server/builder/policy-bridges.d.ts +0 -41
- package/dist/server/builder/policy-bridges.d.ts.map +0 -1
- package/dist/server/builder/policy-bridges.js +0 -96
- package/dist/server/builder/policy-bridges.js.map +0 -1
- package/dist/server/builder/programmatic-registration.d.ts +0 -43
- package/dist/server/builder/programmatic-registration.d.ts.map +0 -1
- package/dist/server/builder/programmatic-registration.js +0 -261
- package/dist/server/builder/programmatic-registration.js.map +0 -1
- package/dist/server/fs-routes/co-located-attach.d.ts +0 -32
- package/dist/server/fs-routes/co-located-attach.d.ts.map +0 -1
- package/dist/server/fs-routes/co-located-attach.js +0 -69
- package/dist/server/fs-routes/co-located-attach.js.map +0 -1
- package/dist/server/fs-routes/route-naming.d.ts +0 -61
- package/dist/server/fs-routes/route-naming.d.ts.map +0 -1
- package/dist/server/fs-routes/route-naming.js +0 -191
- package/dist/server/fs-routes/route-naming.js.map +0 -1
- package/dist/ui/server/fs-routes/co-located-attach.d.ts +0 -32
- package/dist/ui/server/fs-routes/co-located-attach.d.ts.map +0 -1
- package/dist/ui/server/fs-routes/route-naming.d.ts +0 -61
- package/dist/ui/server/fs-routes/route-naming.d.ts.map +0 -1
|
@@ -11,7 +11,6 @@
|
|
|
11
11
|
import type { LoggerPort } from '../../ports/outbound/logger.js';
|
|
12
12
|
import type { Context, Interceptor } from '../../types/index.js';
|
|
13
13
|
import type { PolicyEnginePort } from '../../ports/outbound/policy-engine.js';
|
|
14
|
-
import { type CoLocatedAccumulator } from './co-located-accumulator.js';
|
|
15
14
|
import type { PolicyConfig, Principal, ProcedurePolicyConfig } from './types.js';
|
|
16
15
|
export interface PolicyCoverageEntry {
|
|
17
16
|
/** Operation/channel name as registered in the registry. */
|
|
@@ -53,38 +52,7 @@ export interface PolicyBootstrap {
|
|
|
53
52
|
* audit when `defaultMode: 'deny'` is configured.
|
|
54
53
|
*/
|
|
55
54
|
getCoverage: (registered: readonly PolicyCoverageEntry[]) => PolicyCoverageReport;
|
|
56
|
-
/**
|
|
57
|
-
* Accumulator for co-located policies (1.1.60+). Discovery calls
|
|
58
|
-
* `accumulator.add()` for every (route, policy) pair it surfaces; the
|
|
59
|
-
* application path (`applyDiscoveryResult`) calls `flush()` once at
|
|
60
|
-
* the end of a load to materialise one policy per cascade file with
|
|
61
|
-
* the union of route names in `scope.routes`, deduping the N-copy
|
|
62
|
-
* leak that earlier releases produced when a single cascade
|
|
63
|
-
* `_policy.yaml` was attached to N routes (Bug A from 1.1.58).
|
|
64
|
-
*
|
|
65
|
-
* `reset()` is called at the top of a hot reload so the next flush
|
|
66
|
-
* only contains the policies for the routes that survived the
|
|
67
|
-
* reload.
|
|
68
|
-
*/
|
|
69
|
-
coLocatedAccumulator: CoLocatedAccumulator;
|
|
70
55
|
}
|
|
71
|
-
/**
|
|
72
|
-
* Per-server state for the co-located policy pipeline (1.1.60+).
|
|
73
|
-
*
|
|
74
|
-
* The accumulator exists so that a single cascade `_policy.yaml` shared
|
|
75
|
-
* by N routes produces ONE entry in the engine instead of N copies
|
|
76
|
-
* (one per route). Each `add()` records the route name against the
|
|
77
|
-
* policy's `(source, index)` key. `flush()` materialises one policy
|
|
78
|
-
* per key with `scope.routes` set to the union and commits to the
|
|
79
|
-
* engine. `reset()` clears the accumulator without touching the
|
|
80
|
-
* engine — used on hot reload so the next flush reflects only the
|
|
81
|
-
* routes that survived the reload.
|
|
82
|
-
*
|
|
83
|
-
* Imported from `./co-located-accumulator.js`. Re-exported here so
|
|
84
|
-
* existing call sites that imported the type from `bootstrap` keep
|
|
85
|
-
* working.
|
|
86
|
-
*/
|
|
87
|
-
export type { CoLocatedAccumulator } from './co-located-accumulator.js';
|
|
88
56
|
export interface CreatePolicyBootstrapOptions {
|
|
89
57
|
/** Fallback logger if `policy.logger` is not provided. */
|
|
90
58
|
logger: LoggerPort;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/middleware/policy/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;
|
|
1
|
+
{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/middleware/policy/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAChE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uCAAuC,CAAA;AAM7E,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAA;AAEhF,MAAM,WAAW,mBAAmB;IAClC,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAA;IACZ,kFAAkF;IAClF,IAAI,EAAE,MAAM,CAAA;IACZ,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;IAC7B,4CAA4C;IAC5C,KAAK,EAAE,MAAM,CAAA;IACb,2DAA2D;IAC3D,OAAO,EAAE,MAAM,CAAA;IACf,gEAAgE;IAChE,MAAM,EAAE,MAAM,CAAA;IACd,iFAAiF;IACjF,IAAI,EAAE,mBAAmB,EAAE,CAAA;CAC5B;AAED,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,MAAM,EAAE,gBAAgB,CAAA;IACxB,gEAAgE;IAChE,WAAW,EAAE,OAAO,GAAG,MAAM,CAAA;IAC7B,uEAAuE;IACvE,kBAAkB,EAAE,CAAC,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,KAAK,WAAW,CAAA;IACzF,kEAAkE;IAClE,uBAAuB,EAAE,CAAC,aAAa,EAAE,MAAM,KAAK,WAAW,CAAA;IAC/D;;;;OAIG;IACH,gBAAgB,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,CAAC,CAAA;IACtD;;;;OAIG;IACH,WAAW,EAAE,CAAC,UAAU,EAAE,SAAS,mBAAmB,EAAE,KAAK,oBAAoB,CAAA;CAClF;AAED,MAAM,WAAW,4BAA4B;IAC3C,0DAA0D;IAC1D,MAAM,EAAE,UAAU,CAAA;IAClB;;;OAGG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAA;CAC9B;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,YAAY,GAAG,SAAS,EAChC,OAAO,EAAE,4BAA4B,GACpC,eAAe,GAAG,IAAI,CAyFxB"}
|
|
@@ -12,7 +12,6 @@ import { createDefaultEngine } from './engine/index.js';
|
|
|
12
12
|
import { createPolicyInterceptor, createNoPolicyDeclaredInterceptor } from './interceptor.js';
|
|
13
13
|
import { loadPoliciesFromDir, mergePolicies } from './loader.js';
|
|
14
14
|
import { createPrincipalResolver } from './principal/index.js';
|
|
15
|
-
import { createCoLocatedAccumulator, } from './co-located-accumulator.js';
|
|
16
15
|
import { setPolicyProvider } from '../../mcp/resources/index.js';
|
|
17
16
|
/**
|
|
18
17
|
* Wire the entire policy stack from a single call. Returns null if
|
|
@@ -58,15 +57,6 @@ export function createPolicyBootstrap(config, options) {
|
|
|
58
57
|
});
|
|
59
58
|
};
|
|
60
59
|
const noPolicyDeclaredFactory = (procedureName) => createNoPolicyDeclaredInterceptor(procedureName, productionErrorBody);
|
|
61
|
-
// Co-located policy accumulator (1.1.60+). Collects (source, index)
|
|
62
|
-
// → Set<routeName> across the load, then flushes ONE policy per
|
|
63
|
-
// (source, index) with `scope.routes` set to the union of routes.
|
|
64
|
-
// Without this, an unscoped cascade _policy.yaml shared by N
|
|
65
|
-
// routes produced N copies in the engine (Bug A from 1.1.58).
|
|
66
|
-
const coLocatedAccumulator = createCoLocatedAccumulator({
|
|
67
|
-
engine,
|
|
68
|
-
flushLogger: policyLogger,
|
|
69
|
-
});
|
|
70
60
|
const getCoverage = (registered) => {
|
|
71
61
|
const gaps = [];
|
|
72
62
|
let covered = 0;
|
|
@@ -105,7 +95,6 @@ export function createPolicyBootstrap(config, options) {
|
|
|
105
95
|
noPolicyDeclaredFactory,
|
|
106
96
|
resolvePrincipal: async (ctx) => principalResolver(ctx),
|
|
107
97
|
getCoverage,
|
|
108
|
-
coLocatedAccumulator,
|
|
109
98
|
};
|
|
110
99
|
}
|
|
111
100
|
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/middleware/policy/bootstrap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,uBAAuB,EAAE,iCAAiC,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAC9D,OAAO,
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/middleware/policy/bootstrap.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/server/builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"builder.d.ts","sourceRoot":"","sources":["../../src/server/builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAiBH,OAAO,KAAK,EACV,aAAa,EASb,YAAY,EAeb,MAAM,YAAY,CAAA;AA2FnB;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,aAAa,GAAG,YAAY,CA2lDjE"}
|
package/dist/server/builder.js
CHANGED
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { createRegistry } from '../core/registry.js';
|
|
7
7
|
import { createRouter } from '../core/router.js';
|
|
8
|
+
import { getRouterModuleDefinition } from './router-module.js';
|
|
8
9
|
import { createSchemaRegistry } from '../validation/index.js';
|
|
9
10
|
import { createMarkdownDocsState, joinDocsEndpoint, normalizeDocsBasePath, } from '../docs/index.js';
|
|
10
|
-
import { isDevelopment, generateResourceRoutes, } from './fs-routes/index.js';
|
|
11
|
+
import { createRouteInterceptors, isDevelopment, generateResourceRoutes, } from './fs-routes/index.js';
|
|
11
12
|
import { createLogger, configureLogger, getLogger } from '../utils/logger.js';
|
|
12
13
|
import { createPolicyBootstrap } from '../middleware/policy/index.js';
|
|
13
|
-
import { createProcedureBuilder, createStreamBuilder, createEventBuilder, createGroupBuilder, } from './handler-builders.js';
|
|
14
|
+
import { createProcedureBuilder, createStreamBuilder, createEventBuilder, createGroupBuilder, joinHandlerName, } from './handler-builders.js';
|
|
14
15
|
import { createResourceBuilder } from './resource-builder.js';
|
|
15
16
|
import { addCoLocatedPoliciesToEngine, buildCoLocatedAuthzInterceptorsForName, registerDiscoveredHandlers, resolveHooksForProcedure, } from './discovery-utils.js';
|
|
16
17
|
import { createRegistrationService } from './orchestration/registration.js';
|
|
@@ -20,8 +21,6 @@ import { createFrontDoorBootstrap } from './front-door.js';
|
|
|
20
21
|
import { createProtocolFusionDiagnosticsStore } from './protocol-fusion-diagnostics.js';
|
|
21
22
|
import { createDiscoveryBootstrap } from './discovery-bootstrap.js';
|
|
22
23
|
import { createServerLifecycle } from './builder/lifecycle.js';
|
|
23
|
-
import { createGraphQLPolicyBridge, createChannelCoLocatedPolicyEnforcer, } from './builder/policy-bridges.js';
|
|
24
|
-
import { createProgrammaticRegistration } from './builder/programmatic-registration.js';
|
|
25
24
|
import { configureMetrics, configureTracing, createTelemetryState, } from './telemetry-bootstrap.js';
|
|
26
25
|
import { adaptPinoLogger } from '../adapters/outbound/logger/pino.js';
|
|
27
26
|
import { createServerPlanner } from './planner.js';
|
|
@@ -29,7 +28,7 @@ import { createServerRuntimePlanBuilder } from './runtime-plan.js';
|
|
|
29
28
|
import { createHttpNamespace, createWebSocketNamespace, createStreamsNamespace, createRpcNamespace, createTcpNamespace, createUdpNamespace, createGrpcNamespace, } from './builder/protocol-namespaces.js';
|
|
30
29
|
import { applyExtendedProtocolConfig } from './builder/with-protocols.js';
|
|
31
30
|
import { applyResourceMap } from './builder/resources.js';
|
|
32
|
-
import { createEnvelopeInterceptorFromOptions, programmaticSource, } from './builder/metadata.js';
|
|
31
|
+
import { createEnvelopeInterceptorFromOptions, policyMetadataFromRouteMeta, programmaticSource, } from './builder/metadata.js';
|
|
33
32
|
import { createServerPluginRuntime } from './builder/plugin-runtime.js';
|
|
34
33
|
import { createProcedureOperationRegistrar } from './builder/operation-registrar.js';
|
|
35
34
|
const logger = createLogger('server');
|
|
@@ -373,29 +372,11 @@ export function createServer(options) {
|
|
|
373
372
|
// protected from the cleanup pass.
|
|
374
373
|
let discoveredRoutes = new Set();
|
|
375
374
|
function applyDiscoveryResult(result, isReload = true) {
|
|
376
|
-
// Hot reload: drop the previous load's accumulation so the next
|
|
377
|
-
// flush only contains policies for routes that survived. The
|
|
378
|
-
// engine entries themselves are overwritten by the engine's
|
|
379
|
-
// replace-in-place semantics on the next flush.
|
|
380
|
-
if (isReload) {
|
|
381
|
-
policyBootstrap?.coLocatedAccumulator.reset();
|
|
382
|
-
}
|
|
383
375
|
const { discoveredNames } = registrationService.applyDiscoveryResult(result, channelRegistry, restResourceRegistry, tcpHandlers, udpHandlers, isReload ? discoveredRoutes : undefined);
|
|
384
376
|
discoveredRoutes = discoveredNames;
|
|
385
|
-
// GraphQL resources also accumulate their co-located policies via
|
|
386
|
-
// `registerGraphQLResource` → `addCoLocatedPoliciesToEngine`, so
|
|
387
|
-
// they must run BEFORE the flush. Otherwise their accumulated
|
|
388
|
-
// policies are dropped because the flush already happened.
|
|
389
377
|
for (const resource of result.graphqlResources) {
|
|
390
378
|
registerGraphQLResource(resource);
|
|
391
379
|
}
|
|
392
|
-
// Once every route, channel, and GraphQL resource in the load has
|
|
393
|
-
// been registered (and its co-located policies accumulated),
|
|
394
|
-
// materialise the union into the engine. One policy per
|
|
395
|
-
// (source, index), regardless of how many routes referenced it.
|
|
396
|
-
if (policyBootstrap) {
|
|
397
|
-
policyBootstrap.coLocatedAccumulator.flush();
|
|
398
|
-
}
|
|
399
380
|
advanceApiDocumentationRevision();
|
|
400
381
|
}
|
|
401
382
|
const previewContext = serverPlanner.createPreviewContext({
|
|
@@ -460,6 +441,53 @@ export function createServer(options) {
|
|
|
460
441
|
})),
|
|
461
442
|
})
|
|
462
443
|
: undefined;
|
|
444
|
+
function createGraphQLPolicyBridge(bootstrap) {
|
|
445
|
+
if (!bootstrap)
|
|
446
|
+
return undefined;
|
|
447
|
+
return {
|
|
448
|
+
async evaluate(ctx, authz, value, args, parent) {
|
|
449
|
+
const principal = await bootstrap.resolvePrincipal(ctx);
|
|
450
|
+
const rawResource = await authz.resource(value, args, ctx, parent);
|
|
451
|
+
const resources = rawResource == null
|
|
452
|
+
? [{ type: '*', id: '*', tenantId: principal.tenantId }]
|
|
453
|
+
: Array.isArray(rawResource)
|
|
454
|
+
? rawResource
|
|
455
|
+
: [rawResource];
|
|
456
|
+
if (resources.length === 0) {
|
|
457
|
+
resources.push({ type: '*', id: '*', tenantId: principal.tenantId });
|
|
458
|
+
}
|
|
459
|
+
const protocol = ctx.protocol;
|
|
460
|
+
const protocolValue = typeof protocol === 'string' ? protocol : 'graphql';
|
|
461
|
+
let lastDecision;
|
|
462
|
+
if (authz.mode === 'any') {
|
|
463
|
+
for (const resource of resources) {
|
|
464
|
+
const decision = await bootstrap.engine.evaluate({
|
|
465
|
+
principal,
|
|
466
|
+
action: authz.action,
|
|
467
|
+
resource,
|
|
468
|
+
protocol: protocolValue,
|
|
469
|
+
});
|
|
470
|
+
lastDecision = decision;
|
|
471
|
+
if (decision.allowed)
|
|
472
|
+
return decision;
|
|
473
|
+
}
|
|
474
|
+
return lastDecision;
|
|
475
|
+
}
|
|
476
|
+
for (const resource of resources) {
|
|
477
|
+
const decision = await bootstrap.engine.evaluate({
|
|
478
|
+
principal,
|
|
479
|
+
action: authz.action,
|
|
480
|
+
resource,
|
|
481
|
+
protocol: protocolValue,
|
|
482
|
+
});
|
|
483
|
+
lastDecision = decision;
|
|
484
|
+
if (!decision.allowed)
|
|
485
|
+
return decision;
|
|
486
|
+
}
|
|
487
|
+
return lastDecision;
|
|
488
|
+
},
|
|
489
|
+
};
|
|
490
|
+
}
|
|
463
491
|
const serverLifecycle = createServerLifecycle({
|
|
464
492
|
logger,
|
|
465
493
|
state: serverState,
|
|
@@ -495,7 +523,20 @@ export function createServer(options) {
|
|
|
495
523
|
getWsSubscribeHandler: () => wsSubscribeHandler,
|
|
496
524
|
getWsMessageHandler: () => wsMessageHandler,
|
|
497
525
|
getWsUnsubscribeHandler: () => wsUnsubscribeHandler,
|
|
498
|
-
channelCoLocatedPolicyEnforcer:
|
|
526
|
+
channelCoLocatedPolicyEnforcer: policyBootstrap
|
|
527
|
+
? async (channelName, policies, ctx) => {
|
|
528
|
+
addCoLocatedPoliciesToEngine(channelName, policies, { bootstrap: policyBootstrap }, undefined, { route: channelName });
|
|
529
|
+
const principal = await policyBootstrap.resolvePrincipal(ctx);
|
|
530
|
+
const ctxProtocol = ctx.protocol;
|
|
531
|
+
const decision = await policyBootstrap.engine.evaluate({
|
|
532
|
+
principal,
|
|
533
|
+
action: channelName,
|
|
534
|
+
resource: { type: 'channel', id: channelName, tenantId: principal.tenantId },
|
|
535
|
+
protocol: typeof ctxProtocol === 'string' ? ctxProtocol : 'websocket',
|
|
536
|
+
});
|
|
537
|
+
return decision.allowed;
|
|
538
|
+
}
|
|
539
|
+
: undefined,
|
|
499
540
|
graphqlPolicyBridge: createGraphQLPolicyBridge(policyBootstrap),
|
|
500
541
|
});
|
|
501
542
|
/**
|
|
@@ -542,28 +583,6 @@ export function createServer(options) {
|
|
|
542
583
|
},
|
|
543
584
|
})
|
|
544
585
|
: undefined;
|
|
545
|
-
// Programmatic registration methods (mount + addX + registerHandler)
|
|
546
|
-
// are produced by a factory and spread into the server object below.
|
|
547
|
-
// `getServer` is a thunk because the methods return `server` for
|
|
548
|
-
// chaining, and `server` is defined immediately after this call.
|
|
549
|
-
const programmaticRegistration = createProgrammaticRegistration({
|
|
550
|
-
registry,
|
|
551
|
-
schemaRegistry,
|
|
552
|
-
globalInterceptors,
|
|
553
|
-
normalizeInterceptors,
|
|
554
|
-
policyInterceptorFactory,
|
|
555
|
-
policyDefaultMode,
|
|
556
|
-
noPolicyDeclaredFactory,
|
|
557
|
-
recordOperationRegistration,
|
|
558
|
-
registerProcedureOperation,
|
|
559
|
-
registerChannel,
|
|
560
|
-
registerRestResource,
|
|
561
|
-
registerResource,
|
|
562
|
-
registerTcpHandler,
|
|
563
|
-
registerUdpHandler,
|
|
564
|
-
logger,
|
|
565
|
-
getServer: () => server,
|
|
566
|
-
});
|
|
567
586
|
const server = {
|
|
568
587
|
// === Authorization (policies) ===
|
|
569
588
|
policy: policyNamespace,
|
|
@@ -928,7 +947,247 @@ export function createServer(options) {
|
|
|
928
947
|
group(prefix) {
|
|
929
948
|
return createGroupBuilder(registry, schemaRegistry, prefix, [...globalInterceptors], hooksResolver, envelopeInterceptor);
|
|
930
949
|
},
|
|
931
|
-
|
|
950
|
+
mount(prefix, module, options = {}) {
|
|
951
|
+
const definition = getRouterModuleDefinition(module);
|
|
952
|
+
const mountInterceptors = options.interceptors ?? [];
|
|
953
|
+
for (const route of definition.routes) {
|
|
954
|
+
const fullName = joinHandlerName(prefix, route.name);
|
|
955
|
+
const routeSchema = route.kind === 'procedure' ? route.schema : undefined;
|
|
956
|
+
// Synthesize policy interceptor at mount-time using the host server's
|
|
957
|
+
// factory. Module routes carry `route.authz` (resolved from per-procedure
|
|
958
|
+
// .authz() or module's defaultAuthz). When defaultMode is 'deny' and
|
|
959
|
+
// no authz was declared, inject the no-policy-declared deny.
|
|
960
|
+
const authzInterceptors = [];
|
|
961
|
+
if (route.kind === 'procedure') {
|
|
962
|
+
if (route.authz && policyInterceptorFactory) {
|
|
963
|
+
authzInterceptors.push(policyInterceptorFactory(fullName, route.authz));
|
|
964
|
+
}
|
|
965
|
+
else if (!route.authz &&
|
|
966
|
+
policyDefaultMode === 'deny' &&
|
|
967
|
+
noPolicyDeclaredFactory) {
|
|
968
|
+
authzInterceptors.push(noPolicyDeclaredFactory(fullName));
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
const interceptors = normalizeInterceptors([
|
|
972
|
+
...globalInterceptors,
|
|
973
|
+
...mountInterceptors,
|
|
974
|
+
...route.moduleInterceptors,
|
|
975
|
+
...authzInterceptors,
|
|
976
|
+
...route.interceptors,
|
|
977
|
+
], routeSchema);
|
|
978
|
+
if (route.schema) {
|
|
979
|
+
schemaRegistry.register(fullName, route.schema);
|
|
980
|
+
}
|
|
981
|
+
if (route.kind === 'procedure') {
|
|
982
|
+
registry.procedure(fullName, route.handler, {
|
|
983
|
+
summary: route.summary,
|
|
984
|
+
description: route.description,
|
|
985
|
+
tags: route.tags,
|
|
986
|
+
graphql: route.graphql,
|
|
987
|
+
httpPath: route.httpPath,
|
|
988
|
+
httpMethod: route.httpMethod,
|
|
989
|
+
jsonrpc: route.jsonrpc,
|
|
990
|
+
grpc: route.grpc,
|
|
991
|
+
authz: route.authz,
|
|
992
|
+
interceptors: interceptors.length > 0 ? interceptors : undefined,
|
|
993
|
+
});
|
|
994
|
+
}
|
|
995
|
+
else if (route.kind === 'stream') {
|
|
996
|
+
registry.stream(fullName, route.handler, {
|
|
997
|
+
description: route.description,
|
|
998
|
+
direction: route.streamDirection,
|
|
999
|
+
interceptors: interceptors.length > 0 ? interceptors : undefined,
|
|
1000
|
+
});
|
|
1001
|
+
}
|
|
1002
|
+
else {
|
|
1003
|
+
registry.event(fullName, route.handler, {
|
|
1004
|
+
description: route.description,
|
|
1005
|
+
delivery: route.delivery,
|
|
1006
|
+
retryPolicy: route.retryPolicy,
|
|
1007
|
+
deduplicationWindow: route.deduplicationWindow,
|
|
1008
|
+
interceptors: interceptors.length > 0 ? interceptors : undefined,
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
return server;
|
|
1013
|
+
},
|
|
1014
|
+
// === Programmatic Registration ===
|
|
1015
|
+
addProcedure(input) {
|
|
1016
|
+
// Normalize input (LoadedRoute has 'handler' directly, AddProcedureInput also has 'handler')
|
|
1017
|
+
const name = input.name;
|
|
1018
|
+
const handler = input.handler;
|
|
1019
|
+
const inputSchema = input.inputSchema;
|
|
1020
|
+
const outputSchema = input.outputSchema;
|
|
1021
|
+
const summary = 'meta' in input ? input.meta?.summary : input.summary;
|
|
1022
|
+
const description = 'meta' in input ? input.meta?.description : input.description;
|
|
1023
|
+
const tags = 'meta' in input ? input.meta?.tags : input.tags;
|
|
1024
|
+
const graphql = 'meta' in input ? input.meta?.graphql : input.graphql;
|
|
1025
|
+
const httpPath = 'meta' in input ? input.meta?.httpPath : input.httpPath;
|
|
1026
|
+
const httpMethod = 'meta' in input ? input.meta?.httpMethod : input.httpMethod;
|
|
1027
|
+
const jsonrpc = 'meta' in input ? input.meta?.jsonrpc : input.jsonrpc;
|
|
1028
|
+
const grpc = 'meta' in input ? input.meta?.grpc : input.grpc;
|
|
1029
|
+
const policies = 'meta' in input
|
|
1030
|
+
? policyMetadataFromRouteMeta(input.meta)
|
|
1031
|
+
: input.policies;
|
|
1032
|
+
const routeInterceptors = 'middlewares' in input ? createRouteInterceptors(input) : [];
|
|
1033
|
+
const inputInterceptors = 'interceptors' in input ? input.interceptors ?? [] : [];
|
|
1034
|
+
registerProcedureOperation({
|
|
1035
|
+
name,
|
|
1036
|
+
handler,
|
|
1037
|
+
inputSchema,
|
|
1038
|
+
outputSchema,
|
|
1039
|
+
summary,
|
|
1040
|
+
description,
|
|
1041
|
+
tags,
|
|
1042
|
+
graphql,
|
|
1043
|
+
httpPath,
|
|
1044
|
+
httpMethod,
|
|
1045
|
+
jsonrpc,
|
|
1046
|
+
grpc,
|
|
1047
|
+
policies,
|
|
1048
|
+
interceptors: [...routeInterceptors, ...inputInterceptors],
|
|
1049
|
+
registration: {
|
|
1050
|
+
source: 'filePath' in input
|
|
1051
|
+
? { kind: 'discovery', location: input.filePath }
|
|
1052
|
+
: programmaticSource(),
|
|
1053
|
+
},
|
|
1054
|
+
});
|
|
1055
|
+
logger.debug({ name }, 'Added procedure');
|
|
1056
|
+
return server;
|
|
1057
|
+
},
|
|
1058
|
+
addStream(input) {
|
|
1059
|
+
const name = input.name;
|
|
1060
|
+
const handler = input.handler;
|
|
1061
|
+
const inputSchema = input.inputSchema;
|
|
1062
|
+
const outputSchema = input.outputSchema;
|
|
1063
|
+
const description = 'meta' in input ? input.meta?.description : input.description;
|
|
1064
|
+
const direction = 'meta' in input ? input.meta?.direction : input.direction;
|
|
1065
|
+
const policies = 'meta' in input
|
|
1066
|
+
? policyMetadataFromRouteMeta(input.meta)
|
|
1067
|
+
: input.policies;
|
|
1068
|
+
const routeInterceptors = 'middlewares' in input ? createRouteInterceptors(input) : [];
|
|
1069
|
+
const inputInterceptors = 'interceptors' in input ? input.interceptors ?? [] : [];
|
|
1070
|
+
const interceptors = [...globalInterceptors, ...routeInterceptors, ...inputInterceptors];
|
|
1071
|
+
if (inputSchema || outputSchema) {
|
|
1072
|
+
const schema = {};
|
|
1073
|
+
if (inputSchema)
|
|
1074
|
+
schema.input = inputSchema;
|
|
1075
|
+
if (outputSchema)
|
|
1076
|
+
schema.output = outputSchema;
|
|
1077
|
+
schemaRegistry.register(name, schema);
|
|
1078
|
+
}
|
|
1079
|
+
registry.stream(name, handler, {
|
|
1080
|
+
description,
|
|
1081
|
+
direction,
|
|
1082
|
+
policies,
|
|
1083
|
+
interceptors: interceptors.length > 0 ? interceptors : undefined,
|
|
1084
|
+
});
|
|
1085
|
+
recordOperationRegistration(name, {
|
|
1086
|
+
source: 'filePath' in input
|
|
1087
|
+
? { kind: 'discovery', location: input.filePath }
|
|
1088
|
+
: programmaticSource(),
|
|
1089
|
+
});
|
|
1090
|
+
logger.debug({ name }, 'Added stream');
|
|
1091
|
+
return server;
|
|
1092
|
+
},
|
|
1093
|
+
addEvent(input) {
|
|
1094
|
+
const name = input.name;
|
|
1095
|
+
const handler = input.handler;
|
|
1096
|
+
const inputSchema = input.inputSchema;
|
|
1097
|
+
const description = 'meta' in input ? input.meta?.description : input.description;
|
|
1098
|
+
const delivery = 'meta' in input ? input.meta?.delivery : input.delivery;
|
|
1099
|
+
const retryPolicy = 'meta' in input ? input.meta?.retryPolicy : input.retryPolicy;
|
|
1100
|
+
const deduplicationWindow = 'meta' in input ? input.meta?.deduplicationWindow : input.deduplicationWindow;
|
|
1101
|
+
const policies = 'meta' in input
|
|
1102
|
+
? policyMetadataFromRouteMeta(input.meta)
|
|
1103
|
+
: input.policies;
|
|
1104
|
+
const routeInterceptors = 'middlewares' in input ? createRouteInterceptors(input) : [];
|
|
1105
|
+
const inputInterceptors = 'interceptors' in input ? input.interceptors ?? [] : [];
|
|
1106
|
+
const interceptors = [...globalInterceptors, ...routeInterceptors, ...inputInterceptors];
|
|
1107
|
+
if (inputSchema) {
|
|
1108
|
+
schemaRegistry.register(name, { input: inputSchema });
|
|
1109
|
+
}
|
|
1110
|
+
registry.event(name, handler, {
|
|
1111
|
+
description,
|
|
1112
|
+
delivery,
|
|
1113
|
+
retryPolicy,
|
|
1114
|
+
deduplicationWindow,
|
|
1115
|
+
policies,
|
|
1116
|
+
interceptors: interceptors.length > 0 ? interceptors : undefined,
|
|
1117
|
+
});
|
|
1118
|
+
recordOperationRegistration(name, {
|
|
1119
|
+
source: 'filePath' in input
|
|
1120
|
+
? { kind: 'discovery', location: input.filePath }
|
|
1121
|
+
: programmaticSource(),
|
|
1122
|
+
});
|
|
1123
|
+
logger.debug({ name }, 'Added event');
|
|
1124
|
+
return server;
|
|
1125
|
+
},
|
|
1126
|
+
addChannel(channel) {
|
|
1127
|
+
registerChannel(channel);
|
|
1128
|
+
logger.debug({ name: channel.name }, 'Channel configuration registered');
|
|
1129
|
+
return server;
|
|
1130
|
+
},
|
|
1131
|
+
addRest(resource) {
|
|
1132
|
+
registerRestResource(resource);
|
|
1133
|
+
return server;
|
|
1134
|
+
},
|
|
1135
|
+
addResource(resource) {
|
|
1136
|
+
registerResource(resource);
|
|
1137
|
+
return server;
|
|
1138
|
+
},
|
|
1139
|
+
addTcpHandler(handler) {
|
|
1140
|
+
registerTcpHandler(handler);
|
|
1141
|
+
return server;
|
|
1142
|
+
},
|
|
1143
|
+
addUdpHandler(handler) {
|
|
1144
|
+
registerUdpHandler(handler);
|
|
1145
|
+
return server;
|
|
1146
|
+
},
|
|
1147
|
+
registerHandler(name, handler, opts) {
|
|
1148
|
+
const kind = opts?.kind ?? 'procedure';
|
|
1149
|
+
if (kind === 'stream') {
|
|
1150
|
+
return server.addStream({
|
|
1151
|
+
name,
|
|
1152
|
+
handler: handler,
|
|
1153
|
+
inputSchema: opts?.input,
|
|
1154
|
+
outputSchema: opts?.output,
|
|
1155
|
+
direction: opts?.direction,
|
|
1156
|
+
description: opts?.description,
|
|
1157
|
+
policies: opts?.policies,
|
|
1158
|
+
interceptors: opts?.interceptors,
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
if (kind === 'event') {
|
|
1162
|
+
return server.addEvent({
|
|
1163
|
+
name,
|
|
1164
|
+
handler: handler,
|
|
1165
|
+
inputSchema: opts?.input,
|
|
1166
|
+
description: opts?.description,
|
|
1167
|
+
delivery: opts?.delivery,
|
|
1168
|
+
retryPolicy: opts?.retryPolicy,
|
|
1169
|
+
deduplicationWindow: opts?.deduplicationWindow,
|
|
1170
|
+
policies: opts?.policies,
|
|
1171
|
+
interceptors: opts?.interceptors,
|
|
1172
|
+
});
|
|
1173
|
+
}
|
|
1174
|
+
return server.addProcedure({
|
|
1175
|
+
name,
|
|
1176
|
+
handler: handler,
|
|
1177
|
+
inputSchema: opts?.input,
|
|
1178
|
+
outputSchema: opts?.output,
|
|
1179
|
+
summary: opts?.summary,
|
|
1180
|
+
description: opts?.description,
|
|
1181
|
+
tags: opts?.tags,
|
|
1182
|
+
graphql: opts?.graphql,
|
|
1183
|
+
httpPath: opts?.httpPath,
|
|
1184
|
+
httpMethod: opts?.httpMethod,
|
|
1185
|
+
jsonrpc: opts?.jsonrpc,
|
|
1186
|
+
grpc: opts?.grpc,
|
|
1187
|
+
policies: opts?.policies,
|
|
1188
|
+
interceptors: opts?.interceptors,
|
|
1189
|
+
});
|
|
1190
|
+
},
|
|
932
1191
|
addDiscovery(result) {
|
|
933
1192
|
// `addDiscovery` accepts a complete view of the discovered surface.
|
|
934
1193
|
// Whether this is the initial load or a subsequent re-application
|