@highflame/policy 1.2.1 → 2.0.1
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/README.md +219 -0
- package/_schemas/overwatch/context.json +433 -0
- package/_schemas/overwatch/schema.cedarschema +179 -0
- package/_schemas/palisade/context.json +325 -0
- package/_schemas/palisade/schema.cedarschema +168 -0
- package/dist/builder.d.ts +1 -2
- package/dist/builder.d.ts.map +1 -1
- package/dist/builder.js +16 -3
- package/dist/builder.js.map +1 -1
- package/dist/context.gen.d.ts +1 -94
- package/dist/context.gen.d.ts.map +1 -1
- package/dist/context.gen.js +1 -97
- package/dist/context.gen.js.map +1 -1
- package/dist/engine.d.ts +18 -18
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +44 -28
- package/dist/engine.js.map +1 -1
- package/dist/engine.test.js.map +1 -1
- package/dist/entities.gen.d.ts +1 -0
- package/dist/entities.gen.d.ts.map +1 -1
- package/dist/entities.gen.js +1 -0
- package/dist/entities.gen.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/overwatch-context.gen.d.ts +29 -0
- package/dist/overwatch-context.gen.d.ts.map +1 -0
- package/dist/overwatch-context.gen.js +30 -0
- package/dist/overwatch-context.gen.js.map +1 -0
- package/dist/palisade-context.gen.d.ts +25 -0
- package/dist/palisade-context.gen.d.ts.map +1 -0
- package/dist/palisade-context.gen.js +26 -0
- package/dist/palisade-context.gen.js.map +1 -0
- package/dist/schema.gen.d.ts +1 -1
- package/dist/schema.gen.d.ts.map +1 -1
- package/dist/schema.gen.js +60 -541
- package/dist/schema.gen.js.map +1 -1
- package/dist/schemas.d.ts +64 -0
- package/dist/schemas.d.ts.map +1 -0
- package/dist/schemas.js +70 -0
- package/dist/schemas.js.map +1 -0
- package/dist/schemas.test.d.ts +8 -0
- package/dist/schemas.test.d.ts.map +1 -0
- package/dist/schemas.test.js +377 -0
- package/dist/schemas.test.js.map +1 -0
- package/dist/service-schemas.gen.d.ts +48 -0
- package/dist/service-schemas.gen.d.ts.map +1 -0
- package/dist/service-schemas.gen.js +581 -0
- package/dist/service-schemas.gen.js.map +1 -0
- package/dist/studio-ui.test.d.ts +8 -0
- package/dist/studio-ui.test.d.ts.map +1 -0
- package/dist/studio-ui.test.js +165 -0
- package/dist/studio-ui.test.js.map +1 -0
- package/dist/types.d.ts +4 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -1
- package/package.json +9 -6
- package/src/builder.ts +18 -5
- package/src/context.gen.ts +0 -97
- package/src/engine.test.ts +0 -1
- package/src/engine.ts +62 -33
- package/src/entities.gen.ts +1 -0
- package/src/index.ts +17 -0
- package/src/overwatch-context.gen.ts +32 -0
- package/src/palisade-context.gen.ts +28 -0
- package/src/schema.gen.ts +60 -541
- package/src/schemas.test.ts +445 -0
- package/src/schemas.ts +91 -0
- package/src/service-schemas.gen.ts +608 -0
- package/src/studio-ui.test.ts +207 -0
- package/src/types.ts +17 -0
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service-specific Cedar schemas and context metadata
|
|
3
|
+
*
|
|
4
|
+
* This module provides access to service-specific Cedar schemas
|
|
5
|
+
* and their associated context metadata for UI builders.
|
|
6
|
+
*
|
|
7
|
+
* Schemas are bundled with the package and loaded at runtime. The schema
|
|
8
|
+
* files are copied from schemas/ to packages/typescript/_schemas/ during
|
|
9
|
+
* codegen (see Makefile). This ensures the package is self-contained and
|
|
10
|
+
* works correctly when installed from npm.
|
|
11
|
+
*
|
|
12
|
+
* Available Schemas:
|
|
13
|
+
* - Overwatch (Guardian): IDE security policies for LLM agents and tool calls
|
|
14
|
+
* - Palisade: ML supply chain security policies for artifact scanning
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { OVERWATCH_SCHEMA, OVERWATCH_CONTEXT } from '@highflame/policy/schemas';
|
|
19
|
+
* import { PolicyEngine } from '@highflame/policy';
|
|
20
|
+
*
|
|
21
|
+
* const engine = new PolicyEngine();
|
|
22
|
+
* engine.loadSchema(OVERWATCH_SCHEMA);
|
|
23
|
+
*
|
|
24
|
+
* // Parse context metadata for UI dropdowns
|
|
25
|
+
* const contextMeta = JSON.parse(OVERWATCH_CONTEXT);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export { OverwatchContextKey } from './overwatch-context.gen.js';
|
|
29
|
+
export { PalisadeContextKey } from './palisade-context.gen.js';
|
|
30
|
+
export type { OverwatchContextKey as OverwatchContextKeyType } from './overwatch-context.gen.js';
|
|
31
|
+
export type { PalisadeContextKey as PalisadeContextKeyType } from './palisade-context.gen.js';
|
|
32
|
+
/**
|
|
33
|
+
* Overwatch (Guardian) Cedar schema
|
|
34
|
+
*
|
|
35
|
+
* Full Cedar schema for IDE security, including:
|
|
36
|
+
* - Actions: process_prompt, call_tool, connect_server, read_file, write_file
|
|
37
|
+
* - Entities: User, Agent, LlmPrompt, Tool, Server, FilePath
|
|
38
|
+
* - 20+ context attributes for threat detection and workspace security
|
|
39
|
+
*/
|
|
40
|
+
export declare const OVERWATCH_SCHEMA: string;
|
|
41
|
+
/**
|
|
42
|
+
* Overwatch context metadata (JSON)
|
|
43
|
+
*
|
|
44
|
+
* Metadata describing available context attributes for each Overwatch action.
|
|
45
|
+
* Used by PolicyBuilder UI to generate context dropdowns with type information.
|
|
46
|
+
*/
|
|
47
|
+
export declare const OVERWATCH_CONTEXT: string;
|
|
48
|
+
/**
|
|
49
|
+
* Palisade Cedar schema
|
|
50
|
+
*
|
|
51
|
+
* Full Cedar schema for ML supply chain security, including:
|
|
52
|
+
* - Actions: scan_artifact, validate_integrity, validate_provenance, quarantine_artifact, load_model, deploy_model
|
|
53
|
+
* - Entities: Scanner, Artifact, Package
|
|
54
|
+
* - 15+ context attributes for ML security findings
|
|
55
|
+
*/
|
|
56
|
+
export declare const PALISADE_SCHEMA: string;
|
|
57
|
+
/**
|
|
58
|
+
* Palisade context metadata (JSON)
|
|
59
|
+
*
|
|
60
|
+
* Metadata describing available context attributes for each Palisade action.
|
|
61
|
+
* Used by PolicyBuilder UI to generate context dropdowns with type information.
|
|
62
|
+
*/
|
|
63
|
+
export declare const PALISADE_CONTEXT: string;
|
|
64
|
+
//# sourceMappingURL=schemas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAaH,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,YAAY,EAAE,mBAAmB,IAAI,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACjG,YAAY,EAAE,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAE9F;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,QAG5B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAG7B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,QAG3B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,QAG5B,CAAC"}
|
package/dist/schemas.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Service-specific Cedar schemas and context metadata
|
|
3
|
+
*
|
|
4
|
+
* This module provides access to service-specific Cedar schemas
|
|
5
|
+
* and their associated context metadata for UI builders.
|
|
6
|
+
*
|
|
7
|
+
* Schemas are bundled with the package and loaded at runtime. The schema
|
|
8
|
+
* files are copied from schemas/ to packages/typescript/_schemas/ during
|
|
9
|
+
* codegen (see Makefile). This ensures the package is self-contained and
|
|
10
|
+
* works correctly when installed from npm.
|
|
11
|
+
*
|
|
12
|
+
* Available Schemas:
|
|
13
|
+
* - Overwatch (Guardian): IDE security policies for LLM agents and tool calls
|
|
14
|
+
* - Palisade: ML supply chain security policies for artifact scanning
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```typescript
|
|
18
|
+
* import { OVERWATCH_SCHEMA, OVERWATCH_CONTEXT } from '@highflame/policy/schemas';
|
|
19
|
+
* import { PolicyEngine } from '@highflame/policy';
|
|
20
|
+
*
|
|
21
|
+
* const engine = new PolicyEngine();
|
|
22
|
+
* engine.loadSchema(OVERWATCH_SCHEMA);
|
|
23
|
+
*
|
|
24
|
+
* // Parse context metadata for UI dropdowns
|
|
25
|
+
* const contextMeta = JSON.parse(OVERWATCH_CONTEXT);
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
import * as fs from 'fs';
|
|
29
|
+
import * as path from 'path';
|
|
30
|
+
import { fileURLToPath } from 'url';
|
|
31
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
+
const __dirname = path.dirname(__filename);
|
|
33
|
+
// Path to schemas directory (bundled with package)
|
|
34
|
+
const SCHEMAS_DIR = path.join(__dirname, '..', '_schemas');
|
|
35
|
+
// Re-export service-specific context keys
|
|
36
|
+
export { OverwatchContextKey } from './overwatch-context.gen.js';
|
|
37
|
+
export { PalisadeContextKey } from './palisade-context.gen.js';
|
|
38
|
+
/**
|
|
39
|
+
* Overwatch (Guardian) Cedar schema
|
|
40
|
+
*
|
|
41
|
+
* Full Cedar schema for IDE security, including:
|
|
42
|
+
* - Actions: process_prompt, call_tool, connect_server, read_file, write_file
|
|
43
|
+
* - Entities: User, Agent, LlmPrompt, Tool, Server, FilePath
|
|
44
|
+
* - 20+ context attributes for threat detection and workspace security
|
|
45
|
+
*/
|
|
46
|
+
export const OVERWATCH_SCHEMA = fs.readFileSync(path.join(SCHEMAS_DIR, 'overwatch', 'schema.cedarschema'), 'utf-8');
|
|
47
|
+
/**
|
|
48
|
+
* Overwatch context metadata (JSON)
|
|
49
|
+
*
|
|
50
|
+
* Metadata describing available context attributes for each Overwatch action.
|
|
51
|
+
* Used by PolicyBuilder UI to generate context dropdowns with type information.
|
|
52
|
+
*/
|
|
53
|
+
export const OVERWATCH_CONTEXT = fs.readFileSync(path.join(SCHEMAS_DIR, 'overwatch', 'context.json'), 'utf-8');
|
|
54
|
+
/**
|
|
55
|
+
* Palisade Cedar schema
|
|
56
|
+
*
|
|
57
|
+
* Full Cedar schema for ML supply chain security, including:
|
|
58
|
+
* - Actions: scan_artifact, validate_integrity, validate_provenance, quarantine_artifact, load_model, deploy_model
|
|
59
|
+
* - Entities: Scanner, Artifact, Package
|
|
60
|
+
* - 15+ context attributes for ML security findings
|
|
61
|
+
*/
|
|
62
|
+
export const PALISADE_SCHEMA = fs.readFileSync(path.join(SCHEMAS_DIR, 'palisade', 'schema.cedarschema'), 'utf-8');
|
|
63
|
+
/**
|
|
64
|
+
* Palisade context metadata (JSON)
|
|
65
|
+
*
|
|
66
|
+
* Metadata describing available context attributes for each Palisade action.
|
|
67
|
+
* Used by PolicyBuilder UI to generate context dropdowns with type information.
|
|
68
|
+
*/
|
|
69
|
+
export const PALISADE_CONTEXT = fs.readFileSync(path.join(SCHEMAS_DIR, 'palisade', 'context.json'), 'utf-8');
|
|
70
|
+
//# sourceMappingURL=schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.js","sourceRoot":"","sources":["../src/schemas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,mDAAmD;AACnD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC;AAE3D,0CAA0C;AAC1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAI/D;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC,YAAY,CAC7C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,oBAAoB,CAAC,EACzD,OAAO,CACR,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,EAAE,CAAC,YAAY,CAC9C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,EAAE,cAAc,CAAC,EACnD,OAAO,CACR,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,EAAE,CAAC,YAAY,CAC5C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,oBAAoB,CAAC,EACxD,OAAO,CACR,CAAC;AAEF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,EAAE,CAAC,YAAY,CAC7C,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,UAAU,EAAE,cAAc,CAAC,EAClD,OAAO,CACR,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.test.d.ts","sourceRoot":"","sources":["../src/schemas.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Schema validation tests
|
|
3
|
+
*
|
|
4
|
+
* Tests service-specific schema loading and policy validation
|
|
5
|
+
* using Overwatch (Guardian) and Palisade schemas.
|
|
6
|
+
*/
|
|
7
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
8
|
+
import { PolicyEngine, PolicyValidator, newEntityUID, newEntity, } from './index.js';
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
// Load service-specific schemas
|
|
12
|
+
const SCHEMAS_DIR = path.join(__dirname, '..', '..', '..', 'schemas');
|
|
13
|
+
const OVERWATCH_SCHEMA = fs.readFileSync(path.join(SCHEMAS_DIR, 'overwatch', 'schema.cedarschema'), 'utf-8');
|
|
14
|
+
const PALISADE_SCHEMA = fs.readFileSync(path.join(SCHEMAS_DIR, 'palisade', 'schema.cedarschema'), 'utf-8');
|
|
15
|
+
describe('Service-Specific Schemas', () => {
|
|
16
|
+
describe('Schema Loading', () => {
|
|
17
|
+
it('should load Overwatch schema successfully', () => {
|
|
18
|
+
expect(OVERWATCH_SCHEMA).toBeTruthy();
|
|
19
|
+
expect(OVERWATCH_SCHEMA).toContain('namespace');
|
|
20
|
+
expect(OVERWATCH_SCHEMA).toContain('Overwatch');
|
|
21
|
+
});
|
|
22
|
+
it('should load Palisade schema successfully', () => {
|
|
23
|
+
expect(PALISADE_SCHEMA).toBeTruthy();
|
|
24
|
+
expect(PALISADE_SCHEMA).toContain('namespace');
|
|
25
|
+
expect(PALISADE_SCHEMA).toContain('Palisade');
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('Overwatch Schema Validation', () => {
|
|
29
|
+
let validator;
|
|
30
|
+
beforeEach(() => {
|
|
31
|
+
validator = new PolicyValidator(OVERWATCH_SCHEMA);
|
|
32
|
+
});
|
|
33
|
+
it('should validate a correct Overwatch policy', () => {
|
|
34
|
+
const validPolicy = `
|
|
35
|
+
permit(
|
|
36
|
+
principal is Overwatch::User,
|
|
37
|
+
action == Overwatch::Action::"call_tool",
|
|
38
|
+
resource is Overwatch::Tool
|
|
39
|
+
)
|
|
40
|
+
when {
|
|
41
|
+
context.threat_count < 5 &&
|
|
42
|
+
context.highest_severity != "critical"
|
|
43
|
+
};
|
|
44
|
+
`;
|
|
45
|
+
const result = validator.validate(validPolicy);
|
|
46
|
+
if (!result.valid) {
|
|
47
|
+
console.log('Validation errors:', result.errors);
|
|
48
|
+
}
|
|
49
|
+
expect(result.valid).toBe(true);
|
|
50
|
+
expect(result.errors).toHaveLength(0);
|
|
51
|
+
});
|
|
52
|
+
it('should reject policy with invalid entity type', () => {
|
|
53
|
+
const invalidPolicy = `
|
|
54
|
+
permit(
|
|
55
|
+
principal is Overwatch::NonExistentEntity,
|
|
56
|
+
action == Overwatch::Action::"call_tool",
|
|
57
|
+
resource is Overwatch::Tool
|
|
58
|
+
);
|
|
59
|
+
`;
|
|
60
|
+
const result = validator.validate(invalidPolicy);
|
|
61
|
+
expect(result.valid).toBe(false);
|
|
62
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
63
|
+
});
|
|
64
|
+
it('should reject policy with invalid action', () => {
|
|
65
|
+
const invalidPolicy = `
|
|
66
|
+
permit(
|
|
67
|
+
principal is Overwatch::User,
|
|
68
|
+
action == Overwatch::Action::"invalid_action",
|
|
69
|
+
resource is Overwatch::Tool
|
|
70
|
+
);
|
|
71
|
+
`;
|
|
72
|
+
const result = validator.validate(invalidPolicy);
|
|
73
|
+
expect(result.valid).toBe(false);
|
|
74
|
+
expect(result.errors.length).toBeGreaterThan(0);
|
|
75
|
+
});
|
|
76
|
+
it('should validate policy with multiple context attributes', () => {
|
|
77
|
+
const policy = `
|
|
78
|
+
permit(
|
|
79
|
+
principal is Overwatch::Agent,
|
|
80
|
+
action == Overwatch::Action::"process_prompt",
|
|
81
|
+
resource is Overwatch::LlmPrompt
|
|
82
|
+
)
|
|
83
|
+
when {
|
|
84
|
+
context.threat_count == 0 &&
|
|
85
|
+
context.highest_severity == "low" &&
|
|
86
|
+
context.contains_secrets == false
|
|
87
|
+
};
|
|
88
|
+
`;
|
|
89
|
+
const result = validator.validate(policy);
|
|
90
|
+
expect(result.valid).toBe(true);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe('Palisade Schema Validation', () => {
|
|
94
|
+
let validator;
|
|
95
|
+
beforeEach(() => {
|
|
96
|
+
validator = new PolicyValidator(PALISADE_SCHEMA);
|
|
97
|
+
});
|
|
98
|
+
it('should validate a correct Palisade policy', () => {
|
|
99
|
+
const validPolicy = `
|
|
100
|
+
permit(
|
|
101
|
+
principal is Palisade::Scanner,
|
|
102
|
+
action == Palisade::Action::"scan_artifact",
|
|
103
|
+
resource is Palisade::Artifact
|
|
104
|
+
)
|
|
105
|
+
when {
|
|
106
|
+
context.environment == "production" &&
|
|
107
|
+
context.artifact_format == "safetensors"
|
|
108
|
+
};
|
|
109
|
+
`;
|
|
110
|
+
const result = validator.validate(validPolicy);
|
|
111
|
+
expect(result.valid).toBe(true);
|
|
112
|
+
expect(result.errors).toHaveLength(0);
|
|
113
|
+
});
|
|
114
|
+
it('should reject policy with wrong namespace', () => {
|
|
115
|
+
const invalidPolicy = `
|
|
116
|
+
permit(
|
|
117
|
+
principal is Overwatch::Scanner,
|
|
118
|
+
action == Palisade::Action::"scan_artifact",
|
|
119
|
+
resource is Palisade::Artifact
|
|
120
|
+
);
|
|
121
|
+
`;
|
|
122
|
+
const result = validator.validate(invalidPolicy);
|
|
123
|
+
expect(result.valid).toBe(false);
|
|
124
|
+
});
|
|
125
|
+
it('should validate policy with ML-specific context', () => {
|
|
126
|
+
const policy = `
|
|
127
|
+
forbid(
|
|
128
|
+
principal is Palisade::Scanner,
|
|
129
|
+
action == Palisade::Action::"scan_artifact",
|
|
130
|
+
resource is Palisade::Artifact
|
|
131
|
+
)
|
|
132
|
+
when {
|
|
133
|
+
context.pickle_exec_path_detected == true ||
|
|
134
|
+
context.severity == "CRITICAL"
|
|
135
|
+
};
|
|
136
|
+
`;
|
|
137
|
+
const result = validator.validate(policy);
|
|
138
|
+
expect(result.valid).toBe(true);
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
describe('PolicyEngine with Service Schemas', () => {
|
|
142
|
+
it('should evaluate Overwatch policy correctly', () => {
|
|
143
|
+
const policy = `
|
|
144
|
+
permit(
|
|
145
|
+
principal is Overwatch::User,
|
|
146
|
+
action == Overwatch::Action::"call_tool",
|
|
147
|
+
resource is Overwatch::Tool
|
|
148
|
+
)
|
|
149
|
+
when { context.threat_count < 5 };
|
|
150
|
+
`;
|
|
151
|
+
const engine = new PolicyEngine({ schema: OVERWATCH_SCHEMA });
|
|
152
|
+
engine.loadPolicies(policy);
|
|
153
|
+
const entities = [
|
|
154
|
+
newEntity('Overwatch::User', 'mcp_client', { user_type: 'external', email: 'user@example.com' }),
|
|
155
|
+
newEntity('Overwatch::Tool', 'shell', { tool_name: 'shell', risk_level: 'high' }),
|
|
156
|
+
];
|
|
157
|
+
const decision = engine.evaluate({
|
|
158
|
+
principal: newEntityUID('Overwatch::User', 'mcp_client'),
|
|
159
|
+
action: 'Overwatch::Action::"call_tool"',
|
|
160
|
+
resource: newEntityUID('Overwatch::Tool', 'shell'),
|
|
161
|
+
context: {
|
|
162
|
+
content: 'ls -la',
|
|
163
|
+
source: 'claudecode',
|
|
164
|
+
event: 'PreToolUse',
|
|
165
|
+
user_email: 'user@example.com',
|
|
166
|
+
tool_name: 'shell',
|
|
167
|
+
mcp_server: 'filesystem',
|
|
168
|
+
mcp_tool: 'shell',
|
|
169
|
+
path: '/workspace',
|
|
170
|
+
cwd: '/workspace',
|
|
171
|
+
workspace_root: '/workspace',
|
|
172
|
+
threat_count: 3,
|
|
173
|
+
highest_severity: 'low',
|
|
174
|
+
threat_categories: [],
|
|
175
|
+
threat_types: [],
|
|
176
|
+
yara_threats: [],
|
|
177
|
+
max_threat_severity: 1,
|
|
178
|
+
contains_secrets: false,
|
|
179
|
+
response_content: '',
|
|
180
|
+
},
|
|
181
|
+
entities,
|
|
182
|
+
});
|
|
183
|
+
if (decision.effect !== 'Allow') {
|
|
184
|
+
console.log('Decision:', decision);
|
|
185
|
+
console.log('Reason:', decision.reason);
|
|
186
|
+
}
|
|
187
|
+
expect(decision.effect).toBe('Allow');
|
|
188
|
+
});
|
|
189
|
+
it('should deny Overwatch policy when context fails condition', () => {
|
|
190
|
+
const policy = `
|
|
191
|
+
permit(
|
|
192
|
+
principal is Overwatch::User,
|
|
193
|
+
action == Overwatch::Action::"call_tool",
|
|
194
|
+
resource is Overwatch::Tool
|
|
195
|
+
)
|
|
196
|
+
when { context.threat_count < 5 };
|
|
197
|
+
`;
|
|
198
|
+
const engine = new PolicyEngine({ schema: OVERWATCH_SCHEMA });
|
|
199
|
+
engine.loadPolicies(policy);
|
|
200
|
+
const entities = [
|
|
201
|
+
newEntity('Overwatch::User', 'mcp_client', { user_type: 'external', email: 'user@example.com' }),
|
|
202
|
+
newEntity('Overwatch::Tool', 'shell', { tool_name: 'shell', risk_level: 'high' }),
|
|
203
|
+
];
|
|
204
|
+
const decision = engine.evaluate({
|
|
205
|
+
principal: newEntityUID('Overwatch::User', 'mcp_client'),
|
|
206
|
+
action: 'Overwatch::Action::"call_tool"',
|
|
207
|
+
resource: newEntityUID('Overwatch::Tool', 'shell'),
|
|
208
|
+
context: { threat_count: 10 }, // Too many threats
|
|
209
|
+
entities,
|
|
210
|
+
});
|
|
211
|
+
expect(decision.effect).toBe('Deny');
|
|
212
|
+
});
|
|
213
|
+
it('should evaluate Palisade policy correctly', () => {
|
|
214
|
+
const policy = `
|
|
215
|
+
forbid(
|
|
216
|
+
principal is Palisade::Scanner,
|
|
217
|
+
action == Palisade::Action::"load_model",
|
|
218
|
+
resource is Palisade::Artifact
|
|
219
|
+
)
|
|
220
|
+
when {
|
|
221
|
+
context.pickle_exec_path_detected == true
|
|
222
|
+
};
|
|
223
|
+
`;
|
|
224
|
+
const engine = new PolicyEngine({ schema: PALISADE_SCHEMA });
|
|
225
|
+
engine.loadPolicies(policy);
|
|
226
|
+
const entities = [
|
|
227
|
+
newEntity('Palisade::Scanner', 'palisade', { scanner_type: 'ml_security' }),
|
|
228
|
+
newEntity('Palisade::Artifact', 'model.pkl', { artifact_format: 'pickle', path: '/models/model.pkl', signed: false, signer: 'unsigned' }),
|
|
229
|
+
];
|
|
230
|
+
const decision = engine.evaluate({
|
|
231
|
+
principal: newEntityUID('Palisade::Scanner', 'palisade'),
|
|
232
|
+
action: 'Palisade::Action::"load_model"',
|
|
233
|
+
resource: newEntityUID('Palisade::Artifact', 'model.pkl'),
|
|
234
|
+
context: {
|
|
235
|
+
environment: 'production',
|
|
236
|
+
pickle_exec_path_detected: true,
|
|
237
|
+
severity: 'CRITICAL',
|
|
238
|
+
},
|
|
239
|
+
entities,
|
|
240
|
+
});
|
|
241
|
+
expect(decision.effect).toBe('Deny');
|
|
242
|
+
});
|
|
243
|
+
it('should allow Palisade policy when condition is false', () => {
|
|
244
|
+
const policy = `
|
|
245
|
+
permit(
|
|
246
|
+
principal is Palisade::Scanner,
|
|
247
|
+
action == Palisade::Action::"scan_artifact",
|
|
248
|
+
resource is Palisade::Artifact
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
forbid(
|
|
252
|
+
principal is Palisade::Scanner,
|
|
253
|
+
action == Palisade::Action::"scan_artifact",
|
|
254
|
+
resource is Palisade::Artifact
|
|
255
|
+
)
|
|
256
|
+
when {
|
|
257
|
+
context.pickle_exec_path_detected == true
|
|
258
|
+
};
|
|
259
|
+
`;
|
|
260
|
+
const engine = new PolicyEngine({ schema: PALISADE_SCHEMA });
|
|
261
|
+
engine.loadPolicies(policy);
|
|
262
|
+
const entities = [
|
|
263
|
+
newEntity('Palisade::Scanner', 'palisade', { scanner_type: 'ml_security' }),
|
|
264
|
+
newEntity('Palisade::Artifact', 'model.safetensors', { artifact_format: 'safetensors', path: '/models/model.safetensors', signed: true, signer: 'trusted-org' }),
|
|
265
|
+
];
|
|
266
|
+
const decision = engine.evaluate({
|
|
267
|
+
principal: newEntityUID('Palisade::Scanner', 'palisade'),
|
|
268
|
+
action: 'Palisade::Action::"scan_artifact"',
|
|
269
|
+
resource: newEntityUID('Palisade::Artifact', 'model.safetensors'),
|
|
270
|
+
context: {
|
|
271
|
+
environment: 'production',
|
|
272
|
+
pickle_exec_path_detected: false,
|
|
273
|
+
severity: 'INFO',
|
|
274
|
+
finding_type: 'backdoor_check',
|
|
275
|
+
artifact_format: 'safetensors',
|
|
276
|
+
path: '/models/model.safetensors',
|
|
277
|
+
artifact_signed: true,
|
|
278
|
+
provenance_signer: 'trusted',
|
|
279
|
+
tokenizer_added_tokens_count: 0,
|
|
280
|
+
adapter_base_digest_mismatch: false,
|
|
281
|
+
gguf_suspicious_metadata: false,
|
|
282
|
+
safetensors_integrity_violation: false,
|
|
283
|
+
metadata_malicious_pattern: false,
|
|
284
|
+
metadata_cosai_level_numeric: 3,
|
|
285
|
+
match_count: 0,
|
|
286
|
+
},
|
|
287
|
+
entities,
|
|
288
|
+
});
|
|
289
|
+
if (decision.effect !== 'Allow') {
|
|
290
|
+
console.log('Decision:', decision);
|
|
291
|
+
console.log('Reason:', decision.reason);
|
|
292
|
+
}
|
|
293
|
+
expect(decision.effect).toBe('Allow');
|
|
294
|
+
});
|
|
295
|
+
});
|
|
296
|
+
describe('Example from REFACTORING_SUMMARY.md', () => {
|
|
297
|
+
it('should work with Guardian plugin example', () => {
|
|
298
|
+
const engine = new PolicyEngine({ schema: OVERWATCH_SCHEMA });
|
|
299
|
+
const policy = `
|
|
300
|
+
permit(
|
|
301
|
+
principal is Overwatch::User,
|
|
302
|
+
action == Overwatch::Action::"call_tool",
|
|
303
|
+
resource is Overwatch::Tool
|
|
304
|
+
)
|
|
305
|
+
when {
|
|
306
|
+
context.threat_count < 10 &&
|
|
307
|
+
context.highest_severity != "critical"
|
|
308
|
+
};
|
|
309
|
+
`;
|
|
310
|
+
engine.loadPolicies(policy);
|
|
311
|
+
const entities = [
|
|
312
|
+
newEntity('Overwatch::User', 'mcp_client', { user_type: 'external', email: 'user@example.com' }),
|
|
313
|
+
newEntity('Overwatch::Tool', 'shell', { tool_name: 'shell', risk_level: 'high' }),
|
|
314
|
+
];
|
|
315
|
+
const decision = engine.evaluate({
|
|
316
|
+
principal: newEntityUID('Overwatch::User', 'mcp_client'),
|
|
317
|
+
action: 'Overwatch::Action::"call_tool"',
|
|
318
|
+
resource: newEntityUID('Overwatch::Tool', 'shell'),
|
|
319
|
+
context: {
|
|
320
|
+
content: 'cat /etc/passwd',
|
|
321
|
+
source: 'claudecode',
|
|
322
|
+
event: 'PreToolUse',
|
|
323
|
+
user_email: 'user@example.com',
|
|
324
|
+
tool_name: 'shell',
|
|
325
|
+
mcp_server: 'filesystem',
|
|
326
|
+
mcp_tool: 'shell',
|
|
327
|
+
path: '/etc/passwd',
|
|
328
|
+
cwd: '/workspace',
|
|
329
|
+
workspace_root: '/workspace',
|
|
330
|
+
threat_count: 5,
|
|
331
|
+
highest_severity: 'medium',
|
|
332
|
+
threat_categories: [],
|
|
333
|
+
threat_types: [],
|
|
334
|
+
yara_threats: [],
|
|
335
|
+
max_threat_severity: 2,
|
|
336
|
+
contains_secrets: false,
|
|
337
|
+
response_content: '',
|
|
338
|
+
},
|
|
339
|
+
entities,
|
|
340
|
+
});
|
|
341
|
+
expect(decision.effect).toBe('Allow');
|
|
342
|
+
});
|
|
343
|
+
it('should work with Palisade service example', () => {
|
|
344
|
+
const engine = new PolicyEngine({ schema: PALISADE_SCHEMA });
|
|
345
|
+
const policy = `
|
|
346
|
+
forbid(
|
|
347
|
+
principal is Palisade::Scanner,
|
|
348
|
+
action == Palisade::Action::"load_model",
|
|
349
|
+
resource is Palisade::Artifact
|
|
350
|
+
)
|
|
351
|
+
when {
|
|
352
|
+
context.environment == "production" &&
|
|
353
|
+
context.pickle_exec_path_detected == true &&
|
|
354
|
+
context.severity == "CRITICAL"
|
|
355
|
+
};
|
|
356
|
+
`;
|
|
357
|
+
engine.loadPolicies(policy);
|
|
358
|
+
const entities = [
|
|
359
|
+
newEntity('Palisade::Scanner', 'palisade', { scanner_type: 'ml_security' }),
|
|
360
|
+
newEntity('Palisade::Artifact', 'model.pkl', { artifact_format: 'pickle', path: '/models/model.pkl', signed: false, signer: 'unsigned' }),
|
|
361
|
+
];
|
|
362
|
+
const decision = engine.evaluate({
|
|
363
|
+
principal: newEntityUID('Palisade::Scanner', 'palisade'),
|
|
364
|
+
action: 'Palisade::Action::"load_model"',
|
|
365
|
+
resource: newEntityUID('Palisade::Artifact', 'model.pkl'),
|
|
366
|
+
context: {
|
|
367
|
+
environment: 'production',
|
|
368
|
+
pickle_exec_path_detected: true,
|
|
369
|
+
severity: 'CRITICAL',
|
|
370
|
+
},
|
|
371
|
+
entities,
|
|
372
|
+
});
|
|
373
|
+
expect(decision.effect).toBe('Deny');
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
//# sourceMappingURL=schemas.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemas.test.js","sourceRoot":"","sources":["../src/schemas.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Overwatch (Guardian) Cedar schema
|
|
3
|
+
*
|
|
4
|
+
* Full Cedar schema for IDE security, including:
|
|
5
|
+
* - Actions: process_prompt, call_tool, connect_server, read_file, write_file
|
|
6
|
+
* - Entities: User, Agent, LlmPrompt, Tool, Server, FilePath
|
|
7
|
+
* - Context attributes for threat detection and workspace security
|
|
8
|
+
*/
|
|
9
|
+
export declare const OVERWATCH_SCHEMA = "// Overwatch (Guardian) Cedar Schema\n// ===================================\n// IDE Security & Policy Enforcement\n//\n// Overwatch protects IDE operations (prompts, tool calls, file access) by evaluating\n// threats detected by YARA and Javelin scanners against Cedar policies.\n//\n// Architecture:\n// User/Agent \u2192 IDE Hook \u2192 YARA/Javelin \u2192 Cedar Policy \u2192 Allow/Deny\n//\n// Supported IDEs:\n// - Cursor (beforeSubmitPrompt, beforeShellExecution, beforeMCPExecution, etc.)\n// - Claude Code (UserPromptSubmit, PreToolUse)\n// - GitHub Copilot (userPromptSubmitted, preToolUse)\n\nnamespace Overwatch {\n\n// =============================================================================\n// ENTITIES\n// =============================================================================\n\n// Human user or service account making requests to the IDE\nentity User {\n user_type: String, // \"external\" or \"internal\"\n email: String, // User email (optional)\n};\n\n// AI agent (Claude, GitHub Copilot, etc.)\nentity Agent {\n agent_type: String, // \"claude\", \"copilot\", etc.\n};\n\n// LLM prompt or session\nentity LlmPrompt {\n prompt_type: String, // \"user_prompt\", \"session\"\n};\n\n// MCP tool or native IDE tool\nentity Tool {\n tool_name: String, // \"shell\", \"read_file\", \"playwright\", etc.\n risk_level: String, // \"low\", \"medium\", \"high\"\n};\n\n// MCP server\nentity Server {\n server_name: String, // \"filesystem\", \"playwright\", etc.\n};\n\n// File system path\nentity FilePath {\n path: String,\n is_within_workspace: Bool,\n};\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\n// User submits a prompt or receives AI response\naction process_prompt appliesTo {\n principal: [User, Agent],\n resource: [LlmPrompt],\n context: {\n // Event & Source\n content: String, // Raw content being scanned\n source: String, // IDE source: \"cursor\", \"claudecode\", \"github_copilot\"\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // Workspace\n cwd: String, // Current working directory\n workspace_root: String, // Workspace/repository root\n\n // Threat Detection\n threat_count: Long, // Total threats detected\n highest_severity: String, // \"critical\", \"high\", \"medium\", \"low\"\n threat_categories: Set<String>, // Threat category names\n threat_types: Set<String>, // YARA threat categories\n yara_threats: Set<String>, // YARA rule names\n max_threat_severity: Long, // Numeric severity (0-4)\n contains_secrets: Bool, // Whether secrets detected\n prompt_text: String, // Same as content (legacy)\n response_content: String, // Response content (if available)\n },\n};\n\n// User calls a tool (native IDE tool or MCP tool)\naction call_tool appliesTo {\n principal: [User, Agent],\n resource: [Tool, FilePath],\n context: {\n // Event & Source\n content: String, // Raw content being scanned (e.g., shell command)\n source: String, // IDE source\n event: String, // Hook event name\n user_email: String, // User identifier\n\n // Tool & MCP\n tool_name: String, // Normalized tool name (\"shell\", \"read_file\", etc.)\n mcp_server: String, // MCP server name\n mcp_tool: String, // MCP tool name\n\n // File & Path\n path: String, // File path (if file operation)\n\n // Workspace\n cwd: String,\n workspace_root: String,\n\n // Threat Detection\n threat_count: Long,\n highest_severity: String,\n threat_categories: Set<String>,\n threat_types: Set<String>,\n yara_threats: Set<String>,\n max_threat_severity: Long,\n contains_secrets: Bool,\n response_content: String,\n },\n};\n\n// Connect to an MCP server\naction connect_server appliesTo {\n principal: [User, Agent],\n resource: [Server],\n context: {\n content: String,\n source: String,\n event: String,\n user_email: String,\n mcp_server: String,\n threat_count: Long,\n highest_severity: String,\n threat_categories: Set<String>,\n max_threat_severity: Long,\n },\n};\n\n// Read a file from disk\naction read_file appliesTo {\n principal: [User, Agent],\n resource: [FilePath],\n context: {\n content: String,\n source: String,\n event: String,\n user_email: String,\n path: String,\n cwd: String,\n workspace_root: String,\n threat_count: Long,\n highest_severity: String,\n threat_categories: Set<String>,\n max_threat_severity: Long,\n contains_secrets: Bool,\n },\n};\n\n// Write a file to disk\naction write_file appliesTo {\n principal: [User, Agent],\n resource: [FilePath],\n context: {\n content: String,\n source: String,\n event: String,\n user_email: String,\n path: String,\n cwd: String,\n workspace_root: String,\n threat_count: Long,\n highest_severity: String,\n threat_categories: Set<String>,\n max_threat_severity: Long,\n contains_secrets: Bool,\n },\n};\n\n}\n";
|
|
10
|
+
/**
|
|
11
|
+
* Palisade Cedar schema
|
|
12
|
+
*
|
|
13
|
+
* Full Cedar schema for ML supply chain security, including:
|
|
14
|
+
* - Actions: scan_artifact, validate_integrity, validate_provenance, quarantine_artifact, load_model, deploy_model
|
|
15
|
+
* - Entities: Scanner, Artifact, Package
|
|
16
|
+
* - Context attributes for ML security findings
|
|
17
|
+
*/
|
|
18
|
+
export declare const PALISADE_SCHEMA = "// Palisade Cedar Schema\n// =====================\n// ML Supply Chain Security & Artifact Scanning\n//\n// Palisade scans ML model artifacts (safetensors, GGUF, pickle, PyTorch) for\n// security vulnerabilities and enforces policies based on findings.\n//\n// Architecture:\n// Scanner \u2192 Validators (Pickle, SafeTensors, GGUF, etc.) \u2192 Cedar Policy \u2192 Allow/Deny/Quarantine\n//\n// Supported Formats:\n// - SafeTensors (.safetensors)\n// - GGUF (.gguf)\n// - Pickle (.pkl, .pickle, .pt)\n// - PyTorch (.pth, .pt)\n// - ONNX (.onnx)\n\nnamespace Palisade {\n\n// =============================================================================\n// ENTITIES\n// =============================================================================\n\n// Security scanner service\nentity Scanner {\n scanner_type: String, // \"palisade\", \"redteam\", etc.\n};\n\n// ML model artifact\nentity Artifact {\n artifact_format: String, // \"safetensors\", \"gguf\", \"pickle\", \"pytorch\", \"onnx\"\n path: String, // File path\n signed: Bool, // Whether digitally signed\n signer: String, // Who signed (if applicable)\n};\n\n// Software package (npm, PyPI, etc.)\nentity Package {\n package_name: String,\n package_version: String,\n};\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\n// Scan an ML artifact for security issues\naction scan_artifact appliesTo {\n principal: [Scanner],\n resource: [Artifact],\n context: {\n // Core Finding & Severity\n finding_type: String, // Type of finding (e.g., \"backdoor_detected\", \"safetensors_integrity_violation\")\n severity: String, // \"CRITICAL\", \"HIGH\", \"MEDIUM\", \"LOW\", \"INFO\"\n environment: String, // \"production\", \"strict_production\", \"development\", \"permissive_development\", \"research\"\n\n // Artifact Metadata\n artifact_format: String, // \"safetensors\", \"gguf\", \"pickle\", \"pytorch\", \"onnx\"\n path: String, // File path to artifact\n artifact_signed: Bool, // Whether artifact is digitally signed\n provenance_signer: String, // \"unknown\", \"unsigned\", or signer name\n\n // Pickle Security\n pickle_exec_path_detected: Bool, // Pickle RCE execution path detected (CRITICAL)\n\n // Tokenizer Security\n tokenizer_added_tokens_count: Long, // Number of added tokens (0-5000+)\n\n // LoRA Security\n adapter_base_digest_mismatch: Bool, // LoRA adapter base model digest mismatch\n\n // GGUF Security\n gguf_suspicious_metadata: Bool, // GGUF metadata contains suspicious patterns\n\n // SafeTensors Security\n safetensors_integrity_violation: Bool, // SafeTensors file integrity violated\n\n // General Metadata Security\n metadata_malicious_pattern: Bool, // Metadata contains malicious patterns\n\n // CoSAI Maturity\n metadata_cosai_level_numeric: Long, // CoSAI maturity level (0-5, higher = more trustworthy)\n\n // Backdoor Detection\n match_count: Long, // Number of behavioral backdoor indicator matches\n },\n};\n\n// Validate artifact integrity (checksum, signature)\naction validate_integrity appliesTo {\n principal: [Scanner],\n resource: [Artifact],\n context: {\n artifact_format: String,\n path: String,\n artifact_signed: Bool,\n provenance_signer: String,\n safetensors_integrity_violation: Bool,\n finding_type: String,\n severity: String,\n },\n};\n\n// Validate artifact provenance (signer, origin)\naction validate_provenance appliesTo {\n principal: [Scanner],\n resource: [Artifact],\n context: {\n artifact_format: String,\n path: String,\n artifact_signed: Bool,\n provenance_signer: String,\n metadata_cosai_level_numeric: Long,\n finding_type: String,\n severity: String,\n },\n};\n\n// Quarantine a malicious artifact\naction quarantine_artifact appliesTo {\n principal: [Scanner],\n resource: [Artifact],\n context: {\n finding_type: String,\n severity: String,\n environment: String,\n artifact_format: String,\n path: String,\n },\n};\n\n// Load an ML model into memory\naction load_model appliesTo {\n principal: [Scanner],\n resource: [Artifact],\n context: {\n artifact_format: String,\n environment: String,\n artifact_signed: Bool,\n severity: String,\n },\n};\n\n// Deploy an ML model to production\naction deploy_model appliesTo {\n principal: [Scanner],\n resource: [Artifact],\n context: {\n artifact_format: String,\n environment: String,\n artifact_signed: Bool,\n provenance_signer: String,\n severity: String,\n },\n};\n\n// Scan a software package\naction scan_package appliesTo {\n principal: [Scanner],\n resource: [Package],\n context: {\n finding_type: String,\n severity: String,\n environment: String,\n },\n};\n\n}\n";
|
|
19
|
+
/**
|
|
20
|
+
* Context attribute metadata for Overwatch actions.
|
|
21
|
+
* Used by PolicyBuilder UI to generate form fields.
|
|
22
|
+
*/
|
|
23
|
+
export interface ContextAttribute {
|
|
24
|
+
key: string;
|
|
25
|
+
type: 'string' | 'number' | 'boolean' | 'array';
|
|
26
|
+
required: boolean;
|
|
27
|
+
description: string;
|
|
28
|
+
}
|
|
29
|
+
export interface ActionContext {
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
context_attributes: ContextAttribute[];
|
|
33
|
+
}
|
|
34
|
+
export interface ServiceContext {
|
|
35
|
+
service: string;
|
|
36
|
+
version: string;
|
|
37
|
+
description: string;
|
|
38
|
+
actions: ActionContext[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Overwatch context metadata (parsed JSON)
|
|
42
|
+
*/
|
|
43
|
+
export declare const OVERWATCH_CONTEXT: ServiceContext;
|
|
44
|
+
/**
|
|
45
|
+
* Palisade context metadata (parsed JSON)
|
|
46
|
+
*/
|
|
47
|
+
export declare const PALISADE_CONTEXT: ServiceContext;
|
|
48
|
+
//# sourceMappingURL=service-schemas.gen.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service-schemas.gen.d.ts","sourceRoot":"","sources":["../src/service-schemas.gen.ts"],"names":[],"mappings":"AAUA;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,izKAmL5B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,eAAe,87JAwK3B,CAAC;AAEF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,CAAC;IAChD,QAAQ,EAAE,OAAO,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,gBAAgB,EAAE,CAAC;CACxC;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,aAAa,EAAE,CAAC;CAC1B;AAED;;GAEG;AACH,eAAO,MAAM,iBAAiB,EAAE,cAwG/B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,cA8F9B,CAAC"}
|