Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
771582b
docs(post_v9_audits): add nwave convo + v9 audit
RCSnyder May 8, 2026
830751e
docs(iterate): version scope to v9.1 — Onboarding Gate
RCSnyder May 8, 2026
203b6d9
docs(analyze): produce v9.1 readiness.md (AC-89..AC-94)
RCSnyder May 8, 2026
91737db
feat(build): AC-94 honesty pass — README five-row security table + DE…
RCSnyder May 8, 2026
88f98c3
feat(build): AC-89 pcy init — bootstrap .env with strong random secrets
RCSnyder May 10, 2026
7d4712c
feat(build): AC-90 pcy doctor — 8-check self-diagnosis with table/jso…
RCSnyder May 10, 2026
4cdb192
feat(build): AC-92 docs/onboarding.md — one-page first-run gate
RCSnyder May 10, 2026
17b2b6a
feat(build): AC-93 pcy provider — per-workspace LLM provider rows
May 10, 2026
5716003
feat(build): AC-91 pcy backup / pcy restore (v9.1 V91-S6)
RCSnyder May 10, 2026
2d71a20
fix(build): AC-91 review-fix — wire --include-vault-key into restore …
RCSnyder May 10, 2026
eee48c0
fix(review): amend AC-90 to 7 checks, add AC-93 resolver test
RCSnyder May 10, 2026
0e195ee
fix(review): align onboarding doc + doctor docstring to 7 checks
RCSnyder May 10, 2026
e3ebc64
docs(reconcile): v9.1 onboarding gate 7-axis drift sweep — REPAIRED
RCSnyder May 10, 2026
79068d1
docs(verify): align Doctor clap docstring to 7 checks
RCSnyder May 10, 2026
3a96724
docs(deploy): v9.1 onboarding gate delivery handoff
RCSnyder May 11, 2026
0f4d56e
fix(ci): clippy assertions_on_constants + AC-40 rpassword allowlist f…
RCSnyder May 11, 2026
75985aa
fix(ci): allowlist 'provider remove' for --yes flag (AC-93)
RCSnyder May 11, 2026
f893132
fix(ci): allowlist VAULT_KEY_BASE64 as INTERNAL_ONLY env var (AC-29 +…
RCSnyder May 11, 2026
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
74 changes: 74 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ tabled = "0.15"
# canonical `tool_definitions()` `parameters` schemas.
jsonschema = "0.28"

# AC-91 (v9.1): backup / restore tarballs. `tar` walks the archive;
# `flate2` provides gzip framing. Sanctioned in v9.1 ITERATE clarifier
# CR-v91-1; both crates are MIT/Apache-2.0 and trivially auditable.
tar = "0.4"
flate2 = "1"

# AC-53 / Slice A2b.1: Linux-only sandbox crates.
#
# These crates provide the six-layer fail-closed sandbox (bwrap
Expand Down
24 changes: 22 additions & 2 deletions DELIVERY.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
# DELIVERY.md — Open Pincery v8.0
# DELIVERY.md — Open Pincery v9.1

## v9.1 Summary

v9.1 is the **Onboarding Gate** — the smallest set of operator-facing tools that turn a fresh clone into a working install in 15 minutes without reading the source. Six acceptance criteria: AC-89 (`pcy init` — `.env` bootstrap with 32-byte OsRng secrets, mode 0600, no secret bytes on stdout), AC-90 (`pcy doctor` — seven ordered self-diagnosis checks with strict-mode + JSON output; eighth sandbox-preflight check deferred to v9.2 as AC-90b), AC-91 (`pcy backup` / `pcy restore` — tarball with `pg_dump --format=custom`, manifest with schema-version forward-incompatibility refusal, optional `--include-vault-key` round-trip, 0o600 recovered-key extraction), AC-92 (`docs/onboarding.md` — single one-page first-run gate, ≤250 lines, every fenced `pcy` command tied to a real clap verb), AC-93 (`pcy provider {add|list|use|remove}` — first-class per-workspace LLM provider rows with credentialed key resolution; refuses raw `--key` at clap layer), AC-94 (honesty pass — README five-row "Security Model" table reflects shipped code; aspirational design-vocabulary names that were never code are removed from the live surface). Two new crates (`tar`, `flate2`), one new migration (`llm_providers`), three new event types (`backup_taken`, `backup_restored`, `llm_provider_env_fallback`). v9.1 ship gate **CLEAR** after REVIEW (round 3 PASS) + RECONCILE + VERIFY (PASS with declared MLP residual risks).

## v9.0 Summary

v9.0 is the security-and-correctness wave. It closes thirteen acceptance criteria identified by the v9 TLA+ + security audit: AC-53 (process sandbox — bubblewrap + seccomp + landlock + `pincery-init`), AC-76 (12-payload sandbox-escape suite live in CI), AC-77 (default-deny seccomp allowlist + `sandbox_blocked` SIGSYS event), AC-78 (per-agent SHA-256 event-log hash chain with `BEFORE INSERT` trigger, `pcy audit verify`, and startup verify gate that exits 5 on chain breakage), AC-79 (prompt-injection floor: untrusted-content delimiters, per-wake canary, JSON-Schema tool-call gate, per-wake tool-call rate limit), AC-80 (single-use TTL-bounded workspace-scoped capability nonces), AC-81 (TLA+ spec-coverage manifest + commit-msg hook), AC-82 (fine-grained ten-state wake lifecycle with CAS-only DB transitions and canonical-JSON `lifecycle_transition` events — the final v9.0 ship blocker), AC-83 (kernel-floor preflight at startup), AC-84 (kernel-floor library helper), AC-85/AC-86/AC-87 (sandbox hardening follow-ups), and AC-88 (devshell pin + parity tests). v8.0 agentic-harness CLI polish, v7 credential vault, v5 operator onramp, v4 self-host hardening, and the v1–v3 feature set carry forward unchanged. v9.0 ship gate **CLEAR** as of merge of PR #4 to `main` (2026-05-08).

## What Was Built

A multi-agent platform runtime implementing the Open Pincery architecture: event-sourced agents with CAS lifecycle management, LLM-powered wake/sleep cycles, maintenance projections, HTTP API, graceful shutdown, Docker Compose deployment, API rate limiting, webhook ingress, agent management, structured JSON logging, Prometheus metrics, health/readiness split, CI pipeline, signed release artifacts with SBOMs, and operator runbooks. v4 adds self-host hardening: non-root container user, runtime budget-cap enforcement with transactional cost accounting, authenticated webhook-secret rotation, a `pcy` CLI binary, a vanilla-JS control plane UI, and a published v4 API stability contract. v7 adds an AES-256-GCM credential vault with reasoner-cooperative PLACEHOLDER dispatch. **v8.0 lands the agentic-harness CLI polish**: auto-generated OpenAPI, named connection contexts with `pcy whoami`, idempotent `pcy login`/`bootstrap`, JSON-by-default piped output (`--output`), shell completions (`pcy completion`), and a clap-tree naming lint that forced every subcommand to carry a real `about` description. Single-binary Rust server backed by PostgreSQL.
A multi-agent platform runtime implementing the Open Pincery architecture: event-sourced agents with CAS lifecycle management, LLM-powered wake/sleep cycles, maintenance projections, HTTP API, graceful shutdown, Docker Compose deployment, API rate limiting, webhook ingress, agent management, structured JSON logging, Prometheus metrics, health/readiness split, CI pipeline, signed release artifacts with SBOMs, and operator runbooks. v4 adds self-host hardening: non-root container user, runtime budget-cap enforcement with transactional cost accounting, authenticated webhook-secret rotation, a `pcy` CLI binary, a vanilla-JS control plane UI, and a published v4 API stability contract. v7 adds an AES-256-GCM credential vault with reasoner-cooperative PLACEHOLDER dispatch. **v8.0 lands the agentic-harness CLI polish**: auto-generated OpenAPI, named connection contexts with `pcy whoami`, idempotent `pcy login`/`bootstrap`, JSON-by-default piped output (`--output`), shell completions (`pcy completion`), and a clap-tree naming lint that forced every subcommand to carry a real `about` description. **v9.0 lands the security-and-correctness wave** described in the v9.0 Summary above. Single-binary Rust server backed by PostgreSQL.

## How to Use It

Expand Down Expand Up @@ -106,7 +114,9 @@ At startup the server performs a fail-closed preflight for these requirements. I
- **New required env var**: `OPEN_PINCERY_VAULT_KEY` — 32 random bytes, base64-encoded. Generate once with `openssl rand -base64 32`; store alongside `OPEN_PINCERY_BOOTSTRAP_TOKEN`; losing it means losing access to every stored credential. Rotation requires re-sealing — deferred to v8.
- **New CLI verbs**: `pcy credential add|list|revoke`. The `add` path prompts for the value via rpassword and never touches argv/history.
- **New tool available to agents**: `list_credentials` (names only). The reasoner is prompted to use `PLACEHOLDER:<name>` in `env` on any shell call instead of ever pasting a secret value.
<!-- historical -->
- **Zero runtime substitution outside dispatch**: There is no network-level redaction or proxy. If an agent names a credential and also echoes the raw value in its own text, the harness cannot prevent that — the v2 prompt makes this refusal contract explicit. Cryptographic isolation of secrets from the reasoner (Zerobox-style) is the v8/v9 step.
<!-- /historical -->
- **Additive migrations**: Three new migration files; no v6 row is mutated.

## v8.0 Changes (from v7) — Agentic-Harness CLI Polish
Expand Down Expand Up @@ -201,7 +211,17 @@ This wave adds the seven P0 acceptance criteria identified by the v9 TLA+ + secu

## Known Limitations

### v9.1 (Onboarding Gate)

- **L-v91-1 — backup audit events not in `events` table**: `backup_taken` and `backup_restored` emit via `tracing::info!(target: "open_pincery::audit", …)` + `eprintln!` rather than as rows in `events`. The events table requires `agent_id NOT NULL` and the v9.1 budget (T-v91-2) sanctioned only the `llm_providers` migration. Operators relying on audit-log scrapers for backup compliance must consume stdout/stderr until v9.2 adds an `operator_events` table.
- **AC-90b — sandbox-smoke doctor check deferred to v9.2**: `pcy doctor` ships seven of the eight originally scoped checks. The eighth ("re-run a no-op sandboxed command and verify exit 0 + `sandbox_blocked` not emitted") needs a bootstrapped DB + agent at probe time and was out of the v9.1 7.5-day budget. The `Probe::sandbox_smoke` trait method is preserved as a forward-compat stub.
- **AC-93c — key-in-process-memory probe deferred to v9.2**: The wake-loop resolver reads the credentialed LLM key from the vault into a `String` and hands it to `LlmClient::new`. The AC-71 "key value never appears in agent process memory" guarantee is satisfied by construction at the `--key` flag layer (clap rejects raw keys) and at the env-var layer (no `LLM_API_KEY` lookup when a provider row exists), but it is not yet asserted with a live-process memory probe. Closing requires either `secret_proxy` extension to the LLM client or a `/proc/self/maps` grep in VERIFY.
- **AC-91 live `pg_dump`/`pg_restore` round-trip exercised in CI only**: The backup/restore in-process tests (manifest shape, forward-incompatible refusal, vault-key 0o600 extraction, key-bytes byte-grep) all pass locally; the end-to-end binary round-trip runs on CI with a real Postgres + `postgresql-client`.
- **`pg_dump` / `pg_restore` are operator-side tools**: Backup and restore are designed to run on the host, not inside the runtime container. The runtime image does not bundle the Postgres client utilities.

<!-- historical -->
- **Host-level sandbox only**: v6 ships env-clear + tempdir + 30s timeout + sudo-token rejection via `ProcessExecutor`. This is defense-in-depth, not isolation — a process running as the `pcy` user can still read any file that user can read. True container-level isolation (Zerobox) is on the roadmap.
<!-- /historical -->
- **Sudo reject is token-based, not path-based**: commands containing a `sudo` token are rejected pre-spawn; commands invoking `/usr/bin/sudo` by absolute path are not caught by the tokeniser and rely on `env_clear` + tempdir + no-tty for defense. Documented in `src/runtime/sandbox.rs`.
- **Credential substitution is reasoner-cooperative**: v7 protects against _accidental_ leakage through event/log/argv paths and against unauthorised dispatch spawns, but a malicious or confused reasoner that types a PLACEHOLDER value into plaintext content will still produce plaintext. Cryptographic isolation (v8/v9) is the structural fix.
- **Vault master-key rotation not yet implemented**: `OPEN_PINCERY_VAULT_KEY` is single-valued; re-sealing on rotation is a v8 item.
Expand Down
45 changes: 26 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,15 @@ Each agent has its own event stream, identity projection, and work list. The run

## Security Model

Six defense layers, from innermost to outermost:
Five defense layers, each backed by shipped code on `main` and a closed acceptance criterion. The table reflects the runtime topology actually deployed by `docker compose up -d --wait`; aspirational design vocabulary from earlier scoping rounds is retained only inside `<!-- historical -->` markers below.

1. **[Zerobox](https://github.com/afshinm/zerobox)** — deny-by-default per-tool process sandboxing with secret injection via proxy
2. **[OneCLI](https://github.com/onecli/onecli)** — credential vault where agents authenticate with proxy tokens; real credentials injected at the gateway
3. **Prompt injection defense** — delimiter enforcement, instruction hierarchy, canary tokens, rate limiting
4. **[Greywall](https://github.com/GreyhavenHQ/greywall)** — outer host-level sandbox wrapping the entire runtime
5. **Database security** — Postgres RLS, compile-time checked queries, append-only audit
6. **Webhook/API security** — HMAC-SHA256 verification, SHA-256 dedup, rate limiting, TLS
| Layer | Mechanism | Status | AC |
| --- | --- | --- | --- |
| Process sandbox | bubblewrap + seccomp default-deny allowlist + landlock ABI ≥ 6 + `pincery-init` exec wrapper + UID/capability drop | Shipped | AC-53 / AC-77 / AC-83 / AC-85 / AC-86 |
| Audit log | SHA-256 per-agent hash chain w/ Postgres `BEFORE INSERT` trigger + `pcy audit verify` + startup verify gate (exit 5) | Shipped | AC-78 |
| Capability gate | Single-use TTL nonces, workspace-scoped, capability-shape-bound | Shipped | AC-80 |
| Prompt-injection floor | Untrusted-content delimiter wrapping + per-wake canary + JSON-Schema tool-call gate + per-wake rate limit | Shipped | AC-79 |
| Credential vault | AES-256-GCM at rest + `PLACEHOLDER:` substitution via secret-proxy (plaintext never enters the reasoner process) | Shipped | AC-38 / AC-40 / AC-43 / AC-71 / AC-74 |

See [docs/SECURITY.md](docs/SECURITY.md) for the v9 threat model — adversary capabilities, in-scope vs out-of-scope attacks, and the vulnerability disclosure process.

Expand Down Expand Up @@ -145,22 +146,28 @@ Start with:

- [docs/input/technical-stack.md](docs/input/technical-stack.md) — implementation stack and crate choices
- [docs/input/OpenPinceryAgent.tla](docs/input/OpenPinceryAgent.tla) — formal TLA+ specification of the agent state machine. Copy into [TLA+ Process Studio](https://tlaplus-process-studio.com/) for visualizing the state machine of the system.
- [docs/input/security-architecture.md](docs/input/security-architecture.md) — six-layer security model
- [docs/input/security-architecture.md](docs/input/security-architecture.md) — original five-layer security model writeup
- [docs/input/best-practices.md](docs/input/best-practices.md) — practices mapped to academic research

## Development

Open Pincery v9 introduces a Linux-only agent sandbox (AC-53 **Zerobox**,
AC-71 secret injection proxy, AC-72 per-agent egress allowlist) that
relies on kernel primitives unavailable on macOS or Windows hosts
(bubblewrap, slirp4netns, landlock LSM, cgroup v2). AC-75 ships a
pinned Ubuntu 24.04 Docker "devshell" so every contributor runs the
identical toolchain against the identical kernel surface.

> **Terminology.** _Zerobox_ is the Linux sandbox architecture that
> isolates each tool invocation. [`zeroize`](https://docs.rs/zeroize)
> is an unrelated Rust crate used under AC-74 for memory hygiene inside
> the secret-handling path. They coexist; neither replaces the other.
Open Pincery v9 introduces a Linux-only agent sandbox (AC-53 process
sandbox, AC-71 secret-injection proxy, AC-72 per-agent egress
allowlist) that relies on kernel primitives unavailable on macOS or
Windows hosts (bubblewrap, slirp4netns, landlock LSM, cgroup v2).
AC-75 ships a pinned Ubuntu 24.04 Docker "devshell" so every
contributor runs the identical toolchain against the identical kernel
surface.

<!-- historical -->
> **Terminology (historical).** Earlier design rounds named the Linux
> sandbox architecture _Zerobox_; the implementation that shipped is
> the bubblewrap + seccomp + landlock + `pincery-init` stack described
> in the Security Model table above. The unrelated Rust crate
> [`zeroize`](https://docs.rs/zeroize) is used under AC-74 for memory
> hygiene inside the secret-handling path — different concern, similar
> name, no relationship.
<!-- /historical -->

### On Linux

Expand Down
Loading
Loading