@highflame/policy 2.0.1 → 2.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 (47) hide show
  1. package/dist/annotations.d.ts +127 -0
  2. package/dist/annotations.d.ts.map +1 -0
  3. package/dist/annotations.js +175 -0
  4. package/dist/annotations.js.map +1 -0
  5. package/dist/builder.d.ts +114 -25
  6. package/dist/builder.d.ts.map +1 -1
  7. package/dist/builder.js +295 -113
  8. package/dist/builder.js.map +1 -1
  9. package/dist/entity-metadata-types.gen.d.ts +17 -0
  10. package/dist/entity-metadata-types.gen.d.ts.map +1 -0
  11. package/dist/entity-metadata-types.gen.js +3 -0
  12. package/dist/entity-metadata-types.gen.js.map +1 -0
  13. package/dist/index.d.ts +5 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +5 -1
  16. package/dist/index.js.map +1 -1
  17. package/dist/overwatch-entities.gen.d.ts +12 -0
  18. package/dist/overwatch-entities.gen.d.ts.map +1 -0
  19. package/dist/overwatch-entities.gen.js +38 -0
  20. package/dist/overwatch-entities.gen.js.map +1 -0
  21. package/dist/palisade-entities.gen.d.ts +12 -0
  22. package/dist/palisade-entities.gen.d.ts.map +1 -0
  23. package/dist/palisade-entities.gen.js +46 -0
  24. package/dist/palisade-entities.gen.js.map +1 -0
  25. package/dist/parser.d.ts +1 -1
  26. package/dist/parser.d.ts.map +1 -1
  27. package/dist/parser.js +18 -11
  28. package/dist/parser.js.map +1 -1
  29. package/dist/parser.test.js +2 -2
  30. package/dist/parser.test.js.map +1 -1
  31. package/dist/studio-ui.test.js +526 -1
  32. package/dist/studio-ui.test.js.map +1 -1
  33. package/dist/types.d.ts +5 -1
  34. package/dist/types.d.ts.map +1 -1
  35. package/dist/types.js +6 -1
  36. package/dist/types.js.map +1 -1
  37. package/package.json +1 -1
  38. package/src/annotations.ts +243 -0
  39. package/src/builder.ts +386 -127
  40. package/src/entity-metadata-types.gen.ts +19 -0
  41. package/src/index.ts +13 -1
  42. package/src/overwatch-entities.gen.ts +41 -0
  43. package/src/palisade-entities.gen.ts +49 -0
  44. package/src/parser.test.ts +2 -2
  45. package/src/parser.ts +20 -12
  46. package/src/studio-ui.test.ts +606 -0
  47. package/src/types.ts +15 -1
