@provos/ironcurtain 0.1.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.
- package/LICENSE +202 -0
- package/README.md +311 -0
- package/dist/agent/index.d.ts +10 -0
- package/dist/agent/index.js +71 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/prompts.d.ts +5 -0
- package/dist/agent/prompts.js +26 -0
- package/dist/agent/prompts.js.map +1 -0
- package/dist/agent/tools.d.ts +13 -0
- package/dist/agent/tools.js +51 -0
- package/dist/agent/tools.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +78 -0
- package/dist/cli.js.map +1 -0
- package/dist/config/constitution.md +16 -0
- package/dist/config/generated/compiled-policy.json +236 -0
- package/dist/config/generated/test-scenarios.json +765 -0
- package/dist/config/generated/tool-annotations.json +955 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.js +151 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/mcp-servers.json +22 -0
- package/dist/config/model-provider.d.ts +49 -0
- package/dist/config/model-provider.js +78 -0
- package/dist/config/model-provider.js.map +1 -0
- package/dist/config/paths.d.ts +59 -0
- package/dist/config/paths.js +96 -0
- package/dist/config/paths.js.map +1 -0
- package/dist/config/types.d.ts +89 -0
- package/dist/config/types.js +2 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config/user-config.d.ts +93 -0
- package/dist/config/user-config.js +309 -0
- package/dist/config/user-config.js.map +1 -0
- package/dist/hash.d.ts +17 -0
- package/dist/hash.js +34 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +11 -0
- package/dist/logger.js +93 -0
- package/dist/logger.js.map +1 -0
- package/dist/pipeline/annotate.d.ts +9 -0
- package/dist/pipeline/annotate.js +136 -0
- package/dist/pipeline/annotate.js.map +1 -0
- package/dist/pipeline/compile.d.ts +23 -0
- package/dist/pipeline/compile.js +386 -0
- package/dist/pipeline/compile.js.map +1 -0
- package/dist/pipeline/constitution-compiler.d.ts +22 -0
- package/dist/pipeline/constitution-compiler.js +197 -0
- package/dist/pipeline/constitution-compiler.js.map +1 -0
- package/dist/pipeline/generate-with-repair.d.ts +22 -0
- package/dist/pipeline/generate-with-repair.js +64 -0
- package/dist/pipeline/generate-with-repair.js.map +1 -0
- package/dist/pipeline/handwritten-scenarios.d.ts +9 -0
- package/dist/pipeline/handwritten-scenarios.js +321 -0
- package/dist/pipeline/handwritten-scenarios.js.map +1 -0
- package/dist/pipeline/llm-logger.d.ts +42 -0
- package/dist/pipeline/llm-logger.js +78 -0
- package/dist/pipeline/llm-logger.js.map +1 -0
- package/dist/pipeline/pipeline-shared.d.ts +47 -0
- package/dist/pipeline/pipeline-shared.js +145 -0
- package/dist/pipeline/pipeline-shared.js.map +1 -0
- package/dist/pipeline/policy-verifier.d.ts +46 -0
- package/dist/pipeline/policy-verifier.js +277 -0
- package/dist/pipeline/policy-verifier.js.map +1 -0
- package/dist/pipeline/scenario-generator.d.ts +11 -0
- package/dist/pipeline/scenario-generator.js +128 -0
- package/dist/pipeline/scenario-generator.js.map +1 -0
- package/dist/pipeline/tool-annotator.d.ts +24 -0
- package/dist/pipeline/tool-annotator.js +201 -0
- package/dist/pipeline/tool-annotator.js.map +1 -0
- package/dist/pipeline/types.d.ts +122 -0
- package/dist/pipeline/types.js +10 -0
- package/dist/pipeline/types.js.map +1 -0
- package/dist/sandbox/index.d.ts +39 -0
- package/dist/sandbox/index.js +178 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/session/agent-session.d.ts +83 -0
- package/dist/session/agent-session.js +382 -0
- package/dist/session/agent-session.js.map +1 -0
- package/dist/session/cli-transport.d.ts +61 -0
- package/dist/session/cli-transport.js +320 -0
- package/dist/session/cli-transport.js.map +1 -0
- package/dist/session/errors.d.ts +19 -0
- package/dist/session/errors.js +33 -0
- package/dist/session/errors.js.map +1 -0
- package/dist/session/index.d.ts +29 -0
- package/dist/session/index.js +104 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/message-compactor.d.ts +32 -0
- package/dist/session/message-compactor.js +81 -0
- package/dist/session/message-compactor.js.map +1 -0
- package/dist/session/prompts.d.ts +5 -0
- package/dist/session/prompts.js +62 -0
- package/dist/session/prompts.js.map +1 -0
- package/dist/session/resource-budget-tracker.d.ts +124 -0
- package/dist/session/resource-budget-tracker.js +327 -0
- package/dist/session/resource-budget-tracker.js.map +1 -0
- package/dist/session/step-loop-detector.d.ts +63 -0
- package/dist/session/step-loop-detector.js +136 -0
- package/dist/session/step-loop-detector.js.map +1 -0
- package/dist/session/transport.d.ts +24 -0
- package/dist/session/transport.js +2 -0
- package/dist/session/transport.js.map +1 -0
- package/dist/session/truncate-result.d.ts +35 -0
- package/dist/session/truncate-result.js +71 -0
- package/dist/session/truncate-result.js.map +1 -0
- package/dist/session/types.d.ts +220 -0
- package/dist/session/types.js +6 -0
- package/dist/session/types.js.map +1 -0
- package/dist/trusted-process/audit-log.d.ts +7 -0
- package/dist/trusted-process/audit-log.js +21 -0
- package/dist/trusted-process/audit-log.js.map +1 -0
- package/dist/trusted-process/call-circuit-breaker.d.ts +33 -0
- package/dist/trusted-process/call-circuit-breaker.js +61 -0
- package/dist/trusted-process/call-circuit-breaker.js.map +1 -0
- package/dist/trusted-process/escalation.d.ts +7 -0
- package/dist/trusted-process/escalation.js +38 -0
- package/dist/trusted-process/escalation.js.map +1 -0
- package/dist/trusted-process/index.d.ts +32 -0
- package/dist/trusted-process/index.js +151 -0
- package/dist/trusted-process/index.js.map +1 -0
- package/dist/trusted-process/mcp-client-manager.d.ts +25 -0
- package/dist/trusted-process/mcp-client-manager.js +90 -0
- package/dist/trusted-process/mcp-client-manager.js.map +1 -0
- package/dist/trusted-process/mcp-proxy-server.d.ts +24 -0
- package/dist/trusted-process/mcp-proxy-server.js +451 -0
- package/dist/trusted-process/mcp-proxy-server.js.map +1 -0
- package/dist/trusted-process/path-utils.d.ts +50 -0
- package/dist/trusted-process/path-utils.js +158 -0
- package/dist/trusted-process/path-utils.js.map +1 -0
- package/dist/trusted-process/policy-engine.d.ts +88 -0
- package/dist/trusted-process/policy-engine.js +523 -0
- package/dist/trusted-process/policy-engine.js.map +1 -0
- package/dist/trusted-process/policy-roots.d.ts +50 -0
- package/dist/trusted-process/policy-roots.js +67 -0
- package/dist/trusted-process/policy-roots.js.map +1 -0
- package/dist/trusted-process/policy-types.d.ts +6 -0
- package/dist/trusted-process/policy-types.js +2 -0
- package/dist/trusted-process/policy-types.js.map +1 -0
- package/dist/trusted-process/sandbox-integration.d.ts +92 -0
- package/dist/trusted-process/sandbox-integration.js +184 -0
- package/dist/trusted-process/sandbox-integration.js.map +1 -0
- package/dist/types/argument-roles.d.ts +112 -0
- package/dist/types/argument-roles.js +344 -0
- package/dist/types/argument-roles.js.map +1 -0
- package/dist/types/audit.d.ts +18 -0
- package/dist/types/audit.js +2 -0
- package/dist/types/audit.js.map +1 -0
- package/dist/types/mcp.d.ts +20 -0
- package/dist/types/mcp.js +2 -0
- package/dist/types/mcp.js.map +1 -0
- package/package.json +83 -0
- package/src/config/constitution.md +16 -0
- package/src/config/generated/compiled-policy.json +236 -0
- package/src/config/generated/test-scenarios.json +765 -0
- package/src/config/generated/tool-annotations.json +955 -0
- package/src/config/mcp-servers.json +22 -0
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constitution Compiler -- LLM-driven compilation of English-language
|
|
3
|
+
* constitution principles into enforceable declarative policy rules.
|
|
4
|
+
*
|
|
5
|
+
* The compiler takes the constitution text, tool annotations, and system
|
|
6
|
+
* config (concrete directory paths) and produces an ordered rule chain
|
|
7
|
+
* that faithfully implements the non-structural principles.
|
|
8
|
+
*/
|
|
9
|
+
import { z } from 'zod';
|
|
10
|
+
import { generateObjectWithRepair } from './generate-with-repair.js';
|
|
11
|
+
import { isArgumentRole, getArgumentRoleValues } from '../types/argument-roles.js';
|
|
12
|
+
import { formatExecutionResults } from './policy-verifier.js';
|
|
13
|
+
const pathConditionSchema = z.object({
|
|
14
|
+
roles: z.array(z.enum(getArgumentRoleValues())),
|
|
15
|
+
within: z.string(),
|
|
16
|
+
});
|
|
17
|
+
const domainConditionSchema = z.object({
|
|
18
|
+
roles: z.array(z.enum(getArgumentRoleValues())),
|
|
19
|
+
allowed: z.array(z.string()),
|
|
20
|
+
});
|
|
21
|
+
function buildCompilerResponseSchema(serverNames, toolNames) {
|
|
22
|
+
const compiledRuleSchema = z.object({
|
|
23
|
+
name: z.string(),
|
|
24
|
+
description: z.string(),
|
|
25
|
+
principle: z.string(),
|
|
26
|
+
if: z.object({
|
|
27
|
+
roles: z.array(z.enum(getArgumentRoleValues())).optional(),
|
|
28
|
+
server: z.array(z.enum(serverNames)).optional(),
|
|
29
|
+
tool: z.array(z.enum(toolNames)).optional(),
|
|
30
|
+
sideEffects: z.boolean().optional(),
|
|
31
|
+
paths: pathConditionSchema.optional(),
|
|
32
|
+
domains: domainConditionSchema.optional(),
|
|
33
|
+
}),
|
|
34
|
+
then: z.enum(['allow', 'deny', 'escalate']),
|
|
35
|
+
reason: z.string(),
|
|
36
|
+
});
|
|
37
|
+
return z.object({
|
|
38
|
+
rules: z.array(compiledRuleSchema),
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
export function buildCompilerPrompt(constitutionText, annotations, config) {
|
|
42
|
+
const annotationsSummary = annotations.map(a => {
|
|
43
|
+
const argsDesc = Object.entries(a.args)
|
|
44
|
+
.map(([name, roles]) => ` ${name}: [${roles.join(', ')}]`)
|
|
45
|
+
.join('\n');
|
|
46
|
+
return ` ${a.serverName}/${a.toolName}: ${a.comment}, sideEffects=${a.sideEffects}\n args:\n${argsDesc || ' (none)'}`;
|
|
47
|
+
}).join('\n');
|
|
48
|
+
return `You are compiling a security policy from a constitution document into enforceable declarative rules.
|
|
49
|
+
|
|
50
|
+
## Constitution
|
|
51
|
+
|
|
52
|
+
${constitutionText}
|
|
53
|
+
|
|
54
|
+
## Tool Annotations
|
|
55
|
+
|
|
56
|
+
These are the available tools and their classified capabilities:
|
|
57
|
+
|
|
58
|
+
${annotationsSummary}
|
|
59
|
+
|
|
60
|
+
## Structural Invariants (handled automatically by the engine -- do NOT generate rules for these)
|
|
61
|
+
|
|
62
|
+
The following checks are hardcoded and evaluated BEFORE compiled rules:
|
|
63
|
+
|
|
64
|
+
1. **Protected paths** -- any read, write, or delete targeting these paths is automatically denied:
|
|
65
|
+
${config.protectedPaths.map(p => `- ${p}`).join('\n')}
|
|
66
|
+
|
|
67
|
+
2. **Sandbox containment** -- any tool call where ALL paths are within the sandbox directory is automatically allowed. Do NOT generate rules for sandbox-internal operations; the engine handles this at runtime with the dynamically configured sandbox path.
|
|
68
|
+
|
|
69
|
+
## Instructions
|
|
70
|
+
|
|
71
|
+
Produce an ORDERED list of policy rules (first match wins). Each rule has:
|
|
72
|
+
- "name": a kebab-case identifier
|
|
73
|
+
- "description": what the rule does
|
|
74
|
+
- "principle": which constitution principle this implements
|
|
75
|
+
- "if": conditions that must ALL be true for the rule to fire:
|
|
76
|
+
- "roles": array of argument roles to match. The rule fires if the tool has ANY argument with ANY of these roles. Use this for blanket rules (e.g., deny all tools with delete-path arguments). Omit = any tool.
|
|
77
|
+
- "server": array of server names (omit = any server)
|
|
78
|
+
- "tool": array of specific tool names (omit = any matching tool)
|
|
79
|
+
- "sideEffects": match on the tool's sideEffects annotation (omit = don't filter)
|
|
80
|
+
- "paths": path condition with "roles" (which argument roles to extract paths from) and "within" (concrete absolute directory). Rule fires only if ALL extracted paths are within that directory. If zero paths are extracted (tool has no matching path arguments), the condition is NOT satisfied and the rule does NOT match. This implicitly requires matching roles, so top-level "roles" is redundant when "paths" is present.
|
|
81
|
+
- "domains": domain condition with "roles" (which URL argument roles to extract domains from) and "allowed" (list of allowed domain patterns, e.g. ["github.com", "*.github.com"]). Rule fires only if ALL extracted domains match an allowed pattern. Supports exact match, "*.example.com" prefix wildcards, and "*" (any domain). If zero URLs are extracted, the condition is NOT satisfied and the rule does NOT match.
|
|
82
|
+
- "then": the policy decision:
|
|
83
|
+
- "allow" — the operation is explicitly permitted by the constitution
|
|
84
|
+
- "deny" — the operation is categorically forbidden by the constitution (absolute prohibition)
|
|
85
|
+
- "escalate" — the operation is not explicitly permitted but also not forbidden; route to a human for approval
|
|
86
|
+
- "reason": human-readable explanation
|
|
87
|
+
|
|
88
|
+
CRITICAL RULES:
|
|
89
|
+
1. Do NOT generate rules for protected path checking, unknown tool denial, or sandbox containment -- those are handled by structural invariants in the engine.
|
|
90
|
+
2. Use CONCRETE ABSOLUTE paths (e.g., "/home/user/Downloads"), not abstract labels.
|
|
91
|
+
3. "Outside a directory" semantics: use rule ordering. A rule with "within" matches the inside case; the next rule without "paths" catches everything else as a fallthrough.
|
|
92
|
+
4. The move tool's source argument has both read-path and delete-path roles. A blanket "roles": ["delete-path"] rule will catch all moves.
|
|
93
|
+
5. Order matters: more specific rules before more general ones.
|
|
94
|
+
6. Use all three decision types. Map each constitution principle to the appropriate decision: "allow" for grants, "deny" for prohibitions, and "escalate" for principles that require human judgment or approval. If the constitution does not explicitly forbid an operation, prefer "escalate" over "deny" so a human can decide.
|
|
95
|
+
7. The rule chain must cover all operation types with appropriate fallthrough rules. Do not leave gaps — every combination of argument roles should eventually match a rule.
|
|
96
|
+
|
|
97
|
+
Be concise in descriptions and reasons -- one sentence each.`;
|
|
98
|
+
}
|
|
99
|
+
export function buildRepairPrompt(basePrompt, repairContext) {
|
|
100
|
+
const rulesText = repairContext.previousRules
|
|
101
|
+
.map((r, i) => ` ${i + 1}. [${r.name}] if: ${JSON.stringify(r.if)} then: ${r.then} -- ${r.reason}`)
|
|
102
|
+
.join('\n');
|
|
103
|
+
const failuresText = formatExecutionResults(repairContext.failedScenarios);
|
|
104
|
+
return `${basePrompt}
|
|
105
|
+
|
|
106
|
+
## REPAIR INSTRUCTIONS (attempt ${repairContext.attemptNumber})
|
|
107
|
+
|
|
108
|
+
Your previous compilation produced rules that failed verification. You MUST fix these issues.
|
|
109
|
+
|
|
110
|
+
### Previous Rules
|
|
111
|
+
|
|
112
|
+
${rulesText}
|
|
113
|
+
|
|
114
|
+
### Failed Scenarios
|
|
115
|
+
|
|
116
|
+
${failuresText}
|
|
117
|
+
|
|
118
|
+
### Judge Analysis
|
|
119
|
+
|
|
120
|
+
${repairContext.judgeAnalysis}
|
|
121
|
+
|
|
122
|
+
### Requirements
|
|
123
|
+
|
|
124
|
+
1. Fix the rule ordering, conditions, or add missing rules to make ALL failed scenarios pass.
|
|
125
|
+
2. Do NOT break scenarios that were already passing — only fix the failures.
|
|
126
|
+
3. Pay close attention to the judge analysis for specific guidance on what went wrong.
|
|
127
|
+
4. Return a complete, corrected rule set (not just the changed rules).`;
|
|
128
|
+
}
|
|
129
|
+
export async function compileConstitution(constitutionText, annotations, config, llm, repairContext, onProgress) {
|
|
130
|
+
const serverNames = [...new Set(annotations.map(a => a.serverName))];
|
|
131
|
+
const toolNames = [...new Set(annotations.map(a => a.toolName))];
|
|
132
|
+
const schema = buildCompilerResponseSchema(serverNames, toolNames);
|
|
133
|
+
const basePrompt = buildCompilerPrompt(constitutionText, annotations, config);
|
|
134
|
+
const prompt = repairContext
|
|
135
|
+
? buildRepairPrompt(basePrompt, repairContext)
|
|
136
|
+
: basePrompt;
|
|
137
|
+
const { output } = await generateObjectWithRepair({
|
|
138
|
+
model: llm,
|
|
139
|
+
schema,
|
|
140
|
+
prompt,
|
|
141
|
+
onProgress,
|
|
142
|
+
});
|
|
143
|
+
return output.rules;
|
|
144
|
+
}
|
|
145
|
+
export function validateCompiledRules(rules) {
|
|
146
|
+
const errors = [];
|
|
147
|
+
const warnings = [];
|
|
148
|
+
for (const rule of rules) {
|
|
149
|
+
// Validate top-level roles
|
|
150
|
+
if (rule.if.roles) {
|
|
151
|
+
for (const role of rule.if.roles) {
|
|
152
|
+
if (!isArgumentRole(role)) {
|
|
153
|
+
errors.push(`Rule "${rule.name}": invalid role "${role}" in roles`);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
// Validate path roles
|
|
158
|
+
if (rule.if.paths) {
|
|
159
|
+
for (const role of rule.if.paths.roles) {
|
|
160
|
+
if (!isArgumentRole(role)) {
|
|
161
|
+
errors.push(`Rule "${rule.name}": invalid role "${role}" in paths.roles`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
// Validate within is an absolute path
|
|
165
|
+
if (!rule.if.paths.within.startsWith('/')) {
|
|
166
|
+
errors.push(`Rule "${rule.name}": paths.within must be an absolute path, got "${rule.if.paths.within}"`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
// Validate domain roles
|
|
170
|
+
if (rule.if.domains) {
|
|
171
|
+
for (const role of rule.if.domains.roles) {
|
|
172
|
+
if (!isArgumentRole(role)) {
|
|
173
|
+
errors.push(`Rule "${rule.name}": invalid role "${role}" in domains.roles`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
if (rule.if.domains.allowed.length === 0) {
|
|
177
|
+
warnings.push(`Rule "${rule.name}": domains.allowed is empty (condition will never match)`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
// Check for structural invariant concepts that should not be compiled
|
|
181
|
+
const lowerName = rule.name.toLowerCase();
|
|
182
|
+
const lowerDesc = rule.description.toLowerCase();
|
|
183
|
+
if (lowerName.includes('protected') ||
|
|
184
|
+
lowerName.includes('structural') ||
|
|
185
|
+
lowerName.includes('unknown-tool') ||
|
|
186
|
+
lowerDesc.includes('protected path') ||
|
|
187
|
+
lowerDesc.includes('unknown tool')) {
|
|
188
|
+
errors.push(`Rule "${rule.name}": appears to implement a structural invariant -- these must not be in compiled rules`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return {
|
|
192
|
+
valid: errors.length === 0,
|
|
193
|
+
errors,
|
|
194
|
+
warnings,
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=constitution-compiler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constitution-compiler.js","sourceRoot":"","sources":["../../src/pipeline/constitution-compiler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-turn LLM repair for schema validation failures.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `generateText` with `Output.object`. On schema validation failure
|
|
5
|
+
* (NoObjectGeneratedError), feeds the Zod error back to the LLM in a
|
|
6
|
+
* multi-turn conversation so it can fix its output.
|
|
7
|
+
*/
|
|
8
|
+
import type { LanguageModel } from 'ai';
|
|
9
|
+
import type { z } from 'zod';
|
|
10
|
+
interface GenerateObjectWithRepairOptions<T extends z.ZodType> {
|
|
11
|
+
model: LanguageModel;
|
|
12
|
+
schema: T;
|
|
13
|
+
prompt: string;
|
|
14
|
+
maxRepairAttempts?: number;
|
|
15
|
+
maxOutputTokens?: number;
|
|
16
|
+
onProgress?: (message: string) => void;
|
|
17
|
+
}
|
|
18
|
+
export declare function generateObjectWithRepair<T extends z.ZodType>({ model, schema, prompt, maxRepairAttempts, maxOutputTokens, onProgress, }: GenerateObjectWithRepairOptions<T>): Promise<{
|
|
19
|
+
output: z.infer<T>;
|
|
20
|
+
repairAttempts: number;
|
|
21
|
+
}>;
|
|
22
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-turn LLM repair for schema validation failures.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `generateText` with `Output.object`. On schema validation failure
|
|
5
|
+
* (NoObjectGeneratedError), feeds the Zod error back to the LLM in a
|
|
6
|
+
* multi-turn conversation so it can fix its output.
|
|
7
|
+
*/
|
|
8
|
+
import { generateText, NoObjectGeneratedError, Output } from 'ai';
|
|
9
|
+
const DEFAULT_MAX_TOKENS = 8192;
|
|
10
|
+
function formatValidationError(cause) {
|
|
11
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
12
|
+
}
|
|
13
|
+
export async function generateObjectWithRepair({ model, schema, prompt, maxRepairAttempts = 2, maxOutputTokens = DEFAULT_MAX_TOKENS, onProgress, }) {
|
|
14
|
+
// First attempt: simple prompt-based call
|
|
15
|
+
try {
|
|
16
|
+
const result = await generateText({
|
|
17
|
+
model,
|
|
18
|
+
output: Output.object({ schema }),
|
|
19
|
+
prompt,
|
|
20
|
+
maxOutputTokens,
|
|
21
|
+
});
|
|
22
|
+
return { output: result.output, repairAttempts: 0 };
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (!NoObjectGeneratedError.isInstance(error))
|
|
26
|
+
throw error;
|
|
27
|
+
if (maxRepairAttempts <= 0)
|
|
28
|
+
throw error;
|
|
29
|
+
// Build multi-turn conversation for repair
|
|
30
|
+
const messages = [
|
|
31
|
+
{ role: 'user', content: prompt },
|
|
32
|
+
{ role: 'assistant', content: error.text ?? '' },
|
|
33
|
+
{
|
|
34
|
+
role: 'user',
|
|
35
|
+
content: `Your response failed schema validation:\n${formatValidationError(error.cause)}\n\nPlease fix the errors and return valid JSON matching the schema.`,
|
|
36
|
+
},
|
|
37
|
+
];
|
|
38
|
+
let lastError = error;
|
|
39
|
+
for (let attempt = 0; attempt < maxRepairAttempts; attempt++) {
|
|
40
|
+
onProgress?.(`Schema repair ${attempt + 1}/${maxRepairAttempts}...`);
|
|
41
|
+
try {
|
|
42
|
+
const result = await generateText({
|
|
43
|
+
model,
|
|
44
|
+
output: Output.object({ schema }),
|
|
45
|
+
messages,
|
|
46
|
+
maxOutputTokens,
|
|
47
|
+
});
|
|
48
|
+
return { output: result.output, repairAttempts: attempt + 1 };
|
|
49
|
+
}
|
|
50
|
+
catch (retryError) {
|
|
51
|
+
if (!NoObjectGeneratedError.isInstance(retryError))
|
|
52
|
+
throw retryError;
|
|
53
|
+
lastError = retryError;
|
|
54
|
+
// Append the failed response and error for next attempt
|
|
55
|
+
messages.push({ role: 'assistant', content: retryError.text ?? '' }, {
|
|
56
|
+
role: 'user',
|
|
57
|
+
content: `Still failing schema validation:\n${formatValidationError(retryError.cause)}\n\nPlease fix the errors and return valid JSON matching the schema.`,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
throw lastError;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=generate-with-repair.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate-with-repair.js","sourceRoot":"","sources":["../../src/pipeline/generate-with-repair.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAGlE,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,SAAS,qBAAqB,CAAC,KAAc;IAC3C,OAAO,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAChE,CAAC;AAWD,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAsB,EAClE,KAAK,EACL,MAAM,EACN,MAAM,EACN,iBAAiB,GAAG,CAAC,EACrB,eAAe,GAAG,kBAAkB,EACpC,UAAU,GACyB;IACnC,0CAA0C;IAC1C,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;YAChC,KAAK;YACL,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;YACjC,MAAM;YACN,eAAe;SAChB,CAAC,CAAC;QACH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAoB,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC;IACpE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,KAAK,CAAC;YAAE,MAAM,KAAK,CAAC;QAC3D,IAAI,iBAAiB,IAAI,CAAC;YAAE,MAAM,KAAK,CAAC;QAExC,2CAA2C;QAC3C,MAAM,QAAQ,GAA2D;YACvE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE;YACjC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE;YAChD;gBACE,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,4CAA4C,qBAAqB,CAAC,KAAK,CAAC,KAAK,CAAC,sEAAsE;aAC9J;SACF,CAAC;QAEF,IAAI,SAAS,GAAY,KAAK,CAAC;QAE/B,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,GAAG,iBAAiB,EAAE,OAAO,EAAE,EAAE,CAAC;YAC7D,UAAU,EAAE,CAAC,iBAAiB,OAAO,GAAG,CAAC,IAAI,iBAAiB,KAAK,CAAC,CAAC;YACrE,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;oBAChC,KAAK;oBACL,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;oBACjC,QAAQ;oBACR,eAAe;iBAChB,CAAC,CAAC;gBACH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,MAAoB,EAAE,cAAc,EAAE,OAAO,GAAG,CAAC,EAAE,CAAC;YAC9E,CAAC;YAAC,OAAO,UAAU,EAAE,CAAC;gBACpB,IAAI,CAAC,sBAAsB,CAAC,UAAU,CAAC,UAAU,CAAC;oBAAE,MAAM,UAAU,CAAC;gBACrE,SAAS,GAAG,UAAU,CAAC;gBAEvB,wDAAwD;gBACxD,QAAQ,CAAC,IAAI,CACX,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,CAAC,IAAI,IAAI,EAAE,EAAE,EACrD;oBACE,IAAI,EAAE,MAAM;oBACZ,OAAO,EAAE,qCAAqC,qBAAqB,CAAC,UAAU,CAAC,KAAK,CAAC,sEAAsE;iBAC5J,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,MAAM,SAAS,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mandatory handwritten test scenarios derived from existing policy engine tests.
|
|
3
|
+
*
|
|
4
|
+
* These provide human-authored ground truth that the verifier always checks,
|
|
5
|
+
* mitigating circular reasoning where the compiler and scenario generator
|
|
6
|
+
* share the same blind spots.
|
|
7
|
+
*/
|
|
8
|
+
import type { TestScenario } from './types.js';
|
|
9
|
+
export declare function getHandwrittenScenarios(sandboxDir: string): TestScenario[];
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mandatory handwritten test scenarios derived from existing policy engine tests.
|
|
3
|
+
*
|
|
4
|
+
* These provide human-authored ground truth that the verifier always checks,
|
|
5
|
+
* mitigating circular reasoning where the compiler and scenario generator
|
|
6
|
+
* share the same blind spots.
|
|
7
|
+
*/
|
|
8
|
+
export function getHandwrittenScenarios(sandboxDir) {
|
|
9
|
+
return [
|
|
10
|
+
// Read operations
|
|
11
|
+
{
|
|
12
|
+
description: 'Read file inside sandbox -- allow',
|
|
13
|
+
request: {
|
|
14
|
+
serverName: 'filesystem',
|
|
15
|
+
toolName: 'read_file',
|
|
16
|
+
arguments: { path: `${sandboxDir}/test.txt` },
|
|
17
|
+
},
|
|
18
|
+
expectedDecision: 'allow',
|
|
19
|
+
reasoning: 'Containment principle: reads within the sandbox directory are permitted',
|
|
20
|
+
source: 'handwritten',
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
description: 'Read file outside sandbox -- escalate',
|
|
24
|
+
request: {
|
|
25
|
+
serverName: 'filesystem',
|
|
26
|
+
toolName: 'read_file',
|
|
27
|
+
arguments: { path: '/etc/passwd' },
|
|
28
|
+
},
|
|
29
|
+
expectedDecision: 'escalate',
|
|
30
|
+
reasoning: 'Human oversight principle: reads outside the sandbox require human approval',
|
|
31
|
+
source: 'handwritten',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
description: 'List directory inside sandbox -- allow',
|
|
35
|
+
request: {
|
|
36
|
+
serverName: 'filesystem',
|
|
37
|
+
toolName: 'list_directory',
|
|
38
|
+
arguments: { path: sandboxDir },
|
|
39
|
+
},
|
|
40
|
+
expectedDecision: 'allow',
|
|
41
|
+
reasoning: 'Containment principle: listing the sandbox directory is permitted',
|
|
42
|
+
source: 'handwritten',
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
description: 'Search files inside sandbox -- allow',
|
|
46
|
+
request: {
|
|
47
|
+
serverName: 'filesystem',
|
|
48
|
+
toolName: 'search_files',
|
|
49
|
+
arguments: { path: sandboxDir, pattern: '*.txt' },
|
|
50
|
+
},
|
|
51
|
+
expectedDecision: 'allow',
|
|
52
|
+
reasoning: 'Containment principle: searching within the sandbox is permitted',
|
|
53
|
+
source: 'handwritten',
|
|
54
|
+
},
|
|
55
|
+
// Write operations
|
|
56
|
+
{
|
|
57
|
+
description: 'Write file inside sandbox -- allow',
|
|
58
|
+
request: {
|
|
59
|
+
serverName: 'filesystem',
|
|
60
|
+
toolName: 'write_file',
|
|
61
|
+
arguments: { path: `${sandboxDir}/output.txt`, content: 'hello' },
|
|
62
|
+
},
|
|
63
|
+
expectedDecision: 'allow',
|
|
64
|
+
reasoning: 'Containment principle: writes within the sandbox directory are permitted',
|
|
65
|
+
source: 'handwritten',
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
description: 'Write file outside sandbox -- escalate',
|
|
69
|
+
request: {
|
|
70
|
+
serverName: 'filesystem',
|
|
71
|
+
toolName: 'write_file',
|
|
72
|
+
arguments: { path: '/etc/test.txt', content: 'hello' },
|
|
73
|
+
},
|
|
74
|
+
expectedDecision: 'escalate',
|
|
75
|
+
reasoning: 'Human oversight principle: writes outside permitted areas require human approval',
|
|
76
|
+
source: 'handwritten',
|
|
77
|
+
},
|
|
78
|
+
// Delete operations
|
|
79
|
+
{
|
|
80
|
+
description: 'Delete file inside sandbox -- allow (structural sandbox invariant)',
|
|
81
|
+
request: {
|
|
82
|
+
serverName: 'filesystem',
|
|
83
|
+
toolName: 'delete_file',
|
|
84
|
+
arguments: { path: `${sandboxDir}/test.txt` },
|
|
85
|
+
},
|
|
86
|
+
expectedDecision: 'allow',
|
|
87
|
+
reasoning: 'Structural sandbox invariant: all paths are within the sandbox, auto-allowed before unknown-tool and compiled-rule checks',
|
|
88
|
+
source: 'handwritten',
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
description: 'Delete file outside sandbox -- deny',
|
|
92
|
+
request: {
|
|
93
|
+
serverName: 'filesystem',
|
|
94
|
+
toolName: 'delete_file',
|
|
95
|
+
arguments: { path: '/etc/important.txt' },
|
|
96
|
+
},
|
|
97
|
+
expectedDecision: 'deny',
|
|
98
|
+
reasoning: 'No destruction principle: delete operations are never permitted',
|
|
99
|
+
source: 'handwritten',
|
|
100
|
+
},
|
|
101
|
+
// Path traversal
|
|
102
|
+
{
|
|
103
|
+
description: 'Path traversal attempt -- escalate',
|
|
104
|
+
request: {
|
|
105
|
+
serverName: 'filesystem',
|
|
106
|
+
toolName: 'read_file',
|
|
107
|
+
arguments: { path: `${sandboxDir}/../../../etc/passwd` },
|
|
108
|
+
},
|
|
109
|
+
expectedDecision: 'escalate',
|
|
110
|
+
reasoning: 'Human oversight principle: path traversal resolves outside sandbox, requires human approval',
|
|
111
|
+
source: 'handwritten',
|
|
112
|
+
},
|
|
113
|
+
// Move operations (move_file source has read-path + delete-path, destination has write-path)
|
|
114
|
+
{
|
|
115
|
+
description: 'Move file sandbox-to-sandbox -- allow (structural sandbox invariant)',
|
|
116
|
+
request: {
|
|
117
|
+
serverName: 'filesystem',
|
|
118
|
+
toolName: 'move_file',
|
|
119
|
+
arguments: {
|
|
120
|
+
source: `${sandboxDir}/a.txt`,
|
|
121
|
+
destination: `${sandboxDir}/b.txt`,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
expectedDecision: 'allow',
|
|
125
|
+
reasoning: 'Structural sandbox invariant: all paths are within the sandbox, auto-allowed before compiled rules',
|
|
126
|
+
source: 'handwritten',
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
description: 'Move file sandbox-to-external -- escalate (source sandbox-resolved, write-path escalated)',
|
|
130
|
+
request: {
|
|
131
|
+
serverName: 'filesystem',
|
|
132
|
+
toolName: 'move_file',
|
|
133
|
+
arguments: {
|
|
134
|
+
source: `${sandboxDir}/a.txt`,
|
|
135
|
+
destination: '/tmp/outside/b.txt',
|
|
136
|
+
},
|
|
137
|
+
},
|
|
138
|
+
expectedDecision: 'escalate',
|
|
139
|
+
reasoning: 'Source roles (read-path, delete-path) are sandbox-resolved. Only write-path on external destination is evaluated → escalate.',
|
|
140
|
+
source: 'handwritten',
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
description: 'Move file external-to-sandbox -- deny (source has delete-path)',
|
|
144
|
+
request: {
|
|
145
|
+
serverName: 'filesystem',
|
|
146
|
+
toolName: 'move_file',
|
|
147
|
+
arguments: {
|
|
148
|
+
source: '/etc/important.txt',
|
|
149
|
+
destination: `${sandboxDir}/important.txt`,
|
|
150
|
+
},
|
|
151
|
+
},
|
|
152
|
+
expectedDecision: 'deny',
|
|
153
|
+
reasoning: 'No destruction: move_file source has delete-path role, caught by deny-delete-operations',
|
|
154
|
+
source: 'handwritten',
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
description: 'Move file external-to-external -- deny (source has delete-path)',
|
|
158
|
+
request: {
|
|
159
|
+
serverName: 'filesystem',
|
|
160
|
+
toolName: 'move_file',
|
|
161
|
+
arguments: {
|
|
162
|
+
source: '/etc/a.txt',
|
|
163
|
+
destination: '/tmp/outside/b.txt',
|
|
164
|
+
},
|
|
165
|
+
},
|
|
166
|
+
expectedDecision: 'deny',
|
|
167
|
+
reasoning: 'No destruction: move_file source has delete-path role, caught by deny-delete-operations',
|
|
168
|
+
source: 'handwritten',
|
|
169
|
+
},
|
|
170
|
+
// Side-effect-free tool
|
|
171
|
+
{
|
|
172
|
+
description: 'list_allowed_directories (side-effect-free) -- allow',
|
|
173
|
+
request: {
|
|
174
|
+
serverName: 'filesystem',
|
|
175
|
+
toolName: 'list_allowed_directories',
|
|
176
|
+
arguments: {},
|
|
177
|
+
},
|
|
178
|
+
expectedDecision: 'allow',
|
|
179
|
+
reasoning: 'Least privilege: no side effects, no path arguments, safe to allow',
|
|
180
|
+
source: 'handwritten',
|
|
181
|
+
},
|
|
182
|
+
// Unknown tool
|
|
183
|
+
{
|
|
184
|
+
description: 'Unknown tool -- deny (structural invariant)',
|
|
185
|
+
request: {
|
|
186
|
+
serverName: 'filesystem',
|
|
187
|
+
toolName: 'execute_command',
|
|
188
|
+
arguments: { command: 'rm -rf /' },
|
|
189
|
+
},
|
|
190
|
+
expectedDecision: 'deny',
|
|
191
|
+
reasoning: 'Structural invariant: unknown tools with no annotation are denied',
|
|
192
|
+
source: 'handwritten',
|
|
193
|
+
},
|
|
194
|
+
// ── Git read operations in sandbox → allow ────────────────────────
|
|
195
|
+
{
|
|
196
|
+
description: 'Git status in sandbox -- allow',
|
|
197
|
+
request: {
|
|
198
|
+
serverName: 'git',
|
|
199
|
+
toolName: 'git_status',
|
|
200
|
+
arguments: { path: sandboxDir },
|
|
201
|
+
},
|
|
202
|
+
expectedDecision: 'allow',
|
|
203
|
+
reasoning: 'Read-only git operation within the sandbox is allowed by containment principle',
|
|
204
|
+
source: 'handwritten',
|
|
205
|
+
},
|
|
206
|
+
{
|
|
207
|
+
description: 'Git log in sandbox -- allow',
|
|
208
|
+
request: {
|
|
209
|
+
serverName: 'git',
|
|
210
|
+
toolName: 'git_log',
|
|
211
|
+
arguments: { path: sandboxDir },
|
|
212
|
+
},
|
|
213
|
+
expectedDecision: 'allow',
|
|
214
|
+
reasoning: 'Read-only git operation within the sandbox is allowed by containment principle',
|
|
215
|
+
source: 'handwritten',
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
description: 'Git diff in sandbox -- allow',
|
|
219
|
+
request: {
|
|
220
|
+
serverName: 'git',
|
|
221
|
+
toolName: 'git_diff',
|
|
222
|
+
arguments: { path: sandboxDir },
|
|
223
|
+
},
|
|
224
|
+
expectedDecision: 'allow',
|
|
225
|
+
reasoning: 'Read-only git operation within the sandbox is allowed by containment principle',
|
|
226
|
+
source: 'handwritten',
|
|
227
|
+
},
|
|
228
|
+
// ── Git write operations in sandbox → allow ───────────────────────
|
|
229
|
+
{
|
|
230
|
+
description: 'Git add in sandbox -- allow',
|
|
231
|
+
request: {
|
|
232
|
+
serverName: 'git',
|
|
233
|
+
toolName: 'git_add',
|
|
234
|
+
arguments: { path: sandboxDir, files: ['test.txt'] },
|
|
235
|
+
},
|
|
236
|
+
expectedDecision: 'allow',
|
|
237
|
+
reasoning: 'Staging files within the sandbox is allowed by containment principle',
|
|
238
|
+
source: 'handwritten',
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
description: 'Git commit in sandbox -- allow',
|
|
242
|
+
request: {
|
|
243
|
+
serverName: 'git',
|
|
244
|
+
toolName: 'git_commit',
|
|
245
|
+
arguments: { path: sandboxDir, message: 'test commit' },
|
|
246
|
+
},
|
|
247
|
+
expectedDecision: 'allow',
|
|
248
|
+
reasoning: 'Committing within the sandbox is allowed by containment principle',
|
|
249
|
+
source: 'handwritten',
|
|
250
|
+
},
|
|
251
|
+
// ── Git remote/destructive operations → escalate ──────────────────
|
|
252
|
+
{
|
|
253
|
+
description: 'Git push from sandbox -- escalate',
|
|
254
|
+
request: {
|
|
255
|
+
serverName: 'git',
|
|
256
|
+
toolName: 'git_push',
|
|
257
|
+
arguments: { path: sandboxDir, remote: 'origin' },
|
|
258
|
+
},
|
|
259
|
+
expectedDecision: 'escalate',
|
|
260
|
+
reasoning: 'Push is a remote-contacting operation that requires human approval',
|
|
261
|
+
source: 'handwritten',
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
description: 'Git pull to sandbox -- escalate',
|
|
265
|
+
request: {
|
|
266
|
+
serverName: 'git',
|
|
267
|
+
toolName: 'git_pull',
|
|
268
|
+
arguments: { path: sandboxDir, remote: 'origin' },
|
|
269
|
+
},
|
|
270
|
+
expectedDecision: 'escalate',
|
|
271
|
+
reasoning: 'Pull is a remote-contacting operation that requires human approval',
|
|
272
|
+
source: 'handwritten',
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
description: 'Git reset in sandbox -- escalate',
|
|
276
|
+
request: {
|
|
277
|
+
serverName: 'git',
|
|
278
|
+
toolName: 'git_reset',
|
|
279
|
+
arguments: { path: sandboxDir, mode: 'hard' },
|
|
280
|
+
},
|
|
281
|
+
expectedDecision: 'escalate',
|
|
282
|
+
reasoning: 'Reset is a history-rewriting operation that requires human approval',
|
|
283
|
+
source: 'handwritten',
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
description: 'Git merge in sandbox -- escalate',
|
|
287
|
+
request: {
|
|
288
|
+
serverName: 'git',
|
|
289
|
+
toolName: 'git_merge',
|
|
290
|
+
arguments: { path: sandboxDir, branch: 'feature' },
|
|
291
|
+
},
|
|
292
|
+
expectedDecision: 'escalate',
|
|
293
|
+
reasoning: 'Merge is a history-rewriting operation that requires human approval',
|
|
294
|
+
source: 'handwritten',
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
description: 'Git branch delete in sandbox -- escalate',
|
|
298
|
+
request: {
|
|
299
|
+
serverName: 'git',
|
|
300
|
+
toolName: 'git_branch',
|
|
301
|
+
arguments: { path: sandboxDir, name: 'old-branch', delete: true },
|
|
302
|
+
},
|
|
303
|
+
expectedDecision: 'escalate',
|
|
304
|
+
reasoning: 'Branch deletion requires human approval',
|
|
305
|
+
source: 'handwritten',
|
|
306
|
+
},
|
|
307
|
+
// ── Unknown git tool → deny ───────────────────────────────────────
|
|
308
|
+
{
|
|
309
|
+
description: 'Unknown git tool -- deny (structural invariant)',
|
|
310
|
+
request: {
|
|
311
|
+
serverName: 'git',
|
|
312
|
+
toolName: 'git_execute_arbitrary',
|
|
313
|
+
arguments: { command: 'rm -rf /' },
|
|
314
|
+
},
|
|
315
|
+
expectedDecision: 'deny',
|
|
316
|
+
reasoning: 'Structural invariant: unknown tools with no annotation are denied',
|
|
317
|
+
source: 'handwritten',
|
|
318
|
+
},
|
|
319
|
+
];
|
|
320
|
+
}
|
|
321
|
+
//# sourceMappingURL=handwritten-scenarios.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handwritten-scenarios.js","sourceRoot":"","sources":["../../src/pipeline/handwritten-scenarios.ts"],"names":[],"mappings":"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"}
|