dodo-mcp 1.2.1 → 1.3.1

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 (151) hide show
  1. package/README.md +37 -6
  2. package/dist/cli/dataRecovery.js +38 -0
  3. package/dist/cli/dataRecovery.js.map +1 -0
  4. package/dist/cli/deployment.js +61 -0
  5. package/dist/cli/deployment.js.map +1 -0
  6. package/dist/cli/main.js +36 -1
  7. package/dist/cli/main.js.map +1 -1
  8. package/dist/config/globalConfig.js +3 -5
  9. package/dist/config/globalConfig.js.map +1 -1
  10. package/dist/errors.js +1 -1
  11. package/dist/errors.js.map +1 -1
  12. package/dist/ipc/server.js +2 -0
  13. package/dist/ipc/server.js.map +1 -1
  14. package/dist/ipc/timeouts.js +5 -0
  15. package/dist/ipc/timeouts.js.map +1 -0
  16. package/dist/platform/privateFs.js +32 -3
  17. package/dist/platform/privateFs.js.map +1 -1
  18. package/dist/platform/windowsPrivateAcl.js +90 -0
  19. package/dist/platform/windowsPrivateAcl.js.map +1 -0
  20. package/dist/security/outboundAddress.js +20 -0
  21. package/dist/security/outboundAddress.js.map +1 -0
  22. package/dist/server/aiAdmin.js +21 -24
  23. package/dist/server/aiAdmin.js.map +1 -1
  24. package/dist/server/appServer.js +3 -6
  25. package/dist/server/appServer.js.map +1 -1
  26. package/dist/server/bootstrap.js +14 -0
  27. package/dist/server/bootstrap.js.map +1 -1
  28. package/dist/server/configSession.js +21 -0
  29. package/dist/server/configSession.js.map +1 -0
  30. package/dist/server/configUi/index.html +3 -0
  31. package/dist/server/configUi/ui/dataRecovery.js +90 -0
  32. package/dist/server/configUi/ui/deployment.js +111 -0
  33. package/dist/server/configUi/ui/recovery.js +167 -0
  34. package/dist/server/configUi/workbench.js +23 -7
  35. package/dist/server/installationRuntime.js +3 -1
  36. package/dist/server/installationRuntime.js.map +1 -1
  37. package/dist/server/instructions.js.map +1 -1
  38. package/dist/server/ipcDispatch.js +219 -0
  39. package/dist/server/ipcDispatch.js.map +1 -1
  40. package/dist/server/localConfig.js +34 -11
  41. package/dist/server/localConfig.js.map +1 -1
  42. package/dist/server/remoteConfig.js +23 -13
  43. package/dist/server/remoteConfig.js.map +1 -1
  44. package/dist/server/stdioServer.js +2 -5
  45. package/dist/server/stdioServer.js.map +1 -1
  46. package/dist/services/ai/network.js +1 -18
  47. package/dist/services/ai/network.js.map +1 -1
  48. package/dist/services/ai/subagents.js +5 -2
  49. package/dist/services/ai/subagents.js.map +1 -1
  50. package/dist/services/assistance/verification.js +43 -10
  51. package/dist/services/assistance/verification.js.map +1 -1
  52. package/dist/services/changes/applier.js +472 -297
  53. package/dist/services/changes/applier.js.map +1 -1
  54. package/dist/services/git/gitService.js +150 -34
  55. package/dist/services/git/gitService.js.map +1 -1
  56. package/dist/services/jobs/jobManager.js +59 -2
  57. package/dist/services/jobs/jobManager.js.map +1 -1
  58. package/dist/services/jobs/spool.js +9 -3
  59. package/dist/services/jobs/spool.js.map +1 -1
  60. package/dist/services/multimodal/mediaService.js +6 -6
  61. package/dist/services/multimodal/mediaService.js.map +1 -1
  62. package/dist/services/recovery/configKeys.js +115 -0
  63. package/dist/services/recovery/configKeys.js.map +1 -0
  64. package/dist/services/recovery/configVault.js +361 -0
  65. package/dist/services/recovery/configVault.js.map +1 -0
  66. package/dist/services/recovery/contracts.js +24 -0
  67. package/dist/services/recovery/contracts.js.map +1 -0
  68. package/dist/services/recovery/databaseAwareness.js +179 -0
  69. package/dist/services/recovery/databaseAwareness.js.map +1 -0
  70. package/dist/services/recovery/deploymentArchive.js +129 -0
  71. package/dist/services/recovery/deploymentArchive.js.map +1 -0
  72. package/dist/services/recovery/deploymentContracts.js +70 -0
  73. package/dist/services/recovery/deploymentContracts.js.map +1 -0
  74. package/dist/services/recovery/deploymentHealth.js +143 -0
  75. package/dist/services/recovery/deploymentHealth.js.map +1 -0
  76. package/dist/services/recovery/deploymentMaintenance.js +197 -0
  77. package/dist/services/recovery/deploymentMaintenance.js.map +1 -0
  78. package/dist/services/recovery/deploymentService.js +429 -0
  79. package/dist/services/recovery/deploymentService.js.map +1 -0
  80. package/dist/services/recovery/deploymentSource.js +36 -0
  81. package/dist/services/recovery/deploymentSource.js.map +1 -0
  82. package/dist/services/recovery/dockerDeployment.js +172 -0
  83. package/dist/services/recovery/dockerDeployment.js.map +1 -0
  84. package/dist/services/recovery/drift.js +178 -0
  85. package/dist/services/recovery/drift.js.map +1 -0
  86. package/dist/services/recovery/evidence.js +127 -0
  87. package/dist/services/recovery/evidence.js.map +1 -0
  88. package/dist/services/recovery/gitCopies.js +219 -0
  89. package/dist/services/recovery/gitCopies.js.map +1 -0
  90. package/dist/services/recovery/history.js +423 -0
  91. package/dist/services/recovery/history.js.map +1 -0
  92. package/dist/services/recovery/recoveryService.js +521 -0
  93. package/dist/services/recovery/recoveryService.js.map +1 -0
  94. package/dist/services/recovery/storage.js +344 -0
  95. package/dist/services/recovery/storage.js.map +1 -0
  96. package/dist/services/schedules/scheduleService.js +9 -10
  97. package/dist/services/schedules/scheduleService.js.map +1 -1
  98. package/dist/store/db.js +71 -0
  99. package/dist/store/db.js.map +1 -1
  100. package/dist/tools/catalog.js +4 -0
  101. package/dist/tools/catalog.js.map +1 -1
  102. package/dist/tools/changeTools.js +1 -1
  103. package/dist/tools/changeTools.js.map +1 -1
  104. package/dist/tools/context.js +23 -3
  105. package/dist/tools/context.js.map +1 -1
  106. package/dist/tools/deploymentTools.js +58 -0
  107. package/dist/tools/deploymentTools.js.map +1 -0
  108. package/dist/tools/directTools.js +9 -5
  109. package/dist/tools/directTools.js.map +1 -1
  110. package/dist/tools/gitTools.js +7 -2
  111. package/dist/tools/gitTools.js.map +1 -1
  112. package/dist/tools/jobTools.js +4 -4
  113. package/dist/tools/jobTools.js.map +1 -1
  114. package/dist/tools/projectTools.js +1 -0
  115. package/dist/tools/projectTools.js.map +1 -1
  116. package/dist/tools/recoveryTools.js +79 -0
  117. package/dist/tools/recoveryTools.js.map +1 -0
  118. package/dist/tools/runtimeTools.js +1 -1
  119. package/dist/tools/runtimeTools.js.map +1 -1
  120. package/dist/tools/surface.js +6 -1
  121. package/dist/tools/surface.js.map +1 -1
  122. package/dist/tunnel/credentials.js +1 -1
  123. package/dist/tunnel/credentials.js.map +1 -1
  124. package/docs/ARCHITECTURE.md +92 -2
  125. package/docs/CI.md +118 -0
  126. package/docs/COMPATIBILITY.md +7 -6
  127. package/docs/EVALUATION.md +17 -12
  128. package/docs/MANUAL_ACCEPTANCE.md +72 -2
  129. package/docs/MCP_CONNECTIONS.md +238 -0
  130. package/docs/RECOVERY.md +448 -0
  131. package/docs/RELEASE_1.3.0.md +64 -0
  132. package/docs/RELEASE_1.3.1.md +49 -0
  133. package/docs/RELEASE_NOTES.md +31 -0
  134. package/docs/SECURITY.md +123 -0
  135. package/docs/TEST_REPORT.md +312 -5
  136. package/docs/TUNNEL.md +6 -0
  137. package/docs/WEB_CLIENTS.md +3 -0
  138. package/docs/adr/047-temporary-remote-config.md +11 -0
  139. package/docs/adr/051-source-recovery-foundation.md +45 -0
  140. package/docs/adr/052-reviewed-source-restore.md +50 -0
  141. package/docs/adr/053-content-drift-and-private-git-recovery.md +29 -0
  142. package/docs/adr/054-verified-source-checkpoints.md +58 -0
  143. package/docs/adr/055-reviewed-docker-deployments.md +42 -0
  144. package/docs/adr/056-owner-data-recovery.md +47 -0
  145. package/docs/adr/README.md +7 -0
  146. package/native/private-state-windows.cs +105 -0
  147. package/package.json +8 -1
  148. package/schemas/global-config.schema.json +34 -0
  149. package/schemas/tools.compact.json +175 -15
  150. package/schemas/tools.hybrid.json +350 -16
  151. package/schemas/tools.json +4883 -816
