@cullet/erp-core 1.0.2 → 1.0.3

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 (144) hide show
  1. package/README.md +24 -24
  2. package/dist/gate-engine-registry.js.map +1 -1
  3. package/dist/gate-v1-payload.schema.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/outcome.js.map +1 -1
  8. package/dist/policies/engines/v1/gate/index.js.map +1 -1
  9. package/dist/policy-service.js.map +1 -1
  10. package/dist/validation-code.js.map +1 -1
  11. package/dist/validation-error.js.map +1 -1
  12. package/dist/validation-field.js.map +1 -1
  13. package/meta.json +67 -67
  14. package/package.json +56 -56
  15. package/src/core/application/commands/command.ts +3 -3
  16. package/src/core/application/commands/requested-by.ts +60 -60
  17. package/src/core/application/index.ts +21 -21
  18. package/src/core/application/policy-error-mapper.ts +54 -54
  19. package/src/core/application/ports/index.ts +6 -6
  20. package/src/core/application/ports/logger.port.ts +4 -4
  21. package/src/core/application/ports/metrics.port.ts +3 -3
  22. package/src/core/application/ports/policy-port.ts +7 -7
  23. package/src/core/application/ports/repository.port.ts +3 -3
  24. package/src/core/application/ports/temporal-repository.port.ts +4 -4
  25. package/src/core/application/ports/tracer.port.ts +7 -7
  26. package/src/core/application/queries/query.ts +13 -13
  27. package/src/core/application/temporal/index.ts +7 -7
  28. package/src/core/application/temporal/temporal-context.ts +20 -20
  29. package/src/core/application/temporal/temporal-use-case.ts +22 -22
  30. package/src/core/application/use-case.ts +10 -10
  31. package/src/core/config/core-config.instance.ts +1 -1
  32. package/src/core/config/core-config.ts +59 -59
  33. package/src/core/config/index.ts +6 -6
  34. package/src/core/config/policy-reporter.ts +31 -31
  35. package/src/core/config/silent-policy-reporter.ts +1 -1
  36. package/src/core/domain/entity.ts +44 -44
  37. package/src/core/domain/rulesets/entity-ruleset.contracts.ts +6 -6
  38. package/src/core/domain/rulesets/ruleset-registry.ts +49 -49
  39. package/src/core/domain/rulesets/ruleset.contracts.ts +6 -6
  40. package/src/core/domain/rulesets/value-object-ruleset.contracts.ts +5 -5
  41. package/src/core/domain/temporal/index.ts +11 -11
  42. package/src/core/domain/temporal/temporal-range.ts +16 -16
  43. package/src/core/domain/temporal/temporal-snapshot.ts +24 -24
  44. package/src/core/domain/temporal/transaction-time.ts +30 -30
  45. package/src/core/domain/temporal/valid-time.ts +29 -29
  46. package/src/core/domain/value-object.ts +16 -16
  47. package/src/core/errors/app-error.ts +64 -64
  48. package/src/core/errors/authentication-error.ts +134 -134
  49. package/src/core/errors/authorization-error.ts +154 -154
  50. package/src/core/errors/business-rule-violation-error.ts +15 -15
  51. package/src/core/errors/conflict-error.ts +202 -201
  52. package/src/core/errors/error-codes.ts +48 -48
  53. package/src/core/errors/idempotency-error.ts +324 -320
  54. package/src/core/errors/index.ts +50 -50
  55. package/src/core/errors/integration-error.ts +120 -120
  56. package/src/core/errors/legacy-incompatible-error.ts +13 -13
  57. package/src/core/errors/not-found-error.ts +14 -14
  58. package/src/core/errors/serialization-error.ts +167 -167
  59. package/src/core/errors/temporal-error.ts +109 -107
  60. package/src/core/errors/types.ts +35 -35
  61. package/src/core/errors/unexpected-error.ts +10 -10
  62. package/src/core/errors/utils/index.ts +2 -2
  63. package/src/core/errors/utils/json-safe.ts +53 -53
  64. package/src/core/errors/validation-error.ts +18 -18
  65. package/src/core/exceptions/business-rule-violation-exception.ts +6 -6
  66. package/src/core/exceptions/domain-exception.ts +5 -5
  67. package/src/core/exceptions/entity-not-found-exception.ts +6 -6
  68. package/src/core/exceptions/invalid-state-transition-exception.ts +8 -8
  69. package/src/core/exceptions/invariant-violation-exception.ts +3 -3
  70. package/src/core/exceptions/validation-code.ts +35 -29
  71. package/src/core/exceptions/validation-exception.ts +19 -19
  72. package/src/core/exceptions/validation-field.ts +20 -19
  73. package/src/core/index.ts +7 -7
  74. package/src/core/policies/asof/asof.ts +47 -47
  75. package/src/core/policies/catalog/catalog.instance.ts +8 -6
  76. package/src/core/policies/catalog/index.ts +4 -4
  77. package/src/core/policies/catalog/policy-catalog-entry.ts +199 -197
  78. package/src/core/policies/catalog/policy-catalog.ts +101 -101
  79. package/src/core/policies/catalog/policy-key.ts +51 -51
  80. package/src/core/policies/context/context-builder.ts +335 -313
  81. package/src/core/policies/context/context-registry.instance.ts +9 -9
  82. package/src/core/policies/context/context-registry.ts +61 -61
  83. package/src/core/policies/context/context-resolver.ts +12 -12
  84. package/src/core/policies/context/context-seed.ts +19 -15
  85. package/src/core/policies/context/index.ts +9 -9
  86. package/src/core/policies/context/path.ts +135 -128
  87. package/src/core/policies/defs/in-memory-policy-definition-repo.ts +56 -55
  88. package/src/core/policies/defs/index.ts +10 -10
  89. package/src/core/policies/defs/policy-definition-repository.ts +3 -3
  90. package/src/core/policies/defs/policy-definition.ts +143 -142
  91. package/src/core/policies/defs/policy-scope.ts +21 -19
  92. package/src/core/policies/defs/policy-semver.ts +51 -51
  93. package/src/core/policies/engines/compute-engine-registry.ts +43 -43
  94. package/src/core/policies/engines/compute-evaluator-registry.ts +20 -20
  95. package/src/core/policies/engines/compute-registry.ts +45 -45
  96. package/src/core/policies/engines/compute-types.ts +15 -15
  97. package/src/core/policies/engines/condition-evaluator-reporter.ts +17 -17
  98. package/src/core/policies/engines/gate-engine-registry.ts +27 -25
  99. package/src/core/policies/engines/gate-types.ts +28 -28
  100. package/src/core/policies/engines/index.ts +28 -28
  101. package/src/core/policies/engines/parse-compute-payload.ts +51 -45
  102. package/src/core/policies/engines/parse-gate-payload.ts +42 -42
  103. package/src/core/policies/engines/v1/compute/compute-engine-v1.ts +39 -37
  104. package/src/core/policies/engines/v1/compute/compute-payload.schema.ts +43 -41
  105. package/src/core/policies/engines/v1/compute/index.ts +6 -6
  106. package/src/core/policies/engines/v1/compute/resolve-decision-table-v1.ts +41 -39
  107. package/src/core/policies/engines/v1/condition-evaluator.ts +547 -505
  108. package/src/core/policies/engines/v1/condition-schema.ts +35 -35
  109. package/src/core/policies/engines/v1/condition-types.ts +21 -21
  110. package/src/core/policies/engines/v1/gate/gate-engine-v1.ts +134 -130
  111. package/src/core/policies/engines/v1/gate/gate-types-v1.ts +5 -5
  112. package/src/core/policies/engines/v1/gate/gate-v1-payload.schema.ts +32 -30
  113. package/src/core/policies/engines/v1/gate/index.ts +4 -4
  114. package/src/core/policies/engines/v1/index.ts +8 -8
  115. package/src/core/policies/index.ts +72 -72
  116. package/src/core/policies/package/policy-package.ts +3 -3
  117. package/src/core/policies/policy-ids.ts +25 -25
  118. package/src/core/policies/resolver/policy-resolver.ts +34 -34
  119. package/src/core/policies/service/index.ts +6 -6
  120. package/src/core/policies/service/policy-evaluation-error.ts +141 -133
  121. package/src/core/policies/service/policy-service.ts +432 -419
  122. package/src/core/policies/utils/date.ts +3 -3
  123. package/src/core/policies/utils/hash.ts +61 -61
  124. package/src/core/result/outcome.ts +131 -126
  125. package/src/core/result/result.ts +130 -127
  126. package/src/core/shared/aggregate-version.ts +5 -5
  127. package/src/core/shared/hashing.ts +18 -18
  128. package/src/core/shared/immutable.ts +29 -29
  129. package/src/core/shared/temporal-guards.ts +9 -9
  130. package/src/core/versioning/domain-event-contracts.ts +40 -40
  131. package/src/core/versioning/version.ts +19 -19
  132. package/src/examples/rulesets/entity/order-creation-rules-v1.ts +18 -18
  133. package/src/examples/rulesets/entity/order-invariants-v1.ts +31 -29
  134. package/src/examples/rulesets/entity/order-invariants-v2.ts +12 -12
  135. package/src/examples/rulesets/entity/order.ts +127 -127
  136. package/src/examples/rulesets/value-object/cpf-rules-v1.ts +41 -39
  137. package/src/examples/rulesets/value-object/cpf-rules-v2.ts +14 -12
  138. package/src/examples/rulesets/value-object/cpf.ts +24 -24
  139. package/src/examples/rulesets/value-object/customer.ts +42 -39
  140. package/src/examples/rulesets/value-object/person-name-rules-v1.ts +27 -27
  141. package/src/examples/rulesets/value-object/person-name-rules-v2.ts +13 -13
  142. package/src/examples/rulesets/value-object/person-name.ts +29 -26
  143. package/src/index.ts +2 -2
  144. package/src/version.ts +1 -1
