Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ open build/desktop/Prayu.app
| v95 | Analyzer 结果、Artifact 与审计事件原子提交 | atomic Analyzer result, Artifact, and audit-event commit |
| v96 | 用户审批档的精确宿主命令提案、审阅与恰好一次执行 | exact approval-mode host-command proposals, reviews, and exactly-once execution |
| v97 | 持久 Docker 生命周期所有权、代际租约与崩溃恢复 | durable Docker lifecycle ownership, generation leases, and crash recovery |
| v98 | 有界 Docker 容器 I/O 合同:只读输入投影、日志限额与原子输出提交 | bounded Docker container I/O contract: read-only input projection, log capture limits, and atomic output commit |

</details>

Expand Down
2 changes: 2 additions & 0 deletions docs/PROGRESS_BOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

## 一、当前阶段

2026-08-14 单切片 `Docker 容器 I/O 合同(新增标签,对应 Issue #39)` 推进到 SQLite v98,仍未接入任何产品入口或执行授权。只读输入投影 `sandbox_docker_input_projection.v1` 把规范化相对路径、SHA-256、大小与媒体类型封印到生命周期 attempt/generation、Plan、Observation、Run/Mission/Workspace 与 Spec 指纹上,输入挂载固定 `/run/cyberagent/inputs` 只读,并新增真实 inspect Mounts 隔离校验(唯一可写挂载必须是专用输出挂载,输入与工作区树必须只读)。日志捕获 `sandbox_docker_log_capture.v1` 只走 `POST containers/{id}/attach?logs=1&stderr=1&stdout=1&stream=0`:解复用器按流限制 256 KiB/4096 行与墙钟时限,拒绝畸形/超大帧,替换非法 UTF-8 并计数,脱敏 Secret,只落库元数据与摘要回执。输出暂存 `sandbox_docker_output_staging.v1` 只导出专用输出挂载的 `GET containers/{id}/archive`,tar 走查在 Windows/Linux 同一路径规则下拒绝绝对/穿越/反斜杠/盘符路径、symlink/hardlink/设备节点、重复项,并限制 64 文件/单文件 4 MiB/总量 16 MiB,文本文件按媒体类型识别与脱敏后写入进程内暂存目录;被拒归档不带任何受信清单。原子提交 `sandbox_docker_output_commit.v1` 要求接受清单与已完成暂存回执逐项精确一致,从暂存目录重读并复哈希后在同一 SQLite 事务中写入回执与全部条目,operation key 幂等,失败不残留半提交行。HTTP 白名单只开放上述两个端点,应用服务不接 CLI/HTTP/Desktop,新增 15 个事件类型记录 prepared/acquired/taken-over/failed/completed。域/黄金向量/对抗路径/传输/Store/应用定向测试在 macOS 通过;Windows 与 Linux CI 将跑同一路径矩阵。边界见 ADR 0098 与 Issue #39;产品准入(Policy/Approval/Budget/Network 与 CLI/HTTP/Desktop 接线)仍是下一个 Docker 切片。

2026-08-14 单切片 `D0-Mac(macOS Desktop 便携构建,新增标签)` 保持 SQLite v97 与全部权限边界不变,为 Desktop 增加 macOS 构建:`cmd/cyberagent-desktop` 按构建标签拆分为共享 `desktop`、Windows `windows && desktop && wv2runtime.error` 与新增 darwin 实现;macOS 使用系统自带 WKWebView 且无运行时预检,启动失败只写 stderr 并显示有界严格转义的 osascript 对话框,工作区启动器只通过固定 `/usr/bin/open` 打开已验证 .app(Finder、Terminal、Antigravity、PyCharm、WebStorm、Visual Studio Code)。Windows 专属的 Credential Manager、ConPTY 用户终端、Safe Web/WFP 与受控宿主执行在 macOS 保持失败关闭。`scripts/build-desktop-darwin.sh` 产出 ad-hoc 签名、未公证的 `build/desktop/Prayu.app`,复用连续双构建 SHA-256 校验并写入 `portable_release_metadata.v1`;`scripts/check-macos-compat.sh` 检查 Mach-O/架构/codesign/元数据与 operator-preview 包边界;CI 新增 `desktop-macos` 任务;React 标题栏为原生红绿灯预留空间。desktop-tag Go 测试在 macOS 通过,App/desktop-bridge React 测试通过;签名、公证与人工 macOS 矩阵未做,`release_ready` 保持 false。边界见 ADR 0097 与 `docs/DESKTOP_PLAN.md`;本轮没有重跑 WFP、Docker、付费 Provider 或全仓重型门,下次上下文压缩后不得重复。

