@bleedingdev/modern-js-bff-core 3.9.0-ultramodern.2 → 3.9.0-ultramodern.21
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/cjs/client/generateClient.js +67 -138
- package/dist/cjs/index.js +24 -114
- package/dist/cjs/router/index.js +7 -5
- package/dist/cjs/utils/index.js +11 -21
- package/dist/esm/client/generateClient.mjs +65 -139
- package/dist/esm/index.mjs +1 -5
- package/dist/esm/router/index.mjs +7 -5
- package/dist/esm/utils/index.mjs +0 -1
- package/dist/esm-node/client/generateClient.mjs +65 -139
- package/dist/esm-node/index.mjs +1 -5
- package/dist/esm-node/router/index.mjs +7 -5
- package/dist/esm-node/utils/index.mjs +0 -1
- package/dist/types/client/generateClient.d.ts +24 -1
- package/dist/types/index.d.ts +1 -5
- package/dist/types/utils/index.d.ts +0 -1
- package/package.json +10 -19
- package/dist/cjs/adapter-kit/index.js +0 -144
- package/dist/cjs/adapter-kit/parity-scenarios/cross-project-denial.js +0 -55
- package/dist/cjs/adapter-kit/parity-scenarios/envelope.js +0 -128
- package/dist/cjs/adapter-kit/parity-scenarios/operation-context.js +0 -152
- package/dist/cjs/adapter-kit/parity-scenarios/schema.js +0 -109
- package/dist/cjs/adapter-kit/parity-scenarios/shared.js +0 -71
- package/dist/cjs/adapter-kit/parity.js +0 -204
- package/dist/cjs/security/crossProjectPolicy.js +0 -309
- package/dist/cjs/security/operationContracts.js +0 -183
- package/dist/cjs/security/resolveCrossProjectPolicy.js +0 -65
- package/dist/cjs/utils/alias.js +0 -112
- package/dist/esm/adapter-kit/index.mjs +0 -79
- package/dist/esm/adapter-kit/parity-scenarios/cross-project-denial.mjs +0 -17
- package/dist/esm/adapter-kit/parity-scenarios/envelope.mjs +0 -90
- package/dist/esm/adapter-kit/parity-scenarios/operation-context.mjs +0 -111
- package/dist/esm/adapter-kit/parity-scenarios/schema.mjs +0 -71
- package/dist/esm/adapter-kit/parity-scenarios/shared.mjs +0 -21
- package/dist/esm/adapter-kit/parity.mjs +0 -148
- package/dist/esm/security/crossProjectPolicy.mjs +0 -259
- package/dist/esm/security/operationContracts.mjs +0 -127
- package/dist/esm/security/resolveCrossProjectPolicy.mjs +0 -27
- package/dist/esm/utils/alias.mjs +0 -57
- package/dist/esm-node/adapter-kit/index.mjs +0 -80
- package/dist/esm-node/adapter-kit/parity-scenarios/cross-project-denial.mjs +0 -18
- package/dist/esm-node/adapter-kit/parity-scenarios/envelope.mjs +0 -91
- package/dist/esm-node/adapter-kit/parity-scenarios/operation-context.mjs +0 -112
- package/dist/esm-node/adapter-kit/parity-scenarios/schema.mjs +0 -72
- package/dist/esm-node/adapter-kit/parity-scenarios/shared.mjs +0 -22
- package/dist/esm-node/adapter-kit/parity.mjs +0 -149
- package/dist/esm-node/security/crossProjectPolicy.mjs +0 -260
- package/dist/esm-node/security/operationContracts.mjs +0 -130
- package/dist/esm-node/security/resolveCrossProjectPolicy.mjs +0 -28
- package/dist/esm-node/utils/alias.mjs +0 -58
- package/dist/types/adapter-kit/index.d.ts +0 -90
- package/dist/types/adapter-kit/parity-scenarios/cross-project-denial.d.ts +0 -2
- package/dist/types/adapter-kit/parity-scenarios/envelope.d.ts +0 -2
- package/dist/types/adapter-kit/parity-scenarios/operation-context.d.ts +0 -3
- package/dist/types/adapter-kit/parity-scenarios/schema.d.ts +0 -2
- package/dist/types/adapter-kit/parity-scenarios/shared.d.ts +0 -32
- package/dist/types/adapter-kit/parity.d.ts +0 -43
- package/dist/types/security/crossProjectPolicy.d.ts +0 -110
- package/dist/types/security/operationContracts.d.ts +0 -84
- package/dist/types/security/resolveCrossProjectPolicy.d.ts +0 -39
- package/dist/types/utils/alias.d.ts +0 -7
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-project BFF policy evaluator.
|
|
3
|
-
*
|
|
4
|
-
* THREAT MODEL — read before relying on this module:
|
|
5
|
-
*
|
|
6
|
-
* Every header this evaluator inspects (envelope, operation id, operation
|
|
7
|
-
* context details) is constructed by the CLIENT from public, open-source
|
|
8
|
-
* formats. Without an out-of-band identity binding the checks below are a
|
|
9
|
-
* version-skew and misconfiguration gate, not an authentication or
|
|
10
|
-
* authorization boundary: any caller can echo an allowed `requestId` and a
|
|
11
|
-
* matching operation context.
|
|
12
|
-
*
|
|
13
|
-
* To use `allowedNamespaces`, supply
|
|
14
|
-
* {@link CrossProjectPolicyConfig.verifyProducerIdentity}: a server-side
|
|
15
|
-
* hook that derives the producer namespace from a VERIFIED channel (mTLS
|
|
16
|
-
* peer identity, gateway-authenticated JWT claims, service-mesh headers
|
|
17
|
-
* stripped at the edge, ...). Requests fail closed when a namespace allowlist
|
|
18
|
-
* is configured without this hook unless `allowClientAssertedNamespace` is
|
|
19
|
-
* explicitly enabled. That escape hatch keeps legacy local/demo ergonomics:
|
|
20
|
-
* the client-asserted namespace must match the allowlist. When the hook is
|
|
21
|
-
* present, the client-asserted namespace must match the verified namespace
|
|
22
|
-
* and the allowlist is checked against the verified value.
|
|
23
|
-
*
|
|
24
|
-
* Client-side counterparts in `@modern-js/create-request` (identity binding,
|
|
25
|
-
* operation contract validation) are developer-experience aids that fail
|
|
26
|
-
* fast in well-behaved clients; they protect nothing against a malicious
|
|
27
|
-
* caller.
|
|
28
|
-
*/
|
|
29
|
-
export declare const BFF_ENVELOPE_HEADER = "x-modernjs-bff-envelope";
|
|
30
|
-
export declare const BFF_OPERATION_CONTEXT_HEADER = "x-operation-id";
|
|
31
|
-
export declare const BFF_OPERATION_CONTEXT_DETAIL_HEADER = "x-modernjs-bff-operation-context";
|
|
32
|
-
export type CrossProjectOperationContract = {
|
|
33
|
-
schemaHash?: string;
|
|
34
|
-
operationVersion?: number;
|
|
35
|
-
operationId?: string;
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Request facts observed by the server adapter rather than asserted by the
|
|
39
|
-
* client. `routePath` is the matched route template when the router exposes
|
|
40
|
-
* one (for example `/api/customers/:id`), not the client-provided detail.
|
|
41
|
-
*/
|
|
42
|
-
export type CrossProjectRequestObservation = {
|
|
43
|
-
method: string;
|
|
44
|
-
routePath: string;
|
|
45
|
-
};
|
|
46
|
-
export type CrossProjectRequestTarget = {
|
|
47
|
-
method: string;
|
|
48
|
-
pathname: string;
|
|
49
|
-
};
|
|
50
|
-
export type CrossProjectPolicyViolationReason = 'missing_envelope' | 'invalid_envelope' | 'missing_request_id' | 'namespace_not_allowed' | 'missing_operation_context' | 'operation_context_mismatch' | 'missing_operation_context_details' | 'invalid_operation_context_details' | 'operation_context_details_request_id_mismatch' | 'missing_operation_schema_hash' | 'missing_operation_version' | 'unknown_operation_contract' | 'operation_schema_hash_mismatch' | 'operation_version_mismatch' | 'producer_identity_mismatch';
|
|
51
|
-
export type CrossProjectPolicyViolation = {
|
|
52
|
-
code: 'BFF_CROSS_PROJECT_POLICY_DENIED';
|
|
53
|
-
reason: CrossProjectPolicyViolationReason;
|
|
54
|
-
message: string;
|
|
55
|
-
status: number;
|
|
56
|
-
};
|
|
57
|
-
export interface CrossProjectPolicyConfig {
|
|
58
|
-
enabled?: boolean;
|
|
59
|
-
requireEnvelope?: boolean;
|
|
60
|
-
requireOperationContext?: boolean;
|
|
61
|
-
requireOperationContextDetails?: boolean;
|
|
62
|
-
requireOperationSchemaHash?: boolean;
|
|
63
|
-
requireOperationVersion?: boolean;
|
|
64
|
-
allowedNamespaces?: string[];
|
|
65
|
-
/**
|
|
66
|
-
* Explicit local/demo escape hatch for legacy clients that only provide
|
|
67
|
-
* client-built requestId namespaces. Defaults to false. Enabling this keeps
|
|
68
|
-
* `allowedNamespaces` advisory and must not be used as authorization.
|
|
69
|
-
*/
|
|
70
|
-
allowClientAssertedNamespace?: boolean;
|
|
71
|
-
envelopeHeader?: string;
|
|
72
|
-
operationContextHeader?: string;
|
|
73
|
-
operationContextDetailHeader?: string;
|
|
74
|
-
expectedOperationContracts?: Record<string, CrossProjectOperationContract>;
|
|
75
|
-
allowUnknownOperations?: boolean;
|
|
76
|
-
denyStatus?: number;
|
|
77
|
-
/**
|
|
78
|
-
* Server-side hook binding producer namespace to VERIFIED identity
|
|
79
|
-
* channel (mTLS peer, gateway-authenticated JWT, mesh identity headers).
|
|
80
|
-
*
|
|
81
|
-
* When provided, the namespace asserted by the client envelope must match
|
|
82
|
-
* the namespace returned by this hook, and `allowedNamespaces` is checked
|
|
83
|
-
* against the verified value instead of the client-asserted one. Returning
|
|
84
|
-
* `undefined` (identity could not be verified) denies the request.
|
|
85
|
-
*
|
|
86
|
-
* By default, `allowedNamespaces` requires this hook and fails closed
|
|
87
|
-
* without it. Set `allowClientAssertedNamespace` only for local/demo
|
|
88
|
-
* ergonomics where advisory client-asserted namespace checks are acceptable.
|
|
89
|
-
*/
|
|
90
|
-
verifyProducerIdentity?: (headers: Record<string, unknown>) => string | undefined;
|
|
91
|
-
}
|
|
92
|
-
/** Serializable, fully-defaulted policy accepted by edge dispatchers. */
|
|
93
|
-
export type NormalizedCrossProjectPolicy = CrossProjectPolicyConfig & {
|
|
94
|
-
enabled: boolean;
|
|
95
|
-
requireEnvelope: boolean;
|
|
96
|
-
requireOperationContext: boolean;
|
|
97
|
-
requireOperationContextDetails: boolean;
|
|
98
|
-
requireOperationSchemaHash: boolean;
|
|
99
|
-
requireOperationVersion: boolean;
|
|
100
|
-
allowUnknownOperations: boolean;
|
|
101
|
-
expectedOperationContracts: Record<string, CrossProjectOperationContract>;
|
|
102
|
-
};
|
|
103
|
-
/**
|
|
104
|
-
* Resolves a concrete adapter request to the server-owned route template in
|
|
105
|
-
* the operation contract map. Effect receives requests after its BFF mount
|
|
106
|
-
* prefix has been stripped, so leading literal route segments may be mount
|
|
107
|
-
* prefixes. Ambiguous matches fail closed by retaining the concrete path.
|
|
108
|
-
*/
|
|
109
|
-
export declare const resolveCrossProjectRequestObservation: (request: CrossProjectRequestTarget, policy: Pick<CrossProjectPolicyConfig, 'expectedOperationContracts'>) => CrossProjectRequestObservation | undefined;
|
|
110
|
-
export declare const evaluateCrossProjectPolicy: (headers: Record<string, unknown>, policy?: CrossProjectPolicyConfig, observedRequest?: CrossProjectRequestObservation) => CrossProjectPolicyViolation | null;
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import 'reflect-metadata';
|
|
2
|
-
import type { ApiHandler } from '../router/types.js';
|
|
3
|
-
export type OperationContractEntry = {
|
|
4
|
-
name: string;
|
|
5
|
-
httpMethod: string;
|
|
6
|
-
routePath: string;
|
|
7
|
-
};
|
|
8
|
-
export type OperationContractDefinition = {
|
|
9
|
-
requestId: string;
|
|
10
|
-
operationVersion: number;
|
|
11
|
-
schemaHash: string;
|
|
12
|
-
method: string;
|
|
13
|
-
routePath: string;
|
|
14
|
-
operationId: string;
|
|
15
|
-
handlerName: string;
|
|
16
|
-
filename?: string;
|
|
17
|
-
};
|
|
18
|
-
export type OperationContractMap = Record<string, OperationContractDefinition>;
|
|
19
|
-
export declare const DEFAULT_OPERATION_VERSION = 1;
|
|
20
|
-
/**
|
|
21
|
-
* Derives the operation version from a producer package version: the semver
|
|
22
|
-
* major is the contract version, so consumers regenerated against an older
|
|
23
|
-
* producer major fail the `operation_version_mismatch` gate instead of
|
|
24
|
-
* silently calling an incompatible API.
|
|
25
|
-
*
|
|
26
|
-
* Falls back to {@link DEFAULT_OPERATION_VERSION} when no parseable version
|
|
27
|
-
* is available.
|
|
28
|
-
*/
|
|
29
|
-
export declare const deriveOperationVersion: (packageVersion?: unknown) => number;
|
|
30
|
-
/**
|
|
31
|
-
* Serializes the zod input schemas attached to an operator-decorated handler
|
|
32
|
-
* (`Data`/`Query`/`Params`/`Headers`/`Upload` metadata) into JSON-schema
|
|
33
|
-
* documents. Returns `undefined` for handlers without schema metadata
|
|
34
|
-
* (plain handlers, farrow schema-mode handlers).
|
|
35
|
-
*/
|
|
36
|
-
export declare const serializeOperationSchemas: (handler: ApiHandler | undefined) => Record<string, unknown> | undefined;
|
|
37
|
-
export type OperationContractHashInput = OperationContractEntry & {
|
|
38
|
-
/** Serialized schema documents; omit for schema-less operations. */
|
|
39
|
-
schemas?: Record<string, unknown> | undefined;
|
|
40
|
-
};
|
|
41
|
-
/**
|
|
42
|
-
* Per-operation contract hash. The hash covers the operation identity
|
|
43
|
-
* (name, method, route, producer requestId) plus the serialized input
|
|
44
|
-
* schemas, so:
|
|
45
|
-
*
|
|
46
|
-
* - changing an input schema changes the hash of exactly that operation;
|
|
47
|
-
* - reordering routes or adding unrelated operations never rotates the hash
|
|
48
|
-
* of other operations (each operation is hashed independently).
|
|
49
|
-
*/
|
|
50
|
-
export declare const createOperationContractHash: (operation: OperationContractHashInput, requestId: string) => string;
|
|
51
|
-
export declare const createOperationEntries: (handlers: Array<{
|
|
52
|
-
name: string;
|
|
53
|
-
httpMethod: string;
|
|
54
|
-
routePath: string;
|
|
55
|
-
}>) => OperationContractEntry[];
|
|
56
|
-
/**
|
|
57
|
-
* Aggregate hash over a set of per-operation contract hashes. Used for the
|
|
58
|
-
* module-level `operationSchemaHash` manifest export; stable across route
|
|
59
|
-
* reordering because the per-operation hashes are sorted before hashing.
|
|
60
|
-
*/
|
|
61
|
-
export declare const createOperationSchemaHash: (operationEntries: Array<OperationContractEntry & {
|
|
62
|
-
schemaHash?: string;
|
|
63
|
-
}>, requestId: string) => string;
|
|
64
|
-
export type OperationContractSource = {
|
|
65
|
-
name: string;
|
|
66
|
-
httpMethod: string;
|
|
67
|
-
routePath: string;
|
|
68
|
-
filename?: string;
|
|
69
|
-
/**
|
|
70
|
-
* Optional handler function used to serialize schema metadata. Sources
|
|
71
|
-
* without a handler (e.g. reflected Effect HttpApi endpoints) hash the
|
|
72
|
-
* route identity only.
|
|
73
|
-
*/
|
|
74
|
-
handler?: ApiHandler;
|
|
75
|
-
};
|
|
76
|
-
export declare const buildOperationContractMap: ({ handlers, requestId, operationVersion, }: {
|
|
77
|
-
handlers: OperationContractSource[];
|
|
78
|
-
requestId?: string;
|
|
79
|
-
/**
|
|
80
|
-
* Producer contract version, usually `deriveOperationVersion(pkg.version)`.
|
|
81
|
-
* Defaults to {@link DEFAULT_OPERATION_VERSION}.
|
|
82
|
-
*/
|
|
83
|
-
operationVersion?: number;
|
|
84
|
-
}) => OperationContractMap;
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import type { CrossProjectPolicyConfig, NormalizedCrossProjectPolicy } from './crossProjectPolicy.js';
|
|
2
|
-
import { type OperationContractSource } from './operationContracts.js';
|
|
3
|
-
/**
|
|
4
|
-
* Runtime input collected by BFF server adapters (hono/effect/...) before
|
|
5
|
-
* the cross-project policy can be enforced.
|
|
6
|
-
*
|
|
7
|
-
* `crossProjectPolicy` accepts the raw `bff.crossProjectPolicy` user config —
|
|
8
|
-
* `BffCrossProjectPolicyUserConfig` is a structural subset of
|
|
9
|
-
* `CrossProjectPolicyConfig`, so no casts are required at the call site.
|
|
10
|
-
*/
|
|
11
|
-
export interface ResolveCrossProjectPolicyInput {
|
|
12
|
-
crossProjectPolicy?: CrossProjectPolicyConfig;
|
|
13
|
-
/** Registered API handlers used to derive the operation-contract map. */
|
|
14
|
-
handlers: OperationContractSource[];
|
|
15
|
-
/** Logical producer ID (`bff.requestId`). */
|
|
16
|
-
requestId?: string;
|
|
17
|
-
/** Marker injected by generated cross-project SDK plugins. */
|
|
18
|
-
isCrossProjectServer?: boolean;
|
|
19
|
-
/**
|
|
20
|
-
* Producer contract version (usually derived from the producer
|
|
21
|
-
* package.json major via `deriveOperationVersion`).
|
|
22
|
-
*/
|
|
23
|
-
operationVersion?: number;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Fully-defaulted policy returned by {@link resolveCrossProjectPolicy}.
|
|
27
|
-
*/
|
|
28
|
-
export type ResolvedCrossProjectPolicy = NormalizedCrossProjectPolicy;
|
|
29
|
-
/**
|
|
30
|
-
* Normalizes the user-facing cross-project policy config into the evaluator
|
|
31
|
-
* input shared by every BFF server adapter:
|
|
32
|
-
*
|
|
33
|
-
* - returns `undefined` when neither a policy nor the cross-project server
|
|
34
|
-
* marker is present (policy middleware must not be installed);
|
|
35
|
-
* - applies the documented defaults for all `require*` switches;
|
|
36
|
-
* - merges generated operation contracts (derived from the registered
|
|
37
|
-
* handlers) over any user-provided `expectedOperationContracts`.
|
|
38
|
-
*/
|
|
39
|
-
export declare const resolveCrossProjectPolicy: (input: ResolveCrossProjectPolicyInput) => ResolvedCrossProjectPolicy | undefined;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
interface Paths {
|
|
2
|
-
[key: string]: string[] | string;
|
|
3
|
-
}
|
|
4
|
-
export declare const getRelativeRuntimePath: (appDirectory: string, serverRuntimePath: string) => string;
|
|
5
|
-
export declare const createMatchPath: (paths: Paths) => (request: string) => string | null;
|
|
6
|
-
export declare const registerPaths: (paths: Paths) => () => void;
|
|
7
|
-
export {};
|