@@ -8,117 +8,117 @@ import { PolicyCatalogEntry } from "./policy-catalog-entry";
8
8
  * The catalog defines the universe of policies; the database cannot invent new ones.
9
9
  */
10
10
  export class PolicyCatalog {
11
- private readonly versionedEntries: ReadonlyMap<string, PolicyCatalogEntry>;
12
- private readonly entriesByKey: ReadonlyMap<
13
- string,
14
- readonly PolicyCatalogEntry[]
15
- >;
16
-
17
- constructor(entries: readonly PolicyCatalogEntry[]) {
18
- const families = new Map<string, PolicyCatalogEntry[]>();
19
- const versionedMap = new Map<string, PolicyCatalogEntry>();
20
-
21
- for (const rawEntry of entries) {
22
- const entry = PolicyCatalogEntry.from(rawEntry);
23
- const key = entry.key.toString();
24
- const variantKey = entry.toVariantKey();
25
-
26
- if (versionedMap.has(variantKey)) {
27
- throw new UnexpectedError(
28
- `Duplicate PolicyCatalog entry for key "${key}" and variant "${variantKey}"`,
29
- );
30
- }
31
-
32
- const family = families.get(key) ?? [];
33
- family.push(entry);
34
- families.set(key, family);
35
- versionedMap.set(variantKey, entry);
36
- }
37
-
38
- for (const family of families.values()) {
39
- PolicyCatalogEntry.assertFamilyConsistency(family);
11
+ private readonly versionedEntries: ReadonlyMap<string, PolicyCatalogEntry>;
12
+ private readonly entriesByKey: ReadonlyMap<
13
+ string,
14
+ readonly PolicyCatalogEntry[]
15
+ >;
16
+
17
+ constructor(entries: readonly PolicyCatalogEntry[]) {
18
+ const families = new Map<string, PolicyCatalogEntry[]>();
19
+ const versionedMap = new Map<string, PolicyCatalogEntry>();
20
+
21
+ for (const rawEntry of entries) {
22
+ const entry = PolicyCatalogEntry.from(rawEntry);
23
+ const key = entry.key.toString();
24
+ const variantKey = entry.toVariantKey();
25
+
26
+ if (versionedMap.has(variantKey)) {
27
+ throw new UnexpectedError(
28
+ `Duplicate PolicyCatalog entry for key "${key}" and variant "${variantKey}"`,
29
+ );
30
+ }
31
+
32
+ const family = families.get(key) ?? [];
33
+ family.push(entry);
34
+ families.set(key, family);
35
+ versionedMap.set(variantKey, entry);
36
+ }
37
+
38
+ for (const family of families.values()) {
39
+ PolicyCatalogEntry.assertFamilyConsistency(family);
40
+ }
41
+
42
+ this.versionedEntries = versionedMap;
43
+ this.entriesByKey = families;
40
44
  }
41
45
 
42
- this.versionedEntries = versionedMap;
43
- this.entriesByKey = families;
44
- }
45
-
46
- get(key: string): Result<PolicyCatalogEntry, string> {
47
- const familyResult = this.getFamily(key);
48
- if (familyResult.isErr()) {
49
- return Result.err(familyResult.errorOrNull()!);
46
+ get(key: string): Result<PolicyCatalogEntry, string> {
47
+ const familyResult = this.getFamily(key);
48
+ if (familyResult.isErr()) {
49
+ return Result.err(familyResult.errorOrNull()!);
50
+ }
51
+
52
+ const family = familyResult.getOrNull()!;
53
+ if (family.length > 1) {
54
+ return Result.err(
55
+ `Policy key "${key}" has multiple catalog variants; use getVersioned(...) or getFamily(...)`,
56
+ );
57
+ }
58
+
59
+ const [entry] = family;
60
+ if (!entry) {
61
+ return Result.err(`Policy not found in catalog: "${key}"`);
62
+ }
63
+
64
+ return Result.ok(entry);
50
65
  }
51
66
 
52
- const family = familyResult.getOrNull()!;
53
- if (family.length > 1) {
54
- return Result.err(
55
- `Policy key "${key}" has multiple catalog variants; use getVersioned(...) or getFamily(...)`,
56
- );
57
- }
67
+ getFamily(key: string): Result<readonly PolicyCatalogEntry[], string> {
68
+ const family = this.entriesByKey.get(key);
69
+ if (!family) {
70
+ return Result.err(`Policy not found in catalog: "${key}"`);
71
+ }
58
72
 
59
- const [entry] = family;
60
- if (!entry) {
61
- return Result.err(`Policy not found in catalog: "${key}"`);
73
+ return Result.ok(family);
62
74
  }
63
75
 
64
- return Result.ok(entry);
65
- }
66
-
67
- getFamily(key: string): Result<readonly PolicyCatalogEntry[], string> {
68
- const family = this.entriesByKey.get(key);
69
- if (!family) {
70
- return Result.err(`Policy not found in catalog: "${key}"`);
71
- }
72
-
73
- return Result.ok(family);
74
- }
75
-
76
- getVersioned(params: {
77
- readonly key: string;
78
- readonly kind: "GATE" | "COMPUTE";
79
- readonly gateEngineVersion?: number;
80
- readonly computeEngineVersion?: number;
81
- readonly payloadSchemaVersion?: number;
82
- }): Result<PolicyCatalogEntry, string> {
83
- const family = this.entriesByKey.get(params.key);
84
- if (!family || family.length === 0) {
85
- return Result.err(`Policy not found in catalog: "${params.key}"`);
76
+ getVersioned(params: {
77
+ readonly key: string;
78
+ readonly kind: "GATE" | "COMPUTE";
79
+ readonly gateEngineVersion?: number;
80
+ readonly computeEngineVersion?: number;
81
+ readonly payloadSchemaVersion?: number;
82
+ }): Result<PolicyCatalogEntry, string> {
83
+ const family = this.entriesByKey.get(params.key);
84
+ if (!family || family.length === 0) {
85
+ return Result.err(`Policy not found in catalog: "${params.key}"`);
86
+ }
87
+
88
+ const exactMatch = family.find((entry) => entry.matchesVersion(params));
89
+ if (exactMatch) {
90
+ return Result.ok(exactMatch);
91
+ }
92
+
93
+ if (family.length === 1 && !family[0].hasExplicitVersionSelector()) {
94
+ return Result.ok(family[0]);
95
+ }
96
+
97
+ const versionDetails = [
98
+ params.kind,
99
+ params.gateEngineVersion !== undefined
100
+ ? `gateEngineVersion=${params.gateEngineVersion}`
101
+ : null,
102
+ params.computeEngineVersion !== undefined
103
+ ? `computeEngineVersion=${params.computeEngineVersion}`
104
+ : null,
105
+ params.payloadSchemaVersion !== undefined
106
+ ? `payloadSchemaVersion=${params.payloadSchemaVersion}`
107
+ : null,
108
+ ]
109
+ .filter((part): part is string => part !== null)
110
+ .join(", ");
111
+
112
+ return Result.err(
113
+ `Policy variant not found in catalog: "${params.key}" (${versionDetails})`,
114
+ );
86
115
  }
87
116
 
88
- const exactMatch = family.find((entry) => entry.matchesVersion(params));
89
- if (exactMatch) {
90
- return Result.ok(exactMatch);
117
+ list(): readonly PolicyCatalogEntry[] {
118
+ return Array.from(this.versionedEntries.values());
91
119
  }
92
120
 
93
- if (family.length === 1 && !family[0].hasExplicitVersionSelector()) {
94
- return Result.ok(family[0]);
121
+ has(key: string): boolean {
122
+ return this.entriesByKey.has(key);
95
123
  }
96
-
97
- const versionDetails = [
98
- params.kind,
99
- params.gateEngineVersion !== undefined
100
- ? `gateEngineVersion=${params.gateEngineVersion}`
101
- : null,
102
- params.computeEngineVersion !== undefined
103
- ? `computeEngineVersion=${params.computeEngineVersion}`
104
- : null,
105
- params.payloadSchemaVersion !== undefined
106
- ? `payloadSchemaVersion=${params.payloadSchemaVersion}`
107
- : null,
108
- ]
109
- .filter((part): part is string => part !== null)
110
- .join(", ");
111
-
112
- return Result.err(
113
- `Policy variant not found in catalog: "${params.key}" (${versionDetails})`,
114
- );
115
- }
116
-
117
- list(): readonly PolicyCatalogEntry[] {
118
- return Array.from(this.versionedEntries.values());
119
- }
120
-
121
- has(key: string): boolean {
122
- return this.entriesByKey.has(key);
123
- }
124
124
  }
@@ -13,66 +13,66 @@ const SEGMENT_PATTERN = /^[a-z][a-z0-9_]*$/;
13
13
  const MAX_POLICY_KEY_LENGTH = 255;
14
14
 
15
15
  export class PolicyKey {
16
- public readonly module: string;
17
- public readonly area: string;
18
- public readonly name: string;
16
+ public readonly module: string;
17
+ public readonly area: string;
18
+ public readonly name: string;
19
19
 
20
- private constructor(module: string, area: string, name: string) {
21
- this.module = module;
22
- this.area = area;
23
- this.name = name;
24
- Object.freeze(this);
25
- }
26
-
27
- static parse(raw: string): Result<PolicyKey, string> {
28
- if (!raw || typeof raw !== "string") {
29
- return Result.err("PolicyKey cannot be empty");
20
+ private constructor(module: string, area: string, name: string) {
21
+ this.module = module;
22
+ this.area = area;
23
+ this.name = name;
24
+ Object.freeze(this);
30
25
  }
31
26
 
32
- if (raw.length > MAX_POLICY_KEY_LENGTH) {
33
- return Result.err(
34
- `PolicyKey cannot exceed ${MAX_POLICY_KEY_LENGTH} characters, got ${raw.length}`,
35
- );
36
- }
27
+ static parse(raw: string): Result<PolicyKey, string> {
28
+ if (!raw || typeof raw !== "string") {
29
+ return Result.err("PolicyKey cannot be empty");
30
+ }
37
31
 
38
- const segments = raw.split(".");
39
- if (segments.length !== 3) {
40
- return Result.err(
41
- `PolicyKey must have exactly 3 segments (module.area.name), got ${segments.length}: "${raw}"`,
42
- );
43
- }
32
+ if (raw.length > MAX_POLICY_KEY_LENGTH) {
33
+ return Result.err(
34
+ `PolicyKey cannot exceed ${MAX_POLICY_KEY_LENGTH} characters, got ${raw.length}`,
35
+ );
36
+ }
44
37
 
45
- const [rawModule, rawArea, name] = segments;
38
+ const segments = raw.split(".");
39
+ if (segments.length !== 3) {
40
+ return Result.err(
41
+ `PolicyKey must have exactly 3 segments (module.area.name), got ${segments.length}: "${raw}"`,
42
+ );
43
+ }
46
44
 
47
- if (!SEGMENT_PATTERN.test(rawModule)) {
48
- return Result.err(
49
- `PolicyKey segment "module" is invalid: "${rawModule}". ` +
50
- "Must start with a lowercase letter and contain only [a-z0-9_].",
51
- );
52
- }
45
+ const [rawModule, rawArea, name] = segments;
53
46
 
54
- if (!SEGMENT_PATTERN.test(rawArea)) {
55
- return Result.err(
56
- `PolicyKey segment "area" is invalid: "${rawArea}". ` +
57
- "Must start with a lowercase letter and contain only [a-z0-9_].",
58
- );
59
- }
47
+ if (!SEGMENT_PATTERN.test(rawModule)) {
48
+ return Result.err(
49
+ `PolicyKey segment "module" is invalid: "${rawModule}". ` +
50
+ "Must start with a lowercase letter and contain only [a-z0-9_].",
51
+ );
52
+ }
60
53
 
61
- if (!SEGMENT_PATTERN.test(name)) {
62
- return Result.err(
63
- `PolicyKey segment "name" is invalid: "${name}". ` +
64
- "Must start with a lowercase letter and contain only [a-z0-9_].",
65
- );
66
- }
54
+ if (!SEGMENT_PATTERN.test(rawArea)) {
55
+ return Result.err(
56
+ `PolicyKey segment "area" is invalid: "${rawArea}". ` +
57
+ "Must start with a lowercase letter and contain only [a-z0-9_].",
58
+ );
59
+ }
67
60
 
68
- return Result.ok(new PolicyKey(rawModule, rawArea, name));
69
- }
61
+ if (!SEGMENT_PATTERN.test(name)) {
62
+ return Result.err(
63
+ `PolicyKey segment "name" is invalid: "${name}". ` +
64
+ "Must start with a lowercase letter and contain only [a-z0-9_].",
65
+ );
66
+ }
70
67
 
71
- toString(): string {
72
- return `${this.module}.${this.area}.${this.name}`;
73
- }
68
+ return Result.ok(new PolicyKey(rawModule, rawArea, name));
69
+ }
74
70
 
75
- equals(other: PolicyKey): boolean {
76
- return this.toString() === other.toString();
77
- }
71
+ toString(): string {
72
+ return `${this.module}.${this.area}.${this.name}`;
73
+ }
74
+
75
+ equals(other: PolicyKey): boolean {
76
+ return this.toString() === other.toString();
77
+ }
78
78
  }