Skip to content

docs(egress): contained-mode egress-jail doctrine + docs flip (PR 3/3)#156

Merged
jraicr merged 1 commit into
devfrom
feat/phase2-egress-3
Jun 5, 2026
Merged

docs(egress): contained-mode egress-jail doctrine + docs flip (PR 3/3)#156
jraicr merged 1 commit into
devfrom
feat/phase2-egress-3

Conversation

@jraicr

@jraicr jraicr commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

What

Slice 3/3 of the Phase 2 egress jail (issue #149, v0.4.0). Slices 1+2 (#154, #155)
merged the egress-jail code to dev; the doctrine still said
"Phase 1 — contained mode does NOT filter egress". This PR closes that
code↔doctrine desync. Prose only — no behavior change.

Changes (7 files, +215 / -46)

  • CLAUDE.md INV-9 — removed the PHASE 1 NOTE clause; the Rule now describes
    the egress jail (internal: true bridge + per-session tinyproxy sidecar,
    deny-by-default CONNECT allowlist on 443, add-only baseline, zero new Linux
    caps). Appended the Phase 2 failure mode to Why; rewrote Honest framing
    to name all 7 residual gaps (a)–(g), including the shared internal-bridge
    gap (g) (concurrent sessions share one internal bridge → a peer session's
    sidecar is reachable; accepted-but-named, out of scope). Appended the egress
    code paths to Where. Updated the §4 threat-model boundary.
  • docs/security.md — rewrote the network-exfiltration paragraph; added a
    residual-gaps subsection (a)–(g).
  • docs/architecture.md — new "Contained mode — egress jail topology" section
    (dual-bridge drydock_internal/drydock_egress + per-session sidecar diagram).
  • docs/troubleshooting.md — new "a domain is not reachable (403)" section:
    ~/.config/drydock/egress-allowlist[-<project>] how-to + drydock doctor
    EGRESS section + a drydock_net upgrade-cleanup note.
  • README.md — replaced the "Phase 1 does not filter egress" lines with the
    egress-jail summary + allowlist pointer.
  • docs/ROADMAP.md — dual-mode-containment Phase 2 → Done.
  • CHANGELOG.md[Unreleased] egress-jail entry.

Invariants

  • INV-8 — touched but PRESERVED. The sidecar runs cap_drop: ALL with zero
    cap_add; the agent's cap_add is unchanged from Phase 1. No new Linux
    capability is introduced anywhere. The doctrine states this explicitly.
  • dood mode — untouched (remains threat model A; INV-6 unchanged).

Honest-framing acceptance (grep audit)

  • Forbidden phrases (exfiltration-proof, egress-proof, sandboxed network,
    still threat model A, containment isn't sandboxing, not a security feature) — 0 occurrences.
  • All 7 gaps (a)–(g) named in both CLAUDE.md INV-9 and
    docs/security.md.
  • drydock_net appears in doc prose only in the troubleshooting
    upgrade-cleanup note; current topology is drydock_internal/drydock_egress.
  • The shipped baseline is framed as provisional (finalized by the v0.4.0
    release gate); the docs do not over-claim completeness.

Design deviation (documented)

Design §9a's draft closing sentence used the literal tokens "egress-proof" /
"exfiltration-proof" in a negation, which collides with the forbidden-phrase
grep (zero occurrences). Resolved in favor of the acceptance grep: the
"not a guarantee" disclaimer was reworded to keep the honest limitation without
the forbidden tokens.

Verification

  • scripts/test.sh1137/1137 green.
  • Fresh adversarial review (opus, cross-checked prose vs. the merged
    docker-compose.contain.yml and egress-baseline.conf): READY, 0 critical.
  • sdd-verify against REQ-7 / R7.1–R7.8 + scenarios R7-A..R7-E: PASS,
    0 critical / 0 warning.

Not in this PR

Release gates G1 (empirical baseline capture), G2 (runtime double-gate smoke),
G3 (v0.4.0 release) are maintainer-gated, bare-Linux, and tracked under #149
this PR does not close #149.

Refs #149.

…3/3)

Close the code<->doctrine desync left after slices 1+2 merged the egress-jail
code: the doctrine still described contained mode as "Phase 1 — egress open".

CLAUDE.md INV-9: replace the PHASE 1 NOTE with the egress-jail rule (internal:true
bridge + per-session tinyproxy sidecar, deny-by-default CONNECT allowlist on 443,
add-only baseline, zero new Linux caps); append the Phase 2 failure mode to Why;
rewrite Honest framing to name all 7 residual gaps (a-g), including the shared
internal-bridge gap (g); append the egress code paths to Where. Update the §4
threat-model boundary. §3 carried no egress-open claim, so no edit was needed.

docs: security.md (egress rewrite + residual-gaps subsection a-g), README,
architecture.md (dual-bridge + sidecar topology), troubleshooting.md (domain-not-
reachable how-to + 403 + doctor EGRESS + drydock_net upgrade note), ROADMAP
(Phase 2 -> Done), CHANGELOG (egress-jail entry).

INV-8 intact: the sidecar runs cap_drop: ALL with zero cap_add; the agent cap_add
is unchanged. dood mode untouched. The baseline is framed as provisional
(finalized by the v0.4.0 release gate). scripts/test.sh 1137/1137 green.
@jraicr jraicr added type:docs Documentation size:m Medium: 100-400 lines labels Jun 5, 2026
@jraicr jraicr merged commit bf38bbe into dev Jun 5, 2026
3 checks passed
@jraicr jraicr deleted the feat/phase2-egress-3 branch June 5, 2026 18:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:m Medium: 100-400 lines type:docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant