Repository navigation
Fix/lru eviction and effective fingerprint - #3
Merged
Merged
Conversation
Containerising surfaced that the HTTP API never applied the configured rate limit. The `rate_limit` section was validated on load and build_rate_limiter had 13 integration tests behind it, but nothing in the API path ever constructed a limiter -- the configured limit was documentation. AetheryaAPI now builds one per process and passes it to the pipeline. Verified through the container: 65 requests from one actor against a limit of 60 gave 60 allowed and 5 refused, window visible in Redis. mypy then caught that run_pipeline typed rate_limiter as ActorRateLimiter, so the Redis backend could not have been passed to it at all. Widened to the RateLimiter protocol. Dockerfile is two-stage and non-root, with the semantic model baked in at build time: with require_warm_semantic_model, downloading it on first boot would either delay readiness or leave the advisory layer silently inactive. The healthcheck asserts ok && !degraded && policy_fingerprint_match, so a replica serving under an unintended policy is not marked healthy. docker-compose runs the decision service plus Redis with the audit chain on a named volume. Verified intact across a restart (9 events, 0 invalid). config/policy.docker.yaml carries the distributed backend. The repo default stays memory because redis fails closed and would refuse every request without a reachable server -- correct behaviour, wrong default. A test pins the two files to differ in exactly that field so they cannot drift. Also validated the Redis integration suite against Redis 7.4.8 (previously only 6.2.14): 13/13. Verification: 1076 tests, 100% coverage, mypy strict and ruff clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ty gate The last two pushes failed CI on the same test. examples/agent_loop.py checked for the openai SDK before checking for the API key, so the error raised depended on whether openai happened to be installed -- present in a dev environment, absent from CI's [dev] extra. test_openai_backend_requires_a_key therefore passed locally and failed in CI. The key is checked first now, which is also the better ergonomics: a missing key is the common case and you should not need the SDK installed to be told about it. Both paths are covered, one by blocking the import. Diagnosing that surfaced a second, local-only problem: security_gate phase 2 generates its own corpus, but AuditLogger appends by design, so a file left by a previous run was appended to and counted. The phase then failed on events it did not create and reported invalid == total, which reads like a real integrity regression rather than stale state. CI never hits it; a second local run always does. Phase 2 now starts clean, with a test asserting idempotence. Verified by running the suite with openai, redis and redislite blocked at import to reproduce CI's dependency set: 1078 tests, 100% coverage. Also re-ran every CI job locally -- lint, ruff format, mypy, the four named suites, security baseline, security gate, chaos, pipeline SLO and the slow semantic tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The phases were documented but not deployable: enforcement lived in each integration, and "review every hard_deny before advancing" was a grep nobody would run. Three pieces close that. enforcement.py makes the posture configuration. The engine always computes a full decision; enforcement.phase decides how much is enforced, so advancing is a config change and all three phases exist from day one. apply_enforcement never mutates the decision -- the audit records what the engine ruled, not what a partially-enforcing deployment did about it, and conflating those makes phase-1 data worthless. client.py is the sidecar surface: agent in one process, engine in another, one HTTP call between them. Fails closed from phase 2 on, because a boundary that disappears when the network hiccups is not a boundary. Phase 1 is the explicit exception: it enforces nothing, so an outage must not stop the agent. rollout_report.py answers the exit criteria from the audit trail and exits non-zero until ready, so it works as a promotion gate. The hard_deny_reviewed criterion never auto-passes: the tool can count and list those events, it cannot judge them, and auto-passing would turn the gate into the formality it exists to prevent. Writing its tests found that the report crashed on a malformed audit line or an empty file, because verify_audit_file raises rather than returning. Both are findings an operator must see before advancing -- now reported as a failed chain_intact criterion with the detail. Dockerfile.slim: 8.7GB -> 330MB. The size was never AETHERYA, it was PyTorch, pulled in for the advisory semantic layer. That layer is capped below every deny threshold so it can escalate to a human but never refuse alone, and the deterministic core does not use it. Verified against the running container: the slim image hard-denies exactly what the full one does, including the quote-split evasion r''m -rf /, and reports healthy in 8s instead of ~25s. client.py is also written to satisfy black and ruff-format simultaneously; CI runs both and they disagreed on three lines sitting at the length boundary. Verified end to end against the live stack: phases 1, 2 and 3 over HTTP with the same agent and only the flag changing, and fail-closed on an unreachable service. 1140 tests, 100% coverage under CI's dependency set, mypy strict and ruff clean, security_baseline 0 differences, pipeline p95 0.15ms. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
No description provided.