Commit Graph

221 Commits

Author SHA1 Message Date
didericis-claude e82dbaba09 docs(prd): draft PRD for separate agent/bottle selection
Closes #269.
2026-06-25 16:13:19 -04:00
github-actions[bot] 9f7c067e85 ci(prd): assign sequential numbers to new PRDs 2026-06-25 11:42:07 +00:00
didericis-claude 302920e290 feat: support multiple parents in bottle extends:
Allow extends: to accept a list of bottle names in addition to a plain
string. Parents are resolved independently and folded left-to-right
into a single combined parent before the child is merged on top, so
orthogonal concerns (base env, networking, agent provider) can live in
separate bottles without forcing a linear chain.

Merge rules for the parent fold: env dict-merge with later winning on
collision; git-gate.user per-field overlay; git-gate.repos union by
name with later winning per-field on same name; egress.routes
concatenated; all scalar fields (supervise, agent_provider, egress.log)
use last-wins. The existing child-wins-over-all-parents rule is
unchanged. Cycle detection, diamond deduplication, and missing/invalid
parent errors all work across multi-parent graphs.

Closes #268
2026-06-25 05:10:03 -04:00
github-actions[bot] 8a092504b8 ci(prd): assign sequential numbers to new PRDs 2026-06-25 04:50:36 +00:00
didericis-claude 9b929d0684 fix(egress): strip injected Authorization and redact bodies in LOG_FULL path
_log_request and _log_response wrote headers and bodies to stderr verbatim.
_log_request also included the sidecar-injected upstream Authorization value,
exposing live bearer tokens on every allowed request under LOG_FULL.

Apply redact_tokens to all header values and bodies in both log functions;
exclude the authorization header from _log_request entirely since its value
is always a live sidecar-injected credential by the time _log_request runs.

Closes #257
2026-06-25 00:32:42 -04:00
github-actions[bot] ec41f629a4 ci(prd): assign sequential numbers to new PRDs 2026-06-25 04:19:30 +00:00
didericis-codex 4808ef557a fix(egress): randomize canary secret env name
lint / lint (push) Successful in 2m15s
test / unit (pull_request) Successful in 45s
test / integration (pull_request) Successful in 26s
2026-06-25 03:25:37 +00:00
didericis-claude e02fab15d0 docs(prd): flip prd-new-strengthen-outbound-exfil-detection Draft → Active
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:09:11 -04:00
didericis-claude ea6bc5a170 docs: draft PRD prd-new for strengthen-outbound-exfil-detection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 23:09:11 -04:00
didericis d2d50be65a Restructure PRD 0062 to the init-prd template
test / unit (pull_request) Successful in 39s
test / integration (pull_request) Successful in 25s
lint / lint (push) Successful in 2m8s
test / unit (push) Successful in 41s
test / integration (push) Successful in 25s
Update Quality Badges / update-badges (push) Successful in 1m32s
Conform the PRD to the standard PRD-new skeleton: add a Scope section
(In scope / Out of scope), rename Design -> Proposed Design and split
its prose into New services / Existing code touched / Data model
changes / External dependencies, fold the old Implementation chunks
into In scope, and add a References section. No change in substance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-24 21:10:31 -04:00
didericis 1ad710a041 Default agent-provider routes to the redact on-match policy
lint / lint (push) Successful in 1m42s
test / unit (pull_request) Successful in 34s
test / integration (pull_request) Successful in 16s
Provider routes (the agent talking to its own LLM API — api.anthropic.com,
the Codex backend, etc.) carry the whole conversation payload, which is the
worst source of token-shaped false positives. egress_routes_for_bottle now
fills outbound_on_match=redact on any provider route that doesn't set it
explicitly, so a match there is scrubbed and forwarded rather than blocked
or queued for the operator. A provider that sets the policy keeps its
choice; manifest routes still default to supervise.

Tests: provider route gets redact default, explicit provider policy
preserved, manifest route unaffected. README + PRD 0062 updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnvBjPZC5V7qeQpFbQdDmS
2026-06-24 20:40:36 -04:00
didericis cdfaaa3de8 Add dlp.outbound_on_match policy (block | redact | supervise)
lint / lint (push) Successful in 1m41s
test / unit (pull_request) Successful in 30s
test / integration (pull_request) Successful in 18s
Give each egress route a policy for what the proxy does when an outbound
DLP detector matches a token, defaulting to the supervise flow added in
the previous commit. The goal is cutting false-positive friction without
weakening default-deny.

- redact: scrub the matched value(s) from the body, non-host headers, and
  path/query via redact_tokens, then re-scan. Forward if clean; fail
  closed with a 403 if a match remains on a surface redaction can't
  rewrite (the hostname, or a unicode-evasion token). For routes where a
  token-shaped value is noise the upstream doesn't need.
- block: the original hard 403, never overridable.
- supervise (default, unset): hold the request for operator approval.

Structural blocks (CRLF, no safelist-able value) stay hard 403s under
every policy.

