@highflame/policy 1.1.3 → 1.2.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.
@@ -0,0 +1,190 @@
1
+ /**
2
+ * Engine unit tests
3
+ *
4
+ * Tests the PolicyEngine evaluate() function.
5
+ * These tests are consistent across Go, TypeScript, and Python SDKs.
6
+ */
7
+ import { describe, it, expect, beforeEach } from 'vitest';
8
+ import { PolicyEngine, EntityType, ActionType, InputValidationError, DEFAULT_LIMITS, } from './index.js';
9
+ describe('PolicyEngine', () => {
10
+ let engine;
11
+ const permitAllPolicy = `
12
+ permit(principal, action, resource);
13
+ `;
14
+ const denyAllPolicy = `
15
+ forbid(principal, action, resource);
16
+ `;
17
+ // Simple context-based policy without action constraint for testing context evaluation
18
+ const contextBasedPolicy = `
19
+ @id("allow-production")
20
+ permit(
21
+ principal,
22
+ action,
23
+ resource
24
+ )
25
+ when { context.environment == "production" };
26
+
27
+ @id("deny-all")
28
+ forbid(principal, action, resource);
29
+ `;
30
+ beforeEach(() => {
31
+ engine = new PolicyEngine();
32
+ });
33
+ describe('basic evaluation', () => {
34
+ it('should allow when permit policy matches', () => {
35
+ engine.loadPolicies(permitAllPolicy);
36
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test-scanner', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors');
37
+ expect(decision.effect).toBe('Allow');
38
+ });
39
+ it('should deny when forbid policy matches', () => {
40
+ engine.loadPolicies(denyAllPolicy);
41
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test-scanner', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors');
42
+ expect(decision.effect).toBe('Deny');
43
+ });
44
+ it('should deny when no policies match (default deny)', () => {
45
+ engine.loadPolicies(''); // No policies
46
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test-scanner', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors');
47
+ expect(decision.effect).toBe('Deny');
48
+ });
49
+ });
50
+ describe('context-based evaluation', () => {
51
+ beforeEach(() => {
52
+ engine.loadPolicies(contextBasedPolicy);
53
+ });
54
+ it('should allow when context matches permit condition', () => {
55
+ // Use simple permit policy to test context evaluation in isolation
56
+ const simplePermitPolicy = `
57
+ permit(principal, action, resource)
58
+ when { context.environment == "production" };
59
+ `;
60
+ const testEngine = new PolicyEngine();
61
+ testEngine.loadPolicies(simplePermitPolicy);
62
+ const decision = testEngine.evaluateSimple(EntityType.Scanner, 'palisade', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { environment: 'production' });
63
+ expect(decision.effect).toBe('Allow');
64
+ });
65
+ it('should deny when context does not match permit condition', () => {
66
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'palisade', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { environment: 'development' });
67
+ expect(decision.effect).toBe('Deny');
68
+ });
69
+ it('should deny when context is missing required field', () => {
70
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'palisade', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', {} // Missing environment
71
+ );
72
+ expect(decision.effect).toBe('Deny');
73
+ });
74
+ });
75
+ describe('input validation', () => {
76
+ beforeEach(() => {
77
+ engine.loadPolicies(permitAllPolicy);
78
+ });
79
+ it('should accept valid context', () => {
80
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', {
81
+ environment: 'production',
82
+ severity: 'HIGH',
83
+ count: 42,
84
+ enabled: true,
85
+ });
86
+ expect(decision.effect).toBe('Allow');
87
+ });
88
+ it('should reject context with too many keys', () => {
89
+ const engine = new PolicyEngine({ limits: { maxContextKeys: 5 } });
90
+ engine.loadPolicies(permitAllPolicy);
91
+ const bigContext = {};
92
+ for (let i = 0; i < 10; i++) {
93
+ bigContext[`key${i}`] = 'value';
94
+ }
95
+ expect(() => {
96
+ engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', bigContext);
97
+ }).toThrow(InputValidationError);
98
+ });
99
+ it('should reject context with too long strings', () => {
100
+ const engine = new PolicyEngine({ limits: { maxStringLength: 100 } });
101
+ engine.loadPolicies(permitAllPolicy);
102
+ const longString = 'x'.repeat(200);
103
+ expect(() => {
104
+ engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { value: longString });
105
+ }).toThrow(InputValidationError);
106
+ });
107
+ it('should reject deeply nested context', () => {
108
+ const engine = new PolicyEngine({ limits: { maxNestingDepth: 3 } });
109
+ engine.loadPolicies(permitAllPolicy);
110
+ const deepContext = {
111
+ level1: {
112
+ level2: {
113
+ level3: {
114
+ level4: {
115
+ level5: 'too deep',
116
+ },
117
+ },
118
+ },
119
+ },
120
+ };
121
+ expect(() => {
122
+ engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', deepContext);
123
+ }).toThrow(InputValidationError);
124
+ });
125
+ it('should allow skipping validation', () => {
126
+ const engine = new PolicyEngine({
127
+ skipValidation: true,
128
+ limits: { maxContextKeys: 1 },
129
+ });
130
+ engine.loadPolicies(permitAllPolicy);
131
+ // This would normally fail validation
132
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { key1: 'value1', key2: 'value2', key3: 'value3' });
133
+ expect(decision.effect).toBe('Allow');
134
+ });
135
+ });
136
+ describe('complex context types', () => {
137
+ beforeEach(() => {
138
+ engine.loadPolicies(permitAllPolicy);
139
+ });
140
+ it('should handle array context values', () => {
141
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { threats: ['malware', 'backdoor', 'injection'] });
142
+ expect(decision.effect).toBe('Allow');
143
+ });
144
+ it('should handle nested object context', () => {
145
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', {
146
+ metadata: {
147
+ format: 'safetensors',
148
+ size: 1024,
149
+ },
150
+ });
151
+ expect(decision.effect).toBe('Allow');
152
+ });
153
+ it('should handle empty context', () => {
154
+ // Cedar doesn't have null values - this tests that empty context works
155
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', {});
156
+ expect(decision.effect).toBe('Allow');
157
+ });
158
+ it('should handle boolean context values', () => {
159
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { is_signed: true, is_malicious: false });
160
+ expect(decision.effect).toBe('Allow');
161
+ });
162
+ it('should handle integer context values', () => {
163
+ // Cedar uses Long type for numbers (integers only, no floats)
164
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors', { severity_score: 7, count: 100 });
165
+ expect(decision.effect).toBe('Allow');
166
+ });
167
+ });
168
+ describe('error handling', () => {
169
+ it('should handle invalid policy syntax gracefully', () => {
170
+ const invalidPolicy = `permit(principal, action, resource`; // Missing closing paren
171
+ expect(() => {
172
+ engine.loadPolicies(invalidPolicy);
173
+ engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors');
174
+ }).not.toThrow();
175
+ // Should return deny with reason
176
+ engine.loadPolicies(invalidPolicy);
177
+ const decision = engine.evaluateSimple(EntityType.Scanner, 'test', ActionType.ScanArtifact, EntityType.Artifact, '/model.safetensors');
178
+ expect(decision.effect).toBe('Deny');
179
+ });
180
+ });
181
+ describe('DEFAULT_LIMITS', () => {
182
+ it('should have consistent default values', () => {
183
+ expect(DEFAULT_LIMITS.maxContextKeys).toBe(100);
184
+ expect(DEFAULT_LIMITS.maxStringLength).toBe(1_000_000);
185
+ expect(DEFAULT_LIMITS.maxNestingDepth).toBe(10);
186
+ expect(DEFAULT_LIMITS.maxContextSizeBytes).toBe(10_000_000);
187
+ });
188
+ });
189
+ });
190
+ //# sourceMappingURL=engine.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"engine.test.js","sourceRoot":"","sources":["../src/engine.test.ts"],"names":[],"mappings":"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"}
@@ -4,8 +4,12 @@
4
4
  export declare const EntityType: {
5
5
  readonly Agent: "Agent";
6
6
  readonly Artifact: "Artifact";
7
+ readonly ExternalAPI: "ExternalAPI";
7
8
  readonly FilePath: "FilePath";
9
+ readonly GitBranch: "GitBranch";
8
10
  readonly HttpEndpoint: "HttpEndpoint";
11
+ readonly Memory: "Memory";
12
+ readonly Model: "Model";
9
13
  readonly Package: "Package";
10
14
  readonly Repository: "Repository";
11
15
  readonly Resource: "Resource";
@@ -1 +1 @@
1
- {"version":3,"file":"entities.gen.d.ts","sourceRoot":"","sources":["../src/entities.gen.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;CAcb,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACnB,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAMxG"}
1
+ {"version":3,"file":"entities.gen.d.ts","sourceRoot":"","sources":["../src/entities.gen.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;CAkBb,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,UAAU,CAAC,CAAC,MAAM,OAAO,UAAU,CAAC,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,EAAE,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,MAAM;IACnB,GAAG,EAAE,SAAS,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,SAAS,EAAE,CAAC;CACzB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,SAAS,CAE7E;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAMxG"}
@@ -6,8 +6,12 @@
6
6
  export const EntityType = {
7
7
  Agent: 'Agent',
8
8
  Artifact: 'Artifact',
9
+ ExternalAPI: 'ExternalAPI',
9
10
  FilePath: 'FilePath',
11
+ GitBranch: 'GitBranch',
10
12
  HttpEndpoint: 'HttpEndpoint',
13
+ Memory: 'Memory',
14
+ Model: 'Model',
11
15
  Package: 'Package',
12
16
  Repository: 'Repository',
13
17
  Resource: 'Resource',
@@ -1 +1 @@
1
- {"version":3,"file":"entities.gen.js","sourceRoot":"","sources":["../src/entities.gen.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,uCAAuC;AAEvC;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,UAAU;IACpB,YAAY,EAAE,cAAc;IAC5B,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,YAAY,EAAE,cAAc;IAC5B,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;CACN,CAAC;AAqBX;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAyB,EAAE,EAAU;IAC9D,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAyB,EAAE,EAAU,EAAE,KAA+B;IAC5F,OAAO;QACH,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,KAAK,EAAE,KAAK,IAAI,EAAE;QAClB,OAAO,EAAE,EAAE;KACd,CAAC;AACN,CAAC"}
1
+ {"version":3,"file":"entities.gen.js","sourceRoot":"","sources":["../src/entities.gen.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAC3D,uCAAuC;AAEvC;;GAEG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,KAAK,EAAE,OAAO;IACd,QAAQ,EAAE,UAAU;IACpB,WAAW,EAAE,aAAa;IAC1B,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,YAAY,EAAE,cAAc;IAC5B,MAAM,EAAE,QAAQ;IAChB,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,QAAQ,EAAE,UAAU;IACpB,YAAY,EAAE,cAAc;IAC5B,OAAO,EAAE,SAAS;IAClB,MAAM,EAAE,QAAQ;IAChB,OAAO,EAAE,SAAS;IAClB,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;CACN,CAAC;AAqBX;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,IAAyB,EAAE,EAAU;IAC9D,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;AACxB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,IAAyB,EAAE,EAAU,EAAE,KAA+B;IAC5F,OAAO;QACH,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;QACjB,KAAK,EAAE,KAAK,IAAI,EAAE;QAClB,OAAO,EAAE,EAAE;KACd,CAAC;AACN,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Cedar Policy Parser
3
+ *
4
+ * Converts Cedar policy text to structured PolicyRule format using the
5
+ * official Cedar engine (cedar-wasm) for parsing.
6
+ *
7
+ * Architecture:
8
+ * 1. Cedar text → Cedar JSON (via cedar-wasm policyToJson)
9
+ * 2. Cedar JSON → PolicyRule (simple JSON mapping)
10
+ */
11
+ import type { PolicyRule } from "./builder.js";
12
+ /**
13
+ * Result of parsing Cedar policies
14
+ */
15
+ export interface ParseResult {
16
+ /** Policies successfully converted to PolicyRule format */
17
+ rules: PolicyRule[];
18
+ /** Policies that couldn't be fully represented as PolicyRule (raw Cedar text) */
19
+ unstructured: string[];
20
+ /** Any parsing errors encountered */
21
+ errors: string[];
22
+ }
23
+ /**
24
+ * Parse Cedar policy text and convert to PolicyRule format.
25
+ *
26
+ * Uses the official cedar-wasm engine for parsing, ensuring correctness.
27
+ * Policies with features that can't be represented as PolicyRule (e.g.,
28
+ * unless clauses, complex expressions) are returned in the unstructured array.
29
+ *
30
+ * @param cedarText - Cedar policy text to parse
31
+ * @returns ParseResult with structured rules, unstructured policies, and errors
32
+ */
33
+ export declare function parseCedarToRules(cedarText: string): ParseResult;
34
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAkE,MAAM,cAAc,CAAC;AAE/G;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,2DAA2D;IAC3D,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,iFAAiF;IACjF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,qCAAqC;IACrC,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAmDD;;;;;;;;;GASG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,CA2DhE"}
package/dist/parser.js ADDED
@@ -0,0 +1,348 @@
1
+ /**
2
+ * Cedar Policy Parser
3
+ *
4
+ * Converts Cedar policy text to structured PolicyRule format using the
5
+ * official Cedar engine (cedar-wasm) for parsing.
6
+ *
7
+ * Architecture:
8
+ * 1. Cedar text → Cedar JSON (via cedar-wasm policyToJson)
9
+ * 2. Cedar JSON → PolicyRule (simple JSON mapping)
10
+ */
11
+ import * as cedar from "@cedar-policy/cedar-wasm/nodejs";
12
+ /**
13
+ * Normalize entity reference to simple { type, id } format
14
+ */
15
+ function normalizeEntityRef(ref) {
16
+ if ("__entity" in ref) {
17
+ return ref.__entity;
18
+ }
19
+ return ref;
20
+ }
21
+ /**
22
+ * Parse Cedar policy text and convert to PolicyRule format.
23
+ *
24
+ * Uses the official cedar-wasm engine for parsing, ensuring correctness.
25
+ * Policies with features that can't be represented as PolicyRule (e.g.,
26
+ * unless clauses, complex expressions) are returned in the unstructured array.
27
+ *
28
+ * @param cedarText - Cedar policy text to parse
29
+ * @returns ParseResult with structured rules, unstructured policies, and errors
30
+ */
31
+ export function parseCedarToRules(cedarText) {
32
+ const result = {
33
+ rules: [],
34
+ unstructured: [],
35
+ errors: [],
36
+ };
37
+ try {
38
+ // Split the policy set into individual policies and templates
39
+ const partsResult = cedar.policySetTextToParts(cedarText);
40
+ if (partsResult.type === "failure") {
41
+ for (const error of partsResult.errors) {
42
+ result.errors.push(error.message);
43
+ }
44
+ return result;
45
+ }
46
+ // Process each policy
47
+ let index = 0;
48
+ for (const policyText of partsResult.policies) {
49
+ // Convert individual policy to JSON using cedar-wasm
50
+ const jsonResult = cedar.policyToJson(policyText);
51
+ if (jsonResult.type === "failure") {
52
+ for (const error of jsonResult.errors) {
53
+ result.errors.push(`Policy ${index}: ${error.message}`);
54
+ }
55
+ index++;
56
+ continue;
57
+ }
58
+ const policy = jsonResult.json;
59
+ const policyId = policy.annotations?.id || `policy${index}`;
60
+ const conversion = cedarJsonToRule(policy, policyId, index, policyText);
61
+ if (conversion.error) {
62
+ result.errors.push(`Policy ${policyId}: ${conversion.error}`);
63
+ }
64
+ if (conversion.rule) {
65
+ result.rules.push(conversion.rule);
66
+ }
67
+ else if (conversion.raw) {
68
+ result.unstructured.push(conversion.raw);
69
+ }
70
+ index++;
71
+ }
72
+ // Templates can't be represented as PolicyRule
73
+ for (const templateText of partsResult.policy_templates) {
74
+ result.unstructured.push(templateText);
75
+ }
76
+ }
77
+ catch (e) {
78
+ result.errors.push(`Parse error: ${e instanceof Error ? e.message : String(e)}`);
79
+ }
80
+ return result;
81
+ }
82
+ /**
83
+ * Convert Cedar JSON policy to PolicyRule.
84
+ * This is pure JSON mapping - no parsing logic.
85
+ */
86
+ function cedarJsonToRule(policy, policyId, index, originalText) {
87
+ // Check if this policy can be represented as PolicyRule
88
+ if (!canRepresentAsRule(policy)) {
89
+ // Return original text if available, otherwise convert back from JSON
90
+ const raw = originalText || getRawCedar(policyId, policy);
91
+ return { raw };
92
+ }
93
+ const rule = {
94
+ id: policy.annotations?.id || policyId,
95
+ name: policy.annotations?.name || policy.annotations?.id || policyId,
96
+ effect: policy.effect,
97
+ principal: mapScopeToEntity(policy.principal),
98
+ action: mapActionScope(policy.action),
99
+ resource: mapScopeToEntity(policy.resource),
100
+ conditions: [],
101
+ enabled: true,
102
+ order: index,
103
+ };
104
+ // Map description from annotations
105
+ if (policy.annotations?.description) {
106
+ rule.description = policy.annotations.description;
107
+ }
108
+ // Map conditions
109
+ const { conditions, rawCondition } = mapConditions(policy.conditions);
110
+ rule.conditions = conditions;
111
+ if (rawCondition) {
112
+ rule.rawCondition = rawCondition;
113
+ }
114
+ return { rule };
115
+ }
116
+ /**
117
+ * Check if a Cedar policy can be represented as PolicyRule
118
+ */
119
+ function canRepresentAsRule(policy) {
120
+ // Unless clauses can't be represented
121
+ for (const cond of policy.conditions) {
122
+ if (cond.kind === "unless") {
123
+ return false;
124
+ }
125
+ }
126
+ // Template slots can't be represented
127
+ if (hasSlot(policy.principal) || hasSlot(policy.resource)) {
128
+ return false;
129
+ }
130
+ // Multiple entity "in" constraints are complex
131
+ const action = policy.action;
132
+ if (action.op === "in" && "entities" in action && action.entities.length > 1) {
133
+ // Multiple actions are OK, we handle those
134
+ }
135
+ return true;
136
+ }
137
+ /**
138
+ * Check if a scope constraint uses a slot (template)
139
+ */
140
+ function hasSlot(scope) {
141
+ if (scope.op === "All" || scope.op === "is") {
142
+ return false;
143
+ }
144
+ return "slot" in scope;
145
+ }
146
+ /**
147
+ * Get raw Cedar text for a policy that can't be represented as PolicyRule
148
+ */
149
+ function getRawCedar(policyId, policy) {
150
+ try {
151
+ // policyToText accepts Policy which is string | PolicyJson
152
+ const textResult = cedar.policyToText(policy);
153
+ if (textResult.type === "success") {
154
+ return textResult.text;
155
+ }
156
+ }
157
+ catch {
158
+ // Ignore conversion errors
159
+ }
160
+ return `// Complex policy: ${policyId}`;
161
+ }
162
+ /**
163
+ * Map Cedar scope constraint to PolicyEntity
164
+ */
165
+ function mapScopeToEntity(scope) {
166
+ if (scope.op === "All") {
167
+ return null;
168
+ }
169
+ if (scope.op === "==") {
170
+ if ("entity" in scope) {
171
+ const entity = normalizeEntityRef(scope.entity);
172
+ return { type: entity.type, id: entity.id };
173
+ }
174
+ // Slot - can't represent
175
+ return null;
176
+ }
177
+ if (scope.op === "is") {
178
+ // Type constraint
179
+ return { type: scope.entity_type };
180
+ }
181
+ if (scope.op === "in") {
182
+ if ("entity" in scope) {
183
+ const entity = normalizeEntityRef(scope.entity);
184
+ return { type: entity.type, id: entity.id };
185
+ }
186
+ // Slot - can't represent
187
+ return null;
188
+ }
189
+ return null;
190
+ }
191
+ /**
192
+ * Map action scope to action string(s)
193
+ */
194
+ function mapActionScope(scope) {
195
+ if (scope.op === "All") {
196
+ return "*";
197
+ }
198
+ if (scope.op === "==") {
199
+ const entity = normalizeEntityRef(scope.entity);
200
+ return entity.id;
201
+ }
202
+ if (scope.op === "in") {
203
+ if ("entities" in scope) {
204
+ const actions = scope.entities.map(e => normalizeEntityRef(e).id);
205
+ return actions.length === 1 ? actions[0] : actions;
206
+ }
207
+ if ("entity" in scope) {
208
+ const entity = normalizeEntityRef(scope.entity);
209
+ return entity.id;
210
+ }
211
+ }
212
+ return "";
213
+ }
214
+ /**
215
+ * Map Cedar conditions to PolicyCondition array
216
+ */
217
+ function mapConditions(conditions) {
218
+ const result = [];
219
+ const rawParts = [];
220
+ for (const cond of conditions) {
221
+ if (cond.kind !== "when") {
222
+ continue;
223
+ }
224
+ const parsed = mapConditionBody(cond.body);
225
+ if (parsed.condition) {
226
+ result.push(parsed.condition);
227
+ }
228
+ else if (parsed.raw) {
229
+ rawParts.push(parsed.raw);
230
+ }
231
+ }
232
+ return {
233
+ conditions: result,
234
+ rawCondition: rawParts.length > 0 ? rawParts.join(" && ") : undefined,
235
+ };
236
+ }
237
+ /**
238
+ * Map a Cedar expression body to PolicyCondition
239
+ *
240
+ * Cedar JSON expressions use nested objects with operator keys.
241
+ * Comparison format: { "==": { left: { ".": { left: { Var: "context" }, attr: "field" } }, right: { Value: "x" } } }
242
+ */
243
+ function mapConditionBody(body) {
244
+ const expr = body;
245
+ // Check comparison operators
246
+ for (const op of ["==", "!=", "<", "<=", ">", ">="]) {
247
+ const comparison = expr[op];
248
+ if (comparison) {
249
+ const condition = mapComparison(op, comparison);
250
+ if (condition)
251
+ return { condition };
252
+ }
253
+ }
254
+ // Check contains
255
+ if (expr.contains) {
256
+ const condition = mapContains(expr.contains);
257
+ if (condition)
258
+ return { condition };
259
+ }
260
+ // Check like
261
+ if (expr.like) {
262
+ const condition = mapLike(expr.like);
263
+ if (condition)
264
+ return { condition };
265
+ }
266
+ // Can't map - return as raw JSON
267
+ return { raw: JSON.stringify(body) };
268
+ }
269
+ function mapComparison(op, args) {
270
+ const field = extractContextField(args.left);
271
+ if (!field)
272
+ return null;
273
+ const value = extractLiteralValue(args.right);
274
+ if (value === undefined)
275
+ return null;
276
+ const operator = mapOperator(op);
277
+ if (!operator)
278
+ return null;
279
+ return { field, operator, value };
280
+ }
281
+ function mapContains(args) {
282
+ const field = extractContextField(args.left);
283
+ if (!field)
284
+ return null;
285
+ const value = extractLiteralValue(args.right);
286
+ if (value === undefined)
287
+ return null;
288
+ return { field, operator: "contains", value };
289
+ }
290
+ function mapLike(args) {
291
+ const field = extractContextField(args.left);
292
+ if (!field)
293
+ return null;
294
+ // Convert pattern to string (e.g., ["Wildcard", { Literal: "foo" }, "Wildcard"] -> "*foo*")
295
+ const patternStr = args.pattern.map(p => {
296
+ if (p === "Wildcard")
297
+ return "*";
298
+ if (typeof p === "object" && "Literal" in p)
299
+ return p.Literal;
300
+ return "";
301
+ }).join("");
302
+ return { field, operator: "like", value: patternStr };
303
+ }
304
+ /**
305
+ * Extract field name from context.field access pattern
306
+ * Pattern: { ".": { left: { Var: "context" }, attr: "field_name" } }
307
+ */
308
+ function extractContextField(expr) {
309
+ const dotAccess = expr["."];
310
+ if (!dotAccess)
311
+ return null;
312
+ // Check if accessing context variable
313
+ const leftExpr = dotAccess.left;
314
+ if (leftExpr.Var !== "context")
315
+ return null;
316
+ return dotAccess.attr;
317
+ }
318
+ /**
319
+ * Extract literal value from Cedar JSON
320
+ * Pattern: { Value: <literal> }
321
+ */
322
+ function extractLiteralValue(expr) {
323
+ if (!("Value" in expr))
324
+ return undefined;
325
+ const value = expr.Value;
326
+ if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
327
+ return value;
328
+ }
329
+ if (Array.isArray(value) && value.every(v => typeof v === "string")) {
330
+ return value;
331
+ }
332
+ return undefined;
333
+ }
334
+ /**
335
+ * Map Cedar operator to ConditionOperator
336
+ */
337
+ function mapOperator(cedarOp) {
338
+ const mapping = {
339
+ "==": "eq",
340
+ "!=": "neq",
341
+ "<": "lt",
342
+ "<=": "lte",
343
+ ">": "gt",
344
+ ">=": "gte",
345
+ };
346
+ return mapping[cedarOp] || null;
347
+ }
348
+ //# sourceMappingURL=parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Parser unit tests
3
+ *
4
+ * Tests the Cedar text → PolicyRule conversion using the official Cedar engine.
5
+ * These tests demonstrate how a client like highflame-authz would use the parser.
6
+ */
7
+ export {};
8
+ //# sourceMappingURL=parser.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.test.d.ts","sourceRoot":"","sources":["../src/parser.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}