@rewind-ai/cli 0.6.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/.env.example +8 -0
- package/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/src/action/capture.d.ts +15 -0
- package/dist/src/action/capture.js +215 -0
- package/dist/src/action/capture.js.map +1 -0
- package/dist/src/action/mediate.d.ts +28 -0
- package/dist/src/action/mediate.js +109 -0
- package/dist/src/action/mediate.js.map +1 -0
- package/dist/src/action/mutate.d.ts +11 -0
- package/dist/src/action/mutate.js +189 -0
- package/dist/src/action/mutate.js.map +1 -0
- package/dist/src/action/objects.d.ts +5 -0
- package/dist/src/action/objects.js +50 -0
- package/dist/src/action/objects.js.map +1 -0
- package/dist/src/action/store.d.ts +24 -0
- package/dist/src/action/store.js +149 -0
- package/dist/src/action/store.js.map +1 -0
- package/dist/src/action/types.d.ts +84 -0
- package/dist/src/action/types.js +3 -0
- package/dist/src/action/types.js.map +1 -0
- package/dist/src/action/undo.d.ts +11 -0
- package/dist/src/action/undo.js +42 -0
- package/dist/src/action/undo.js.map +1 -0
- package/dist/src/adapters/filesystem.d.ts +35 -0
- package/dist/src/adapters/filesystem.js +499 -0
- package/dist/src/adapters/filesystem.js.map +1 -0
- package/dist/src/adapters/index.d.ts +7 -0
- package/dist/src/adapters/index.js +19 -0
- package/dist/src/adapters/index.js.map +1 -0
- package/dist/src/adapters/types.d.ts +54 -0
- package/dist/src/adapters/types.js +7 -0
- package/dist/src/adapters/types.js.map +1 -0
- package/dist/src/api/server.d.ts +25 -0
- package/dist/src/api/server.js +786 -0
- package/dist/src/api/server.js.map +1 -0
- package/dist/src/approval/store.d.ts +35 -0
- package/dist/src/approval/store.js +113 -0
- package/dist/src/approval/store.js.map +1 -0
- package/dist/src/checkpoint.d.ts +9 -0
- package/dist/src/checkpoint.js +140 -0
- package/dist/src/checkpoint.js.map +1 -0
- package/dist/src/cli/v5.d.ts +15 -0
- package/dist/src/cli/v5.js +110 -0
- package/dist/src/cli/v5.js.map +1 -0
- package/dist/src/cli.d.ts +2 -0
- package/dist/src/cli.js +823 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/clients/types.d.ts +90 -0
- package/dist/src/clients/types.js +239 -0
- package/dist/src/clients/types.js.map +1 -0
- package/dist/src/commercial/auth/provider.d.ts +61 -0
- package/dist/src/commercial/auth/provider.js +227 -0
- package/dist/src/commercial/auth/provider.js.map +1 -0
- package/dist/src/commercial/entitlement/provider.d.ts +27 -0
- package/dist/src/commercial/entitlement/provider.js +192 -0
- package/dist/src/commercial/entitlement/provider.js.map +1 -0
- package/dist/src/commercial/entitlement/signing.d.ts +61 -0
- package/dist/src/commercial/entitlement/signing.js +124 -0
- package/dist/src/commercial/entitlement/signing.js.map +1 -0
- package/dist/src/commercial/env.d.ts +10 -0
- package/dist/src/commercial/env.js +40 -0
- package/dist/src/commercial/env.js.map +1 -0
- package/dist/src/commercial/product.d.ts +26 -0
- package/dist/src/commercial/product.js +39 -0
- package/dist/src/commercial/product.js.map +1 -0
- package/dist/src/commercial/store.d.ts +46 -0
- package/dist/src/commercial/store.js +104 -0
- package/dist/src/commercial/store.js.map +1 -0
- package/dist/src/commercial/stripe/checkout.d.ts +104 -0
- package/dist/src/commercial/stripe/checkout.js +469 -0
- package/dist/src/commercial/stripe/checkout.js.map +1 -0
- package/dist/src/core/compatibility.d.ts +15 -0
- package/dist/src/core/compatibility.js +226 -0
- package/dist/src/core/compatibility.js.map +1 -0
- package/dist/src/core/engine.d.ts +33 -0
- package/dist/src/core/engine.js +432 -0
- package/dist/src/core/engine.js.map +1 -0
- package/dist/src/core/lifecycle.d.ts +17 -0
- package/dist/src/core/lifecycle.js +56 -0
- package/dist/src/core/lifecycle.js.map +1 -0
- package/dist/src/core/types.d.ts +140 -0
- package/dist/src/core/types.js +37 -0
- package/dist/src/core/types.js.map +1 -0
- package/dist/src/destroy.d.ts +21 -0
- package/dist/src/destroy.js +219 -0
- package/dist/src/destroy.js.map +1 -0
- package/dist/src/diff.d.ts +13 -0
- package/dist/src/diff.js +251 -0
- package/dist/src/diff.js.map +1 -0
- package/dist/src/enforcement/detect.d.ts +13 -0
- package/dist/src/enforcement/detect.js +75 -0
- package/dist/src/enforcement/detect.js.map +1 -0
- package/dist/src/enforcement/hook-policy.d.ts +38 -0
- package/dist/src/enforcement/hook-policy.js +111 -0
- package/dist/src/enforcement/hook-policy.js.map +1 -0
- package/dist/src/enforcement/index.d.ts +8 -0
- package/dist/src/enforcement/index.js +8 -0
- package/dist/src/enforcement/index.js.map +1 -0
- package/dist/src/enforcement/perf.d.ts +6 -0
- package/dist/src/enforcement/perf.js +18 -0
- package/dist/src/enforcement/perf.js.map +1 -0
- package/dist/src/enforcement/policy.d.ts +12 -0
- package/dist/src/enforcement/policy.js +84 -0
- package/dist/src/enforcement/policy.js.map +1 -0
- package/dist/src/enforcement/readonly.d.ts +17 -0
- package/dist/src/enforcement/readonly.js +124 -0
- package/dist/src/enforcement/readonly.js.map +1 -0
- package/dist/src/enforcement/sandbox-clone.d.ts +6 -0
- package/dist/src/enforcement/sandbox-clone.js +11 -0
- package/dist/src/enforcement/sandbox-clone.js.map +1 -0
- package/dist/src/enforcement/setup.d.ts +33 -0
- package/dist/src/enforcement/setup.js +168 -0
- package/dist/src/enforcement/setup.js.map +1 -0
- package/dist/src/enforcement/trust.d.ts +10 -0
- package/dist/src/enforcement/trust.js +71 -0
- package/dist/src/enforcement/trust.js.map +1 -0
- package/dist/src/enforcement/types.d.ts +40 -0
- package/dist/src/enforcement/types.js +3 -0
- package/dist/src/enforcement/types.js.map +1 -0
- package/dist/src/entitlement/provider.d.ts +48 -0
- package/dist/src/entitlement/provider.js +95 -0
- package/dist/src/entitlement/provider.js.map +1 -0
- package/dist/src/hash.d.ts +9 -0
- package/dist/src/hash.js +23 -0
- package/dist/src/hash.js.map +1 -0
- package/dist/src/ledger/query.d.ts +19 -0
- package/dist/src/ledger/query.js +158 -0
- package/dist/src/ledger/query.js.map +1 -0
- package/dist/src/manifest.d.ts +32 -0
- package/dist/src/manifest.js +242 -0
- package/dist/src/manifest.js.map +1 -0
- package/dist/src/mcp/server.d.ts +7 -0
- package/dist/src/mcp/server.js +364 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/dist/src/paths.d.ts +94 -0
- package/dist/src/paths.js +354 -0
- package/dist/src/paths.js.map +1 -0
- package/dist/src/permission/engine.d.ts +15 -0
- package/dist/src/permission/engine.js +147 -0
- package/dist/src/permission/engine.js.map +1 -0
- package/dist/src/permission/types.d.ts +42 -0
- package/dist/src/permission/types.js +3 -0
- package/dist/src/permission/types.js.map +1 -0
- package/dist/src/product/setup.d.ts +35 -0
- package/dist/src/product/setup.js +300 -0
- package/dist/src/product/setup.js.map +1 -0
- package/dist/src/protect/audit.d.ts +5 -0
- package/dist/src/protect/audit.js +26 -0
- package/dist/src/protect/audit.js.map +1 -0
- package/dist/src/protect/capture.d.ts +7 -0
- package/dist/src/protect/capture.js +250 -0
- package/dist/src/protect/capture.js.map +1 -0
- package/dist/src/protect/fingerprint.d.ts +4 -0
- package/dist/src/protect/fingerprint.js +49 -0
- package/dist/src/protect/fingerprint.js.map +1 -0
- package/dist/src/protect/hook-cli.d.ts +2 -0
- package/dist/src/protect/hook-cli.js +107 -0
- package/dist/src/protect/hook-cli.js.map +1 -0
- package/dist/src/protect/index.d.ts +12 -0
- package/dist/src/protect/index.js +12 -0
- package/dist/src/protect/index.js.map +1 -0
- package/dist/src/protect/install.d.ts +34 -0
- package/dist/src/protect/install.js +293 -0
- package/dist/src/protect/install.js.map +1 -0
- package/dist/src/protect/intercept.d.ts +11 -0
- package/dist/src/protect/intercept.js +390 -0
- package/dist/src/protect/intercept.js.map +1 -0
- package/dist/src/protect/protect.d.ts +17 -0
- package/dist/src/protect/protect.js +194 -0
- package/dist/src/protect/protect.js.map +1 -0
- package/dist/src/protect/root-paths.d.ts +13 -0
- package/dist/src/protect/root-paths.js +140 -0
- package/dist/src/protect/root-paths.js.map +1 -0
- package/dist/src/protect/shell-policy.d.ts +17 -0
- package/dist/src/protect/shell-policy.js +269 -0
- package/dist/src/protect/shell-policy.js.map +1 -0
- package/dist/src/protect/status.d.ts +11 -0
- package/dist/src/protect/status.js +165 -0
- package/dist/src/protect/status.js.map +1 -0
- package/dist/src/protect/store.d.ts +20 -0
- package/dist/src/protect/store.js +170 -0
- package/dist/src/protect/store.js.map +1 -0
- package/dist/src/protect/types.d.ts +116 -0
- package/dist/src/protect/types.js +3 -0
- package/dist/src/protect/types.js.map +1 -0
- package/dist/src/protect/undo-session.d.ts +14 -0
- package/dist/src/protect/undo-session.js +182 -0
- package/dist/src/protect/undo-session.js.map +1 -0
- package/dist/src/restore.d.ts +39 -0
- package/dist/src/restore.js +141 -0
- package/dist/src/restore.js.map +1 -0
- package/dist/src/sandbox.d.ts +23 -0
- package/dist/src/sandbox.js +198 -0
- package/dist/src/sandbox.js.map +1 -0
- package/dist/src/session/ambient.d.ts +10 -0
- package/dist/src/session/ambient.js +53 -0
- package/dist/src/session/ambient.js.map +1 -0
- package/dist/src/session/attribution.d.ts +27 -0
- package/dist/src/session/attribution.js +201 -0
- package/dist/src/session/attribution.js.map +1 -0
- package/dist/src/session/index.d.ts +25 -0
- package/dist/src/session/index.js +472 -0
- package/dist/src/session/index.js.map +1 -0
- package/dist/src/session/process.d.ts +34 -0
- package/dist/src/session/process.js +234 -0
- package/dist/src/session/process.js.map +1 -0
- package/dist/src/session/store.d.ts +14 -0
- package/dist/src/session/store.js +125 -0
- package/dist/src/session/store.js.map +1 -0
- package/dist/src/session/types.d.ts +111 -0
- package/dist/src/session/types.js +3 -0
- package/dist/src/session/types.js.map +1 -0
- package/dist/src/session/watcher.d.ts +32 -0
- package/dist/src/session/watcher.js +186 -0
- package/dist/src/session/watcher.js.map +1 -0
- package/dist/src/timing.d.ts +7 -0
- package/dist/src/timing.js +19 -0
- package/dist/src/timing.js.map +1 -0
- package/dist/src/types.d.ts +101 -0
- package/dist/src/types.js +3 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/verify.d.ts +8 -0
- package/dist/src/verify.js +126 -0
- package/dist/src/verify.js.map +1 -0
- package/docs/ADAPTERS.md +37 -0
- package/docs/APPROVALS.md +32 -0
- package/docs/ARCHITECTURE.md +57 -0
- package/docs/ATTRIBUTION.md +179 -0
- package/docs/COMMERCIAL.md +51 -0
- package/docs/CURSOR-ENFORCEMENT.md +73 -0
- package/docs/ENFORCEMENT.md +134 -0
- package/docs/FUTURE.md +91 -0
- package/docs/HUMAN-SETUP.md +98 -0
- package/docs/IDENTITY-AUTHORITY.md +35 -0
- package/docs/MCP.md +107 -0
- package/docs/PACKAGING.md +77 -0
- package/docs/PERMISSIONS.md +53 -0
- package/docs/PRODUCT-V5.md +63 -0
- package/docs/PRODUCT-V6.md +69 -0
- package/docs/PROTECTED-SESSIONS.md +155 -0
- package/docs/THREAT-MODEL.md +84 -0
- package/docs/TRANSACTIONS.md +57 -0
- package/package.json +85 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect.js","sourceRoot":"","sources":["../../../src/enforcement/detect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure policy decision helpers for Cursor hooks / harnesses.
|
|
3
|
+
* Prompt compliance is NOT used here — these return allow/deny for tool gates.
|
|
4
|
+
*/
|
|
5
|
+
export type HookPermission = "allow" | "deny";
|
|
6
|
+
export interface HookDecision {
|
|
7
|
+
permission: HookPermission;
|
|
8
|
+
user_message?: string;
|
|
9
|
+
agent_message?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function pathTouchesEnforced(candidate: string | null | undefined, enforcedRootAbs?: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* preToolUse decision: deny native mutating tools targeting enforced sandbox.
|
|
14
|
+
* Allow Read/Grep/Glob and non-enforced paths.
|
|
15
|
+
*/
|
|
16
|
+
export declare function decidePreToolUse(input: {
|
|
17
|
+
tool_name?: string;
|
|
18
|
+
tool_input?: unknown;
|
|
19
|
+
enforcedRootAbs?: string;
|
|
20
|
+
}): HookDecision;
|
|
21
|
+
/**
|
|
22
|
+
* beforeShellExecution: deny mutation commands that mention the enforced sandbox.
|
|
23
|
+
* Read-only commands (cat, ls, find without -delete, etc.) that only read are allowed
|
|
24
|
+
* even if they mention the path — but redirection / rm / chmod are denied.
|
|
25
|
+
*/
|
|
26
|
+
export declare function decideShellExecution(input: {
|
|
27
|
+
command?: string;
|
|
28
|
+
enforcedRootAbs?: string;
|
|
29
|
+
}): HookDecision;
|
|
30
|
+
/**
|
|
31
|
+
* beforeMCPExecution: allow REWIND tools; deny nothing by default for rewind server.
|
|
32
|
+
*/
|
|
33
|
+
export declare function decideMcpExecution(input: {
|
|
34
|
+
tool_name?: string;
|
|
35
|
+
mcp_server_name?: string;
|
|
36
|
+
}): HookDecision;
|
|
37
|
+
/** Test harness: classify whether a shell write should be blocked by policy. */
|
|
38
|
+
export declare function shellWriteWouldBeBlocked(command: string, enforcedRootAbs?: string): boolean;
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure policy decision helpers for Cursor hooks / harnesses.
|
|
3
|
+
* Prompt compliance is NOT used here — these return allow/deny for tool gates.
|
|
4
|
+
*/
|
|
5
|
+
import { ENFORCED_SANDBOX_DIR_NAME } from "../paths.js";
|
|
6
|
+
const MUTATING_NATIVE_TOOLS = new Set([
|
|
7
|
+
"Write",
|
|
8
|
+
"Delete",
|
|
9
|
+
"StrReplace",
|
|
10
|
+
"EditNotebook",
|
|
11
|
+
"DeleteNotebookCell",
|
|
12
|
+
]);
|
|
13
|
+
/** Shell tokens that indicate filesystem mutation. */
|
|
14
|
+
const SHELL_MUTATION_RE = /(^|[\s;|&])(rm|mv|cp|mkdir|rmdir|touch|chmod|chown|ln|tee|install|dd|truncate|sed\s+-i)\b|>|>>|>\(/i;
|
|
15
|
+
export function pathTouchesEnforced(candidate, enforcedRootAbs) {
|
|
16
|
+
if (!candidate)
|
|
17
|
+
return false;
|
|
18
|
+
const norm = candidate.replace(/\\/g, "/");
|
|
19
|
+
// Segment match: ".../name/...", " name/...", or exact name.
|
|
20
|
+
const seg = new RegExp(`(?:^|[\\s/"'])${ENFORCED_SANDBOX_DIR_NAME}(?:/|$|[\\s"'])`);
|
|
21
|
+
if (seg.test(norm))
|
|
22
|
+
return true;
|
|
23
|
+
if (enforcedRootAbs) {
|
|
24
|
+
const root = enforcedRootAbs.replace(/\\/g, "/");
|
|
25
|
+
const c = norm;
|
|
26
|
+
if (c === root || c.startsWith(root.endsWith("/") ? root : root + "/")) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
function extractPathsFromToolInput(toolInput) {
|
|
33
|
+
if (!toolInput || typeof toolInput !== "object")
|
|
34
|
+
return [];
|
|
35
|
+
const o = toolInput;
|
|
36
|
+
const keys = ["path", "file_path", "target_notebook", "from", "to"];
|
|
37
|
+
const out = [];
|
|
38
|
+
for (const k of keys) {
|
|
39
|
+
if (typeof o[k] === "string")
|
|
40
|
+
out.push(o[k]);
|
|
41
|
+
}
|
|
42
|
+
if (Array.isArray(o.paths)) {
|
|
43
|
+
for (const p of o.paths) {
|
|
44
|
+
if (typeof p === "string")
|
|
45
|
+
out.push(p);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* preToolUse decision: deny native mutating tools targeting enforced sandbox.
|
|
52
|
+
* Allow Read/Grep/Glob and non-enforced paths.
|
|
53
|
+
*/
|
|
54
|
+
export function decidePreToolUse(input) {
|
|
55
|
+
const name = input.tool_name ?? "";
|
|
56
|
+
if (!MUTATING_NATIVE_TOOLS.has(name)) {
|
|
57
|
+
return { permission: "allow" };
|
|
58
|
+
}
|
|
59
|
+
const paths = extractPathsFromToolInput(input.tool_input);
|
|
60
|
+
const hits = paths.filter((p) => pathTouchesEnforced(p, input.enforcedRootAbs));
|
|
61
|
+
if (hits.length === 0) {
|
|
62
|
+
return { permission: "allow" };
|
|
63
|
+
}
|
|
64
|
+
return {
|
|
65
|
+
permission: "deny",
|
|
66
|
+
user_message: "REWIND V3: native write/delete to sandbox-enforced-project is blocked. Use REWIND MCP.",
|
|
67
|
+
agent_message: "POLICY: Direct native mutation of sandbox-enforced-project is denied. Use rewind_write_file / rewind_create_file / other REWIND MCP tools with sandbox=enforced.",
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* beforeShellExecution: deny mutation commands that mention the enforced sandbox.
|
|
72
|
+
* Read-only commands (cat, ls, find without -delete, etc.) that only read are allowed
|
|
73
|
+
* even if they mention the path — but redirection / rm / chmod are denied.
|
|
74
|
+
*/
|
|
75
|
+
export function decideShellExecution(input) {
|
|
76
|
+
const cmd = input.command ?? "";
|
|
77
|
+
if (!cmd.trim())
|
|
78
|
+
return { permission: "allow" };
|
|
79
|
+
const touches = pathTouchesEnforced(cmd, input.enforcedRootAbs);
|
|
80
|
+
if (!touches)
|
|
81
|
+
return { permission: "allow" };
|
|
82
|
+
if (SHELL_MUTATION_RE.test(cmd)) {
|
|
83
|
+
return {
|
|
84
|
+
permission: "deny",
|
|
85
|
+
user_message: "REWIND V3: shell mutation of sandbox-enforced-project is blocked.",
|
|
86
|
+
agent_message: "POLICY: Shell filesystem mutation against sandbox-enforced-project is denied. Use REWIND MCP mediation.",
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Mentions enforced path but no obvious mutation token — still deny chmod-like patterns
|
|
90
|
+
// already covered. Allow pure reads.
|
|
91
|
+
return { permission: "allow" };
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* beforeMCPExecution: allow REWIND tools; deny nothing by default for rewind server.
|
|
95
|
+
*/
|
|
96
|
+
export function decideMcpExecution(input) {
|
|
97
|
+
const server = (input.mcp_server_name ?? "").toLowerCase();
|
|
98
|
+
const tool = input.tool_name ?? "";
|
|
99
|
+
if (server === "rewind" || tool.startsWith("rewind_")) {
|
|
100
|
+
return { permission: "allow" };
|
|
101
|
+
}
|
|
102
|
+
return { permission: "allow" };
|
|
103
|
+
}
|
|
104
|
+
/** Test harness: classify whether a shell write should be blocked by policy. */
|
|
105
|
+
export function shellWriteWouldBeBlocked(command, enforcedRootAbs) {
|
|
106
|
+
const input = { command };
|
|
107
|
+
if (enforcedRootAbs !== undefined)
|
|
108
|
+
input.enforcedRootAbs = enforcedRootAbs;
|
|
109
|
+
return decideShellExecution(input).permission === "deny";
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=hook-policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-policy.js","sourceRoot":"","sources":["../../../src/enforcement/hook-policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type { PolicyEvent, EnforcementState, PathTrustRecord } from "./types.js";
|
|
2
|
+
export { recordPolicyEvent, listPolicyEvents, loadPolicyEvent, formatPolicyViolation, } from "./policy.js";
|
|
3
|
+
export { markAuthoritative, markUntrusted, getPathTrust, listTrustRecords, setPathTrust, } from "./trust.js";
|
|
4
|
+
export { decidePreToolUse, decideShellExecution, decideMcpExecution, shellWriteWouldBeBlocked, pathTouchesEnforced, } from "./hook-policy.js";
|
|
5
|
+
export { lockEnforcedReadonly, unlockEnforcedWritable, withEnforcedWriteAccess, probeDirectWriteBlocked, } from "./readonly.js";
|
|
6
|
+
export { enableEnforcement, disableEnforcement, createEnforcedSandbox, loadEnforcementState, isEnforcedLocked, runUnderWriteDenySeatbelt, writeSeatbeltProfile, } from "./setup.js";
|
|
7
|
+
export { classifyExternalMutation, recordBlockedWrite, } from "./detect.js";
|
|
8
|
+
export { measureMs, formatPerfTable } from "./perf.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { recordPolicyEvent, listPolicyEvents, loadPolicyEvent, formatPolicyViolation, } from "./policy.js";
|
|
2
|
+
export { markAuthoritative, markUntrusted, getPathTrust, listTrustRecords, setPathTrust, } from "./trust.js";
|
|
3
|
+
export { decidePreToolUse, decideShellExecution, decideMcpExecution, shellWriteWouldBeBlocked, pathTouchesEnforced, } from "./hook-policy.js";
|
|
4
|
+
export { lockEnforcedReadonly, unlockEnforcedWritable, withEnforcedWriteAccess, probeDirectWriteBlocked, } from "./readonly.js";
|
|
5
|
+
export { enableEnforcement, disableEnforcement, createEnforcedSandbox, loadEnforcementState, isEnforcedLocked, runUnderWriteDenySeatbelt, writeSeatbeltProfile, } from "./setup.js";
|
|
6
|
+
export { classifyExternalMutation, recordBlockedWrite, } from "./detect.js";
|
|
7
|
+
export { measureMs, formatPerfTable } from "./perf.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/enforcement/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,GACtB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,gBAAgB,EAChB,YAAY,GACb,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,wBAAwB,EACxB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,gBAAgB,EAChB,yBAAyB,EACzB,oBAAoB,GACrB,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
export async function measureMs(name, fn, detail) {
|
|
3
|
+
const t0 = performance.now();
|
|
4
|
+
const result = await fn();
|
|
5
|
+
const ms = performance.now() - t0;
|
|
6
|
+
const sample = { name, ms };
|
|
7
|
+
if (detail !== undefined)
|
|
8
|
+
sample.detail = detail;
|
|
9
|
+
return { result, sample };
|
|
10
|
+
}
|
|
11
|
+
export function formatPerfTable(samples) {
|
|
12
|
+
const lines = ["REWIND V3 PERFORMANCE (no optimisation)", ""];
|
|
13
|
+
for (const s of samples) {
|
|
14
|
+
lines.push(`${s.name.padEnd(32)} ${s.ms.toFixed(2).padStart(10)} ms${s.detail ? ` (${s.detail})` : ""}`);
|
|
15
|
+
}
|
|
16
|
+
return lines.join("\n");
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=perf.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perf.js","sourceRoot":"","sources":["../../../src/enforcement/perf.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9C,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAY,EACZ,EAAoB,EACpB,MAAe;IAEf,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;IAC1B,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IAClC,MAAM,MAAM,GAAe,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;IACxC,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC;IACjD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAqB;IACnD,MAAM,KAAK,GAAG,CAAC,yCAAyC,EAAE,EAAE,CAAC,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,IAAI,CACR,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PolicyEvent, PolicyEventType, PolicyEventStatus } from "./types.js";
|
|
2
|
+
export declare function newPolicyEventId(): string;
|
|
3
|
+
export declare function recordPolicyEvent(input: {
|
|
4
|
+
type: PolicyEventType;
|
|
5
|
+
path?: string | null;
|
|
6
|
+
mechanism: string;
|
|
7
|
+
evidence: string;
|
|
8
|
+
status: PolicyEventStatus;
|
|
9
|
+
}, projectRoot?: string): Promise<PolicyEvent>;
|
|
10
|
+
export declare function loadPolicyEvent(id: string, projectRoot?: string): Promise<PolicyEvent>;
|
|
11
|
+
export declare function listPolicyEvents(projectRoot?: string): Promise<PolicyEvent[]>;
|
|
12
|
+
export declare function formatPolicyViolation(event: PolicyEvent): string;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { mkdir, writeFile, readFile, readdir, rename, } from "node:fs/promises";
|
|
3
|
+
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { getPolicyDir, getProjectRoot } from "../paths.js";
|
|
5
|
+
async function writeJsonAtomic(file, data) {
|
|
6
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
7
|
+
const tmp = `${file}.tmp-${process.pid}`;
|
|
8
|
+
await writeFile(tmp, JSON.stringify(data, null, 2) + "\n", "utf8");
|
|
9
|
+
await rename(tmp, file);
|
|
10
|
+
}
|
|
11
|
+
export function newPolicyEventId() {
|
|
12
|
+
return `pol_${randomBytes(8).toString("hex")}`;
|
|
13
|
+
}
|
|
14
|
+
export async function recordPolicyEvent(input, projectRoot = getProjectRoot()) {
|
|
15
|
+
const event = {
|
|
16
|
+
id: newPolicyEventId(),
|
|
17
|
+
version: 3,
|
|
18
|
+
time: new Date().toISOString(),
|
|
19
|
+
type: input.type,
|
|
20
|
+
path: input.path ?? null,
|
|
21
|
+
mechanism: input.mechanism,
|
|
22
|
+
evidence: input.evidence,
|
|
23
|
+
status: input.status,
|
|
24
|
+
};
|
|
25
|
+
const dir = getPolicyDir(projectRoot);
|
|
26
|
+
await mkdir(dir, { recursive: true });
|
|
27
|
+
await writeJsonAtomic(path.join(dir, `${event.id}.json`), event);
|
|
28
|
+
await writeFile(path.join(dir, "index.jsonl"), JSON.stringify({
|
|
29
|
+
id: event.id,
|
|
30
|
+
type: event.type,
|
|
31
|
+
path: event.path,
|
|
32
|
+
status: event.status,
|
|
33
|
+
time: event.time,
|
|
34
|
+
}) + "\n", { flag: "a" });
|
|
35
|
+
await writeJsonAtomic(path.join(dir, "latest.json"), { id: event.id });
|
|
36
|
+
return event;
|
|
37
|
+
}
|
|
38
|
+
export async function loadPolicyEvent(id, projectRoot = getProjectRoot()) {
|
|
39
|
+
if (!/^pol_[A-Za-z0-9]+$/.test(id)) {
|
|
40
|
+
throw new Error(`Invalid policy event id: ${id}`);
|
|
41
|
+
}
|
|
42
|
+
const raw = await readFile(path.join(getPolicyDir(projectRoot), `${id}.json`), "utf8");
|
|
43
|
+
return JSON.parse(raw);
|
|
44
|
+
}
|
|
45
|
+
export async function listPolicyEvents(projectRoot = getProjectRoot()) {
|
|
46
|
+
const dir = getPolicyDir(projectRoot);
|
|
47
|
+
let names;
|
|
48
|
+
try {
|
|
49
|
+
names = await readdir(dir);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
const events = [];
|
|
55
|
+
for (const n of names) {
|
|
56
|
+
if (!n.startsWith("pol_") || !n.endsWith(".json"))
|
|
57
|
+
continue;
|
|
58
|
+
try {
|
|
59
|
+
events.push(await loadPolicyEvent(n.replace(/\.json$/, ""), projectRoot));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
/* skip */
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
events.sort((a, b) => a.time.localeCompare(b.time) || a.id.localeCompare(b.id));
|
|
66
|
+
return events;
|
|
67
|
+
}
|
|
68
|
+
export function formatPolicyViolation(event) {
|
|
69
|
+
return [
|
|
70
|
+
"POLICY VIOLATION",
|
|
71
|
+
"",
|
|
72
|
+
`Unexpected filesystem mutation detected:`,
|
|
73
|
+
event.path ?? "(unknown path)",
|
|
74
|
+
"",
|
|
75
|
+
"No mediated REWIND action exists for this change.",
|
|
76
|
+
"",
|
|
77
|
+
`Type: ${event.type}`,
|
|
78
|
+
`Mechanism: ${event.mechanism}`,
|
|
79
|
+
`Evidence: ${event.evidence}`,
|
|
80
|
+
`Status: ${event.status}`,
|
|
81
|
+
`Event: ${event.id}`,
|
|
82
|
+
].join("\n");
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../../src/enforcement/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare function lockEnforcedReadonly(projectRoot?: string): Promise<{
|
|
2
|
+
files: number;
|
|
3
|
+
dirs: number;
|
|
4
|
+
}>;
|
|
5
|
+
export declare function unlockEnforcedWritable(projectRoot?: string): Promise<{
|
|
6
|
+
files: number;
|
|
7
|
+
dirs: number;
|
|
8
|
+
}>;
|
|
9
|
+
/**
|
|
10
|
+
* Run fn while the enforced tree is briefly writable, then re-lock.
|
|
11
|
+
* Fail-closed: always attempts re-lock in finally.
|
|
12
|
+
*/
|
|
13
|
+
export declare function withEnforcedWriteAccess<T>(projectRoot: string, fn: () => Promise<T>): Promise<T>;
|
|
14
|
+
export declare function probeDirectWriteBlocked(projectRoot?: string): Promise<{
|
|
15
|
+
blocked: boolean;
|
|
16
|
+
error: string | null;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { chmod, lstat, readdir, realpath, } from "node:fs/promises";
|
|
3
|
+
import { ENFORCED_SANDBOX_DIR_NAME, PathSafetyError, assertApprovedSandbox, getEnforcedSandboxPath, getProjectRoot, isPathInside, } from "../paths.js";
|
|
4
|
+
/**
|
|
5
|
+
* Filesystem read-only lock for sandbox-enforced-project.
|
|
6
|
+
* Same UID as REWIND — broker must unlock briefly to mutate.
|
|
7
|
+
* This is NOT a separate identity boundary; document that clearly.
|
|
8
|
+
*/
|
|
9
|
+
async function walk(abs, root, visit) {
|
|
10
|
+
if (!(await isPathInsideAsync(root, abs))) {
|
|
11
|
+
throw new PathSafetyError(`Walk escape blocked: ${abs}`);
|
|
12
|
+
}
|
|
13
|
+
const st = await lstat(abs);
|
|
14
|
+
if (st.isSymbolicLink()) {
|
|
15
|
+
// Do not follow; leave symlink mode alone (often irrelevant)
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
if (st.isDirectory()) {
|
|
19
|
+
const kids = await readdir(abs);
|
|
20
|
+
for (const name of kids) {
|
|
21
|
+
await walk(path.join(abs, name), root, visit);
|
|
22
|
+
}
|
|
23
|
+
await visit(abs, true);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (st.isFile()) {
|
|
27
|
+
await visit(abs, false);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function isPathInsideAsync(root, candidate) {
|
|
31
|
+
if (isPathInside(root, candidate))
|
|
32
|
+
return true;
|
|
33
|
+
try {
|
|
34
|
+
const rr = await realpath(root);
|
|
35
|
+
const rc = await realpath(candidate);
|
|
36
|
+
return isPathInside(rr, rc);
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export async function lockEnforcedReadonly(projectRoot = getProjectRoot()) {
|
|
43
|
+
const root = getEnforcedSandboxPath(projectRoot);
|
|
44
|
+
await assertApprovedSandbox(root, projectRoot, ENFORCED_SANDBOX_DIR_NAME);
|
|
45
|
+
let files = 0;
|
|
46
|
+
let dirs = 0;
|
|
47
|
+
await walk(root, root, async (abs, isDir) => {
|
|
48
|
+
if (isDir) {
|
|
49
|
+
await chmod(abs, 0o555);
|
|
50
|
+
dirs += 1;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
await chmod(abs, 0o444);
|
|
54
|
+
files += 1;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
return { files, dirs };
|
|
58
|
+
}
|
|
59
|
+
export async function unlockEnforcedWritable(projectRoot = getProjectRoot()) {
|
|
60
|
+
const root = getEnforcedSandboxPath(projectRoot);
|
|
61
|
+
await assertApprovedSandbox(root, projectRoot, ENFORCED_SANDBOX_DIR_NAME);
|
|
62
|
+
let files = 0;
|
|
63
|
+
let dirs = 0;
|
|
64
|
+
// Unlock root first so we can traverse
|
|
65
|
+
await chmod(root, 0o755);
|
|
66
|
+
await walk(root, root, async (abs, isDir) => {
|
|
67
|
+
if (isDir) {
|
|
68
|
+
await chmod(abs, 0o755);
|
|
69
|
+
dirs += 1;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
await chmod(abs, 0o644);
|
|
73
|
+
files += 1;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
return { files, dirs };
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Run fn while the enforced tree is briefly writable, then re-lock.
|
|
80
|
+
* Fail-closed: always attempts re-lock in finally.
|
|
81
|
+
*/
|
|
82
|
+
export async function withEnforcedWriteAccess(projectRoot, fn) {
|
|
83
|
+
await unlockEnforcedWritable(projectRoot);
|
|
84
|
+
let result;
|
|
85
|
+
let fnError;
|
|
86
|
+
try {
|
|
87
|
+
result = await fn();
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
fnError = err;
|
|
91
|
+
}
|
|
92
|
+
try {
|
|
93
|
+
await lockEnforcedReadonly(projectRoot);
|
|
94
|
+
}
|
|
95
|
+
catch (err) {
|
|
96
|
+
process.stderr.write(`[rewind-enforcement] CRITICAL: failed to re-lock enforced sandbox: ${err instanceof Error ? err.message : String(err)}\n` +
|
|
97
|
+
`Recovery: chmod -R u+w "${getEnforcedSandboxPath(projectRoot)}" && ` +
|
|
98
|
+
`find "${getEnforcedSandboxPath(projectRoot)}" -type d -exec chmod 555 {} \\; && ` +
|
|
99
|
+
`find "${getEnforcedSandboxPath(projectRoot)}" -type f -exec chmod 444 {} \\;\n`);
|
|
100
|
+
if (fnError === undefined)
|
|
101
|
+
throw err;
|
|
102
|
+
throw fnError;
|
|
103
|
+
}
|
|
104
|
+
if (fnError !== undefined)
|
|
105
|
+
throw fnError;
|
|
106
|
+
return result;
|
|
107
|
+
}
|
|
108
|
+
export async function probeDirectWriteBlocked(projectRoot = getProjectRoot()) {
|
|
109
|
+
const root = getEnforcedSandboxPath(projectRoot);
|
|
110
|
+
const probe = path.join(root, `.rewind-probe-${process.pid}.txt`);
|
|
111
|
+
const { writeFile, rm } = await import("node:fs/promises");
|
|
112
|
+
try {
|
|
113
|
+
await writeFile(probe, "should-fail");
|
|
114
|
+
await rm(probe, { force: true }).catch(() => undefined);
|
|
115
|
+
return { blocked: false, error: null };
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
return {
|
|
119
|
+
blocked: true,
|
|
120
|
+
error: err instanceof Error ? err.message : String(err),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=readonly.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readonly.js","sourceRoot":"","sources":["../../../src/enforcement/readonly.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { materializeSandbox, SANDBOX_SEED } from "../sandbox.js";
|
|
2
|
+
/** Materialize deterministic sandbox content at an already-validated root. */
|
|
3
|
+
export async function planSandboxForRoot(root, seed = SANDBOX_SEED) {
|
|
4
|
+
const result = await materializeSandbox(root, seed);
|
|
5
|
+
return {
|
|
6
|
+
fileCount: result.fileCount,
|
|
7
|
+
directoryCount: result.directoryCount,
|
|
8
|
+
symlinkCount: result.symlinkCount,
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=sandbox-clone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-clone.js","sourceRoot":"","sources":["../../../src/enforcement/sandbox-clone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAEjE,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY,EACZ,OAAe,YAAY;IAM3B,MAAM,MAAM,GAAG,MAAM,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACpD,OAAO;QACL,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,cAAc,EAAE,MAAM,CAAC,cAAc;QACrC,YAAY,EAAE,MAAM,CAAC,YAAY;KAClC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { EnforcementMechanism, EnforcementState } from "./types.js";
|
|
2
|
+
export declare function enforcementStatePath(projectRoot?: string): string;
|
|
3
|
+
export declare function loadEnforcementState(projectRoot?: string): Promise<EnforcementState | null>;
|
|
4
|
+
export declare function saveEnforcementState(state: EnforcementState, projectRoot?: string): Promise<void>;
|
|
5
|
+
/**
|
|
6
|
+
* Create sandbox-enforced-project from the same deterministic plan as V0,
|
|
7
|
+
* without touching sandbox-test-project.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createEnforcedSandbox(projectRoot?: string): Promise<{
|
|
10
|
+
root: string;
|
|
11
|
+
fileCount: number;
|
|
12
|
+
directoryCount: number;
|
|
13
|
+
symlinkCount: number;
|
|
14
|
+
}>;
|
|
15
|
+
export declare function writeSeatbeltProfile(projectRoot?: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Run a command under sandbox-exec with writes to enforced sandbox denied.
|
|
18
|
+
*/
|
|
19
|
+
export declare function runUnderWriteDenySeatbelt(command: string, args: string[], profilePath: string): Promise<{
|
|
20
|
+
code: number;
|
|
21
|
+
stdout: string;
|
|
22
|
+
stderr: string;
|
|
23
|
+
}>;
|
|
24
|
+
export interface EnableEnforcementOptions {
|
|
25
|
+
mechanism?: EnforcementMechanism;
|
|
26
|
+
installHooks?: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare function enableEnforcement(projectRoot?: string, options?: EnableEnforcementOptions): Promise<EnforcementState>;
|
|
29
|
+
export declare function disableEnforcement(projectRoot?: string, options?: {
|
|
30
|
+
removeTree?: boolean;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
/** True when mediated writes to enforced sandbox must use broker unlock. */
|
|
33
|
+
export declare function isEnforcedLocked(projectRoot?: string): Promise<boolean>;
|