@cullet/erp-core 1.2.0 → 1.4.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.
Files changed (218) hide show
  1. package/KIT_CONTEXT.md +5 -3
  2. package/README.md +160 -0
  3. package/dist/abac/index.cjs +7 -0
  4. package/dist/abac/index.d.cts +2 -0
  5. package/dist/abac/index.d.ts +2 -0
  6. package/dist/abac/index.js +2 -0
  7. package/dist/app-error.cjs +193 -0
  8. package/dist/app-error.cjs.map +1 -0
  9. package/dist/app-error.d.cts +108 -0
  10. package/dist/app-error.js +170 -0
  11. package/dist/app-error.js.map +1 -0
  12. package/dist/application/index.cjs +27 -0
  13. package/dist/application/index.d.cts +3 -0
  14. package/dist/application/index.d.ts +2 -1
  15. package/dist/application/index.js +2 -1
  16. package/dist/authorization-error.cjs +157 -0
  17. package/dist/authorization-error.cjs.map +1 -0
  18. package/dist/authorization-error.d.cts +113 -0
  19. package/dist/authorization-error.d.ts +113 -0
  20. package/dist/authorization-error.js +152 -0
  21. package/dist/authorization-error.js.map +1 -0
  22. package/dist/authorizer.port.d.cts +130 -0
  23. package/dist/authorizer.port.d.ts +130 -0
  24. package/dist/composite-authorizer.d.cts +216 -0
  25. package/dist/composite-authorizer.d.ts +216 -0
  26. package/dist/condition-evaluator.cjs +565 -0
  27. package/dist/condition-evaluator.cjs.map +1 -0
  28. package/dist/condition-evaluator.js +536 -0
  29. package/dist/condition-evaluator.js.map +1 -0
  30. package/dist/core-config.d.cts +172 -0
  31. package/dist/{gate-types.d.ts → core-config.d.ts} +78 -77
  32. package/dist/domain/index.cjs +17 -0
  33. package/dist/domain/index.d.cts +4 -0
  34. package/dist/domain/index.d.ts +2 -1
  35. package/dist/domain/index.js +2 -1
  36. package/dist/domain-event-contracts.cjs +34 -0
  37. package/dist/domain-event-contracts.cjs.map +1 -0
  38. package/dist/domain-event-contracts.d.cts +27 -0
  39. package/dist/domain-event-contracts.js +2 -1
  40. package/dist/domain-event-contracts.js.map +1 -1
  41. package/dist/domain-exception.cjs +17 -0
  42. package/dist/domain-exception.cjs.map +1 -0
  43. package/dist/domain-exception.d.cts +7 -0
  44. package/dist/entity.cjs +126 -0
  45. package/dist/entity.cjs.map +1 -0
  46. package/dist/entity.js +115 -0
  47. package/dist/entity.js.map +1 -0
  48. package/dist/errors/index.cjs +43 -0
  49. package/dist/errors/index.d.cts +4 -0
  50. package/dist/errors/index.d.ts +2 -1
  51. package/dist/errors/index.js +4 -2
  52. package/dist/exceptions/index.cjs +17 -0
  53. package/dist/exceptions/index.d.cts +5 -0
  54. package/dist/exceptions/validation-field.cjs +3 -0
  55. package/dist/exceptions/validation-field.d.cts +2 -0
  56. package/dist/gate-engine-registry.cjs +309 -0
  57. package/dist/gate-engine-registry.cjs.map +1 -0
  58. package/dist/gate-engine-registry.d.cts +82 -0
  59. package/dist/gate-engine-registry.d.ts +3 -2
  60. package/dist/gate-engine-registry.js +2 -1
  61. package/dist/gate-engine-registry.js.map +1 -1
  62. package/dist/gate-v1-payload.schema.cjs +76 -0
  63. package/dist/gate-v1-payload.schema.cjs.map +1 -0
  64. package/dist/gate-v1-payload.schema.js +1 -533
  65. package/dist/gate-v1-payload.schema.js.map +1 -1
  66. package/dist/hashing.cjs +66 -0
  67. package/dist/hashing.cjs.map +1 -0
  68. package/dist/immutable.cjs +77 -0
  69. package/dist/immutable.cjs.map +1 -0
  70. package/dist/immutable.d.cts +6 -0
  71. package/dist/index.cjs +181 -0
  72. package/dist/index.cjs.map +1 -0
  73. package/dist/index.d.cts +37 -0
  74. package/dist/index.d.ts +19 -12
  75. package/dist/index.js +15 -9
  76. package/dist/index.js.map +1 -1
  77. package/dist/invalid-state-transition-exception.cjs +47 -0
  78. package/dist/invalid-state-transition-exception.cjs.map +1 -0
  79. package/dist/invariant-violation-exception.cjs +16 -0
  80. package/dist/invariant-violation-exception.cjs.map +1 -0
  81. package/dist/not-found-error.cjs +65 -0
  82. package/dist/not-found-error.cjs.map +1 -0
  83. package/dist/not-found-error.js +1 -1
  84. package/dist/outcome.cjs +97 -0
  85. package/dist/outcome.cjs.map +1 -0
  86. package/dist/outcome.d.cts +58 -0
  87. package/dist/outcome.d.ts +1 -83
  88. package/dist/parse-gate-payload.d.cts +62 -0
  89. package/dist/parse-gate-payload.d.ts +2 -2
  90. package/dist/path.d.cts +90 -0
  91. package/dist/path.d.ts +2 -2
  92. package/dist/plugin.cjs +79 -0
  93. package/dist/plugin.cjs.map +1 -0
  94. package/dist/plugin.d.cts +85 -0
  95. package/dist/plugins/index.cjs +3 -0
  96. package/dist/plugins/index.d.cts +2 -0
  97. package/dist/policies/engines/index.cjs +10 -0
  98. package/dist/policies/engines/index.d.cts +4 -0
  99. package/dist/policies/engines/index.d.ts +1 -1
  100. package/dist/policies/engines/v1/gate/index.cjs +92 -0
  101. package/dist/policies/engines/v1/gate/index.cjs.map +1 -0
  102. package/dist/policies/engines/v1/gate/index.d.cts +121 -0
  103. package/dist/policies/engines/v1/gate/index.d.ts +2 -2
  104. package/dist/policies/engines/v1/gate/index.js +2 -1
  105. package/dist/policies/engines/v1/gate/index.js.map +1 -1
  106. package/dist/policies/index.cjs +41 -0
  107. package/dist/policies/index.d.cts +8 -0
  108. package/dist/policies/index.d.ts +3 -2
  109. package/dist/policies/index.js +2 -2
  110. package/dist/policy-bridge.cjs +437 -0
  111. package/dist/policy-bridge.cjs.map +1 -0
  112. package/dist/policy-bridge.d.cts +185 -0
  113. package/dist/policy-bridge.d.ts +185 -0
  114. package/dist/policy-bridge.js +396 -0
  115. package/dist/policy-bridge.js.map +1 -0
  116. package/dist/policy-service.cjs +1190 -0
  117. package/dist/policy-service.cjs.map +1 -0
  118. package/dist/policy-service.d.cts +559 -0
  119. package/dist/policy-service.d.ts +2 -2
  120. package/dist/policy-service.js +239 -239
  121. package/dist/policy-service.js.map +1 -1
  122. package/dist/rbac/index.cjs +9 -0
  123. package/dist/rbac/index.d.cts +3 -0
  124. package/dist/rbac/index.d.ts +3 -0
  125. package/dist/rbac/index.js +2 -0
  126. package/dist/requested-by.cjs +54 -0
  127. package/dist/requested-by.cjs.map +1 -0
  128. package/dist/requested-by.d.cts +25 -0
  129. package/dist/requested-by.d.ts +25 -0
  130. package/dist/requested-by.js +49 -0
  131. package/dist/requested-by.js.map +1 -0
  132. package/dist/result/index.cjs +7 -0
  133. package/dist/result/index.d.cts +3 -0
  134. package/dist/result/index.d.ts +2 -1
  135. package/dist/result.cjs +135 -0
  136. package/dist/result.cjs.map +1 -0
  137. package/dist/result.d.cts +84 -0
  138. package/dist/result.d.ts +84 -0
  139. package/dist/rule.cjs +327 -0
  140. package/dist/rule.cjs.map +1 -0
  141. package/dist/rule.js +298 -0
  142. package/dist/rule.js.map +1 -0
  143. package/dist/ruleset-registry.cjs +47 -0
  144. package/dist/ruleset-registry.cjs.map +1 -0
  145. package/dist/rulesets/index.cjs +3 -0
  146. package/dist/rulesets/index.d.cts +2 -0
  147. package/dist/temporal-guards.cjs +32 -0
  148. package/dist/temporal-guards.cjs.map +1 -0
  149. package/dist/temporal-use-case.cjs +139 -0
  150. package/dist/temporal-use-case.cjs.map +1 -0
  151. package/dist/temporal-use-case.d.cts +282 -0
  152. package/dist/temporal-use-case.d.ts +5 -27
  153. package/dist/temporal-use-case.js +2 -48
  154. package/dist/temporal-use-case.js.map +1 -1
  155. package/dist/unexpected-error.cjs +19 -0
  156. package/dist/unexpected-error.cjs.map +1 -0
  157. package/dist/unexpected-error.js +2 -167
  158. package/dist/unexpected-error.js.map +1 -1
  159. package/dist/use-case.cjs +96 -0
  160. package/dist/use-case.cjs.map +1 -0
  161. package/dist/uuid-identifier.cjs +65 -0
  162. package/dist/uuid-identifier.cjs.map +1 -0
  163. package/dist/uuid-identifier.d.cts +147 -0
  164. package/dist/uuid-identifier.d.ts +2 -85
  165. package/dist/validation-code.cjs +60 -0
  166. package/dist/validation-code.cjs.map +1 -0
  167. package/dist/validation-code.d.cts +23 -0
  168. package/dist/validation-error.cjs +887 -0
  169. package/dist/validation-error.cjs.map +1 -0
  170. package/dist/validation-error.d.cts +681 -0
  171. package/dist/validation-error.d.ts +2 -98
  172. package/dist/validation-error.js +7 -134
  173. package/dist/validation-error.js.map +1 -1
  174. package/dist/validation-exception.cjs +41 -0
  175. package/dist/validation-exception.cjs.map +1 -0
  176. package/dist/validation-exception.d.cts +50 -0
  177. package/dist/validation-field.cjs +28 -0
  178. package/dist/validation-field.cjs.map +1 -0
  179. package/dist/validation-field.d.cts +12 -0
  180. package/dist/value-object-ruleset.contracts.d.cts +36 -0
  181. package/dist/value-object.cjs +85 -0
  182. package/dist/value-object.cjs.map +1 -0
  183. package/dist/value-object.d.cts +89 -0
  184. package/dist/value-object.d.ts +89 -0
  185. package/dist/value-object.js +1 -112
  186. package/dist/value-object.js.map +1 -1
  187. package/dist/version.d.cts +10 -0
  188. package/dist/versioning/index.cjs +7 -0
  189. package/dist/versioning/index.d.cts +3 -0
  190. package/meta.json +19 -4
  191. package/package.json +173 -28
  192. package/src/abac/index.ts +1 -0
  193. package/src/core/abac/abac-request.ts +29 -0
  194. package/src/core/abac/attributes.ts +39 -0
  195. package/src/core/abac/authorizer.ts +108 -0
  196. package/src/core/abac/combining.ts +63 -0
  197. package/src/core/abac/composite-authorizer.ts +45 -0
  198. package/src/core/abac/domain/policy-set.ts +52 -0
  199. package/src/core/abac/domain/rule.ts +197 -0
  200. package/src/core/abac/index.ts +21 -0
  201. package/src/core/application/ports/abac-authorizer.port.ts +20 -0
  202. package/src/core/application/ports/authorizer.port.ts +22 -0
  203. package/src/core/errors/authorization-error.ts +26 -0
  204. package/src/core/errors/error-codes.ts +1 -0
  205. package/src/core/index.ts +7 -0
  206. package/src/core/rbac/access-request.ts +32 -0
  207. package/src/core/rbac/authorizer.ts +91 -0
  208. package/src/core/rbac/domain/grant.ts +96 -0
  209. package/src/core/rbac/domain/permission-set.ts +67 -0
  210. package/src/core/rbac/domain/permission.ts +119 -0
  211. package/src/core/rbac/domain/role.ts +101 -0
  212. package/src/core/rbac/domain/scope.ts +84 -0
  213. package/src/core/rbac/index.ts +15 -0
  214. package/src/core/rbac/policy-bridge.ts +44 -0
  215. package/src/examples/application/authorize-cancel-order-abac.example.ts +107 -0
  216. package/src/examples/application/authorize-cancel-order.example.ts +101 -0
  217. package/src/rbac/index.ts +1 -0
  218. package/src/version.ts +1 -1