package/docs/SECURITY.md CHANGED
@@ -29,6 +29,19 @@ DODO ใช้หลายชั้นร่วมกัน:
29
29
 
30
30
  การผ่านชั้นใดชั้นหนึ่งไม่ grant สิทธิ์ชั้นอื่น
31
31
 
32
+ Windows filesystem sharing-lock retries are bounded syscall retries. The journaled
33
+ writer revalidates paths and expected bytes before each replacement, deletion or
34
+ move attempt, including compensation. A concurrent external edit stops the retry
35
+ and is preserved for review; the entire tool/action is never repeated implicitly.
36
+ Internal OS error causes remain private and are omitted from MCP error envelopes.
37
+
38
+ Windows private-directory initialization rereads owner/DACL on each invocation.
39
+ An exact current-user-owned, protected, three-principal FullControl ACL is left
40
+ unchanged instead of re-propagating identical permissions into live descendants
41
+ while other owner CLI processes initialize them. This is not a permission cache;
42
+ unexpected owners and permissive verification paths still fail closed. Native
43
+ and PowerShell implementations apply the same checks, including final revalidation.
44
+
32
45
  Project Registry เป็น owner metadata แยกจาก authority: project ID หรือ readiness
33
46
  ไม่ grant OAuth scope, workspace ACL หรือ trust และ AI ไม่มี MCP tool สำหรับเพิ่ม ลบ
34
47
  หรือเปลี่ยนรายการโปรเจกต์
@@ -341,3 +354,113 @@ Admin API ไม่อยู่บน public MCP Events ใช้ authenticated
341
354
  ใช้ textContent แสดง path/model/error และไม่ render HTML จากโมเดล Tunnel credential
342
355
  อยู่ใน reviewed OS store/reference และไม่ถูกส่งกลับให้ browser การเริ่ม DODO,
343
356
  ปลดล็อก Keychain และให้ macOS permissions ต้องผ่านเจ้าของ
