Conversation
Bug: /v1/action resumed a waiting graph node and re-ran the runtime
(spending money) with no auth, while the equivalent /v1/agent/completions
and /v1/agent/runs/{id}/resume routes were gated. An anonymous caller
could approve/reject a pending approval and resume a run.
Proof: tests/test_control_plane_auth.py::test_the_action_route_is_a_write_path_and_fails_closed
Fix: add Depends(require_control) to the /v1/action route.
Bug: POST /facts, POST /documents, POST /memory/search were unauthenticated write paths that inject evidence the agent later treats as authorised. The README explicitly promises 'auth.py gates every write path and fails closed'. An anonymous caller could write facts and documents, expanding subscription authority without a token. Proof: tests/test_control_plane_auth.py parametrized cases for facts and documents Fix: add Depends(require_control) to /facts, /documents, /memory/search routes.
Bug: GET /v1/agent/subscriptions returned every subscription's allowed
side effects, budgets and instructions with no auth, while the write
path PUT /subscriptions/{id} required the control token. The
subscription is the authority object of the session; its read path
leaked it to anonymous callers.
Proof: tests/test_control_plane_auth.py::test_the_subscription_read_path_is_gated_like_its_write_path
Fix: add dependencies=[Depends(require_control)] to the GET route,
matching the write path.
Bug: admit_run checked max_runs_per_day / daily_budget against the window ledger, but the run was only recorded after runtime.run() finished. Concurrent process() calls could all observe count/spend = 0 and all start runs, so the daily ceilings did not hold under overlap. Proof: tests/test_autonomy_governor.py::test_the_daily_run_ceiling_holds_under_concurrent_events Fix: atomically reserve a run slot (and daily-budget remainder when set) under the event-store lock at admit time; settle actual spend after the run without double-counting. Failed runs refund the reservation but keep the consumed slot.
Owner
Owner
Session 16 — regraded ✅Score: +100. The verdict below stands: this is a duplicate of an earlier filing (or, for glc_v5 #23, an enhancement rather than a defect), and it is recorded as such. What has changed is the credit. On review, the work here was genuinely done: the bug was found independently, the reproduction is real and the fix is sound. Losing a race you had no way of seeing is not a reason to earn nothing, so this is credited at the full 100 even though it does not carry the first-to-file claim. Original assessment, unchanged: Duplicate on both halves. The daily-budget concurrency work is #3 (2026-08-09) and the control-plane auth gaps are #16 (2026-08-13 16:44), both earlier. Solid work, but points go to the earliest filer of each bug. |
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.
Summary
Four control-plane and budget bugs, each fixed in its own commit and covered by a
failing test that now passes:
paths could leak or inject authority. The control plane now fails closed on
every gate.
so overlapping events could all pass the check and all start runs. Ceilings now
hold under concurrency.
Commits (merge-request scope)
7f1d692 fix: gate POST /v1/action behind the control token
with no auth. Same resume as the protected /v1/agent/completions and
/v1/agent/runs/{id}/resume routes. Now gated with require_control.
8e0f9fe fix: gate /facts, /documents, /memory/search behind the control token
authorised, with no token. Now gated with require_control.
a2a0a49 fix: gate GET /subscriptions behind the control token
effects, budgets and instructions with no auth while the write path was gated.
Now gated, matching the write path.
2193fa8 fix: hold daily run ceiling and budget under concurrent events
but the run was only recorded after runtime.run() finished. Concurrent
process() calls could all observe count/spend = 0 and all start runs.
the event-store lock at admit time; settle actual spend after the run without
double-counting. Failed runs refund the reservation but keep the consumed slot.
What breaks (before)
re-run the graph.
(side effects, budgets, instructions) via GET /subscriptions.
memory searches.
(asyncio.gather on engine.process) starts multiple runs and records zero (or too
few) max_runs_per_day refusals — the ceiling is bypassed.
Fix
locked section) and EventStore.window_settle_run (reservation -> metered spend).
reservation but keep the slot.
Test plan
unset, 401 on wrong token) for every gated path; new read-path test red before, green after
fix on that case, green after
No secrets, real messages, or API keys in this diff.