@buyong/pi-codex-auto-review 0.0.0-stage → 0.2.2
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 +201 -0
- package/NOTICE +12 -0
- package/README.ko.md +85 -0
- package/README.md +84 -2
- package/dist/approval-commands.d.ts +4 -0
- package/dist/approval-commands.js +230 -0
- package/dist/approval-commands.js.map +1 -0
- package/dist/approval-settings.d.ts +9 -0
- package/dist/approval-settings.js +47 -0
- package/dist/approval-settings.js.map +1 -0
- package/dist/approvals.d.ts +73 -0
- package/dist/approvals.js +288 -0
- package/dist/approvals.js.map +1 -0
- package/dist/audit.d.ts +28 -0
- package/dist/audit.js +64 -0
- package/dist/audit.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +99 -0
- package/dist/cli.js.map +1 -0
- package/dist/context-files.d.ts +14 -0
- package/dist/context-files.js +134 -0
- package/dist/context-files.js.map +1 -0
- package/dist/contracts.d.ts +260 -0
- package/dist/contracts.js +168 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.js +191 -0
- package/dist/index.js.map +1 -0
- package/dist/pi-host.d.ts +2 -0
- package/dist/pi-host.js +7 -0
- package/dist/pi-host.js.map +1 -0
- package/dist/policy/domains.d.ts +5 -0
- package/dist/policy/domains.js +28 -0
- package/dist/policy/domains.js.map +1 -0
- package/dist/policy/index.d.ts +55 -0
- package/dist/policy/index.js +521 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/paths.d.ts +5 -0
- package/dist/policy/paths.js +67 -0
- package/dist/policy/paths.js.map +1 -0
- package/dist/policy/rule-engine.d.ts +2 -0
- package/dist/policy/rule-engine.js +283 -0
- package/dist/policy/rule-engine.js.map +1 -0
- package/dist/policy/rule-types.d.ts +30 -0
- package/dist/policy/rule-types.js +2 -0
- package/dist/policy/rule-types.js.map +1 -0
- package/dist/policy/rules-sync.d.ts +1 -0
- package/dist/policy/rules-sync.js +14 -0
- package/dist/policy/rules-sync.js.map +1 -0
- package/dist/policy/rules-worker.d.ts +1 -0
- package/dist/policy/rules-worker.js +14 -0
- package/dist/policy/rules-worker.js.map +1 -0
- package/dist/policy/rules.d.ts +9 -0
- package/dist/policy/rules.js +149 -0
- package/dist/policy/rules.js.map +1 -0
- package/dist/policy/shell.d.ts +14 -0
- package/dist/policy/shell.js +151 -0
- package/dist/policy/shell.js.map +1 -0
- package/dist/policy/starlark/builtins.d.ts +6 -0
- package/dist/policy/starlark/builtins.js +764 -0
- package/dist/policy/starlark/builtins.js.map +1 -0
- package/dist/policy/starlark/evaluator.d.ts +18 -0
- package/dist/policy/starlark/evaluator.js +518 -0
- package/dist/policy/starlark/evaluator.js.map +1 -0
- package/dist/policy/starlark/lexer.d.ts +14 -0
- package/dist/policy/starlark/lexer.js +189 -0
- package/dist/policy/starlark/lexer.js.map +1 -0
- package/dist/policy/starlark/parser.d.ts +140 -0
- package/dist/policy/starlark/parser.js +508 -0
- package/dist/policy/starlark/parser.js.map +1 -0
- package/dist/policy/starlark/validation.d.ts +4 -0
- package/dist/policy/starlark/validation.js +183 -0
- package/dist/policy/starlark/validation.js.map +1 -0
- package/dist/policy/starlark/values.d.ts +46 -0
- package/dist/policy/starlark/values.js +363 -0
- package/dist/policy/starlark/values.js.map +1 -0
- package/dist/reports.d.ts +21 -0
- package/dist/reports.js +78 -0
- package/dist/reports.js.map +1 -0
- package/dist/review/context.d.ts +38 -0
- package/dist/review/context.js +314 -0
- package/dist/review/context.js.map +1 -0
- package/dist/review/investigation.d.ts +39 -0
- package/dist/review/investigation.js +77 -0
- package/dist/review/investigation.js.map +1 -0
- package/dist/review/lifecycle.d.ts +29 -0
- package/dist/review/lifecycle.js +114 -0
- package/dist/review/lifecycle.js.map +1 -0
- package/dist/review/policy.d.ts +4 -0
- package/dist/review/policy.js +37 -0
- package/dist/review/policy.js.map +1 -0
- package/dist/review/upstream-policy.d.ts +2 -0
- package/dist/review/upstream-policy.js +210 -0
- package/dist/review/upstream-policy.js.map +1 -0
- package/dist/review/user-input.d.ts +5 -0
- package/dist/review/user-input.js +54 -0
- package/dist/review/user-input.js.map +1 -0
- package/dist/reviewer.d.ts +55 -0
- package/dist/reviewer.js +336 -0
- package/dist/reviewer.js.map +1 -0
- package/dist/signals.d.ts +10 -0
- package/dist/signals.js +36 -0
- package/dist/signals.js.map +1 -0
- package/dist/startup.d.ts +22 -0
- package/dist/startup.js +198 -0
- package/dist/startup.js.map +1 -0
- package/dist/tools/controller.d.ts +72 -0
- package/dist/tools/controller.js +644 -0
- package/dist/tools/controller.js.map +1 -0
- package/dist/tools/environment.d.ts +2 -0
- package/dist/tools/environment.js +11 -0
- package/dist/tools/environment.js.map +1 -0
- package/dist/tools/executor.d.ts +14 -0
- package/dist/tools/executor.js +92 -0
- package/dist/tools/executor.js.map +1 -0
- package/dist/tools/external.d.ts +31 -0
- package/dist/tools/external.js +35 -0
- package/dist/tools/external.js.map +1 -0
- package/dist/tools/mcp.d.ts +17 -0
- package/dist/tools/mcp.js +317 -0
- package/dist/tools/mcp.js.map +1 -0
- package/dist/tools/mutation-queue.d.ts +1 -0
- package/dist/tools/mutation-queue.js +16 -0
- package/dist/tools/mutation-queue.js.map +1 -0
- package/docs/publishing.ko.md +127 -0
- package/docs/publishing.md +127 -0
- package/docs/security/dependencies.ko.md +54 -0
- package/docs/security/dependencies.md +54 -0
- package/docs/testing/auto-review-protection.ko.md +158 -0
- package/docs/testing/auto-review-protection.md +158 -0
- package/docs/usage.ko.md +242 -0
- package/docs/usage.md +242 -0
- package/package.json +76 -5
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type PermissionProfile } from "./contracts.js";
|
|
2
|
+
import type { GuardSettings } from "./policy/index.js";
|
|
3
|
+
export interface ContextFile {
|
|
4
|
+
readonly path: string;
|
|
5
|
+
readonly content: string;
|
|
6
|
+
}
|
|
7
|
+
/** Codex a956835d/core/src/agents_md.rs precedence, traversal and aggregate byte budget. */
|
|
8
|
+
export declare function loadContextFiles(options: {
|
|
9
|
+
cwd: string;
|
|
10
|
+
agentDir: string;
|
|
11
|
+
profile: PermissionProfile;
|
|
12
|
+
settings: GuardSettings;
|
|
13
|
+
isProjectTrusted: boolean;
|
|
14
|
+
}): ContextFile[];
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { closeSync, constants, fstatSync, openSync, readSync, realpathSync, statSync, } from "node:fs";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
|
+
import { GuardError } from "./contracts.js";
|
|
4
|
+
import { isWithin } from "./policy/paths.js";
|
|
5
|
+
const NAMES = ["AGENTS.override.md", "AGENTS.md"];
|
|
6
|
+
function isMissing(error) {
|
|
7
|
+
return ["ENOENT", "ENOTDIR"].includes(error.code ?? "");
|
|
8
|
+
}
|
|
9
|
+
function isFilename(name) {
|
|
10
|
+
return (!!name &&
|
|
11
|
+
![".", ".."].includes(name) &&
|
|
12
|
+
!name.includes("\0") &&
|
|
13
|
+
basename(name) === name &&
|
|
14
|
+
(process.platform !== "win32" || !/[\\:]/.test(name)));
|
|
15
|
+
}
|
|
16
|
+
function exists(path) {
|
|
17
|
+
try {
|
|
18
|
+
statSync(path);
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
if (isMissing(error))
|
|
23
|
+
return false;
|
|
24
|
+
throw error;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function choose(directory, names) {
|
|
28
|
+
for (const name of names) {
|
|
29
|
+
const path = join(directory, name);
|
|
30
|
+
try {
|
|
31
|
+
if (statSync(path).isFile())
|
|
32
|
+
return path;
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
if (!isMissing(error))
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function boundedRead(path, maxBytes, profile, isGlobal, agentDir) {
|
|
41
|
+
const target = realpathSync(path);
|
|
42
|
+
// Only the specifically selected global instruction file is an internal controller read.
|
|
43
|
+
const isGlobalInstruction = isGlobal &&
|
|
44
|
+
target === join(realpathSync(agentDir), basename(path)) &&
|
|
45
|
+
NAMES.includes(basename(path));
|
|
46
|
+
if (!isGlobalInstruction &&
|
|
47
|
+
(profile.denyRead.some((root) => isWithin(target, root)) ||
|
|
48
|
+
!profile.readRoots.some((root) => isWithin(target, root)))) {
|
|
49
|
+
throw new GuardError("CONTEXT_FILE_DENIED", `Instruction file crosses a protected read boundary: ${path}`);
|
|
50
|
+
}
|
|
51
|
+
const expected = statSync(target);
|
|
52
|
+
if (!expected.isFile() || expected.nlink > 1)
|
|
53
|
+
throw new GuardError("CONTEXT_FILE_DENIED", "Instruction file must be a regular file without hard-link aliases");
|
|
54
|
+
const fd = openSync(target, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
|
|
55
|
+
try {
|
|
56
|
+
const actual = fstatSync(fd);
|
|
57
|
+
if (!actual.isFile() ||
|
|
58
|
+
actual.dev !== expected.dev ||
|
|
59
|
+
actual.ino !== expected.ino ||
|
|
60
|
+
actual.nlink > 1 ||
|
|
61
|
+
realpathSync(path) !== target)
|
|
62
|
+
throw new GuardError("CONTEXT_FILE_CHANGED", "Instruction file changed during loading");
|
|
63
|
+
const data = Buffer.alloc(Math.min(actual.size, maxBytes));
|
|
64
|
+
let count = 0;
|
|
65
|
+
while (count < data.length) {
|
|
66
|
+
const read = readSync(fd, data, count, data.length - count, count);
|
|
67
|
+
if (!read)
|
|
68
|
+
break;
|
|
69
|
+
count += read;
|
|
70
|
+
}
|
|
71
|
+
const content = data.subarray(0, count).toString("utf8");
|
|
72
|
+
return content.trim()
|
|
73
|
+
? { file: { path, content }, bytesRead: count }
|
|
74
|
+
: undefined;
|
|
75
|
+
}
|
|
76
|
+
finally {
|
|
77
|
+
closeSync(fd);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/** Codex a956835d/core/src/agents_md.rs precedence, traversal and aggregate byte budget. */
|
|
81
|
+
export function loadContextFiles(options) {
|
|
82
|
+
const { settings, profile } = options;
|
|
83
|
+
const result = [];
|
|
84
|
+
// The host's agent directory is the Pi equivalent of Codex's instruction home.
|
|
85
|
+
for (const name of NAMES) {
|
|
86
|
+
const global = choose(options.agentDir, [name]);
|
|
87
|
+
if (!global)
|
|
88
|
+
continue;
|
|
89
|
+
const file = boundedRead(global, 32768, profile, true, options.agentDir);
|
|
90
|
+
if (file) {
|
|
91
|
+
result.push(file.file);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!options.isProjectTrusted || settings.projectDocMaxBytes === 0)
|
|
96
|
+
return result;
|
|
97
|
+
const cwd = resolve(options.cwd), markers = (settings.projectRootMarkers ?? [".git"]).filter(isFilename);
|
|
98
|
+
let root;
|
|
99
|
+
for (let dir = cwd; markers.length; dir = dirname(dir)) {
|
|
100
|
+
if (markers.some((name) => exists(join(dir, name)))) {
|
|
101
|
+
root = dir;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
if (dirname(dir) === dir)
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
const directories = [cwd];
|
|
108
|
+
if (root)
|
|
109
|
+
for (let dir = cwd; dir !== root;) {
|
|
110
|
+
dir = dirname(dir);
|
|
111
|
+
directories.unshift(dir);
|
|
112
|
+
}
|
|
113
|
+
const names = [
|
|
114
|
+
...new Set([
|
|
115
|
+
...NAMES,
|
|
116
|
+
...settings.projectDocFallbackFilenames.filter(isFilename),
|
|
117
|
+
]),
|
|
118
|
+
];
|
|
119
|
+
let remaining = settings.projectDocMaxBytes;
|
|
120
|
+
for (const directory of directories) {
|
|
121
|
+
if (!remaining)
|
|
122
|
+
break;
|
|
123
|
+
const path = choose(directory, names);
|
|
124
|
+
if (!path || result.some((file) => file.path === path))
|
|
125
|
+
continue;
|
|
126
|
+
const file = boundedRead(path, remaining, profile, false, options.agentDir);
|
|
127
|
+
if (file) {
|
|
128
|
+
result.push(file.file);
|
|
129
|
+
remaining = Math.max(0, remaining - file.bytesRead);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=context-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-files.js","sourceRoot":"","sources":["../src/context-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import type { ReadToolOptions } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
export type Json = null | boolean | number | string | Json[] | {
|
|
3
|
+
[key: string]: Json;
|
|
4
|
+
};
|
|
5
|
+
export type DecisionKind = "allow" | "ask" | "deny";
|
|
6
|
+
export type ActionSource = "model" | "nested" | "user-bash" | "extension";
|
|
7
|
+
export type EvidenceStatus = "pass" | "fail" | "environment-blocked" | "not-run";
|
|
8
|
+
export type ToolName = "bash" | "read" | "edit" | "write" | "grep" | "find" | "ls";
|
|
9
|
+
export declare const TOOL_NAMES: readonly ToolName[];
|
|
10
|
+
export interface PermissionProfile {
|
|
11
|
+
readonly mode: "read-only" | "workspace-write";
|
|
12
|
+
readonly readRoots: readonly string[];
|
|
13
|
+
readonly writeRoots: readonly string[];
|
|
14
|
+
readonly denyRead: readonly string[];
|
|
15
|
+
readonly denyWrite: readonly string[];
|
|
16
|
+
readonly allowedDomains: readonly string[];
|
|
17
|
+
readonly deniedDomains: readonly string[];
|
|
18
|
+
/** Base sandbox metadata protection; unlike denyWrite, eligible exact actions may request review. */
|
|
19
|
+
readonly readOnlyPaths?: readonly string[];
|
|
20
|
+
}
|
|
21
|
+
export interface PermissionDelta {
|
|
22
|
+
readonly readPaths: readonly string[];
|
|
23
|
+
readonly writePaths: readonly string[];
|
|
24
|
+
readonly domains: readonly string[];
|
|
25
|
+
}
|
|
26
|
+
export declare const EMPTY_DELTA: PermissionDelta;
|
|
27
|
+
export interface GuardAction {
|
|
28
|
+
readonly schemaVersion: 1;
|
|
29
|
+
readonly toolCallId: string;
|
|
30
|
+
readonly tool: string;
|
|
31
|
+
readonly source: ActionSource;
|
|
32
|
+
readonly args: Readonly<Record<string, Json>>;
|
|
33
|
+
readonly cwd: string;
|
|
34
|
+
readonly sessionId: string;
|
|
35
|
+
readonly policyRevision: string;
|
|
36
|
+
readonly permissionDigest: string;
|
|
37
|
+
readonly digest: string;
|
|
38
|
+
}
|
|
39
|
+
export interface PolicyDecision {
|
|
40
|
+
readonly kind: DecisionKind;
|
|
41
|
+
readonly reason: string;
|
|
42
|
+
readonly actionDigest: string;
|
|
43
|
+
readonly delta: PermissionDelta;
|
|
44
|
+
readonly isHardDeny: boolean;
|
|
45
|
+
readonly approvalCategory?: "sandbox" | "rules" | "mcp_elicitations";
|
|
46
|
+
readonly requiresFreshReview?: boolean;
|
|
47
|
+
readonly requiresUserInput?: boolean;
|
|
48
|
+
readonly authority?: ExecutionAuthority;
|
|
49
|
+
}
|
|
50
|
+
export type ApprovalPolicy = "on-request" | "never" | {
|
|
51
|
+
readonly sandbox: boolean;
|
|
52
|
+
readonly rules: boolean;
|
|
53
|
+
readonly mcp_elicitations?: boolean;
|
|
54
|
+
};
|
|
55
|
+
export type RiskLevel = "low" | "medium" | "high" | "critical";
|
|
56
|
+
export type UserAuthorization = "unknown" | "low" | "medium" | "high";
|
|
57
|
+
/** Field names intentionally match the pinned Codex assessment wire format. */
|
|
58
|
+
export interface ReviewAssessment {
|
|
59
|
+
readonly risk_level: RiskLevel;
|
|
60
|
+
readonly user_authorization: UserAuthorization;
|
|
61
|
+
readonly outcome: "allow" | "deny";
|
|
62
|
+
readonly rationale: string;
|
|
63
|
+
}
|
|
64
|
+
export type ReviewTerminalState = "approved" | "denied" | "timed-out" | "aborted" | "failed";
|
|
65
|
+
export interface ReviewContextItem {
|
|
66
|
+
readonly id: string;
|
|
67
|
+
readonly source: "user" | "developer" | "agents" | "user-confirmation" | "assistant" | "tool-call" | "tool-result";
|
|
68
|
+
readonly trust: "authorization" | "evidence";
|
|
69
|
+
readonly content: Json;
|
|
70
|
+
readonly isTruncated?: boolean;
|
|
71
|
+
}
|
|
72
|
+
export interface ReviewContext {
|
|
73
|
+
readonly sessionId: string;
|
|
74
|
+
readonly contextId: string;
|
|
75
|
+
readonly turnId: string;
|
|
76
|
+
readonly items: readonly ReviewContextItem[];
|
|
77
|
+
readonly digest: string;
|
|
78
|
+
}
|
|
79
|
+
export interface ReviewBinding {
|
|
80
|
+
readonly actionDigest: string;
|
|
81
|
+
readonly contextDigest: string;
|
|
82
|
+
readonly policyDigest: string;
|
|
83
|
+
}
|
|
84
|
+
export type ReviewResult = ReviewBinding & ({
|
|
85
|
+
readonly status: "approved" | "denied";
|
|
86
|
+
readonly assessment: ReviewAssessment;
|
|
87
|
+
} | {
|
|
88
|
+
readonly status: "timed-out" | "aborted" | "failed";
|
|
89
|
+
readonly failure: "timeout" | "cancelled" | "provider" | "invalid-output" | "investigation" | "context";
|
|
90
|
+
readonly reason: string;
|
|
91
|
+
});
|
|
92
|
+
export type ExecutionAuthority = {
|
|
93
|
+
readonly kind: "sandbox" | "scoped-permissions";
|
|
94
|
+
readonly actionDigest: string;
|
|
95
|
+
} | {
|
|
96
|
+
readonly kind: "command-rule";
|
|
97
|
+
readonly actionDigest: string;
|
|
98
|
+
readonly ruleDigest: string;
|
|
99
|
+
} | {
|
|
100
|
+
readonly kind: "reviewed-command";
|
|
101
|
+
readonly actionDigest: string;
|
|
102
|
+
};
|
|
103
|
+
export interface RetryAuthorization {
|
|
104
|
+
readonly id: string;
|
|
105
|
+
readonly denialId: string;
|
|
106
|
+
readonly actionIdentity: string;
|
|
107
|
+
readonly sessionId: string;
|
|
108
|
+
readonly contextId: string;
|
|
109
|
+
}
|
|
110
|
+
export interface RecentDenial {
|
|
111
|
+
readonly id: string;
|
|
112
|
+
readonly action: GuardAction;
|
|
113
|
+
readonly contextId: string;
|
|
114
|
+
readonly assessment: ReviewAssessment;
|
|
115
|
+
}
|
|
116
|
+
export interface Grant {
|
|
117
|
+
readonly id: string;
|
|
118
|
+
readonly scope: "once" | "session" | "persistent";
|
|
119
|
+
readonly actionDigest: string;
|
|
120
|
+
readonly ruleDigest: string;
|
|
121
|
+
readonly sessionId: string;
|
|
122
|
+
readonly policyRevision: string;
|
|
123
|
+
readonly permissionDigest: string;
|
|
124
|
+
readonly delta: PermissionDelta;
|
|
125
|
+
}
|
|
126
|
+
export interface ToolResult {
|
|
127
|
+
content: ({
|
|
128
|
+
type: "text";
|
|
129
|
+
text: string;
|
|
130
|
+
} | {
|
|
131
|
+
type: "image";
|
|
132
|
+
data: string;
|
|
133
|
+
mimeType: string;
|
|
134
|
+
})[];
|
|
135
|
+
details?: unknown;
|
|
136
|
+
structuredContent?: Json;
|
|
137
|
+
isError?: boolean;
|
|
138
|
+
}
|
|
139
|
+
export interface ExecutionOptions {
|
|
140
|
+
readonly signal?: AbortSignal;
|
|
141
|
+
/** Pi BashOperations timeout is in seconds. Review and UI deadlines use milliseconds. */
|
|
142
|
+
readonly timeoutSeconds?: number;
|
|
143
|
+
readonly env?: NodeJS.ProcessEnv;
|
|
144
|
+
readonly onData?: (data: Buffer) => void;
|
|
145
|
+
readonly onUpdate?: (result: ToolResult) => void;
|
|
146
|
+
/** Execute the original Pi definition after admission, in the same process. */
|
|
147
|
+
readonly delegate?: (signal: AbortSignal) => Promise<Json>;
|
|
148
|
+
readonly authority?: ExecutionAuthority;
|
|
149
|
+
readonly onNetworkRequest?: (request: NetworkApprovalRequest, signal: AbortSignal) => Promise<boolean>;
|
|
150
|
+
}
|
|
151
|
+
export interface NetworkApprovalRequest {
|
|
152
|
+
readonly host: string;
|
|
153
|
+
readonly port?: number;
|
|
154
|
+
}
|
|
155
|
+
export type WorkerJob = {
|
|
156
|
+
kind: "shell";
|
|
157
|
+
command: string;
|
|
158
|
+
cwd: string;
|
|
159
|
+
shellPath?: string;
|
|
160
|
+
timeoutSeconds?: number;
|
|
161
|
+
env?: NodeJS.ProcessEnv;
|
|
162
|
+
} | {
|
|
163
|
+
kind: "tool";
|
|
164
|
+
tool: ToolName;
|
|
165
|
+
args: Record<string, Json>;
|
|
166
|
+
cwd: string;
|
|
167
|
+
toolCallId: string;
|
|
168
|
+
options?: Omit<ReadToolOptions, "operations">;
|
|
169
|
+
} | {
|
|
170
|
+
kind: "file";
|
|
171
|
+
operation: "read" | "write" | "mkdir" | "access" | "stat" | "list";
|
|
172
|
+
path: string;
|
|
173
|
+
content?: string;
|
|
174
|
+
cwd: string;
|
|
175
|
+
};
|
|
176
|
+
export type WorkerFrame = {
|
|
177
|
+
schemaVersion: 1;
|
|
178
|
+
type: "data";
|
|
179
|
+
data: string;
|
|
180
|
+
} | {
|
|
181
|
+
schemaVersion: 1;
|
|
182
|
+
type: "update";
|
|
183
|
+
result: ToolResult;
|
|
184
|
+
} | {
|
|
185
|
+
schemaVersion: 1;
|
|
186
|
+
type: "result";
|
|
187
|
+
result: Json;
|
|
188
|
+
} | {
|
|
189
|
+
schemaVersion: 1;
|
|
190
|
+
type: "error";
|
|
191
|
+
code: string;
|
|
192
|
+
message: string;
|
|
193
|
+
};
|
|
194
|
+
/** Only the unsandboxed broker's private IPC channel can send this control frame. */
|
|
195
|
+
export interface BrokerControlFrame {
|
|
196
|
+
readonly schemaVersion: 1;
|
|
197
|
+
readonly type: "workload-started";
|
|
198
|
+
readonly processGroupId: number;
|
|
199
|
+
}
|
|
200
|
+
/** Private controller/broker IPC only. Workload stdout must still reject these frame types. */
|
|
201
|
+
export interface BrokerNetworkRequest {
|
|
202
|
+
readonly schemaVersion: 1;
|
|
203
|
+
readonly type: "network-request";
|
|
204
|
+
readonly requestId: string;
|
|
205
|
+
readonly destination: NetworkApprovalRequest;
|
|
206
|
+
}
|
|
207
|
+
export interface TestEvidence {
|
|
208
|
+
readonly schemaVersion?: 1 | 2;
|
|
209
|
+
readonly runId?: string;
|
|
210
|
+
readonly artifactPath?: string;
|
|
211
|
+
readonly provenance?: "executed" | "preserved-legacy" | "synthetic";
|
|
212
|
+
readonly startedAt?: string;
|
|
213
|
+
readonly recordedAt?: string;
|
|
214
|
+
readonly provider?: {
|
|
215
|
+
readonly package: string;
|
|
216
|
+
readonly version: string;
|
|
217
|
+
readonly id: string;
|
|
218
|
+
readonly model: string;
|
|
219
|
+
};
|
|
220
|
+
readonly imageDigest?: string;
|
|
221
|
+
readonly pluginArtifactDigest?: string;
|
|
222
|
+
readonly suite: string;
|
|
223
|
+
readonly status: EvidenceStatus;
|
|
224
|
+
readonly command: string;
|
|
225
|
+
readonly testFiles: readonly string[];
|
|
226
|
+
readonly coveredBehavior: readonly string[];
|
|
227
|
+
readonly tests: readonly {
|
|
228
|
+
name: string;
|
|
229
|
+
status: EvidenceStatus;
|
|
230
|
+
isSkipped?: boolean;
|
|
231
|
+
}[];
|
|
232
|
+
readonly platform: string;
|
|
233
|
+
readonly sourceDigest: string;
|
|
234
|
+
readonly contractDigest: string;
|
|
235
|
+
readonly runtimeVersions: Readonly<Record<string, string>>;
|
|
236
|
+
readonly evidenceKind: "unit-doubles" | "simulated-provider-ui" | "native-os" | "workflow";
|
|
237
|
+
readonly nativeControls?: readonly {
|
|
238
|
+
kind: "allow" | "deny";
|
|
239
|
+
effect: string;
|
|
240
|
+
isObserved: boolean;
|
|
241
|
+
platform: string;
|
|
242
|
+
}[];
|
|
243
|
+
readonly blockedReasons: readonly string[];
|
|
244
|
+
}
|
|
245
|
+
export declare class GuardError extends Error {
|
|
246
|
+
readonly code: string;
|
|
247
|
+
constructor(code: string, message: string, options?: ErrorOptions);
|
|
248
|
+
}
|
|
249
|
+
export declare function canonicalJson(value: unknown): string;
|
|
250
|
+
export declare function digest(value: unknown): string;
|
|
251
|
+
export declare function immutable<T>(value: T): T;
|
|
252
|
+
export declare function createProfile(input: PermissionProfile): PermissionProfile;
|
|
253
|
+
export declare function createAction(input: Omit<GuardAction, "schemaVersion" | "digest" | "permissionDigest">, profile: PermissionProfile): GuardAction;
|
|
254
|
+
/** Reusable grants still bind exact inputs/cwd/source/profile, but not a previous logical call id. */
|
|
255
|
+
export declare function ruleDigest(action: GuardAction): string;
|
|
256
|
+
/** A retry gets a new invocation ID, but cannot change session, semantics or context. */
|
|
257
|
+
export declare function retryIdentity(action: GuardAction, contextId: string): string;
|
|
258
|
+
export declare function approvalEligible(policy: ApprovalPolicy, category: "sandbox" | "rules" | "mcp_elicitations"): boolean;
|
|
259
|
+
export declare function decision(action: GuardAction, kind: DecisionKind, reason: string, delta?: PermissionDelta, isHardDeny?: boolean): PolicyDecision;
|
|
260
|
+
export declare function validateWorkerFrame(value: unknown): WorkerFrame;
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { isAbsolute, resolve } from "node:path";
|
|
3
|
+
import { isDomainPattern, normalizeHost } from "./policy/domains.js";
|
|
4
|
+
export const TOOL_NAMES = Object.freeze([
|
|
5
|
+
"bash",
|
|
6
|
+
"read",
|
|
7
|
+
"edit",
|
|
8
|
+
"write",
|
|
9
|
+
"grep",
|
|
10
|
+
"find",
|
|
11
|
+
"ls",
|
|
12
|
+
]);
|
|
13
|
+
export const EMPTY_DELTA = Object.freeze({
|
|
14
|
+
readPaths: Object.freeze([]),
|
|
15
|
+
writePaths: Object.freeze([]),
|
|
16
|
+
domains: Object.freeze([]),
|
|
17
|
+
});
|
|
18
|
+
export class GuardError extends Error {
|
|
19
|
+
code;
|
|
20
|
+
constructor(code, message, options) {
|
|
21
|
+
super(message, options);
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.name = "GuardError";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export function canonicalJson(value) {
|
|
27
|
+
if (value === null ||
|
|
28
|
+
typeof value === "string" ||
|
|
29
|
+
typeof value === "boolean")
|
|
30
|
+
return JSON.stringify(value);
|
|
31
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
32
|
+
return JSON.stringify(value);
|
|
33
|
+
if (Array.isArray(value))
|
|
34
|
+
return `[${value.map(canonicalJson).join(",")}]`;
|
|
35
|
+
if (typeof value === "object" &&
|
|
36
|
+
value !== null &&
|
|
37
|
+
Object.getPrototypeOf(value) === Object.prototype) {
|
|
38
|
+
return `{${Object.keys(value)
|
|
39
|
+
.sort()
|
|
40
|
+
.map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`)
|
|
41
|
+
.join(",")}}`;
|
|
42
|
+
}
|
|
43
|
+
throw new GuardError("INVALID_JSON", "Expected finite JSON data");
|
|
44
|
+
}
|
|
45
|
+
export function digest(value) {
|
|
46
|
+
return createHash("sha256").update(canonicalJson(value)).digest("hex");
|
|
47
|
+
}
|
|
48
|
+
export function immutable(value) {
|
|
49
|
+
if (value && typeof value === "object") {
|
|
50
|
+
for (const item of Object.values(value))
|
|
51
|
+
immutable(item);
|
|
52
|
+
Object.freeze(value);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
export function createProfile(input) {
|
|
57
|
+
if (!["read-only", "workspace-write"].includes(input.mode))
|
|
58
|
+
throw new GuardError("INVALID_PROFILE", "Unknown permission mode");
|
|
59
|
+
for (const key of [
|
|
60
|
+
"readRoots",
|
|
61
|
+
"writeRoots",
|
|
62
|
+
"denyRead",
|
|
63
|
+
"denyWrite",
|
|
64
|
+
]) {
|
|
65
|
+
if (!Array.isArray(input[key]) ||
|
|
66
|
+
input[key].some((p) => typeof p !== "string" || !isAbsolute(p) || p.includes("\0")))
|
|
67
|
+
throw new GuardError("INVALID_PROFILE", `Invalid ${key}`);
|
|
68
|
+
}
|
|
69
|
+
if (input.readOnlyPaths !== undefined &&
|
|
70
|
+
(!Array.isArray(input.readOnlyPaths) ||
|
|
71
|
+
input.readOnlyPaths.some((path) => typeof path !== "string" ||
|
|
72
|
+
!isAbsolute(path) ||
|
|
73
|
+
path.includes("\0"))))
|
|
74
|
+
throw new GuardError("INVALID_PROFILE", "Invalid readOnlyPaths");
|
|
75
|
+
if (input.mode === "read-only" && input.writeRoots.length)
|
|
76
|
+
throw new GuardError("INVALID_PROFILE", "Read-only profiles cannot contain write roots");
|
|
77
|
+
for (const key of ["allowedDomains", "deniedDomains"]) {
|
|
78
|
+
if (!Array.isArray(input[key]) ||
|
|
79
|
+
input[key].some((p) => !isDomainPattern(p)))
|
|
80
|
+
throw new GuardError("INVALID_PROFILE", `Invalid ${key}`);
|
|
81
|
+
}
|
|
82
|
+
return immutable(JSON.parse(canonicalJson({
|
|
83
|
+
...input,
|
|
84
|
+
allowedDomains: input.allowedDomains.map(normalizeHost),
|
|
85
|
+
deniedDomains: input.deniedDomains.map(normalizeHost),
|
|
86
|
+
})));
|
|
87
|
+
}
|
|
88
|
+
export function createAction(input, profile) {
|
|
89
|
+
for (const key of [
|
|
90
|
+
"toolCallId",
|
|
91
|
+
"tool",
|
|
92
|
+
"cwd",
|
|
93
|
+
"sessionId",
|
|
94
|
+
"policyRevision",
|
|
95
|
+
]) {
|
|
96
|
+
if (typeof input[key] !== "string" ||
|
|
97
|
+
!input[key] ||
|
|
98
|
+
input[key].includes("\0"))
|
|
99
|
+
throw new GuardError("INVALID_ACTION", `Invalid ${key}`);
|
|
100
|
+
}
|
|
101
|
+
if (!["model", "nested", "user-bash", "extension"].includes(input.source))
|
|
102
|
+
throw new GuardError("INVALID_ACTION", "Invalid action source");
|
|
103
|
+
if (!input.args ||
|
|
104
|
+
Array.isArray(input.args) ||
|
|
105
|
+
typeof input.args !== "object")
|
|
106
|
+
throw new GuardError("INVALID_ACTION", "Arguments must be an object");
|
|
107
|
+
const fields = JSON.parse(canonicalJson({
|
|
108
|
+
...input,
|
|
109
|
+
cwd: resolve(input.cwd),
|
|
110
|
+
schemaVersion: 1,
|
|
111
|
+
permissionDigest: digest(profile),
|
|
112
|
+
}));
|
|
113
|
+
return immutable({ ...fields, digest: digest(fields) });
|
|
114
|
+
}
|
|
115
|
+
/** Reusable grants still bind exact inputs/cwd/source/profile, but not a previous logical call id. */
|
|
116
|
+
export function ruleDigest(action) {
|
|
117
|
+
const { digest: ignoredDigest, toolCallId: ignoredId, sessionId: ignoredSession, ...fields } = action;
|
|
118
|
+
return digest(fields);
|
|
119
|
+
}
|
|
120
|
+
/** A retry gets a new invocation ID, but cannot change session, semantics or context. */
|
|
121
|
+
export function retryIdentity(action, contextId) {
|
|
122
|
+
// A runtime destination belongs to the same semantic command even though its new
|
|
123
|
+
// invocation necessarily has a different origin digest. Destination/port stay bound.
|
|
124
|
+
const { originatingActionDigest: ignoredOrigin, ...networkArgs } = action.args;
|
|
125
|
+
const semantic = action.args.networkDestination && typeof ignoredOrigin === "string"
|
|
126
|
+
? { ...action, args: networkArgs }
|
|
127
|
+
: action;
|
|
128
|
+
return digest({
|
|
129
|
+
action: ruleDigest(semantic),
|
|
130
|
+
sessionId: action.sessionId,
|
|
131
|
+
contextId,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
export function approvalEligible(policy, category) {
|
|
135
|
+
return (policy === "on-request" ||
|
|
136
|
+
(typeof policy === "object" && policy[category] === true));
|
|
137
|
+
}
|
|
138
|
+
export function decision(action, kind, reason, delta = EMPTY_DELTA, isHardDeny = false) {
|
|
139
|
+
if (!["allow", "ask", "deny"].includes(kind) ||
|
|
140
|
+
(isHardDeny && kind !== "deny"))
|
|
141
|
+
throw new GuardError("INVALID_DECISION", "Invalid decision");
|
|
142
|
+
return immutable({
|
|
143
|
+
kind,
|
|
144
|
+
reason,
|
|
145
|
+
actionDigest: action.digest,
|
|
146
|
+
delta: JSON.parse(canonicalJson(delta)),
|
|
147
|
+
isHardDeny,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
export function validateWorkerFrame(value) {
|
|
151
|
+
const frame = value;
|
|
152
|
+
if (frame?.schemaVersion !== 1 ||
|
|
153
|
+
!["data", "update", "result", "error"].includes(frame.type))
|
|
154
|
+
throw new GuardError("INVALID_IPC", "Invalid worker frame");
|
|
155
|
+
canonicalJson(value);
|
|
156
|
+
if (frame.type === "data" && typeof frame.data !== "string")
|
|
157
|
+
throw new GuardError("INVALID_IPC", "Invalid data frame");
|
|
158
|
+
if (frame.type === "error" &&
|
|
159
|
+
(typeof frame.code !== "string" || typeof frame.message !== "string"))
|
|
160
|
+
throw new GuardError("INVALID_IPC", "Invalid error frame");
|
|
161
|
+
if (frame.type === "result" && !Object.hasOwn(frame, "result"))
|
|
162
|
+
throw new GuardError("INVALID_IPC", "Missing worker result");
|
|
163
|
+
if (frame.type === "update" &&
|
|
164
|
+
(!frame.result || !Array.isArray(frame.result.content)))
|
|
165
|
+
throw new GuardError("INVALID_IPC", "Invalid update");
|
|
166
|
+
return frame;
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=contracts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"contracts.js","sourceRoot":"","sources":["../src/contracts.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type BashToolOptions, type ExtensionFactory, type McpExtensionOptions, type ReadToolOptions } from "@earendil-works/pi-coding-agent";
|
|
2
|
+
import type { PermissionProfile } from "./contracts.js";
|
|
3
|
+
import { type GuardSettings } from "./policy/index.js";
|
|
4
|
+
import type { ReviewProvider } from "./reviewer.js";
|
|
5
|
+
import { GuardController } from "./tools/controller.js";
|
|
6
|
+
import { type ToolExecutor } from "./tools/executor.js";
|
|
7
|
+
import { type McpToolPolicies } from "./tools/mcp.js";
|
|
8
|
+
export interface GuardOptions {
|
|
9
|
+
cwd?: string;
|
|
10
|
+
agentDir?: string;
|
|
11
|
+
settings?: Partial<GuardSettings>;
|
|
12
|
+
settingsPath?: string;
|
|
13
|
+
profile?: PermissionProfile;
|
|
14
|
+
executor?: ToolExecutor;
|
|
15
|
+
provider?: ReviewProvider;
|
|
16
|
+
bashOptions?: Omit<BashToolOptions, "operations">;
|
|
17
|
+
readOptions?: Omit<ReadToolOptions, "operations">;
|
|
18
|
+
/** Trusted code directories are protected against model writes, including imported siblings. */
|
|
19
|
+
trustedExtensionPaths?: readonly string[];
|
|
20
|
+
mcp?: McpExtensionOptions | false;
|
|
21
|
+
mcpToolPolicies?: McpToolPolicies;
|
|
22
|
+
}
|
|
23
|
+
export declare function createGuardExtension(options?: GuardOptions): {
|
|
24
|
+
factory: ExtensionFactory;
|
|
25
|
+
assertReady(): GuardController;
|
|
26
|
+
};
|
|
27
|
+
declare const _default: ExtensionFactory;
|
|
28
|
+
export default _default;
|