Commit graph

241 commits

Author SHA1 Message Date
Meta Vens
3bff0d779c persona matrix mouth: log the many-peer server's errors and keep serving
Some checks failed
Publish Container / Build and publish Bifrost image (push) Has been cancelled
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 01:51:57 +01:00
Meta Vens
b892c64f00 persona matrix mouth: one session per client on the many-peer RUDP server; every request answered on the connection it arrived on
Two Persona turns running at once no longer take each other's session. Requests run in order per client, not across clients.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-31 01:51:57 +01:00
Meta Vens
a7621f9eed Research: Discord-like roles on Matrix and the chat client (matrix-roles-from-bifrost-estates)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:09:06 +01:00
Meta Vens
ccb0e6b08c Research: email mouth prior art (payment-mints-invite-bifrost-ledger-email-mouth)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:09:06 +01:00
Meta Vens
6cf24644bc Research: customer-member onboarding prior art and body facts (customers-get-voting-power-onboarding-owed)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 19:09:05 +01:00
Meta Vens
cc76f0f2d0 mouth-all-personas: one Matrix mouth serves every Persona; deliveries carry mentions and is_direct, refusals are typed; same-server DM invites accepted; the ring is deleted (Persona turns are the heartbeat's) (squash of eureka-body/mouth-all-personas 7b63031..5b628e2; Soul s1-s3)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-30 02:49:59 +01:00
Meta Vens
18bbe6c312 Research: estate tally adds bloc-parliament-at-threshold and operator influence cap (Fork Desk 41)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:15:38 +01:00
Meta Vens
1036849534 Research: estate tally note points at its sims/ folder
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:07:49 +01:00
Meta Vens
3f241c0fe4 Research: estate tally game theory, power indices and simulations (Fork Desk 39, estate-internal-tally)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 22:07:10 +01:00
Meta Vens
eee86193c0 Research: swarm governance on Bifrost, readiness and prior art (follow-up swarm-governance-on-bifrost)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 21:48:14 +01:00
Meta Vens
7b630312e1 persona-mouth: Matrix ear and mouth for Personas (brake-refusing sends, token only in the Authorization header, cursor after ack, one ring per idle window); delete the Discord posting actuator (squash of eureka-body/persona-mouth 1894f65..ab2bdc6; Soul s1)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-29 19:41:30 +01:00
Meta Vens
1894f653d0 Back-channel logout: members who leave Active are logged out of chat (gamecult-chat cut bifrost-oidc-backchannel-logout r2)
Merges gamecult-chat/bifrost-oidc-backchannel-logout (83daabe..37c8fe1).
gamecult-chat:cut_report:cut-bifrost-oidc-backchannel-logout.h1/h2; Soul s1 and s2 hold. Not deployed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 02:10:34 +01:00
Meta Vens
37c8fe1a72 Logout tests: pin the loop's own tick-failure catch now that subject faults are isolated
A pass that cannot read its subjects (a scope factory failing like a database outage) is logged
by exception type only and retried after the interval, never in a tight loop. The earlier loop
test reached this catch through a per-subject exception, which the isolation now absorbs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 01:57:31 +01:00
Meta Vens
8340ee0e92 Logout reconciler: one subject's unexpected exception does not stop the pass
Caught per subject, logged at error with the subject id and exception type only, authorizations
left valid; cancellation still stops the pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 01:50:54 +01:00
Meta Vens
ec66fba5ca Logout client: no auto-redirect, pin the redirect rule and the 10 s timeout
The named logout HttpClient's primary handler disables auto-redirect, so a 3xx from MAS is a
non-delivery retried like any non-2xx instead of being followed to a final 2xx that revokes.
Pinned through the real DI registration against a real loopback listener answering 302, and
the registered client's Timeout is pinned to exactly 10 s. The unexpected-exception test is
replaced by the isolation test (its fix is the next commit) and the cancellation test stands alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 01:50:53 +01:00
Meta Vens
51fe807b66 Logout loop test: the tick failure is logged by exception type only
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 01:03:02 +01:00
Meta Vens
868b91fefb Logout reconciler: a recovered subject's backoff clears at once, not when it expires
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:57:31 +01:00
Meta Vens
af64868326 Logout tests: loop, log content, 2xx range, backoff reset, exception and cancellation paths
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:56:18 +01:00
Meta Vens
c9e470bef4 docs/oidc-issuer: BackchannelLogoutUri, reconcile semantics, MAS facts and the tick-window tradeoff
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:39:57 +01:00
Meta Vens
69b670e3af Fix logout test support compile errors
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:38:56 +01:00
Meta Vens
404dafdd40 OIDC back-channel logout: a reconciler ends the sessions of subjects who are not Active
OidcLogoutReconciler derives pending logouts from valid OpenIddict authorizations x
membership, POSTs one signed logout token per non-Active subject to MAS, and revokes
the authorizations only after a 2xx. Registered only when
Bifrost:Oidc:Clients:Mas:BackchannelLogoutUri is set. The active-member reading is
the endpoints' existing one, now shared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-28 00:38:15 +01:00
Meta Vens
83daabe512 Bifrost as OIDC issuer for the Matrix chat (gamecult-chat cut bifrost-oidc-issuer, squash of 1ef289a..ec4acfa and abd12b3..)
One configured client (stale clients removed with their tokens and authorizations), Active membership re-checked at token and userinfo through IsStillActiveMemberAsync, PKCE required by the server option, OpenIddict.Server.AspNetCore + EntityFrameworkCore 7.7.1 with no vulnerable transitives. Soul s2, s3 and s4 hold; Low conformance gaps in gamecult-chat:follow_up:oidc-issuer-spec-conformance.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 04:57:16 +01:00
Meta Vens
78d38d92e6 Merge security/bifrost-dependency-pins: Npgsql 8.0.3, System.Text.Json 8.0.5, Caching.Memory 8.0.1 pinned; NuGet lockfiles; locked-mode restore (audit 2026-10-22; Soul cleared)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-22 23:45:01 +02:00
Meta Vens
d7d4b21c4b Commit NuGet lockfiles for the web and test projects
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:29:46 +02:00
Meta Vens
a15648db04 Pin Npgsql 8.0.3, System.Text.Json 8.0.5, Caching.Memory 8.0.1; enable NuGet lockfiles
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 23:26:49 +02:00
Meta Vens
b2110f53fa Merge hands/heimdall-callback-signed
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-22 18:11:28 +02:00
Meta Vens
b7e3bdf28d Heimdall sign-in: the attempt reader takes no optional nonce; ownership is one ordinal comparison
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 23:02:48 +02:00
Meta Vens
d743e4f363 Heimdall tests: an unreadable form with a genuine attempt cookie present is still no attempt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 23:00:06 +02:00
Meta Vens
efb278a910 Heimdall tests: the no-attempt-field refusal carries a genuine code, so only the missing nonce can refuse it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 22:57:26 +02:00
Meta Vens
d463336206 Heimdall tests: a genuine attempt cookie under a name that is no slot is no attempt
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 22:41:31 +02:00
Meta Vens
b54e8d5dc8 Heimdall tests: fix a string literal in the parallel-starts test
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 22:32:07 +02:00
Meta Vens
053272a0f3 Heimdall tests: re-point the cookie-ring tests to the slot cookie; a refusal with no matching attempt deletes nothing
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 22:31:25 +02:00
Meta Vens
15f96c408c Heimdall sign-in: attempt cookies live in a ring of two fixed slots, so the Cookie header is bounded by construction; pin the completion form's id
Start takes a free slot or overwrites the one expiring first; parallel starts carry the same request
cookies, choose the same slot and overwrite each other. Complete finds its attempt by scanning the
slots for the posted nonce; an overwritten attempt finds none and is refused like any other. The
per-request counting sweep, its byte budget and the nonce-named cookie are deleted.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 22:25:24 +02:00
Meta Vens
8186d6f8fa Heimdall tests: drop the exact-byte boundary test; the 5120-byte bound has a 3 KB margin, and no two attempt cookies can reach it
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 21:33:17 +02:00
Meta Vens
21f2c75c78 Heimdall tests: name the sums near the bound when the boundary pair is missing
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 21:32:31 +02:00
Meta Vens
ec2f812b59 Heimdall attempt cookie bound: pin the exact byte boundary and that unrelated cookies are never swept
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 21:26:31 +02:00
Meta Vens
4a28cea1f9 Heimdall sign-in: Start sweeps dead and oldest attempt cookies to keep the Cookie header bounded; pin the complete page's real form
Start deletes request attempt cookies that are no live attempt, then the live ones expiring first until the new attempt and the survivors fit 5120 bytes, so the newest attempt always completes and the header stays under nginx's 8 KB. Behavioural tests drive a cookie jar past the bound and read the served page's form fields and action through the test host.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 20:41:41 +02:00
Meta Vens
79c29fe16e Merge hands/mill-votes-cut-5b: vote budgets per prefix and account, mint budget 30 per address per hour, monotonic windows, oldest-unexhausted eviction at the cap
Soul passes concept-mill-votes:verdict:cut-5b.s1 to .s4. Operator rulings
mint-budget-30-per-hour and budget-table-evict-oldest. Undeployed; Cut 6
deploys with the sign-in fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 20:35:34 +02:00
Meta Vens
cf74019194 Mill votes: the very-busy refusal offers sign-in to a voter who is not signed in
Accounts have their own table, so signing in works while the cast or mint
table is full. A signed-in voter is not told to sign in. Pinned through the
full pipeline at a small cap, for both audiences.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 20:23:59 +02:00
Meta Vens
a9b9b29bf9 Pin the account table's own cap
The cap-not-wired-accounts hand mutant survived: no test filled the account table.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 19:58:09 +02:00
Meta Vens
912d083894 Fix a string literal broken across lines in the table-full test
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-11 19:17:27 +02:00
Meta Vens
436a02864f Vote budgets: at the cap a new key evicts the least recently used key with permits left
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>
2026-10-11 19:16:30 +02:00
Meta Vens
8f57dc89f0 Pin the no-client-address bucket of the vote budgets
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>
2026-10-11 17:38:56 +02:00
Meta Vens
a8c3ecf495 Vote budgets: monotonic windows, a key cap, 30 mints an hour and a readable 429
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>
2026-10-11 17:32:01 +02:00
Meta Vens
2c8384e44a Pin that a signed-in retract spends the account budget
Hand mutant retract-key-ignores-signed-in-voter survived the first table.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:46:45 +02:00
Meta Vens
9fcef927fd Pin the budget sweep and Retry-After rounding; drop a redundant Math.Max
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>
2026-10-11 09:35:50 +02:00
Meta Vens
34f5dfa6f1 Heimdall attempt cookie: a deletion carries only the Path
HttpOnly, Secure and SameSite on a deletion decide nothing (a cookie is matched on name and path); Stryker found those two booleans surviving. The deletion is pinned by path, expiry and the absence of Max-Age.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:08:10 +02:00
Meta Vens
7f375ecf8f Pin the empty Origin branch with a server-built request
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>
2026-10-11 09:02:01 +02:00
Meta Vens
0f71a9f3ca Heimdall tests: fix two log-join string literals broken by a newline
d695674 does not build (two string literals split across lines); this commit repairs it. cf4e5b4 inherits the break.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 09:01:06 +02:00
Meta Vens
fbf6e43955 Concept vote rate limits: cast and mint budgets per account or network prefix
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>
2026-10-11 09:00:23 +02:00