@sapl/nestjs 1.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.
Files changed (123) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +539 -0
  3. package/dist/EnforceDropWhileDenied.d.ts +4 -0
  4. package/dist/EnforceDropWhileDenied.d.ts.map +1 -0
  5. package/dist/EnforceDropWhileDenied.js +8 -0
  6. package/dist/EnforceDropWhileDenied.js.map +1 -0
  7. package/dist/EnforceDropWhileDeniedAspect.d.ts +15 -0
  8. package/dist/EnforceDropWhileDeniedAspect.d.ts.map +1 -0
  9. package/dist/EnforceDropWhileDeniedAspect.js +108 -0
  10. package/dist/EnforceDropWhileDeniedAspect.js.map +1 -0
  11. package/dist/EnforceOptions.d.ts +42 -0
  12. package/dist/EnforceOptions.d.ts.map +1 -0
  13. package/dist/EnforceOptions.js +3 -0
  14. package/dist/EnforceOptions.js.map +1 -0
  15. package/dist/EnforceRecoverableIfDenied.d.ts +4 -0
  16. package/dist/EnforceRecoverableIfDenied.d.ts.map +1 -0
  17. package/dist/EnforceRecoverableIfDenied.js +8 -0
  18. package/dist/EnforceRecoverableIfDenied.js.map +1 -0
  19. package/dist/EnforceRecoverableIfDeniedAspect.d.ts +15 -0
  20. package/dist/EnforceRecoverableIfDeniedAspect.d.ts.map +1 -0
  21. package/dist/EnforceRecoverableIfDeniedAspect.js +134 -0
  22. package/dist/EnforceRecoverableIfDeniedAspect.js.map +1 -0
  23. package/dist/EnforceTillDenied.d.ts +4 -0
  24. package/dist/EnforceTillDenied.d.ts.map +1 -0
  25. package/dist/EnforceTillDenied.js +8 -0
  26. package/dist/EnforceTillDenied.js.map +1 -0
  27. package/dist/EnforceTillDeniedAspect.d.ts +15 -0
  28. package/dist/EnforceTillDeniedAspect.d.ts.map +1 -0
  29. package/dist/EnforceTillDeniedAspect.js +119 -0
  30. package/dist/EnforceTillDeniedAspect.js.map +1 -0
  31. package/dist/MethodInvocationContext.d.ts +8 -0
  32. package/dist/MethodInvocationContext.d.ts.map +1 -0
  33. package/dist/MethodInvocationContext.js +3 -0
  34. package/dist/MethodInvocationContext.js.map +1 -0
  35. package/dist/PostEnforce.d.ts +23 -0
  36. package/dist/PostEnforce.d.ts.map +1 -0
  37. package/dist/PostEnforce.js +27 -0
  38. package/dist/PostEnforce.js.map +1 -0
  39. package/dist/PostEnforceAspect.d.ts +15 -0
  40. package/dist/PostEnforceAspect.d.ts.map +1 -0
  41. package/dist/PostEnforceAspect.js +81 -0
  42. package/dist/PostEnforceAspect.js.map +1 -0
  43. package/dist/PreEnforce.d.ts +21 -0
  44. package/dist/PreEnforce.d.ts.map +1 -0
  45. package/dist/PreEnforce.js +25 -0
  46. package/dist/PreEnforce.js.map +1 -0
  47. package/dist/PreEnforceAspect.d.ts +15 -0
  48. package/dist/PreEnforceAspect.d.ts.map +1 -0
  49. package/dist/PreEnforceAspect.js +107 -0
  50. package/dist/PreEnforceAspect.js.map +1 -0
  51. package/dist/StreamingEnforceOptions.d.ts +22 -0
  52. package/dist/StreamingEnforceOptions.d.ts.map +1 -0
  53. package/dist/StreamingEnforceOptions.js +3 -0
  54. package/dist/StreamingEnforceOptions.js.map +1 -0
  55. package/dist/SubscriptionBuilder.d.ts +17 -0
  56. package/dist/SubscriptionBuilder.d.ts.map +1 -0
  57. package/dist/SubscriptionBuilder.js +86 -0
  58. package/dist/SubscriptionBuilder.js.map +1 -0
  59. package/dist/SubscriptionContext.d.ts +48 -0
  60. package/dist/SubscriptionContext.d.ts.map +1 -0
  61. package/dist/SubscriptionContext.js +3 -0
  62. package/dist/SubscriptionContext.js.map +1 -0
  63. package/dist/constraints/ConstraintEnforcementService.d.ts +22 -0
  64. package/dist/constraints/ConstraintEnforcementService.d.ts.map +1 -0
  65. package/dist/constraints/ConstraintEnforcementService.js +209 -0
  66. package/dist/constraints/ConstraintEnforcementService.js.map +1 -0
  67. package/dist/constraints/ConstraintHandlerBundle.d.ts +19 -0
  68. package/dist/constraints/ConstraintHandlerBundle.d.ts.map +1 -0
  69. package/dist/constraints/ConstraintHandlerBundle.js +47 -0
  70. package/dist/constraints/ConstraintHandlerBundle.js.map +1 -0
  71. package/dist/constraints/SaplConstraintHandler.d.ts +3 -0
  72. package/dist/constraints/SaplConstraintHandler.d.ts.map +1 -0
  73. package/dist/constraints/SaplConstraintHandler.js +6 -0
  74. package/dist/constraints/SaplConstraintHandler.js.map +1 -0
  75. package/dist/constraints/StreamingConstraintHandlerBundle.d.ts +18 -0
  76. package/dist/constraints/StreamingConstraintHandlerBundle.d.ts.map +1 -0
  77. package/dist/constraints/StreamingConstraintHandlerBundle.js +34 -0
  78. package/dist/constraints/StreamingConstraintHandlerBundle.js.map +1 -0
  79. package/dist/constraints/api/index.d.ts +35 -0
  80. package/dist/constraints/api/index.d.ts.map +1 -0
  81. package/dist/constraints/api/index.js +11 -0
  82. package/dist/constraints/api/index.js.map +1 -0
  83. package/dist/constraints/providers/ContentFilter.d.ts +3 -0
  84. package/dist/constraints/providers/ContentFilter.d.ts.map +1 -0
  85. package/dist/constraints/providers/ContentFilter.js +224 -0
  86. package/dist/constraints/providers/ContentFilter.js.map +1 -0
  87. package/dist/constraints/providers/ContentFilterPredicateProvider.d.ts +6 -0
  88. package/dist/constraints/providers/ContentFilterPredicateProvider.d.ts.map +1 -0
  89. package/dist/constraints/providers/ContentFilterPredicateProvider.js +26 -0
  90. package/dist/constraints/providers/ContentFilterPredicateProvider.js.map +1 -0
  91. package/dist/constraints/providers/ContentFilteringProvider.d.ts +7 -0
  92. package/dist/constraints/providers/ContentFilteringProvider.d.ts.map +1 -0
  93. package/dist/constraints/providers/ContentFilteringProvider.js +29 -0
  94. package/dist/constraints/providers/ContentFilteringProvider.js.map +1 -0
  95. package/dist/enforcement-utils.d.ts +7 -0
  96. package/dist/enforcement-utils.d.ts.map +1 -0
  97. package/dist/enforcement-utils.js +28 -0
  98. package/dist/enforcement-utils.js.map +1 -0
  99. package/dist/index.d.ts +20 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +37 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/pdp.service.d.ts +17 -0
  104. package/dist/pdp.service.d.ts.map +1 -0
  105. package/dist/pdp.service.js +296 -0
  106. package/dist/pdp.service.js.map +1 -0
  107. package/dist/sapl.constants.d.ts +2 -0
  108. package/dist/sapl.constants.d.ts.map +1 -0
  109. package/dist/sapl.constants.js +5 -0
  110. package/dist/sapl.constants.js.map +1 -0
  111. package/dist/sapl.interfaces.d.ts +25 -0
  112. package/dist/sapl.interfaces.d.ts.map +1 -0
  113. package/dist/sapl.interfaces.js +3 -0
  114. package/dist/sapl.interfaces.js.map +1 -0
  115. package/dist/sapl.module.d.ts +7 -0
  116. package/dist/sapl.module.d.ts.map +1 -0
  117. package/dist/sapl.module.js +91 -0
  118. package/dist/sapl.module.js.map +1 -0
  119. package/dist/types.d.ts +29 -0
  120. package/dist/types.d.ts.map +1 -0
  121. package/dist/types.js +3 -0
  122. package/dist/types.js.map +1 -0
  123. package/package.json +67 -0