项目正在从可运行的 v0.1 CLI/TUI 骨架迁移到 V2 Run-centric Runtime。当前只推进通用 Agent Harness 与 Code 工作流;CTF 专用求解和攻防自动化已经移出活跃路线图,仅保留通用扩展接口供未来独立附加包接入。
Expand Down
41 changes: 38 additions & 3 deletions docs/PROJECT_MEMORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,41 @@

Last updated: 2026-08-14

## Current Single-Slice Checkpoint: macOS Desktop Portable Build / Schema v97 Unchanged
## Current Single-Slice Checkpoint: Bounded Docker Container I/O Contract / Schema v98

On 2026-08-14 schema v98 added the bounded Docker container I/O contract for
issue #39, still without any product entry or authority grant. A sealed
read-only input projection (sandbox_docker_input_projection.v1) binds
canonical relative paths, SHA-256, size, and media type to the lifecycle
attempt/generation, plan, observation, Run, Mission, Workspace, and spec; the
input mount stays fixed at /run/cyberagent/inputs read-only and a mount
isolation verifier checks real inspection mounts (exactly one writable mount,
owned by the dedicated output target; input and workspace trees read-only).
Log capture (sandbox_docker_log_capture.v1) goes only through POST
containers/{id}/attach with logs=1&stderr=1&stdout=1&stream=0; a demuxer
bounds bytes (256 KiB) and lines (4096) per stream, enforces a deadline,
rejects malformed/oversized frames, counts and replaces invalid UTF-8,
redacts secrets, and persists only digest-only receipts. Output staging
(sandbox_docker_output_staging.v1) exports only GET containers/{id}/archive
of the dedicated output mount and walks the tar under one Windows/Linux path
rule set: no absolute/traversal/backslash/drive-letter paths, no
symlink/hardlink/device entries, no duplicates, caps of 64 files / 4 MiB per
file / 16 MiB total, media-type detection, and text redaction into a
process-local staging directory; rejected archives carry no trusted manifest.
Atomic output commit (sandbox_docker_output_commit.v1) requires an accepted
manifest that exactly matches completed staging entries, re-reads and
re-hashes the staged files, and inserts the receipt plus every entry in one
replay-safe SQLite transaction; a failure leaves no partial rows. The HTTP
transport allowlist admits exactly the two endpoints, the application service
stays unwired from CLI/HTTP/Desktop, and 15 new event kinds record the
prepared/acquired/taken-over/failed/completed transitions. Focused domain,
golden-vector, adversarial-path, transport, store, and application tests pass
on macOS; Windows/Linux CI will exercise the same path matrix. See ADR 0098
and issue #39. Do not repeat this slice or the v97 lifecycle review after
compaction; product admission (Policy/Approval/Budget/Network and
CLI/HTTP/Desktop wiring) remains the next Docker slice.

### Previous Checkpoint: macOS Desktop Portable Build / Schema v97 Unchanged

On 2026-08-14 a new single-slice delivery added a macOS portable Desktop build
without changing SQLite schema or any authority boundary. cmd/cyberagent-desktop
Expand Down Expand Up @@ -565,6 +599,7 @@ Read in this order after a long context break:
102. `docs/DESKTOP_PLAN.md`
103. `docs/SKILL_PACKAGE_PLAN.md`
104. `docs/adr/0097-macos-desktop-portable-build.md`
105. `docs/adr/0098-bounded-docker-container-io-contract.md`

## Current Baseline

