@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,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.”
|