@highflame/policy 2.0.10 → 2.1.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/_schemas/guardrails/context.json +435 -0
- package/_schemas/guardrails/schema.cedarschema +225 -0
- package/_schemas/guardrails/templates/defaults/agentic_safety.cedar +94 -0
- package/_schemas/guardrails/templates/defaults/baseline.cedar +24 -0
- package/_schemas/guardrails/templates/defaults/injection.cedar +70 -0
- package/_schemas/guardrails/templates/defaults/pii.cedar +48 -0
- package/_schemas/guardrails/templates/defaults/secrets.cedar +40 -0
- package/_schemas/guardrails/templates/defaults/semantic.cedar +59 -0
- package/_schemas/guardrails/templates/defaults/tool_risk.cedar +58 -0
- package/_schemas/guardrails/templates/defaults/toxicity.cedar +76 -0
- package/_schemas/guardrails/templates/mcp_tool_permissions.cedar +84 -0
- package/_schemas/guardrails/templates/profiles/chat_assistant/privacy.cedar +22 -0
- package/_schemas/guardrails/templates/profiles/chat_assistant/security.cedar +35 -0
- package/_schemas/guardrails/templates/profiles/chat_assistant/trust_safety.cedar +43 -0
- package/_schemas/guardrails/templates/profiles/chat_assistant.cedar +85 -0
- package/_schemas/guardrails/templates/profiles/code_agent/agentic_security.cedar +109 -0
- package/_schemas/guardrails/templates/profiles/code_agent/security.cedar +22 -0
- package/_schemas/guardrails/templates/profiles/code_agent.cedar +125 -0
- package/_schemas/guardrails/templates/profiles/data_pipeline/agentic_security.cedar +38 -0
- package/_schemas/guardrails/templates/profiles/data_pipeline/privacy.cedar +40 -0
- package/_schemas/guardrails/templates/profiles/data_pipeline/security.cedar +49 -0
- package/_schemas/guardrails/templates/profiles/data_pipeline.cedar +111 -0
- package/_schemas/guardrails/templates/templates.json +213 -0
- package/dist/builder.d.ts +61 -0
- package/dist/builder.js +4 -2
- package/dist/entities.gen.d.ts +4 -0
- package/dist/entities.gen.js +4 -0
- package/dist/explain.d.ts +178 -0
- package/dist/explain.js +390 -0
- package/dist/guardrails-context.gen.d.ts +49 -0
- package/dist/guardrails-context.gen.js +50 -0
- package/dist/guardrails-defaults.gen.d.ts +61 -0
- package/dist/guardrails-defaults.gen.js +1278 -0
- package/dist/guardrails-entities.gen.d.ts +11 -0
- package/dist/guardrails-entities.gen.js +37 -0
- package/dist/index.d.ts +6 -1
- package/dist/index.js +6 -1
- package/dist/overwatch-defaults.gen.js +98 -0
- package/dist/parser.js +136 -4
- package/dist/schema.gen.d.ts +1 -1
- package/dist/schema.gen.js +6 -0
- package/dist/service-schemas.gen.d.ts +10 -0
- package/dist/service-schemas.gen.js +337 -1
- package/dist/types.d.ts +6 -1
- package/dist/types.js +6 -1
- package/package.json +5 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ServiceEntityMetadata, ActionEntityMetadata } from './entity-metadata-types.gen.js';
|
|
2
|
+
/**
|
|
3
|
+
* Guardrails entity metadata for UI components.
|
|
4
|
+
* Extracted from Cedar schema appliesTo blocks.
|
|
5
|
+
*/
|
|
6
|
+
export declare const GUARDRAILS_ENTITIES: ServiceEntityMetadata;
|
|
7
|
+
/**
|
|
8
|
+
* Per-action entity mapping for Guardrails.
|
|
9
|
+
* Maps action names to their valid principals and resources.
|
|
10
|
+
*/
|
|
11
|
+
export declare const GUARDRAILS_ACTION_ENTITIES: Record<string, ActionEntityMetadata>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
// Code generated by highflame-policy-codegen. DO NOT EDIT.
|
|
2
|
+
// Source: schemas/guardrails/schema.cedarschema
|
|
3
|
+
/**
|
|
4
|
+
* Guardrails entity metadata for UI components.
|
|
5
|
+
* Extracted from Cedar schema appliesTo blocks.
|
|
6
|
+
*/
|
|
7
|
+
export const GUARDRAILS_ENTITIES = {
|
|
8
|
+
principals: ['Agent', 'User'],
|
|
9
|
+
resources: ['App', 'Session'],
|
|
10
|
+
actions: ['call_tool', 'connect_server', 'process_prompt', 'read_file', 'write_file'],
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Per-action entity mapping for Guardrails.
|
|
14
|
+
* Maps action names to their valid principals and resources.
|
|
15
|
+
*/
|
|
16
|
+
export const GUARDRAILS_ACTION_ENTITIES = {
|
|
17
|
+
'call_tool': {
|
|
18
|
+
principals: ['User', 'Agent'],
|
|
19
|
+
resources: ['Session'],
|
|
20
|
+
},
|
|
21
|
+
'connect_server': {
|
|
22
|
+
principals: ['User', 'Agent'],
|
|
23
|
+
resources: ['Session'],
|
|
24
|
+
},
|
|
25
|
+
'process_prompt': {
|
|
26
|
+
principals: ['User', 'Agent'],
|
|
27
|
+
resources: ['App', 'Session'],
|
|
28
|
+
},
|
|
29
|
+
'read_file': {
|
|
30
|
+
principals: ['User', 'Agent'],
|
|
31
|
+
resources: ['Session'],
|
|
32
|
+
},
|
|
33
|
+
'write_file': {
|
|
34
|
+
principals: ['User', 'Agent'],
|
|
35
|
+
resources: ['Session'],
|
|
36
|
+
},
|
|
37
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -7,12 +7,17 @@ export * from './builder.js';
|
|
|
7
7
|
export * from './parser.js';
|
|
8
8
|
export * from './errors.js';
|
|
9
9
|
export * from './annotations.js';
|
|
10
|
-
export
|
|
10
|
+
export * from './explain.js';
|
|
11
|
+
export { GUARDRAILS_SCHEMA, GUARDRAILS_CONTEXT, OVERWATCH_SCHEMA, OVERWATCH_CONTEXT, PALISADE_SCHEMA, PALISADE_CONTEXT, } from './service-schemas.gen.js';
|
|
11
12
|
export type { ContextAttribute, ActionContext, ServiceContext, } from './service-schemas.gen.js';
|
|
13
|
+
export { GuardrailsContextKey } from './guardrails-context.gen.js';
|
|
12
14
|
export { OverwatchContextKey } from './overwatch-context.gen.js';
|
|
13
15
|
export { PalisadeContextKey } from './palisade-context.gen.js';
|
|
16
|
+
export { GUARDRAILS_ENTITIES, GUARDRAILS_ACTION_ENTITIES, } from './guardrails-entities.gen.js';
|
|
14
17
|
export { OVERWATCH_ENTITIES, OVERWATCH_ACTION_ENTITIES, } from './overwatch-entities.gen.js';
|
|
15
18
|
export { PALISADE_ENTITIES, PALISADE_ACTION_ENTITIES, } from './palisade-entities.gen.js';
|
|
16
19
|
export type { ServiceEntityMetadata, ActionEntityMetadata } from './entity-metadata-types.gen.js';
|
|
20
|
+
export { GUARDRAILS_DEFAULTS, GUARDRAILS_TEMPLATES, GUARDRAILS_CATEGORIES, GUARDRAILS_TEMPLATES_JSON, getGuardrailsDefaultsByCategory, getGuardrailsTemplatesByCategory, getGuardrailsTemplateById, } from './guardrails-defaults.gen.js';
|
|
21
|
+
export type { GuardrailsCategory, GuardrailsCategoryInfo, GuardrailsDefaultPolicy, GuardrailsTemplate, } from './guardrails-defaults.gen.js';
|
|
17
22
|
export { OVERWATCH_DEFAULTS, OVERWATCH_TEMPLATES, OVERWATCH_CATEGORIES, OVERWATCH_TEMPLATES_JSON, getOverwatchDefaultsByCategory, getOverwatchTemplatesByCategory, getOverwatchTemplateById, } from './overwatch-defaults.gen.js';
|
|
18
23
|
export type { OverwatchCategory, OverwatchCategoryInfo, OverwatchDefaultPolicy, OverwatchTemplate, } from './overwatch-defaults.gen.js';
|
package/dist/index.js
CHANGED
|
@@ -13,13 +13,18 @@ export * from './builder.js';
|
|
|
13
13
|
export * from './parser.js';
|
|
14
14
|
export * from './errors.js';
|
|
15
15
|
export * from './annotations.js';
|
|
16
|
+
// Decision explanation
|
|
17
|
+
export * from './explain.js';
|
|
16
18
|
// Service-specific schemas and context (inlined)
|
|
17
|
-
export { OVERWATCH_SCHEMA, OVERWATCH_CONTEXT, PALISADE_SCHEMA, PALISADE_CONTEXT, } from './service-schemas.gen.js';
|
|
19
|
+
export { GUARDRAILS_SCHEMA, GUARDRAILS_CONTEXT, OVERWATCH_SCHEMA, OVERWATCH_CONTEXT, PALISADE_SCHEMA, PALISADE_CONTEXT, } from './service-schemas.gen.js';
|
|
18
20
|
// Service-specific context key enums
|
|
21
|
+
export { GuardrailsContextKey } from './guardrails-context.gen.js';
|
|
19
22
|
export { OverwatchContextKey } from './overwatch-context.gen.js';
|
|
20
23
|
export { PalisadeContextKey } from './palisade-context.gen.js';
|
|
21
24
|
// Service-specific entity metadata (for UI - principals, resources, actions)
|
|
25
|
+
export { GUARDRAILS_ENTITIES, GUARDRAILS_ACTION_ENTITIES, } from './guardrails-entities.gen.js';
|
|
22
26
|
export { OVERWATCH_ENTITIES, OVERWATCH_ACTION_ENTITIES, } from './overwatch-entities.gen.js';
|
|
23
27
|
export { PALISADE_ENTITIES, PALISADE_ACTION_ENTITIES, } from './palisade-entities.gen.js';
|
|
24
28
|
// Service-specific default policies, templates, and categories
|
|
29
|
+
export { GUARDRAILS_DEFAULTS, GUARDRAILS_TEMPLATES, GUARDRAILS_CATEGORIES, GUARDRAILS_TEMPLATES_JSON, getGuardrailsDefaultsByCategory, getGuardrailsTemplatesByCategory, getGuardrailsTemplateById, } from './guardrails-defaults.gen.js';
|
|
25
30
|
export { OVERWATCH_DEFAULTS, OVERWATCH_TEMPLATES, OVERWATCH_CATEGORIES, OVERWATCH_TEMPLATES_JSON, getOverwatchDefaultsByCategory, getOverwatchTemplatesByCategory, getOverwatchTemplateById, } from './overwatch-defaults.gen.js';
|
|
@@ -773,6 +773,86 @@ forbid (
|
|
|
773
773
|
resource
|
|
774
774
|
);
|
|
775
775
|
`;
|
|
776
|
+
const OVERWATCH_TOOLS_MCP_TOOL_PERMISSIONS_CEDAR = `// =============================================================================
|
|
777
|
+
// MCP Tool Permissions Template (Overwatch)
|
|
778
|
+
// =============================================================================
|
|
779
|
+
// Per-tool access control for MCP servers in IDE environments.
|
|
780
|
+
// Complements the existing MCP Server Allowlist (connect_server action)
|
|
781
|
+
// with fine-grained per-tool control on call_tool action.
|
|
782
|
+
//
|
|
783
|
+
// Category: tools
|
|
784
|
+
// Namespace: Overwatch
|
|
785
|
+
// =============================================================================
|
|
786
|
+
|
|
787
|
+
// -- GitHub MCP: Read-only access -------------------------------------------
|
|
788
|
+
|
|
789
|
+
@id("mcp-tool-allow-read-github")
|
|
790
|
+
@name("Allow read-only GitHub tools")
|
|
791
|
+
@description("Permit read operations from GitHub MCP server")
|
|
792
|
+
@severity("medium")
|
|
793
|
+
@tags("mcp,github,read-only,least-privilege")
|
|
794
|
+
permit (
|
|
795
|
+
principal,
|
|
796
|
+
action == Overwatch::Action::"call_tool",
|
|
797
|
+
resource
|
|
798
|
+
) when {
|
|
799
|
+
context has mcp_server && context.mcp_server == "github" &&
|
|
800
|
+
context has tool_name &&
|
|
801
|
+
(context.tool_name == "read_issues" ||
|
|
802
|
+
context.tool_name == "get_issue" ||
|
|
803
|
+
context.tool_name == "list_repos" ||
|
|
804
|
+
context.tool_name == "get_pull_request" ||
|
|
805
|
+
context.tool_name == "search_code" ||
|
|
806
|
+
context.tool_name == "get_file_contents")
|
|
807
|
+
};
|
|
808
|
+
|
|
809
|
+
@id("mcp-tool-deny-write-github")
|
|
810
|
+
@name("Deny write GitHub tools")
|
|
811
|
+
@description("Block create/update/delete operations on GitHub MCP server")
|
|
812
|
+
@severity("high")
|
|
813
|
+
@tags("mcp,github,write-block,least-privilege")
|
|
814
|
+
forbid (
|
|
815
|
+
principal,
|
|
816
|
+
action == Overwatch::Action::"call_tool",
|
|
817
|
+
resource
|
|
818
|
+
) when {
|
|
819
|
+
context has mcp_server && context.mcp_server == "github"
|
|
820
|
+
};
|
|
821
|
+
|
|
822
|
+
// -- Organization-wide MCP server exclusions --------------------------------
|
|
823
|
+
|
|
824
|
+
@id("mcp-tool-exclude-server")
|
|
825
|
+
@name("Exclude specific MCP servers")
|
|
826
|
+
@description("Block all tool calls from excluded MCP servers (org-wide exclusion list)")
|
|
827
|
+
@severity("critical")
|
|
828
|
+
@tags("mcp,exclusion,org-wide,block")
|
|
829
|
+
forbid (
|
|
830
|
+
principal,
|
|
831
|
+
action == Overwatch::Action::"call_tool",
|
|
832
|
+
resource
|
|
833
|
+
) when {
|
|
834
|
+
// Add server names to block across the organization.
|
|
835
|
+
// Modify this list to match your exclusion requirements.
|
|
836
|
+
context has mcp_server &&
|
|
837
|
+
(context.mcp_server == "untrusted-server" ||
|
|
838
|
+
context.mcp_server == "deprecated-server")
|
|
839
|
+
};
|
|
840
|
+
|
|
841
|
+
// -- Block unverified MCP servers -------------------------------------------
|
|
842
|
+
|
|
843
|
+
@id("mcp-tool-block-unverified")
|
|
844
|
+
@name("Block tools from unverified MCP servers")
|
|
845
|
+
@description("Deny tool calls from MCP servers not in the verified registry")
|
|
846
|
+
@severity("high")
|
|
847
|
+
@tags("mcp,trust,verification")
|
|
848
|
+
forbid (
|
|
849
|
+
principal,
|
|
850
|
+
action == Overwatch::Action::"call_tool",
|
|
851
|
+
resource
|
|
852
|
+
) when {
|
|
853
|
+
context has mcp_server_verified && context.mcp_server_verified == false
|
|
854
|
+
};
|
|
855
|
+
`;
|
|
776
856
|
const OVERWATCH_ORG_DEFAULT_DENY_CEDAR = `// Default Deny All Template
|
|
777
857
|
// Organization-wide baseline: deny all unless explicitly permitted
|
|
778
858
|
// Category: organization
|
|
@@ -978,6 +1058,15 @@ export const OVERWATCH_TEMPLATES = [
|
|
|
978
1058
|
severity: 'medium',
|
|
979
1059
|
tags: ['mcp', 'allowlist', 'whitelist'],
|
|
980
1060
|
},
|
|
1061
|
+
{
|
|
1062
|
+
id: 'tools-mcp-tool-permissions',
|
|
1063
|
+
name: 'MCP Tool Permissions',
|
|
1064
|
+
description: 'Per-tool access control for MCP servers — allow specific tools while denying others, exclude servers org-wide, block unverified sources',
|
|
1065
|
+
category: 'tools',
|
|
1066
|
+
cedarText: OVERWATCH_TOOLS_MCP_TOOL_PERMISSIONS_CEDAR,
|
|
1067
|
+
severity: 'high',
|
|
1068
|
+
tags: ['mcp', 'tools', 'least-privilege', 'per-server', 'exclusion'],
|
|
1069
|
+
},
|
|
981
1070
|
{
|
|
982
1071
|
id: 'org-default-deny',
|
|
983
1072
|
name: 'Default Deny All',
|
|
@@ -1142,6 +1231,15 @@ export const OVERWATCH_TEMPLATES_JSON = `{
|
|
|
1142
1231
|
"severity": "medium",
|
|
1143
1232
|
"tags": ["mcp", "allowlist", "whitelist"]
|
|
1144
1233
|
},
|
|
1234
|
+
{
|
|
1235
|
+
"id": "tools-mcp-tool-permissions",
|
|
1236
|
+
"name": "MCP Tool Permissions",
|
|
1237
|
+
"description": "Per-tool access control for MCP servers — allow specific tools while denying others, exclude servers org-wide, block unverified sources",
|
|
1238
|
+
"category": "tools",
|
|
1239
|
+
"file": "mcp_tool_permissions.cedar",
|
|
1240
|
+
"severity": "high",
|
|
1241
|
+
"tags": ["mcp", "tools", "least-privilege", "per-server", "exclusion"]
|
|
1242
|
+
},
|
|
1145
1243
|
{
|
|
1146
1244
|
"id": "org-default-deny",
|
|
1147
1245
|
"name": "Default Deny All",
|
package/dist/parser.js
CHANGED
|
@@ -134,11 +134,14 @@ function cedarJsonToRule(policy, policyId, index, originalText) {
|
|
|
134
134
|
order: index,
|
|
135
135
|
};
|
|
136
136
|
// Map conditions
|
|
137
|
-
const { conditions, rawCondition } = mapConditions(policy.conditions, originalText);
|
|
137
|
+
const { conditions, rawCondition, conditionExpression } = mapConditions(policy.conditions, originalText);
|
|
138
138
|
rule.conditions = conditions;
|
|
139
139
|
if (rawCondition) {
|
|
140
140
|
rule.rawCondition = rawCondition;
|
|
141
141
|
}
|
|
142
|
+
if (conditionExpression) {
|
|
143
|
+
rule.conditionExpression = conditionExpression;
|
|
144
|
+
}
|
|
142
145
|
return { rule };
|
|
143
146
|
}
|
|
144
147
|
catch (e) {
|
|
@@ -227,7 +230,7 @@ function mapScopeToEntity(scope, field) {
|
|
|
227
230
|
if (scope.op === "in") {
|
|
228
231
|
if ("entity" in scope) {
|
|
229
232
|
const entity = normalizeEntityRef(scope.entity);
|
|
230
|
-
return { type: entity.type, id: entity.id };
|
|
233
|
+
return { type: entity.type, id: entity.id, operator: 'in' };
|
|
231
234
|
}
|
|
232
235
|
if ("slot" in scope) {
|
|
233
236
|
throw ParserError.scopeSlotNotSupported("in", field);
|
|
@@ -279,17 +282,20 @@ function mapActionScope(scope) {
|
|
|
279
282
|
throw ParserError.actionUnsupportedOp(scope.op);
|
|
280
283
|
}
|
|
281
284
|
/**
|
|
282
|
-
* Map Cedar conditions to PolicyCondition array.
|
|
283
|
-
* When conditions can't be mapped to
|
|
285
|
+
* Map Cedar conditions to PolicyCondition array + recursive ConditionExpression.
|
|
286
|
+
* When conditions can't be mapped to the flat format, extract the raw Cedar
|
|
284
287
|
* condition text from the engine-serialized policy text (not JSON AST).
|
|
285
288
|
*/
|
|
286
289
|
function mapConditions(conditions, originalText) {
|
|
287
290
|
const result = [];
|
|
288
291
|
let hasUnmapped = false;
|
|
292
|
+
// Collect condition expressions from all when clauses
|
|
293
|
+
const expressions = [];
|
|
289
294
|
for (const cond of conditions) {
|
|
290
295
|
if (cond.kind !== "when") {
|
|
291
296
|
continue;
|
|
292
297
|
}
|
|
298
|
+
// Flat mapping (backward compat)
|
|
293
299
|
const parsed = mapConditionBody(cond.body);
|
|
294
300
|
if (parsed.condition) {
|
|
295
301
|
result.push(parsed.condition);
|
|
@@ -297,15 +303,26 @@ function mapConditions(conditions, originalText) {
|
|
|
297
303
|
else if (parsed.raw) {
|
|
298
304
|
hasUnmapped = true;
|
|
299
305
|
}
|
|
306
|
+
// Recursive mapping (new)
|
|
307
|
+
expressions.push(mapConditionBodyToExpression(cond.body, originalText));
|
|
300
308
|
}
|
|
301
309
|
// Extract readable Cedar condition text instead of storing JSON AST
|
|
302
310
|
let rawCondition;
|
|
303
311
|
if (hasUnmapped && originalText) {
|
|
304
312
|
rawCondition = extractWhenClause(originalText);
|
|
305
313
|
}
|
|
314
|
+
// Build the final condition expression
|
|
315
|
+
let conditionExpression;
|
|
316
|
+
if (expressions.length === 1) {
|
|
317
|
+
conditionExpression = expressions[0];
|
|
318
|
+
}
|
|
319
|
+
else if (expressions.length > 1) {
|
|
320
|
+
conditionExpression = { kind: 'and', children: expressions };
|
|
321
|
+
}
|
|
306
322
|
return {
|
|
307
323
|
conditions: result,
|
|
308
324
|
rawCondition: rawCondition || undefined,
|
|
325
|
+
conditionExpression,
|
|
309
326
|
};
|
|
310
327
|
}
|
|
311
328
|
/**
|
|
@@ -365,6 +382,121 @@ function mapConditionBody(body) {
|
|
|
365
382
|
// Can't map - return as raw JSON
|
|
366
383
|
return { raw: JSON.stringify(body) };
|
|
367
384
|
}
|
|
385
|
+
// ---------------------------------------------------------------------------
|
|
386
|
+
// Recursive condition expression walker
|
|
387
|
+
// ---------------------------------------------------------------------------
|
|
388
|
+
/**
|
|
389
|
+
* Recursively walk the Cedar JSON AST to build a ConditionExpression tree.
|
|
390
|
+
* Flattens binary && / || chains into n-ary and/or nodes.
|
|
391
|
+
*/
|
|
392
|
+
function mapConditionBodyToExpression(expr, originalText) {
|
|
393
|
+
// Logical AND — flatten binary chain
|
|
394
|
+
if (expr["&&"]) {
|
|
395
|
+
const children = flattenBinaryChain("&&", expr);
|
|
396
|
+
return { kind: 'and', children };
|
|
397
|
+
}
|
|
398
|
+
// Logical OR — flatten binary chain
|
|
399
|
+
if (expr["||"]) {
|
|
400
|
+
const children = flattenBinaryChain("||", expr);
|
|
401
|
+
return { kind: 'or', children };
|
|
402
|
+
}
|
|
403
|
+
// Negation
|
|
404
|
+
if (expr["!"]) {
|
|
405
|
+
const child = mapConditionBodyToExpression(expr["!"].arg, originalText);
|
|
406
|
+
return { kind: 'not', child };
|
|
407
|
+
}
|
|
408
|
+
// Has (existence check): { has: { left: { Var: "context" }, attr: "field" } }
|
|
409
|
+
if (expr.has) {
|
|
410
|
+
const field = extractHasField(expr.has);
|
|
411
|
+
if (field) {
|
|
412
|
+
return { kind: 'has', field };
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
// Leaf: comparison operators
|
|
416
|
+
for (const op of ["==", "!=", "<", "<=", ">", ">="]) {
|
|
417
|
+
const comparison = expr[op];
|
|
418
|
+
if (comparison) {
|
|
419
|
+
const mapped = mapComparisonToExpression(op, comparison);
|
|
420
|
+
if (mapped)
|
|
421
|
+
return mapped;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
// Leaf: contains
|
|
425
|
+
if (expr.contains) {
|
|
426
|
+
const mapped = mapContainsToExpression(expr.contains);
|
|
427
|
+
if (mapped)
|
|
428
|
+
return mapped;
|
|
429
|
+
}
|
|
430
|
+
// Leaf: like
|
|
431
|
+
if (expr.like) {
|
|
432
|
+
const mapped = mapLikeToExpression(expr.like);
|
|
433
|
+
if (mapped)
|
|
434
|
+
return mapped;
|
|
435
|
+
}
|
|
436
|
+
// Fallback — extract readable text if possible
|
|
437
|
+
const text = originalText ? extractWhenClause(originalText) : JSON.stringify(expr);
|
|
438
|
+
return { kind: 'raw', text };
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Flatten a binary chain of && or || into a flat array of expressions.
|
|
442
|
+
* (A && B) && C becomes [A, B, C] instead of nested binary pairs.
|
|
443
|
+
*/
|
|
444
|
+
function flattenBinaryChain(op, expr) {
|
|
445
|
+
const node = expr[op];
|
|
446
|
+
if (!node)
|
|
447
|
+
return [mapConditionBodyToExpression(expr)];
|
|
448
|
+
return [
|
|
449
|
+
...flattenBinaryChain(op, node.left),
|
|
450
|
+
...flattenBinaryChain(op, node.right),
|
|
451
|
+
];
|
|
452
|
+
}
|
|
453
|
+
/**
|
|
454
|
+
* Extract field name from a "has" expression.
|
|
455
|
+
* Pattern: { left: { Var: "context" }, attr: "field_name" }
|
|
456
|
+
*/
|
|
457
|
+
function extractHasField(has) {
|
|
458
|
+
if (has.left.Var === "context") {
|
|
459
|
+
return has.attr;
|
|
460
|
+
}
|
|
461
|
+
return null;
|
|
462
|
+
}
|
|
463
|
+
function mapComparisonToExpression(op, args) {
|
|
464
|
+
const field = extractContextField(args.left);
|
|
465
|
+
if (!field)
|
|
466
|
+
return null;
|
|
467
|
+
const value = extractLiteralValue(args.right);
|
|
468
|
+
if (value === undefined)
|
|
469
|
+
return null;
|
|
470
|
+
const operator = mapOperator(op);
|
|
471
|
+
if (!operator)
|
|
472
|
+
return null;
|
|
473
|
+
return { kind: 'comparison', field, operator, value };
|
|
474
|
+
}
|
|
475
|
+
function mapContainsToExpression(args) {
|
|
476
|
+
const field = extractContextField(args.left);
|
|
477
|
+
if (!field)
|
|
478
|
+
return null;
|
|
479
|
+
const value = extractLiteralValue(args.right);
|
|
480
|
+
if (value === undefined || typeof value === 'object')
|
|
481
|
+
return null;
|
|
482
|
+
return { kind: 'contains', field, value: value };
|
|
483
|
+
}
|
|
484
|
+
function mapLikeToExpression(args) {
|
|
485
|
+
const field = extractContextField(args.left);
|
|
486
|
+
if (!field)
|
|
487
|
+
return null;
|
|
488
|
+
const patternStr = args.pattern.map(p => {
|
|
489
|
+
if (p === "Wildcard")
|
|
490
|
+
return "*";
|
|
491
|
+
if (typeof p === "object" && "Literal" in p)
|
|
492
|
+
return p.Literal.replace(/\*/g, "\\*");
|
|
493
|
+
return "";
|
|
494
|
+
}).join("");
|
|
495
|
+
return { kind: 'like', field, pattern: patternStr };
|
|
496
|
+
}
|
|
497
|
+
// ---------------------------------------------------------------------------
|
|
498
|
+
// Flat condition mapping (backward compat)
|
|
499
|
+
// ---------------------------------------------------------------------------
|
|
368
500
|
function mapComparison(op, args) {
|
|
369
501
|
const field = extractContextField(args.left);
|
|
370
502
|
if (!field)
|
package/dist/schema.gen.d.ts
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
* Embedded Cedar schema for policy validation.
|
|
3
3
|
* This is the Highflame Cedar schema used across all services.
|
|
4
4
|
*/
|
|
5
|
-
export declare const CEDAR_SCHEMA = "// Highflame Cedar Schema - Entity and Action Definitions\n// =======================================================\n// This file defines all entity types and actions used across Highflame services.\n// Used for code generation (EntityType and ActionType constants).\n//\n// For policy validation, use service-specific schemas:\n// - schemas/overwatch/schema.cedarschema (Guardian IDE security)\n// - schemas/palisade/schema.cedarschema (ML supply chain security)\n\nnamespace Highflame {\n\n// =============================================================================\n// ENTITIES\n// =============================================================================\n\nentity User {\n user_type: String,\n};\n\nentity Agent {\n agent_type: String,\n};\n\nentity Scanner {\n scanner_type: String,\n};\n\nentity Service {\n service_type: String,\n};\n\nentity Resource {};\n\nentity LlmPrompt {\n prompt_type: String,\n};\n\nentity ResponseData {};\n\nentity Tool {\n tool_name: String,\n};\n\nentity FilePath {\n path: String,\n};\n\nentity HttpEndpoint {\n hostname: String,\n};\n\nentity Server {\n server_name: String,\n};\n\nentity Artifact {\n artifact_format: String,\n};\n\nentity Repository {\n repo_url: String,\n};\n\nentity Package {\n package_name: String,\n};\n\nentity GitBranch {\n branch_name: String,\n};\n\nentity Model {\n model_name: String,\n};\n\nentity ExternalAPI {\n api_name: String,\n};\n\nentity Memory {\n memory_type: String,\n};\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\naction process_prompt;\naction process_response;\naction invoke_model;\naction filter_content;\naction call_tool;\naction connect_server;\naction access_server_resource;\naction skip_guardrails;\naction read_file;\naction write_file;\naction delete_file;\naction http_request;\naction call_external_api;\naction execute_code;\naction run_tests;\naction run_build;\naction git_operation;\naction git_clone;\naction git_commit;\naction git_push;\naction git_pull;\naction git_merge;\naction git_checkout;\naction git_reset;\naction git_rebase;\naction delegate_task;\naction spawn_subprocess;\naction access_memory;\naction scan_target;\naction scan_package;\naction scan_artifact;\naction validate_integrity;\naction validate_provenance;\naction quarantine_artifact;\naction load_model;\naction deploy_model;\naction transfer_data;\naction export_data;\n}\n";
|
|
5
|
+
export declare const CEDAR_SCHEMA = "// Highflame Cedar Schema - Entity and Action Definitions\n// =======================================================\n// This file defines all entity types and actions used across Highflame services.\n// Used for code generation (EntityType and ActionType constants).\n//\n// For policy validation, use service-specific schemas:\n// - schemas/overwatch/schema.cedarschema (Guardian IDE security)\n// - schemas/palisade/schema.cedarschema (ML supply chain security)\n\nnamespace Highflame {\n\n// =============================================================================\n// ENTITIES\n// =============================================================================\n\n// Multi-tenant hierarchy (used by services for ReBAC policy scoping)\nentity Account {};\nentity Project {};\nentity App {};\nentity Session {};\n\nentity User {\n user_type: String,\n};\n\nentity Agent {\n agent_type: String,\n};\n\nentity Scanner {\n scanner_type: String,\n};\n\nentity Service {\n service_type: String,\n};\n\nentity Resource {};\n\nentity LlmPrompt {\n prompt_type: String,\n};\n\nentity ResponseData {};\n\nentity Tool {\n tool_name: String,\n};\n\nentity FilePath {\n path: String,\n};\n\nentity HttpEndpoint {\n hostname: String,\n};\n\nentity Server {\n server_name: String,\n};\n\nentity Artifact {\n artifact_format: String,\n};\n\nentity Repository {\n repo_url: String,\n};\n\nentity Package {\n package_name: String,\n};\n\nentity GitBranch {\n branch_name: String,\n};\n\nentity Model {\n model_name: String,\n};\n\nentity ExternalAPI {\n api_name: String,\n};\n\nentity Memory {\n memory_type: String,\n};\n\n// =============================================================================\n// ACTIONS\n// =============================================================================\n\naction process_prompt;\naction process_response;\naction invoke_model;\naction filter_content;\naction call_tool;\naction connect_server;\naction access_server_resource;\naction skip_guardrails;\naction read_file;\naction write_file;\naction delete_file;\naction http_request;\naction call_external_api;\naction execute_code;\naction run_tests;\naction run_build;\naction git_operation;\naction git_clone;\naction git_commit;\naction git_push;\naction git_pull;\naction git_merge;\naction git_checkout;\naction git_reset;\naction git_rebase;\naction delegate_task;\naction spawn_subprocess;\naction access_memory;\naction scan_target;\naction scan_package;\naction scan_artifact;\naction validate_integrity;\naction validate_provenance;\naction quarantine_artifact;\naction load_model;\naction deploy_model;\naction transfer_data;\naction export_data;\n}\n";
|
package/dist/schema.gen.js
CHANGED
|
@@ -19,6 +19,12 @@ namespace Highflame {
|
|
|
19
19
|
// ENTITIES
|
|
20
20
|
// =============================================================================
|
|
21
21
|
|
|
22
|
+
// Multi-tenant hierarchy (used by services for ReBAC policy scoping)
|
|
23
|
+
entity Account {};
|
|
24
|
+
entity Project {};
|
|
25
|
+
entity App {};
|
|
26
|
+
entity Session {};
|
|
27
|
+
|
|
22
28
|
entity User {
|
|
23
29
|
user_type: String,
|
|
24
30
|
};
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Guardrails Cedar schema
|
|
3
|
+
*
|
|
4
|
+
* Full Cedar schema for guardrails, embedded at codegen time.
|
|
5
|
+
*/
|
|
6
|
+
export declare const GUARDRAILS_SCHEMA = "// =============================================================================\n// Guardrails Cedar Schema\n// =============================================================================\n// Defines entity types, actions, and context attributes for the highflame-shield\n// guardrails service. This schema enables type-safe policy authoring and\n// validation in both Studio UI and backend.\n//\n// Service: highflame-shield (guardrails)\n// Namespace: Guardrails\n// =============================================================================\n\nnamespace Guardrails {\n // =========================================================================\n // Entity Types \u2014 ReBAC Hierarchy\n // =========================================================================\n // Entity hierarchy enables Cedar's `in` operator for policy scoping:\n // Account (org root)\n // \u2514\u2500\u2500 Project in [Account]\n // \u2514\u2500\u2500 App in [Project]\n // \u2514\u2500\u2500 Session in [App]\n //\n // Policy scoping examples:\n // resource == Guardrails::App::\"<uuid>\" \u2192 app-scoped\n // resource in Guardrails::Project::\"<uuid>\" \u2192 project-wide\n // resource in Guardrails::Account::\"<uuid>\" \u2192 org-wide\n // =========================================================================\n\n /// Account represents an organization (top-level tenant)\n entity Account;\n\n /// Project represents a project within an account\n entity Project in [Account];\n\n /// User represents a principal (human or service) making requests\n entity User;\n\n /// Agent represents an AI agent (Claude, Cursor, Copilot, etc.) making requests\n entity Agent;\n\n /// App represents a protected application (guardrails-enabled LLM app)\n entity App in [Project];\n\n /// Session represents an agentic conversation session with state tracking\n entity Session in [App];\n\n // =========================================================================\n // Actions\n // =========================================================================\n\n /// Process user prompts and AI responses for security threats and content violations\n action \"process_prompt\" appliesTo {\n principal: [User, Agent],\n resource: [App, Session],\n context: ProcessPromptContext\n };\n\n /// Execute tool calls (shell, file operations, MCP tools)\n action \"call_tool\" appliesTo {\n principal: [User, Agent],\n resource: [Session],\n context: CallToolContext\n };\n\n /// Read file operations\n action \"read_file\" appliesTo {\n principal: [User, Agent],\n resource: [Session],\n context: FileReadContext\n };\n\n /// Write file operations\n action \"write_file\" appliesTo {\n principal: [User, Agent],\n resource: [Session],\n context: FileWriteContext\n };\n\n /// Connect to an MCP server\n action \"connect_server\" appliesTo {\n principal: [User, Agent],\n resource: [Session],\n context: ConnectServerContext\n };\n\n // =========================================================================\n // Context Types (Action-Specific)\n // =========================================================================\n\n /// Context for process_prompt action (user prompts & AI responses)\n type ProcessPromptContext = {\n // Core metadata (required)\n \"request_id\": String,\n \"timestamp\": Long,\n \"direction\": String, // \"input\" | \"output\"\n \"content_type\": String, // \"prompt\" | \"response\" | \"tool_call\" | \"file\"\n \"detector_count\": Long,\n\n // Security - Injection & Jailbreak (optional)\n \"injection_score\"?: Long, // 0-100\n \"jailbreak_score\"?: Long, // 0-100\n \"injection_type\"?: String, // \"prompt\" | \"sql\" | \"command\" | \"none\"\n\n // Privacy - Secrets (optional)\n \"contains_secrets\"?: Bool,\n \"secret_count\"?: Long,\n \"secret_types\"?: Set<String>, // [\"aws_access_key\", \"github_token\", ...]\n\n // Privacy - PII (optional)\n \"pii_detected\"?: Bool,\n \"pii_count\"?: Long,\n \"pii_types\"?: Set<String>, // [\"email\", \"phone\", \"ssn\", \"credit_card\", ...]\n\n // Trust & Safety - Toxicity (optional)\n \"violence_score\"?: Long, // 0-100\n \"hate_speech_score\"?: Long, // 0-100\n \"sexual_score\"?: Long, // 0-100\n \"weapons_score\"?: Long, // 0-100\n \"crime_score\"?: Long, // 0-100\n \"profanity_score\"?: Long, // 0-100\n\n // Semantic - Topic Classification (optional)\n \"content_topics\"?: Set<String>, // [\"controlled_substances\", \"weapons_manufacturing\", ...]\n \"topic_confidence\"?: Long, // 0-100\n\n // Security - Invisible Character Detection (optional)\n \"contains_invisible_chars\"?: Bool,\n \"invisible_chars_score\"?: Long, // 0-100\n\n // Additional detectors (optional)\n \"hallucination_score\"?: Long,\n \"sentiment_score\"?: Long,\n \"contains_code\"?: Bool,\n \"code_languages\"?: Set<String>,\n \"keyword_matched\"?: Bool,\n \"keyword_categories\"?: Set<String>,\n \"detected_language\"?: String,\n \"phishing_detected\"?: Bool,\n\n };\n\n /// Context for call_tool action (agentic tool execution)\n type CallToolContext = {\n // Core metadata (required)\n \"request_id\": String,\n \"timestamp\": Long,\n\n // Tool Risk (optional)\n \"tool_name\"?: String, // \"shell\", \"write_file\", \"http_post\", etc.\n \"tool_risk_score\"?: Long, // 0-100\n \"tool_is_sensitive\"?: Bool,\n \"tool_category\"?: String, // \"safe\" | \"sensitive\" | \"dangerous\"\n \"tool_is_builtin\"?: Bool,\n\n // MCP context (optional \u2014 only present for MCP tool calls)\n \"mcp_server\"?: String, // MCP server name (e.g., \"github\", \"filesystem\")\n \"mcp_tool\"?: String, // MCP tool name within the server\n \"mcp_server_verified\"?: Bool, // Whether server is from verified registry\n\n // Agentic - Behavioral Patterns (optional)\n \"suspicious_pattern\"?: Bool,\n \"pattern_type\"?: String, // \"data_exfiltration\" | \"secret_exfiltration\" | \"db_exfiltration\" | \"none\"\n \"sequence_risk\"?: Long, // 0-100\n\n // Agentic - Loop Detection (optional)\n \"loop_detected\"?: Bool,\n \"loop_count\"?: Long,\n \"loop_tool\"?: String,\n\n // Agentic - Budget Control (optional)\n \"budget_remaining_pct\"?: Long, // 0-100\n \"budget_exceeded\"?: Bool,\n\n // Semantic - Topic Classification (optional)\n \"content_topics\"?: Set<String>, // [\"controlled_substances\", \"weapons_manufacturing\", ...]\n \"topic_confidence\"?: Long, // 0-100\n\n // Security checks on tool arguments (optional)\n \"contains_secrets\"?: Bool,\n \"secret_types\"?: Set<String>,\n \"pii_detected\"?: Bool,\n \"pii_types\"?: Set<String>,\n \"injection_score\"?: Long,\n\n };\n\n /// Context for read_file action\n type FileReadContext = {\n // Core metadata (required)\n \"request_id\": String,\n \"timestamp\": Long,\n\n // Security checks on file content (optional)\n \"contains_secrets\"?: Bool,\n \"secret_types\"?: Set<String>,\n \"pii_detected\"?: Bool,\n \"pii_types\"?: Set<String>,\n\n };\n\n /// Context for write_file action\n type FileWriteContext = {\n // Core metadata (required)\n \"request_id\": String,\n \"timestamp\": Long,\n\n // Security checks on content being written (optional)\n \"contains_secrets\"?: Bool,\n \"secret_types\"?: Set<String>,\n \"pii_detected\"?: Bool,\n \"pii_types\"?: Set<String>,\n\n };\n\n /// Context for connect_server action (MCP server connections)\n type ConnectServerContext = {\n // Core metadata (required)\n \"request_id\": String,\n \"timestamp\": Long,\n\n // MCP context (optional)\n \"mcp_server\"?: String, // MCP server name (e.g., \"github\", \"filesystem\")\n \"mcp_server_verified\"?: Bool, // Whether server is from verified registry\n\n };\n}\n";
|
|
1
7
|
/**
|
|
2
8
|
* Overwatch Cedar schema
|
|
3
9
|
*
|
|
@@ -31,6 +37,10 @@ export interface ServiceContext {
|
|
|
31
37
|
description: string;
|
|
32
38
|
actions: ActionContext[];
|
|
33
39
|
}
|
|
40
|
+
/**
|
|
41
|
+
* Guardrails context metadata (parsed JSON)
|
|
42
|
+
*/
|
|
43
|
+
export declare const GUARDRAILS_CONTEXT: ServiceContext;
|
|
34
44
|
/**
|
|
35
45
|
* Overwatch context metadata (parsed JSON)
|
|
36
46
|
*/
|