Skip to content

feat: authenticate control-plane actors - #16

Draft
fly1d wants to merge 2 commits into
mainfrom
codex/auth-policy
Draft

fly1d wants to merge 2 commits into
mainfrom
codex/auth-policy

Conversation

@fly1d

@fly1d fly1d commented Aug 11, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • add a framework-neutral bearer authenticator that maps SHA-256 token fingerprints to subjects and scoped permissions
  • require authentication and least-privilege authorization for every /v1 operation when protected mode is enabled
  • reject audit-producing writes when the request actor differs from the authenticated subject
  • fail service startup unless authentication is configured or insecure in-memory development mode is explicitly selected
  • exercise the complete authentication boundary in unit, API, container, and PostgreSQL Compose scenarios

Closes #15.

Risk classification

High. This changes authentication, authorization, service startup, and audit identity semantics. The current solo-maintainer policy in docs/QUALITY_GATES.md requires independent external security review before production release. The existing owner decision is hold; this PR remains a draft with external-review-required and production-blocked. The experimental merge exception has not been established.

Review focus

  • missing, invalid, and wrong-scheme credentials return the same 401 contract with WWW-Authenticate: Bearer
  • each route maps to the minimum intended permission
  • actor-bearing writes reject impersonation before reaching the store
  • durable startup cannot silently fall back to unauthenticated mode
  • raw tokens never enter the repository, server configuration, image, or access logs
  • the adapter boundary can support OIDC later without rewriting route policy

Evidence

Current revision:

  • synchronized with main at 401e9bb18844259f63432a14b6363442ba5b8fb0, preserving the SDK, pilot examples, and current governance policy
  • make check: 52 passed, 1 PostgreSQL integration test skipped without a database; 98.11% coverage
  • strict Ruff and Mypy checks pass
  • the refund demo passes both approve and reject flows with distinct operator, agent, and reviewer tokens scoped to their required permissions
  • CI run 35639897860 passed on commit 91ac23c09d43ad8fa8dd3e779f4bb6084e79fa8d: fast-gate, postgres-integration, and container-build, including the packaged authentication smoke test
  • PostgreSQL was skipped only in local verification; the updated revision passed the database migration/integration gate in CI

Earlier-revision evidence (not a substitute for rerunning the updated revision):

  • packaged image refused startup without auth or the explicit development switch
  • packaged protected mode covered missing, invalid, under-scoped, mismatched-actor, and valid credentials
  • Compose exercised migrations, authenticated API access, and persistence across restart

Compatibility and rollback

  • make run remains the explicit unauthenticated in-memory development path
  • packaged service startup now requires ACP_AUTH_CONFIG or ACP_ALLOW_INSECURE_DEV=true
  • when authentication is enabled, request actor must equal the configured principal subject
  • no database migration or public response schema changes are included
  • rollback is the previous application image/config; existing PostgreSQL data is unchanged

Remaining risks

  • static bearer tokens are long-lived and configuration reload requires a restart
  • no centralized revocation, OIDC/JWKS validation, rate limiting, or automated rotation yet
  • permissions are global and do not yet enforce tenant or resource ownership boundaries
  • TLS termination and caller-side secret storage remain deployment responsibilities

@fly1d fly1d left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Final technical review completed after all required CI checks passed.

Findings resolved before submission:

  • unauthenticated startup was initially implicit; runtime startup now fails unless authentication is configured or the in-memory development switch is explicitly set
  • the packaged-service gate initially exercised only valid credentials; it now covers fail-closed startup, missing and invalid tokens, under-scoped access, actor mismatch, and the valid governance flow
  • wrong authentication schemes now share the same non-disclosing 401 response as missing and invalid bearer tokens
  • every /v1 OpenAPI operation is covered by a regression assertion requiring the bearer security scheme

No unresolved blocking code findings remain. Residual risks are documented in the PR: long-lived static tokens, restart-based configuration reload, no central revocation/OIDC/rate limiting, and no tenant/resource authorization.

Merge is intentionally pending the two independent approvals required for high-risk authentication changes by docs/QUALITY_GATES.md.

@fly1d fly1d mentioned this pull request Aug 12, 2026
6 tasks
@fly1d fly1d added external-review-required Independent domain review is required before production release production-blocked Must not be deployed or designated for production labels Aug 14, 2026
@fly1d
fly1d marked this pull request as draft August 14, 2026 10:23
@fly1d

fly1d commented Aug 14, 2026

Copy link
Copy Markdown
Owner Author

Solo-maintainer owner decision

  • Risk: high; authentication, authorization scopes, actor binding, and deployment fail-closed behavior define a security boundary.
  • External review: still required before production release. Prior self-review and CI are supporting evidence, not an independent security approval.
  • Experimental merge exception: not currently satisfied. The branch documents durable/external deployment configuration and is not labeled in user documentation as experimental and prohibited for production.
  • Base status: the branch predates governance docs: adopt solo-maintainer governance #23, pilot docs: define governed refund paid pilot #21, and SDK feat: add typed Python SDK #18 and must be rebased with all checks rerun before any later merge decision.
  • Owner decision: hold. PR converted to draft and labeled external-review-required and production-blocked.
  • Removal criteria: independent security review resolves findings, branch is rebased onto current main, authenticated container/PostgreSQL smokes pass, and a new owner decision is recorded.

This status follows the solo-maintainer policy in docs/QUALITY_GATES.md; merging code and approving production use remain separate decisions.

Resolve documentation conflicts while preserving the SDK, pilot materials,
and current quality gates. Exercise approve/reject demo flows with distinct,
least-privilege authenticated principals.

Validation: make check (52 passed, 1 PostgreSQL test skipped; 98.11% coverage).
Draft hold and independent security review requirements remain in effect.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

external-review-required Independent domain review is required before production release production-blocked Must not be deployed or designated for production

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Authenticate API principals and enforce scoped permissions

1 participant