Threads outbound_on_match from the bottle manifest (manifest_egress)
through the resolved EgressRoute and rendered routes.yaml (egress.py) to
the addon's Route (egress_addon_core), and round-trips it via the
list-egress-routes introspection endpoint. The allow/egress-block tool
descriptions document the new key.

Tests: manifest parse/validation, core parse/validation, full
manifest->render->addon round-trip for redact. README + PRD 0062 updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnvBjPZC5V7qeQpFbQdDmS
2026-06-24 16:50:13 -04:00
didericis 7f2352287e PRD 0062: supervisor override for egress token blocks
lint / lint (push) Successful in 1m42s
test / unit (pull_request) Successful in 31s
test / integration (pull_request) Successful in 16s
When the outbound DLP catches a token, route the block through the
existing supervisor approval queue instead of returning 403 outright.
The egress proxy holds the request open until the operator answers, then
remembers an approved value for the life of the proxy so the request --
and later ones carrying it -- flow through. Fails closed on rejection,
timeout, malformed response, or when supervise is disabled.

- ScanResult.matched carries the raw matched substring (sidecar-only;
  never logged or written to the proposal). scan_outbound and the token
  detectors take a safe_tokens set and skip approved values, continuing
  past a safelisted match so a second secret in the same request is
  still caught.
- New egress-token-allow proposal tool, written directly to the queue by
  the addon (the gitleaks-allow pattern from PRD 0061). build_token_allow
  _payload renders host/method/path/detector reason + redacted context.
- Async request hook polls the queue without stalling the proxy event
  loop; EGRESS_TOKEN_ALLOW_TIMEOUT_SECONDS (default 300) bounds the wait.
- Supervisor TUI renders egress-token-allow like gitleaks-allow: report
  only, modify unavailable, approval requires a recorded reason.
- Unit tests for the matched/safe-tokens plumbing, payload builder, tool
  constant round-trip, and TUI paths; README + PRD 0062.

Closes #261.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HnvBjPZC5V7qeQpFbQdDmS
2026-06-24 16:12:50 -04:00
github-actions[bot] de71533a17 ci(prd): assign sequential numbers to new PRDs 2026-06-23 21:47:01 +00:00
didericis-codex 83eb9e4041 docs(prd): add gitleaks allow supervision 2026-06-23 17:36:08 -04:00
github-actions[bot] 4d56f515bc ci(prd): assign sequential numbers to new PRDs 2026-06-23 21:32:54 +00:00
didericis-codex 6e73cc4d86 feat: support smolmachines bottle commit 2026-06-23 16:53:41 -04:00
didericis-claude 64fac71025 docs(prd): mark commit-bottle-state PRD as Active 2026-06-23 16:53:41 -04:00
didericis-claude f8ac22c316 feat(cli): add commit command to snapshot running bottle state
Adds `./cli.py commit [<slug>]` which runs `docker commit` on the
active agent container and stores the resulting image tag in per-bottle
state. The next `./cli.py resume <slug>` automatically boots from the
committed snapshot instead of rebuilding from the Dockerfile, preserving
all in-container state across restarts and migrations.

- bottle_state: add write_committed_image / read_committed_image helpers
- docker/util: add commit_container wrapper around `docker commit`
- docker/launch: check for a committed image before the Dockerfile build
  step; fall back to normal build if the image is absent from the daemon
- cli/commit: new command with interactive slug picker; errors clearly on
  non-Docker backends
