@cullet/erp-core 1.4.0 → 2.0.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/KIT_CONTEXT.md +7 -1
- package/dist/abac/index.d.cts +2 -2
- package/dist/abac/index.d.ts +2 -2
- package/dist/aggregate-version.cjs +14 -0
- package/dist/aggregate-version.cjs.map +1 -0
- package/dist/aggregate-version.js +9 -0
- package/dist/aggregate-version.js.map +1 -0
- package/dist/app-error.cjs +21 -6
- package/dist/app-error.cjs.map +1 -1
- package/dist/app-error.js +21 -6
- package/dist/app-error.js.map +1 -1
- package/dist/application/index.cjs +8 -4
- package/dist/application/index.d.cts +2 -2
- package/dist/application/index.d.ts +2 -2
- package/dist/application/index.js +1 -2
- package/dist/authorization-error.cjs +67 -17
- package/dist/authorization-error.cjs.map +1 -1
- package/dist/authorization-error.d.cts +6 -2
- package/dist/authorization-error.d.ts +6 -2
- package/dist/authorization-error.js +50 -18
- package/dist/authorization-error.js.map +1 -1
- package/dist/authorizer.port.d.cts +18 -3
- package/dist/authorizer.port.d.ts +18 -3
- package/dist/composite-authorizer.d.cts +63 -10
- package/dist/composite-authorizer.d.ts +63 -10
- package/dist/condition-evaluator.cjs +117 -172
- package/dist/condition-evaluator.cjs.map +1 -1
- package/dist/condition-evaluator.js +118 -167
- package/dist/condition-evaluator.js.map +1 -1
- package/dist/core-config.d.cts +53 -6
- package/dist/core-config.d.ts +53 -6
- package/dist/decorate.cjs +14 -0
- package/dist/decorate.js +9 -0
- package/dist/domain/index.cjs +107 -2
- package/dist/domain/index.cjs.map +1 -0
- package/dist/domain/index.d.cts +25 -1
- package/dist/domain/index.d.ts +25 -1
- package/dist/domain/index.js +99 -3
- package/dist/domain/index.js.map +1 -0
- package/dist/domain-event-contracts.cjs +12 -8
- package/dist/domain-event-contracts.cjs.map +1 -1
- package/dist/domain-event-contracts.d.cts +29 -4
- package/dist/domain-event-contracts.d.ts +29 -4
- package/dist/domain-event-contracts.js +11 -7
- package/dist/domain-event-contracts.js.map +1 -1
- package/dist/domain-exception.cjs +2 -1
- package/dist/domain-exception.cjs.map +1 -1
- package/dist/domain-exception.js +2 -1
- package/dist/domain-exception.js.map +1 -1
- package/dist/errors/index.cjs +3 -2
- package/dist/errors/index.d.cts +1 -1
- package/dist/errors/index.d.ts +1 -1
- package/dist/errors/index.js +3 -2
- package/dist/exceptions/index.cjs +2 -2
- package/dist/exceptions/index.d.cts +1 -2
- package/dist/exceptions/index.d.ts +1 -2
- package/dist/exceptions/index.js +2 -2
- package/dist/gate-engine-registry.cjs.map +1 -1
- package/dist/gate-engine-registry.d.cts +1 -1
- package/dist/gate-engine-registry.d.ts +1 -1
- package/dist/gate-engine-registry.js.map +1 -1
- package/dist/gate-v1-payload.schema.cjs +11 -6
- package/dist/gate-v1-payload.schema.cjs.map +1 -1
- package/dist/gate-v1-payload.schema.js +11 -6
- package/dist/gate-v1-payload.schema.js.map +1 -1
- package/dist/hashing.cjs +2 -44
- package/dist/hashing.cjs.map +1 -1
- package/dist/hashing.js +3 -39
- package/dist/hashing.js.map +1 -1
- package/dist/immutable.cjs +25 -12
- package/dist/immutable.cjs.map +1 -1
- package/dist/immutable.js +24 -11
- package/dist/immutable.js.map +1 -1
- package/dist/index.cjs +15 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +9 -10
- package/dist/index.d.ts +9 -10
- package/dist/index.js +8 -9
- package/dist/index.js.map +1 -1
- package/dist/invalid-state-transition-exception.cjs +6 -6
- package/dist/invalid-state-transition-exception.cjs.map +1 -1
- package/dist/invalid-state-transition-exception.js +6 -6
- package/dist/invalid-state-transition-exception.js.map +1 -1
- package/dist/invariant-violation-exception.cjs +2 -2
- package/dist/invariant-violation-exception.cjs.map +1 -1
- package/dist/invariant-violation-exception.js +2 -2
- package/dist/invariant-violation-exception.js.map +1 -1
- package/dist/not-found-error.cjs +6 -4
- package/dist/not-found-error.cjs.map +1 -1
- package/dist/not-found-error.js +6 -4
- package/dist/not-found-error.js.map +1 -1
- package/dist/outcome.cjs +5 -5
- package/dist/outcome.cjs.map +1 -1
- package/dist/outcome.js +5 -5
- package/dist/outcome.js.map +1 -1
- package/dist/parse-gate-payload.d.cts +1 -1
- package/dist/parse-gate-payload.d.ts +1 -1
- package/dist/path.d.cts +2 -2
- package/dist/path.d.ts +2 -2
- package/dist/plugin.cjs +23 -13
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +22 -8
- package/dist/plugin.d.ts +22 -8
- package/dist/plugin.js +23 -13
- package/dist/plugin.js.map +1 -1
- package/dist/policies/engines/index.d.cts +1 -1
- package/dist/policies/engines/index.d.ts +1 -1
- package/dist/policies/engines/v1/gate/index.d.cts +3 -13
- package/dist/policies/engines/v1/gate/index.d.ts +3 -13
- package/dist/policies/index.d.cts +1 -1
- package/dist/policies/index.d.ts +1 -1
- package/dist/policy-bridge.cjs +30 -2
- package/dist/policy-bridge.cjs.map +1 -1
- package/dist/policy-bridge.d.cts +18 -0
- package/dist/policy-bridge.d.ts +18 -0
- package/dist/policy-bridge.js +30 -2
- package/dist/policy-bridge.js.map +1 -1
- package/dist/policy-service.cjs +41 -46
- package/dist/policy-service.cjs.map +1 -1
- package/dist/policy-service.d.cts +72 -9
- package/dist/policy-service.d.ts +72 -9
- package/dist/policy-service.js +43 -48
- package/dist/policy-service.js.map +1 -1
- package/dist/requested-by.cjs +4 -4
- package/dist/requested-by.cjs.map +1 -1
- package/dist/requested-by.js +2 -2
- package/dist/requested-by.js.map +1 -1
- package/dist/result.cjs +29 -1
- package/dist/result.cjs.map +1 -1
- package/dist/result.d.cts +12 -0
- package/dist/result.d.ts +12 -0
- package/dist/result.js +29 -1
- package/dist/result.js.map +1 -1
- package/dist/rule.cjs +94 -24
- package/dist/rule.cjs.map +1 -1
- package/dist/rule.js +94 -24
- package/dist/rule.js.map +1 -1
- package/dist/ruleset-registry.cjs +19 -0
- package/dist/ruleset-registry.cjs.map +1 -1
- package/dist/ruleset-registry.js +19 -0
- package/dist/ruleset-registry.js.map +1 -1
- package/dist/stable-stringify.cjs +87 -0
- package/dist/stable-stringify.cjs.map +1 -0
- package/dist/stable-stringify.js +76 -0
- package/dist/stable-stringify.js.map +1 -0
- package/dist/temporal-snapshot.d.cts +87 -0
- package/dist/temporal-snapshot.d.ts +87 -0
- package/dist/temporal-use-case.cjs +174 -16
- package/dist/temporal-use-case.cjs.map +1 -1
- package/dist/temporal-use-case.d.cts +82 -44
- package/dist/temporal-use-case.d.ts +82 -44
- package/dist/temporal-use-case.js +167 -15
- package/dist/temporal-use-case.js.map +1 -1
- package/dist/unexpected-error.cjs +4 -2
- package/dist/unexpected-error.cjs.map +1 -1
- package/dist/unexpected-error.js +4 -2
- package/dist/unexpected-error.js.map +1 -1
- package/dist/uuid-identifier.cjs +141 -8
- package/dist/uuid-identifier.cjs.map +1 -1
- package/dist/uuid-identifier.d.cts +26 -7
- package/dist/uuid-identifier.d.ts +26 -7
- package/dist/uuid-identifier.js +135 -8
- package/dist/uuid-identifier.js.map +1 -1
- package/dist/uuid.cjs +23 -0
- package/dist/uuid.cjs.map +1 -0
- package/dist/uuid.js +18 -0
- package/dist/uuid.js.map +1 -0
- package/dist/validation-code.cjs +9 -0
- package/dist/validation-code.cjs.map +1 -1
- package/dist/validation-code.d.cts +3 -0
- package/dist/validation-code.d.ts +3 -0
- package/dist/validation-code.js +9 -0
- package/dist/validation-code.js.map +1 -1
- package/dist/validation-error.cjs +42 -67
- package/dist/validation-error.cjs.map +1 -1
- package/dist/validation-error.d.cts +29 -8
- package/dist/validation-error.d.ts +29 -8
- package/dist/validation-error.js +41 -66
- package/dist/validation-error.js.map +1 -1
- package/dist/validation-exception.cjs +17 -6
- package/dist/validation-exception.cjs.map +1 -1
- package/dist/validation-exception.d.cts +33 -9
- package/dist/validation-exception.d.ts +33 -9
- package/dist/validation-exception.js +17 -6
- package/dist/validation-exception.js.map +1 -1
- package/dist/validation-field.cjs +3 -0
- package/dist/validation-field.cjs.map +1 -1
- package/dist/validation-field.d.cts +1 -0
- package/dist/validation-field.d.ts +1 -0
- package/dist/validation-field.js +3 -0
- package/dist/validation-field.js.map +1 -1
- package/dist/value-object-ruleset.contracts.d.cts +10 -0
- package/dist/value-object-ruleset.contracts.d.ts +10 -0
- package/dist/value-object.cjs +23 -4
- package/dist/value-object.cjs.map +1 -1
- package/dist/value-object.d.cts +25 -1
- package/dist/value-object.d.ts +25 -1
- package/dist/value-object.js +23 -4
- package/dist/value-object.js.map +1 -1
- package/dist/version.d.cts +27 -0
- package/dist/version.d.ts +27 -0
- package/dist/versioning/index.d.cts +2 -2
- package/dist/versioning/index.d.ts +2 -2
- package/meta.json +5 -2
- package/package.json +1 -1
- package/src/core/abac/authorizer.ts +60 -10
- package/src/core/abac/domain/policy-set.ts +52 -5
- package/src/core/abac/domain/rule.ts +28 -16
- package/src/core/abac/index.ts +7 -1
- package/src/core/application/commands/command.ts +14 -1
- package/src/core/application/commands/requested-by.ts +13 -5
- package/src/core/application/index.ts +2 -1
- package/src/core/application/policy-error-mapper.ts +6 -0
- package/src/core/application/ports/index.ts +7 -0
- package/src/core/application/ports/temporal-repository.port.ts +35 -2
- package/src/core/application/queries/index.ts +1 -1
- package/src/core/application/queries/query.ts +25 -3
- package/src/core/application/temporal/temporal-use-case.ts +31 -4
- package/src/core/application/use-case.ts +45 -8
- package/src/core/config/core-config.ts +46 -25
- package/src/core/config/index.ts +1 -0
- package/src/core/config/policy-reporter.ts +32 -1
- package/src/core/domain/entity.ts +51 -8
- package/src/core/domain/rulesets/entity-ruleset.contracts.ts +0 -2
- package/src/core/domain/rulesets/ruleset-registry.ts +24 -0
- package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +1 -7
- package/src/core/domain/temporal/half-open-interval.ts +34 -0
- package/src/core/domain/temporal/temporal-snapshot.ts +13 -2
- package/src/core/domain/temporal/transaction-time.ts +19 -15
- package/src/core/domain/temporal/valid-time.ts +20 -15
- package/src/core/domain/uuid-identifier.ts +6 -11
- package/src/core/domain/value-object.ts +29 -3
- package/src/core/errors/authentication-error.ts +5 -31
- package/src/core/errors/authorization-error.ts +12 -20
- package/src/core/errors/business-rule-violation-error.ts +4 -1
- package/src/core/errors/idempotency-error.ts +5 -2
- package/src/core/errors/index.ts +4 -0
- package/src/core/errors/integration-error.ts +4 -24
- package/src/core/errors/legacy-incompatible-error.ts +1 -0
- package/src/core/errors/not-found-error.ts +4 -1
- package/src/core/errors/temporal-error.ts +22 -20
- package/src/core/errors/unexpected-error.ts +5 -1
- package/src/core/errors/utils/factory-helpers.ts +70 -0
- package/src/core/errors/utils/index.ts +5 -0
- package/src/core/errors/utils/json-safe.ts +35 -12
- package/src/core/errors/validation-error.ts +4 -1
- package/src/core/exceptions/business-rule-violation-exception.ts +2 -1
- package/src/core/exceptions/domain-exception.ts +9 -1
- package/src/core/exceptions/entity-not-found-exception.ts +5 -1
- package/src/core/exceptions/invalid-state-transition-exception.ts +5 -2
- package/src/core/exceptions/invariant-violation-exception.ts +2 -2
- package/src/core/exceptions/validation-code.ts +14 -0
- package/src/core/exceptions/validation-exception.ts +44 -5
- package/src/core/exceptions/validation-field.ts +11 -1
- package/src/core/plugins/plugin.ts +25 -15
- package/src/core/plugins/types.ts +4 -2
- package/src/core/policies/asof/asof.ts +12 -0
- package/src/core/policies/catalog/policy-catalog-entry.ts +3 -1
- package/src/core/policies/catalog/policy-catalog.ts +5 -1
- package/src/core/policies/context/context-builder.ts +20 -0
- package/src/core/policies/context/context-resolver.ts +5 -0
- package/src/core/policies/context/context-seed.ts +11 -0
- package/src/core/policies/defs/in-memory-policy-definition-repo.ts +0 -2
- package/src/core/policies/engines/parse-gate-payload.ts +9 -0
- package/src/core/policies/engines/v1/condition-date-operands.ts +112 -0
- package/src/core/policies/engines/v1/condition-evaluator.ts +120 -291
- package/src/core/policies/engines/v1/condition-schema.ts +23 -19
- package/src/core/policies/engines/v1/condition-types.ts +18 -11
- package/src/core/policies/index.ts +4 -6
- package/src/core/policies/service/policy-service.ts +46 -35
- package/src/core/policies/utils/hash.ts +5 -69
- package/src/core/policies/utils/result.ts +1 -1
- package/src/core/rbac/access-request.ts +12 -2
- package/src/core/rbac/authorizer.ts +8 -1
- package/src/core/rbac/domain/role.ts +20 -0
- package/src/core/rbac/domain/scope.ts +6 -1
- package/src/core/result/index.ts +5 -0
- package/src/core/result/outcome.ts +5 -7
- package/src/core/result/result.ts +34 -1
- package/src/core/shared/hashing.ts +6 -57
- package/src/core/shared/immutable.ts +22 -4
- package/src/core/shared/stable-stringify.ts +144 -0
- package/src/core/shared/uuid.ts +16 -0
- package/src/core/versioning/domain-event-contracts.ts +43 -15
- package/src/core/versioning/index.ts +1 -0
- package/src/core/versioning/version.ts +30 -1
- package/src/domain/index.ts +5 -0
- package/src/examples/rulesets/entity/order-creation-rules-v1.ts +1 -1
- package/src/examples/rulesets/entity/order-invariants-v1.ts +2 -4
- package/src/examples/rulesets/entity/order-invariants-v2.ts +2 -4
- package/src/examples/rulesets/value-object/cpf-rules-v1.ts +2 -4
- package/src/examples/rulesets/value-object/cpf-rules-v2.ts +2 -4
- package/src/examples/rulesets/value-object/person-name-rules-v1.ts +2 -4
- package/src/examples/rulesets/value-object/person-name-rules-v2.ts +2 -4
- package/src/result/index.ts +7 -2
- package/src/version.ts +1 -1
- package/dist/domain-exception.d.cts +0 -7
- package/dist/domain-exception.d.ts +0 -7
- package/dist/entity.cjs +0 -126
- package/dist/entity.cjs.map +0 -1
- package/dist/entity.js +0 -115
- package/dist/entity.js.map +0 -1
- package/dist/use-case.cjs +0 -96
- package/dist/use-case.cjs.map +0 -1
- package/dist/use-case.js +0 -91
- package/dist/use-case.js.map +0 -1
|
@@ -16,9 +16,13 @@ type AuthorizationErrorMetadata = {
|
|
|
16
16
|
type: string;
|
|
17
17
|
id?: string;
|
|
18
18
|
};
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Optional: the acting principal (do not include sensitive data). `actorId`
|
|
21
|
+
* is the raw `RequestedBy` value — a user UUID *or* a `"system:<job>"`
|
|
22
|
+
* identity — so it must not be assumed to be a human user.
|
|
23
|
+
*/
|
|
20
24
|
actor?: {
|
|
21
|
-
|
|
25
|
+
actorId: string;
|
|
22
26
|
role?: string;
|
|
23
27
|
};
|
|
24
28
|
/** Optional: expected requirement */
|
|
@@ -1,4 +1,48 @@
|
|
|
1
1
|
import { r as ErrorCodes, t as AppError } from "./app-error.js";
|
|
2
|
+
//#region src/core/errors/utils/factory-helpers.ts
|
|
3
|
+
/** The envelope fields AppError understands; everything else is metadata. */
|
|
4
|
+
const APP_ERROR_OPTION_KEYS = [
|
|
5
|
+
"cause",
|
|
6
|
+
"type",
|
|
7
|
+
"severity",
|
|
8
|
+
"correlationId",
|
|
9
|
+
"requestId",
|
|
10
|
+
"commandId",
|
|
11
|
+
"createdAtIso",
|
|
12
|
+
"publicMessage"
|
|
13
|
+
];
|
|
14
|
+
/**
|
|
15
|
+
* Picks the AppError envelope fields out of a flat factory input, so they can
|
|
16
|
+
* be forwarded to the constructor as options instead of leaking into metadata.
|
|
17
|
+
*/
|
|
18
|
+
function pickAppErrorOptions(input) {
|
|
19
|
+
return {
|
|
20
|
+
cause: input?.cause,
|
|
21
|
+
type: input?.type,
|
|
22
|
+
severity: input?.severity,
|
|
23
|
+
correlationId: input?.correlationId,
|
|
24
|
+
requestId: input?.requestId,
|
|
25
|
+
commandId: input?.commandId,
|
|
26
|
+
createdAtIso: input?.createdAtIso,
|
|
27
|
+
publicMessage: input?.publicMessage
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The complement of {@link pickAppErrorOptions}: everything that is *not* an
|
|
32
|
+
* AppError envelope field, i.e. the caller-supplied metadata. Keeps the cause
|
|
33
|
+
* and the public message out of the internal data block.
|
|
34
|
+
*/
|
|
35
|
+
function stripAppErrorOptions(input) {
|
|
36
|
+
const result = { ...input };
|
|
37
|
+
for (const key of APP_ERROR_OPTION_KEYS) delete result[key];
|
|
38
|
+
return result;
|
|
39
|
+
}
|
|
40
|
+
/** Drops keys whose value is `undefined` (mirrors how JSON.stringify treats them). */
|
|
41
|
+
function compactMetadata(input) {
|
|
42
|
+
if (!input) return void 0;
|
|
43
|
+
return Object.fromEntries(Object.entries(input).filter(([, value]) => value !== void 0));
|
|
44
|
+
}
|
|
45
|
+
//#endregion
|
|
2
46
|
//#region src/core/errors/authorization-error.ts
|
|
3
47
|
/**
|
|
4
48
|
* Raised when an authenticated actor is not allowed to perform a business
|
|
@@ -44,7 +88,7 @@ var AuthorizationError = class AuthorizationError extends AppError {
|
|
|
44
88
|
reason: "forbidden",
|
|
45
89
|
...extractMetadataOnly(input)
|
|
46
90
|
},
|
|
47
|
-
...
|
|
91
|
+
...pickAppErrorOptions(input)
|
|
48
92
|
});
|
|
49
93
|
}
|
|
50
94
|
/**
|
|
@@ -66,7 +110,7 @@ var AuthorizationError = class AuthorizationError extends AppError {
|
|
|
66
110
|
...extractMetadataOnly(input),
|
|
67
111
|
decision: "deny"
|
|
68
112
|
},
|
|
69
|
-
...
|
|
113
|
+
...pickAppErrorOptions(input)
|
|
70
114
|
});
|
|
71
115
|
}
|
|
72
116
|
/**
|
|
@@ -87,7 +131,7 @@ var AuthorizationError = class AuthorizationError extends AppError {
|
|
|
87
131
|
reason: "missing_role",
|
|
88
132
|
...extractMetadataOnly(input)
|
|
89
133
|
},
|
|
90
|
-
...
|
|
134
|
+
...pickAppErrorOptions(input)
|
|
91
135
|
});
|
|
92
136
|
}
|
|
93
137
|
/**
|
|
@@ -106,7 +150,7 @@ var AuthorizationError = class AuthorizationError extends AppError {
|
|
|
106
150
|
reason: "missing_capability",
|
|
107
151
|
...extractMetadataOnly(input)
|
|
108
152
|
},
|
|
109
|
-
...
|
|
153
|
+
...pickAppErrorOptions(input)
|
|
110
154
|
});
|
|
111
155
|
}
|
|
112
156
|
/**
|
|
@@ -126,27 +170,15 @@ var AuthorizationError = class AuthorizationError extends AppError {
|
|
|
126
170
|
reason: "out_of_scope",
|
|
127
171
|
...extractMetadataOnly(input)
|
|
128
172
|
},
|
|
129
|
-
...
|
|
173
|
+
...pickAppErrorOptions(input)
|
|
130
174
|
});
|
|
131
175
|
}
|
|
132
176
|
};
|
|
133
|
-
function extractAppErrorOptions(options) {
|
|
134
|
-
return {
|
|
135
|
-
cause: options?.cause,
|
|
136
|
-
type: options?.type,
|
|
137
|
-
severity: options?.severity,
|
|
138
|
-
correlationId: options?.correlationId,
|
|
139
|
-
requestId: options?.requestId,
|
|
140
|
-
commandId: options?.commandId,
|
|
141
|
-
createdAtIso: options?.createdAtIso,
|
|
142
|
-
publicMessage: options?.publicMessage
|
|
143
|
-
};
|
|
144
|
-
}
|
|
145
177
|
function extractMetadataOnly(input) {
|
|
146
178
|
const { cause, type, severity, correlationId, requestId, commandId, createdAtIso, publicMessage, ...metadata } = input;
|
|
147
179
|
return metadata;
|
|
148
180
|
}
|
|
149
181
|
//#endregion
|
|
150
|
-
export { AuthorizationError as t };
|
|
182
|
+
export { stripAppErrorOptions as i, compactMetadata as n, pickAppErrorOptions as r, AuthorizationError as t };
|
|
151
183
|
|
|
152
184
|
//# sourceMappingURL=authorization-error.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authorization-error.js","names":[],"sources":["../src/core/errors/authorization-error.ts"],"sourcesContent":["import { AppError } from \"./app-error.js\";\nimport { ErrorCodes } from \"./error-codes.js\";\nimport type { AppErrorOptions, ErrorSeverity } from \"./types.js\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype AuthorizationErrorReason =\n | \"forbidden\"\n | \"missing_role\"\n | \"missing_capability\"\n | \"out_of_scope\"\n | \"outside_time_window\"\n | \"policy_denied\"\n | \"unknown\";\n\ntype AuthorizationRequirement = {\n role?: string;\n capability?: string;\n scope?: string; // e.g.: \"school:{id}\" or \"class:{id}\"\n};\n\ntype AuthorizationErrorMetadata = {\n reason: AuthorizationErrorReason;\n\n /** Stable action you evaluated (not an HTTP route — a \"business action\") */\n action: string;\n\n /** Resource identification (without leaking the full payload) */\n resource?: { type: string; id?: string };\n\n /** Optional: actor (do not include sensitive data) */\n actor?: { userId: string; role?: string };\n\n /** Optional: expected requirement */\n required?: AuthorizationRequirement;\n\n /** Optional: policy (when you already have PolicyEvaluation or similar) */\n policyId?: string;\n policyVersion?: number;\n evaluatedAtIso?: string;\n decision?: \"allow\" | \"deny\";\n reasonCode?: string;\n\n /** Optional: additional non-sensitive info */\n details?: string;\n};\n\n/**\n * Options for AuthorizationError factory methods.\n * Combines metadata fields (except 'reason') with common AppError options.\n */\ntype AuthorizationErrorFactoryOptions = Omit<\n AuthorizationErrorMetadata,\n \"reason\"\n> &\n Omit<AppErrorOptions, \"metadata\">;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// AuthorizationError\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Raised when an authenticated actor is not allowed to perform a business\n * action — the \"you may not\" error, distinct from authentication (\"who are\n * you\"). Maps to an HTTP 403 at the edge.\n *\n * The discriminating {@link reason} records *why* access was denied (a flat\n * forbid, a missing role/capability, an out-of-scope target, or a policy\n * decision) so the boundary can shape the response without re-deriving it. The\n * metadata is deliberately built around a stable business `action` and a\n * type/id resource reference rather than an HTTP route or full payload, keeping\n * sensitive data out of logs. Instances are frozen. Construct through the\n * static factories, never directly.\n */\nclass AuthorizationError extends AppError {\n public readonly reason: AuthorizationErrorReason;\n\n private constructor(params: {\n message: string;\n code: string;\n reason: AuthorizationErrorReason;\n metadata: AuthorizationErrorMetadata;\n cause?: unknown;\n type?: string;\n severity?: ErrorSeverity;\n correlationId?: string;\n requestId?: string;\n commandId?: string;\n createdAtIso?: string;\n publicMessage?: string;\n }) {\n super(params.message, params.code, {\n cause: params.cause,\n metadata: params.metadata,\n type: params.type,\n severity: params.severity,\n correlationId: params.correlationId,\n requestId: params.requestId,\n commandId: params.commandId,\n createdAtIso: params.createdAtIso,\n publicMessage: params.publicMessage,\n });\n\n this.reason = params.reason;\n Object.freeze(this);\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Factories\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * A flat denial with no more specific reason — the actor simply may not\n * perform this action. Reach for a more precise factory\n * ({@link AuthorizationError.missingCapability}, {@link AuthorizationError.outOfScope},\n * {@link AuthorizationError.policyDenied}) when the cause is known.\n */\n static forbidden(\n input: AuthorizationErrorFactoryOptions,\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Action not allowed\",\n code: ErrorCodes.authorization.forbidden,\n reason: \"forbidden\",\n metadata: { reason: \"forbidden\", ...extractMetadataOnly(input) },\n ...extractAppErrorOptions(input),\n });\n }\n\n /**\n * The action was denied by an evaluated policy. Captures the deciding\n * policy's id, version, and evaluation instant into the metadata (with\n * `decision: \"deny\"`) so the denial is auditable back to the exact policy\n * that produced it.\n *\n * @param input - Factory options plus the required `policyId`,\n * `policyVersion`, and `evaluatedAtIso` of the deciding policy.\n */\n static policyDenied(\n input: AuthorizationErrorFactoryOptions & {\n policyId: string;\n policyVersion: number;\n evaluatedAtIso: string;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Action denied by policy\",\n code: ErrorCodes.authorization.policyDenied,\n reason: \"policy_denied\",\n metadata: {\n reason: \"policy_denied\",\n ...extractMetadataOnly(input),\n decision: \"deny\",\n },\n ...extractAppErrorOptions(input),\n });\n }\n\n /**\n * The actor holds no role at all that bears on the action — the most basic\n * denial, distinct from {@link AuthorizationError.missingCapability} (which\n * means the actor *has* roles, just none granting the required capability).\n * The expected {@link AuthorizationRequirement} is recorded so the boundary\n * can tell the caller what grant is missing.\n *\n * @param input - Factory options plus the `required` role/capability/scope.\n */\n static missingRole(\n input: AuthorizationErrorFactoryOptions & {\n required: AuthorizationRequirement;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Missing required role to perform the action\",\n code: ErrorCodes.authorization.missingRole,\n reason: \"missing_role\",\n metadata: {\n reason: \"missing_role\",\n ...extractMetadataOnly(input),\n },\n ...extractAppErrorOptions(input),\n });\n }\n\n /**\n * The actor lacks a required role or capability. The expected\n * {@link AuthorizationRequirement} is recorded so the boundary can tell the\n * caller precisely what grant is missing.\n *\n * @param input - Factory options plus the `required` role/capability/scope.\n */\n static missingCapability(\n input: AuthorizationErrorFactoryOptions & {\n required: AuthorizationRequirement;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Insufficient capability to perform the action\",\n code: ErrorCodes.authorization.missingCapability,\n reason: \"missing_capability\",\n metadata: {\n reason: \"missing_capability\",\n ...extractMetadataOnly(input),\n },\n ...extractAppErrorOptions(input),\n });\n }\n\n /**\n * The actor may perform the action in general, but not on *this* target —\n * the resource falls outside the actor's permitted scope (e.g. a different\n * school or tenant than the one they are bound to).\n *\n * @param input - Factory options plus the optional `required` scope that the\n * target failed to satisfy.\n */\n static outOfScope(\n input: AuthorizationErrorFactoryOptions & {\n required?: AuthorizationRequirement;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Action outside the allowed scope\",\n code: ErrorCodes.authorization.outOfScope,\n reason: \"out_of_scope\",\n metadata: { reason: \"out_of_scope\", ...extractMetadataOnly(input) },\n ...extractAppErrorOptions(input),\n });\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction extractAppErrorOptions(options?: Partial<AppErrorOptions>) {\n return {\n cause: options?.cause,\n type: options?.type,\n severity: options?.severity,\n correlationId: options?.correlationId,\n requestId: options?.requestId,\n commandId: options?.commandId,\n createdAtIso: options?.createdAtIso,\n publicMessage: options?.publicMessage,\n };\n}\n\nfunction extractMetadataOnly(\n input: AuthorizationErrorFactoryOptions,\n): Omit<AuthorizationErrorMetadata, \"reason\"> {\n const {\n cause,\n type,\n severity,\n correlationId,\n requestId,\n commandId,\n createdAtIso,\n publicMessage,\n ...metadata\n } = input;\n return metadata;\n}\n\nexport { AuthorizationError };\nexport type {\n AuthorizationErrorMetadata,\n AuthorizationErrorReason,\n AuthorizationRequirement,\n};\n"],"mappings":";;;;;;;;;;;;;;;AA4EA,IAAM,qBAAN,MAAM,2BAA2B,SAAS;CAGtC,YAAoB,QAajB;EACC,MAAM,OAAO,SAAS,OAAO,MAAM;GAC/B,OAAO,OAAO;GACd,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,eAAe,OAAO;GACtB,WAAW,OAAO;GAClB,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,eAAe,OAAO;EAC1B,CAAC;EAED,KAAK,SAAS,OAAO;EACrB,OAAO,OAAO,IAAI;CACtB;;;;;;;CAYA,OAAO,UACH,OACkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IAAE,QAAQ;IAAa,GAAG,oBAAoB,KAAK;GAAE;GAC/D,GAAG,uBAAuB,KAAK;EACnC,CAAC;CACL;;;;;;;;;;CAWA,OAAO,aACH,OAKkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IACN,QAAQ;IACR,GAAG,oBAAoB,KAAK;IAC5B,UAAU;GACd;GACA,GAAG,uBAAuB,KAAK;EACnC,CAAC;CACL;;;;;;;;;;CAWA,OAAO,YACH,OAGkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IACN,QAAQ;IACR,GAAG,oBAAoB,KAAK;GAChC;GACA,GAAG,uBAAuB,KAAK;EACnC,CAAC;CACL;;;;;;;;CASA,OAAO,kBACH,OAGkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IACN,QAAQ;IACR,GAAG,oBAAoB,KAAK;GAChC;GACA,GAAG,uBAAuB,KAAK;EACnC,CAAC;CACL;;;;;;;;;CAUA,OAAO,WACH,OAGkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IAAE,QAAQ;IAAgB,GAAG,oBAAoB,KAAK;GAAE;GAClE,GAAG,uBAAuB,KAAK;EACnC,CAAC;CACL;AACJ;AAMA,SAAS,uBAAuB,SAAoC;CAChE,OAAO;EACH,OAAO,SAAS;EAChB,MAAM,SAAS;EACf,UAAU,SAAS;EACnB,eAAe,SAAS;EACxB,WAAW,SAAS;EACpB,WAAW,SAAS;EACpB,cAAc,SAAS;EACvB,eAAe,SAAS;CAC5B;AACJ;AAEA,SAAS,oBACL,OAC0C;CAC1C,MAAM,EACF,OACA,MACA,UACA,eACA,WACA,WACA,cACA,eACA,GAAG,aACH;CACJ,OAAO;AACX"}
|
|
1
|
+
{"version":3,"file":"authorization-error.js","names":[],"sources":["../src/core/errors/utils/factory-helpers.ts","../src/core/errors/authorization-error.ts"],"sourcesContent":["// Shared helpers for the error factories: separating the AppError envelope\n// options from the free-form metadata, and dropping undefined-valued keys.\n// Previously each of authentication/authorization/integration carried its own\n// near-identical copy of these.\n\nimport type { AppErrorOptions } from \"../types.js\";\n\n/** The envelope fields AppError understands; everything else is metadata. */\nconst APP_ERROR_OPTION_KEYS = [\n \"cause\",\n \"type\",\n \"severity\",\n \"correlationId\",\n \"requestId\",\n \"commandId\",\n \"createdAtIso\",\n \"publicMessage\",\n] as const;\n\ntype AppErrorEnvelope = Pick<\n AppErrorOptions,\n (typeof APP_ERROR_OPTION_KEYS)[number]\n>;\n\n/**\n * Picks the AppError envelope fields out of a flat factory input, so they can\n * be forwarded to the constructor as options instead of leaking into metadata.\n */\nfunction pickAppErrorOptions(\n input?: Partial<AppErrorOptions>,\n): AppErrorEnvelope {\n return {\n cause: input?.cause,\n type: input?.type,\n severity: input?.severity,\n correlationId: input?.correlationId,\n requestId: input?.requestId,\n commandId: input?.commandId,\n createdAtIso: input?.createdAtIso,\n publicMessage: input?.publicMessage,\n };\n}\n\n/**\n * The complement of {@link pickAppErrorOptions}: everything that is *not* an\n * AppError envelope field, i.e. the caller-supplied metadata. Keeps the cause\n * and the public message out of the internal data block.\n */\nfunction stripAppErrorOptions<T extends Record<string, unknown>>(\n input: T,\n): Omit<T, (typeof APP_ERROR_OPTION_KEYS)[number]> {\n const result = { ...input };\n for (const key of APP_ERROR_OPTION_KEYS) {\n delete result[key];\n }\n return result;\n}\n\n/** Drops keys whose value is `undefined` (mirrors how JSON.stringify treats them). */\nfunction compactMetadata<T extends Record<string, unknown>>(\n input?: T,\n): T | undefined {\n if (!input) return undefined;\n\n return Object.fromEntries(\n Object.entries(input).filter(([, value]) => value !== undefined),\n ) as T;\n}\n\nexport { compactMetadata, pickAppErrorOptions, stripAppErrorOptions };\n","import { AppError } from \"./app-error.js\";\nimport { ErrorCodes } from \"./error-codes.js\";\nimport type { AppErrorOptions, ErrorSeverity } from \"./types.js\";\nimport { pickAppErrorOptions } from \"./utils/index.js\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Types\n// ─────────────────────────────────────────────────────────────────────────────\n\ntype AuthorizationErrorReason =\n | \"forbidden\"\n | \"missing_role\"\n | \"missing_capability\"\n | \"out_of_scope\"\n | \"outside_time_window\"\n | \"policy_denied\"\n | \"unknown\";\n\ntype AuthorizationRequirement = {\n role?: string;\n capability?: string;\n scope?: string; // e.g.: \"school:{id}\" or \"class:{id}\"\n};\n\ntype AuthorizationErrorMetadata = {\n reason: AuthorizationErrorReason;\n\n /** Stable action you evaluated (not an HTTP route — a \"business action\") */\n action: string;\n\n /** Resource identification (without leaking the full payload) */\n resource?: { type: string; id?: string };\n\n /**\n * Optional: the acting principal (do not include sensitive data). `actorId`\n * is the raw `RequestedBy` value — a user UUID *or* a `\"system:<job>\"`\n * identity — so it must not be assumed to be a human user.\n */\n actor?: { actorId: string; role?: string };\n\n /** Optional: expected requirement */\n required?: AuthorizationRequirement;\n\n /** Optional: policy (when you already have PolicyEvaluation or similar) */\n policyId?: string;\n policyVersion?: number;\n evaluatedAtIso?: string;\n decision?: \"allow\" | \"deny\";\n reasonCode?: string;\n\n /** Optional: additional non-sensitive info */\n details?: string;\n};\n\n/**\n * Options for AuthorizationError factory methods.\n * Combines metadata fields (except 'reason') with common AppError options.\n */\ntype AuthorizationErrorFactoryOptions = Omit<\n AuthorizationErrorMetadata,\n \"reason\"\n> &\n Omit<AppErrorOptions, \"metadata\">;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// AuthorizationError\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Raised when an authenticated actor is not allowed to perform a business\n * action — the \"you may not\" error, distinct from authentication (\"who are\n * you\"). Maps to an HTTP 403 at the edge.\n *\n * The discriminating {@link reason} records *why* access was denied (a flat\n * forbid, a missing role/capability, an out-of-scope target, or a policy\n * decision) so the boundary can shape the response without re-deriving it. The\n * metadata is deliberately built around a stable business `action` and a\n * type/id resource reference rather than an HTTP route or full payload, keeping\n * sensitive data out of logs. Instances are frozen. Construct through the\n * static factories, never directly.\n */\nclass AuthorizationError extends AppError {\n public readonly reason: AuthorizationErrorReason;\n\n private constructor(params: {\n message: string;\n code: string;\n reason: AuthorizationErrorReason;\n metadata: AuthorizationErrorMetadata;\n cause?: unknown;\n type?: string;\n severity?: ErrorSeverity;\n correlationId?: string;\n requestId?: string;\n commandId?: string;\n createdAtIso?: string;\n publicMessage?: string;\n }) {\n super(params.message, params.code, {\n cause: params.cause,\n metadata: params.metadata,\n type: params.type,\n severity: params.severity,\n correlationId: params.correlationId,\n requestId: params.requestId,\n commandId: params.commandId,\n createdAtIso: params.createdAtIso,\n publicMessage: params.publicMessage,\n });\n\n this.reason = params.reason;\n Object.freeze(this);\n }\n\n // ─────────────────────────────────────────────────────────────────────────\n // Factories\n // ─────────────────────────────────────────────────────────────────────────\n\n /**\n * A flat denial with no more specific reason — the actor simply may not\n * perform this action. Reach for a more precise factory\n * ({@link AuthorizationError.missingCapability}, {@link AuthorizationError.outOfScope},\n * {@link AuthorizationError.policyDenied}) when the cause is known.\n */\n static forbidden(\n input: AuthorizationErrorFactoryOptions,\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Action not allowed\",\n code: ErrorCodes.authorization.forbidden,\n reason: \"forbidden\",\n metadata: { reason: \"forbidden\", ...extractMetadataOnly(input) },\n ...pickAppErrorOptions(input),\n });\n }\n\n /**\n * The action was denied by an evaluated policy. Captures the deciding\n * policy's id, version, and evaluation instant into the metadata (with\n * `decision: \"deny\"`) so the denial is auditable back to the exact policy\n * that produced it.\n *\n * @param input - Factory options plus the required `policyId`,\n * `policyVersion`, and `evaluatedAtIso` of the deciding policy.\n */\n static policyDenied(\n input: AuthorizationErrorFactoryOptions & {\n policyId: string;\n policyVersion: number;\n evaluatedAtIso: string;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Action denied by policy\",\n code: ErrorCodes.authorization.policyDenied,\n reason: \"policy_denied\",\n metadata: {\n reason: \"policy_denied\",\n ...extractMetadataOnly(input),\n decision: \"deny\",\n },\n ...pickAppErrorOptions(input),\n });\n }\n\n /**\n * The actor holds no role at all that bears on the action — the most basic\n * denial, distinct from {@link AuthorizationError.missingCapability} (which\n * means the actor *has* roles, just none granting the required capability).\n * The expected {@link AuthorizationRequirement} is recorded so the boundary\n * can tell the caller what grant is missing.\n *\n * @param input - Factory options plus the `required` role/capability/scope.\n */\n static missingRole(\n input: AuthorizationErrorFactoryOptions & {\n required: AuthorizationRequirement;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Missing required role to perform the action\",\n code: ErrorCodes.authorization.missingRole,\n reason: \"missing_role\",\n metadata: {\n reason: \"missing_role\",\n ...extractMetadataOnly(input),\n },\n ...pickAppErrorOptions(input),\n });\n }\n\n /**\n * The actor lacks a required role or capability. The expected\n * {@link AuthorizationRequirement} is recorded so the boundary can tell the\n * caller precisely what grant is missing.\n *\n * @param input - Factory options plus the `required` role/capability/scope.\n */\n static missingCapability(\n input: AuthorizationErrorFactoryOptions & {\n required: AuthorizationRequirement;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Insufficient capability to perform the action\",\n code: ErrorCodes.authorization.missingCapability,\n reason: \"missing_capability\",\n metadata: {\n reason: \"missing_capability\",\n ...extractMetadataOnly(input),\n },\n ...pickAppErrorOptions(input),\n });\n }\n\n /**\n * The actor may perform the action in general, but not on *this* target —\n * the resource falls outside the actor's permitted scope (e.g. a different\n * school or tenant than the one they are bound to).\n *\n * @param input - Factory options plus the optional `required` scope that the\n * target failed to satisfy.\n */\n static outOfScope(\n input: AuthorizationErrorFactoryOptions & {\n required?: AuthorizationRequirement;\n },\n ): AuthorizationError {\n return new AuthorizationError({\n message: \"Action outside the allowed scope\",\n code: ErrorCodes.authorization.outOfScope,\n reason: \"out_of_scope\",\n metadata: { reason: \"out_of_scope\", ...extractMetadataOnly(input) },\n ...pickAppErrorOptions(input),\n });\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Helpers\n// ─────────────────────────────────────────────────────────────────────────────\n\nfunction extractMetadataOnly(\n input: AuthorizationErrorFactoryOptions,\n): Omit<AuthorizationErrorMetadata, \"reason\"> {\n const {\n cause,\n type,\n severity,\n correlationId,\n requestId,\n commandId,\n createdAtIso,\n publicMessage,\n ...metadata\n } = input;\n return metadata;\n}\n\nexport { AuthorizationError };\nexport type {\n AuthorizationErrorMetadata,\n AuthorizationErrorReason,\n AuthorizationRequirement,\n};\n"],"mappings":";;;AAQA,MAAM,wBAAwB;CAC1B;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACJ;;;;;AAWA,SAAS,oBACL,OACgB;CAChB,OAAO;EACH,OAAO,OAAO;EACd,MAAM,OAAO;EACb,UAAU,OAAO;EACjB,eAAe,OAAO;EACtB,WAAW,OAAO;EAClB,WAAW,OAAO;EAClB,cAAc,OAAO;EACrB,eAAe,OAAO;CAC1B;AACJ;;;;;;AAOA,SAAS,qBACL,OAC+C;CAC/C,MAAM,SAAS,EAAE,GAAG,MAAM;CAC1B,KAAK,MAAM,OAAO,uBACd,OAAO,OAAO;CAElB,OAAO;AACX;;AAGA,SAAS,gBACL,OACa;CACb,IAAI,CAAC,OAAO,OAAO,KAAA;CAEnB,OAAO,OAAO,YACV,OAAO,QAAQ,KAAK,EAAE,QAAQ,GAAG,WAAW,UAAU,KAAA,CAAS,CACnE;AACJ;;;;;;;;;;;;;;;;ACcA,IAAM,qBAAN,MAAM,2BAA2B,SAAS;CAGtC,YAAoB,QAajB;EACC,MAAM,OAAO,SAAS,OAAO,MAAM;GAC/B,OAAO,OAAO;GACd,UAAU,OAAO;GACjB,MAAM,OAAO;GACb,UAAU,OAAO;GACjB,eAAe,OAAO;GACtB,WAAW,OAAO;GAClB,WAAW,OAAO;GAClB,cAAc,OAAO;GACrB,eAAe,OAAO;EAC1B,CAAC;EAED,KAAK,SAAS,OAAO;EACrB,OAAO,OAAO,IAAI;CACtB;;;;;;;CAYA,OAAO,UACH,OACkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IAAE,QAAQ;IAAa,GAAG,oBAAoB,KAAK;GAAE;GAC/D,GAAG,oBAAoB,KAAK;EAChC,CAAC;CACL;;;;;;;;;;CAWA,OAAO,aACH,OAKkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IACN,QAAQ;IACR,GAAG,oBAAoB,KAAK;IAC5B,UAAU;GACd;GACA,GAAG,oBAAoB,KAAK;EAChC,CAAC;CACL;;;;;;;;;;CAWA,OAAO,YACH,OAGkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IACN,QAAQ;IACR,GAAG,oBAAoB,KAAK;GAChC;GACA,GAAG,oBAAoB,KAAK;EAChC,CAAC;CACL;;;;;;;;CASA,OAAO,kBACH,OAGkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IACN,QAAQ;IACR,GAAG,oBAAoB,KAAK;GAChC;GACA,GAAG,oBAAoB,KAAK;EAChC,CAAC;CACL;;;;;;;;;CAUA,OAAO,WACH,OAGkB;EAClB,OAAO,IAAI,mBAAmB;GAC1B,SAAS;GACT,MAAM,WAAW,cAAc;GAC/B,QAAQ;GACR,UAAU;IAAE,QAAQ;IAAgB,GAAG,oBAAoB,KAAK;GAAE;GAClE,GAAG,oBAAoB,KAAK;EAChC,CAAC;CACL;AACJ;AAMA,SAAS,oBACL,OAC0C;CAC1C,MAAM,EACF,OACA,MACA,UACA,eACA,WACA,WACA,cACA,eACA,GAAG,aACH;CACJ,OAAO;AACX"}
|
|
@@ -68,7 +68,12 @@ type ScopeProps = {
|
|
|
68
68
|
*/
|
|
69
69
|
declare class Scope extends ValueObject<ScopeProps, string> {
|
|
70
70
|
private constructor();
|
|
71
|
-
/**
|
|
71
|
+
/**
|
|
72
|
+
* Validates `"type:id"` or the global `"*"`, throwing on anything else.
|
|
73
|
+
* `Scope.of("*")` is accepted and is equivalent to {@link Scope.global} —
|
|
74
|
+
* prefer `global()` at call-sites for intent, `of("*")` when rehydrating a
|
|
75
|
+
* stored string.
|
|
76
|
+
*/
|
|
72
77
|
static of(raw: string): Scope;
|
|
73
78
|
/** The global scope `"*"`, which {@link includes} every other scope. */
|
|
74
79
|
static global(): Scope;
|
|
@@ -101,12 +106,22 @@ interface AccessRequest {
|
|
|
101
106
|
* Never a wildcard — only the *granted* permissions on roles may wildcard.
|
|
102
107
|
*/
|
|
103
108
|
readonly required: Permission;
|
|
104
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* The target resource, identified without leaking its payload. Carried for
|
|
111
|
+
* audit metadata only — the RBAC decisor does **not** check it. Per-resource
|
|
112
|
+
* ownership (this actor may cancel *this* order) is an ABAC/policy concern,
|
|
113
|
+
* not a role/permission one.
|
|
114
|
+
*/
|
|
105
115
|
readonly resource?: {
|
|
106
116
|
readonly type: string;
|
|
107
117
|
readonly id?: string;
|
|
108
118
|
};
|
|
109
|
-
/**
|
|
119
|
+
/**
|
|
120
|
+
* The scope the resource lives in, e.g. `Scope.of("school:123")`. Asking in
|
|
121
|
+
* the global scope (`Scope.global()`) means "may I do this *everywhere*?" and
|
|
122
|
+
* so requires a globally-scoped grant — it is **not** "in any scope I happen
|
|
123
|
+
* to hold". Ask about a concrete scope to check a bounded grant.
|
|
124
|
+
*/
|
|
110
125
|
readonly scope: Scope;
|
|
111
126
|
}
|
|
112
127
|
//#endregion
|
|
@@ -68,7 +68,12 @@ type ScopeProps = {
|
|
|
68
68
|
*/
|
|
69
69
|
declare class Scope extends ValueObject<ScopeProps, string> {
|
|
70
70
|
private constructor();
|
|
71
|
-
/**
|
|
71
|
+
/**
|
|
72
|
+
* Validates `"type:id"` or the global `"*"`, throwing on anything else.
|
|
73
|
+
* `Scope.of("*")` is accepted and is equivalent to {@link Scope.global} —
|
|
74
|
+
* prefer `global()` at call-sites for intent, `of("*")` when rehydrating a
|
|
75
|
+
* stored string.
|
|
76
|
+
*/
|
|
72
77
|
static of(raw: string): Scope;
|
|
73
78
|
/** The global scope `"*"`, which {@link includes} every other scope. */
|
|
74
79
|
static global(): Scope;
|
|
@@ -101,12 +106,22 @@ interface AccessRequest {
|
|
|
101
106
|
* Never a wildcard — only the *granted* permissions on roles may wildcard.
|
|
102
107
|
*/
|
|
103
108
|
readonly required: Permission;
|
|
104
|
-
/**
|
|
109
|
+
/**
|
|
110
|
+
* The target resource, identified without leaking its payload. Carried for
|
|
111
|
+
* audit metadata only — the RBAC decisor does **not** check it. Per-resource
|
|
112
|
+
* ownership (this actor may cancel *this* order) is an ABAC/policy concern,
|
|
113
|
+
* not a role/permission one.
|
|
114
|
+
*/
|
|
105
115
|
readonly resource?: {
|
|
106
116
|
readonly type: string;
|
|
107
117
|
readonly id?: string;
|
|
108
118
|
};
|
|
109
|
-
/**
|
|
119
|
+
/**
|
|
120
|
+
* The scope the resource lives in, e.g. `Scope.of("school:123")`. Asking in
|
|
121
|
+
* the global scope (`Scope.global()`) means "may I do this *everywhere*?" and
|
|
122
|
+
* so requires a globally-scoped grant — it is **not** "in any scope I happen
|
|
123
|
+
* to hold". Ask about a concrete scope to check a bounded grant.
|
|
124
|
+
*/
|
|
110
125
|
readonly scope: Scope;
|
|
111
126
|
}
|
|
112
127
|
//#endregion
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as RequestedBy } from "./requested-by.cjs";
|
|
2
2
|
import { t as AuthorizationError } from "./authorization-error.cjs";
|
|
3
3
|
import { r as Result } from "./result.cjs";
|
|
4
|
-
import {
|
|
4
|
+
import { A as ConditionNode, t as CoreConfig, w as PolicyContext } from "./core-config.cjs";
|
|
5
5
|
import { t as ValueObject } from "./value-object.cjs";
|
|
6
6
|
import { n as AccessRequest, t as AuthorizerPort } from "./authorizer.port.cjs";
|
|
7
7
|
|
|
@@ -93,6 +93,26 @@ type AbacRuleProps = {
|
|
|
93
93
|
* authored in TypeScript — trusted data, not untrusted JSON — the structural
|
|
94
94
|
* check is a hand-rolled walk of the condition tree rather than a schema parse.
|
|
95
95
|
* Build one through {@link of}; the constructor is private.
|
|
96
|
+
*
|
|
97
|
+
* **Attribute semantics a rule author must know (the condition is evaluated by
|
|
98
|
+
* the shared gate/compute engine, whose runtime rules apply here too):**
|
|
99
|
+
* - **A referenced attribute that is *absent* from the request is a technical
|
|
100
|
+
* evaluation error, not a non-match.** By default (`onEvaluationError:
|
|
101
|
+
* "fail-closed"` on the {@link AbacPolicySet}) that error fails the *entire*
|
|
102
|
+
* decision closed — so adding a rule that reads an attribute a given call site
|
|
103
|
+
* does not yet populate makes that call site start returning `forbidden`,
|
|
104
|
+
* *even for requests the older rules used to permit*. Choose
|
|
105
|
+
* `onEvaluationError: "skip-rule"` on the set to skip an unevaluable rule
|
|
106
|
+
* instead of failing the whole set.
|
|
107
|
+
* - **`isNull` / `isNotNull` test for an explicit `null`/`undefined` *value*, not
|
|
108
|
+
* for a missing key.** A key that is absent from the bag never reaches the
|
|
109
|
+
* operator — it short-circuits to the missing-attribute error above. To match
|
|
110
|
+
* "no deletedAt", the consumer must put `deletedAt: null` in the bag, not omit
|
|
111
|
+
* it. Pass `allowNull: true` on a relational leaf to treat a present `null` as
|
|
112
|
+
* a non-match instead of an error.
|
|
113
|
+
* - **Date comparison operands must be strict ISO-8601 UTC**
|
|
114
|
+
* (`YYYY-MM-DDTHH:mm:ss.sssZ`); a bare `"2026-07-09"` or an offset like
|
|
115
|
+
* `+00:00` is rejected as an invalid operand and fails closed.
|
|
96
116
|
*/
|
|
97
117
|
declare class AbacRule extends ValueObject<AbacRuleProps, AbacRuleProps> {
|
|
98
118
|
private constructor();
|
|
@@ -128,28 +148,51 @@ type CombiningAlgorithm = "deny-overrides" | "permit-overrides" | "first-applica
|
|
|
128
148
|
/** The resolved decision plus the rule (if any) that produced it. */
|
|
129
149
|
//#endregion
|
|
130
150
|
//#region src/core/abac/domain/policy-set.d.ts
|
|
151
|
+
/**
|
|
152
|
+
* How the {@link AbacAuthorizer} reacts when a rule's condition cannot be
|
|
153
|
+
* evaluated (a referenced attribute is absent, an operand is wrong-typed).
|
|
154
|
+
*
|
|
155
|
+
* - `fail-closed` (default, secure): the whole decision fails closed as
|
|
156
|
+
* `forbidden`. Safe, but it means adding a rule that reads an attribute a call
|
|
157
|
+
* site does not populate makes that call site deny everything until it does.
|
|
158
|
+
* - `skip-rule`: the unevaluable rule is dropped from the applicable set and the
|
|
159
|
+
* remaining rules decide — the escape valve for evolving rules without
|
|
160
|
+
* trailing every call site. The evaluator still reports the anomaly.
|
|
161
|
+
*/
|
|
162
|
+
type OnEvaluationError = "fail-closed" | "skip-rule";
|
|
131
163
|
/**
|
|
132
164
|
* An ordered collection of {@link AbacRule}s plus how to combine them
|
|
133
|
-
* ({@link CombiningAlgorithm})
|
|
134
|
-
* ({@link defaultEffect})
|
|
165
|
+
* ({@link CombiningAlgorithm}), what to decide when no rule applies
|
|
166
|
+
* ({@link defaultEffect}), and how to react to an unevaluable rule
|
|
167
|
+
* ({@link onEvaluationError}). This is where ABAC goes beyond a single gate
|
|
135
168
|
* condition: several PERMIT/DENY rules resolved by an explicit algorithm.
|
|
136
169
|
*
|
|
137
|
-
* Closed by default — the combining algorithm defaults to `"deny-overrides"
|
|
138
|
-
* the default effect to `"DENY"`,
|
|
139
|
-
*
|
|
170
|
+
* Closed by default — the combining algorithm defaults to `"deny-overrides"`,
|
|
171
|
+
* the default effect to `"DENY"`, and evaluation errors to `"fail-closed"`, so a
|
|
172
|
+
* request matching nothing (or hitting a technical error) is denied. A plain
|
|
173
|
+
* holder (not a value object); build through {@link of}.
|
|
140
174
|
*/
|
|
141
175
|
declare class AbacPolicySet {
|
|
142
176
|
private readonly _rules;
|
|
143
177
|
private readonly _algorithm;
|
|
144
178
|
private readonly _defaultEffect;
|
|
179
|
+
private readonly _onEvaluationError;
|
|
145
180
|
private constructor();
|
|
181
|
+
/**
|
|
182
|
+
* Builds a policy set. Rejects duplicate rule ids with
|
|
183
|
+
* {@link InvalidValueException} so a denial's `policyId` attribution is
|
|
184
|
+
* unambiguous.
|
|
185
|
+
*/
|
|
146
186
|
static of(rules: readonly AbacRule[], options?: {
|
|
147
187
|
readonly algorithm?: CombiningAlgorithm;
|
|
148
188
|
readonly defaultEffect?: RuleEffect;
|
|
189
|
+
readonly onEvaluationError?: OnEvaluationError;
|
|
149
190
|
}): AbacPolicySet;
|
|
191
|
+
private static assertUniqueIds;
|
|
150
192
|
get rules(): readonly AbacRule[];
|
|
151
193
|
get algorithm(): CombiningAlgorithm;
|
|
152
194
|
get defaultEffect(): RuleEffect;
|
|
195
|
+
get onEvaluationError(): OnEvaluationError;
|
|
153
196
|
}
|
|
154
197
|
//#endregion
|
|
155
198
|
//#region src/core/abac/authorizer.d.ts
|
|
@@ -173,17 +216,27 @@ interface AbacDecision {
|
|
|
173
216
|
* "errors as values" contract of `RbacAuthorizer`/`GateEngineV1`.
|
|
174
217
|
*
|
|
175
218
|
* A denial maps to {@link AuthorizationError.policyDenied}, attributed to the
|
|
176
|
-
* deciding rule's `id`/`version
|
|
219
|
+
* deciding rule's `id`/`version`. A condition-evaluation failure (a missing
|
|
177
220
|
* attribute, a wrong-typed operand) fails closed as
|
|
178
|
-
* {@link AuthorizationError.forbidden}
|
|
179
|
-
*
|
|
221
|
+
* {@link AuthorizationError.forbidden} — also attributed to the culprit rule's
|
|
222
|
+
* `id`/`version` — unless the set opts into `onEvaluationError: "skip-rule"`, in
|
|
223
|
+
* which case the unevaluable rule is skipped and the rest decide. Every resolved
|
|
224
|
+
* decision (PERMIT and DENY) is emitted best-effort through the configured
|
|
225
|
+
* reporter as an `abac-decision` event (silent by default). Timestamps come from
|
|
226
|
+
* an injectable `clock` (default `() => new Date()`), so the decisor is pure
|
|
227
|
+
* given one. Loading the dynamic attributes is the consumer's job (behind an
|
|
228
|
+
* `AbacAuthorizerPort` adapter); this class only decides.
|
|
180
229
|
*/
|
|
181
230
|
declare class AbacAuthorizer {
|
|
182
231
|
private readonly coreConfig;
|
|
232
|
+
private readonly clock;
|
|
183
233
|
constructor(params?: {
|
|
184
234
|
readonly coreConfig?: CoreConfig;
|
|
235
|
+
/** Injectable clock for deterministic timestamps; defaults to `() => new Date()`. */
|
|
236
|
+
readonly clock?: () => Date;
|
|
185
237
|
});
|
|
186
238
|
authorize(request: AbacRequest, policies: AbacPolicySet): Result<AbacDecision, AuthorizationError>;
|
|
239
|
+
private reportDecision;
|
|
187
240
|
}
|
|
188
241
|
//#endregion
|
|
189
242
|
//#region src/core/abac/composite-authorizer.d.ts
|
|
@@ -212,5 +265,5 @@ declare class CompositeAuthorizer {
|
|
|
212
265
|
authorize(request: CompositeAccessRequest): Promise<Result<void, AuthorizationError>>;
|
|
213
266
|
}
|
|
214
267
|
//#endregion
|
|
215
|
-
export { AbacPolicySet as a,
|
|
268
|
+
export { AbacPolicySet as a, AbacRule as c, abacContext as d, AbacAuthorizerPort as f, AbacDecision as i, AbacRuleProps as l, AbacRequest as m, CompositeAuthorizer as n, OnEvaluationError as o, AbacAttributes as p, AbacAuthorizer as r, CombiningAlgorithm as s, CompositeAccessRequest as t, RuleEffect as u };
|
|
216
269
|
//# sourceMappingURL=composite-authorizer.d.cts.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { t as RequestedBy } from "./requested-by.js";
|
|
2
2
|
import { t as AuthorizationError } from "./authorization-error.js";
|
|
3
3
|
import { r as Result } from "./result.js";
|
|
4
|
-
import {
|
|
4
|
+
import { A as ConditionNode, t as CoreConfig, w as PolicyContext } from "./core-config.js";
|
|
5
5
|
import { t as ValueObject } from "./value-object.js";
|
|
6
6
|
import { n as AccessRequest, t as AuthorizerPort } from "./authorizer.port.js";
|
|
7
7
|
|
|
@@ -93,6 +93,26 @@ type AbacRuleProps = {
|
|
|
93
93
|
* authored in TypeScript — trusted data, not untrusted JSON — the structural
|
|
94
94
|
* check is a hand-rolled walk of the condition tree rather than a schema parse.
|
|
95
95
|
* Build one through {@link of}; the constructor is private.
|
|
96
|
+
*
|
|
97
|
+
* **Attribute semantics a rule author must know (the condition is evaluated by
|
|
98
|
+
* the shared gate/compute engine, whose runtime rules apply here too):**
|
|
99
|
+
* - **A referenced attribute that is *absent* from the request is a technical
|
|
100
|
+
* evaluation error, not a non-match.** By default (`onEvaluationError:
|
|
101
|
+
* "fail-closed"` on the {@link AbacPolicySet}) that error fails the *entire*
|
|
102
|
+
* decision closed — so adding a rule that reads an attribute a given call site
|
|
103
|
+
* does not yet populate makes that call site start returning `forbidden`,
|
|
104
|
+
* *even for requests the older rules used to permit*. Choose
|
|
105
|
+
* `onEvaluationError: "skip-rule"` on the set to skip an unevaluable rule
|
|
106
|
+
* instead of failing the whole set.
|
|
107
|
+
* - **`isNull` / `isNotNull` test for an explicit `null`/`undefined` *value*, not
|
|
108
|
+
* for a missing key.** A key that is absent from the bag never reaches the
|
|
109
|
+
* operator — it short-circuits to the missing-attribute error above. To match
|
|
110
|
+
* "no deletedAt", the consumer must put `deletedAt: null` in the bag, not omit
|
|
111
|
+
* it. Pass `allowNull: true` on a relational leaf to treat a present `null` as
|
|
112
|
+
* a non-match instead of an error.
|
|
113
|
+
* - **Date comparison operands must be strict ISO-8601 UTC**
|
|
114
|
+
* (`YYYY-MM-DDTHH:mm:ss.sssZ`); a bare `"2026-07-09"` or an offset like
|
|
115
|
+
* `+00:00` is rejected as an invalid operand and fails closed.
|
|
96
116
|
*/
|
|
97
117
|
declare class AbacRule extends ValueObject<AbacRuleProps, AbacRuleProps> {
|
|
98
118
|
private constructor();
|
|
@@ -128,28 +148,51 @@ type CombiningAlgorithm = "deny-overrides" | "permit-overrides" | "first-applica
|
|
|
128
148
|
/** The resolved decision plus the rule (if any) that produced it. */
|
|
129
149
|
//#endregion
|
|
130
150
|
//#region src/core/abac/domain/policy-set.d.ts
|
|
151
|
+
/**
|
|
152
|
+
* How the {@link AbacAuthorizer} reacts when a rule's condition cannot be
|
|
153
|
+
* evaluated (a referenced attribute is absent, an operand is wrong-typed).
|
|
154
|
+
*
|
|
155
|
+
* - `fail-closed` (default, secure): the whole decision fails closed as
|
|
156
|
+
* `forbidden`. Safe, but it means adding a rule that reads an attribute a call
|
|
157
|
+
* site does not populate makes that call site deny everything until it does.
|
|
158
|
+
* - `skip-rule`: the unevaluable rule is dropped from the applicable set and the
|
|
159
|
+
* remaining rules decide — the escape valve for evolving rules without
|
|
160
|
+
* trailing every call site. The evaluator still reports the anomaly.
|
|
161
|
+
*/
|
|
162
|
+
type OnEvaluationError = "fail-closed" | "skip-rule";
|
|
131
163
|
/**
|
|
132
164
|
* An ordered collection of {@link AbacRule}s plus how to combine them
|
|
133
|
-
* ({@link CombiningAlgorithm})
|
|
134
|
-
* ({@link defaultEffect})
|
|
165
|
+
* ({@link CombiningAlgorithm}), what to decide when no rule applies
|
|
166
|
+
* ({@link defaultEffect}), and how to react to an unevaluable rule
|
|
167
|
+
* ({@link onEvaluationError}). This is where ABAC goes beyond a single gate
|
|
135
168
|
* condition: several PERMIT/DENY rules resolved by an explicit algorithm.
|
|
136
169
|
*
|
|
137
|
-
* Closed by default — the combining algorithm defaults to `"deny-overrides"
|
|
138
|
-
* the default effect to `"DENY"`,
|
|
139
|
-
*
|
|
170
|
+
* Closed by default — the combining algorithm defaults to `"deny-overrides"`,
|
|
171
|
+
* the default effect to `"DENY"`, and evaluation errors to `"fail-closed"`, so a
|
|
172
|
+
* request matching nothing (or hitting a technical error) is denied. A plain
|
|
173
|
+
* holder (not a value object); build through {@link of}.
|
|
140
174
|
*/
|
|
141
175
|
declare class AbacPolicySet {
|
|
142
176
|
private readonly _rules;
|
|
143
177
|
private readonly _algorithm;
|
|
144
178
|
private readonly _defaultEffect;
|
|
179
|
+
private readonly _onEvaluationError;
|
|
145
180
|
private constructor();
|
|
181
|
+
/**
|
|
182
|
+
* Builds a policy set. Rejects duplicate rule ids with
|
|
183
|
+
* {@link InvalidValueException} so a denial's `policyId` attribution is
|
|
184
|
+
* unambiguous.
|
|
185
|
+
*/
|
|
146
186
|
static of(rules: readonly AbacRule[], options?: {
|
|
147
187
|
readonly algorithm?: CombiningAlgorithm;
|
|
148
188
|
readonly defaultEffect?: RuleEffect;
|
|
189
|
+
readonly onEvaluationError?: OnEvaluationError;
|
|
149
190
|
}): AbacPolicySet;
|
|
191
|
+
private static assertUniqueIds;
|
|
150
192
|
get rules(): readonly AbacRule[];
|
|
151
193
|
get algorithm(): CombiningAlgorithm;
|
|
152
194
|
get defaultEffect(): RuleEffect;
|
|
195
|
+
get onEvaluationError(): OnEvaluationError;
|
|
153
196
|
}
|
|
154
197
|
//#endregion
|
|
155
198
|
//#region src/core/abac/authorizer.d.ts
|
|
@@ -173,17 +216,27 @@ interface AbacDecision {
|
|
|
173
216
|
* "errors as values" contract of `RbacAuthorizer`/`GateEngineV1`.
|
|
174
217
|
*
|
|
175
218
|
* A denial maps to {@link AuthorizationError.policyDenied}, attributed to the
|
|
176
|
-
* deciding rule's `id`/`version
|
|
219
|
+
* deciding rule's `id`/`version`. A condition-evaluation failure (a missing
|
|
177
220
|
* attribute, a wrong-typed operand) fails closed as
|
|
178
|
-
* {@link AuthorizationError.forbidden}
|
|
179
|
-
*
|
|
221
|
+
* {@link AuthorizationError.forbidden} — also attributed to the culprit rule's
|
|
222
|
+
* `id`/`version` — unless the set opts into `onEvaluationError: "skip-rule"`, in
|
|
223
|
+
* which case the unevaluable rule is skipped and the rest decide. Every resolved
|
|
224
|
+
* decision (PERMIT and DENY) is emitted best-effort through the configured
|
|
225
|
+
* reporter as an `abac-decision` event (silent by default). Timestamps come from
|
|
226
|
+
* an injectable `clock` (default `() => new Date()`), so the decisor is pure
|
|
227
|
+
* given one. Loading the dynamic attributes is the consumer's job (behind an
|
|
228
|
+
* `AbacAuthorizerPort` adapter); this class only decides.
|
|
180
229
|
*/
|
|
181
230
|
declare class AbacAuthorizer {
|
|
182
231
|
private readonly coreConfig;
|
|
232
|
+
private readonly clock;
|
|
183
233
|
constructor(params?: {
|
|
184
234
|
readonly coreConfig?: CoreConfig;
|
|
235
|
+
/** Injectable clock for deterministic timestamps; defaults to `() => new Date()`. */
|
|
236
|
+
readonly clock?: () => Date;
|
|
185
237
|
});
|
|
186
238
|
authorize(request: AbacRequest, policies: AbacPolicySet): Result<AbacDecision, AuthorizationError>;
|
|
239
|
+
private reportDecision;
|
|
187
240
|
}
|
|
188
241
|
//#endregion
|
|
189
242
|
//#region src/core/abac/composite-authorizer.d.ts
|
|
@@ -212,5 +265,5 @@ declare class CompositeAuthorizer {
|
|
|
212
265
|
authorize(request: CompositeAccessRequest): Promise<Result<void, AuthorizationError>>;
|
|
213
266
|
}
|
|
214
267
|
//#endregion
|
|
215
|
-
export { AbacPolicySet as a,
|
|
268
|
+
export { AbacPolicySet as a, AbacRule as c, abacContext as d, AbacAuthorizerPort as f, AbacDecision as i, AbacRuleProps as l, AbacRequest as m, CompositeAuthorizer as n, OnEvaluationError as o, AbacAttributes as p, AbacAuthorizer as r, CombiningAlgorithm as s, CompositeAccessRequest as t, RuleEffect as u };
|
|
216
269
|
//# sourceMappingURL=composite-authorizer.d.ts.map
|