Stage 1 — Security & Guardrail Hardening#30
Merged
Conversation
The _get_optional_api_key_record dependency in interfaces/api/main.py declared `authorization` and `x_api_key` with plain `= None` defaults, so FastAPI bound them as query parameters. Real `Authorization: Bearer` and `X-Api-Key` request headers never reached the validator: every buyer request on the ~26 endpoints routed through this wrapper was treated as anonymous (PUBLIC-tier pricing), and invalid, revoked, or expired keys were silently accepted as anonymous instead of rejected with 401. Fix: mirror the Header(None) / Header(None, alias="X-Api-Key") defaults from ad_seller.auth.dependencies.get_api_key_record, which the wrapper delegates to. Adds tests/unit/test_auth_header_binding.py exercising the real app via httpx.ASGITransport (no dependency override for the auth dependency): valid X-Api-Key and Bearer credentials resolve to the key's identity tier, invalid/revoked/expired keys return 401, credential-less requests keep the anonymous PUBLIC path, and the auth params are no longer exposed as query parameters. bead: ar-70x0 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Event emission was fail-open across the board: emit_event swallowed every exception, so audit-trail events for money decisions (proposal accept/reject/counter, deal creation/registration, approval decisions, negotiation rounds) could silently drop when the event bus failed. Surgical hotfix, not a bus redesign: - AUDIT_EVENT_TYPES (events/models.py): the money-relevant event types whose loss would break the audit trail. - events/audit_fallback.py: append-only JSONL fallback writer with fsync-on-write; path from settings (audit_fallback_path, default data/audit_fallback.jsonl). - emit_event (events/helpers.py): on bus failure for an audit-class event, write the event to the fallback JSONL and continue; if the fallback write also fails, re-raise so the transaction surfaces the error (fail-closed). Non-audit events keep the existing fail-open behavior unchanged. bead: ar-z64h Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…origin/fix/audit-fail-closed' into release/stage-1-hardening
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stage 1 — Security & Guardrail Hardening
First release in a staged re-architecture of the agent. Ships only safety-critical fixes; fully backward-compatible — no API, schema, or configuration changes.
Later stages introduce a shared contract library and structural consolidation (in progress on integration branches).
🤖 Generated with Claude Code