@rbacbee-lib/core 0.1.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/dist/index.js ADDED
@@ -0,0 +1,579 @@
1
+ // src/domain/errors/rbac-error.ts
2
+ var RbacError = class extends Error {
3
+ code;
4
+ constructor(code, message) {
5
+ super(message);
6
+ this.name = new.target.name;
7
+ this.code = code;
8
+ }
9
+ };
10
+ var RbacValidationError = class extends RbacError {
11
+ constructor(message) {
12
+ super("RBAC_VALIDATION_ERROR", message);
13
+ }
14
+ };
15
+ var RbacAuthorizationError = class extends RbacError {
16
+ constructor(message = "Authorization denied") {
17
+ super("RBAC_AUTHORIZATION_DENIED", message);
18
+ }
19
+ };
20
+ var RbacConfigurationError = class extends RbacError {
21
+ constructor(message) {
22
+ super("RBAC_CONFIGURATION_ERROR", message);
23
+ }
24
+ };
25
+
26
+ // src/domain/value-objects/identifiers.ts
27
+ var ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_:@./-]{0,255}$/;
28
+ var PERMISSION_PATTERN = /^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$/;
29
+ var StringValueObject = class {
30
+ value;
31
+ constructor(value, name, pattern, maxLength) {
32
+ const normalized = value.trim();
33
+ if (normalized.length === 0) {
34
+ throw new RbacValidationError(`${name} cannot be empty`);
35
+ }
36
+ if (normalized.length > maxLength) {
37
+ throw new RbacValidationError(`${name} cannot exceed ${maxLength} characters`);
38
+ }
39
+ if (!pattern.test(normalized)) {
40
+ throw new RbacValidationError(`${name} contains invalid characters`);
41
+ }
42
+ this.value = normalized;
43
+ Object.freeze(this);
44
+ }
45
+ equals(other) {
46
+ return this.value === other.value;
47
+ }
48
+ toString() {
49
+ return this.value;
50
+ }
51
+ };
52
+ var UserId = class _UserId extends StringValueObject {
53
+ constructor(value) {
54
+ super(value, "UserId", ID_PATTERN, 256);
55
+ }
56
+ static create(value) {
57
+ return new _UserId(value);
58
+ }
59
+ };
60
+ var RoleId = class _RoleId extends StringValueObject {
61
+ constructor(value) {
62
+ super(value, "RoleId", ID_PATTERN, 256);
63
+ }
64
+ static create(value) {
65
+ return new _RoleId(value);
66
+ }
67
+ };
68
+ var TenantId = class _TenantId extends StringValueObject {
69
+ constructor(value) {
70
+ super(value, "TenantId", ID_PATTERN, 256);
71
+ }
72
+ static create(value) {
73
+ return new _TenantId(value);
74
+ }
75
+ };
76
+ var ResourceId = class _ResourceId extends StringValueObject {
77
+ constructor(value) {
78
+ super(value, "ResourceId", ID_PATTERN, 256);
79
+ }
80
+ static create(value) {
81
+ return new _ResourceId(value);
82
+ }
83
+ };
84
+ var PermissionKey = class _PermissionKey extends StringValueObject {
85
+ constructor(value) {
86
+ super(value, "PermissionKey", PERMISSION_PATTERN, 128);
87
+ }
88
+ static create(value) {
89
+ return new _PermissionKey(value);
90
+ }
91
+ };
92
+ var PolicyKey = class _PolicyKey extends StringValueObject {
93
+ constructor(value) {
94
+ super(value, "PolicyKey", PERMISSION_PATTERN, 128);
95
+ }
96
+ static create(value) {
97
+ return new _PolicyKey(value);
98
+ }
99
+ };
100
+
101
+ // src/domain/policies/policy-registry.ts
102
+ var PolicyRegistry = class {
103
+ handlers = /* @__PURE__ */ new Map();
104
+ register(policy, handler) {
105
+ const key = PolicyKey.create(policy).value;
106
+ this.handlers.set(key, handler);
107
+ }
108
+ has(policy) {
109
+ return this.handlers.has(PolicyKey.create(policy).value);
110
+ }
111
+ async evaluate(policy, principal, context) {
112
+ const key = PolicyKey.create(policy).value;
113
+ const handler = this.handlers.get(key);
114
+ if (handler === void 0) {
115
+ return {
116
+ decision: "deny",
117
+ reason: "policy not registered",
118
+ principal,
119
+ context,
120
+ policy: key
121
+ };
122
+ }
123
+ const result = await handler({ principal, context });
124
+ if (typeof result === "boolean") {
125
+ return {
126
+ decision: result ? "allow" : "deny",
127
+ reason: result ? "policy allowed" : "policy denied",
128
+ principal,
129
+ context,
130
+ policy: key
131
+ };
132
+ }
133
+ return result;
134
+ }
135
+ };
136
+
137
+ // src/infrastructure/clock/system-clock.ts
138
+ var SystemClock = class {
139
+ now() {
140
+ return /* @__PURE__ */ new Date();
141
+ }
142
+ };
143
+
144
+ // src/domain/services/permission-evaluator.ts
145
+ var PermissionEvaluator = class {
146
+ evaluatePermission(profile, principal, requiredPermission, context) {
147
+ const now = context.now ?? /* @__PURE__ */ new Date();
148
+ const matched = profile.permissions.filter((permission) => permissionApplies(permission, requiredPermission, context, now)).map((permission) => permission.key);
149
+ if (matched.length > 0) {
150
+ return {
151
+ decision: "allow",
152
+ reason: "permission matched",
153
+ principal,
154
+ context,
155
+ permission: requiredPermission,
156
+ matched
157
+ };
158
+ }
159
+ return {
160
+ decision: "deny",
161
+ reason: "permission not found",
162
+ principal,
163
+ context,
164
+ permission: requiredPermission
165
+ };
166
+ }
167
+ evaluateRole(profile, principal, requiredRole, context) {
168
+ const now = context.now ?? /* @__PURE__ */ new Date();
169
+ const matched = profile.roles.filter((role) => roleApplies(role, requiredRole, context, now)).map((role) => role.id);
170
+ if (matched.length > 0) {
171
+ return {
172
+ decision: "allow",
173
+ reason: "role matched",
174
+ principal,
175
+ context,
176
+ role: requiredRole,
177
+ matched
178
+ };
179
+ }
180
+ return {
181
+ decision: "deny",
182
+ reason: "role not found",
183
+ principal,
184
+ context,
185
+ role: requiredRole
186
+ };
187
+ }
188
+ };
189
+ function matchesPermission(granted, required) {
190
+ if (granted === "*" || granted === required) {
191
+ return true;
192
+ }
193
+ const grantedParts = granted.split(":");
194
+ const requiredParts = required.split(":");
195
+ for (let index = 0; index < grantedParts.length; index += 1) {
196
+ const grantedPart = grantedParts[index];
197
+ const requiredPart = requiredParts[index];
198
+ if (grantedPart === void 0) {
199
+ return false;
200
+ }
201
+ if (grantedPart === "*") {
202
+ return index === grantedParts.length - 1 || requiredPart !== void 0;
203
+ }
204
+ if (requiredPart === void 0 || grantedPart !== requiredPart) {
205
+ return false;
206
+ }
207
+ }
208
+ return grantedParts.length === requiredParts.length;
209
+ }
210
+ function permissionApplies(granted, requiredPermission, context, now) {
211
+ if (granted.expiresAt !== void 0 && granted.expiresAt <= now) {
212
+ return false;
213
+ }
214
+ if (!scopeApplies(granted, context)) {
215
+ return false;
216
+ }
217
+ return matchesPermission(granted.key, requiredPermission);
218
+ }
219
+ function roleApplies(granted, requiredRole, context, now) {
220
+ if (granted.expiresAt !== void 0 && granted.expiresAt <= now) {
221
+ return false;
222
+ }
223
+ if (!scopeApplies(granted, context)) {
224
+ return false;
225
+ }
226
+ return granted.id === requiredRole || granted.name === requiredRole;
227
+ }
228
+ function scopeApplies(granted, context) {
229
+ if (granted.tenantId !== void 0 && granted.tenantId !== context.tenantId) {
230
+ return false;
231
+ }
232
+ if (granted.resourceType !== void 0 && granted.resourceType !== context.resourceType) {
233
+ return false;
234
+ }
235
+ if (granted.resourceId !== void 0 && granted.resourceId !== context.resourceId) {
236
+ return false;
237
+ }
238
+ return true;
239
+ }
240
+
241
+ // src/application/use-cases/check-permission.ts
242
+ var CheckPermissionUseCase = class {
243
+ accessRepository;
244
+ evaluator;
245
+ cache;
246
+ audit;
247
+ clock;
248
+ cacheTtlMs;
249
+ constructor(dependencies) {
250
+ this.accessRepository = dependencies.accessRepository;
251
+ this.evaluator = dependencies.evaluator ?? new PermissionEvaluator();
252
+ this.cache = dependencies.cache;
253
+ this.audit = dependencies.audit;
254
+ this.clock = dependencies.clock ?? new SystemClock();
255
+ this.cacheTtlMs = dependencies.cacheTtlMs;
256
+ }
257
+ async execute(principal, requiredPermission, context = {}) {
258
+ UserId.create(principal.userId);
259
+ PermissionKey.create(requiredPermission);
260
+ const normalizedContext = normalizeContext(principal, context, this.clock.now());
261
+ const profile = await this.loadProfile(principal, normalizedContext);
262
+ const result = profile === null ? deny(principal, normalizedContext, requiredPermission, "access profile not found") : this.evaluator.evaluatePermission(
263
+ profile,
264
+ principal,
265
+ requiredPermission,
266
+ normalizedContext
267
+ );
268
+ await this.audit?.record({
269
+ type: "authorization.checked",
270
+ occurredAt: this.clock.now(),
271
+ decision: result.decision,
272
+ principal,
273
+ permission: requiredPermission,
274
+ context: normalizedContext,
275
+ reason: result.reason
276
+ });
277
+ return result;
278
+ }
279
+ async loadProfile(principal, context) {
280
+ const cacheKey = accessProfileCacheKey(principal.userId, context.tenantId);
281
+ const cachedProfile = await this.cache?.get(cacheKey);
282
+ if (cachedProfile !== void 0) {
283
+ return cachedProfile;
284
+ }
285
+ const query = { userId: principal.userId };
286
+ if (context.tenantId !== void 0) {
287
+ TenantId.create(context.tenantId);
288
+ Object.assign(query, { tenantId: context.tenantId });
289
+ }
290
+ const profile = await this.accessRepository.getAccessProfile(query);
291
+ if (profile !== null) {
292
+ await this.cache?.set(cacheKey, profile, this.cacheTtlMs);
293
+ }
294
+ return profile;
295
+ }
296
+ };
297
+ function normalizeContext(principal, context, now) {
298
+ return {
299
+ ...context,
300
+ tenantId: context.tenantId ?? principal.tenantId,
301
+ now: context.now ?? now
302
+ };
303
+ }
304
+ function accessProfileCacheKey(userId, tenantId) {
305
+ return `rbac:access-profile:${userId}:${tenantId ?? "global"}`;
306
+ }
307
+ function deny(principal, context, permission, reason) {
308
+ return {
309
+ decision: "deny",
310
+ reason,
311
+ principal,
312
+ context,
313
+ permission
314
+ };
315
+ }
316
+
317
+ // src/application/use-cases/check-role.ts
318
+ var CheckRoleUseCase = class {
319
+ accessRepository;
320
+ evaluator;
321
+ cache;
322
+ audit;
323
+ clock;
324
+ cacheTtlMs;
325
+ constructor(dependencies) {
326
+ this.accessRepository = dependencies.accessRepository;
327
+ this.evaluator = dependencies.evaluator ?? new PermissionEvaluator();
328
+ this.cache = dependencies.cache;
329
+ this.audit = dependencies.audit;
330
+ this.clock = dependencies.clock ?? new SystemClock();
331
+ this.cacheTtlMs = dependencies.cacheTtlMs;
332
+ }
333
+ async execute(principal, requiredRole, context = {}) {
334
+ UserId.create(principal.userId);
335
+ RoleId.create(requiredRole);
336
+ const normalizedContext = normalizeContext(principal, context, this.clock.now());
337
+ const profile = await this.loadProfile(principal, normalizedContext);
338
+ const result = profile === null ? deny2(principal, normalizedContext, requiredRole, "access profile not found") : this.evaluator.evaluateRole(profile, principal, requiredRole, normalizedContext);
339
+ await this.audit?.record({
340
+ type: "role.checked",
341
+ occurredAt: this.clock.now(),
342
+ decision: result.decision,
343
+ principal,
344
+ role: requiredRole,
345
+ context: normalizedContext,
346
+ reason: result.reason
347
+ });
348
+ return result;
349
+ }
350
+ async loadProfile(principal, context) {
351
+ const cacheKey = accessProfileCacheKey(principal.userId, context.tenantId);
352
+ const cachedProfile = await this.cache?.get(cacheKey);
353
+ if (cachedProfile !== void 0) {
354
+ return cachedProfile;
355
+ }
356
+ const query = { userId: principal.userId };
357
+ if (context.tenantId !== void 0) {
358
+ TenantId.create(context.tenantId);
359
+ Object.assign(query, { tenantId: context.tenantId });
360
+ }
361
+ const profile = await this.accessRepository.getAccessProfile(query);
362
+ if (profile !== null) {
363
+ await this.cache?.set(cacheKey, profile, this.cacheTtlMs);
364
+ }
365
+ return profile;
366
+ }
367
+ };
368
+ function deny2(principal, context, role, reason) {
369
+ return {
370
+ decision: "deny",
371
+ reason,
372
+ principal,
373
+ context,
374
+ role
375
+ };
376
+ }
377
+
378
+ // src/application/rbac-engine.ts
379
+ var DefaultRbacEngine = class {
380
+ checkPermission;
381
+ checkRole;
382
+ policies;
383
+ audit;
384
+ clock;
385
+ constructor(dependencies) {
386
+ this.clock = dependencies.clock ?? new SystemClock();
387
+ this.audit = dependencies.audit;
388
+ this.policies = dependencies.policies ?? new PolicyRegistry();
389
+ this.checkPermission = new CheckPermissionUseCase(dependencies);
390
+ this.checkRole = new CheckRoleUseCase(dependencies);
391
+ }
392
+ can(principal, permission, context = {}) {
393
+ return this.checkPermission.execute(principal, permission, context);
394
+ }
395
+ async assertCan(principal, permission, context = {}) {
396
+ const result = await this.can(principal, permission, context);
397
+ if (result.decision === "deny") {
398
+ throw new RbacAuthorizationError(result.reason);
399
+ }
400
+ }
401
+ hasRole(principal, role, context = {}) {
402
+ return this.checkRole.execute(principal, role, context);
403
+ }
404
+ async evaluatePolicy(policy, principal, context = {}) {
405
+ const key = PolicyKey.create(policy).value;
406
+ const result = await this.policies.evaluate(key, principal, {
407
+ ...context,
408
+ tenantId: context.tenantId ?? principal.tenantId,
409
+ now: context.now ?? this.clock.now()
410
+ });
411
+ await this.audit?.record({
412
+ type: "policy.checked",
413
+ occurredAt: this.clock.now(),
414
+ decision: result.decision,
415
+ principal,
416
+ policy: key,
417
+ context: result.context,
418
+ reason: result.reason
419
+ });
420
+ return result;
421
+ }
422
+ };
423
+ function createRbacEngine(dependencies) {
424
+ return new DefaultRbacEngine(dependencies);
425
+ }
426
+
427
+ // src/domain/entities/assignment.ts
428
+ var Assignment = class _Assignment {
429
+ userId;
430
+ roleId;
431
+ tenantId;
432
+ resourceType;
433
+ resourceId;
434
+ expiresAt;
435
+ constructor(input) {
436
+ this.userId = UserId.create(input.userId);
437
+ this.roleId = RoleId.create(input.roleId);
438
+ this.tenantId = input.tenantId === void 0 ? void 0 : TenantId.create(input.tenantId);
439
+ this.resourceType = input.resourceType;
440
+ this.resourceId = input.resourceId === void 0 ? void 0 : ResourceId.create(input.resourceId);
441
+ this.expiresAt = input.expiresAt;
442
+ Object.freeze(this);
443
+ }
444
+ static create(input) {
445
+ return new _Assignment(input);
446
+ }
447
+ toPrimitives() {
448
+ const output = {
449
+ userId: this.userId.value,
450
+ roleId: this.roleId.value
451
+ };
452
+ return {
453
+ ...output,
454
+ ...this.tenantId === void 0 ? {} : { tenantId: this.tenantId.value },
455
+ ...this.resourceType === void 0 ? {} : { resourceType: this.resourceType },
456
+ ...this.resourceId === void 0 ? {} : { resourceId: this.resourceId.value },
457
+ ...this.expiresAt === void 0 ? {} : { expiresAt: this.expiresAt }
458
+ };
459
+ }
460
+ };
461
+
462
+ // src/domain/entities/permission.ts
463
+ var Permission = class _Permission {
464
+ key;
465
+ description;
466
+ constructor(key, description) {
467
+ this.key = key;
468
+ this.description = description;
469
+ Object.freeze(this);
470
+ }
471
+ static create(input) {
472
+ return new _Permission(PermissionKey.create(input.key), input.description);
473
+ }
474
+ toPrimitives() {
475
+ const output = { key: this.key.value };
476
+ if (this.description !== void 0) {
477
+ return { ...output, description: this.description };
478
+ }
479
+ return output;
480
+ }
481
+ };
482
+
483
+ // src/domain/entities/role.ts
484
+ var Role = class _Role {
485
+ id;
486
+ name;
487
+ tenantId;
488
+ permissions;
489
+ constructor(id, name, permissions, tenantId) {
490
+ const normalizedName = name.trim();
491
+ if (normalizedName.length === 0) {
492
+ throw new Error("Role name cannot be empty");
493
+ }
494
+ this.id = id;
495
+ this.name = normalizedName;
496
+ this.permissions = Object.freeze([...permissions]);
497
+ this.tenantId = tenantId;
498
+ Object.freeze(this);
499
+ }
500
+ static create(input) {
501
+ return new _Role(
502
+ RoleId.create(input.id),
503
+ input.name,
504
+ (input.permissions ?? []).map((permission) => PermissionKey.create(permission)),
505
+ input.tenantId === void 0 ? void 0 : TenantId.create(input.tenantId)
506
+ );
507
+ }
508
+ toPrimitives() {
509
+ const output = {
510
+ id: this.id.value,
511
+ name: this.name,
512
+ permissions: this.permissions.map((permission) => permission.value)
513
+ };
514
+ if (this.tenantId !== void 0) {
515
+ return { ...output, tenantId: this.tenantId.value };
516
+ }
517
+ return output;
518
+ }
519
+ };
520
+
521
+ // src/infrastructure/cache/memory-cache.ts
522
+ var MemoryCache = class {
523
+ entries = /* @__PURE__ */ new Map();
524
+ async get(key) {
525
+ const entry = this.entries.get(key);
526
+ if (entry === void 0) {
527
+ return void 0;
528
+ }
529
+ if (entry.expiresAt !== void 0 && entry.expiresAt <= Date.now()) {
530
+ this.entries.delete(key);
531
+ return void 0;
532
+ }
533
+ return entry.value;
534
+ }
535
+ async set(key, value, ttlMs) {
536
+ const entry = ttlMs === void 0 ? { value } : { value, expiresAt: Date.now() + ttlMs };
537
+ this.entries.set(key, entry);
538
+ }
539
+ async delete(key) {
540
+ this.entries.delete(key);
541
+ }
542
+ async deleteByPrefix(prefix) {
543
+ for (const key of this.entries.keys()) {
544
+ if (key.startsWith(prefix)) {
545
+ this.entries.delete(key);
546
+ }
547
+ }
548
+ }
549
+ clear() {
550
+ this.entries.clear();
551
+ }
552
+ };
553
+ export {
554
+ Assignment,
555
+ CheckPermissionUseCase,
556
+ CheckRoleUseCase,
557
+ DefaultRbacEngine,
558
+ MemoryCache,
559
+ Permission,
560
+ PermissionEvaluator,
561
+ PermissionKey,
562
+ PolicyKey,
563
+ PolicyRegistry,
564
+ RbacAuthorizationError,
565
+ RbacConfigurationError,
566
+ RbacError,
567
+ RbacValidationError,
568
+ ResourceId,
569
+ Role,
570
+ RoleId,
571
+ SystemClock,
572
+ TenantId,
573
+ UserId,
574
+ accessProfileCacheKey,
575
+ createRbacEngine,
576
+ matchesPermission,
577
+ normalizeContext
578
+ };
579
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/domain/errors/rbac-error.ts","../src/domain/value-objects/identifiers.ts","../src/domain/policies/policy-registry.ts","../src/infrastructure/clock/system-clock.ts","../src/domain/services/permission-evaluator.ts","../src/application/use-cases/check-permission.ts","../src/application/use-cases/check-role.ts","../src/application/rbac-engine.ts","../src/domain/entities/assignment.ts","../src/domain/entities/permission.ts","../src/domain/entities/role.ts","../src/infrastructure/cache/memory-cache.ts"],"sourcesContent":["export class RbacError extends Error {\n public readonly code: string;\n\n public constructor(code: string, message: string) {\n super(message);\n this.name = new.target.name;\n this.code = code;\n }\n}\n\nexport class RbacValidationError extends RbacError {\n public constructor(message: string) {\n super('RBAC_VALIDATION_ERROR', message);\n }\n}\n\nexport class RbacAuthorizationError extends RbacError {\n public constructor(message = 'Authorization denied') {\n super('RBAC_AUTHORIZATION_DENIED', message);\n }\n}\n\nexport class RbacConfigurationError extends RbacError {\n public constructor(message: string) {\n super('RBAC_CONFIGURATION_ERROR', message);\n }\n}\n","import { RbacValidationError } from '../errors/rbac-error';\n\nconst ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9_:@./-]{0,255}$/;\nconst PERMISSION_PATTERN = /^[A-Za-z0-9*][A-Za-z0-9:_.*-]{0,127}$/;\n\nabstract class StringValueObject {\n public readonly value: string;\n\n protected constructor(value: string, name: string, pattern: RegExp, maxLength: number) {\n const normalized = value.trim();\n\n if (normalized.length === 0) {\n throw new RbacValidationError(`${name} cannot be empty`);\n }\n\n if (normalized.length > maxLength) {\n throw new RbacValidationError(`${name} cannot exceed ${maxLength} characters`);\n }\n\n if (!pattern.test(normalized)) {\n throw new RbacValidationError(`${name} contains invalid characters`);\n }\n\n this.value = normalized;\n Object.freeze(this);\n }\n\n public equals(other: StringValueObject): boolean {\n return this.value === other.value;\n }\n\n public toString(): string {\n return this.value;\n }\n}\n\nexport class UserId extends StringValueObject {\n private constructor(value: string) {\n super(value, 'UserId', ID_PATTERN, 256);\n }\n\n public static create(value: string): UserId {\n return new UserId(value);\n }\n}\n\nexport class RoleId extends StringValueObject {\n private constructor(value: string) {\n super(value, 'RoleId', ID_PATTERN, 256);\n }\n\n public static create(value: string): RoleId {\n return new RoleId(value);\n }\n}\n\nexport class TenantId extends StringValueObject {\n private constructor(value: string) {\n super(value, 'TenantId', ID_PATTERN, 256);\n }\n\n public static create(value: string): TenantId {\n return new TenantId(value);\n }\n}\n\nexport class ResourceId extends StringValueObject {\n private constructor(value: string) {\n super(value, 'ResourceId', ID_PATTERN, 256);\n }\n\n public static create(value: string): ResourceId {\n return new ResourceId(value);\n }\n}\n\nexport class PermissionKey extends StringValueObject {\n private constructor(value: string) {\n super(value, 'PermissionKey', PERMISSION_PATTERN, 128);\n }\n\n public static create(value: string): PermissionKey {\n return new PermissionKey(value);\n }\n}\n\nexport class PolicyKey extends StringValueObject {\n private constructor(value: string) {\n super(value, 'PolicyKey', PERMISSION_PATTERN, 128);\n }\n\n public static create(value: string): PolicyKey {\n return new PolicyKey(value);\n }\n}\n","import { PolicyKey } from '../value-objects/identifiers';\nimport type { AuthorizationResult, RbacAuthorizationContext, RbacPrincipal } from '../rbac-types';\n\nexport interface RbacPolicyInput {\n readonly principal: RbacPrincipal;\n readonly context: RbacAuthorizationContext;\n}\n\nexport type RbacPolicyHandler = (\n input: RbacPolicyInput\n) => boolean | AuthorizationResult | Promise<boolean | AuthorizationResult>;\n\nexport class PolicyRegistry {\n private readonly handlers = new Map<string, RbacPolicyHandler>();\n\n public register(policy: string, handler: RbacPolicyHandler): void {\n const key = PolicyKey.create(policy).value;\n this.handlers.set(key, handler);\n }\n\n public has(policy: string): boolean {\n return this.handlers.has(PolicyKey.create(policy).value);\n }\n\n public async evaluate(\n policy: string,\n principal: RbacPrincipal,\n context: RbacAuthorizationContext\n ): Promise<AuthorizationResult> {\n const key = PolicyKey.create(policy).value;\n const handler = this.handlers.get(key);\n\n if (handler === undefined) {\n return {\n decision: 'deny',\n reason: 'policy not registered',\n principal,\n context,\n policy: key\n };\n }\n\n const result = await handler({ principal, context });\n\n if (typeof result === 'boolean') {\n return {\n decision: result ? 'allow' : 'deny',\n reason: result ? 'policy allowed' : 'policy denied',\n principal,\n context,\n policy: key\n };\n }\n\n return result;\n }\n}\n","import type { ClockPort } from '../../ports/clock-port';\n\nexport class SystemClock implements ClockPort {\n public now(): Date {\n return new Date();\n }\n}\n","import type {\n AccessPermission,\n AccessProfile,\n AccessRole,\n AuthorizationResult,\n RbacAuthorizationContext,\n RbacPrincipal\n} from '../rbac-types';\n\nexport class PermissionEvaluator {\n public evaluatePermission(\n profile: AccessProfile,\n principal: RbacPrincipal,\n requiredPermission: string,\n context: RbacAuthorizationContext\n ): AuthorizationResult {\n const now = context.now ?? new Date();\n const matched = profile.permissions\n .filter((permission) => permissionApplies(permission, requiredPermission, context, now))\n .map((permission) => permission.key);\n\n if (matched.length > 0) {\n return {\n decision: 'allow',\n reason: 'permission matched',\n principal,\n context,\n permission: requiredPermission,\n matched\n };\n }\n\n return {\n decision: 'deny',\n reason: 'permission not found',\n principal,\n context,\n permission: requiredPermission\n };\n }\n\n public evaluateRole(\n profile: AccessProfile,\n principal: RbacPrincipal,\n requiredRole: string,\n context: RbacAuthorizationContext\n ): AuthorizationResult {\n const now = context.now ?? new Date();\n const matched = profile.roles\n .filter((role) => roleApplies(role, requiredRole, context, now))\n .map((role) => role.id);\n\n if (matched.length > 0) {\n return {\n decision: 'allow',\n reason: 'role matched',\n principal,\n context,\n role: requiredRole,\n matched\n };\n }\n\n return {\n decision: 'deny',\n reason: 'role not found',\n principal,\n context,\n role: requiredRole\n };\n }\n}\n\nexport function matchesPermission(granted: string, required: string): boolean {\n if (granted === '*' || granted === required) {\n return true;\n }\n\n const grantedParts = granted.split(':');\n const requiredParts = required.split(':');\n\n for (let index = 0; index < grantedParts.length; index += 1) {\n const grantedPart = grantedParts[index];\n const requiredPart = requiredParts[index];\n\n if (grantedPart === undefined) {\n return false;\n }\n\n if (grantedPart === '*') {\n return index === grantedParts.length - 1 || requiredPart !== undefined;\n }\n\n if (requiredPart === undefined || grantedPart !== requiredPart) {\n return false;\n }\n }\n\n return grantedParts.length === requiredParts.length;\n}\n\nfunction permissionApplies(\n granted: AccessPermission,\n requiredPermission: string,\n context: RbacAuthorizationContext,\n now: Date\n): boolean {\n if (granted.expiresAt !== undefined && granted.expiresAt <= now) {\n return false;\n }\n\n if (!scopeApplies(granted, context)) {\n return false;\n }\n\n return matchesPermission(granted.key, requiredPermission);\n}\n\nfunction roleApplies(\n granted: AccessRole,\n requiredRole: string,\n context: RbacAuthorizationContext,\n now: Date\n): boolean {\n if (granted.expiresAt !== undefined && granted.expiresAt <= now) {\n return false;\n }\n\n if (!scopeApplies(granted, context)) {\n return false;\n }\n\n return granted.id === requiredRole || granted.name === requiredRole;\n}\n\nfunction scopeApplies(\n granted: Pick<AccessPermission | AccessRole, 'tenantId' | 'resourceType' | 'resourceId'>,\n context: RbacAuthorizationContext\n): boolean {\n if (granted.tenantId !== undefined && granted.tenantId !== context.tenantId) {\n return false;\n }\n\n if (granted.resourceType !== undefined && granted.resourceType !== context.resourceType) {\n return false;\n }\n\n if (granted.resourceId !== undefined && granted.resourceId !== context.resourceId) {\n return false;\n }\n\n return true;\n}\n","import { PermissionKey, TenantId, UserId } from '../../domain/value-objects/identifiers';\nimport { PermissionEvaluator } from '../../domain/services/permission-evaluator';\nimport type {\n AccessProfile,\n AuthorizationResult,\n RbacAuthorizationContext,\n RbacPrincipal\n} from '../../domain/rbac-types';\nimport type { AccessProfileQuery, AccessRepository } from '../../ports/access-repository';\nimport type { AuditPort } from '../../ports/audit-port';\nimport type { CachePort } from '../../ports/cache-port';\nimport type { ClockPort } from '../../ports/clock-port';\nimport { SystemClock } from '../../infrastructure/clock/system-clock';\n\nexport interface CheckPermissionDependencies {\n readonly accessRepository: AccessRepository;\n readonly evaluator?: PermissionEvaluator;\n readonly cache?: CachePort;\n readonly audit?: AuditPort;\n readonly clock?: ClockPort;\n readonly cacheTtlMs?: number;\n}\n\nexport class CheckPermissionUseCase {\n private readonly accessRepository: AccessRepository;\n private readonly evaluator: PermissionEvaluator;\n private readonly cache?: CachePort;\n private readonly audit?: AuditPort;\n private readonly clock: ClockPort;\n private readonly cacheTtlMs?: number;\n\n public constructor(dependencies: CheckPermissionDependencies) {\n this.accessRepository = dependencies.accessRepository;\n this.evaluator = dependencies.evaluator ?? new PermissionEvaluator();\n this.cache = dependencies.cache;\n this.audit = dependencies.audit;\n this.clock = dependencies.clock ?? new SystemClock();\n this.cacheTtlMs = dependencies.cacheTtlMs;\n }\n\n public async execute(\n principal: RbacPrincipal,\n requiredPermission: string,\n context: RbacAuthorizationContext = {}\n ): Promise<AuthorizationResult> {\n UserId.create(principal.userId);\n PermissionKey.create(requiredPermission);\n\n const normalizedContext = normalizeContext(principal, context, this.clock.now());\n const profile = await this.loadProfile(principal, normalizedContext);\n\n const result =\n profile === null\n ? deny(principal, normalizedContext, requiredPermission, 'access profile not found')\n : this.evaluator.evaluatePermission(\n profile,\n principal,\n requiredPermission,\n normalizedContext\n );\n\n await this.audit?.record({\n type: 'authorization.checked',\n occurredAt: this.clock.now(),\n decision: result.decision,\n principal,\n permission: requiredPermission,\n context: normalizedContext,\n reason: result.reason\n });\n\n return result;\n }\n\n private async loadProfile(\n principal: RbacPrincipal,\n context: RbacAuthorizationContext\n ): Promise<AccessProfile | null> {\n const cacheKey = accessProfileCacheKey(principal.userId, context.tenantId);\n const cachedProfile = await this.cache?.get<AccessProfile>(cacheKey);\n\n if (cachedProfile !== undefined) {\n return cachedProfile;\n }\n\n const query: AccessProfileQuery = { userId: principal.userId };\n\n if (context.tenantId !== undefined) {\n TenantId.create(context.tenantId);\n Object.assign(query, { tenantId: context.tenantId });\n }\n\n const profile = await this.accessRepository.getAccessProfile(query);\n\n if (profile !== null) {\n await this.cache?.set(cacheKey, profile, this.cacheTtlMs);\n }\n\n return profile;\n }\n}\n\nexport function normalizeContext(\n principal: RbacPrincipal,\n context: RbacAuthorizationContext,\n now: Date\n): RbacAuthorizationContext {\n return {\n ...context,\n tenantId: context.tenantId ?? principal.tenantId,\n now: context.now ?? now\n };\n}\n\nexport function accessProfileCacheKey(userId: string, tenantId?: string): string {\n return `rbac:access-profile:${userId}:${tenantId ?? 'global'}`;\n}\n\nfunction deny(\n principal: RbacPrincipal,\n context: RbacAuthorizationContext,\n permission: string,\n reason: string\n): AuthorizationResult {\n return {\n decision: 'deny',\n reason,\n principal,\n context,\n permission\n };\n}\n","import { RoleId, TenantId, UserId } from '../../domain/value-objects/identifiers';\nimport { PermissionEvaluator } from '../../domain/services/permission-evaluator';\nimport type {\n AccessProfile,\n AuthorizationResult,\n RbacAuthorizationContext,\n RbacPrincipal\n} from '../../domain/rbac-types';\nimport type { AccessProfileQuery, AccessRepository } from '../../ports/access-repository';\nimport type { AuditPort } from '../../ports/audit-port';\nimport type { CachePort } from '../../ports/cache-port';\nimport type { ClockPort } from '../../ports/clock-port';\nimport { SystemClock } from '../../infrastructure/clock/system-clock';\nimport { accessProfileCacheKey, normalizeContext } from './check-permission';\n\nexport interface CheckRoleDependencies {\n readonly accessRepository: AccessRepository;\n readonly evaluator?: PermissionEvaluator;\n readonly cache?: CachePort;\n readonly audit?: AuditPort;\n readonly clock?: ClockPort;\n readonly cacheTtlMs?: number;\n}\n\nexport class CheckRoleUseCase {\n private readonly accessRepository: AccessRepository;\n private readonly evaluator: PermissionEvaluator;\n private readonly cache?: CachePort;\n private readonly audit?: AuditPort;\n private readonly clock: ClockPort;\n private readonly cacheTtlMs?: number;\n\n public constructor(dependencies: CheckRoleDependencies) {\n this.accessRepository = dependencies.accessRepository;\n this.evaluator = dependencies.evaluator ?? new PermissionEvaluator();\n this.cache = dependencies.cache;\n this.audit = dependencies.audit;\n this.clock = dependencies.clock ?? new SystemClock();\n this.cacheTtlMs = dependencies.cacheTtlMs;\n }\n\n public async execute(\n principal: RbacPrincipal,\n requiredRole: string,\n context: RbacAuthorizationContext = {}\n ): Promise<AuthorizationResult> {\n UserId.create(principal.userId);\n RoleId.create(requiredRole);\n\n const normalizedContext = normalizeContext(principal, context, this.clock.now());\n const profile = await this.loadProfile(principal, normalizedContext);\n\n const result =\n profile === null\n ? deny(principal, normalizedContext, requiredRole, 'access profile not found')\n : this.evaluator.evaluateRole(profile, principal, requiredRole, normalizedContext);\n\n await this.audit?.record({\n type: 'role.checked',\n occurredAt: this.clock.now(),\n decision: result.decision,\n principal,\n role: requiredRole,\n context: normalizedContext,\n reason: result.reason\n });\n\n return result;\n }\n\n private async loadProfile(\n principal: RbacPrincipal,\n context: RbacAuthorizationContext\n ): Promise<AccessProfile | null> {\n const cacheKey = accessProfileCacheKey(principal.userId, context.tenantId);\n const cachedProfile = await this.cache?.get<AccessProfile>(cacheKey);\n\n if (cachedProfile !== undefined) {\n return cachedProfile;\n }\n\n const query: AccessProfileQuery = { userId: principal.userId };\n\n if (context.tenantId !== undefined) {\n TenantId.create(context.tenantId);\n Object.assign(query, { tenantId: context.tenantId });\n }\n\n const profile = await this.accessRepository.getAccessProfile(query);\n\n if (profile !== null) {\n await this.cache?.set(cacheKey, profile, this.cacheTtlMs);\n }\n\n return profile;\n }\n}\n\nfunction deny(\n principal: RbacPrincipal,\n context: RbacAuthorizationContext,\n role: string,\n reason: string\n): AuthorizationResult {\n return {\n decision: 'deny',\n reason,\n principal,\n context,\n role\n };\n}\n","import { RbacAuthorizationError } from '../domain/errors/rbac-error';\nimport { PolicyRegistry } from '../domain/policies/policy-registry';\nimport type {\n AuthorizationResult,\n RbacAuthorizationContext,\n RbacPrincipal\n} from '../domain/rbac-types';\nimport { PolicyKey } from '../domain/value-objects/identifiers';\nimport type { AccessRepository } from '../ports/access-repository';\nimport type { AuditPort } from '../ports/audit-port';\nimport type { CachePort } from '../ports/cache-port';\nimport type { ClockPort } from '../ports/clock-port';\nimport { SystemClock } from '../infrastructure/clock/system-clock';\nimport { CheckPermissionUseCase } from './use-cases/check-permission';\nimport { CheckRoleUseCase } from './use-cases/check-role';\n\nexport interface RbacEngine {\n can(\n principal: RbacPrincipal,\n permission: string,\n context?: RbacAuthorizationContext\n ): Promise<AuthorizationResult>;\n assertCan(\n principal: RbacPrincipal,\n permission: string,\n context?: RbacAuthorizationContext\n ): Promise<void>;\n hasRole(\n principal: RbacPrincipal,\n role: string,\n context?: RbacAuthorizationContext\n ): Promise<AuthorizationResult>;\n evaluatePolicy(\n policy: string,\n principal: RbacPrincipal,\n context?: RbacAuthorizationContext\n ): Promise<AuthorizationResult>;\n}\n\nexport interface RbacEngineDependencies {\n readonly accessRepository: AccessRepository;\n readonly cache?: CachePort;\n readonly audit?: AuditPort;\n readonly clock?: ClockPort;\n readonly policies?: PolicyRegistry;\n readonly cacheTtlMs?: number;\n}\n\nexport class DefaultRbacEngine implements RbacEngine {\n private readonly checkPermission: CheckPermissionUseCase;\n private readonly checkRole: CheckRoleUseCase;\n private readonly policies: PolicyRegistry;\n private readonly audit?: AuditPort;\n private readonly clock: ClockPort;\n\n public constructor(dependencies: RbacEngineDependencies) {\n this.clock = dependencies.clock ?? new SystemClock();\n this.audit = dependencies.audit;\n this.policies = dependencies.policies ?? new PolicyRegistry();\n this.checkPermission = new CheckPermissionUseCase(dependencies);\n this.checkRole = new CheckRoleUseCase(dependencies);\n }\n\n public can(\n principal: RbacPrincipal,\n permission: string,\n context: RbacAuthorizationContext = {}\n ): Promise<AuthorizationResult> {\n return this.checkPermission.execute(principal, permission, context);\n }\n\n public async assertCan(\n principal: RbacPrincipal,\n permission: string,\n context: RbacAuthorizationContext = {}\n ): Promise<void> {\n const result = await this.can(principal, permission, context);\n\n if (result.decision === 'deny') {\n throw new RbacAuthorizationError(result.reason);\n }\n }\n\n public hasRole(\n principal: RbacPrincipal,\n role: string,\n context: RbacAuthorizationContext = {}\n ): Promise<AuthorizationResult> {\n return this.checkRole.execute(principal, role, context);\n }\n\n public async evaluatePolicy(\n policy: string,\n principal: RbacPrincipal,\n context: RbacAuthorizationContext = {}\n ): Promise<AuthorizationResult> {\n const key = PolicyKey.create(policy).value;\n const result = await this.policies.evaluate(key, principal, {\n ...context,\n tenantId: context.tenantId ?? principal.tenantId,\n now: context.now ?? this.clock.now()\n });\n\n await this.audit?.record({\n type: 'policy.checked',\n occurredAt: this.clock.now(),\n decision: result.decision,\n principal,\n policy: key,\n context: result.context,\n reason: result.reason\n });\n\n return result;\n }\n}\n\nexport function createRbacEngine(dependencies: RbacEngineDependencies): RbacEngine {\n return new DefaultRbacEngine(dependencies);\n}\n","import type { RoleAssignment } from '../rbac-types';\nimport { ResourceId, RoleId, TenantId, UserId } from '../value-objects/identifiers';\n\nexport class Assignment {\n public readonly userId: UserId;\n public readonly roleId: RoleId;\n public readonly tenantId?: TenantId;\n public readonly resourceType?: string;\n public readonly resourceId?: ResourceId;\n public readonly expiresAt?: Date;\n\n private constructor(input: RoleAssignment) {\n this.userId = UserId.create(input.userId);\n this.roleId = RoleId.create(input.roleId);\n this.tenantId = input.tenantId === undefined ? undefined : TenantId.create(input.tenantId);\n this.resourceType = input.resourceType;\n this.resourceId =\n input.resourceId === undefined ? undefined : ResourceId.create(input.resourceId);\n this.expiresAt = input.expiresAt;\n Object.freeze(this);\n }\n\n public static create(input: RoleAssignment): Assignment {\n return new Assignment(input);\n }\n\n public toPrimitives(): RoleAssignment {\n const output: RoleAssignment = {\n userId: this.userId.value,\n roleId: this.roleId.value\n };\n\n return {\n ...output,\n ...(this.tenantId === undefined ? {} : { tenantId: this.tenantId.value }),\n ...(this.resourceType === undefined ? {} : { resourceType: this.resourceType }),\n ...(this.resourceId === undefined ? {} : { resourceId: this.resourceId.value }),\n ...(this.expiresAt === undefined ? {} : { expiresAt: this.expiresAt })\n };\n }\n}\n","import type { PermissionDefinition } from '../rbac-types';\nimport { PermissionKey } from '../value-objects/identifiers';\n\nexport class Permission {\n public readonly key: PermissionKey;\n public readonly description?: string;\n\n private constructor(key: PermissionKey, description?: string) {\n this.key = key;\n this.description = description;\n Object.freeze(this);\n }\n\n public static create(input: PermissionDefinition): Permission {\n return new Permission(PermissionKey.create(input.key), input.description);\n }\n\n public toPrimitives(): PermissionDefinition {\n const output: PermissionDefinition = { key: this.key.value };\n\n if (this.description !== undefined) {\n return { ...output, description: this.description };\n }\n\n return output;\n }\n}\n","import type { RoleDefinition } from '../rbac-types';\nimport { PermissionKey, RoleId, TenantId } from '../value-objects/identifiers';\n\nexport class Role {\n public readonly id: RoleId;\n public readonly name: string;\n public readonly tenantId?: TenantId;\n public readonly permissions: readonly PermissionKey[];\n\n private constructor(\n id: RoleId,\n name: string,\n permissions: readonly PermissionKey[],\n tenantId?: TenantId\n ) {\n const normalizedName = name.trim();\n\n if (normalizedName.length === 0) {\n throw new Error('Role name cannot be empty');\n }\n\n this.id = id;\n this.name = normalizedName;\n this.permissions = Object.freeze([...permissions]);\n this.tenantId = tenantId;\n Object.freeze(this);\n }\n\n public static create(input: RoleDefinition): Role {\n return new Role(\n RoleId.create(input.id),\n input.name,\n (input.permissions ?? []).map((permission) => PermissionKey.create(permission)),\n input.tenantId === undefined ? undefined : TenantId.create(input.tenantId)\n );\n }\n\n public toPrimitives(): RoleDefinition {\n const output: RoleDefinition = {\n id: this.id.value,\n name: this.name,\n permissions: this.permissions.map((permission) => permission.value)\n };\n\n if (this.tenantId !== undefined) {\n return { ...output, tenantId: this.tenantId.value };\n }\n\n return output;\n }\n}\n","import type { CachePort } from '../../ports/cache-port';\n\ninterface MemoryCacheEntry {\n readonly value: unknown;\n readonly expiresAt?: number;\n}\n\nexport class MemoryCache implements CachePort {\n private readonly entries = new Map<string, MemoryCacheEntry>();\n\n public async get<TValue>(key: string): Promise<TValue | undefined> {\n const entry = this.entries.get(key);\n\n if (entry === undefined) {\n return undefined;\n }\n\n if (entry.expiresAt !== undefined && entry.expiresAt <= Date.now()) {\n this.entries.delete(key);\n return undefined;\n }\n\n return entry.value as TValue;\n }\n\n public async set<TValue>(key: string, value: TValue, ttlMs?: number): Promise<void> {\n const entry: MemoryCacheEntry =\n ttlMs === undefined ? { value } : { value, expiresAt: Date.now() + ttlMs };\n\n this.entries.set(key, entry);\n }\n\n public async delete(key: string): Promise<void> {\n this.entries.delete(key);\n }\n\n public async deleteByPrefix(prefix: string): Promise<void> {\n for (const key of this.entries.keys()) {\n if (key.startsWith(prefix)) {\n this.entries.delete(key);\n }\n }\n }\n\n public clear(): void {\n this.entries.clear();\n }\n}\n"],"mappings":"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","names":["deny"]}