@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.
Files changed (244) hide show
  1. package/.env.example +8 -0
  2. package/LICENSE +21 -0
  3. package/README.md +39 -0
  4. package/dist/src/action/capture.d.ts +15 -0
  5. package/dist/src/action/capture.js +215 -0
  6. package/dist/src/action/capture.js.map +1 -0
  7. package/dist/src/action/mediate.d.ts +28 -0
  8. package/dist/src/action/mediate.js +109 -0
  9. package/dist/src/action/mediate.js.map +1 -0
  10. package/dist/src/action/mutate.d.ts +11 -0
  11. package/dist/src/action/mutate.js +189 -0
  12. package/dist/src/action/mutate.js.map +1 -0
  13. package/dist/src/action/objects.d.ts +5 -0
  14. package/dist/src/action/objects.js +50 -0
  15. package/dist/src/action/objects.js.map +1 -0
  16. package/dist/src/action/store.d.ts +24 -0
  17. package/dist/src/action/store.js +149 -0
  18. package/dist/src/action/store.js.map +1 -0
  19. package/dist/src/action/types.d.ts +84 -0
  20. package/dist/src/action/types.js +3 -0
  21. package/dist/src/action/types.js.map +1 -0
  22. package/dist/src/action/undo.d.ts +11 -0
  23. package/dist/src/action/undo.js +42 -0
  24. package/dist/src/action/undo.js.map +1 -0
  25. package/dist/src/adapters/filesystem.d.ts +35 -0
  26. package/dist/src/adapters/filesystem.js +499 -0
  27. package/dist/src/adapters/filesystem.js.map +1 -0
  28. package/dist/src/adapters/index.d.ts +7 -0
  29. package/dist/src/adapters/index.js +19 -0
  30. package/dist/src/adapters/index.js.map +1 -0
  31. package/dist/src/adapters/types.d.ts +54 -0
  32. package/dist/src/adapters/types.js +7 -0
  33. package/dist/src/adapters/types.js.map +1 -0
  34. package/dist/src/api/server.d.ts +25 -0
  35. package/dist/src/api/server.js +786 -0
  36. package/dist/src/api/server.js.map +1 -0
  37. package/dist/src/approval/store.d.ts +35 -0
  38. package/dist/src/approval/store.js +113 -0
  39. package/dist/src/approval/store.js.map +1 -0
  40. package/dist/src/checkpoint.d.ts +9 -0
  41. package/dist/src/checkpoint.js +140 -0
  42. package/dist/src/checkpoint.js.map +1 -0
  43. package/dist/src/cli/v5.d.ts +15 -0
  44. package/dist/src/cli/v5.js +110 -0
  45. package/dist/src/cli/v5.js.map +1 -0
  46. package/dist/src/cli.d.ts +2 -0
  47. package/dist/src/cli.js +823 -0
  48. package/dist/src/cli.js.map +1 -0
  49. package/dist/src/clients/types.d.ts +90 -0
  50. package/dist/src/clients/types.js +239 -0
  51. package/dist/src/clients/types.js.map +1 -0
  52. package/dist/src/commercial/auth/provider.d.ts +61 -0
  53. package/dist/src/commercial/auth/provider.js +227 -0
  54. package/dist/src/commercial/auth/provider.js.map +1 -0
  55. package/dist/src/commercial/entitlement/provider.d.ts +27 -0
  56. package/dist/src/commercial/entitlement/provider.js +192 -0
  57. package/dist/src/commercial/entitlement/provider.js.map +1 -0
  58. package/dist/src/commercial/entitlement/signing.d.ts +61 -0
  59. package/dist/src/commercial/entitlement/signing.js +124 -0
  60. package/dist/src/commercial/entitlement/signing.js.map +1 -0
  61. package/dist/src/commercial/env.d.ts +10 -0
  62. package/dist/src/commercial/env.js +40 -0
  63. package/dist/src/commercial/env.js.map +1 -0
  64. package/dist/src/commercial/product.d.ts +26 -0
  65. package/dist/src/commercial/product.js +39 -0
  66. package/dist/src/commercial/product.js.map +1 -0
  67. package/dist/src/commercial/store.d.ts +46 -0
  68. package/dist/src/commercial/store.js +104 -0
  69. package/dist/src/commercial/store.js.map +1 -0
  70. package/dist/src/commercial/stripe/checkout.d.ts +104 -0
  71. package/dist/src/commercial/stripe/checkout.js +469 -0
  72. package/dist/src/commercial/stripe/checkout.js.map +1 -0
  73. package/dist/src/core/compatibility.d.ts +15 -0
  74. package/dist/src/core/compatibility.js +226 -0
  75. package/dist/src/core/compatibility.js.map +1 -0
  76. package/dist/src/core/engine.d.ts +33 -0
  77. package/dist/src/core/engine.js +432 -0
  78. package/dist/src/core/engine.js.map +1 -0
  79. package/dist/src/core/lifecycle.d.ts +17 -0
  80. package/dist/src/core/lifecycle.js +56 -0
  81. package/dist/src/core/lifecycle.js.map +1 -0
  82. package/dist/src/core/types.d.ts +140 -0
  83. package/dist/src/core/types.js +37 -0
  84. package/dist/src/core/types.js.map +1 -0
  85. package/dist/src/destroy.d.ts +21 -0
  86. package/dist/src/destroy.js +219 -0
  87. package/dist/src/destroy.js.map +1 -0
  88. package/dist/src/diff.d.ts +13 -0
  89. package/dist/src/diff.js +251 -0
  90. package/dist/src/diff.js.map +1 -0
  91. package/dist/src/enforcement/detect.d.ts +13 -0
  92. package/dist/src/enforcement/detect.js +75 -0
  93. package/dist/src/enforcement/detect.js.map +1 -0
  94. package/dist/src/enforcement/hook-policy.d.ts +38 -0
  95. package/dist/src/enforcement/hook-policy.js +111 -0
  96. package/dist/src/enforcement/hook-policy.js.map +1 -0
  97. package/dist/src/enforcement/index.d.ts +8 -0
  98. package/dist/src/enforcement/index.js +8 -0
  99. package/dist/src/enforcement/index.js.map +1 -0
  100. package/dist/src/enforcement/perf.d.ts +6 -0
  101. package/dist/src/enforcement/perf.js +18 -0
  102. package/dist/src/enforcement/perf.js.map +1 -0
  103. package/dist/src/enforcement/policy.d.ts +12 -0
  104. package/dist/src/enforcement/policy.js +84 -0
  105. package/dist/src/enforcement/policy.js.map +1 -0
  106. package/dist/src/enforcement/readonly.d.ts +17 -0
  107. package/dist/src/enforcement/readonly.js +124 -0
  108. package/dist/src/enforcement/readonly.js.map +1 -0
  109. package/dist/src/enforcement/sandbox-clone.d.ts +6 -0
  110. package/dist/src/enforcement/sandbox-clone.js +11 -0
  111. package/dist/src/enforcement/sandbox-clone.js.map +1 -0
  112. package/dist/src/enforcement/setup.d.ts +33 -0
  113. package/dist/src/enforcement/setup.js +168 -0
  114. package/dist/src/enforcement/setup.js.map +1 -0
  115. package/dist/src/enforcement/trust.d.ts +10 -0
  116. package/dist/src/enforcement/trust.js +71 -0
  117. package/dist/src/enforcement/trust.js.map +1 -0
  118. package/dist/src/enforcement/types.d.ts +40 -0
  119. package/dist/src/enforcement/types.js +3 -0
  120. package/dist/src/enforcement/types.js.map +1 -0
  121. package/dist/src/entitlement/provider.d.ts +48 -0
  122. package/dist/src/entitlement/provider.js +95 -0
  123. package/dist/src/entitlement/provider.js.map +1 -0
  124. package/dist/src/hash.d.ts +9 -0
  125. package/dist/src/hash.js +23 -0
  126. package/dist/src/hash.js.map +1 -0
  127. package/dist/src/ledger/query.d.ts +19 -0
  128. package/dist/src/ledger/query.js +158 -0
  129. package/dist/src/ledger/query.js.map +1 -0
  130. package/dist/src/manifest.d.ts +32 -0
  131. package/dist/src/manifest.js +242 -0
  132. package/dist/src/manifest.js.map +1 -0
  133. package/dist/src/mcp/server.d.ts +7 -0
  134. package/dist/src/mcp/server.js +364 -0
  135. package/dist/src/mcp/server.js.map +1 -0
  136. package/dist/src/paths.d.ts +94 -0
  137. package/dist/src/paths.js +354 -0
  138. package/dist/src/paths.js.map +1 -0
  139. package/dist/src/permission/engine.d.ts +15 -0
  140. package/dist/src/permission/engine.js +147 -0
  141. package/dist/src/permission/engine.js.map +1 -0
  142. package/dist/src/permission/types.d.ts +42 -0
  143. package/dist/src/permission/types.js +3 -0
  144. package/dist/src/permission/types.js.map +1 -0
  145. package/dist/src/product/setup.d.ts +35 -0
  146. package/dist/src/product/setup.js +300 -0
  147. package/dist/src/product/setup.js.map +1 -0
  148. package/dist/src/protect/audit.d.ts +5 -0
  149. package/dist/src/protect/audit.js +26 -0
  150. package/dist/src/protect/audit.js.map +1 -0
  151. package/dist/src/protect/capture.d.ts +7 -0
  152. package/dist/src/protect/capture.js +250 -0
  153. package/dist/src/protect/capture.js.map +1 -0
  154. package/dist/src/protect/fingerprint.d.ts +4 -0
  155. package/dist/src/protect/fingerprint.js +49 -0
  156. package/dist/src/protect/fingerprint.js.map +1 -0
  157. package/dist/src/protect/hook-cli.d.ts +2 -0
  158. package/dist/src/protect/hook-cli.js +107 -0
  159. package/dist/src/protect/hook-cli.js.map +1 -0
  160. package/dist/src/protect/index.d.ts +12 -0
  161. package/dist/src/protect/index.js +12 -0
  162. package/dist/src/protect/index.js.map +1 -0
  163. package/dist/src/protect/install.d.ts +34 -0
  164. package/dist/src/protect/install.js +293 -0
  165. package/dist/src/protect/install.js.map +1 -0
  166. package/dist/src/protect/intercept.d.ts +11 -0
  167. package/dist/src/protect/intercept.js +390 -0
  168. package/dist/src/protect/intercept.js.map +1 -0
  169. package/dist/src/protect/protect.d.ts +17 -0
  170. package/dist/src/protect/protect.js +194 -0
  171. package/dist/src/protect/protect.js.map +1 -0
  172. package/dist/src/protect/root-paths.d.ts +13 -0
  173. package/dist/src/protect/root-paths.js +140 -0
  174. package/dist/src/protect/root-paths.js.map +1 -0
  175. package/dist/src/protect/shell-policy.d.ts +17 -0
  176. package/dist/src/protect/shell-policy.js +269 -0
  177. package/dist/src/protect/shell-policy.js.map +1 -0
  178. package/dist/src/protect/status.d.ts +11 -0
  179. package/dist/src/protect/status.js +165 -0
  180. package/dist/src/protect/status.js.map +1 -0
  181. package/dist/src/protect/store.d.ts +20 -0
  182. package/dist/src/protect/store.js +170 -0
  183. package/dist/src/protect/store.js.map +1 -0
  184. package/dist/src/protect/types.d.ts +116 -0
  185. package/dist/src/protect/types.js +3 -0
  186. package/dist/src/protect/types.js.map +1 -0
  187. package/dist/src/protect/undo-session.d.ts +14 -0
  188. package/dist/src/protect/undo-session.js +182 -0
  189. package/dist/src/protect/undo-session.js.map +1 -0
  190. package/dist/src/restore.d.ts +39 -0
  191. package/dist/src/restore.js +141 -0
  192. package/dist/src/restore.js.map +1 -0
  193. package/dist/src/sandbox.d.ts +23 -0
  194. package/dist/src/sandbox.js +198 -0
  195. package/dist/src/sandbox.js.map +1 -0
  196. package/dist/src/session/ambient.d.ts +10 -0
  197. package/dist/src/session/ambient.js +53 -0
  198. package/dist/src/session/ambient.js.map +1 -0
  199. package/dist/src/session/attribution.d.ts +27 -0
  200. package/dist/src/session/attribution.js +201 -0
  201. package/dist/src/session/attribution.js.map +1 -0
  202. package/dist/src/session/index.d.ts +25 -0
  203. package/dist/src/session/index.js +472 -0
  204. package/dist/src/session/index.js.map +1 -0
  205. package/dist/src/session/process.d.ts +34 -0
  206. package/dist/src/session/process.js +234 -0
  207. package/dist/src/session/process.js.map +1 -0
  208. package/dist/src/session/store.d.ts +14 -0
  209. package/dist/src/session/store.js +125 -0
  210. package/dist/src/session/store.js.map +1 -0
  211. package/dist/src/session/types.d.ts +111 -0
  212. package/dist/src/session/types.js +3 -0
  213. package/dist/src/session/types.js.map +1 -0
  214. package/dist/src/session/watcher.d.ts +32 -0
  215. package/dist/src/session/watcher.js +186 -0
  216. package/dist/src/session/watcher.js.map +1 -0
  217. package/dist/src/timing.d.ts +7 -0
  218. package/dist/src/timing.js +19 -0
  219. package/dist/src/timing.js.map +1 -0
  220. package/dist/src/types.d.ts +101 -0
  221. package/dist/src/types.js +3 -0
  222. package/dist/src/types.js.map +1 -0
  223. package/dist/src/verify.d.ts +8 -0
  224. package/dist/src/verify.js +126 -0
  225. package/dist/src/verify.js.map +1 -0
  226. package/docs/ADAPTERS.md +37 -0
  227. package/docs/APPROVALS.md +32 -0
  228. package/docs/ARCHITECTURE.md +57 -0
  229. package/docs/ATTRIBUTION.md +179 -0
  230. package/docs/COMMERCIAL.md +51 -0
  231. package/docs/CURSOR-ENFORCEMENT.md +73 -0
  232. package/docs/ENFORCEMENT.md +134 -0
  233. package/docs/FUTURE.md +91 -0
  234. package/docs/HUMAN-SETUP.md +98 -0
  235. package/docs/IDENTITY-AUTHORITY.md +35 -0
  236. package/docs/MCP.md +107 -0
  237. package/docs/PACKAGING.md +77 -0
  238. package/docs/PERMISSIONS.md +53 -0
  239. package/docs/PRODUCT-V5.md +63 -0
  240. package/docs/PRODUCT-V6.md +69 -0
  241. package/docs/PROTECTED-SESSIONS.md +155 -0
  242. package/docs/THREAT-MODEL.md +84 -0
  243. package/docs/TRANSACTIONS.md +57 -0
  244. package/package.json +85 -0