@@ -0,0 +1,185 @@
1
+ import { t as RequestedBy } from "./requested-by.cjs";
2
+ import { t as AuthorizationError } from "./authorization-error.cjs";
3
+ import { r as Result } from "./result.cjs";
4
+ import { t as ValueObject } from "./value-object.cjs";
5
+ import { a as Permission, n as AccessRequest, r as Scope } from "./authorizer.port.cjs";
6
+
7
+ //#region src/core/rbac/domain/role.d.ts
8
+
9
+ /**
10
+ * The serializable shape of a role: a name plus its permissions kept as their
11
+ * primitive `"resource:action"` strings (so the role round-trips through JSON
12
+ * and stays deep-frozen). The {@link Role.permissions} getter rehydrates them
13
+ * back into {@link Permission} objects.
14
+ */
15
+ type RoleProps = {
16
+ readonly name: string;
17
+ readonly permissions: readonly string[];
18
+ };
19
+ /**
20
+ * A named bundle of {@link Permission}s — `"cashier"`, `"manager"`, `"admin"`.
21
+ * There is **no role hierarchy** in v1: a role grants exactly the permissions
22
+ * it lists (wildcards included). Duplicate permissions are collapsed on
23
+ * construction, preserving first-seen order.
24
+ *
25
+ * A zod-free value object. Build through {@link of}; reconstruct a serialized
26
+ * one through {@link fromProps}.
27
+ */
28
+ declare class Role extends ValueObject<RoleProps, RoleProps> {
29
+ private readonly _permissions;
30
+ private constructor();
31
+ /**
32
+ * Builds a role from a name and its permissions. Throws
33
+ * {@link InvalidValueException} when the name is blank. Duplicate
34
+ * permissions are deduplicated.
35
+ */
36
+ static of(name: string, permissions: readonly Permission[]): Role;
37
+ /**
38
+ * Rebuilds a role from its serialized {@link RoleProps} — the inverse of
39
+ * {@link toPrimitive}. Each stored string is re-parsed through
40
+ * {@link Permission.of}, so a malformed payload still fails loudly.
41
+ */
42
+ static fromProps(props: RoleProps): Role;
43
+ get name(): string;
44
+ /** The role's permissions, rehydrated from their stored primitive form. */
45
+ get permissions(): readonly Permission[];
46
+ /** Whether any permission in this role {@link Permission.implies | implies} `required`. */
47
+ grants(required: Permission): boolean;
48
+ toPrimitive(): RoleProps;
49
+ }
50
+ //#endregion
51
+ //#region src/core/rbac/domain/grant.d.ts
52
+ /**
53
+ * The serializable shape a consumer persists and loads: the actor's identity
54
+ * (`RequestedBy.raw`), the role they hold (as {@link RoleProps}), and the scope
55
+ * the role applies in (the {@link Scope} string).
56
+ */
57
+ type GrantProps = {
58
+ readonly subject: string;
59
+ readonly role: RoleProps;
60
+ readonly scope: string;
61
+ };
62
+ /**
63
+ * A role binding — it ties one actor to one {@link Role} within one
64
+ * {@link Scope}. This is the unit the consumer stores (a `(subject, role,
65
+ * scope)` row) and rehydrates into the pure decisor; the kit itself persists
66
+ * nothing.
67
+ *
68
+ * A zod-free value object built through {@link of} from live
69
+ * `RequestedBy`/`Role`/`Scope` objects; the getters reconstruct those objects
70
+ * back from the frozen primitive form.
71
+ */
72
+ declare class Grant extends ValueObject<GrantProps, GrantProps> {
73
+ private readonly _subject;
74
+ private readonly _role;
75
+ private readonly _scope;
76
+ private constructor();
77
+ static of(params: {
78
+ subject: RequestedBy;
79
+ role: Role;
80
+ scope: Scope;
81
+ }): Grant;
82
+ /**
83
+ * Rebuilds a grant from its serialized {@link GrantProps} — the inverse of
84
+ * {@link toPrimitive}, symmetric to {@link Role.fromProps}. Each part is
85
+ * re-validated (subject through {@link RequestedBy.parse}, role through
86
+ * {@link Role.fromProps}, scope through {@link Scope.of}), so a malformed
87
+ * payload still fails loudly.
88
+ */
89
+ static fromProps(props: GrantProps): Grant;
90
+ get subject(): RequestedBy;
91
+ get role(): Role;
92
+ get scope(): Scope;
93
+ /** Whether this grant belongs to `actor`. */
94
+ appliesTo(actor: RequestedBy): boolean;
95
+ toPrimitive(): GrantProps;
96
+ }
97
+ //#endregion
98
+ //#region src/core/rbac/authorizer.d.ts
99
+ /**
100
+ * The pure RBAC decisor. Given an {@link AccessRequest} and the {@link Grant}s
101
+ * already loaded for the actor, it answers "may this actor do this?" with no
102
+ * I/O — no storage, no network, no clock — returning a {@link Result}. An
103
+ * authorization *decision* is never thrown, always a value, mirroring the
104
+ * "errors as values" contract of `UseCase`/`PolicyService`. Loading the grants
105
+ * is the consumer's job (behind an `AuthorizerPort` adapter); this class only
106
+ * decides.
107
+ *
108
+ * The one thing it *does* throw is {@link InvalidValueException} when the caller
109
+ * misuses the API by passing a wildcard `required` permission — that is a
110
+ * programming error surfaced loudly, not an authorization outcome.
111
+ */
112
+ declare class RbacAuthorizer {
113
+ /**
114
+ * Decides the request against the supplied grants. The checks run
115
+ * role → capability → scope so the denial reason is the most informative
116
+ * one available:
117
+ *
118
+ * 1. no grant for the actor → `missing_role`;
119
+ * 2. has grants but none grants the permission → `missing_capability`;
120
+ * 3. grants the permission but not in scope → `out_of_scope`;
121
+ * 4. otherwise → ALLOW (`Result.ok`).
122
+ *
123
+ * @throws {@link InvalidValueException} when `request.required` is a wildcard
124
+ * permission (only *granted* permissions may wildcard, never the *required*
125
+ * one).
126
+ */
127
+ authorize(request: AccessRequest, grants: readonly Grant[]): Result<void, AuthorizationError>;
128
+ }
129
+ //#endregion
130
+ //#region src/core/rbac/domain/permission-set.d.ts
131
+ /**
132
+ * The flattened, deduplicated permissions an actor effectively holds across a
133
+ * set of {@link Grant}s, together with the role names that contributed them.
134
+ *
135
+ * Pure resolution, isolated from the decisor so the "roles → permissions"
136
+ * collapse can be tested on its own. Build through {@link fromGrants}; pre-filter
137
+ * the grants to a single actor first when that matters (the set does not know
138
+ * which actor it describes).
139
+ */
140
+ declare class PermissionSet {
141
+ private readonly permissions;
142
+ private readonly _roleNames;
143
+ private constructor();
144
+ /**
145
+ * Collapses the roles across `grants` into one permission set. Permissions
146
+ * are deduplicated by their primitive form and role names by value, both
147
+ * preserving first-seen order.
148
+ */
149
+ static fromGrants(grants: readonly Grant[]): PermissionSet;
150
+ /** Whether any held permission {@link Permission.implies | implies} `required`. */
151
+ has(required: Permission): boolean;
152
+ /** The effective permissions, deduplicated. */
153
+ toArray(): readonly Permission[];
154
+ /** The names of the roles that contributed to this set, deduplicated. */
155
+ get roleNames(): readonly string[];
156
+ }
157
+ //#endregion
158
+ //#region src/core/rbac/policy-bridge.d.ts
159
+ /**
160
+ * Projects an actor's RBAC facts into flat {@link PolicyContext}-style fields so
161
+ * a declarative gate policy can reason over them (ABAC) — without importing the
162
+ * policy engine or `zod`. It only builds a plain object; the consumer merges it
163
+ * into `seed.fields` of `PolicyService.evaluate(...)`.
164
+ *
165
+ * The grants are filtered to `actor` first, so passing an actor's full grant
166
+ * list (or a mixed one) is safe.
167
+ *
168
+ * **Wildcards are projected literally — they are NOT expanded.** `actor.roles`
169
+ * and `actor.permissions` are the exact stored strings, so a permission such as
170
+ * `"orders:*"` or `"*:*"` appears verbatim. A gate condition like
171
+ * `{ field: "actor.permissions", op: "in", value: "orders:cancel" }` does a
172
+ * *literal* membership test and will therefore NOT match a holder of
173
+ * `"orders:*"`. Open-ended wildcards cannot be enumerated into a finite list, so
174
+ * for wildcard-aware checks either match on the finite `actor.roles` instead, or
175
+ * make the wildcard-aware decision with `RbacAuthorizer` (which knows
176
+ * {@link Permission.implies}) and use the gate only for the extra ABAC
177
+ * conditions.
178
+ *
179
+ * @returns `{ "actor.id", "actor.roles", "actor.permissions" }`, where roles and
180
+ * permissions are plain string arrays (wildcards left literal).
181
+ */
182
+ declare function rbacContextFields(actor: RequestedBy, grants: readonly Grant[]): Record<string, unknown>;
183
+ //#endregion
184
+ export { GrantProps as a, Grant as i, PermissionSet as n, Role as o, RbacAuthorizer as r, RoleProps as s, rbacContextFields as t };
185
+ //# sourceMappingURL=policy-bridge.d.cts.map
@@ -0,0 +1,185 @@
1
+ import { t as RequestedBy } from "./requested-by.js";
2
+ import { t as AuthorizationError } from "./authorization-error.js";
3
+ import { r as Result } from "./result.js";
4
+ import { t as ValueObject } from "./value-object.js";
5
+ import { a as Permission, n as AccessRequest, r as Scope } from "./authorizer.port.js";
6
+
7
+ //#region src/core/rbac/domain/role.d.ts
8
+
9
+ /**
10
+ * The serializable shape of a role: a name plus its permissions kept as their
11
+ * primitive `"resource:action"` strings (so the role round-trips through JSON
12
+ * and stays deep-frozen). The {@link Role.permissions} getter rehydrates them
13
+ * back into {@link Permission} objects.
14
+ */
15
+ type RoleProps = {
16
+ readonly name: string;
17
+ readonly permissions: readonly string[];
18
+ };
19
+ /**
20
+ * A named bundle of {@link Permission}s — `"cashier"`, `"manager"`, `"admin"`.
21
+ * There is **no role hierarchy** in v1: a role grants exactly the permissions
22
+ * it lists (wildcards included). Duplicate permissions are collapsed on
23
+ * construction, preserving first-seen order.
24
+ *
25
+ * A zod-free value object. Build through {@link of}; reconstruct a serialized
26
+ * one through {@link fromProps}.
27
+ */
28
+ declare class Role extends ValueObject<RoleProps, RoleProps> {
29
+ private readonly _permissions;
30
+ private constructor();
31
+ /**
32
+ * Builds a role from a name and its permissions. Throws
33
+ * {@link InvalidValueException} when the name is blank. Duplicate
34
+ * permissions are deduplicated.
35
+ */
36
+ static of(name: string, permissions: readonly Permission[]): Role;
37
+ /**
38
+ * Rebuilds a role from its serialized {@link RoleProps} — the inverse of
39
+ * {@link toPrimitive}. Each stored string is re-parsed through
40
+ * {@link Permission.of}, so a malformed payload still fails loudly.
41
+ */
42
+ static fromProps(props: RoleProps): Role;
43
+ get name(): string;
44
+ /** The role's permissions, rehydrated from their stored primitive form. */
45
+ get permissions(): readonly Permission[];
46
+ /** Whether any permission in this role {@link Permission.implies | implies} `required`. */
47
+ grants(required: Permission): boolean;
48
+ toPrimitive(): RoleProps;
49
+ }
50
+ //#endregion
51
+ //#region src/core/rbac/domain/grant.d.ts
52
+ /**
53
+ * The serializable shape a consumer persists and loads: the actor's identity
54
+ * (`RequestedBy.raw`), the role they hold (as {@link RoleProps}), and the scope
55
+ * the role applies in (the {@link Scope} string).
56
+ */
57
+ type GrantProps = {
58
+ readonly subject: string;
59
+ readonly role: RoleProps;
60
+ readonly scope: string;
61
+ };
62
+ /**
63
+ * A role binding — it ties one actor to one {@link Role} within one
64
+ * {@link Scope}. This is the unit the consumer stores (a `(subject, role,
65
+ * scope)` row) and rehydrates into the pure decisor; the kit itself persists
66
+ * nothing.
67
+ *
68
+ * A zod-free value object built through {@link of} from live
69
+ * `RequestedBy`/`Role`/`Scope` objects; the getters reconstruct those objects
70
+ * back from the frozen primitive form.
71
+ */
72
+ declare class Grant extends ValueObject<GrantProps, GrantProps> {
73
+ private readonly _subject;
74
+ private readonly _role;
75
+ private readonly _scope;
76
+ private constructor();
77
+ static of(params: {
78
+ subject: RequestedBy;
79
+ role: Role;
80
+ scope: Scope;
81
+ }): Grant;
82
+ /**
83
+ * Rebuilds a grant from its serialized {@link GrantProps} — the inverse of
84
+ * {@link toPrimitive}, symmetric to {@link Role.fromProps}. Each part is
85
+ * re-validated (subject through {@link RequestedBy.parse}, role through
86
+ * {@link Role.fromProps}, scope through {@link Scope.of}), so a malformed
87
+ * payload still fails loudly.
88
+ */
89
+ static fromProps(props: GrantProps): Grant;
90
+ get subject(): RequestedBy;
91
+ get role(): Role;
92
+ get scope(): Scope;
93
+ /** Whether this grant belongs to `actor`. */
94
+ appliesTo(actor: RequestedBy): boolean;
95
+ toPrimitive(): GrantProps;
96
+ }
97
+ //#endregion
98
+ //#region src/core/rbac/authorizer.d.ts
99
+ /**
100
+ * The pure RBAC decisor. Given an {@link AccessRequest} and the {@link Grant}s
101
+ * already loaded for the actor, it answers "may this actor do this?" with no
102
+ * I/O — no storage, no network, no clock — returning a {@link Result}. An
103
+ * authorization *decision* is never thrown, always a value, mirroring the
104
+ * "errors as values" contract of `UseCase`/`PolicyService`. Loading the grants
105
+ * is the consumer's job (behind an `AuthorizerPort` adapter); this class only
106
+ * decides.
107
+ *
108
+ * The one thing it *does* throw is {@link InvalidValueException} when the caller
109
+ * misuses the API by passing a wildcard `required` permission — that is a
110
+ * programming error surfaced loudly, not an authorization outcome.
111
+ */
112
+ declare class RbacAuthorizer {
113
+ /**
114
+ * Decides the request against the supplied grants. The checks run
115
+ * role → capability → scope so the denial reason is the most informative
116
+ * one available:
117
+ *
118
+ * 1. no grant for the actor → `missing_role`;
119
+ * 2. has grants but none grants the permission → `missing_capability`;
120
+ * 3. grants the permission but not in scope → `out_of_scope`;
121
+ * 4. otherwise → ALLOW (`Result.ok`).
122
+ *
123
+ * @throws {@link InvalidValueException} when `request.required` is a wildcard
124
+ * permission (only *granted* permissions may wildcard, never the *required*
125
+ * one).
126
+ */
127
+ authorize(request: AccessRequest, grants: readonly Grant[]): Result<void, AuthorizationError>;
128
+ }
129
+ //#endregion
130
+ //#region src/core/rbac/domain/permission-set.d.ts
131
+ /**
132
+ * The flattened, deduplicated permissions an actor effectively holds across a
133
+ * set of {@link Grant}s, together with the role names that contributed them.
134
+ *
135
+ * Pure resolution, isolated from the decisor so the "roles → permissions"
136
+ * collapse can be tested on its own. Build through {@link fromGrants}; pre-filter
137
+ * the grants to a single actor first when that matters (the set does not know
138
+ * which actor it describes).
139
+ */
140
+ declare class PermissionSet {
141
+ private readonly permissions;
142
+ private readonly _roleNames;
143
+ private constructor();
144
+ /**
145
+ * Collapses the roles across `grants` into one permission set. Permissions
146
+ * are deduplicated by their primitive form and role names by value, both
147
+ * preserving first-seen order.
148
+ */
149
+ static fromGrants(grants: readonly Grant[]): PermissionSet;
150
+ /** Whether any held permission {@link Permission.implies | implies} `required`. */
151
+ has(required: Permission): boolean;
152
+ /** The effective permissions, deduplicated. */
153
+ toArray(): readonly Permission[];
154
+ /** The names of the roles that contributed to this set, deduplicated. */
155
+ get roleNames(): readonly string[];
156
+ }
157
+ //#endregion
158
+ //#region src/core/rbac/policy-bridge.d.ts
159
+ /**
160
+ * Projects an actor's RBAC facts into flat {@link PolicyContext}-style fields so
161
+ * a declarative gate policy can reason over them (ABAC) — without importing the
162
+ * policy engine or `zod`. It only builds a plain object; the consumer merges it
163
+ * into `seed.fields` of `PolicyService.evaluate(...)`.
164
+ *
165
+ * The grants are filtered to `actor` first, so passing an actor's full grant
166
+ * list (or a mixed one) is safe.
167
+ *
168
+ * **Wildcards are projected literally — they are NOT expanded.** `actor.roles`
169
+ * and `actor.permissions` are the exact stored strings, so a permission such as
170
+ * `"orders:*"` or `"*:*"` appears verbatim. A gate condition like
171
+ * `{ field: "actor.permissions", op: "in", value: "orders:cancel" }` does a
172
+ * *literal* membership test and will therefore NOT match a holder of
173
+ * `"orders:*"`. Open-ended wildcards cannot be enumerated into a finite list, so
174
+ * for wildcard-aware checks either match on the finite `actor.roles` instead, or
175
+ * make the wildcard-aware decision with `RbacAuthorizer` (which knows
176
+ * {@link Permission.implies}) and use the gate only for the extra ABAC
177
+ * conditions.
178
+ *
179
+ * @returns `{ "actor.id", "actor.roles", "actor.permissions" }`, where roles and
180
+ * permissions are plain string arrays (wildcards left literal).
181
+ */
182
+ declare function rbacContextFields(actor: RequestedBy, grants: readonly Grant[]): Record<string, unknown>;
183
+ //#endregion
184
+ export { GrantProps as a, Grant as i, PermissionSet as n, Role as o, RbacAuthorizer as r, RoleProps as s, rbacContextFields as t };
185
+ //# sourceMappingURL=policy-bridge.d.ts.map