Skip to content

Adopt security hardening from PR #17 - #19

Merged
imsatoshi merged 1 commit into
mainfrom
claude/adopt-pr17-hardening
Jul 28, 2026
Merged

imsatoshi merged 1 commit into
mainfrom
claude/adopt-pr17-hardening

Conversation

@imsatoshi

Copy link
Copy Markdown
Owner

Extracts the reviewable, self-contained security hardening from #17 (contributed by @jehonathanBao) and reconciles it with the fixes already on main from #18.

The rest of #17 — bollinger_evolver/ (212 files), frontend/ (85 files), and 66 stage_*.md process documents — is not included here. See the review notes on #17 for why.

Agent API

  • Reject API keys passed via query string; headers only. Query keys leak into access logs, browser history, and reverse-proxy diagnostics.
  • Replace wildcard CORS with an explicit origin allowlist.
  • Refuse to start with a missing, weak, or short (<16 char) master key. default-key and the placeholder keys are rejected by name.
  • Bind 127.0.0.1 by default instead of 0.0.0.0; publish the container port on 127.0.0.1 only and pass --api-host explicitly in compose.
  • Stop echoing internal exception text in 500 responses.
  • Leave /api/v1/health unauthenticated (returns only liveness + timestamp) so container healthchecks work; every other endpoint still requires auth.
  • Close the listening socket on stop().

Deployment safety — fail closed instead of pretending

  • StrategyDeployer no longer auto-approves when no approval callback is set; it fails the deployment and says why.
  • Deployment notes now state plainly that shadow trading and gradual rollout are not executed, instead of implying a pipeline that never runs. total_phases reflects reality.
  • AdaptiveOptimizer no longer auto-approves purely on improvement percentage.
  • RollbackManager defaults to enabled=False / require_confirmation=True, and refuses to run without a deploy callback rather than reporting a rollback that never restored the strategy file.
  • New rollback_require_confirmation setting so operators who explicitly opt into auto_rollback_enabled still get unattended rollback; the dataclass default stays fail-closed for anyone constructing RollbackConfig() bare.

Reconciliation

PR #17 predates #18, so applying it verbatim would have reverted four things now on main: the read-permission gate on GET endpoints, the rate limiter, the real rollback endpoint, and the deployer/rollback-manager injection into AdaptiveOptimizer. Those are kept.

tests/test_api_hardening.py is new and pins those invariants — a write-only key cannot read, read endpoints are rate limited, the rollback endpoint delegates to the deployer and reports failure honestly, and the rollback manager never claims success without a deploy callback. A future merge cannot silently drop them again.

Test plan

🤖 Generated with Claude Code

Extracts the reviewable, self-contained hardening from PR #17 and
reconciles it with the fixes already on main from PR #18. The rest of
PR #17 (bollinger_evolver/, frontend/, stage_*.md docs) is not included.

Agent API:
- Reject API keys passed via query string; headers only. Query keys leak
  into access logs, browser history, and proxy diagnostics
- Replace wildcard CORS with an explicit origin allowlist
- Refuse to start with a missing, weak, or short (<16 char) master key
- Bind 127.0.0.1 by default instead of 0.0.0.0; publish the container
  port on 127.0.0.1 only and pass --api-host explicitly in compose
- Stop echoing internal exception text in 500 responses
- Leave /api/v1/health unauthenticated (liveness + timestamp only) so
  container healthchecks work; every other endpoint still requires auth
- Close the listening socket on stop()

Deployment safety (fail closed instead of pretending):
- StrategyDeployer no longer auto-approves when no approval callback is
  set; it fails the deployment and says so
- Deployment notes now state plainly that shadow trading and gradual
  rollout are not executed, instead of implying a pipeline that does not
  run; total_phases reflects reality
- AdaptiveOptimizer no longer auto-approves purely on improvement %
- RollbackManager defaults to enabled=False / require_confirmation=True,
  and refuses to run without a deploy callback rather than reporting a
  rollback that never restored the strategy file
- New rollback_require_confirmation setting so operators who opt into
  auto_rollback_enabled still get unattended rollback

Reconciliation notes: PR #17 predates PR #18, so applying it verbatim
would have reverted the read-permission gate, the rate limiter, the real
rollback endpoint, and the deployer/rollback-manager injection. Those are
kept, and tests/test_api_hardening.py pins them so a future merge cannot
silently drop them again.

Tests: 232 passed (was 210 on main).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@imsatoshi
imsatoshi merged commit 7c380d4 into main Jul 28, 2026
2 checks passed
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