@@ -0,0 +1,140 @@
1
+ /**
2
+ * Path safety for V4 protected project roots.
3
+ * The protected root IS the mutation boundary (unlike V2 named sandboxes).
4
+ */
5
+ import path from "node:path";
6
+ import { lstat, realpath, access } from "node:fs/promises";
7
+ import { constants as fsConstants } from "node:fs";
8
+ import os from "node:os";
9
+ import { PathSafetyError, assertSafeRelativePath, getForbiddenRoots, isPathInside, isPathInsideAsync, normalizeAbsolute, } from "../paths.js";
10
+ import { toRelativePosix } from "../manifest.js";
11
+ export function getProtectDir(projectRoot) {
12
+ return path.join(projectRoot, ".rewind", "protect");
13
+ }
14
+ export function getProtectSessionsDir(projectRoot) {
15
+ return path.join(projectRoot, ".rewind", "sessions");
16
+ }
17
+ export function getProtectAuditDir(projectRoot) {
18
+ return path.join(projectRoot, ".rewind", "audit");
19
+ }
20
+ export function getProtectActionsDir(projectRoot) {
21
+ return path.join(projectRoot, ".rewind", "actions");
22
+ }
23
+ export function getProtectObjectsDir(projectRoot) {
24
+ return path.join(projectRoot, ".rewind", "objects");
25
+ }
26
+ /** Refuse protecting home, Desktop, system roots, or the REWIND package itself by accident. */
27
+ export async function assertSafeProtectRoot(target, rewindPackageRoot) {
28
+ const abs = normalizeAbsolute(target);
29
+ for (const forbidden of getForbiddenRoots()) {
30
+ if (abs === forbidden) {
31
+ throw new PathSafetyError(`Refusing to protect forbidden root: ${abs}`);
32
+ }
33
+ }
34
+ // Refuse protecting the entire home directory or obvious system trees.
35
+ const home = path.resolve(os.homedir());
36
+ if (abs === home || abs === "/" || abs === "/Users" || abs === "/home") {
37
+ throw new PathSafetyError(`Refusing unsafe protect root: ${abs}`);
38
+ }
39
+ // Require the path to exist and be a directory.
40
+ try {
41
+ await access(abs, fsConstants.F_OK);
42
+ }
43
+ catch {
44
+ throw new PathSafetyError(`Protect path does not exist: ${abs}`);
45
+ }
46
+ const st = await lstat(abs);
47
+ if (!st.isDirectory()) {
48
+ throw new PathSafetyError(`Protect path is not a directory: ${abs}`);
49
+ }
50
+ let real;
51
+ try {
52
+ real = await realpath(abs);
53
+ }
54
+ catch {
55
+ throw new PathSafetyError(`Cannot realpath protect root: ${abs}`);
56
+ }
57
+ // Prefer disposable demo trees and explicit project dirs — refuse if equal to rewind package
58
+ // when the user clearly meant a subfolder (optional soft check: allow protecting package
59
+ // only if basename suggests a sandbox). For V4 we ALLOW protecting any non-forbidden dir
60
+ // except we warn against protecting the monorepo via explicit disposable names preference.
61
+ void rewindPackageRoot;
62
+ return real;
63
+ }
64
+ /**
65
+ * Resolve a tool-supplied path to a POSIX relative path inside the protected root.
66
+ */
67
+ export function resolveProtectedRelative(input, projectRoot) {
68
+ if (!input || input.includes("\0")) {
69
+ throw new PathSafetyError("Invalid path");
70
+ }
71
+ let cleaned = input.replace(/\\/g, "/");
72
+ if (path.isAbsolute(cleaned) || cleaned.startsWith("/")) {
73
+ const abs = path.resolve(cleaned);
74
+ if (!isPathInside(projectRoot, abs)) {
75
+ throw new PathSafetyError(`Absolute path outside protected root: ${input}`);
76
+ }
77
+ cleaned = toRelativePosix(projectRoot, abs);
78
+ }
79
+ // Strip protected-root basename prefix if agent passed "sandbox-v4-project/src/..."
80
+ const base = path.basename(projectRoot);
81
+ if (cleaned === base)
82
+ cleaned = "";
83
+ else if (cleaned.startsWith(base + "/"))
84
+ cleaned = cleaned.slice(base.length + 1);
85
+ if (cleaned === "" || cleaned === ".") {
86
+ throw new PathSafetyError("Refusing to mutate protected root directory itself");
87
+ }
88
+ const safe = assertSafeRelativePath(cleaned);
89
+ if (safe === ".rewind" ||
90
+ safe.startsWith(".rewind/") ||
91
+ safe === ".cursor" ||
92
+ safe.startsWith(".cursor/")) {
93
+ throw new PathSafetyError("Refusing to mutate .rewind / .cursor via agent tools");
94
+ }
95
+ const abs = path.resolve(projectRoot, safe);
96
+ if (!isPathInside(projectRoot, abs)) {
97
+ throw new PathSafetyError(`Path escapes protected root: ${input}`);
98
+ }
99
+ return safe;
100
+ }
101
+ export function protectedAbs(rel, projectRoot) {
102
+ const safe = assertSafeRelativePath(rel);
103
+ const abs = path.resolve(projectRoot, safe);
104
+ if (!isPathInside(projectRoot, abs)) {
105
+ throw new PathSafetyError(`Path escapes protected root: ${rel}`);
106
+ }
107
+ return abs;
108
+ }
109
+ export async function assertProtectedNoSymlinkEscape(absolutePath, projectRoot) {
110
+ if (!(await isPathInsideAsync(projectRoot, absolutePath))) {
111
+ throw new PathSafetyError(`Path outside protected root: ${absolutePath}`);
112
+ }
113
+ let st;
114
+ try {
115
+ st = await lstat(absolutePath);
116
+ }
117
+ catch (err) {
118
+ const code = err && typeof err === "object" && "code" in err
119
+ ? String(err.code)
120
+ : "";
121
+ if (code === "ENOENT")
122
+ return;
123
+ throw err;
124
+ }
125
+ if (st.isSymbolicLink()) {
126
+ let real;
127
+ try {
128
+ real = await realpath(absolutePath);
129
+ }
130
+ catch {
131
+ const { readlink } = await import("node:fs/promises");
132
+ const target = await readlink(absolutePath);
133
+ real = path.resolve(path.dirname(absolutePath), target);
134
+ }
135
+ if (!(await isPathInsideAsync(projectRoot, real))) {
136
+ throw new PathSafetyError(`Symlink escape blocked: ${absolutePath} -> ${real}`);
137
+ }
138
+ }
139
+ }
140
+ //# sourceMappingURL=root-paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"root-paths.js","sourceRoot":"","sources":["../../../src/protect/root-paths.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Conservative shell policy for protected Cursor sessions.
3
+ *
4
+ * Prefer false-positive blocks over silent mutation.
5
+ * Opaque interpreters (node/python/…) are DENIED even without obvious redirects —
6
+ * a one-liner can write files without matching mutation regexes.
7
+ */
8
+ export type ShellVerdict = "allow" | "deny";
9
+ export interface ShellDecision {
10
+ permission: ShellVerdict;
11
+ reason: string;
12
+ category: "readonly" | "mutating" | "opaque" | "empty";
13
+ }
14
+ /**
15
+ * Decide whether a shell command may run during a protected agent session.
16
+ */
17
+ export declare function decideProtectedShell(command: string): ShellDecision;
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Conservative shell policy for protected Cursor sessions.
3
+ *
4
+ * Prefer false-positive blocks over silent mutation.
5
+ * Opaque interpreters (node/python/…) are DENIED even without obvious redirects —
6
+ * a one-liner can write files without matching mutation regexes.
7
+ */
8
+ /** Known-safe read-only command prefixes (first token after env assignments). */
9
+ const READONLY_COMMANDS = new Set([
10
+ "pwd",
11
+ "ls",
12
+ "ll",
13
+ "dir",
14
+ "cat",
15
+ "head",
16
+ "tail",
17
+ "less",
18
+ "more",
19
+ "wc",
20
+ "grep",
21
+ "egrep",
22
+ "fgrep",
23
+ "rg",
24
+ "ag",
25
+ "find",
26
+ "which",
27
+ "type",
28
+ "command",
29
+ "echo",
30
+ "printf",
31
+ "true",
32
+ "false",
33
+ "test",
34
+ "[",
35
+ "basename",
36
+ "dirname",
37
+ "realpath",
38
+ "readlink",
39
+ "stat",
40
+ "file",
41
+ "diff",
42
+ "cmp",
43
+ "md5",
44
+ "md5sum",
45
+ "sha256sum",
46
+ "shasum",
47
+ "env",
48
+ "printenv",
49
+ "date",
50
+ "whoami",
51
+ "id",
52
+ "uname",
53
+ "hostname",
54
+ "sleep",
55
+ "clear",
56
+ "jq",
57
+ "yq",
58
+ ]);
59
+ /** git subcommands that are read-only. */
60
+ const GIT_READONLY = new Set([
61
+ "status",
62
+ "diff",
63
+ "log",
64
+ "show",
65
+ "blame",
66
+ "describe",
67
+ "rev-parse",
68
+ "rev-list",
69
+ "ls-files",
70
+ "ls-tree",
71
+ "branch",
72
+ "tag",
73
+ "remote",
74
+ "config", // reading; writing config is rare in agent flows — still allow list/get style
75
+ "shortlog",
76
+ "whatchanged",
77
+ "name-rev",
78
+ "cat-file",
79
+ ]);
80
+ /** First-token commands that are always considered mutating or too dangerous. */
81
+ const ALWAYS_DENY = new Set([
82
+ "rm",
83
+ "rmdir",
84
+ "mv",
85
+ "cp",
86
+ "install",
87
+ "ln",
88
+ "mkdir",
89
+ "touch",
90
+ "chmod",
91
+ "chown",
92
+ "chgrp",
93
+ "tee",
94
+ "dd",
95
+ "truncate",
96
+ "shred",
97
+ "python",
98
+ "python3",
99
+ "python2",
100
+ "perl",
101
+ "ruby",
102
+ "php",
103
+ "lua",
104
+ "bash",
105
+ "sh",
106
+ "zsh",
107
+ "fish",
108
+ "dash",
109
+ "ksh",
110
+ "csh",
111
+ "tcsh",
112
+ "node",
113
+ "nodejs",
114
+ "deno",
115
+ "bun",
116
+ "tsx",
117
+ "ts-node",
118
+ "npm",
119
+ "npx",
120
+ "pnpm",
121
+ "yarn",
122
+ "pip",
123
+ "pip3",
124
+ "cargo",
125
+ "make",
126
+ "cmake",
127
+ "docker",
128
+ "podman",
129
+ "kubectl",
130
+ "osascript",
131
+ "sudo",
132
+ "su",
133
+ "doas",
134
+ "xargs",
135
+ "parallel",
136
+ "nohup",
137
+ "eval",
138
+ "source",
139
+ "exec",
140
+ "builtin",
141
+ "command", // can invoke anything
142
+ ]);
143
+ const MUTATION_TOKEN_RE = /(^|[\s;|&])(rm|mv|cp|mkdir|rmdir|touch|chmod|chown|ln|tee|install|dd|truncate|sed\s+-i|perl\s+-i|ruby\s+-i)\b|>|>>|>\(|<\(/i;
144
+ const FIND_DELETE_RE = /\b-delete\b|\b-exec\b|\b-ok\b/i;
145
+ function stripEnvAssignments(cmd) {
146
+ // Remove leading VAR=value prefixes
147
+ let s = cmd.trim();
148
+ while (/^[A-Za-z_][A-Za-z0-9_]*=[^\s]*\s+/.test(s)) {
149
+ s = s.replace(/^[A-Za-z_][A-Za-z0-9_]*=[^\s]*\s+/, "");
150
+ }
151
+ return s.trim();
152
+ }
153
+ function firstToken(cmd) {
154
+ const s = stripEnvAssignments(cmd);
155
+ if (!s)
156
+ return "";
157
+ // Handle `git status` etc.
158
+ const m = s.match(/^([^\s;|&]+)/);
159
+ if (!m?.[1])
160
+ return "";
161
+ let tok = m[1];
162
+ // strip path prefixes: /usr/bin/rm → rm
163
+ tok = tok.replace(/^.*\//, "");
164
+ return tok.toLowerCase();
165
+ }
166
+ function gitSubcommand(cmd) {
167
+ const s = stripEnvAssignments(cmd);
168
+ const m = s.match(/^git(?:\s+-C\s+\S+)?\s+([a-z][a-z0-9-]+)/i);
169
+ return m?.[1]?.toLowerCase() ?? null;
170
+ }
171
+ /**
172
+ * Decide whether a shell command may run during a protected agent session.
173
+ */
174
+ export function decideProtectedShell(command) {
175
+ const cmd = (command ?? "").trim();
176
+ if (!cmd) {
177
+ return {
178
+ permission: "allow",
179
+ reason: "empty command",
180
+ category: "empty",
181
+ };
182
+ }
183
+ // Compound commands: if any segment looks mutating/opaque, deny the whole thing.
184
+ const segments = cmd.split(/(?:&&|\|\||;|\n|`|\$\()/);
185
+ if (segments.length > 1) {
186
+ for (const seg of segments) {
187
+ const d = decideProtectedShell(seg.trim());
188
+ if (d.permission === "deny" && seg.trim()) {
189
+ return {
190
+ permission: "deny",
191
+ reason: `compound command blocked: ${d.reason}`,
192
+ category: d.category,
193
+ };
194
+ }
195
+ }
196
+ // Pipes: still check for redirects / mutation tokens on full string
197
+ }
198
+ if (MUTATION_TOKEN_RE.test(cmd)) {
199
+ return {
200
+ permission: "deny",
201
+ reason: "mutating shell token or redirection detected",
202
+ category: "mutating",
203
+ };
204
+ }
205
+ if (FIND_DELETE_RE.test(cmd) && /\bfind\b/i.test(cmd)) {
206
+ return {
207
+ permission: "deny",
208
+ reason: "find with -delete/-exec blocked",
209
+ category: "mutating",
210
+ };
211
+ }
212
+ const tok = firstToken(cmd);
213
+ // git special-case before ALWAYS_DENY
214
+ if (tok === "git") {
215
+ const sub = gitSubcommand(cmd);
216
+ if (sub && GIT_READONLY.has(sub)) {
217
+ // deny git checkout/reset/clean/add/commit/push that rewrite worktree
218
+ return {
219
+ permission: "allow",
220
+ reason: `read-only git ${sub}`,
221
+ category: "readonly",
222
+ };
223
+ }
224
+ return {
225
+ permission: "deny",
226
+ reason: `git subcommand blocked: ${sub ?? "(unknown)"}`,
227
+ category: "mutating",
228
+ };
229
+ }
230
+ if (ALWAYS_DENY.has(tok)) {
231
+ // echo without redirect already allowed via mutation check failure —
232
+ // but echo is in READONLY and not ALWAYS_DENY. node/python are ALWAYS_DENY.
233
+ return {
234
+ permission: "deny",
235
+ reason: `opaque or dangerous command blocked: ${tok}`,
236
+ category: tok === "echo" ? "readonly" : "opaque",
237
+ };
238
+ }
239
+ // echo is safe only without redirects (already checked)
240
+ if (tok === "echo" || tok === "printf") {
241
+ return {
242
+ permission: "allow",
243
+ reason: "read-only echo/printf",
244
+ category: "readonly",
245
+ };
246
+ }
247
+ if (READONLY_COMMANDS.has(tok)) {
248
+ // `command` was in READONLY set earlier — removed via ALWAYS_DENY
249
+ if (tok === "find" && FIND_DELETE_RE.test(cmd)) {
250
+ return {
251
+ permission: "deny",
252
+ reason: "find mutation flags",
253
+ category: "mutating",
254
+ };
255
+ }
256
+ return {
257
+ permission: "allow",
258
+ reason: `allowlisted read-only: ${tok}`,
259
+ category: "readonly",
260
+ };
261
+ }
262
+ // Unknown first token → deny (fail closed for shell)
263
+ return {
264
+ permission: "deny",
265
+ reason: `unknown shell command blocked: ${tok || "(unparsed)"}`,
266
+ category: "opaque",
267
+ };
268
+ }
269
+ //# sourceMappingURL=shell-policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shell-policy.js","sourceRoot":"","sources":["../../../src/protect/shell-policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare function formatProtectStatus(projectRoot: string): Promise<string>;
2
+ export declare function formatSessionsList(projectRoot: string): Promise<string>;
3
+ export declare function formatActionsList(projectRoot: string, sessionId?: string): Promise<string>;
4
+ /**
5
+ * Classify a path mutation with no CURSOR_HOOK COMPLETED after-match as UNKNOWN_MUTATION.
6
+ * Does NOT attribute to Cursor.
7
+ */
8
+ export declare function classifyProtectUnknownMutation(relPath: string, projectRoot: string): Promise<{
9
+ trusted: boolean;
10
+ message: string;
11
+ }>;
@@ -0,0 +1,165 @@
1
+ import path from "node:path";
2
+ import { loadActiveSession, loadProtectState, listProtectActions, listSessions, saveSession, } from "./store.js";
3
+ import { appendAuditEvent } from "./audit.js";
4
+ import { recordPolicyEvent } from "../enforcement/policy.js";
5
+ function ago(iso) {
6
+ const ms = Date.now() - new Date(iso).getTime();
7
+ if (ms < 1000)
8
+ return "just now";
9
+ if (ms < 60_000)
10
+ return `${Math.floor(ms / 1000)} seconds ago`;
11
+ if (ms < 3600_000)
12
+ return `${Math.floor(ms / 60_000)} minutes ago`;
13
+ return `${Math.floor(ms / 3600_000)} hours ago`;
14
+ }
15
+ export async function formatProtectStatus(projectRoot) {
16
+ const state = await loadProtectState(projectRoot);
17
+ const session = await loadActiveSession(projectRoot);
18
+ const actions = await listProtectActions(projectRoot);
19
+ if (!state?.protected) {
20
+ return [
21
+ "REWIND",
22
+ "",
23
+ "NOT PROTECTED",
24
+ `Project: ${projectRoot}`,
25
+ "",
26
+ "Run: npm run rewind -- protect <path>",
27
+ ].join("\n");
28
+ }
29
+ const sessionActions = session
30
+ ? actions.filter((a) => a.protectedSessionId === session.id)
31
+ : [];
32
+ const completed = sessionActions.filter((a) => a.status === "COMPLETED");
33
+ const created = completed.filter((a) => !a.before.exists && a.after.exists);
34
+ const deleted = completed.filter((a) => a.before.exists && !a.after.exists);
35
+ const modified = completed.filter((a) => a.before.exists && a.after.exists);
36
+ const failed = sessionActions.filter((a) => a.status === "FAILED");
37
+ const prepared = sessionActions.filter((a) => a.status === "PREPARED" || a.status === "EXECUTING");
38
+ // Drift check vs expected mediated state (lightweight)
39
+ let trust = session?.trust ?? "AUTHORITATIVE";
40
+ if (session && session.status === "ACTIVE") {
41
+ const drift = await detectSessionDrift(projectRoot, session.id);
42
+ if (drift.untrusted) {
43
+ trust = "UNTRUSTED";
44
+ if (session.trust !== "UNTRUSTED") {
45
+ session.trust = "UNTRUSTED";
46
+ await saveSession(session, projectRoot);
47
+ }
48
+ }
49
+ }
50
+ const last = completed.length
51
+ ? completed.reduce((a, b) => (a.completedAt ?? "") > (b.completedAt ?? "") ? a : b)
52
+ : null;
53
+ const lines = [
54
+ "REWIND",
55
+ "",
56
+ "PROTECTED",
57
+ `Project: ${path.basename(projectRoot)}`,
58
+ `Root: ${projectRoot}`,
59
+ `Session: ${session?.id ?? "—"}`,
60
+ `Client: Cursor`,
61
+ `Trust: ${trust}`,
62
+ "",
63
+ "Actions",
64
+ ` ${completed.length} completed`,
65
+ ` ${created.length} created files`,
66
+ ` ${modified.length} modified files`,
67
+ ` ${deleted.length} deleted files`,
68
+ ` ${session?.blockedShellCount ?? 0} shell attempts blocked`,
69
+ failed.length ? ` ${failed.length} failed` : null,
70
+ prepared.length
71
+ ? ` ${prepared.length} incomplete (PREPARED/EXECUTING)`
72
+ : null,
73
+ "",
74
+ "Last action",
75
+ last
76
+ ? ` ${last.target}\n ${ago(last.completedAt ?? last.requestedAt)}`
77
+ : " (none)",
78
+ ];
79
+ return lines.filter((l) => l !== null).join("\n");
80
+ }
81
+ async function detectSessionDrift(projectRoot, sessionId) {
82
+ // Compare current hashes of ledgered targets — if a path was never ledgered
83
+ // but we can't scan whole tree cheaply here, we only flag when an incomplete
84
+ // action exists OR when a completed after no longer matches AND no newer action.
85
+ // Full unexplained mutation scan is in classifyProtectDrift.
86
+ const actions = (await listProtectActions(projectRoot)).filter((a) => a.protectedSessionId === sessionId);
87
+ const incomplete = actions.filter((a) => a.status === "PREPARED" || a.status === "EXECUTING");
88
+ if (incomplete.length > 0) {
89
+ return { untrusted: true, paths: incomplete.map((a) => a.target) };
90
+ }
91
+ return { untrusted: false, paths: [] };
92
+ }
93
+ export async function formatSessionsList(projectRoot) {
94
+ const sessions = await listSessions(projectRoot);
95
+ const lines = ["REWIND SESSIONS", ""];
96
+ if (sessions.length === 0) {
97
+ lines.push("(none)");
98
+ return lines.join("\n");
99
+ }
100
+ for (const s of sessions) {
101
+ lines.push(`${s.id} ${s.status.padEnd(18)} actions=${s.actionIds.length} trust=${s.trust} ${s.startedAt}`);
102
+ }
103
+ return lines.join("\n");
104
+ }
105
+ export async function formatActionsList(projectRoot, sessionId) {
106
+ let actions = await listProtectActions(projectRoot);
107
+ if (sessionId) {
108
+ actions = actions.filter((a) => a.protectedSessionId === sessionId);
109
+ }
110
+ const lines = ["REWIND ACTIONS", ""];
111
+ if (actions.length === 0) {
112
+ lines.push("(none)");
113
+ return lines.join("\n");
114
+ }
115
+ for (const a of actions) {
116
+ lines.push(`${a.id} ${a.status.padEnd(12)} ${a.tool.padEnd(18)} ${a.target}`);
117
+ }
118
+ lines.push("");
119
+ lines.push(`Total: ${actions.length}`);
120
+ return lines.join("\n");
121
+ }
122
+ /**
123
+ * Classify a path mutation with no CURSOR_HOOK COMPLETED after-match as UNKNOWN_MUTATION.
124
+ * Does NOT attribute to Cursor.
125
+ */
126
+ export async function classifyProtectUnknownMutation(relPath, projectRoot) {
127
+ const { captureProtectedEntry, snapshotIdentityHash } = await import("./capture.js");
128
+ const actions = await listProtectActions(projectRoot);
129
+ const live = await captureProtectedEntry(relPath, projectRoot, {
130
+ storeContent: false,
131
+ });
132
+ const liveHash = snapshotIdentityHash(live);
133
+ for (const a of [...actions].reverse()) {
134
+ if (a.status !== "COMPLETED" && a.status !== "UNDONE")
135
+ continue;
136
+ if (a.target !== relPath)
137
+ continue;
138
+ if (snapshotIdentityHash(a.after) === liveHash) {
139
+ return { trusted: true, message: `Matches action ${a.id}` };
140
+ }
141
+ }
142
+ const event = await recordPolicyEvent({
143
+ type: "UNKNOWN_MUTATION",
144
+ path: relPath,
145
+ mechanism: "protect-drift",
146
+ evidence: `No CURSOR_HOOK action explains ${relPath} (live=${liveHash})`,
147
+ status: "UNTRUSTED",
148
+ }, projectRoot);
149
+ await appendAuditEvent({
150
+ type: "UNKNOWN_MUTATION",
151
+ path: relPath,
152
+ detail: event.id,
153
+ }, projectRoot);
154
+ const session = await loadActiveSession(projectRoot);
155
+ if (session) {
156
+ session.trust = "UNTRUSTED";
157
+ session.policyEventIds.push(event.id);
158
+ await saveSession(session, projectRoot);
159
+ }
160
+ return {
161
+ trusted: false,
162
+ message: `UNKNOWN_MUTATION ${relPath} — not attributed to Cursor`,
163
+ };
164
+ }
165
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/protect/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { ProtectActionRecord, ProtectConfig, ProtectState, ProtectedSession } from "./types.js";
2
+ export declare function newProtectedSessionId(): string;
3
+ export declare function newProtectActionId(): string;
4
+ export declare function protectStatePath(projectRoot: string): string;
5
+ export declare function protectConfigPath(projectRoot: string): string;
6
+ export declare function loadProtectState(projectRoot: string): Promise<ProtectState | null>;
7
+ export declare function saveProtectState(state: ProtectState, projectRoot: string): Promise<void>;
8
+ export declare function loadProtectConfig(projectRoot: string): Promise<ProtectConfig | null>;
9
+ export declare function saveProtectConfig(config: ProtectConfig, projectRoot: string): Promise<void>;
10
+ export declare function sessionPath(id: string, projectRoot: string): string;
11
+ export declare function saveSession(session: ProtectedSession, projectRoot: string): Promise<void>;
12
+ export declare function loadSession(id: string, projectRoot: string): Promise<ProtectedSession>;
13
+ export declare function loadActiveSession(projectRoot: string): Promise<ProtectedSession | null>;
14
+ export declare function listSessions(projectRoot: string): Promise<ProtectedSession[]>;
15
+ export declare function protectActionPath(id: string, projectRoot: string): string;
16
+ export declare function saveProtectAction(action: ProtectActionRecord, projectRoot: string): Promise<void>;
17
+ export declare function loadProtectAction(id: string, projectRoot: string): Promise<ProtectActionRecord>;
18
+ export declare function listProtectActions(projectRoot: string): Promise<ProtectActionRecord[]>;
19
+ export declare function listIncompleteProtectActions(projectRoot: string): Promise<ProtectActionRecord[]>;
20
+ export declare function markIncompleteProtectFailed(projectRoot: string): Promise<number>;