@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,179 @@
1
+ # Attribution research — REWIND V1
2
+
3
+ This document separates **TESTED**, **DOCUMENTED**, and **SPECULATIVE** findings.
4
+
5
+ V1 goal: learn what macOS exposes about *who* changed a file **without** restricted Apple entitlements.
6
+
7
+ ---
8
+
9
+ ## Executive result
10
+
11
+ | Capability | Result |
12
+ |------------|--------|
13
+ | Live filesystem observation (WHAT) | **YES** — chokidar / FSEvents |
14
+ | Authoritative final diff | **YES** — V0 manifest diff |
15
+ | Full-session exact rewind | **YES** — V0 restore |
16
+ | Responsible process ID per write | **NO** (without Endpoint Security / privileged tools) |
17
+ | Reliable AGENT vs USER attribution | **NO** |
18
+ | Safe selective agent-only rewind | **NO — disabled** |
19
+
20
+ **Reliable restoration: YES**
21
+ **Live observation: YES**
22
+ **Reliable agent attribution: NO**
23
+
24
+ That outcome is intentional and architecturally decisive for V2.
25
+
26
+ ---
27
+
28
+ ## TESTED (on this Mac, no special entitlements)
29
+
30
+ ### Cursor process hierarchy (observed via `ps`)
31
+
32
+ `npm run session:probe` observed a real Cursor tree on this machine, including approximately:
33
+
34
+ - `Cursor.app` main process
35
+ - `Cursor Helper (Renderer)` windows
36
+ - `Cursor Helper (Plugin)` / extension-host processes
37
+ - language servers (json/html/…) as plugin children
38
+ - `Cursor Helper: terminal pty-host` → interactive `zsh` → user commands (`npm`, `node`, …)
39
+ - `cursorsandbox` helper with network allowlist policy
40
+ - crashpad / GPU / network utility helpers
41
+
42
+ This confirms Cursor has a deep, multi-process tree — but **none of these PIDs are attached to FSEvents write notifications**. Seeing the tree does not attribute a file change.
43
+
44
+ ### FSEvents via chokidar
45
+
46
+ - Node `chokidar` uses FSEvents on macOS.
47
+ - Delivers create / change / unlink / addDir / unlinkDir style signals.
48
+ - **Does not include the PID of the process that performed the I/O.**
49
+ - Signals are coalesced/debounced; they are **not** the transaction source of truth.
50
+ - Final SHA-256 manifest diff remains authoritative.
51
+
52
+ ### Process table (`ps`)
53
+
54
+ - Can list PIDs, PPIDs, users, command lines when the environment allows process enumeration.
55
+ - Can heuristically find processes whose args contain `Cursor` / `Cursor.app`.
56
+ - Can print a **candidate** Cursor process tree (children of Cursor-named roots).
57
+ - **Cannot** prove that a given filesystem event was caused by a node in that tree.
58
+ - In some constrained agent/sandbox environments, `ps`/`pgrep` return empty — treat process listing as best-effort.
59
+
60
+ ### `lsof +D <sandbox>`
61
+
62
+ - Sometimes lists processes with open handles under the sandbox.
63
+ - Short writes (typical agent edits) often complete before `lsof` runs → **empty result**.
64
+ - Open-handle presence is correlative evidence at best (LOW/MEDIUM), never proof of authorship for a past event.
65
+
66
+ ### `eslogger` (Endpoint Security CLI)
67
+
68
+ - Binary exists at `/usr/bin/eslogger`.
69
+ - Without root: fails with `ES_NEW_CLIENT_RESULT_ERR_NOT_PRIVILEGED`.
70
+ - Also requires Full Disk Access for the hosting terminal when root is available.
71
+ - **Not usable as a V1 dependency** for an ordinary unprivileged CLI.
72
+
73
+ ### `fs_usage`
74
+
75
+ - Present at `/usr/bin/fs_usage`.
76
+ - Typically requires root; unprivileged runs fail or yield nothing useful.
77
+ - Not a V1 dependency.
78
+
79
+ ### Ambient noise
80
+
81
+ - `.DS_Store` and similar basename patterns can be tagged **SYSTEM/AMBIENT** with **MEDIUM** confidence based on **filename evidence only**.
82
+ - This is pattern classification, not process attribution.
83
+ - Concurrent human file `notes-from-jack.txt` is **not** auto-labeled AGENT just because an agent session is open.
84
+
85
+ ### Concurrent human change
86
+
87
+ - When a human creates a file during an agent session, V1 **does not** claim it belongs to the agent.
88
+ - Without an explicit test harness marker, it is **UNKNOWN**.
89
+ - With an explicit harness marker (demo only), it can be labeled USER/HIGH — that marker is **not** available for real Cursor sessions.
90
+
91
+ ### Same-file conflict (research test)
92
+
93
+ If the agent writes file A, then the human edits A:
94
+
95
+ - “Undo the agent” ≠ restore checkpoint version of A (that destroys human work).
96
+ - V1 does not attempt magical merge.
97
+ - Full-session rewind remains the only safe restore primitive.
98
+
99
+ ---
100
+
101
+ ## DOCUMENTED (Apple / public sources — not implemented in V1)
102
+
103
+ ### Endpoint Security framework
104
+
105
+ - Provides notify/auth events for file create/write/rename/unlink and process exec/fork/exit.
106
+ - Event messages include rich `es_process_t` (pid, ppid, audit tokens, signing id, executable path, responsible audit token).
107
+ - This **would materially improve attribution** by binding I/O to a responsible process.
108
+
109
+ **Requirements (distribution reality):**
110
+
111
+ - Entitlement: `com.apple.developer.endpoint-security.client` (Apple approval).
112
+ - Usually runs as root / system extension style deployment.
113
+ - Full Disk Access / TCC considerations.
114
+ - Consumer Mac App Store distribution of a full ES client is **highly constrained**; more realistic as a notarized Developer ID system extension with explicit user trust, or enterprise MDM.
115
+
116
+ **V1 stance:** research only — see FUTURE.md. Not a dependency.
117
+
118
+ ### Legacy `/dev/fsevents`
119
+
120
+ - Historical character device could expose PID with events.
121
+ - Deprecated / restricted; Apple pushes Endpoint Security.
122
+ - Not used by V1.
123
+
124
+ ---
125
+
126
+ ## SPECULATIVE (unproven — do not ship assumptions)
127
+
128
+ - Inferring AGENT from “Cursor is focused” or “timing overlaps agent chat” → **false confidence**.
129
+ - Inferring AGENT from file extensions or path prefixes → **false confidence**.
130
+ - Assuming shell children of Cursor Helper own all subsequent writes → **false** (async tools, other apps, Spotlight, git hooks).
131
+ - Using DTrace in production for consumers → SIP / privilege / fragility issues.
132
+
133
+ ---
134
+
135
+ ## Confidence model used by V1
136
+
137
+ | Actor | When allowed |
138
+ |-------|----------------|
139
+ | SYSTEM | Known ambient basename/temp patterns (MEDIUM) |
140
+ | USER | Only with explicit harness marker (HIGH) — not inferred in live Cursor tests |
141
+ | AGENT | Only with explicit harness marker (HIGH) — **never** inferred from Cursor presence |
142
+ | UNKNOWN | Default for all other final diff paths |
143
+
144
+ Evidence kinds actually emitted:
145
+
146
+ - `watcher_signal`
147
+ - `watcher_correlation`
148
+ - `ambient_filename_pattern`
149
+ - `no_watcher_event`
150
+ - `no_responsible_pid`
151
+ - `cursor_present_uncorrelated`
152
+ - `explicit_human_marker` / `explicit_self_write_marker` (tests/demo only)
153
+
154
+ ---
155
+
156
+ ## Conflict strategies for later versions (not solved in V1)
157
+
158
+ 1. **Operation-level patches** — store each write as a patch; rewind agent ops only.
159
+ 2. **Three-way merge** — checkpoint base + agent tip + human tip.
160
+ 3. **Per-write snapshots** — content-addressable version per close/write.
161
+ 4. **CRDT-like / OT** — for collaborative text; weak for binary/project-wide ops.
162
+ 5. **Application integrations** — editor buffer awareness (Cursor extension) beats OS guessing.
163
+ 6. **Transaction mediation** — agent performs mutations through a REWIND proxy that records intent + before/after.
164
+
165
+ Most promising near-term for Universal AI Undo: **(6) mediation + (1)/(3) snapshots**, with ES as optional high-assurance observer — not the sole source of truth.
166
+
167
+ ---
168
+
169
+ ## Implications
170
+
171
+ Universal AI Undo **cannot** be built on FSEvents alone.
172
+
173
+ V2 should assume either:
174
+
175
+ - **Mediated agent I/O** (agent SDK / tool proxy), and/or
176
+ - **Privileged observation** (Endpoint Security), and/or
177
+ - **Editor-integrated hooks** (know which tool call wrote which buffer)
178
+
179
+ Filesystem watching remains necessary for ambient detection and verification — insufficient for authorship.
@@ -0,0 +1,51 @@
1
+ # Commercial boundary
2
+
3
+ ## What the cloud may know
4
+
5
+ - User identity (email / subject)
6
+ - Installation/device id, hostname, platform
7
+ - Subscription status / Stripe customer ids
8
+ - Entitlement issue/refresh events
9
+ - Release/update metadata
10
+
11
+ ## What MUST stay local
12
+
13
+ - Project source files
14
+ - Before/after file contents and CAS blobs
15
+ - Transaction payloads beyond opaque ids (optional aggregate counts only if ever added)
16
+ - Permission policy contents (local)
17
+
18
+ ## Offline / outage
19
+
20
+ | Condition | New mediation | Undo existing |
21
+ |-----------|---------------|---------------|
22
+ | Valid cached entitlement | Allowed | Always |
23
+ | Past `expiresAt`, within `graceUntil` | Allowed (grace) | Always |
24
+ | Past grace (Personal) | Denied / free fallback | **Always** |
25
+ | Stripe/API down | Use cache + grace | **Always** |
26
+ | Invalid signature | Free fallback | **Always** |
27
+
28
+ ## Invariant
29
+
30
+ **NEVER PAYWALL RECOVERY OF ALREADY-RECORDED USER WORK.**
31
+
32
+ ## REAL STRIPE SANDBOX PROOF
33
+
34
+ Local file store (`~/.rewind/commercial/`) is enough for TEST MODE proof.
35
+
36
+ | Piece | Behaviour |
37
+ |-------|-----------|
38
+ | Env | `.env` (gitignored) — `REWIND_STRIPE_SECRET_KEY`, `REWIND_STRIPE_PRICE_ID`, `REWIND_STRIPE_WEBHOOK_SECRET`, optional publishable key |
39
+ | Checkout | Real Stripe Checkout Session when `sk_test_` + `price_` set; else SIMULATED DEVELOPMENT MODE |
40
+ | Webhook | `POST http://127.0.0.1:7429/v1/commercial/stripe/webhook` (raw body + Stripe-Signature) |
41
+ | Events | `checkout.session.completed`, `customer.subscription.created/updated/deleted`, `invoice.payment_failed` |
42
+ | Entitlement | Ed25519 signed Personal after active/trialing webhook |
43
+
44
+ ```bash
45
+ rewind api
46
+ stripe listen --forward-to http://127.0.0.1:7429/v1/commercial/stripe/webhook
47
+ rewind login && rewind subscribe
48
+ # pay with TEST card → webhook → rewind status shows Personal
49
+ ```
50
+
51
+ See [HUMAN-SETUP.md](./HUMAN-SETUP.md). Live `sk_live_` keys are refused unless `REWIND_ALLOW_LIVE_STRIPE=1`.
@@ -0,0 +1,73 @@
1
+ # Cursor enforcement research (V3 → V4)
2
+
3
+ Sources: official Cursor Hooks docs, create-hook skill, third-party hooks references. Verified against documented behaviour (2026).
4
+
5
+ ## SUPPORTED BY CURSOR
6
+
7
+ | Capability | Notes |
8
+ |------------|-------|
9
+ | `preToolUse` permission allow/deny | Can block Write, Delete, Shell, Task, MCP:`name`, etc. before execution |
10
+ | `postToolUse` / `afterFileEdit` | Observe after mutation; cannot veto |
11
+ | `beforeShellExecution` permission allow/deny/ask | Can block shell; `failClosed: true` recommended |
12
+ | `beforeMCPExecution` | Gate MCP tools |
13
+ | `sessionStart` / `sessionEnd` | Session binding / recovery |
14
+ | Project hooks `.cursor/hooks.json` | Loaded for workspace; auto-reload on save |
15
+ | `failClosed` | Failures / timeout / invalid JSON deny instead of allow |
16
+ | Exit code 2 | Equivalent to deny |
17
+ | Matchers | Regex on tool name / command |
18
+ | `updated_input` on preToolUse | Rewrite tool call (unused in V4 Model A) |
19
+
20
+ ## V4 FINDINGS (this repo)
21
+
22
+ | Item | Result |
23
+ |------|--------|
24
+ | Model A: pre capture + allow native + post capture | **Works** in tests with realistic hook JSON fixtures |
25
+ | User must mention REWIND MCP | **No** — protect + normal Cursor tools |
26
+ | Native Write ledgered | YES |
27
+ | Native Delete ledgered | YES |
28
+ | Native StrReplace ledgered | YES |
29
+ | Shell `echo > file` | BLOCKED |
30
+ | Shell `node`/`python` one-liner write | BLOCKED (opaque policy) |
31
+ | Read-only shell (`ls`, `git status`, …) | ALLOWED |
32
+ | failClosed on preToolUse / beforeShellExecution | Installed `true` |
33
+ | Broken hook script | Non-zero exit → Cursor blocks when failClosed |
34
+ | Human editor edit during protect | Succeeds; not claimed as Cursor action |
35
+ | Session undo + human conflict | Conflict preserved; independent actions undone |
36
+ | Live Cursor agent E2E | Manual — see docs/PROTECTED-SESSIONS.md |
37
+
38
+ ## Tool coverage table
39
+
40
+ | Cursor operation | Hook observed | Protected? |
41
+ |---|---|---|
42
+ | create/overwrite file | Write + pre/postToolUse | YES (ledger) |
43
+ | modify file | Write / StrReplace | YES (ledger) |
44
+ | delete file | Delete | YES (ledger) |
45
+ | shell `echo >` | beforeShellExecution | YES (blocked) |
46
+ | `mv` / `rm` / `sed -i` | beforeShellExecution | YES (blocked) |
47
+ | `node`/`python` write | beforeShellExecution | YES (blocked) |
48
+ | `ls` / `cat` / `git status` | beforeShellExecution | YES (allowed) |
49
+ | Human keyboard save | (no agent hook) | N/A — not attributed |
50
+ | Tab inline edit | afterTabFileEdit (not installed) | NOT in V4 scope |
51
+
52
+ ## NOT SUPPORTED (today)
53
+
54
+ | Desired | Reality |
55
+ |---------|---------|
56
+ | Disable all native write tools via one “MCP-only” toggle | No first-party product mode |
57
+ | OS-level block of human editor save | Hooks do not apply |
58
+ | Guaranteed Tab write mediation | after* cannot veto; Tab hooks not wired in V4 |
59
+ | Kernel authorship | Hooks observe declared tool requests only |
60
+
61
+ ## PROMPT-ONLY (NOT ENFORCEMENT)
62
+
63
+ Rules / MCP tool descriptions that say “use REWIND” are **not** required for V4 Model A and are **not** enforcement by themselves.
64
+
65
+ ## Practical V4 policy
66
+
67
+ Installed by `rewind protect <project>` into **that project’s** `.cursor/hooks.json` (merged; unrelated hooks preserved).
68
+
69
+ Scope: the protected project workspace. Not system-wide. Not the REWIND monorepo root (refused).
70
+
71
+ ## V3 note
72
+
73
+ V3 still uses repo-level hooks to **deny** native writes into `sandbox-enforced-project` and force MCP. V4 is a different product surface: **allow + ledger** native tools inside a protected project.
@@ -0,0 +1,134 @@
1
+ # REWIND V3 — Enforcement / Threat Model
2
+
3
+ ## Verdict (honest)
4
+
5
+ Mandatory mediation for **all** Cursor activity on a normal macOS user account is **not** achieved by a single OS control without privileged Endpoint Security or a separate agent identity.
6
+
7
+ V3 **does** demonstrate practical **partial** enforcement boundaries:
8
+
9
+ 1. **fs-readonly + REWIND broker** (same UID): direct `echo >` / `rm` against `sandbox-enforced-project/` fails while mediated MCP writes succeed via brief unlock.
10
+ 2. **sandbox-exec wrapper** (Option A harness): a child process denied `file-write*` under the enforced tree cannot mutate it; the host REWIND broker (unsandboxed) can.
11
+ 3. **Cursor hooks** (`preToolUse` / `beforeShellExecution`): agent native Write/Delete/StrReplace and mutating shell targeting the enforced sandbox can be **denied** by Cursor before execution. This is real vendor tool-loop enforcement — **not** prompt compliance, and **not** OS enforcement.
12
+
13
+ None of these alone is universal. Combined, they form a credible **wrapped-agent** proof for this disposable sandbox only.
14
+
15
+ ## THREAT MODEL
16
+
17
+ ### Trusted
18
+ - REWIND broker / MCP server process (when intentionally run outside seatbelt)
19
+ - Local CAS / action ledger under `.rewind/`
20
+ - Enforcement state under `.rewind/enforcement/`
21
+
22
+ ### Untrusted
23
+ - Agent reasoning / tool selection
24
+ - Native editor write path (Agent Write tool, Tab write)
25
+ - Shell spawned by the agent
26
+ - Subprocesses of the agent
27
+ - Any process that can `chmod` the tree if shell is not also gated
28
+
29
+ ### Assets
30
+ - Filesystem state inside approved sandboxes
31
+ - Action history / provenance
32
+ - User work that must not be clobbered by undo
33
+
34
+ ### Goals
35
+ - Force or detect mutation outside REWIND for the enforced sandbox
36
+ - Preserve reversibility of mediated actions
37
+ - Prevent *silent* bypass where possible; surface policy events when not
38
+
39
+ ### Non-goals
40
+ - Malicious root user
41
+ - Kernel compromise
42
+ - Malware / Endpoint Security evasion
43
+ - Arbitrary system-wide protection
44
+ - Claiming Cursor cannot edit files outside the enforced sandbox
45
+
46
+ ## Tested boundary (this machine)
47
+
48
+ | Mechanism | Result |
49
+ |-----------|--------|
50
+ | chmod a-w tree + broker unlock | **Works** for direct writes; same UID can still `chmod`+write if shell ungated |
51
+ | sandbox-exec deny file-write* under enforced path | **Works** for wrapped children (macOS 26.6); host unrestricted |
52
+ | Docker RO mount + host broker | **Not tested** — Docker daemon unavailable |
53
+ | Separate macOS user | **Research only** — not created |
54
+ | macFUSE overlay | **Unavailable** |
55
+ | Cursor hooks deny Write/Shell | **Supported by Cursor docs**; project hooks installed; policy unit-tested |
56
+ | Prompt / rules only | **Not enforcement** |
57
+
58
+ ## Architecture (best working combo)
59
+
60
+ ```
61
+ Cursor Agent tools (Write/Shell)
62
+ │ denied by .cursor/hooks when targeting sandbox-enforced-project
63
+
64
+ (blocked)
65
+
66
+ Cursor Agent → REWIND MCP (stdio, host)
67
+ │ allowed
68
+
69
+ REWIND broker
70
+ │ unlock → mutate → re-lock (fs-readonly)
71
+
72
+ sandbox-enforced-project/ (authoritative when mediated)
73
+
74
+ Optional harness:
75
+ Restricted child (sandbox-exec) ──deny write──► sandbox-enforced-project
76
+ Host REWIND ────────────────────write OK─────► sandbox-enforced-project
77
+ ```
78
+
79
+ ## Authoritative vs untrusted state
80
+
81
+ - **AUTHORITATIVE**: path last updated by a COMPLETED mediated REWIND action (ledger + trust record).
82
+ - **UNTRUSTED**: unexplained external mutation detected; policy event `UNKNOWN_MUTATION`; **not** absorbed as valid MCP provenance.
83
+
84
+ ## Human access
85
+
86
+ fs-readonly **does** restrict the human owner for that tree while locked (same UID). Cursor hooks do **not** restrict human keyboard edits in the editor.
87
+
88
+ Product implication: eventual architecture needs a separate agent identity or session boundary so the human stays unrestricted while the agent is gated.
89
+
90
+ ## What V3 does NOT protect against
91
+
92
+ - Human (or any unsandboxed same-UID process) `chmod -R u+w` then write, if shell hooks are disabled/bypassed
93
+ - Cursor Tab / non-agent edit paths if hooks do not cover them
94
+ - Launching Cursor itself without project hooks loaded
95
+ - Compromised REWIND broker
96
+ - Edits outside `sandbox-enforced-project/`
97
+
98
+ ## Recovery if lock stuck
99
+
100
+ ```bash
101
+ chmod -R u+w "sandbox-enforced-project"
102
+ # or
103
+ npm run enforce:disable
104
+ ```
105
+
106
+ ## Endpoint Security (research only — not used)
107
+
108
+ Apple Endpoint Security can observe/deny file ops with process attribution. Requires restricted entitlement / system extension / user approval. Deferred — not used in V3 or V4.
109
+
110
+ ## V4 note
111
+
112
+ V4 does **not** claim stronger OS enforcement. It proves a **protected Cursor agent session** via hooks (Model A: intercept + ledger). See [PROTECTED-SESSIONS.md](PROTECTED-SESSIONS.md).
113
+
114
+
115
+ ## Decision matrix (tested)
116
+
117
+ | Approach | Blocks native write | Allows MCP write | Human unaffected | Privileged? | Practical |
118
+ |----------|---------------------|------------------|------------------|-------------|-----------|
119
+ | prompt rules | NO | YES | YES | NO | NO (not enforcement) |
120
+ | chmod fs-readonly + broker | YES (direct) | YES (unlock) | NO (same UID locked) | NO | YES for disposable sandbox |
121
+ | sandbox-exec wrapper | YES (child only) | YES (host) | YES if human outside wrapper | NO | YES as harness; Cursor.app not auto-wrapped |
122
+ | Cursor hooks | YES (agent tools) | YES | YES for keyboard edits | NO | YES within Cursor agent loop |
123
+ | combined (V3 default) | YES (layered) | YES | PARTIAL | NO | YES for `sandbox-enforced-project` only |
124
+ | Docker RO + host broker | untested | — | — | NO | Daemon unavailable here |
125
+ | separate macOS user | research | — | ideally YES | MAYBE | Not prototyped |
126
+ | Endpoint Security | research only | — | — | YES | V4 candidate |
127
+
128
+ ## V3 RESULT
129
+
130
+ **Partial success** for a controlled disposable sandbox using combined non-privileged mechanisms.
131
+
132
+ Universal mandatory mediation of all Cursor activity without stronger OS/vendor control: **NOT PROVEN**.
133
+
134
+ Recommended V4 (do not build now): smallest credible path is either (1) first-party Cursor MCP-only write mode / stronger tool policy, or (2) Endpoint Security deny of non-broker writers to project trees, or (3) agent always launched under seatbelt with MCP broker outside.
package/docs/FUTURE.md ADDED
@@ -0,0 +1,91 @@
1
+ # REWIND — Future research directions
2
+
3
+ These are intentional non-goals for V0. Do not implement them in this proof.
4
+
5
+ ## Filesystem observation
6
+
7
+ - Continuous watching of a target tree
8
+ - Attribute changes, renames, and bulk operations as a stream
9
+ - Correlation of bursts of activity into candidate transactions
10
+
11
+ ## FSEvents
12
+
13
+ - macOS FSEvents as a lightweight change signal
14
+ - Coalescing high-frequency events
15
+ - Gaps vs. truth (missed events, latency, historical limits)
16
+
17
+ ## Endpoint Security
18
+
19
+ - Privileged observation of process-backed file ops
20
+ - Attributing actions to a specific agent process / tool chain
21
+ - Entitlements, privacy, and user consent implications
22
+
23
+ ## Agent session identification
24
+
25
+ - Binding filesystem deltas to an “AI session”
26
+ - Tool-call boundaries as transaction markers
27
+ - Handling concurrent agents and human edits interleaved
28
+ - **V1 finding:** FSEvents alone cannot attribute authorship; prefer mediated tool I/O and/or Endpoint Security
29
+
30
+ ## Browser transactions
31
+
32
+ - Tab/history/download/bookmark mutations
33
+ - Profile isolation and extension surfaces
34
+ - What is reversible vs. merely compensable
35
+
36
+ ## Email inverse operations
37
+
38
+ - Unsend / tombstone / compensatory follow-up
39
+ - Provider API limits; true inverse often impossible
40
+
41
+ ## Calendar inverse operations
42
+
43
+ - Event create/update/delete inverses
44
+ - External attendee side effects (invites already sent)
45
+
46
+ ## Reversibility classes
47
+
48
+ - **REVERSIBLE** — exact prior state can be restored
49
+ - **COMPENSABLE** — cannot undo, but can counter with a new action
50
+ - **IRREVERSIBLE** — no safe inverse (payment settled, message delivered)
51
+
52
+ V0 classifies sandbox filesystem ops as REVERSIBLE only.
53
+
54
+ ## Approval gates
55
+
56
+ - Block or confirm before irreversible actions
57
+ - Policy layers: path allowlists, network egress, spend limits
58
+
59
+ ## Action ledger
60
+
61
+ - Append-only record of observed actions + evidence
62
+ - Cryptographic chaining for tamper-evidence
63
+ - Retention and privacy controls
64
+
65
+ ## Agent SDK / transaction API
66
+
67
+ - `beginTransaction` / `commit` / `rewind`
68
+ - Agent-declared intents vs. observed effects
69
+ - Partial rewind and conflict resolution
70
+ - **V2:** MCP-mediated filesystem tools + action ledger + conflict-aware action undo (local proof)
71
+
72
+ ## MCP bypass / V3 enforcement
73
+
74
+ - **V3:** fs-readonly + broker, sandbox-exec harness, Cursor hooks — see docs/ENFORCEMENT.md
75
+ - V3 RESULT: mandatory mediation without stronger OS/vendor control is **partially** proven for a wrapped/enforced sandbox only — not universal Cursor lockdown
76
+ - Remaining: privileged Endpoint Security, separate agent identity, first-party MCP-only write mode
77
+
78
+ ## MCP bypass
79
+
80
+ - Cursor can still edit files with native tools while REWIND MCP is connected
81
+ - Future: tool allowlists, OS sandbox, or first-party agent integration to force mediation
82
+ - V2 exposes the bypass; it does not close it
83
+
84
+ ## macOS menu bar UI
85
+
86
+ - Ambient “last AI transaction” affordance
87
+ - Inspect + rewind without a full app shell
88
+
89
+ ---
90
+
91
+ Stop here for V0. Prove the filesystem primitive first.
@@ -0,0 +1,98 @@
1
+ # Human setup checklist (Jack)
2
+
3
+ Do these outside the repo. V6 runs in **test/local mode** without them.
4
+
5
+ ## 1. Stripe (TEST MODE first)
6
+
7
+ 1. Create Stripe account → enable Test mode
8
+ 2. Create Product: **REWIND Personal**
9
+ 3. Price: **£2.99 GBP / month** recurring
10
+ 4. Copy `price_…` → `REWIND_STRIPE_PRICE_ID`
11
+ 5. API keys → `REWIND_STRIPE_SECRET_KEY=sk_test_…`
12
+ 6. `REWIND_STRIPE_PUBLISHABLE_KEY=pk_test_…`
13
+ 7. Webhook secret for local proof → `REWIND_STRIPE_WEBHOOK_SECRET=whsec_…` (from Stripe CLI listen)
14
+ 8. **Do not** put live `sk_live_` in env until launch checklist says so
15
+
16
+ Without keys: `rewind subscribe` uses **SIMULATED DEVELOPMENT MODE**.
17
+ With `sk_test_` + `price_`: **STRIPE TEST MODE** real Checkout (Personal only after webhook).
18
+
19
+ Prefer **`~/.rewind/.env`** for global installs (not inside the npm package).
20
+ Project-cwd `.env` also works (gitignored). Copy from `.env.example`. Never commit secrets.
21
+
22
+ ## REAL STRIPE SANDBOX PROOF
23
+
24
+ End-to-end local proof (no website, no live keys):
25
+
26
+ ```bash
27
+ # 1. User-level env
28
+ mkdir -p ~/.rewind
29
+ # Create ~/.rewind/.env with sk_test_…, price_…, and whsec_… (after listen)
30
+
31
+ npm run build && npm pack && npm install -g ./rewind-ai-cli-*.tgz
32
+
33
+ # 2. Local API (default port 7429, loopback only)
34
+ rewind api
35
+ # Webhook: POST http://127.0.0.1:7429/v1/commercial/stripe/webhook
36
+ # Success (public HTML, no token): http://127.0.0.1:7429/subscribed
37
+
38
+ # 3. Stripe CLI (separate terminal) — TEST mode
39
+ stripe listen --forward-to http://127.0.0.1:7429/v1/commercial/stripe/webhook
40
+ # Copy the printed whsec_… into ~/.rewind/.env as REWIND_STRIPE_WEBHOOK_SECRET
41
+ # Restart `rewind api` after updating env so the process loads the secret
42
+
43
+ # 4. Subscribe
44
+ rewind login --email you@example.com
45
+ rewind subscribe
46
+ # Expect: STRIPE TEST MODE + browser opens real Checkout
47
+ # Pay with Stripe TEST card (e.g. 4242 4242 4242 4242)
48
+
49
+ # 5. Confirm
50
+ rewind status
51
+ # Expect: Entitlement shows Personal / REWIND Personal
52
+ ```
53
+
54
+ If `rewind subscribe` prints **SIMULATED DEVELOPMENT MODE**, TEST credentials were not loaded.
55
+
56
+ ## 2. Auth provider (OIDC)
57
+
58
+ Recommended: **Auth0** or **Clerk** (OIDC Authorization Code + PKCE).
59
+
60
+ Why: no password storage in REWIND; browser login; CLI-friendly.
61
+
62
+ 1. Create application (Native / SPA + loopback redirect `http://127.0.0.1:<port>/callback`)
63
+ 2. Set:
64
+ - `REWIND_OIDC_ISSUER`
65
+ - `REWIND_OIDC_CLIENT_ID`
66
+ - (if confidential) `REWIND_OIDC_CLIENT_SECRET` on the commercial service only
67
+
68
+ Until set: `rewind login` uses **LocalDevAuthProvider** (email only, loopback).
69
+
70
+ ## 3. Entitlement signing keys
71
+
72
+ 1. Generate ed25519 keypair (or use `~/.rewind/keys` created on first run)
73
+ 2. **Private key** → signing service / `REWIND_ENTITLEMENT_PRIVATE_KEY` (server only)
74
+ 3. **Public key** → ship in app / `REWIND_ENTITLEMENT_PUBLIC_KEY`
75
+ 4. Never commit private keys
76
+
77
+ ## 4. Package registry
78
+
79
+ 1. npm org **@rewind-ai** + package **`@rewind-ai/cli`** (CLI binary remains `rewind`)
80
+ 2. Optional: Homebrew tap repo
81
+ 3. Optional: Apple Developer ID for notarised macOS app (later)
82
+
83
+ ## 5. Domain / hosting (commercial API)
84
+
85
+ Only needed when leaving local commercial store:
86
+
87
+ 1. HTTPS host for account API + Stripe webhooks
88
+ 2. Do **not** upload project files / before-after contents
89
+
90
+ Local sandbox proof uses loopback `rewind api` + Stripe CLI forward — no public host required.
91
+
92
+ ## 6. Website GET STARTED (document only — do not wire yet)
93
+
94
+ ```
95
+ visitor → account/checkout → download/install → rewind login → rewind setup → first undo
96
+ ```
97
+
98
+ Keep marketing site unchanged until test-mode product flow is proven end-to-end on a clean machine.
@@ -0,0 +1,35 @@
1
+ # Identity & Authority (V5)
2
+
3
+ ## EXISTS — foundation only
4
+
5
+ ### Actor (who requested)
6
+
7
+ ```ts
8
+ { type, client, clientVersion, identity }
9
+ ```
10
+
11
+ For MCP: client name/version from the MCP handshake when available
12
+ (`cursor-vscode@…`). If missing: `UNKNOWN_MCP_CLIENT` / actor type `unknown`.
13
+
14
+ **Never invent a human identity.**
15
+
16
+ ### Authority (on whose behalf)
17
+
18
+ ```ts
19
+ {
20
+ status: "UNKNOWN" | "UNSPECIFIED" | "DELEGATED",
21
+ principal, scope, constraints, expiresAt,
22
+ limits, delegationChain // reserved, unused
23
+ }
24
+ ```
25
+
26
+ V5 mediated actions use `authority.status = "UNKNOWN"`.
27
+
28
+ ## PLANNED
29
+
30
+ - Real delegated principals (user accounts)
31
+ - Scope constraints (paths, adapters, spend)
32
+ - Expiry and revocation
33
+ - Delegation chains
34
+
35
+ Do not read UNKNOWN authority as “trusted human approved.”