@@ -0,0 +1,15 @@
1
+ import { LazyDecorator, WrapParams } from '@toss/nestjs-aop';
2
+ import { ClsService } from 'nestjs-cls';
3
+ import { EnforceOptions } from './EnforceOptions';
4
+ import { PdpService } from './pdp.service';
5
+ import { ConstraintEnforcementService } from './constraints/ConstraintEnforcementService';
6
+ export declare class PostEnforceAspect implements LazyDecorator<any, EnforceOptions> {
7
+ private readonly pdpService;
8
+ private readonly cls;
9
+ private readonly constraintService;
10
+ private readonly logger;
11
+ constructor(pdpService: PdpService, cls: ClsService, constraintService: ConstraintEnforcementService);
12
+ wrap({ method, metadata, methodName, instance }: WrapParams<any, EnforceOptions>): (...args: any[]) => Promise<any>;
13
+ private handlePermit;
14
+ }
15
+ //# sourceMappingURL=PostEnforceAspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostEnforceAspect.d.ts","sourceRoot":"","sources":["../lib/PostEnforceAspect.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,4CAA4C,CAAC;AAG1F,qBACa,iBAAkB,YAAW,aAAa,CAAC,GAAG,EAAE,cAAc,CAAC;IAIxE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;gBAG1C,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,UAAU,EACf,iBAAiB,EAAE,4BAA4B;IAGlE,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,cAAc,CAAC,IAIhE,GAAG,MAAM,GAAG,EAAE;IAqB9B,OAAO,CAAC,YAAY;CA8BrB"}
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var PostEnforceAspect_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.PostEnforceAspect = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const nestjs_aop_1 = require("@toss/nestjs-aop");
16
+ const nestjs_cls_1 = require("nestjs-cls");
17
+ const PostEnforce_1 = require("./PostEnforce");
18
+ const pdp_service_1 = require("./pdp.service");
19
+ const SubscriptionBuilder_1 = require("./SubscriptionBuilder");
20
+ const ConstraintEnforcementService_1 = require("./constraints/ConstraintEnforcementService");
21
+ const enforcement_utils_1 = require("./enforcement-utils");
22
+ let PostEnforceAspect = PostEnforceAspect_1 = class PostEnforceAspect {
23
+ constructor(pdpService, cls, constraintService) {
24
+ this.pdpService = pdpService;
25
+ this.cls = cls;
26
+ this.constraintService = constraintService;
27
+ this.logger = new common_1.Logger(PostEnforceAspect_1.name);
28
+ }
29
+ wrap({ method, metadata, methodName, instance }) {
30
+ const aspect = this;
31
+ const className = instance.constructor.name;
32
+ return async (...args) => {
33
+ const handlerResult = await method(...args);
34
+ const ctx = (0, SubscriptionBuilder_1.buildContext)(aspect.cls, methodName, className, args);
35
+ ctx.returnValue = handlerResult;
36
+ const subscription = (0, SubscriptionBuilder_1.buildSubscriptionFromContext)(metadata, ctx);
37
+ const { secrets, ...safeForLog } = subscription;
38
+ aspect.logger.debug(`Subscription: ${JSON.stringify(safeForLog)}`);
39
+ const decision = await aspect.pdpService.decideOnce(subscription);
40
+ aspect.logger.debug(`Decision: ${JSON.stringify(decision)}`);
41
+ if (decision.decision === 'PERMIT') {
42
+ return aspect.handlePermit(decision, metadata, ctx, handlerResult);
43
+ }
44
+ return (0, enforcement_utils_1.handleDeny)(aspect.logger, aspect.constraintService, decision, metadata, ctx);
45
+ };
46
+ }
47
+ handlePermit(decision, options, ctx, handlerResult) {
48
+ let bundle;
49
+ try {
50
+ bundle = this.constraintService.postEnforceBundleFor(decision);
51
+ }
52
+ catch (error) {
53
+ this.logger.warn(`Obligation handling failed on PERMIT: ${error}`);
54
+ return (0, enforcement_utils_1.applyDeny)(options, ctx, decision);
55
+ }
56
+ try {
57
+ bundle.handleOnDecisionConstraints();
58
+ return bundle.handleAllOnNextConstraints(handlerResult);
59
+ }
60
+ catch (error) {
61
+ const asError = error instanceof Error ? error : new Error(String(error));
62
+ let mappedError = asError;
63
+ try {
64
+ mappedError = bundle.handleAllOnErrorConstraints(asError);
65
+ }
66
+ catch (handlerError) {
67
+ this.logger.warn(`Error handler failed while handling obligation failure: ${handlerError}`);
68
+ }
69
+ this.logger.warn(`Obligation handling failed on PERMIT: ${mappedError}`);
70
+ return (0, enforcement_utils_1.applyDeny)(options, ctx, decision);
71
+ }
72
+ }
73
+ };
74
+ exports.PostEnforceAspect = PostEnforceAspect;
75
+ exports.PostEnforceAspect = PostEnforceAspect = PostEnforceAspect_1 = __decorate([
76
+ (0, nestjs_aop_1.Aspect)(PostEnforce_1.POST_ENFORCE_SYMBOL),
77
+ __metadata("design:paramtypes", [pdp_service_1.PdpService,
78
+ nestjs_cls_1.ClsService,
79
+ ConstraintEnforcementService_1.ConstraintEnforcementService])
80
+ ], PostEnforceAspect);
81
+ //# sourceMappingURL=PostEnforceAspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PostEnforceAspect.js","sourceRoot":"","sources":["../lib/PostEnforceAspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import { EnforceOptions } from './EnforceOptions';
2
+ export declare const PRE_ENFORCE_SYMBOL: unique symbol;
3
+ /**
4
+ * Decorator that marks a method for SAPL pre-enforcement.
5
+ *
6
+ * Works on any injectable class method (controllers, services, etc.) via
7
+ * AOP aspects. The actual authorization check is performed by
8
+ * PreEnforceAspect, which builds an authorization subscription, calls
9
+ * the PDP, and blocks the invocation if the decision is not PERMIT.
10
+ *
11
+ * Because the aspect runs before the method, the method only executes
12
+ * on PERMIT. Use this for methods with side effects that should not
13
+ * execute when access is denied.
14
+ *
15
+ * Example:
16
+ * @PreEnforce({ action: 'read', resource: 'exportData' })
17
+ * @Get('exportData/:id')
18
+ * async getExportData(@Param('id') id: string) { ... }
19
+ */
20
+ export declare const PreEnforce: (options?: EnforceOptions) => MethodDecorator;
21
+ //# sourceMappingURL=PreEnforce.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreEnforce.d.ts","sourceRoot":"","sources":["../lib/PreEnforce.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,eAAO,MAAM,kBAAkB,eAA6B,CAAC;AAE7D;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,UAAU,GAAI,UAAS,cAAmB,oBACT,CAAC"}
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PreEnforce = exports.PRE_ENFORCE_SYMBOL = void 0;
4
+ const nestjs_aop_1 = require("@toss/nestjs-aop");
5
+ exports.PRE_ENFORCE_SYMBOL = Symbol('sapl:pre-enforce');
6
+ /**
7
+ * Decorator that marks a method for SAPL pre-enforcement.
8
+ *
9
+ * Works on any injectable class method (controllers, services, etc.) via
10
+ * AOP aspects. The actual authorization check is performed by
11
+ * PreEnforceAspect, which builds an authorization subscription, calls
12
+ * the PDP, and blocks the invocation if the decision is not PERMIT.
13
+ *
14
+ * Because the aspect runs before the method, the method only executes
15
+ * on PERMIT. Use this for methods with side effects that should not
16
+ * execute when access is denied.
17
+ *
18
+ * Example:
19
+ * @PreEnforce({ action: 'read', resource: 'exportData' })
20
+ * @Get('exportData/:id')
21
+ * async getExportData(@Param('id') id: string) { ... }
22
+ */
23
+ const PreEnforce = (options = {}) => (0, nestjs_aop_1.createDecorator)(exports.PRE_ENFORCE_SYMBOL, options);
24
+ exports.PreEnforce = PreEnforce;
25
+ //# sourceMappingURL=PreEnforce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreEnforce.js","sourceRoot":"","sources":["../lib/PreEnforce.ts"],"names":[],"mappings":";;;AAAA,iDAAmD;AAGtC,QAAA,kBAAkB,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAE7D;;;;;;;;;;;;;;;;GAgBG;AACI,MAAM,UAAU,GAAG,CAAC,UAA0B,EAAE,EAAE,EAAE,CACzD,IAAA,4BAAe,EAAC,0BAAkB,EAAE,OAAO,CAAC,CAAC;AADlC,QAAA,UAAU,cACwB"}
@@ -0,0 +1,15 @@
1
+ import { LazyDecorator, WrapParams } from '@toss/nestjs-aop';
2
+ import { ClsService } from 'nestjs-cls';
3
+ import { EnforceOptions } from './EnforceOptions';
4
+ import { PdpService } from './pdp.service';
5
+ import { ConstraintEnforcementService } from './constraints/ConstraintEnforcementService';
6
+ export declare class PreEnforceAspect implements LazyDecorator<any, EnforceOptions> {
7
+ private readonly pdpService;
8
+ private readonly cls;
9
+ private readonly constraintService;
10
+ private readonly logger;
11
+ constructor(pdpService: PdpService, cls: ClsService, constraintService: ConstraintEnforcementService);
12
+ wrap({ method, metadata, methodName, instance }: WrapParams<any, EnforceOptions>): (...args: any[]) => Promise<any>;
13
+ private handlePermit;
14
+ }
15
+ //# sourceMappingURL=PreEnforceAspect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreEnforceAspect.d.ts","sourceRoot":"","sources":["../lib/PreEnforceAspect.ts"],"names":[],"mappings":"AACA,OAAO,EAAU,aAAa,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAElD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,OAAO,EAAE,4BAA4B,EAAE,MAAM,4CAA4C,CAAC;AAG1F,qBACa,gBAAiB,YAAW,aAAa,CAAC,GAAG,EAAE,cAAc,CAAC;IAIvE,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IALpC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAGzC,UAAU,EAAE,UAAU,EACtB,GAAG,EAAE,UAAU,EACf,iBAAiB,EAAE,4BAA4B;IAGlE,IAAI,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,EAAE,UAAU,CAAC,GAAG,EAAE,cAAc,CAAC,IAIhE,GAAG,MAAM,GAAG,EAAE;IAiB9B,OAAO,CAAC,YAAY;CAqErB"}
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var PreEnforceAspect_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.PreEnforceAspect = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const nestjs_aop_1 = require("@toss/nestjs-aop");
16
+ const nestjs_cls_1 = require("nestjs-cls");
17
+ const PreEnforce_1 = require("./PreEnforce");
18
+ const pdp_service_1 = require("./pdp.service");
19
+ const SubscriptionBuilder_1 = require("./SubscriptionBuilder");
20
+ const ConstraintEnforcementService_1 = require("./constraints/ConstraintEnforcementService");
21
+ const enforcement_utils_1 = require("./enforcement-utils");
22
+ let PreEnforceAspect = PreEnforceAspect_1 = class PreEnforceAspect {
23
+ constructor(pdpService, cls, constraintService) {
24
+ this.pdpService = pdpService;
25
+ this.cls = cls;
26
+ this.constraintService = constraintService;
27
+ this.logger = new common_1.Logger(PreEnforceAspect_1.name);
28
+ }
29
+ wrap({ method, metadata, methodName, instance }) {
30
+ const aspect = this;
31
+ const className = instance.constructor.name;
32
+ return async (...args) => {
33
+ const ctx = (0, SubscriptionBuilder_1.buildContext)(aspect.cls, methodName, className, args);
34
+ const subscription = (0, SubscriptionBuilder_1.buildSubscriptionFromContext)(metadata, ctx);
35
+ const { secrets, ...safeForLog } = subscription;
36
+ aspect.logger.debug(`Subscription: ${JSON.stringify(safeForLog)}`);
37
+ const decision = await aspect.pdpService.decideOnce(subscription);
38
+ aspect.logger.debug(`Decision: ${JSON.stringify(decision)}`);
39
+ if (decision.decision === 'PERMIT') {
40
+ return aspect.handlePermit(decision, metadata, ctx, method, args, methodName, className);
41
+ }
42
+ return (0, enforcement_utils_1.handleDeny)(aspect.logger, aspect.constraintService, decision, metadata, ctx);
43
+ };
44
+ }
45
+ handlePermit(decision, options, ctx, method, args, methodName, className) {
46
+ let bundle;
47
+ try {
48
+ bundle = this.constraintService.preEnforceBundleFor(decision);
49
+ }
50
+ catch (error) {
51
+ this.logger.warn(`Obligation handling failed on PERMIT: ${error}`);
52
+ return (0, enforcement_utils_1.applyDeny)(options, ctx, decision);
53
+ }
54
+ // Phase 1: pre-method obligation handlers -- failure denies access
55
+ const invocationContext = {
56
+ request: ctx.request,
57
+ args,
58
+ methodName,
59
+ className,
60
+ };
61
+ try {
62
+ bundle.handleOnDecisionConstraints();
63
+ bundle.handleMethodInvocationHandlers(invocationContext);
64
+ }
65
+ catch (error) {
66
+ this.logger.warn(`Obligation handling failed on PERMIT: ${error}`);
67
+ return (0, enforcement_utils_1.applyDeny)(options, ctx, decision);
68
+ }
69
+ // Phase 2: method execution -- errors propagate after error handler mapping
70
+ let result;
71
+ try {
72
+ result = method(...invocationContext.args);
73
+ }
74
+ catch (methodError) {
75
+ throw bundle.handleAllOnErrorConstraints(methodError instanceof Error ? methodError : new Error(String(methodError)));
76
+ }
77
+ // Phase 3: post-method obligation handlers -- failure denies access
78
+ if (result instanceof Promise) {
79
+ return result.then((value) => {
80
+ try {
81
+ return bundle.handleAllOnNextConstraints(value);
82
+ }
83
+ catch (obligationError) {
84
+ this.logger.warn(`Obligation handling failed on PERMIT: ${obligationError}`);
85
+ return (0, enforcement_utils_1.applyDeny)(options, ctx, decision);
86
+ }
87
+ }, (methodError) => {
88
+ throw bundle.handleAllOnErrorConstraints(methodError instanceof Error ? methodError : new Error(String(methodError)));
89
+ });
90
+ }
91
+ try {
92
+ return bundle.handleAllOnNextConstraints(result);
93
+ }
94
+ catch (obligationError) {
95
+ this.logger.warn(`Obligation handling failed on PERMIT: ${obligationError}`);
96
+ return (0, enforcement_utils_1.applyDeny)(options, ctx, decision);
97
+ }
98
+ }
99
+ };
100
+ exports.PreEnforceAspect = PreEnforceAspect;
101
+ exports.PreEnforceAspect = PreEnforceAspect = PreEnforceAspect_1 = __decorate([
102
+ (0, nestjs_aop_1.Aspect)(PreEnforce_1.PRE_ENFORCE_SYMBOL),
103
+ __metadata("design:paramtypes", [pdp_service_1.PdpService,
104
+ nestjs_cls_1.ClsService,
105
+ ConstraintEnforcementService_1.ConstraintEnforcementService])
106
+ ], PreEnforceAspect);
107
+ //# sourceMappingURL=PreEnforceAspect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreEnforceAspect.js","sourceRoot":"","sources":["../lib/PreEnforceAspect.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { SubscriptionOptions } from './EnforceOptions';
2
+ import { AuthorizationDecision } from './types';
3
+ /**
4
+ * Restricted emitter passed to streaming callbacks. Only exposes `.next()` to
5
+ * prevent user code from interfering with the stream lifecycle (error/complete)
6
+ * which is managed by the enforcement aspect.
7
+ */
8
+ export interface StreamEventEmitter {
9
+ next(value: any): void;
10
+ }
11
+ export type OnStreamDenyHandler = (decision: AuthorizationDecision, emitter: StreamEventEmitter) => void;
12
+ export type OnStreamRecoverHandler = (decision: AuthorizationDecision, emitter: StreamEventEmitter) => void;
13
+ export interface EnforceTillDeniedOptions extends SubscriptionOptions {
14
+ onStreamDeny?: OnStreamDenyHandler;
15
+ }
16
+ export interface EnforceDropWhileDeniedOptions extends SubscriptionOptions {
17
+ }
18
+ export interface EnforceRecoverableOptions extends SubscriptionOptions {
19
+ onStreamDeny?: OnStreamDenyHandler;
20
+ onStreamRecover?: OnStreamRecoverHandler;
21
+ }
22
+ //# sourceMappingURL=StreamingEnforceOptions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingEnforceOptions.d.ts","sourceRoot":"","sources":["../lib/StreamingEnforceOptions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAEhD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,CAAC;CACxB;AAED,MAAM,MAAM,mBAAmB,GAAG,CAAC,QAAQ,EAAE,qBAAqB,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;AACzG,MAAM,MAAM,sBAAsB,GAAG,CAAC,QAAQ,EAAE,qBAAqB,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;AAE5G,MAAM,WAAW,wBAAyB,SAAQ,mBAAmB;IACnE,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,MAAM,WAAW,6BAA8B,SAAQ,mBAAmB;CACzE;AAED,MAAM,WAAW,yBAA0B,SAAQ,mBAAmB;IACpE,YAAY,CAAC,EAAE,mBAAmB,CAAC;IACnC,eAAe,CAAC,EAAE,sBAAsB,CAAC;CAC1C"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=StreamingEnforceOptions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingEnforceOptions.js","sourceRoot":"","sources":["../lib/StreamingEnforceOptions.ts"],"names":[],"mappings":""}
@@ -0,0 +1,17 @@
1
+ import { ClsService } from 'nestjs-cls';
2
+ import { SubscriptionContext } from './SubscriptionContext';
3
+ import { SubscriptionOptions } from './EnforceOptions';
4
+ import { AuthorizationSubscription } from './types';
5
+ /**
6
+ * Build a SubscriptionContext from the current CLS request and method metadata.
7
+ */
8
+ export declare function buildContext(cls: ClsService, methodName: string, className: string, args: any[]): SubscriptionContext;
9
+ /**
10
+ * Build a complete SAPL authorization subscription from SubscriptionOptions
11
+ * and a pre-built SubscriptionContext.
12
+ *
13
+ * For each field: if the user provided a value (literal or callback), use it.
14
+ * Otherwise apply the sensible default.
15
+ */
16
+ export declare function buildSubscriptionFromContext(options: SubscriptionOptions, ctx: SubscriptionContext): AuthorizationSubscription;
17
+ //# sourceMappingURL=SubscriptionBuilder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriptionBuilder.d.ts","sourceRoot":"","sources":["../lib/SubscriptionBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAqB,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAC;AAqDpD;;GAEG;AACH,wBAAgB,YAAY,CAC1B,GAAG,EAAE,UAAU,EACf,UAAU,EAAE,MAAM,EAClB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,GAAG,EAAE,GACV,mBAAmB,CAWrB;AAED;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,mBAAmB,EAC5B,GAAG,EAAE,mBAAmB,GACvB,yBAAyB,CAY3B"}
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildContext = buildContext;
4
+ exports.buildSubscriptionFromContext = buildSubscriptionFromContext;
5
+ const nestjs_cls_1 = require("nestjs-cls");
6
+ /**
7
+ * Resolve a SubscriptionField: if it's a function, call it with the context.
8
+ * Otherwise return it as a literal value.
9
+ */
10
+ function resolve(field, ctx) {
11
+ return typeof field === 'function' ? field(ctx) : field;
12
+ }
13
+ /**
14
+ * Build the default subject: the decoded JWT claims from request.user,
15
+ * falling back to "anonymous" if no auth guard populated it.
16
+ */
17
+ function defaultSubject(ctx) {
18
+ return ctx.request.user ?? 'anonymous';
19
+ }
20
+ /**
21
+ * Build the default action: HTTP method + controller/handler coordinates.
22
+ */
23
+ function defaultAction(ctx) {
24
+ return {
25
+ method: ctx.request.method,
26
+ controller: ctx.controller,
27
+ handler: ctx.handler,
28
+ };
29
+ }
30
+ /**
31
+ * Build the default resource: route path pattern + resolved parameters.
32
+ */
33
+ function defaultResource(ctx) {
34
+ return {
35
+ path: ctx.request.route?.path ?? ctx.request.url,
36
+ params: ctx.params,
37
+ };
38
+ }
39
+ /**
40
+ * Build the default environment: server-side request metadata only.
41
+ * Client-controlled headers (Date, X-Forwarded-For, X-Request-Id,
42
+ * X-Correlation-Id) are deliberately excluded because they can be forged.
43
+ * Use the environment callback in EnforceOptions to include them explicitly
44
+ * if needed.
45
+ */
46
+ function defaultEnvironment(ctx) {
47
+ return {
48
+ ip: ctx.request.ip,
49
+ hostname: ctx.request.hostname,
50
+ };
51
+ }
52
+ /**
53
+ * Build a SubscriptionContext from the current CLS request and method metadata.
54
+ */
55
+ function buildContext(cls, methodName, className, args) {
56
+ const request = cls.get(nestjs_cls_1.CLS_REQ) ?? {};
57
+ return {
58
+ request,
59
+ params: request.params ?? {},
60
+ query: request.query ?? {},
61
+ body: request.body,
62
+ handler: methodName,
63
+ controller: className,
64
+ args,
65
+ };
66
+ }
67
+ /**
68
+ * Build a complete SAPL authorization subscription from SubscriptionOptions
69
+ * and a pre-built SubscriptionContext.
70
+ *
71
+ * For each field: if the user provided a value (literal or callback), use it.
72
+ * Otherwise apply the sensible default.
73
+ */
74
+ function buildSubscriptionFromContext(options, ctx) {
75
+ const subject = options.subject !== undefined ? resolve(options.subject, ctx) : defaultSubject(ctx);
76
+ const action = options.action !== undefined ? resolve(options.action, ctx) : defaultAction(ctx);
77
+ const resource = options.resource !== undefined ? resolve(options.resource, ctx) : defaultResource(ctx);
78
+ const environment = options.environment !== undefined ? resolve(options.environment, ctx) : defaultEnvironment(ctx);
79
+ const secrets = options.secrets !== undefined ? resolve(options.secrets, ctx) : undefined;
80
+ const subscription = { subject, action, resource, environment };
81
+ if (secrets !== undefined) {
82
+ subscription.secrets = secrets;
83
+ }
84
+ return subscription;
85
+ }
86
+ //# sourceMappingURL=SubscriptionBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriptionBuilder.js","sourceRoot":"","sources":["../lib/SubscriptionBuilder.ts"],"names":[],"mappings":";;AA2DA,oCAgBC;AASD,oEAeC;AAnGD,2CAAiD;AAKjD;;;GAGG;AACH,SAAS,OAAO,CAAC,KAAoC,EAAE,GAAwB;IAC7E,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1D,CAAC;AAED;;;GAGG;AACH,SAAS,cAAc,CAAC,GAAwB;IAC9C,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,WAAW,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,GAAwB;IAC7C,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM;QAC1B,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,GAAG,CAAC,OAAO;KACrB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,GAAwB;IAC/C,OAAO;QACL,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG;QAChD,MAAM,EAAE,GAAG,CAAC,MAAM;KACnB,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,GAAwB;IAClD,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE;QAClB,QAAQ,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ;KAC/B,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAC1B,GAAe,EACf,UAAkB,EAClB,SAAiB,EACjB,IAAW;IAEX,MAAM,OAAO,GAAG,GAAG,CAAC,GAAG,CAAC,oBAAO,CAAC,IAAI,EAAE,CAAC;IACvC,OAAO;QACL,OAAO;QACP,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;QAC5B,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;QAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;QAClB,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,SAAS;QACrB,IAAI;KACL,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,4BAA4B,CAC1C,OAA4B,EAC5B,GAAwB;IAExB,MAAM,OAAO,GAAO,OAAO,CAAC,OAAO,KAAS,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAK,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IAChH,MAAM,MAAM,GAAQ,OAAO,CAAC,MAAM,KAAU,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAM,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC/G,MAAM,QAAQ,GAAM,OAAO,CAAC,QAAQ,KAAQ,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAI,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IACjH,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACpH,MAAM,OAAO,GAAO,OAAO,CAAC,OAAO,KAAS,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAK,CAAC,CAAC,SAAS,CAAC;IAEtG,MAAM,YAAY,GAA8B,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;IAC3F,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,YAAY,CAAC,OAAO,GAAG,OAAO,CAAC;IACjC,CAAC;IACD,OAAO,YAAY,CAAC;AACtB,CAAC"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Minimal structural type for the HTTP request. Covers properties used by
3
+ * the library's default subscription builders. Compatible with both Express
4
+ * and Fastify request objects.
5
+ */
6
+ export interface SaplRequest {
7
+ user?: unknown;
8
+ method?: string;
9
+ url?: string;
10
+ ip?: string;
11
+ hostname?: string;
12
+ route?: {
13
+ path?: string;
14
+ };
15
+ params?: Record<string, string>;
16
+ query?: Record<string, string | string[]>;
17
+ body?: unknown;
18
+ headers?: Record<string, string | string[] | undefined>;
19
+ [key: string]: unknown;
20
+ }
21
+ /**
22
+ * Context available to subscription field callbacks at request time.
23
+ *
24
+ * Passed to any EnforceOptions field that is a function, allowing dynamic
25
+ * subscription construction based on the current request.
26
+ *
27
+ * Example:
28
+ * @PreEnforce({ resource: (ctx) => ({ pilotId: ctx.params.pilotId }) })
29
+ */
30
+ export interface SubscriptionContext {
31
+ /** The full HTTP request object (has .user, .headers, .cookies, etc.) */
32
+ request: SaplRequest;
33
+ /** Route parameters -- @Get(':pilotId') -> ctx.params.pilotId */
34
+ params: Record<string, string>;
35
+ /** Query string parameters -- ?page=2 -> ctx.query.page */
36
+ query: Record<string, string | string[]>;
37
+ /** Request body (POST/PUT) */
38
+ body: any;
39
+ /** Handler method name on the controller */
40
+ handler: string;
41
+ /** Controller class name */
42
+ controller: string;
43
+ /** Handler return value (only populated in @PostEnforce context) */
44
+ returnValue?: any;
45
+ /** Method arguments (available for service methods outside HTTP context) */
46
+ args?: any[];
47
+ }
48
+ //# sourceMappingURL=SubscriptionContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriptionContext.d.ts","sourceRoot":"","sources":["../lib/SubscriptionContext.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACxD,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAClC,yEAAyE;IACzE,OAAO,EAAE,WAAW,CAAC;IACrB,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IACzC,8BAA8B;IAC9B,IAAI,EAAE,GAAG,CAAC;IACV,4CAA4C;IAC5C,OAAO,EAAE,MAAM,CAAC;IAChB,4BAA4B;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,oEAAoE;IACpE,WAAW,CAAC,EAAE,GAAG,CAAC;IAClB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;CACd"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=SubscriptionContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriptionContext.js","sourceRoot":"","sources":["../lib/SubscriptionContext.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { OnModuleInit } from '@nestjs/common';
2
+ import { DiscoveryService } from '@nestjs/core';
3
+ import { ConstraintHandlerBundle } from './ConstraintHandlerBundle';
4
+ import { StreamingConstraintHandlerBundle } from './StreamingConstraintHandlerBundle';
5
+ import { AuthorizationDecision } from '../types';
6
+ export declare class ConstraintEnforcementService implements OnModuleInit {
7
+ private readonly discovery;
8
+ private readonly logger;
9
+ private readonly handlers;
10
+ constructor(discovery: DiscoveryService);
11
+ onModuleInit(): void;
12
+ preEnforceBundleFor(decision: AuthorizationDecision): ConstraintHandlerBundle;
13
+ postEnforceBundleFor(decision: AuthorizationDecision): ConstraintHandlerBundle;
14
+ bestEffortBundleFor(decision: AuthorizationDecision): ConstraintHandlerBundle;
15
+ streamingBundleFor(decision: AuthorizationDecision): StreamingConstraintHandlerBundle;
16
+ streamingBestEffortBundleFor(decision: AuthorizationDecision): StreamingConstraintHandlerBundle;
17
+ private processHandlers;
18
+ private collectHandlers;
19
+ private buildBundle;
20
+ private buildStreamingBundle;
21
+ }
22
+ //# sourceMappingURL=ConstraintEnforcementService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConstraintEnforcementService.d.ts","sourceRoot":"","sources":["../../lib/constraints/ConstraintEnforcementService.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACtF,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAGhD,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,gCAAgC,EAAE,MAAM,oCAAoC,CAAC;AACtF,OAAO,EAAE,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAwHjD,qBACa,4BAA6B,YAAW,YAAY;IAYnD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAXtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAiD;IACxE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAQvB;gBAE2B,SAAS,EAAE,gBAAgB;IAExD,YAAY;IAwBZ,mBAAmB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,uBAAuB;IAI7E,oBAAoB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,uBAAuB;IAI9E,mBAAmB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,uBAAuB;IAI7E,kBAAkB,CAAC,QAAQ,EAAE,qBAAqB,GAAG,gCAAgC;IAIrF,4BAA4B,CAAC,QAAQ,EAAE,qBAAqB,GAAG,gCAAgC;IAI/F,OAAO,CAAC,eAAe;IAkCvB,OAAO,CAAC,eAAe;IA2EvB,OAAO,CAAC,WAAW;IAkBnB,OAAO,CAAC,oBAAoB;CAsB7B"}