Skip to content

docs(adr,openrouter): ADR-0020 — localhost-callback-only OAuth PKCE (Phase 0 prereq)#409

Merged
thinmintdev merged 1 commit into
mainfrom
feature/phase0-adr-0020
May 29, 2026
Merged

docs(adr,openrouter): ADR-0020 — localhost-callback-only OAuth PKCE (Phase 0 prereq)#409
thinmintdev merged 1 commit into
mainfrom
feature/phase0-adr-0020

Conversation

@thinmintdev
Copy link
Copy Markdown
Contributor

Summary

  • ADR-0020 documents the localhost-callback-only constraint (preserves ADR-0012 LAN-trust)
  • Skeleton callback route at /api/openrouter/auth/callback returns 501 (V1 fills in the exchange flow)
  • is_loopback_host helper + per-route guard enforce the constraint from day 1
  • Trade-off: users complete OAuth via localhost browser or SSH-tunneled :8080; documented in CONFIG.md

Why now

DA review of the OpenRouter integration plan flagged this as P0 must-fix #4 (OAuth PKCE callback re-opens auth surface). ADR-0020 ships the architectural decision so V1 has a baseline that respects ADR-0012.

Test plan

  • is_loopback_host truth table (loopback literals accepted; LAN/public/empty rejected; 127.0.0.2 rejected — strict allowlist not /8 CIDR)
  • Callback returns 501 from loopback with adr: ADR-0020 pointer
  • Callback returns 403 from non-loopback with error: loopback_required typed envelope
  • require_loopback helper raises HTTPException(403) for fabricated LAN Request scope
  • require_loopback helper fail-closes on missing ASGI client tuple
  • ADR cross-link to ADR-0012 + ADR-0019 verified
  • CONFIG.md operator note for the tunnel UX
  • CHANGELOG entry under Unreleased
  • ruff format --check src/ tests/ clean
  • ruff check src/ tests/ clean
  • mypy src/hal0/api/openrouter/ clean (0 errors in new module)
  • 18/18 tests pass in tests/api/test_openrouter_auth_loopback.py

Refs openrouter-research-2026-05-28/PLANNING.md §3 Phase 0 + §5 Q1.

🤖 Generated with Claude Code

…Phase 0 OpenRouter prereq)

DA must-fix #4 from the OpenRouter integration analysis: OAuth PKCE
callback re-introduces an auth surface ADR-0012 stripped. ADR-0020
constrains the callback to 127.0.0.1 only — ADR-0012's LAN-trust
posture holds; users SSH-tunnel :8080 to complete the OR handshake.

Scaffolds:
- src/hal0/api/openrouter/auth.py — callback route (501; V1 fills in)
- src/hal0/api/openrouter/_loopback.py — is_loopback_host helper
- /api/openrouter/auth/callback enforces loopback guard from day 1

V1 (OpenRouter-as-Hermes-upstream) lands the actual code-exchange flow
on top of this scaffold.

Refs openrouter-research-2026-05-28/PLANNING.md §3 Phase 0 + §5 Q1.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thinmintdev thinmintdev merged commit 7b9aae3 into main May 29, 2026
4 checks passed
@thinmintdev thinmintdev mentioned this pull request May 29, 2026
4 tasks
thinmintdev added a commit that referenced this pull request May 29, 2026
End-of-stream cut for v0.3. Bundles MCP-completion, memory-map redesign,
Settings → Updates fix (#386), silent-eviction dispatcher recovery (#392),
ADR-0020 OpenRouter callback skeleton (#409), persona spending-cap
primitive (#411), δ-harness Hermes coverage (#410), and the docs/internal
pin + dashboard-v3 walkthrough (#389/#390).

After this tag, active scope rolls to v0.4 (install-mode reconciliation
+ UI polish + fully-implemented Agents/UI/Install bootstrapped) and v0.5
(MCP admin + memory wiring across UI and agents).

CHANGELOG merged from two coexisting Unreleased blocks into a single
[v0.3.2-alpha.1] section; added missing entries for #392 (dispatcher),
#387 (async-job polling contract), and the docs PRs #389/#390.

pyproject 0.3.1-alpha.1 → 0.3.2-alpha.1. uv.lock resynced (was stuck at
0.3.0a1 from prior drift).

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@thinmintdev thinmintdev deleted the feature/phase0-adr-0020 branch May 29, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant