Commit graph Bifrost/tests
Author SHA1 Message Date
028bc2fdf6 Registration: sign-up form with proof-of-work and a no-JS time-lock fallback (#56) 2026-11-11 11:17:25 +00:00
b2e0bb2514 Mouth: tail_gaps on chat_pending.v3, the rooms whose tail is incomplete (#57) 2026-11-11 11:07:35 +00:00
33be966b7d Registration gates: proof-of-work CAPTCHA and training-notice consent receipt (#54) 2026-11-11 10:15:46 +00:00
fc8242f655 Suspension survives sign-in; admin-only Suspend/Unsuspend with a receipt (#53) 2026-11-11 08:38:09 +00:00
e8722d0abf Mouth: room tail on chat_pending.v3 (#51) 2026-11-11 08:15:38 +00:00
24f3deb88e OIDC issuer: chat tier for accounts without Active membership (#52) 2026-11-11 08:13:09 +00:00
5201508bdc OIDC issuer: address budget, token-row cap, scheduled prune, marker brake (#50) 2026-11-11 08:12:48 +00:00
be44a09d52 OIDC: refuse reserved localparts at authorize; gap list in oidc-issuer.md (#49) 2026-11-11 06:39:35 +00:00
1d0548313c Mouth: addressing facts on deliveries (chat_pending.v3 basis and form) (#48) 2026-11-11 06:26:30 +00:00
4e86c33cd2 Resolve CultLib via VOIDBOT_CULTLIB_ROOT in tests; test formerly indexed stores (#47) 2026-11-11 05:01:33 +00:00
781e6eabf6 Desk: pin vectors to CultLib de8a062a (#45) 2026-11-11 02:16:28 +00:00
05dcceb203 Desk: a stale answer on an oversize fork is 422 fork_too_large (#44) 2026-11-11 01:54:04 +00:00
815304568f Desk: pin vectors to CultLib f6c9bf5f (#43) 2026-11-11 01:49:37 +00:00
8385eca00f Desk: a read of an oversize fork is 422 fork_too_large (#42) 2026-11-11 01:35:07 +00:00
7e9ba5796b Desk: the fork desk's Bifrost half (#40) 2026-11-11 01:02:36 +00:00
12a153f66f Mill votes: ranked, paged read and not-yet-voted-by-this-network filter (#41) 2026-11-10 21:06:56 +00:00
73c6f50440 persona mouth: open a direct room for a Persona; answer unknown kinds loudly (#39) 2026-11-10 18:35:51 +00:00
1a3fa02373 Merge pull request 'Reserve Matrix localparts and system names at identity creation' (#34) from heimdall/reserved-identities into main 2026-11-10 17:32:16 +00:00
Heimdall
7e258988e5 Read reports: a report that throws no longer wedges its room
The per-room tail was chained with .then(run), so a rejected run skipped every later report for that room and left the cleanup as an unhandled rejection. Chain on both outcomes and clean up on both. A test reaches it with a presence failure plus a throwing logger and fails on the old chain.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-10 17:31:59 +00:00
Heimdall
62c1d4e0f1 Merge remote-tracking branch 'origin/main' into heimdall/mouth-read-through 2026-11-10 17:31:08 +00:00
Heimdall
cf2c80e4e7 Load cultnet-ts and cultmesh-ts by their scoped names
CultLib 286a9af scoped the two packages under @gamecult. The directories under packages/ keep
their short names; only the bare specifiers change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-10 14:34:19 +00:00
Heimdall
0a44bf88e5 Mouth read-through: serialize reports per room, keep the last landed receipt, re-read the brake, presence off the send path
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-10 14:33:25 +00:00
Heimdall
5ba6571fa6 Test the whole reserved set through both paths and pin case-insensitive matching
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-10 14:30:50 +00:00
Heimdall
2c2cf15094 Matrix mouth: m.read follows a chat_read report, not the ack; presence follows the turn
An ack posted her m.read, so the receipt tracked the queue, not the model. The mouth now posts m.read only
at the event id Huginn reports in gamecult.persona.chat_read.v1, for an event it delivered to her in that
room, forward only, brake read fresh. The ack posts nothing. Presence is online within presenceGraceMs of
a read report, a send or an ack, unavailable after, offline under the brake; a change is PUT at once.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-10 14:17:35 +00:00
Heimdall
8955279ef1 Reserve Matrix localparts and system names at identity creation
The identity becomes the Matrix localpart at SSO, so a new account must not mint a name that
a Matrix account already holds (the 13 Synapse localparts) or a system name. Native register
refuses a reserved name; a derived identity takes the next free suffix. Lookups of existing
accounts and existing rows are untouched; there is no exemption path.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-10 14:06:22 +00:00
800486a9a0 Merge pull request 'Pin the vote page busy-refusal branches' (#14) from heimdall/pin-vote-refusal-branches into main 2026-11-10 14:02:29 +00:00
Heimdall
012d1cb926 Test: a second simultaneous close of a Standard motion must not throw
Fails at this commit with DbUpdateConcurrencyException from CloseMotionAsync:
Motion.Status became a concurrency token in BifrostDbContext.cs:288.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 22:13:59 +00:00
Heimdall
0d7c3ec078 Mind intake: nonce prune is best-effort and never fails a valid request; test the five-lost-races contended branch; doc the retried reveal's phase judgement
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:55:03 +00:00
Heimdall
1c9cb9937e Signed Mind intake: verify before revealing state, dummy verify, issuedAt window and nonce pruning, per-source rate limit and body cap, one account per persona, DbUpdateException is replay only for the nonce
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:54:06 +00:00
Heimdall
8e6afc43ed Signed Mind intake for sealed motions: Ed25519 envelopes, registered public keys, nonce replay refusal, persona bound into the commitment
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:54:06 +00:00
Heimdall
55b7f79c13 Sealed ballot: retry a reveal that loses a RevealSeq race while the window is open, \z in hex patterns, doc the contended 409
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:47:23 +00:00
Heimdall
264233e08f Sealed ballot: freeze the reveal set at close (RevealSeq token), HTTP tests for replay/non-voter/late reveal/close, doc corrected on the ballot schema
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:40:54 +00:00
Heimdall
96da1b7a8c Sealed ballot: race-safe close, close sweep, endpoint tests, backup reader and auth findings in the doc
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:30:35 +00:00
Heimdall
d5a71eb639 Sealed-ballot motions: commit-reveal over typed gamecult.sealed_ballot.v0 documents
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 20:24:49 +00:00
7c563130e8 Merge pull request 'Make every cookie host-only: __Host- names, Secure, Path=/' (#11) from heimdall/host-only-cookies into main
Some checks failed
Publish Container / Build and publish Bifrost image (push) Failing after 14s
2026-11-09 11:48:27 +00:00
Heimdall
58fa80bc5b Make the attempt cookie's deletion Secure so a browser honours it
A __Host- cookie is only removed by a Set-Cookie that is itself Secure. The
hardening test now checks Secure on every header, deletion included, and the
completion tests pin that success and refusal both clear the attempt cookie
with Secure, Path=/ and no Domain.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-09 11:24:02 +00:00
Heimdall
7cfce18fcf Pin the vote page's two unpinned busy-refusal branches
A signed-in retract on a full account table must say busy with no sign-in offer (the
retract door passes its voter to Throttled), and a spent cast budget must say only
"too fast", for anonymous and signed-in voters alike. Both mutants survived Soul s4.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 21:28:41 +00:00
94606d04a6 Matrix mouth: re-read the brake before every join; pin the encoded presence path
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 16:24:17 +00:00
8938dbd739 Matrix mouth: review fixes (stale brake at the join, no receipt while braked, presence on the backlog path, guarded receipt log)
- answerInvites takes a fresh brake read after the long-poll
- readUpTo reads the brake when each receipt would post; held brake drops it, one log line
- the brake read and offline presence PUT precede the full-backlog early return
- a throwing logger cannot reject the unawaited receipt call
- tests: fake keeps the raw path and honours abort signals; the braked-round carve-out is offline presence PUTs only

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 16:18:44 +00:00
111f7e6f1a Mouth tests: the no-wait probe fails fast instead of hanging
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 16:09:25 +00:00
b1b145ee39 Matrix mouth: post each Persona's m.read receipt on her ack, set her presence from her brake
An ack posts her public m.read per room at the newest covered event, fire and
forget (never awaited, failure logged once, no retry). syncOnce reads the brake
once per round, passes it to answerInvites, sends set_presence on /sync and one
presence PUT on a released-to-braked transition (first braked round included).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 16:04:50 +00:00
Heimdall
fd0a43e0e4 Image store: room directory must share the Persona directory's group; never create the Persona directory
The room directory's gid must equal the Persona directory's, else store-failed (a setgid
directory in the wrong group would still give files the wrong group). A missing Persona
directory is refused rather than created; only the room directory is made. The stat is
injectable so the group case is testable where the sandbox cannot chown.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 09:29:59 +00:00
Heimdall
129b517f46 Image store: never chmod a room directory; refuse when setgid is not inherited
A chmod by bifrost, which is not in the Persona's group, clears the setgid bit, so files
would take bifrost's group and the Persona's reader could not open them. Directories and
files are now created with exact modes (fixed umask around mkdir and open), the room
directory must have inherited setgid from the installer's Persona directory or the image
is refused (store-failed), and the Persona directory is never chmodded. Adds behavioural
redirect-refused and fetch-timeout tests.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 09:27:40 +00:00
Heimdall
a85942e858 Test: the streamed cap fails by assertion, not by timeout
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 09:21:46 +00:00
Heimdall
e23f7da2d5 Test: a failed image write leaves no temp file
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 09:19:32 +00:00
Heimdall
02275ee17b Matrix mouth: fetch and store chat images (cut A), ChatDelivery v3
m.image events in delivered messages are fetched as the receiving Persona,
classified by magic bytes, bounded by size and header pixel count, and stored
under IMAGE_STORE_ROOT/<persona>/<room hash>/<bytes hash>[.ext] (0640, dirs
2750). The delivery tuple gains index 11, nil or [path, mime, size, sha256];
the pending kind becomes gamecult.persona.chat_pending.v2 with Huginn's v3
golden bytes. Refusals keep the typed text line plus a fixed-word reason.
The mouth test homeserver is answered in-process so the suite runs under a
capped address space.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-08 09:18:55 +00:00
Heimdall
c757acf525 Make every cookie host-only: __Host- names, Secure, Path=/, no Domain
Session, OAuth correlation, antiforgery, voter and Heimdall attempt cookies all take the
__Host- prefix. The prefix forbids a narrower Path, so the voter (was /mill) and attempt
(was /auth/heimdall) cookies move to Path=/.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-07 18:42:43 +00:00
Heimdall
6548ca8385 mouth: deliver media events as a typed line
m.image/m.file/m.audio/m.video reached Personas as a bare filename and
dropped content.url. The delivery text now leads with
[kind filename mime size url], then the caption. Applies to the delivery
and to context lines. Wire v1 is unchanged. Nothing is fetched: a Persona
turn is a tool-less text call.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 18:09:43 +00:00
7adc7315a3 send gate: re-check the brake after the gate wait, before the PUT
A send queued at the room gate passed the brake check at entry only, so a
brake placed while it waited still let the PUT through. The check now also
runs inside the gate, just before the PUT, and answers a typed Brake refusal.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-03 10:37:22 +00:00
Meta Vens
2387cbc7f6 send gate tests: pin the head read's shape
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 11:06:39 +01:00