@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,49 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { lstat, readdir, readFile, readlink } from "node:fs/promises";
|
|
4
|
+
import { isPathInside } from "../paths.js";
|
|
5
|
+
import { toRelativePosix } from "../manifest.js";
|
|
6
|
+
const SKIP = new Set([".rewind", ".cursor", "node_modules", ".git", "dist"]);
|
|
7
|
+
/**
|
|
8
|
+
* Deterministic fingerprint of protected project file contents (excludes .rewind/.cursor).
|
|
9
|
+
*/
|
|
10
|
+
export async function fingerprintProject(projectRoot) {
|
|
11
|
+
const entries = [];
|
|
12
|
+
async function walk(dir) {
|
|
13
|
+
let kids;
|
|
14
|
+
try {
|
|
15
|
+
kids = await readdir(dir, { withFileTypes: true });
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
kids.sort((a, b) => a.name.localeCompare(b.name));
|
|
21
|
+
for (const ent of kids) {
|
|
22
|
+
if (SKIP.has(ent.name))
|
|
23
|
+
continue;
|
|
24
|
+
const abs = path.join(dir, ent.name);
|
|
25
|
+
if (!isPathInside(projectRoot, abs))
|
|
26
|
+
continue;
|
|
27
|
+
const rel = toRelativePosix(projectRoot, abs);
|
|
28
|
+
if (ent.isSymbolicLink()) {
|
|
29
|
+
const target = await readlink(abs);
|
|
30
|
+
entries.push(`L:${rel}:${target}`);
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (ent.isDirectory()) {
|
|
34
|
+
entries.push(`D:${rel}`);
|
|
35
|
+
await walk(abs);
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (ent.isFile()) {
|
|
39
|
+
const data = await readFile(abs);
|
|
40
|
+
const h = createHash("sha256").update(data).digest("hex");
|
|
41
|
+
const st = await lstat(abs);
|
|
42
|
+
entries.push(`F:${rel}:${h}:${st.mode & 0o7777}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
await walk(projectRoot);
|
|
47
|
+
return createHash("sha256").update(entries.join("\n")).digest("hex");
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=fingerprint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fingerprint.js","sourceRoot":"","sources":["../../../src/protect/fingerprint.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7E;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,WAAmB;IAC1D,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,IAAI,CAAC,GAAW;QAC7B,IAAI,IAAI,CAAC;QACT,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;QACT,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QAClD,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,SAAS;YACjC,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;YACrC,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,GAAG,CAAC;gBAAE,SAAS;YAC9C,MAAM,GAAG,GAAG,eAAe,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;YAC9C,IAAI,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC;gBACzB,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,MAAM,EAAE,CAAC,CAAC;gBACnC,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;gBACtB,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;gBACzB,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,SAAS;YACX,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;gBACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;gBACjC,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC1D,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC5B,OAAO,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,GAAG,MAAM,EAAE,CAAC,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,IAAI,CAAC,WAAW,CAAC,CAAC;IACxB,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Hook CLI entry — reads Cursor hook JSON on stdin, writes decision JSON on stdout.
|
|
4
|
+
* Invoked by .cursor/hooks/rewind-protect.mjs
|
|
5
|
+
*/
|
|
6
|
+
import { readFileSync } from "node:fs";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import { handlePostFailure, handlePostHook, handlePreHook, recoverCrashState, } from "./intercept.js";
|
|
9
|
+
import { loadActiveSession, loadProtectState, saveSession } from "./store.js";
|
|
10
|
+
import { appendAuditEvent } from "./audit.js";
|
|
11
|
+
function projectRootOf() {
|
|
12
|
+
if (process.env.REWIND_PROTECT_ROOT) {
|
|
13
|
+
return path.resolve(process.env.REWIND_PROTECT_ROOT);
|
|
14
|
+
}
|
|
15
|
+
return path.resolve(process.cwd());
|
|
16
|
+
}
|
|
17
|
+
function deny(msg) {
|
|
18
|
+
process.stdout.write(JSON.stringify({
|
|
19
|
+
permission: "deny",
|
|
20
|
+
user_message: msg,
|
|
21
|
+
agent_message: msg,
|
|
22
|
+
}));
|
|
23
|
+
process.exit(2);
|
|
24
|
+
}
|
|
25
|
+
async function main() {
|
|
26
|
+
const projectRoot = projectRootOf();
|
|
27
|
+
const state = await loadProtectState(projectRoot);
|
|
28
|
+
if (!state?.protected) {
|
|
29
|
+
process.stdout.write(JSON.stringify({ permission: "allow" }));
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
let raw = "";
|
|
33
|
+
try {
|
|
34
|
+
raw = readFileSync(0, "utf8");
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
deny("REWIND: failed to read hook stdin");
|
|
38
|
+
}
|
|
39
|
+
let payload;
|
|
40
|
+
try {
|
|
41
|
+
payload = JSON.parse(raw || "{}");
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
deny("REWIND: invalid hook JSON");
|
|
45
|
+
}
|
|
46
|
+
const event = String(payload.hook_event_name ?? "");
|
|
47
|
+
try {
|
|
48
|
+
if (event === "sessionStart") {
|
|
49
|
+
await recoverCrashState(projectRoot);
|
|
50
|
+
const session = await loadActiveSession(projectRoot);
|
|
51
|
+
await appendAuditEvent({
|
|
52
|
+
type: "CURSOR_SESSION_STARTED",
|
|
53
|
+
sessionId: session?.id,
|
|
54
|
+
detail: String(payload.session_id ?? ""),
|
|
55
|
+
}, projectRoot);
|
|
56
|
+
process.stdout.write(JSON.stringify({
|
|
57
|
+
additional_context: "REWIND protected session active. Native file edits are ledgered automatically. Prefer Write/StrReplace/Delete over shell for mutations.",
|
|
58
|
+
}));
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
if (event === "sessionEnd") {
|
|
62
|
+
const session = await loadActiveSession(projectRoot);
|
|
63
|
+
if (session && session.status === "ACTIVE") {
|
|
64
|
+
// Keep ACTIVE across Cursor restarts while protect is enabled —
|
|
65
|
+
// only mark COMPLETED on explicit unprotect / undo-session completion.
|
|
66
|
+
if (typeof payload.session_id === "string") {
|
|
67
|
+
session.cursor.sessionId = payload.session_id;
|
|
68
|
+
}
|
|
69
|
+
await saveSession(session, projectRoot);
|
|
70
|
+
}
|
|
71
|
+
process.stdout.write(JSON.stringify({}));
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (event === "postToolUse" ||
|
|
75
|
+
event === "afterFileEdit" ||
|
|
76
|
+
event === "afterShellExecution" ||
|
|
77
|
+
event === "afterMCPExecution") {
|
|
78
|
+
const decision = await handlePostHook(payload, projectRoot);
|
|
79
|
+
process.stdout.write(JSON.stringify(decision));
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (event === "postToolUseFailure") {
|
|
83
|
+
const decision = await handlePostFailure(payload, projectRoot);
|
|
84
|
+
process.stdout.write(JSON.stringify(decision));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
// Default: pre-style gates
|
|
88
|
+
const decision = await handlePreHook(payload, projectRoot);
|
|
89
|
+
process.stdout.write(JSON.stringify(decision));
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
// Fail closed for security-critical paths
|
|
93
|
+
const critical = event === "preToolUse" ||
|
|
94
|
+
event === "beforeShellExecution" ||
|
|
95
|
+
event === "" ||
|
|
96
|
+
!event;
|
|
97
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
98
|
+
if (critical) {
|
|
99
|
+
deny(`REWIND hook error (fail closed): ${msg}`);
|
|
100
|
+
}
|
|
101
|
+
process.stdout.write(JSON.stringify({ permission: "allow" }));
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
await main().catch((err) => {
|
|
105
|
+
deny(err instanceof Error ? err.message : String(err));
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=hook-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-cli.js","sourceRoot":"","sources":["../../../src/protect/hook-cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type { ProtectedSession, ProtectState, ProtectActionRecord, SessionUndoResult, AuditEvent, HookDecision, } from "./types.js";
|
|
2
|
+
export { protectProject, unprotectProject, resolveProtectTarget } from "./protect.js";
|
|
3
|
+
export { undoProtectAction, undoProtectedSession } from "./undo-session.js";
|
|
4
|
+
export { formatProtectStatus, formatSessionsList, formatActionsList, classifyProtectUnknownMutation, } from "./status.js";
|
|
5
|
+
export { decideProtectedShell } from "./shell-policy.js";
|
|
6
|
+
export { handlePreHook, handlePostHook, handlePostFailure, recoverCrashState, } from "./intercept.js";
|
|
7
|
+
export { mergeHooksJson, stripRewindHooks, mergeMcpJson, stripMcpServer, breakProtectHook, restoreProtectHook, installProtectArtifacts, } from "./install.js";
|
|
8
|
+
export { loadProtectState, loadActiveSession, listSessions, listProtectActions, loadSession, loadProtectAction, markIncompleteProtectFailed, } from "./store.js";
|
|
9
|
+
export { appendAuditEvent, readAuditEvents } from "./audit.js";
|
|
10
|
+
export { fingerprintProject } from "./fingerprint.js";
|
|
11
|
+
export { captureProtectedEntry, restoreProtectedSnapshot, snapshotIdentityHash, } from "./capture.js";
|
|
12
|
+
export { resolveProtectedRelative } from "./root-paths.js";
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export { protectProject, unprotectProject, resolveProtectTarget } from "./protect.js";
|
|
2
|
+
export { undoProtectAction, undoProtectedSession } from "./undo-session.js";
|
|
3
|
+
export { formatProtectStatus, formatSessionsList, formatActionsList, classifyProtectUnknownMutation, } from "./status.js";
|
|
4
|
+
export { decideProtectedShell } from "./shell-policy.js";
|
|
5
|
+
export { handlePreHook, handlePostHook, handlePostFailure, recoverCrashState, } from "./intercept.js";
|
|
6
|
+
export { mergeHooksJson, stripRewindHooks, mergeMcpJson, stripMcpServer, breakProtectHook, restoreProtectHook, installProtectArtifacts, } from "./install.js";
|
|
7
|
+
export { loadProtectState, loadActiveSession, listSessions, listProtectActions, loadSession, loadProtectAction, markIncompleteProtectFailed, } from "./store.js";
|
|
8
|
+
export { appendAuditEvent, readAuditEvents } from "./audit.js";
|
|
9
|
+
export { fingerprintProject } from "./fingerprint.js";
|
|
10
|
+
export { captureProtectedEntry, restoreProtectedSnapshot, snapshotIdentityHash, } from "./capture.js";
|
|
11
|
+
export { resolveProtectedRelative } from "./root-paths.js";
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/protect/index.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,8BAA8B,GAC/B,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EACL,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,kBAAkB,EAClB,uBAAuB,GACxB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,2BAA2B,GAC5B,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EACL,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,wBAAwB,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface HooksJson {
|
|
2
|
+
version: number;
|
|
3
|
+
hooks: Record<string, HookEntry[]>;
|
|
4
|
+
}
|
|
5
|
+
export interface HookEntry {
|
|
6
|
+
command: string;
|
|
7
|
+
matcher?: string;
|
|
8
|
+
failClosed?: boolean;
|
|
9
|
+
timeout?: number;
|
|
10
|
+
type?: string;
|
|
11
|
+
/** Internal marker — stripped before write if present */
|
|
12
|
+
_rewind?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare function mergeHooksJson(existing: HooksJson | null, rewindEntries: Record<string, HookEntry[]>): HooksJson;
|
|
15
|
+
export declare function stripRewindHooks(existing: HooksJson): HooksJson;
|
|
16
|
+
export interface McpJson {
|
|
17
|
+
mcpServers?: Record<string, unknown>;
|
|
18
|
+
}
|
|
19
|
+
export declare function mergeMcpJson(existing: McpJson | null, serverName: string, serverConfig: unknown): McpJson;
|
|
20
|
+
export declare function stripMcpServer(existing: McpJson, serverName: string): McpJson;
|
|
21
|
+
export declare function resolveHookModule(packageRoot: string): string;
|
|
22
|
+
export declare function buildRewindHookEntries(hookCommand: string): Record<string, HookEntry[]>;
|
|
23
|
+
export declare function installProtectArtifacts(projectRoot: string, options?: {
|
|
24
|
+
rewindPackageRoot?: string;
|
|
25
|
+
}): Promise<{
|
|
26
|
+
hookCommand: string;
|
|
27
|
+
hookModule: string;
|
|
28
|
+
managedEvents: string[];
|
|
29
|
+
mcpServerName: string;
|
|
30
|
+
}>;
|
|
31
|
+
export declare function uninstallProtectArtifacts(projectRoot: string, mcpServerName?: string): Promise<void>;
|
|
32
|
+
/** Test helper: break hook for fail-closed demos (rename aside). */
|
|
33
|
+
export declare function breakProtectHook(projectRoot: string): Promise<string>;
|
|
34
|
+
export declare function restoreProtectHook(projectRoot: string): Promise<void>;
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Install / merge Cursor hooks + MCP config for a protected project.
|
|
3
|
+
* Preserves unrelated user configuration.
|
|
4
|
+
*/
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { mkdir, writeFile, readFile, chmod, access, copyFile, } from "node:fs/promises";
|
|
7
|
+
import { constants as fsConstants, existsSync } from "node:fs";
|
|
8
|
+
import { getPackageRoot } from "../paths.js";
|
|
9
|
+
const REWIND_HOOK_MARKER = "rewind-protect";
|
|
10
|
+
function isRewindHook(entry) {
|
|
11
|
+
return (entry.command.includes(REWIND_HOOK_MARKER) ||
|
|
12
|
+
entry.command.includes("rewind-protect"));
|
|
13
|
+
}
|
|
14
|
+
export function mergeHooksJson(existing, rewindEntries) {
|
|
15
|
+
const base = existing ?? { version: 1, hooks: {} };
|
|
16
|
+
const hooks = { ...base.hooks };
|
|
17
|
+
for (const [event, entries] of Object.entries(rewindEntries)) {
|
|
18
|
+
const prev = hooks[event] ?? [];
|
|
19
|
+
const kept = prev.filter((e) => !isRewindHook(e));
|
|
20
|
+
hooks[event] = [...kept, ...entries];
|
|
21
|
+
}
|
|
22
|
+
return { version: 1, hooks };
|
|
23
|
+
}
|
|
24
|
+
export function stripRewindHooks(existing) {
|
|
25
|
+
const hooks = {};
|
|
26
|
+
for (const [event, entries] of Object.entries(existing.hooks ?? {})) {
|
|
27
|
+
const kept = entries.filter((e) => !isRewindHook(e));
|
|
28
|
+
if (kept.length > 0)
|
|
29
|
+
hooks[event] = kept;
|
|
30
|
+
}
|
|
31
|
+
return { version: existing.version ?? 1, hooks };
|
|
32
|
+
}
|
|
33
|
+
export function mergeMcpJson(existing, serverName, serverConfig) {
|
|
34
|
+
const base = existing ? { ...existing } : {};
|
|
35
|
+
const servers = { ...(base.mcpServers ?? {}) };
|
|
36
|
+
servers[serverName] = serverConfig;
|
|
37
|
+
return { ...base, mcpServers: servers };
|
|
38
|
+
}
|
|
39
|
+
export function stripMcpServer(existing, serverName) {
|
|
40
|
+
const servers = { ...(existing.mcpServers ?? {}) };
|
|
41
|
+
delete servers[serverName];
|
|
42
|
+
return { ...existing, mcpServers: servers };
|
|
43
|
+
}
|
|
44
|
+
function rewindPackageRoot() {
|
|
45
|
+
return getPackageRoot();
|
|
46
|
+
}
|
|
47
|
+
export function resolveHookModule(packageRoot) {
|
|
48
|
+
const dist = path.join(packageRoot, "dist", "src", "protect", "hook-cli.js");
|
|
49
|
+
const src = path.join(packageRoot, "src", "protect", "hook-cli.ts");
|
|
50
|
+
if (existsSync(dist))
|
|
51
|
+
return dist;
|
|
52
|
+
return src;
|
|
53
|
+
}
|
|
54
|
+
export function buildRewindHookEntries(hookCommand) {
|
|
55
|
+
return {
|
|
56
|
+
sessionStart: [
|
|
57
|
+
{
|
|
58
|
+
command: hookCommand,
|
|
59
|
+
failClosed: false,
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
sessionEnd: [
|
|
63
|
+
{
|
|
64
|
+
command: hookCommand,
|
|
65
|
+
failClosed: false,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
preToolUse: [
|
|
69
|
+
{
|
|
70
|
+
command: hookCommand,
|
|
71
|
+
matcher: "Write|Delete|StrReplace|EditNotebook|Shell",
|
|
72
|
+
failClosed: true,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
postToolUse: [
|
|
76
|
+
{
|
|
77
|
+
command: hookCommand,
|
|
78
|
+
matcher: "Write|Delete|StrReplace|EditNotebook",
|
|
79
|
+
failClosed: false,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
postToolUseFailure: [
|
|
83
|
+
{
|
|
84
|
+
command: hookCommand,
|
|
85
|
+
matcher: "Write|Delete|StrReplace|EditNotebook",
|
|
86
|
+
failClosed: false,
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
afterFileEdit: [
|
|
90
|
+
{
|
|
91
|
+
command: hookCommand,
|
|
92
|
+
failClosed: false,
|
|
93
|
+
},
|
|
94
|
+
],
|
|
95
|
+
beforeShellExecution: [
|
|
96
|
+
{
|
|
97
|
+
command: hookCommand,
|
|
98
|
+
failClosed: true,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
beforeMCPExecution: [
|
|
102
|
+
{
|
|
103
|
+
command: hookCommand,
|
|
104
|
+
failClosed: false,
|
|
105
|
+
},
|
|
106
|
+
],
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
export async function installProtectArtifacts(projectRoot, options = {}) {
|
|
110
|
+
const pkg = options.rewindPackageRoot ?? rewindPackageRoot();
|
|
111
|
+
const hookModule = resolveHookModule(pkg);
|
|
112
|
+
const cursorDir = path.join(projectRoot, ".cursor");
|
|
113
|
+
const hooksDir = path.join(cursorDir, "hooks");
|
|
114
|
+
await mkdir(hooksDir, { recursive: true });
|
|
115
|
+
// Thin wrapper script — always resolves project-local config
|
|
116
|
+
const wrapperPath = path.join(hooksDir, "rewind-protect.mjs");
|
|
117
|
+
const wrapper = `#!/usr/bin/env node
|
|
118
|
+
/**
|
|
119
|
+
* REWIND V4 protect hook — fail closed on errors for security-critical events.
|
|
120
|
+
* Managed by \`rewind protect\` / \`rewind unprotect\`. Do not edit by hand.
|
|
121
|
+
*/
|
|
122
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
123
|
+
import { spawnSync } from "node:child_process";
|
|
124
|
+
import path from "node:path";
|
|
125
|
+
import { fileURLToPath } from "node:url";
|
|
126
|
+
|
|
127
|
+
const projectRoot = process.cwd();
|
|
128
|
+
const cfgPath = path.join(projectRoot, ".rewind", "protect", "config.json");
|
|
129
|
+
|
|
130
|
+
function deny(msg) {
|
|
131
|
+
process.stdout.write(JSON.stringify({
|
|
132
|
+
permission: "deny",
|
|
133
|
+
user_message: msg,
|
|
134
|
+
agent_message: msg,
|
|
135
|
+
}));
|
|
136
|
+
process.exit(2);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
let raw = "";
|
|
140
|
+
try {
|
|
141
|
+
raw = readFileSync(0, "utf8");
|
|
142
|
+
} catch {
|
|
143
|
+
deny("REWIND hook: failed to read stdin");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
if (!existsSync(cfgPath)) {
|
|
147
|
+
// Not protected — allow (should not be installed without config)
|
|
148
|
+
process.stdout.write(JSON.stringify({ permission: "allow" }));
|
|
149
|
+
process.exit(0);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
let cfg;
|
|
153
|
+
try {
|
|
154
|
+
cfg = JSON.parse(readFileSync(cfgPath, "utf8"));
|
|
155
|
+
} catch {
|
|
156
|
+
deny("REWIND hook: invalid protect config");
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const hookModule = cfg.hookModule;
|
|
160
|
+
const isTs = hookModule.endsWith(".ts");
|
|
161
|
+
const runner = isTs
|
|
162
|
+
? ["npx", ["tsx", hookModule]]
|
|
163
|
+
: ["node", [hookModule]];
|
|
164
|
+
|
|
165
|
+
const result = spawnSync(runner[0], runner[1], {
|
|
166
|
+
input: raw,
|
|
167
|
+
encoding: "utf8",
|
|
168
|
+
cwd: projectRoot,
|
|
169
|
+
env: {
|
|
170
|
+
...process.env,
|
|
171
|
+
REWIND_PROTECT_ROOT: projectRoot,
|
|
172
|
+
},
|
|
173
|
+
timeout: 30000,
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
if (result.error || result.status === null) {
|
|
177
|
+
deny("REWIND hook: runner failed to start");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (result.status !== 0) {
|
|
181
|
+
// Propagate deny / fail-closed
|
|
182
|
+
if (result.stdout) process.stdout.write(result.stdout);
|
|
183
|
+
else deny("REWIND hook: non-zero exit without JSON");
|
|
184
|
+
process.exit(result.status === 2 ? 2 : 2);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
process.stdout.write(result.stdout || JSON.stringify({ permission: "allow" }));
|
|
188
|
+
process.exit(0);
|
|
189
|
+
`;
|
|
190
|
+
await writeFile(wrapperPath, wrapper, "utf8");
|
|
191
|
+
await chmod(wrapperPath, 0o755);
|
|
192
|
+
const hookCommand = "node .cursor/hooks/rewind-protect.mjs";
|
|
193
|
+
const rewindEntries = buildRewindHookEntries(hookCommand);
|
|
194
|
+
// Merge hooks.json
|
|
195
|
+
const hooksPath = path.join(cursorDir, "hooks.json");
|
|
196
|
+
let existingHooks = null;
|
|
197
|
+
try {
|
|
198
|
+
existingHooks = JSON.parse(await readFile(hooksPath, "utf8"));
|
|
199
|
+
}
|
|
200
|
+
catch {
|
|
201
|
+
/* none */
|
|
202
|
+
}
|
|
203
|
+
const merged = mergeHooksJson(existingHooks, rewindEntries);
|
|
204
|
+
await writeFile(hooksPath, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
205
|
+
// Merge mcp.json — optional REWIND server pointing at package
|
|
206
|
+
const mcpPath = path.join(cursorDir, "mcp.json");
|
|
207
|
+
let existingMcp = null;
|
|
208
|
+
try {
|
|
209
|
+
existingMcp = JSON.parse(await readFile(mcpPath, "utf8"));
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
/* none */
|
|
213
|
+
}
|
|
214
|
+
const mcpServerName = "rewind";
|
|
215
|
+
// MCP is optional for Model A; still wire for undo/status convenience
|
|
216
|
+
const serverConfig = {
|
|
217
|
+
command: "npx",
|
|
218
|
+
args: ["tsx", path.join(pkg, "src", "mcp", "server.ts")],
|
|
219
|
+
env: {
|
|
220
|
+
REWIND_PROJECT_ROOT: pkg,
|
|
221
|
+
},
|
|
222
|
+
};
|
|
223
|
+
const mergedMcp = mergeMcpJson(existingMcp, mcpServerName, serverConfig);
|
|
224
|
+
await writeFile(mcpPath, JSON.stringify(mergedMcp, null, 2) + "\n", "utf8");
|
|
225
|
+
// Self-test: wrapper exists and is executable
|
|
226
|
+
await access(wrapperPath, fsConstants.X_OK).catch(async () => {
|
|
227
|
+
await chmod(wrapperPath, 0o755);
|
|
228
|
+
});
|
|
229
|
+
return {
|
|
230
|
+
hookCommand,
|
|
231
|
+
hookModule,
|
|
232
|
+
managedEvents: Object.keys(rewindEntries),
|
|
233
|
+
mcpServerName,
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
export async function uninstallProtectArtifacts(projectRoot, mcpServerName = "rewind") {
|
|
237
|
+
const cursorDir = path.join(projectRoot, ".cursor");
|
|
238
|
+
const hooksPath = path.join(cursorDir, "hooks.json");
|
|
239
|
+
try {
|
|
240
|
+
const existing = JSON.parse(await readFile(hooksPath, "utf8"));
|
|
241
|
+
const stripped = stripRewindHooks(existing);
|
|
242
|
+
await writeFile(hooksPath, JSON.stringify(stripped, null, 2) + "\n", "utf8");
|
|
243
|
+
}
|
|
244
|
+
catch {
|
|
245
|
+
/* none */
|
|
246
|
+
}
|
|
247
|
+
const mcpPath = path.join(cursorDir, "mcp.json");
|
|
248
|
+
try {
|
|
249
|
+
const existing = JSON.parse(await readFile(mcpPath, "utf8"));
|
|
250
|
+
// Only remove if it looks like our managed entry (tsx path to rewind mcp)
|
|
251
|
+
const entry = existing.mcpServers?.[mcpServerName];
|
|
252
|
+
if (entry?.args?.some((a) => typeof a === "string" && a.includes("mcp") && a.includes("rewind")) ||
|
|
253
|
+
entry?.args?.some((a) => typeof a === "string" && a.includes("server.ts"))) {
|
|
254
|
+
const stripped = stripMcpServer(existing, mcpServerName);
|
|
255
|
+
await writeFile(mcpPath, JSON.stringify(stripped, null, 2) + "\n", "utf8");
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
/* none */
|
|
260
|
+
}
|
|
261
|
+
// Leave rewind-protect.mjs in place but harmless without config;
|
|
262
|
+
// optionally remove wrapper
|
|
263
|
+
try {
|
|
264
|
+
const { unlink } = await import("node:fs/promises");
|
|
265
|
+
await unlink(path.join(cursorDir, "hooks", "rewind-protect.mjs"));
|
|
266
|
+
}
|
|
267
|
+
catch {
|
|
268
|
+
/* */
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/** Test helper: break hook for fail-closed demos (rename aside). */
|
|
272
|
+
export async function breakProtectHook(projectRoot) {
|
|
273
|
+
const src = path.join(projectRoot, ".cursor", "hooks", "rewind-protect.mjs");
|
|
274
|
+
const bak = src + ".broken-bak";
|
|
275
|
+
await copyFile(src, bak);
|
|
276
|
+
await writeFile(src, "#!/usr/bin/env node\nthrow new Error('broken');\n", "utf8");
|
|
277
|
+
await chmod(src, 0o755);
|
|
278
|
+
return bak;
|
|
279
|
+
}
|
|
280
|
+
export async function restoreProtectHook(projectRoot) {
|
|
281
|
+
const src = path.join(projectRoot, ".cursor", "hooks", "rewind-protect.mjs");
|
|
282
|
+
const bak = src + ".broken-bak";
|
|
283
|
+
const { rename: ren, unlink } = await import("node:fs/promises");
|
|
284
|
+
try {
|
|
285
|
+
await ren(bak, src);
|
|
286
|
+
}
|
|
287
|
+
catch {
|
|
288
|
+
// reinstall
|
|
289
|
+
await installProtectArtifacts(projectRoot);
|
|
290
|
+
}
|
|
291
|
+
await unlink(bak).catch(() => undefined);
|
|
292
|
+
}
|
|
293
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../../src/protect/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { HookDecision } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Handle preToolUse / beforeShellExecution / beforeMCPExecution.
|
|
4
|
+
*/
|
|
5
|
+
export declare function handlePreHook(payload: Record<string, unknown>, projectRoot: string): Promise<HookDecision>;
|
|
6
|
+
/**
|
|
7
|
+
* Handle postToolUse / afterFileEdit — complete PREPARED/EXECUTING actions.
|
|
8
|
+
*/
|
|
9
|
+
export declare function handlePostHook(payload: Record<string, unknown>, projectRoot: string): Promise<HookDecision>;
|
|
10
|
+
export declare function handlePostFailure(payload: Record<string, unknown>, projectRoot: string): Promise<HookDecision>;
|
|
11
|
+
export declare function recoverCrashState(projectRoot: string): Promise<number>;
|