@@ -0,0 +1,49 @@
1
+ // Code generated by highflame-policy-codegen. DO NOT EDIT.
2
+ // Source: schemas/palisade/schema.cedarschema
3
+
4
+ import type { ServiceEntityMetadata, ActionEntityMetadata } from './entity-metadata-types.gen.js';
5
+
6
+ /**
7
+ * Palisade entity metadata for UI components.
8
+ * Extracted from Cedar schema appliesTo blocks.
9
+ */
10
+ export const PALISADE_ENTITIES: ServiceEntityMetadata = {
11
+ principals: ['Scanner'],
12
+ resources: ['Artifact', 'Package'],
13
+ actions: ['deploy_model', 'load_model', 'quarantine_artifact', 'scan_artifact', 'scan_package', 'validate_integrity', 'validate_provenance'],
14
+ } as const;
15
+
16
+ /**
17
+ * Per-action entity mapping for Palisade.
18
+ * Maps action names to their valid principals and resources.
19
+ */
20
+ export const PALISADE_ACTION_ENTITIES: Record<string, ActionEntityMetadata> = {
21
+ 'deploy_model': {
22
+ principals: ['Scanner'],
23
+ resources: ['Artifact'],
24
+ },
25
+ 'load_model': {
26
+ principals: ['Scanner'],
27
+ resources: ['Artifact'],
28
+ },
29
+ 'quarantine_artifact': {
30
+ principals: ['Scanner'],
31
+ resources: ['Artifact'],
32
+ },
33
+ 'scan_artifact': {
34
+ principals: ['Scanner'],
35
+ resources: ['Artifact'],
36
+ },
37
+ 'scan_package': {
38
+ principals: ['Scanner'],
39
+ resources: ['Package'],
40
+ },
41
+ 'validate_integrity': {
42
+ principals: ['Scanner'],
43
+ resources: ['Artifact'],
44
+ },
45
+ 'validate_provenance': {
46
+ principals: ['Scanner'],
47
+ resources: ['Artifact'],
48
+ },
49
+ } as const;
@@ -26,7 +26,7 @@ describe('parseCedarToRules', () => {
26
26
  expect(result.unstructured).toHaveLength(0);
27
27
 
28
28
  const rule = result.rules[0];
29
- expect(rule.id).toBe('allow-read-files');
29
+ expect(rule.annotations.id).toBe('allow-read-files');
30
30
  expect(rule.effect).toBe('permit');
31
31
  expect(rule.principal).toEqual({ type: 'User' });
32
32
  expect(rule.action).toBe('read_file');
@@ -53,7 +53,7 @@ describe('parseCedarToRules', () => {
53
53
  expect(result.rules).toHaveLength(1);
54
54
 
55
55
  const rule = result.rules[0];
56
- expect(rule.id).toBe('block-high-risk');
56
+ expect(rule.annotations.id).toBe('block-high-risk');
57
57
  expect(rule.effect).toBe('forbid');
58
58
  expect(rule.action).toBe('execute_tool');
59
59
 
package/src/parser.ts CHANGED
@@ -6,11 +6,12 @@
6
6
  *
7
7
  * Architecture:
8
8
  * 1. Cedar text → Cedar JSON (via cedar-wasm policyToJson)
9
- * 2. Cedar JSON → PolicyRule (simple JSON mapping)
9
+ * 2. Cedar JSON → PolicyRule (simple JSON mapping with annotation extraction)
10
10
  */
11
11
 
12
12
  import * as cedar from "@cedar-policy/cedar-wasm/nodejs";
13
13
  import type { PolicyRule, PolicyCondition, PolicyEntity, PolicyEffect, ConditionOperator } from "./builder.js";
14
+ import { parseAnnotations, generateRuleId } from "./annotations.js";
14
15
  import { ParserError, ErrorCodes } from "./errors.js";
15
16
 
16
17
  /**
@@ -145,10 +146,11 @@ export function parseCedarToRules(cedarText: string): ParseResult {
145
146
  // Check for duplicate policy IDs and add warnings
146
147
  const idOccurrences = new Map<string, number[]>();
147
148
  result.rules.forEach((rule, idx) => {
148
- if (rule.id) {
149
- const indices = idOccurrences.get(rule.id) || [];
149
+ const ruleId = rule.annotations.id;
150
+ if (ruleId) {
151
+ const indices = idOccurrences.get(ruleId) || [];
150
152
  indices.push(idx);
151
- idOccurrences.set(rule.id, indices);
153
+ idOccurrences.set(ruleId, indices);
152
154
  }
153
155
  });
154
156
  for (const [id, indices] of idOccurrences) {
@@ -164,7 +166,7 @@ export function parseCedarToRules(cedarText: string): ParseResult {
164
166
 
165
167
  /**
166
168
  * Convert Cedar JSON policy to PolicyRule.
167
- * This is pure JSON mapping - no parsing logic.
169
+ * This is pure JSON mapping - uses parseAnnotations to extract structured annotations.
168
170
  */
169
171
  function cedarJsonToRule(
170
172
  policy: CedarPolicyJSON,
@@ -181,9 +183,20 @@ function cedarJsonToRule(
181
183
  }
182
184
 
183
185
  try {
186
+ // Parse annotations using the shared utility
187
+ const { annotations, customAnnotations } = parseAnnotations(policy.annotations);
188
+
189
+ // Ensure id and name have sensible defaults
190
+ if (!annotations.id) {
191
+ annotations.id = policyId || generateRuleId();
192
+ }
193
+ if (!annotations.name) {
194
+ annotations.name = annotations.id;
195
+ }
196
+
184
197
  const rule: PolicyRule = {
185
- id: policy.annotations?.id || policyId,
186
- name: policy.annotations?.name || policy.annotations?.id || policyId,
198
+ annotations,
199
+ customAnnotations,
187
200
  effect: policy.effect as PolicyEffect,
188
201
  principal: mapScopeToEntity(policy.principal, "principal"),
189
202
  action: mapActionScope(policy.action),
@@ -193,11 +206,6 @@ function cedarJsonToRule(
193
206
  order: index,
194
207
  };
195
208
 
196
- // Map description from annotations
197
- if (policy.annotations?.description) {
198
- rule.description = policy.annotations.description;
199
- }
200
-
201
209
  // Map conditions
202
210
  const { conditions, rawCondition } = mapConditions(policy.conditions);
203
211
  rule.conditions = conditions;