- 50 new unit tests covering all paths

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-23 16:53:41 -04:00
github-actions[bot] f2d5307573 ci(prd): assign sequential numbers to new PRDs 2026-06-11 02:36:07 +00:00
didericis 932e71c0bf fix(macos-container): make backend the macos default 2026-06-10 22:25:00 -04:00
didericis d3b0b330aa fix(macos-container): preserve working builder dns 2026-06-10 22:25:00 -04:00
didericis 5e927bcd13 fix(macos-container): start builder with dns 2026-06-10 22:25:00 -04:00
didericis 890a146413 test(macos-container): add launch integration smoke 2026-06-10 22:25:00 -04:00
didericis-codex eb7cae1fea docs: link macos container prd to review comment 2026-06-10 22:25:00 -04:00
didericis-codex fe82dc7f2b feat: add macos container backend scaffold 2026-06-10 22:25:00 -04:00
didericis-codex 3f04567290 egress: require opt-in for HTTPS git fetch
test / unit (pull_request) Successful in 42s
test / integration (pull_request) Successful in 27s
lint / lint (push) Successful in 1m53s
test / unit (push) Successful in 41s
test / integration (push) Successful in 23s
Update Quality Badges / update-badges (push) Successful in 1m35s
2026-06-10 07:00:01 +00:00
didericis-codex 8ea90adcaf fix: raise git http body cap 2026-06-10 06:29:46 +00:00
didericis 504144eb9c fix(pi): prepare runtime state and agent workdir
lint / lint (push) Failing after 1m58s
test / unit (push) Successful in 41s
test / integration (push) Successful in 24s
Update Quality Badges / update-badges (push) Successful in 1m27s
2026-06-10 00:02:28 -04:00
didericis 598a20a3f0 fix(pi): keep interactive sessions open
lint / lint (push) Successful in 1m29s
test / unit (pull_request) Successful in 30s
test / integration (pull_request) Successful in 17s
2026-06-09 06:00:40 -04:00
didericis c8b5ba3812 feat(pi): support egress injected api keys
lint / lint (push) Successful in 1m38s
test / unit (pull_request) Successful in 31s
test / integration (pull_request) Successful in 17s
2026-06-09 05:56:39 -04:00
didericis-codex 5ea9fda69b docs: activate pi provider prd
lint / lint (push) Successful in 1m43s
test / unit (pull_request) Successful in 34s
test / integration (pull_request) Successful in 18s
2026-06-09 08:32:09 +00:00
didericis-codex 1f38a96561 docs: add pi provider prd 2026-06-09 08:23:00 +00:00
github-actions[bot] f7f161e60f ci(prd): assign sequential numbers to new PRDs 2026-06-09 03:37:10 +00:00
didericis-codex 17fc44d0d8 complete(prd): mark smolmachines default active
lint / lint (push) Successful in 1m46s
test / unit (pull_request) Successful in 41s
test / integration (pull_request) Successful in 22s
2026-06-09 03:27:58 +00:00
didericis-codex 1bebb7467f feat(backend): default to smolmachines 2026-06-09 03:27:31 +00:00
didericis aff042855a ci(prd): rename PRD to prd-new placeholder per new convention
lint / lint (push) Successful in 1m47s
2026-06-08 23:10:09 -04:00
didericis 39b0c4f720 docs(prd): renumber PRD 0055 → 0058 (0055 slot taken by extended-outbound-scan) 2026-06-08 23:10:09 -04:00
didericis 43a5700ae6 docs(prd): PRD 0055 - promote smolmachines to default backend 2026-06-08 23:10:09 -04:00
github-actions[bot] 103f9adcfd ci(prd): assign sequential numbers to new PRDs 2026-06-08 03:26:08 +00:00
didericis 652c8cb5a7 ci(prd): rename PRD to prd-new placeholder per new convention
test / unit (pull_request) Successful in 37s
test / integration (pull_request) Successful in 49s
lint / lint (push) Successful in 1m30s
prd-number / assign-numbers (push) Successful in 32s
test / unit (push) Successful in 31s
test / integration (push) Successful in 42s
Update Quality Badges / update-badges (push) Successful in 1m11s
2026-06-07 23:19:11 -04:00
didericis 11a8f3ba99 docs(prd): renumber PRD 0053 → 0055 (0053 slot claimed by user-provider-plugins) 2026-06-07 23:19:11 -04:00
didericis-claude 1ecef55fea feat(dlp): websocket scanning, response headers, extended encoding variants, sk-proj pattern (PRD 0053) 2026-06-07 23:19:11 -04:00
didericis-claude b1283a0e7b feat(egress): extend outbound DLP scan to headers, query params, path, and hostname (PRD 0053) 2026-06-07 23:19:11 -04:00
didericis-claude 2c51bc47e8 docs(prd): PRD 0053 extended outbound DLP scan surfaces 2026-06-07 23:19:11 -04:00
github-actions[bot] 916b70c595 ci(prd): assign sequential numbers to new PRDs 2026-06-08 00:34:45 +00:00
didericis 8743299226 ci(prd): rename PRD to prd-new placeholder per new convention
lint / lint (push) Failing after 1m29s
test / unit (pull_request) Successful in 30s
test / integration (pull_request) Successful in 44s
2026-06-07 14:41:27 -04:00
didericis 205e94f960 docs(prd): renumber PRD 0053 → 0056 (0053 slot claimed by user-provider-plugins) 2026-06-07 14:41:27 -04:00
didericis 79212481c9 feat(egress): replace log bool with integer log levels (0/1/2)
Level 0 (off, default): no stderr output beyond boot line.
Level 1 (blocks): each block/warn emitted as JSON with reason and
request context (host, method, path, response_status for inbound).
Level 2 (full): level-1 events + egress_request and egress_response
JSON lines for every forwarded connection.

Block logging at level 1+ replaces the previous plain-text stderr write.
DLP warn logging is also gated on level 1+. All block call sites now pass
_req_ctx(flow) so the blocked request is visible in the log entry.
Boot message shows log level label (off/blocks/full).

Adds PRD 0053 documenting wire format, manifest format, and all log event
shapes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:41:27 -04:00
didericis 7ebddf7792 ci(prd): assign sequential numbers to new PRDs
prd-number / assign-numbers (push) Successful in 20s
prd-new-user-provider-plugins → 0053-user-provider-plugins
prd-new-named-labelled-agents → 0054-named-labelled-agents

Both PRDs ship with their implementations so Status flips Draft → Active.
Manual fix: the prd-number workflow did not fire on these merges.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-07 14:23:56 -04:00