diff --git a/docs/routing/NATIVE_ROUTER_RFC.md b/docs/routing/NATIVE_ROUTER_RFC.md new file mode 100644 index 00000000000..4126d328239 --- /dev/null +++ b/docs/routing/NATIVE_ROUTER_RFC.md @@ -0,0 +1,153 @@ +--- +title: "Native Router Workstream RFC" +version: 3.8.43 +lastUpdated: 2026-07-03 +--- + + + +# Native Router Workstream RFC + +Status: proposed +Tracker: [#5670](https://github.com/diegosouzapw/OmniRoute/issues/5670) +Related PRs: #6071, #6079, #6081, #6083 + +## Problem + +OmniRoute already has mature combo routing, provider cooldown, usage history, and +compression evaluation surfaces. The native-router backlog should not land as +independent helper PRs until the maintainer accepts a staged contract for how those +surfaces fit together. + +The current deferred slices are: + +- #6071: router evaluation gate using retained replay/evaluation output. +- #6079: backend failure/cooldown state helper keyed by backend identity. +- #6083: provider plugin manifest HTTP client for sidecars and native backends. +- #6081: backend migration plan for the native-router workstream. + +## Goals + +- Define the order that turns the deferred PRs into a single 3.9/4.0 workstream. +- Keep existing combo routing behavior stable while native backends are introduced. +- Require measurable routing quality gates before routing selection changes. +- Keep provider cooldown semantics explicit across combo targets and future native backends. +- Avoid adding a new provider manifest path until its trust and cache boundaries are clear. + +## Non-Goals + +- Do not replace current combo routing in one release. +- Do not change provider credential storage or encryption as part of the first native-router slice. +- Do not persist transient combo failures as provider-wide cooldowns without provider-specific evidence. +- Do not introduce a sidecar manifest client as an implicit security boundary. + +## Current Source Anchors + +- Combo cascade and live combo events are surfaced through `src/hooks/useLiveDashboard.ts`. +- Provider cooldown and combo-live behavior are exercised by + `scripts/test/combo-live-vps.mjs`. +- Provider connection data is stored in `provider_connections`, referenced by + `scripts/dev/sync-env.mjs`. +- Usage and call-log history are documented around `usage_history` and `call_logs` in + `docs/ops/DATABASE_GUIDE.md`. +- Compression evaluation already has a CLI entrypoint in `scripts/compression-eval/index.ts`. +- Session cooldown state exists in `open-sse/services/sessionPool/session.ts`. + +## Proposed Stages + +### Stage 0: Contract and Fixture Inventory + +Before code changes, document the native-router boundary: + +- Inputs: request metadata, provider/model candidates, account health, usage history. +- Outputs: ordered backend candidates, rejection reasons, selected backend, fallback history. +- State that can affect future calls: provider/account cooldown, circuit-breaker state, + usage aggregates, and explicit user policy. + +Exit criteria: + +- The router contract can be tested without live provider credentials. +- Existing combo routing remains the default. +- Every new persisted field has an owner and a rollback plan. + +### Stage 1: Evaluation Gate + +Land the #6071 class of work first, but only as a read-only gate: + +- Replay retained request/call history. +- Produce scorecards for current routing behavior. +- Track regressions before native routing can select traffic. +- Fail the gate only on deterministic fixtures, not on live-provider variance. + +Exit criteria: + +- A maintainer can run the gate locally without secrets. +- The report explains which routing decision changed and why. +- No production routing path depends on the new evaluator yet. + +### Stage 2: Backend State Model + +Land the #6079 class of work after the gate exists: + +- Normalize backend failure and cooldown state behind a single helper. +- Keep provider/account cooldown distinct from transient combo-target failure. +- Preserve current `provider_connections` semantics unless an issue provides raw + provider evidence requiring a broader cooldown classification. + +Exit criteria: + +- Tests cover provider-wide cooldown, account-specific cooldown, and transient target failure. +- Existing combo behavior remains unchanged unless the new helper is explicitly enabled. +- The data model avoids ambiguous "backend" IDs that cannot be mapped back to a provider/account. + +### Stage 3: Provider Manifest Client + +Land the #6083 class of work only after Stage 2 defines backend identity: + +- Treat manifests as untrusted input. +- Validate provider IDs, model IDs, endpoint URLs, and capability flags. +- Cache manifests with explicit TTL and failure behavior. +- Do not allow a manifest to override credential, egress, or auth policy. + +Exit criteria: + +- Manifest parsing is covered by fixtures for missing, malformed, stale, and hostile input. +- Network fetch failures do not block existing configured providers. +- The manifest client does not become a hidden bypass around provider config. + +### Stage 4: Native Backend Migration Plan + +Land the #6081 class of work as the release plan: + +- 3.9: evaluator and state helper ship behind non-routing paths. +- 3.9.x: manifest client ships as opt-in discovery only. +- 4.0: native-router selection can become eligible after scorecard parity. + +Exit criteria: + +- Rollout can be disabled without schema rollback. +- Dashboards show current route, candidate order, and fallback reason. +- Known rollback path is documented before native-router selection is enabled. + +## Acceptance Gates + +- No route-selection change lands without a deterministic replay fixture. +- No provider cooldown behavior changes without a unit test and, when provider-specific, + a captured raw upstream status/body/header sample. +- No manifest-sourced backend is eligible until validation and trust boundaries are tested. +- No dashboard-visible state is added without a stable event/field owner. + +## Risks + +- A native-router slice could accidentally change combo semantics before the evaluation gate exists. +- Backend identity could collapse provider/account/model into one key and make cooldowns too broad. +- Manifest discovery could become a policy bypass if it is treated as trusted configuration. +- Live-provider tests can be flaky; deterministic fixtures must remain the release gate. + +## Recommended Next PR Order + +1. RFC-only PR for this document. +2. Rebase #6071 as a read-only evaluator/gate PR. +3. Rebase #6079 as a backend state helper with no default routing behavior change. +4. Rebase #6083 as a manifest parser/client behind opt-in discovery. +5. Rebase #6081 as the 3.9/4.0 migration plan after the first three contracts are accepted. diff --git a/docs/security/ISSUE_AGENT_RFC.md b/docs/security/ISSUE_AGENT_RFC.md new file mode 100644 index 00000000000..e39a0d403e4 --- /dev/null +++ b/docs/security/ISSUE_AGENT_RFC.md @@ -0,0 +1,204 @@ +--- +title: "Issue Agent Security Boundary RFC" +version: 3.8.43 +lastUpdated: 2026-07-03 +--- + + + +# Issue Agent Security Boundary RFC + +Status: proposed +Tracker: [#5620](https://github.com/diegosouzapw/OmniRoute/issues/5620) +Related PR: #5867 + +## Problem + +The issue-agent workflow can create high-impact automation: read a GitHub issue, +triage it, modify code, run checks, and prepare a pull request. That is useful only +if the security boundary is explicit before implementation resumes. + +The previous implementation work should remain parked until the maintainer accepts +what the agent may read, write, execute, and publish. + +## Goals + +- Define the trust boundary for issue-to-PR automation. +- Make repository writes opt-in and auditable. +- Keep generated code changes behind local validation before any PR is opened. +- Prevent issue text, comments, or labels from becoming unsandboxed instructions. +- Reuse existing guardrail, credential, and error-sanitization patterns. + +## Non-Goals + +- Do not run untrusted issue text as shell instructions. +- Do not grant production credentials to issue-agent runs. +- Do not auto-merge or auto-release agent-created PRs. +- Do not allow issue labels alone to bypass maintainer approval. +- Do not expose raw secrets, tokens, stack traces, or local paths in issue comments. + +## Current Source Anchors + +- Security guardrail documentation exists in `docs/security/GUARDRAILS.md`. +- CLI token authentication is documented in `docs/security/CLI_TOKEN_AUTH.md`. +- Secret and public credential handling is documented in `docs/security/PUBLIC_CREDS.md`. +- Error response sanitization is documented in `docs/security/ERROR_SANITIZATION.md`. +- Workflow state modeling exists in `open-sse/services/workflowFSM.ts`. +- GitHub/token redaction patterns are present in `scripts/sre/redact-logs.mjs`. +- Local-only and management route classification lives in + `src/server/authz/routeGuard.ts`. +- Spawn-capable route prefixes are centralized in + `src/shared/constants/spawnCapablePrefixes.ts`. +- Settings validation rejects unsafe local-only bypasses in + `src/shared/validation/settingsSchemas.ts`. +- Shared log redaction helpers live in `src/shared/utils/logRedaction.ts`. +- Outbound URL guarding lives in `src/shared/network/outboundUrlGuard.ts`. + +## Threat Model + +### Assets + +- Repository write access. +- GitHub tokens and local credentials. +- Maintainer identity and review trust. +- Local workspace files and environment variables. +- CI minutes and release automation. + +### Attackers + +- External issue author attempting prompt injection. +- Contributor with comment access attempting workflow escalation. +- Compromised dependency or generated code path. +- Malicious or malformed issue payload causing unsafe shell execution. + +### Trust Boundaries + +- GitHub issue content is untrusted input. +- Repository contents are trusted only at the checked-out revision. +- Local secrets are never part of agent context. +- Generated patches are untrusted until tests and review pass. +- CI/release automation is out of scope for the issue agent. +- Any route that can spawn `git`, `gh`, package-manager checks, model CLIs, or + Docker workers is a local-only execution boundary. +- Diagnostic bundles cross a redaction boundary before persistence and before any + model/provider request. + +## Permission Model + +The issue agent should operate in four modes: + +| mode | allowed | forbidden | +| ---------- | ----------------------------------------------------- | ------------------------------ | +| `recorded` | store issue context and proposed next steps | subprocesses, checkout writes | +| `triage` | summarize issue, classify area, identify likely files | edit files, run network writes | +| `patch` | edit local files, run local checks, produce diff | push, post comments, open PR | +| `publish` | push branch, open draft PR, post bounded summary | merge, release, modify secrets | + +Mode escalation requires an explicit maintainer action. The agent must record: + +- issue URL and revision timestamp; +- selected mode; +- files changed; +- commands run; +- tests passed or failed; +- whether network write actions were used. + +## Workflow + +### Stage 0: RFC and Audit Contract + +- Land this RFC before reviving #5867. +- Add an audit envelope for every issue-agent run. +- Define the exact GitHub permissions required for each mode. +- Keep the feature default-off and add an emergency kill switch that short-circuits + new runs before enqueue or worker dispatch. + +Exit criteria: + +- Maintainer can review what the agent is allowed to do before any code path lands. +- The audit record is generated even when the run fails. + +### Stage 1: Triage-Only Agent + +- Add route-guard tests before any execution route exists. +- Read issue title/body/comments. +- Classify affected area from repository search. +- Produce a no-edit report with suspected files and test entrypoints. + +Exit criteria: + +- No file writes. +- No push/comment/PR side effects. +- No subprocess execution. +- Prompt-injection fixtures prove issue text cannot override system policy. + +### Stage 2: Patch Agent + +- Apply local edits on an isolated branch or worktree. +- Run targeted checks. +- Produce a diff and validation report. + +Exit criteria: + +- Dirty workspace is detected before edits. +- Commands are allowlisted. +- Secrets are redacted from logs before summaries are generated. +- Host checkout mutation is impossible outside the explicit patch mode. + +### Stage 2.5: Worker Isolation + +- Run fix-capable work in a Docker worker or equivalent isolated process boundary. +- Do not mount the host Docker socket. +- Mount source read-only unless the run is explicitly in patch mode. +- Pass only scoped GitHub credentials and required environment variables. +- Apply outbound URL guards before any issue-agent fetches untrusted URLs. + +Exit criteria: + +- Tests prove `recorded`, `triage`, and planning modes cannot mutate the host checkout. +- Tests prove command allow-list denial is logged and fails closed. +- A worker failure cannot leak raw environment variables in the API response. + +### Stage 3: Draft PR Publisher + +- Push only the prepared branch. +- Open a draft PR with the audit summary. +- Link back to the originating issue. + +Exit criteria: + +- PR remains draft by default. +- No auto-merge path exists. +- Failed checks are surfaced instead of hidden. + +## Acceptance Gates + +- Unit tests cover prompt injection in issue body, comments, and labels. +- Tests cover mode escalation denial. +- Tests cover dirty-workspace refusal or isolation. +- Tests cover redaction of GitHub tokens and generic secret patterns. +- Documentation states exactly which mode can post comments or open PRs. +- The eventual issue-agent route prefix is local-only for every endpoint that can + enqueue or execute work. +- Spawn-capable issue-agent routes cannot be added to manage-scope bypass + prefixes. +- Request bodies are schema-validated and size-bounded before route execution. +- Run storage is retention-pruned and never stores raw tokens or environment + variables. +- Audit records include actor, mode, issue/PR URL, run ID, branch, redaction + counts, command outcomes, and final status. +- Draft PR creation is impossible from `recorded`, `triage`, or planning modes. + +## Open Questions + +- Should publish mode require a label, a slash command, or both? +- Should patch mode run in an isolated worktree by default? +- Should comments be posted only on success, or should failures also be reported? +- What retention period should audit records use? + +## Recommended Next PR Order + +1. RFC-only PR for this document. +2. Triage-only implementation with prompt-injection fixtures. +3. Patch mode with dirty-workspace isolation and allowlisted commands. +4. Draft PR publisher with explicit maintainer-gated escalation.