Expand All @@ -573,8 +608,8 @@ Read in this order after a long context break:
- Generic coding-agent workflow usability: about 98%.
- Cyber autonomous-workflow usability: about 20%.
- These are engineering estimates based on tested roadmap slices, not performance benchmarks. Do not reuse the retired single-axis "overall product vision" percentage.
- Database schema: v97.
- `README.md` carries the canonical bilingual schema timeline in strict `v1 -> v97` order. `internal/store/readme_history_test.go` binds its row count and ordering to `LatestSchemaVersion`, so a future migration cannot silently leave the public history missing or out of sequence.
- Database schema: v98.
- `README.md` carries the canonical bilingual schema timeline in strict `v1 -> v98` order. `internal/store/readme_history_test.go` binds its row count and ordering to `LatestSchemaVersion`, so a future migration cannot silently leave the public history missing or out of sequence.
- Main languages: Go control plane, TypeScript React/Vite local console, and deterministic Rust 1.97.1 digest/ZIP protocol functions. Rust has no Agent, LLM, config, key, persistence, network, filesystem, subprocess, or product-lifecycle ownership.
- Analyzer status: P10-A through P10-K define and validate the Go/Rust protocol and embedded-WASI boundary. P10-L/schema v94-v95 adds real fixed-module execution, one-shot exact-bound authorization, atomic consumption, redacted execution, metadata-only Artifact content, and Run events. P10-M exposes only this embedded module through CLI/control-token HTTP/Desktop/React; callers cannot provide WebAssembly, imports, mount, network, command, argv, environment, or native process. See ADR 0062, ADR 0063, ADR 0090, ADR 0091, and `analyzers/README.md`.
- Model Harness status: non-schema A1/A2/A3 adds `model_harness.v1` exact transport/tool/JSON/streaming profiles, Go preflight for Root/Specialist/read-only Fan-out, and `model_harness_qualification.v1` at-most-two-call synthetic qualification. Mock is trusted offline; Anthropic-compatible models require explicit qualification. Qualification stores only exact binding digest, capability booleans, and seven-day expiry in existing Provider settings; the synthetic Tool is never executed, availability remains no-probe, and qualification grants no Tool/Shell/file/browser/Docker authority. P13-A adds the durable public-activity read projection; P13-B adds a separate process-local safe public assistant stream with exact cancellation and no raw Provider persistence; P13-C adds the Root-only, independently reviewed `approval` host-command proposal Tool without granting the model execution authority. P10-M2 proves the production Anthropic-compatible route and durable chat path against deterministic local SSE, while P13-B3 verifies one configured real DeepSeek path. Current OpenAPI is 88 paths / 96 operations / 212 schemas. See ADR 0074, ADR 0080, ADR 0091, ADR 0092, and ADR 0093.
Expand Down
16 changes: 15 additions & 1 deletion docs/PROJECT_STATUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,21 @@ Last updated: 2026-08-14

## Resume Context

The current single-slice checkpoint is the macOS Desktop portable build at
The current single-slice checkpoint is the bounded Docker container I/O
contract at schema v98 for issue #39, still without product entry or
authority. A sealed read-only input projection binds canonical paths,
digests, sizes, and media types to the lifecycle attempt/generation and plan
identity, and a mount isolation verifier checks real inspection mounts. Log
capture is limited to the fixed stream=0 attach surface with byte/line/
deadline caps, UTF-8 normalization, and secret redaction, persisting only
digest receipts. Output staging exports only the dedicated output mount and
rejects traversal, links, duplicates, and size violations under one
Windows/Linux path rule set; atomic commit requires an exact manifest match,
re-hashes staged files, and writes receipt plus entries in one replay-safe
transaction. The HTTP allowlist admits exactly two daemon endpoints and the
service is unwired from CLI/HTTP/Desktop. See ADR 0098.

The previous single-slice checkpoint was the macOS Desktop portable build at
unchanged schema v97. cmd/cyberagent-desktop is now split by build tag:
shared shell code under "desktop", Windows-only WebView2/Acrylic/registry
launcher code under "windows && desktop && wv2runtime.error", and a new
Expand Down
2 changes: 2 additions & 0 deletions docs/TASK_BOOK.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

## 当前基线