357
+
358
+ ## Verified recovery and staged-index boundaries
359
+
360
+ `rollback_changes` is restricted to the principal that owns the committed
361
+ changeset. A write scope alone does not authorize another caller's undo. This
362
+ matches the agent snapshot contract. Cross-caller recovery is an explicit owner
363
+ operation, `recover.rollback`, on authenticated private administration, with a
364
+ current workspace/epoch, idempotency receipt and audit. It is not an MCP tool or
365
+ an input flag that an AI can set. Existing changesets retain their recorded
366
+ owner; no ownership migration or automatic transfer occurs.
367
+
368
+ Before source mutation, DODO verifies stored before-image bytes, file identity,
369
+ path policy and current hashes. Restore uses the same engine with an inverse
370
+ plan and its own pre-restore backups. A durable write intent is saved before the
371
+ filesystem operation; startup verifies actual bytes rather than trusting a
372
+ journal status alone. Mixed, damaged or unverifiable state requires owner review;
373
+ startup never replays filesystem writes. Unknown historical rollback direction
374
+ is treated as recovery-required. Final hash checks preserve conflicting human
375
+ edits rather than reporting a successful restore.
376
+
377
+ `git_commit` validates the entire staged diff, including previously staged files,
378
+ against workspace and denied-path rules. Staging uses a separate candidate index;
379
+ a refused stage/commit leaves the user's index unchanged. Allowed pre-existing
380
+ staged changes remain part of normal Git commit semantics. A commit whose result
381
+ or index publication is uncertain requires inspection instead of silent retry.
382
+ Git hooks/filters still execute under the existing exec policy and OS account:
383
+ this protection is not a sandbox against arbitrary hooks or other local programs.
384
+
385
+ Current recovery covers journaled file edits, not every effect of shell commands,
386
+ package installs, directory creation, browser/desktop/device actions, databases
387
+ or external editors. File mode bits are preserved where supported; this is not
388
+ a full ACL/xattr/ownership backup. Portable path rechecks reduce races but do not
389
+ provide filesystem confinement against a hostile process with the same OS user.
390
+ The source snapshot/session UI uses the boundaries below.
391
+
392
+ ## Automatic source snapshots
393
+
394
+ Recovery policy is private owner state; repository settings, MCP calls, discover
395
+ visibility and trust overrides cannot disable it. Explicit opt-out is confirmed
396
+ and audited. Source/backup identity and hashes are checked before effects.
397
+ Caller authority and schedule approvals are rechecked after asynchronous backup.
398
+ No credential echo, extra OAuth scope or approval bypass is introduced.
399
+ See [Recovery boundaries](RECOVERY.md): this does not restore DBs, secrets, remote
400
+ effects or all metadata, and same-user TOCTOU and tampering limits still apply.
401
+
402
+
403
+ Reviewed restore binds plans to caller/project/root identity/epoch and
404
+ requires write scope plus the existing exact-action approval in inspect mode.
405
+ Source selection, backup integrity and current hashes are checked again under the
406
+ shared mutation queue. Private owner cross-caller access is not an MCP argument.
407
+ Session receipt chains reject interleaved edits; unknown shell authorship is never
408
+ claimed as exclusively owned. Restore status and durable idempotency support
409
+ reconnect without repeating uncertain effects. See [ADR-052](adr/052-reviewed-source-restore.md).
410
+
411
+ ## Recovery R03
412
+
413
+ Expected source state is separate from observed backups. External target drift fails closed; only verified committed journals or exact, live owner acknowledgement can advance the baseline. MCP read access cannot acknowledge drift. Acknowledgement never grants OAuth/trust/exec authority. Private Git copies use captured bytes and an empty private index; no working Git history/config, hooks, filters, remotes or helpers are imported. Selected backup paths must be dedicated private directories, outside project/state/credential namespaces, with pinned identity; unavailable volumes do not fall back. Content and Git bytes share quotas. Job observations remain unknown-author data and hold the mutation ticket until their bounded scan finishes. See ADR 053 for scope and root-replacement limits.
414
+
415
+
416
+ ## Recovery R04
417
+
418
+ Recovery names/pins are private owner actions, with current project/epoch, confirmation and live authority checks. They never promote test results or grant permissions. No public mark/purge endpoint exists. Caller-owned evidence retains target ACL checks; current inspection compares snapshot/recipes/runtime and never consumes model-supplied success. Truncated/unknown/skipped test evidence cannot certify a snapshot. Raw test logs and environment values are excluded from Recovery metadata. Source integrity, expected hashes, approvals and sandbox remain unchanged. Names and diffs use text-only DOM rendering. Production/DB protection is not implied.
419
+
420
+ ## registered deployment adapters
421
+
422
+ Docker daemon access is explicitly owner registered and still subject to target
423
+ OAuth scope/ACL, current workspace/epoch, exec approval, source hashes and the
424
+ configured command sandbox. Snapshot creation grants none of those rights.
425
+ No repository Compose hooks, arbitrary Docker arguments, bind mounts, privileged
426
+ mode or permission fallback are accepted. Archive extraction verifies bytes in
427
+ memory without executing or copying mounted data. Health requests use declared
428
+ network scope and reject redirects/metadata/admin URLs, including actual private
429
+ listener ports. No provider credentials or `allowWebFetch` permission are reused.
430
+
431
+ Owner maintenance cannot be discovered/invoked through MCP. Exact review hashes,
432
+ live state and expiry bind cleanup/uncertainty acknowledgement. No force deletion,
433
+ volume prune, silent retry, database downgrade or automatic health success is
434
+ performed. Private job output is not exposed through normal job output tools.
435
+ Generic shell/other daemon clients remain outside this adapter's deployment guard;
436
+ a workspace boundary is not an OS or Docker security sandbox.
437
+
438
+ ## private data recovery
439
+
440
+ Database/config opt-ins do not inherit from default-on source backup. Read-only
441
+ SQLite metadata and owner-authored compatibility rules never execute migrations
442
+ or grant generic SQL rollback. Rule checks before and after the source backup
443
+ reduce drift; an external database is not part of the source transaction.
444
+
445
+ Encrypted config uses dedicated private state and OS-only AES-256-GCM keys, with
446
+ project/root/target/revision-bound associated data. Registered inputs must already
447
+ be private, source-denied files. Owner-only preview is redacted; MCP/discover cannot
448
+ configure, decrypt or restore those copies. Keys never travel in argv/config JSON
449
+ or logs; OS-store failure has no plaintext fallback. Lost keys are unrecoverable.
450
+
451
+ Restore writes an existing file in place after an encrypted before-copy and durable
452
+ UNKNOWN receipt. A crash may leave partial bytes; it never silently retries or
453
+ restarts services. Owner/context/content checks and same-user filesystem race
454
+ limits apply. Key rotation retains old references; retention protects referenced
455
+ backups and does not promise physical secure erasure. See [ADR 056](adr/056-owner-data-recovery.md).
456
+
457
+ ## Config session isolation (1.3.1)
458
+
459
+ Local Config retains its eight-hour process capability. Each owner CLI opening of
460
+ Remote Config creates a distinct, random internal capability bounded by that
461
+ one-hour lease. It never renews or reuses the local browser token. Closing, expiry
462
+ or reopening revokes the old remote capability and cookie. No credential is sent
463
+ in a remote URL or returned by state APIs. AI owner principals, streaming requests
464
+ and queued owner revalidation use the authenticated request session, not the
465
+ server start time. Loopback, Host/Origin, proxy-header rejection, rate limits,
466
+ workspace/epoch checks and public MCP OAuth remain enforced.
@@ -1,5 +1,225 @@
1
1
  # DODO MCP — Test Report
2
2
 
