feat(egress-gate): no-fork Pi admission before history writes - #38
feat(egress-gate): no-fork Pi admission before history writes#38johnnygreco wants to merge 70 commits into
Conversation
bc652d4 to
0540f54
Compare
Phase 0 Review RecordFrozen range: Scope reviewed: final admission names/contracts, registry-derived bindings, removal of the superseded receipt path, immutable fork/proto pin, runtime/example/docs updates, and provider fixture provenance. Independent review:
Validation:
POC scope remained constrained: 22 files in the main Phase 0 commit with net one-line deletion, followed by the focused two-file interoperability fix. No shims, speculative infrastructure, or unrelated cleanup were added. |
Phase 1 Review RecordFrozen range: Scope reviewed: exact seven-origin runtime dispatch, the shared text adapter, distinct assistant/bash adapters, immutable-field validation, Describe bindings, cross-language interoperability, and focused tests. Independent review found one concrete high-severity interoperability defect: Python byte equality rejected valid JavaScript number spellings in arbitrary assistant tool arguments. The minimal fix in Scope audit:
Validation:
|
Phase 2 Review RecordFrozen range: Scope reviewed: stateless v2 whole-context hash/count binding, ordered user/tool entry derivation, Chat Completions and Responses extraction, send-time replacements, pre/post gate checks, append-time empty attestations, runtime handle lookup, and shared JS/Python vectors. Independent findings and disposition:
Scope audit:
Validation:
|
Phase 3 Review RecordFrozen range: Scope reviewed: real self-verifying demo cases, printable commands, content-safe reason-code logging, workload readiness removal, base64 runtime bodies, architecture/example docs, and generated mirror workflow. Independent findings and fixes:
Scope audit:
Validation:
|
Documentation previewBuilt from |
Phase 4 Review RecordReviewed head: Scope remained POC-bounded: the launcher consumes and closes the inherited capability FD, the bridge adapter attaches one bearer header, the existing demo adds an unauthenticated negative control, and focused documentation/tests describe the capability and residual same-user memory-reading risk. Pi and provider behavior are untouched. The final documentation follow-up replaces the stale middleware-field opt-out with the actual supervisor startup flag and updates the canonical architecture page. Its generated mirror was staged and byte-checked through the documented workflow. Independent security and scope reviews: clean; no remaining blocker/high/medium findings. Validation:
|
Final Review RecordReviewed head: Independent Research, documentation, security, and holistic cross-repository reviews are clean: no remaining blocker, high, or medium findings. The final documentation accurately states the implemented POC boundaries, including assistant-thinking coverage, immutable assistant tool calls, transport-history fail-closed limits, capability residual risk, and the checked-in endpoint/catalog scope of Validation:
The real The PR remains draft; no merge/readiness change was made. |
Signed-off-by: Johnny Greco <jogreco@nvidia.com>
Signed-off-by: Johnny Greco <jogreco@nvidia.com>
Delegate generation to omm with project validation and publish its generated bindings and manifest. Align project guidance with the issue-first policy for manager gaps. The generation helper depends on the --check-command option in PR #60.
…avior Preserve allowed native messages and replay metadata, use Pi's native compaction and thinking controls, and validate admission before history publication. Simplify unused admission abstractions and test scaffolding, protect registration ownership, and align the example and architecture docs.
221ab32 to
4d6909f
Compare
What this adds
A runnable proof of concept for admitting content before it enters an agent's conversation, paired with enforcement before a model request leaves its sandbox.
The main contribution is
pi-harness: a launcher using Pi's native TUI and public SDK, with an application-owned agent that checks content before publishing it. Pi still provides the editor, session runtime, tools, resource loading, and JSONL persistence. OpenShell provides the sandbox, network interception, and provider credential delivery. Neither Pi nor OpenShell is patched or forked.The implementation supports reasoning, real tools and tool continuations, expanded skills, and manual/automatic compaction. Admission can deny content or safely redact it before it reaches live history or storage. Allowed native messages retain their block order and provider metadata; Pi's native compaction computation and retention behavior are used.
Why two checks?
Suppose a tool reads sensitive text. Blocking the next model request stops that text leaving the sandbox, but cannot undo an earlier write to the agent's live conversation or saved transcript. Conversely, a cooperative agent check alone cannot stop a different client from sending a raw provider request.
This example demonstrates two complementary boundaries:
This is the narrative for “Gating at the network layer is not enough”: local-history integrity and outbound authorization happen at different times. Neither check replaces the other.
How the pieces fit
flowchart LR subgraph Sandbox[OpenShell sandbox] UI[Native Pi TUI] H[pi-harness: admission-controlled agent] S[Pi live history and JSONL session] UI --> H H -->|Approved events only| S end subgraph Trusted[Outside the sandbox] G[Egress Gate service: policy and receipt signing] O[OpenShell network proxy] end H -->|HTTPS: candidates and context approval| G G -->|Allow, replace, deny, or context receipt| H H -->|Provider request with receipt header| O O -->|Authenticated gRPC: verify actual request| G G -->|Allow or deny and remove receipt header| O O -->|Only on allow: attach real credential and forward| P[Model provider]One Egress Gate service, two interfaces: HTTPS admission for the harness and standard authenticated OpenShell middleware gRPC for the proxy. It is not another model proxy, a loopback bridge, or a custom OpenShell RPC.
pi-harnessAgentSessionConfig.agent; wire checked compaction throughsession_before_compact.A message's journey
sequenceDiagram participant H as pi-harness participant G as Egress Gate participant S as Pi history and JSONL participant O as OpenShell proxy participant M as Model provider H->>G: Check candidate before publication alt Denied G-->>H: Deny Note over H,S: Candidate never enters live history or JSONL else Allowed or safely redacted G-->>H: Approved content H->>S: Publish approved message events Note over H,G: Separate check before each model call H->>G: Approve ordered user/tool context G-->>H: Signed receipt H->>O: Provider request + x-egress-admission O->>G: Actual request + authenticated sandbox context G-->>O: Allow or deny after checking receipt and policy opt Allowed O->>M: Strip receipt, attach credential, forward M-->>H: Response through proxy Note over H,S: Response is another candidate: admit before publication end endCandidate checks cover final user text after explicit skill expansion, project context, finalized assistant answer/reasoning and tool calls, tool results/errors, and completed compaction summaries. Manual and automatic compaction share the checked path, using Pi's native summary computation and recent-context retention, including split turns. Real tools and tool continuations remain available.
Pi's native
AgentSessionremains the persistence owner. The harness gates its events before they can update the transcript; it does not append content and then remove it. Raw response streaming and tool progress are withheld until final content is approved. Temporary candidate buffers and editor drafts are not admitted conversation history.Redaction happens at insertion, so history and subsequent model context agree. Plain reasoning text can be redacted; signed or structured replay metadata cannot be rewritten independently. Allowed native messages preserve their original content blocks, signatures, and metadata. Executable tool-call fields cannot be rewritten. A replacement at the later context-receipt step is rejected rather than silently changing only the outbound request.
What the attestation actually guarantees
The service signs the ordered user/tool text projection, bound to the sandbox, destination, policy, and expiry. At egress, it extracts that projection from the actual request and verifies the receipt. Missing, invalid, expired, or mismatched receipts fail closed. The intercepted request also passes the configured request policy.
Deliberate POC scope
The implementation uses Pi 0.85.1, with OpenShell 0.0.116 as the tested protocol baseline. It supports one selected text-only OpenAI-compatible Chat Completions model, including OpenRouter reasoning requests and replay, fresh sessions, sequential tools, explicit skills, steering/follow-ups,
/new, and manual/automatic compaction. The example model configuration uses GLM-5.3-Flash through OpenRouter; the integration is not tied to that provider or model.The native TUI is real, but this is not full stock Pi behavior or CLI parity. Images, other provider API protocols, arbitrary extensions, resume/import/branching, model switching, resource reload, and direct
!/!!execution are outside this POC. The model's bash tool remains available with bounded output. Unchecked tool progress/details are not published. Responses, including reasoning, are buffered until admitted rather than streamed unchecked into the transcript.Ordinary HTTP-only Egress Gate remains available. The receipt-required service is selected explicitly with
--admission-config. Protocol artifacts are managed throughomm, using the standard OpenShell contract.Try it and review it
Start with the example README. Use your existing gateway, your own native Pi
models.json, and a provider credential; no NVIDIA-specific endpoint is required. Host service reachability and a shared Docker daemon are prerequisites for this example's image workflow.The flow is
prepare, keepserverunning, thenregister,setup, andlaunch.verifyperforms real-model acceptance;cleanupremoves demo resources and its registration. Every action supports--print. Registration helpers support local Homebrew and DEB/RPM user services; other deployments need operator-managed registration. Registration restarts the gateway; cleanup deletes sandbox sessions.The policy's harmless
DENY_THISandREDACT_THISmarkers demonstrate denial and replacement with[REDACTED]; they are explicit example rules, not built-in Pi/OpenShell behavior.Suggested review order:
pi-harness/src:agent.tsowns publication;session.tswires Pi and compaction;admission.tsmaps candidates and obtains receipts.admissionservice package: candidate decisions, receipt signing/verification, and the HTTPS boundary.Validation and remaining acceptance
Deterministic coverage exercises pending/denied live and durable writes, redaction, real tools and skill expansion, compaction, receipt verification, and gateway JWT authentication. Cross-language integration uses Pi's real serializer and a pseudo-terminal-driven native TUI, with local HTTPS admission/provider endpoints and controlled provider responses. Its authenticated local gRPC channel does not exercise production TLS gRPC startup or a live gateway.
Earlier live-runtime checks demonstrated credential delivery, admission denial, and missing-receipt rejection. A receipt-bearing provider request reached a real endpoint but returned 401 with an intentionally invalid credential. That is transport evidence, not successful model inference.
Keep draft: the current native-TUI workflow still needs a successful
./demo.sh verifyrun against live OpenShell and a real model. Do not equate deterministic integration or historical CI results with that acceptance gate.Current local validation passed 384 Python tests, 28 Node tests, formatting/lint/type/import checks, dependency audit, and documentation tests/build. Coverage includes reasoning admission/redaction, immutable replay metadata, native-message preservation, tool continuations, and both compaction paths. These are local results, not a claim about remote CI or live-model acceptance. No Dev Note is published by this PR.