Docker 容器 I/O 合同(Issue #39)已随 schema v98 落地(ADR 0098):只读输入投影、有界日志回执、严格输出暂存与原子 Artifact 提交全部就位,但仍无产品入口;产品准入(Policy/Approval/Budget/Network 与 CLI/HTTP/Desktop 接线)是下一个 Docker 切片。

D0-Mac 已把 Desktop 构建扩展到 macOS(ADR 0097):darwin 构建标签复用同一 Go 控制平面与 WKWebView,产出未签名/未公证的本地 Prayu.app;Windows 专属的凭证库、ConPTY 终端、Safe Web/WFP 与受控宿主执行在 macOS 失败关闭。macOS 签名、公证与人工矩阵仍未排入当前切片。

- 架构完成度:约 99%;其中 V2 Run-centric 控制平面约 99%。
Expand Down
72 changes: 72 additions & 0 deletions docs/adr/0098-bounded-docker-container-io-contract.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# ADR 0098: Bounded Docker Container I/O Contract

Date: 2026-08-14

## Status

Accepted.

## Context

The durable Docker lifecycle slice (schema v97, ADR 0096) proved exact
Stage/create/start/wait/terminate/cleanup ownership, but a container still had
no product-grade I/O contract: the Workspace boundary, log capture, output
extraction, and Artifact commit were not composed into one bounded,
fail-closed transaction set. Issue #39 requires that combination while
keeping product admission closed: no CLI, HTTP, Desktop, Agent, or Tool path
may reach it.

Container output is untrusted evidence. Nothing a container writes may
automatically become prompt context, an approval decision, a command, or host
executable content, and the original Workspace must stay read-only from the
container perspective.

## Decision

1. Read-only input projection (sandbox_docker_input_projection.v1): a sealed
manifest of canonical container-relative paths, SHA-256, size, and media
type, bound to the lifecycle attempt/generation, plan, observation, Run,
Mission, Workspace, and spec fingerprints. The input mount target stays
fixed at /run/cyberagent/inputs with read-only access; the spec invariant
of exactly one writable (dedicated output) mount is unchanged. A mount
isolation verifier checks real inspection mounts: the output target is the
only writable mount in its tree and the input/workspace trees are
read-only.
2. Bounded log capture (sandbox_docker_log_capture.v1): stdout/stderr arrive
only through the fixed POST containers/{id}/attach with
logs=1&stderr=1&stdout=1&stream=0 (no live streaming). A demuxer bounds
each stream by bytes (256 KiB) and lines (4096), enforces a wall-clock
deadline, rejects malformed/oversized frames, replaces invalid UTF-8 and
counts the violations, redacts secrets, and records only metadata plus
digest-only receipts. Raw bytes never persist.
3. Output staging (sandbox_docker_output_staging.v1): the dedicated output
mount is exported only through GET containers/{id}/archive?path=<target>.
The tar walker rejects absolute/traversal paths, Windows separators,
drive letters, symlinks/hardlinks/devices, duplicates, and non-canonical
names; caps file count (64), per-file size (4 MiB), and total size
(16 MiB); detects media types; redacts text content; and writes only
validated regular files into a Run-scoped process-local staging directory.
Rejected archives carry no trusted manifest.
4. Atomic output commit (sandbox_docker_output_commit.v1): an accepted
manifest must exactly match completed staging entries (path, digest,
size, media type). The staged files are re-read and re-hashed, then the
receipt and every entry commit in one SQLite transaction keyed by a
replay-safe operation key digest. Failure leaves no partial rows.
5. Schema v98 persists the four ledgers with strict CHECKs and foreign keys;
events record prepared/acquired/taken-over/failed/completed transitions.
The DockerContainerIOService is exported for tests only; no product entry
is wired, matching the lifecycle slice boundary.
6. Windows and Linux share one path rule set, so the same adversarial path
matrix is exercised on both CI hosts.

## Consequences

- Every container I/O step is bounded, digest-bound, replay-safe, and
fail-closed; the Workspace can only be modified through the already-gated
FileEdit boundaries, never by the container.
- Product admission (Policy/Approval/Budget/Network gates and CLI/HTTP/
Desktop wiring) remains a separate slice; this contract does not authorize
anything.
- Raw logs and staged files are process-local and never reach SQLite or
events; only receipts and digests are durable.

Loading