3
+ ## 1.3.1 Config regression coverage
4
+
5
+ `tests/security/remoteConfig.test.ts` reproduces the previous HTTP 401 after advancing
6
+ the server clock nine hours, then verifies an independent CLI-created session,
7
+ AI owner expiry, settings writes, renewal and queued-request revocation.
8
+ `tests/security/localConfig.test.ts` checks distinct capabilities, local expiry,
9
+ remote revocation and Host/Origin/proxy-header enforcement.
10
+ `tests/integration/remoteConfigUi.test.ts` exercises desktop/mobile Chromium after
11
+ local expiry and re-pairs after closing without restarting the fixture process.
12
+ External AI clients and real Cloudflare remain MANUAL_NOT_RUN; the connection guide
13
+ is based on client documentation and is not a live platform certification.
14
+
15
+ ## 1.3.0 Recovery — หลักฐานก่อน final platform gate
16
+
17
+ Windows full [run35510440500](https://github.com/arthittakun/dodo-mcp/actions/runs/35510440500)
18
+ ที่ `66605d9`: 907pass/1fail/38skip ปัญหา atomic edit เดิมผ่านแล้ว เหลือ concurrent
19
+ CLI project registration ถูกปฏิเสธที่ private ACL Native diagnosis
20
+ [run35511792781](https://github.com/arthittakun/dodo-mcp/actions/runs/35511792781)
21
+ ทำซ้ำได้13/15pass,2fail,0skip และระบุ guard `final-owner` ระหว่าง protect
22
+ แพตช์ `d145a3e` ไม่เขียน/propagate ACL ซ้ำเมื่อผลอ่านสดตรง canonical policy
23
+ แต่ยังตรวจ owner, DACL และ reparse ใหม่ทุกครั้ง ไม่มี permission cache
24
+ [run35512074966](https://github.com/arthittakun/dodo-mcp/actions/runs/35512074966)
25
+ ผ่าน17/17,0skip รวม concurrent add6process จำนวน3รอบ, foreign-owner/permissive
26
+ ACL rejection และ PowerShell fallback ผลนี้เป็น focused pass; full gates ต้อง
27
+ ผ่านบน clean candidate หลังแพตช์นี้ก่อน release
28
+
29
+ macOS และ Linux native Node22/24 full ที่ `66605d9` ผ่านก่อนแพตช์ ACL ล่าสุด:
30
+ macOS910pass/36skip; Linux902pass/44skip ต่อ Node; 946total,0fail,
31
+ packaging17/17, benchmark7/7, audit0 และ fresh install PASS ทั้งหมด
32
+ ไม่ใช้ผล revision ก่อนหน้าแทนการตรวจ candidate หลังแก้
33
+
34
+ Follow-up Windows หลังแก้ Git/restore: full
35
+ [run35508647355](https://github.com/arthittakun/dodo-mcp/actions/runs/35508647355)
36
+ ที่ `6ff35b8` ได้900pass/1fail/38skip เหลือ atomic modification ของไฟล์ชื่อไทย
37
+ ที่มี BOM/CRLF ระบบชดเชยกลับและคืน INTERNAL_ERROR Focus
38
+ [run35509902825](https://github.com/arthittakun/dodo-mcp/actions/runs/35509902825)
39
+ ทำซ้ำได้8pass/1fail/0skip; OS errno เดิมไม่ได้ถูกเก็บ จึงไม่ระบุว่าเกิดจาก antivirus
40
+ หรือโปรแกรมใดโดยไม่มีหลักฐาน
41
+
42
+ ระหว่างตรวจพบและ reproduce อีกปัญหา: การ retry syscall หลัง sharing denial
43
+ ต้องตรวจ expected state ซ้ำ การจำลอง external edit ทำให้ regression3/3ล้มก่อนแก้
44
+ แพตช์ `560d930` ตรวจ hash/path ทุกครั้ง รวม compensation และเก็บ internal cause
45
+ แบบ private โดยไม่ส่งออก MCP error envelope Native
46
+ [run35510211305](https://github.com/arthittakun/dodo-mcp/actions/runs/35510211305)
47
+ ผ่าน16/16,0skip รวมเคส BOM/CRLF และ7retry/compensation/error-redaction cases
48
+ ผลนี้เป็น focused pass; full gates ของ candidate หลังแก้ยังต้องผ่านก่อน release
49
+
50
+ Follow-up วันที่ 2026-09-20 ที่ clean revision `8c76c0a`
51
+ (`sha256:a9118f3ce6d37a0520ef64720122eb36e9c684154aebb9cb984e8e6459f148bc`):
52
+
53
+ | Platform | Core (142 files / 938 tests) | Packaging | Fresh install |
54
+ |---|---|---|---|
55
+ | macOS arm64 / Node 22 | 902 pass / 0 fail / 36 skip | 17/17 | PASS |
56
+ | Linux native / Node 22 | 894 pass / 0 fail / 44 skip | 17/17 | PASS |
57
+ | Linux native / Node 24 | 894 pass / 0 fail / 44 skip | 17/17 | PASS |
58
+
59
+ ทั้งสาม gate: build/typecheck/lint/test:all exit0, DodoBench7/7, production audit0
60
+ Linux [run35507491429](https://github.com/arthittakun/dodo-mcp/actions/runs/35507491429)
61
+ ยืนยัน fresh-install หลังแก้ Node24 fixture connection reset: retry เฉพาะ initialize
62
+ ที่ไม่มี effect ไม่ retry tool calls หรือ OAuth exchange
63
+
64
+ Windows full [run35506660660](https://github.com/arthittakun/dodo-mcp/actions/runs/35506660660)
65
+ ที่ `acf805a`: Node24 core889pass/7fail/38skip; duplicate-activation/UI409 ผ่านแล้ว
66
+ เหลือ Git-copy6เคส และ timeout ของ scenario restore15ไฟล์ หลังเก็บหลักฐานยกเลิก
67
+ Node22 ของ revision เก่าเพื่อทดสอบแพตช์ใหม่ ไม่ถือว่ารอบที่ยกเลิกผ่าน
68
+ แพตช์ Git-copy ใช้ writable fd สำหรับ mandatory flush และ fixture ของปลายทาง private
69
+ ใช้ Windows ACL จริง ความถูกต้องของแพตช์ต้องอ้าง native run ของ revision นั้น
70
+ ผลย้อนหลังข้างต้นไม่ใช้แทน final gate หลังเปลี่ยน source
71
+
72
+ Windows focused [run35507971440](https://github.com/arthittakun/dodo-mcp/actions/runs/35507971440)
73
+ ที่ `144a3ee`: 22pass/3fail/0skip ยืนยัน writable-fd Git backup และ flush-failure
74
+ regression, dirty/untracked restore15ไฟล์, worktree/large blobs และ browser drift
75
+ success path ผ่าน เหลือสาม assertion ที่รอ asynchronous initialization ด้วย poll
76
+ budget เริ่มต้น แยกเพิ่มเวลารอสถานะเป็น30วินาทีโดยไม่เปลี่ยนผล READY/BLOCKED
77
+ ที่ต้องได้หรือ assertions การป้องกันไฟล์/การรันคำสั่ง Full gate ต้องรันอีกครั้ง
78
+ บน clean revision หลังแพตช์นี้ก่อนเผยแพร่
79
+
80
+ ผลแต่ละรอบอ้างเฉพาะ source fingerprint/revision ที่ระบุ ไม่ใช่ผล npm รุ่นก่อน
81
+ และไม่รวม skipped tests เป็น pass ต้องใช้ final native Windows/Linux และ macOS
82
+ ที่ตรง clean candidate ก่อน publish ดู [workflow](https://github.com/arthittakun/dodo-mcp/actions/workflows/platform-gates.yml)
83
+ และ [วิธีอ่านหลักฐาน](CI.md)
84
+
85
+ ชุดรวม macOS วันที่ 2026-09-20 ก่อนแก้ duplicate activation:
86
+ `sha256:b75f20c8669d7a7fbd2e16d80104d1ef6dce4b36855a2ab039ae0d2d475d47e2`
87
+
88
+ - AUTOMATED_PASS: core141files / 933total / 895pass / 0fail / 38skip;
89
+ packaging17/17; build/typecheck/lint/test:all/benchmark/audit/fresh install exit0
90
+ - Production dependency audit0; DodoBench7/7
91
+ - Fresh exact-tarball: OAuth + Compact20, Full158 with explicit Sub-agent exposure,
92
+ write/edit/readback, A/B routing, agent receipt; Recovery checkpoint, reviewed restore,
93
+ hash readback, idempotent retry, unrelated-file preservation, restart receipt and stale-context denial
94
+ - Actual browser desktop/narrow uses isolated state; config plaintext never appears in UI
95
+ - Actual macOS Keychain and Windows Credential Manager random-item put/read/delete passed
96
+ (AUTOMATED_PASS); no owner credentials touched
97
+
98
+ Windows focused [run35505588240](https://github.com/arthittakun/dodo-mcp/actions/runs/35505588240)
99
+ passed78/79,0skip and confirmed the native ACL backend (20freshchecks715ms).
100
+ Remaining browser scan returned409 while duplicate project activation held the queue.
101
+ Follow-up [run35506319903](https://github.com/arthittakun/dodo-mcp/actions/runs/35506319903)
102
+ passed23/24,0skip, including all R06 security/browser/native credential tests;
103
+ scalar diagnostics isolated the same409. The candidate now marks a checkpointed
104
+ runtime active and avoids re-activation, with a regression that keeps external drift
105
+ visible and source writes blocked until reviewed. These focused failures remain
106
+ recorded; neither is a full Windows PASS. Final full gates must certify the fix.
107
+
108
+ MANUAL_NOT_RUN: owner production restore, live external ChatGPT, Android hardware,
109
+ and Linux Secret Service on a logged-in desktop. SQLite metadata fixtures do not
110
+ claim generic database rollback/PITR. Actual disposable Docker product-adapter
111
+ acceptance is separate from native CI and preserves database rows/volumes/config.
112
+
113
+ ## Unreleased — native CI workflow (2026-09-20)
114
+
115
+ Linux platform gate เปลี่ยนเป็น self-hosted native เช่นเดียวกับ Windows โดยไม่ใช้
116
+ Docker เพิ่ม prerequisites และ sandboxed Chromium launch probe; media tests ยัง
117
+ ถูกบังคับให้รัน เก็บ evidence แยกตาม run ID/attempt เพื่อไม่เขียนทับผลเมื่อ rerun
118
+
119
+ `AUTOMATED_PASS` บน macOS สำหรับการเปลี่ยน workflow/gate ครั้งนี้:
120
+ actionlint 1.7.12, typecheck, lint และ gate-evidence unit tests **23 passed / 0 failed**
121
+ รวมการปฏิเสธ Docker report, fingerprint/revision/lock ที่ไม่ตรง, dirty source,
122
+ false pass และ fresh-install ที่ไม่ครบ ผลนี้ไม่ใช่ native Linux/Windows PASS
123
+
124
+ Follow-up: diagnostics เพิ่มเฉพาะ test path/index/source line โดยไม่ส่ง raw error,
125
+ titles หรือ expected/actual values และย้าย CI evidence ออกนอก checkout เพื่อไม่ถูก
126
+ cleanup ลบ Typecheck/lint/actionlint และ gate-evidence tests **25 passed / 0 failed**
127
+ ผ่านบน macOS หลังแก้ ส่วน native application test results ต้องดูแยกตาม CI run
128
+
129
+ Native CI [run 35495748297](https://github.com/arthittakun/dodo-mcp/actions/runs/35495748297)
130
+ ทดสอบ clean commit `e0e5f9a9b14d0d2e7f4c776aeaf0e19b621eb8f9`
131
+ และ fingerprint `sha256:83791f00f244466f064ea413494e7555406835b276f562dca809e3c8901ae665`
132
+ โดยตรงบน Linux X64 ไม่มี Docker:
133
+
134
+ | Gate | Node 22.23.2 | Node 24.21.0 |
135
+ |---|---|---|
136
+ | build/typecheck/lint/full suite | exit 0 | exit 0 |
137
+ | Core / 874 tests | 833 pass / 41 skip / 0 fail | 833 pass / 41 skip / 0 fail |
138
+ | Packaging | 17 pass | 17 pass |
139
+ | DodoBench | 7/7 pass | 7/7 pass |
140
+ | Production audit | 0 vulnerabilities | 0 vulnerabilities |
141
+ | Fresh exact-tarball install | PASS | PASS |
142
+
143
+ ก่อนหน้านี้ run 35495249409 ที่ commit `723733e` มี Linux Node 24 core failure
144
+ หนึ่งเคส (830 pass / 41 skip) ส่วน Node 22 ผ่านครบ ยังไม่ยืนยันสาเหตุของ failure
145
+ รอบแรก และไม่อ้างว่า diagnostics change แก้ runtime bug ผลรอบล่าสุดข้างบนผ่านจริง
146
+ แต่ไม่ลบหรือแทนที่ประวัติผลล้มเหลว
147
+
148
+ Windows Node 22/24 ในรอบแรกล้มก่อน step แรกที่ runner `InitializeSecretMasker` /
149
+ `PowerShellPreAmpersandEscape` ไม่มี application tests ได้รัน ดู [CI](CI.md)
150
+ สำหรับการเปิด runner ใหม่ สถานะรอบแรกเป็น `RUNNER_BLOCKED` ไม่ใช่ application PASS
151
+ และไม่ได้ rerun ใน Linux-only รอบดังกล่าว
152
+
153
+ หลังเจ้าของเปิด runner ใหม่ [Windows run 35496561994](https://github.com/arthittakun/dodo-mcp/actions/runs/35496561994)
154
+ ที่ clean commit `1739646f0678a6e1c29bc92c8eba6cd1a017f0df` ผ่าน startup แล้ว
155
+ Node 24.21.0 ผ่าน build/typecheck/lint แต่ `test:all` หมดเวลา 30 นาที
156
+ (1,800,010 ms) จึงเป็น `AUTOMATED_FAIL` ไม่มี complete core JSON report และยังไม่ถึง
157
+ packaging/benchmark/audit/fresh install Node 22 ถูกยกเลิกก่อนทดสอบเพื่อวินิจฉัย
158
+ ไม่ถือเป็น PASS หรือ application failure ของ Node 22
159
+
160
+ [การอ่านหลักฐานเดิม](https://github.com/arthittakun/dodo-mcp/actions/runs/35498195971)
161
+ พบ reporter output ของ 49 ไฟล์ / 490 tests / 47 failures / 29 skipped ก่อน timeout
162
+ เป็น **ผลบางส่วนเท่านั้น** ไม่ใช่ยอดรวม full suite มี failures ใน Recovery และ
163
+ integration อื่น จึงห้ามสรุปว่าเพิ่ม timeout อย่างเดียวจะผ่าน หรือยกเลิก backup/ACL
164
+ เพื่อให้ผลเขียว งานตรวจเฉพาะกลุ่มมี scope `focused_diagnostics_only` ไม่ใช่ release gate
165
+ Manual Windows acceptance ยัง `MANUAL_NOT_RUN`
166
+
167
+ Focused reproduction [run 35498746408](https://github.com/arthittakun/dodo-mcp/actions/runs/35498746408)
168
+ จบจริง: **17 pass / 8 fail / 0 skip** ใน 2 ไฟล์ (236,088 ms)
169
+ พบ private ACL verifier คืน metadata ก่อน Windows ปรับ Administrators owner
170
+ ขณะที่ journal ตรวจ ctime จาก file descriptor หลังปรับ จึงเกิด `CONFLICT` ทั้งที่
171
+ backup ถูกต้อง แพตช์คืน metadata หลังตรวจ ACL พร้อมปฏิเสธ identity/type/content
172
+ ที่เปลี่ยนระหว่างตรวจ ไม่ลบ hash/ACL/owner/reparse guards
173
+
174
+ หลังแก้ที่ `89b762b` [Windows focused run 35499178559](https://github.com/arthittakun/dodo-mcp/actions/runs/35499178559)
175
+ **34 pass / 0 fail / 0 skip** ใน 3 ไฟล์ (302,245 ms): recoveryBackups, directTools
176
+ และ windowsAclOwner รวม native owner/DACL/junction checks และการอ่าน metadata
177
+ หลัง owner repair ผลนี้เป็น `AUTOMATED_PASS` เฉพาะชุดย่อย ไม่ใช่ full Windows gate
178
+
179
+ Local macOS สำหรับแพตช์: typecheck/lint ผ่าน, 31 focused tests pass / 9 native
180
+ Windows tests skipped ไม่อ้าง skips เป็น Windows evidence Windows full gate
181
+ รอบต่อไปใช้ aggregate `test:all` budget 60 นาที โดยคง timeout ราย test/hook และ
182
+ assertions เดิม ผล full gate หลังแพตช์ยังรอยืนยัน
183
+
184
+ ผล Recovery/Docker ด้านล่างเป็นหลักฐานของ candidate รอบก่อนตาม fingerprint เดิม
185
+ ไม่ใช้แทน native CI ข้างบน ไม่มี merge main หรือ npm publish จากผลนี้
186
+
187
+ ## Unreleased — Source Recovery R00–R02 candidate
188
+
189
+ ตรวจ 2026-09-20 บน source fingerprint
190
+ `sha256:89c3ad25f99781f41824c3b13c39400ef231d173ea818e7eb9cd1717d4782c69`
191
+ ผลนี้เป็น development candidate ไม่ใช่การรับรองว่า npm รุ่นที่เผยแพร่มีฟีเจอร์นี้แล้ว
192
+
193
+ | Gate | macOS arm64 / Node 22 | Linux Docker arm64 / Node 22 |
194
+ |---|---|---|
195
+ | build, typecheck, lint, test:all | exit 0 | exit 0 |
196
+ | Core: 121 files / 832 tests | 797 pass / 35 skip / 0 fail | 791 pass / 41 skip / 0 fail |
197
+ | Packaging / fresh installed restore | 17 pass / 0 fail | 17 pass / 0 fail |
198
+ | Production npm audit | 0 vulnerabilities | 0 vulnerabilities |
199
+ | DodoBench | not rerun in this gate | 7/7 pass |
200
+
201
+ `AUTOMATED_PASS`: real HTTP OAuth/target A/B/caller isolation, read-only refusal,
202
+ inspect approval, external hash/mode conflicts, dirty Git index preservation,
203
+ binary/directory/partial restore, injected write failure compensation, six abrupt
204
+ restore crash boundaries, private owner API and built CLI. Real Chromium verifies
205
+ desktop/390px preview → confirmation → restore → journal status. PACK-17 repeats
206
+ backup/preview/restore/read-back/idempotent retry against an installed tarball.
207
+
208
+ Linux fresh exact-tarball smoke additionally verifies Full STDIO 148 and Compact
209
+ HTTP 20, OAuth, write/edit, target routing and sub-agent protocol fixtures. Sub-agent
210
+ operations are explicitly enabled in that smoke; the normal hidden Full count is 144.
211
+
212
+ One preliminary full run failed a Brain per-run metric assertion when automatic
213
+ indexing ran before the fixture's manual rebuild. The fixture isolates that timer;
214
+ the real parser/index/security and original assertions remain. The final full runs
215
+ above passed; preliminary failed logs were retained. Skips cover platform/backend
216
+ conditions and are not counted as passes.
217
+
218
+ `MANUAL_NOT_RUN`: native Windows/Android, live owner data restore, live provider
219
+ credentials and publication. Automated browser use is not `MANUAL_PASS`.
220
+ See [Recovery scope and limitations](RECOVERY.md) and
221
+ [ADR-052](adr/052-reviewed-source-restore.md).
222
+
3
223
  ## 1.2.1 Agent Profile creation and Compact/Hybrid visibility controls
4
224
 
5
225
  วันที่ตรวจ: 2026-09-16
@@ -505,11 +725,11 @@ Fresh release smoke ติดตั้ง exact tarball ใน temporary prefix
505
725
  แบบ explicit แล้วตรวจ CLI 1.0.0, STDIO Full 125, HTTP Streamable + OAuth Compact 19,
506
726
  write/edit read-back และ Sub-agent receipt จริง ค่า default-off ถูกตรวจแยกใน STDIO/HTTP/
507
727
  packaging regressions
508
- Release policy ใช้ macOS local และ Linux Docker โดย report ต้องมี revision/lock digest
509
- ตรงกันก่อน strict gate จะผ่าน Linux Docker image ติดตั้ง Playwright Chromium
510
- Dedicated self-hosted GitHub Actions รัน Linux X64 Docker และ Windows X64 native
511
- candidate บน Node 22/24 โดยไม่รับ untrusted pull requests Windows manual acceptance
512
- ยังคง `MANUAL_NOT_RUN`
728
+ นโยบายปัจจุบันใช้ macOS local และ Linux native GitHub Actions โดย report ต้องมี
729
+ clean revision/source fingerprint/lock digest ตรงกันก่อน strict gate จะผ่าน
730
+ Dedicated self-hosted GitHub Actions รัน Linux X64 และ Windows X64 โดยตรงบน
731
+ Node 22/24 โดยไม่รับ untrusted pull requests Windows manual acceptance
732
+ ยังคง `MANUAL_NOT_RUN` ดู [CI](CI.md) สำหรับ prerequisites
513
733
 
514
734
  ## Required security scenarios
515
735
 
@@ -555,3 +775,90 @@ end-to-end บนอุปกรณ์ภายนอก: `MANUAL_NOT_RUN`
555
775
  สถานะ Runtime Intelligence ผ่าน external AI และ owner repository จริง: `MANUAL_NOT_RUN`
556
776
 
557
777
  สถานะ Advanced Agent Runtime ผ่าน external AI และ owner repository จริง: `MANUAL_NOT_RUN`
778
+
779
+ ## Unreleased R03 candidate — 2026-09-20 (AUTOMATED_PASS)
780
+
781
+ Final source/test/gate fingerprint: `sha256:e8e638e493bbdacf27f39221178ba29005c9c094348c4cca2cbec19f7ad15f5b`.
782
+
783
+ | Gate | macOS arm64 / Node 22.23.2 | Linux Docker arm64 / Node 22.23.2 |
784
+ |---|---:|---:|
785
+ | Build, typecheck, lint | exit 0 | exit 0 |
786
+ | Core (124 files / 851 tests) | 816 pass / 35 skip / 0 fail | 810 pass / 41 skip / 0 fail |
787
+ | Packaging | 17 pass / 0 fail | 17 pass / 0 fail |
788
+ | Production npm audit | 0 vulnerabilities | 0 vulnerabilities |
789
+ | Headless desktop/narrow owner UI | pass | pass |
790
+ | Exact tarball install and HTTP OAuth / STDIO | packaging smoke pass | release smoke pass |
791
+
792
+ R03 exercises persistent same-size/mtime drift, 54 overwrites + 2 deletions, original/emergency snapshot separation, unknown-author job observation, unchanged/non-target writes, nested ignore rules, deadline/raced hash failures, exact owner acknowledgement and revoked/stale authority. Independent Git tests cover staged secrets, hooks/filters, preserved index/HEAD/config, unborn/detached/parent/linked-worktree repositories, large blobs, unavailable backup volumes, quotas, and uncertain final journal persistence. Existing restore crash, OAuth, ACL, sandbox and path guard suites remain enabled.
793
+
794
+ A separate disposable disaster fixture deleted the original root, working `.git` and CAS objects. On both platforms two approved files were recovered byte-for-byte from independent bare Git objects into a NEW directory; excluded credentials/database data were not restored. This demonstrates an owner-directed recovery procedure, not permission to override the original runtime's root identity.
795
+
796
+ Environment-specific 200-file × 8 KiB scan measurements: unchanged source 63 ms macOS / 151 ms Docker; 54 overwrites + 2 deletions including emergency copy 2316 ms / 1382 ms. The default scan budget is 15000 ms; these small fixtures do not establish performance for all repositories. Linux DodoBench also passed its seven existing cases.
797
+
798
+ Earlier failed rounds are retained privately: a legacy-schema fixture omitted new tables; a new test used the wrong fixture accessor; expected transport/error assertions were corrected to their actual typed contract. Final gates above reran the complete suite. Detailed logs, manifests, screenshots and checksums stay in private development evidence and are excluded from npm.
799
+
800
+ MANUAL_NOT_RUN: live owner projects, native Windows/Android, physical removable-drive removal, live ChatGPT and external provider credentials. Automated browser tests are not manual acceptance. No npm publish or owner-server restart was performed.
801
+
802
+ ## Unreleased R04 candidate — 2026-09-20 (AUTOMATED_PASS)
803
+
804
+ Source fingerprint (both gates):
805
+ `sha256:fb79ab8f05a095b47545299af30e0dabb48633a2a547e3025990101688c375bc`.
806
+ This is a dirty development candidate, not the published package with the same
807
+ version metadata. No release readiness claim is made.
808
+
809
+ | Platform | Core | Packaging | Skipped | Failures |
810
+ |---|---:|---:|---:|---:|
811
+ | macOS arm64, Node 22.23.2 | 833 passed / 868 | 17 passed | 35 | 0 |
812
+ | Linux Docker arm64, Node 22.23.2 | 827 passed / 868 | 17 passed | 41 | 0 |
813
+
814
+ `npm run build`, `npm run test:all` (including typecheck/lint), packaging and
815
+ installed-package checks exited 0. Linux additionally passed the 7-case DodoBench
816
+ and exact-tarball fresh-install smoke (Full STDIO 148; HTTP/OAuth Compact 20,
817
+ write/edit/read-back and target routing). Production dependency audits reported
818
+ 0 vulnerabilities on both platforms. Platform/optional skips remain explicit in
819
+ private machine reports; skipped tests are not passes.
820
+
821
+ 17 new R04 cases cover actual passing/failing/skipped/truncated/unknown/inconsistent
822
+ recipe output, manifest/recipe/runtime drift, caller isolation, owner expiry,
823
+ revision races/tombstones, immutable snapshots, protected pin/name retention,
824
+ OAuth read-only/revoked ACL, rejected model-supplied status, private/public admin
825
+ separation and hostile Origin/proxy headers. Browser fixtures on desktop/390px
826
+ register a project with Recovery on, edit through MCP, verify, pin/name, detect
827
+ stale source, restore/read back, and show a real quota reservation failure. Existing
828
+ restore/crash/hash/secret/sandbox tests remain enabled. UI assets are included in
829
+ the tarball and do not use external CDNs.
830
+
831
+ MANUAL_NOT_RUN: owner's live projects/storage, native Windows, Android and live
832
+ ChatGPT. Production/database recovery is not implemented in R04. Browser fixture
833
+ screenshots are automated evidence, not manual owner acceptance. The first local
834
+ Docker build failed because its daemon was off; the completed container gate above
835
+ was run after starting Docker. Early test-fixture mistakes were corrected without
836
+ relaxing security/schema assertions and remain in private logs.
837
+
838
+ ## Unreleased deployment/data recovery candidates — 2026-09-20
839
+
840
+ R05 source fingerprint `sha256:548622178672a0baf317c33db634d17e33a1d28595781c48d9e18c4a4020b5c5`:
841
+ macOS core135files910total874passed36skipped0failed; packaging17/17. Native Linux
842
+ Node22+24 in run35503836757 each868passed42skipped0failed; packaging17/17,
843
+ benchmark7/7, production audit0 and fresh tarball installPASS. All gate commands
844
+ exit0. Disposable actual Docker acceptance separately passed (26.12s), including
845
+ source/image tampering, unhealthy deployment, exact image rollback, source restore,
846
+ unchanged SQLite/private volume data and reviewed probe/image cleanup.
847
+
848
+ Initial R06 source fingerprint `sha256:77595e3557db592479fcb32c41324d2fdd7f441d10560622343c9f13a040a4c5`:
849
+ macOS Node22 core141files929total892passed37skipped0failed; packaging17/17,
850
+ benchmark7/7,audit0,fresh tarball installPASS; all gate commands exit0. Browser
851
+ fixture exercises SQLite registration, encrypted config backup/redacted review/
852
+ restore, real file read-back, CLI and desktop/narrow layouts. Crypto fixtures use
853
+ an explicitly injected key store; a separate actual macOS Keychain random-item
854
+ put/read/delete test also passed. Helper protocol fixtures cover secret stdin,
855
+ fixed references and failure behavior for macOS/Windows/Linux.
856
+
857
+ These snapshots predate final combined changes and are not release authorization.
858
+ Native Windows R04 focus35503022077 used native .NET ACL checks (20checks718ms),
859
+ 75/78passed;3failures remained in drift tests. The earlier full Windows run failed.
860
+ Those failures remain recorded and are not replaced with skipped assertions.
861
+ Subsequent fixes require new exact-source native gates. Live owner production,
862
+ manual ChatGPT, Linux Secret Service and Windows Credential Manager acceptance
863
+ are MANUAL_NOT_RUN unless a later result explicitly records them. Database row
864
+ rollback/PITR is NOT_SUPPORTED; no such result is implied by source recovery.
package/docs/TUNNEL.md CHANGED
@@ -143,6 +143,12 @@ query/fragment secret Pairing code มีอายุสั้นและใช
143
143
  cookie แบบ `Secure`, `HttpOnly`, `SameSite=Strict`, `Path=/config` Lease ปิดเองภายใน
144
144
  หนึ่งชั่วโมง การเปิดใหม่ยกเลิก code/session เดิม
145
145
 
146
+ ตั้งแต่ 1.3.1 session ของ Remote Config แยกจาก Local Config 8 ชั่วโมงโดยสมบูรณ์
147
+ รัน `dodo --web` หลัง DODO เปิดเกิน 8 ชั่วโมงได้ทันที ไม่ต้อง restart หรือเปิด Local link
148
+ ก่อน การเปิดรอบใหม่ไม่ต่ออายุ Local link เดิม และไม่เปลี่ยน workspace epoch
149
+ AI/Projects, streaming และ owner action ที่รอคิวใช้ session ของคำขอนั้นจริง
150
+ ดู [วิธีเชื่อม AI clients](MCP_CONNECTIONS.md) สำหรับ MCP URL กับ OAuth callback
151
+
146
152
  Remote Config proxy ไปยัง Local Config loopback โดยคง Host/Origin/proxy-header checks,
147
153
  private capability, rate limit, workspace ID/epoch และ owner policy เดิม การปิด lease
148
154
  ไม่หยุด MCP หรือ Tunnel และไม่มี MCP tool สำหรับเปิดหน้า owner นี้
@@ -1,5 +1,8 @@
1
1
  # DODO MCP — เชื่อม ChatGPT และ Web Clients
2
2
 
3
+ ดู [คู่มือทุก AI platform](MCP_CONNECTIONS.md) สำหรับ Claude พร้อมตัวเลือก
4
+ Sign in now / Use your own OAuth client และตัวอย่าง Claude Code, Codex, Gemini CLI, Cursor, VS Code
5
+
3
6
  ## สิ่งที่ต้องแยกให้ออกก่อน
4
7
 
5
8
  | ค่า | ใช้ตรงไหน | ตัวอย่าง |
@@ -45,3 +45,14 @@ expiry still affects only Remote Config; MCP, OAuth and Tunnel continue running.
45
45
  - `tests/security/remoteConfig.test.ts`
46
46
  - `tests/integration/remoteConfigUi.test.ts`
47
47
  - `tests/integration/cli.test.ts`
48
+
49
+ ## 1.3.1 — independent owner sessions
50
+
51
+ The original bridge reused the eight-hour Local Config capability. After eight
52
+ hours a fresh one-hour CLI lease could pair but all upstream API calls failed.
53
+ The bridge now obtains a separate capability with exactly its own lease deadline
54
+ through the in-process Local Config handle. Reopening revokes the old capability;
55
+ local browser expiry is unchanged. Request-bound session validation also governs
56
+ AI owner principals, event streams and queued owner actions. The one-hour public
57
+ lease and one-time pairing remain mandatory. Both owner-managed Cloudflare Local
58
+ and DODO-managed Tunnel modes can open this lease. No server restart is needed.
@@ -0,0 +1,45 @@
1
+ # ADR-051 — Default-on source backup foundation
2
+
3
+ Status: implemented in unreleased working source. Reviewed restore and session
4
+ pins are implemented in [ADR-052](052-reviewed-source-restore.md); publication
5
+ still requires an explicit owner release request.
6
+
7
+ Each leased project runtime owns a RecoveryService. Only owner-registered roots
8
+ activate scanning. Missing versioned private project policy means enabled;
9
+ explicit owner opt-out is preserved. Owner web and CLI share IPC validation.
10
+ Repository configuration and model output cannot alter this policy.
11
+
12
+ Storage is an independent CAS under private installation state. Immutable
13
+ manifests bind project/workspace/root identity, epoch, implicit operation session,
14
+ actor, trigger, scope and policy digest to actual source bytes. SQLite migration
15
+ adds snapshot states, object references, policies and reservations. Older binaries
16
+ refuse the newer schema; no old journal or authority records are rewritten.
17
+
18
+ Capture hashes the scoped inventory, reserves installation/project capacity and
19
+ free disk, streams private object copies, fsyncs, resamples source paths/hashes,
20
+ verifies stored objects, publishes an immutable manifest, then transactionally
21
+ commits refs and READY. Nothing labeled READY is merely a list of hashes.
22
+ PREPARING records interrupted by restart become INCOMPLETE under the project
23
+ lease; no command is replayed. Resource GC cannot remove Recovery objects.
24
+
25
+ The existing Applier adds targeted before-images before journal creation and
26
+ rechecks expected hashes after asynchronous capture. JobManager's async
27
+ startProtected captures a fresh full scope while holding the shared mutation
28
+ queue; its sync entry refuses registered-project bypasses. All production job
29
+ producers use that path. The scheduler rechecks durable approval after capture,
30
+ and tool invocation rechecks caller authority after capture before effects.
31
+ Git commit (including hooks) and directory creation also require checkpoints.
32
+
33
+ Full baselines and explicit mutation targets have different coverage. Policy
34
+ exclusions never silently remove a named target; an allowed ordinary-ignored
35
+ source target is included, while excluded data/secret targets are refused.
36
+ Snapshot retention preserves newest complete full/target points and pins.
37
+ Journal before-images remain independent. ADR-052 adds restore/session pins so
38
+ those consumers can safely retain their old CAS references.
39
+
40
+ Consequences: scans cost I/O and can block mutation on quota, corruption or
41
+ unstable files. This is neither an OS sandbox nor a filesystem-wide atomic
42
+ snapshot. No database/volume/secret, remote side-effect, or full filesystem
43
+ metadata recovery is implied. Session restore is implemented by ADR-052;
44
+ verification-bound stable points remain a later phase. Backup-only releases
45
+ without reviewed restore are not sufficient for default-on Recovery acceptance.
@@ -0,0 +1,50 @@
1
+ # ADR-052: Caller-owned Recovery sessions and reviewed source restore
2
+
3
+ Status: implemented in the unreleased development candidate; release verification
4
+ and platform evidence must match the final source fingerprint.
5
+
6
+ Recovery adds ten operations to the end of the full catalog; compact HTTP keeps
7
+ 20 gateways. `recoverySessionId` is optional top-level invocation context and is
8
+ rejected inside gateway arguments. Sessions are project/root/caller-bound private
9
+ records, independent of conversational memory. An implicit session covers one
10
+ operation; a sub-agent run has an independent recovery session per runtime epoch.
11
+ Restart interrupts open sessions without resuming effects. A fresh session is
12
+ required for new mutations after restart.
13
+
14
+ Before-images are independently stored CAS bytes. Session events link snapshots,
15
+ journaled changesets, jobs and verification IDs, not raw tokens, command contents
16
+ or model reasoning. Changeset attribution is recorded in the journal transaction
17
+ before source writes. Job IDs are linked before process launch. Session baseline
18
+ Git status records bounded allowed dirty/staged/untracked/deleted path metadata;
19
+ it never modifies the index. Shell authorship is unknown. Session undo containing
20
+ jobs is refused; a caller may review a particular checkpoint instead, without
21
+ claiming to undo external effects.
22
+
23
+ Preview stores private immutable plan metadata only. It reads current authorized
24
+ paths, verifies manifest/object integrity and displays bounded diffs plus hashes.
25
+ Ordinary restore leaves unrelated extras alone. Explicit exact mirror includes
26
+ extra allowed source-file deletions and requires a full-source checkpoint. Session
27
+ undo coalesces before-images and checks the entire receipt chain and current
28
+ post-state; interleaved edits refuse the whole selection. Owned directory removal
29
+ requires its recorded identity and planned children, then an empty directory at
30
+ the actual syscall. Unjournaled parent directories are conservatively retained.
31
+
32
+ Apply requires the exact reviewed plan ID/hash, same principal/project/epoch,
33
+ live access and existing trust/approval policy. An independent pre-restore backup
34
+ is mandatory (disabled Recovery must be re-enabled first). The shared project
35
+ queue and R00 journal validate all files before writing; each step persists intent
36
+ before IO. Restore is a forward changeset with pre-restore compensation bytes.
37
+ Ordinary apply_changes cannot execute a recovery plan outside its rechecks.
38
+
39
+ Idempotency is durable. An uncertain reservation never reruns effects; status can
40
+ be inspected after reconnect. Boot classifies actual states as committed, failed
41
+ without change, or recovery-required; it does not replay or force overwrite.
42
+ Directory creation records the resulting identity; a crash before identity receipt
43
+ is conservative recovery-required. Mode/existence are verified where supported;
44
+ this is not a global filesystem snapshot or a complete ACL/xattr backup.
45
+
46
+ Active/interrupted sessions, unresolved journals, live jobs, pinned snapshots and
47
+ unexpired reviewed plans retain backup references. Closed history ages out as a
48
+ unit under owner retention policy. Snapshot references cannot be collected by the
49
+ resource cache. Owner cross-caller actions are only on authenticated private IPC /
50
+ Config with reviewed context and explicit apply confirmation, never an MCP flag.