Ruling budget-table-evict-oldest. FixedWindowBudget keeps two linked lists (window start, last use among keys
with permits left) so eviction and expiry are O(1); a spent key is never evicted, and a table full of spent keys
refuses a new key as TableFull with the true wait. Accounts get their own cast table. The vote page checks the
subject before spending any key, and the refusal names its reason: cast budget, mint budget, or a busy table.
Not verified by a build yet at this commit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Kills the Stryker survivor on the null-client key: a request with no address shares one
bucket and does not throw. Builds with a8c3ecf; test added after the main verify job.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
FixedWindowBudget times windows on the clock's monotonic timestamps so a wall-clock
step cannot stretch or reset one, expires windows from a start-ordered queue instead
of a periodic sweep, and holds at most MaxTrackedKeys keys: a new key at the cap is
denied with the true wait and a held key is never evicted. MintPermits is 30 per hour
per the operator ruling, and a 429 now carries a plain-text reason; a refused new
device is told it can sign in. Not yet built or tested at this commit.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Survivors of the first Stryker pass on FixedWindowBudget: the sweep dropping
live windows, sweeping every call, and the exact window boundary (masked by
the sweep in the first test).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
HttpClient drops an empty header value, so the first version of the test
never sent the header; the request is now built on the TestServer.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One FixedWindowBudget (injectable clock) owned by ConceptVoteRateLimits;
the vote page 429s with Retry-After before any row or cookie. Prefix
lengths and budgets are validated in every environment. Pins the empty
Origin branch of CastRequestGuard.
Unverified; not yet built.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drops antiforgery from the anonymous vote flow: no antiforgery cookie, no hidden token.
CastRequestGuard is the one decider; VoteModel.OnPageHandlerSelected is the one gate and
answers 4xx when no handler is selected (was a NullReferenceException 500).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Empty, NUL and unreadable paths, malformed UTF-8 and lone surrogates refuse
with the command's exit 1. The manifest is bounded (1 MiB, 1000 ships) and
duplicate JSON properties are refused. Titles refuse format, line and
paragraph separator characters and edge whitespace. Naming an already
retired key is a recorded no-op, so a rerun converges.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
UseConceptTallyCors replaces UseCors and appends Vary: Origin to every
response under the export route, preflights and 404s included, keeping any
Vary already set. A single-origin ASP.NET policy never adds it itself.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Stryker flagged ParseManifest, ReadString and RunAsync as compile errors in safe
mode (out vars and try-assigned locals), leaving them unmutated. Behaviour unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
One owner for the route and the policy, so Stryker can mutate them: it
flags every mutant of Program.cs as a compile error (safe mode), which
left the export untested by mutation. Program.cs keeps UseCors and the
two registration calls.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
GET /public/concepts/{collection}/tallies returns per-live-subject up, down and
member counts only, anonymous, Cache-Control public max-age=60. CORS policy
ConceptTallies is built from ConceptVotes:AllowedOrigins, GET only, no
credentials, required on this route alone. Production startup refuses an
allowed origin that is not an exact https origin.
Not yet built or tested when committed.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ConceptSubjectRegistry is the only writer of ConceptSubject. ConceptKey is the
one key grammar (anchored with \z), shared with ConceptAppraisalService.
Not yet built or tested at this commit.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The snapshot is regenerated; EF also reordered two pre-existing properties
(BridgeAction.TargetSurface, one ProjectId) into its canonical order.
Migration discovery now lists thirteen ids.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
ConceptAppraisalService is the only appraisal writer; tallies are derived from
rows. VoterIdentity.For decides voter key and class; NetworkPrefix is the only
prefix computation (HMAC tag). NetworkTagSecret is required in production.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
concept-mill-votes:cut_report:cut-1.h1 and h2, held by Soul
(concept-mill-votes:verdict:cut-1.s2). Production refuses to start without
DataProtection:KeysPath; the deploy (Cut 0b) must set it.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>