Commit graph Bifrost/tests
Author SHA1 Message Date
Meta Vens
526102ec8a ConceptVotePageTests: pin a repeated Origin header and the exact client-error codes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:26:21 +02:00
Meta Vens
75d2cedaa2 ConceptVotePageTests: drop the empty-Origin case (HttpClient never sends an empty header)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:18:06 +02:00
Meta Vens
30ba2af3c1 ConceptVotePageTests: close the Visitor class correctly
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:13:42 +02:00
Meta Vens
6554a1b017 ConceptVotePageTests: fix a stray brace
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-11 00:11:50 +02:00
Meta Vens
e0b3b1a38a Vote page: cookieless CSRF (Origin / Sec-Fetch-Site) and a defined error for handler-less requests
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>
2026-10-11 00:09:25 +02:00
Meta Vens
0c6f9216b6 Merge origin/main into hands/mill-votes-cut-5 2026-10-11 00:06:51 +02:00
Meta Vens
72741198fa Merge hands/mill-votes-cut-3: concept subject registration from the Mill manifest
Held by concept-mill-votes:verdict:cut-3.s2.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:42:02 +02:00
Meta Vens
c9e0b7b0e1 Registry tests: pin the order of already-retired entries
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:26:43 +02:00
Meta Vens
747183078a Registry tests: build the over-bound manifest as an array
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:08:11 +02:00
Meta Vens
9c4124dd9f Registry tests: spell the separator and format characters as escapes
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 23:04:00 +02:00
Meta Vens
0bb3b2f76c Registry: typed refusals for every input failure; strict manifest reader; retire rerun converges
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>
2026-10-10 23:01:40 +02:00
Meta Vens
f7ff76daa4 ConceptVotePageTests: find the visitor's own row by account-less key, drop the empty-tag assertion
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:54:03 +02:00
Meta Vens
e05e1bed81 ConceptVotePageTests: attach the log capture through ConfigureServices
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:51:24 +02:00
Meta Vens
f5a1f387ca Mill vote page: anonymous cast, change and retract, cookie minted only by a cast
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:48:04 +02:00
Meta Vens
11df901cb6 Registry tests: pin the refusal message shape
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:35:46 +02:00
Meta Vens
dcc3425520 Tally export Vary: plain append, no dedupe
The dedupe branch only added equivalent mutants; a repeated Origin token is
harmless.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 22:19:52 +02:00
Meta Vens
464da6bd50 Tally export: every response under the route varies by Origin
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>
2026-10-10 21:46:51 +02:00
Meta Vens
a43f90b48d Registry: one throw for a missing or non-array ships; tests pin refusal codes, title bound and plan order
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 21:39:04 +02:00
Meta Vens
34325e0efd Registry tests: the helper voter's device id no longer embeds the subject key
Commit b17436c does not pass: the forged-key test failed on an invalid device id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 20:00:04 +02:00
Meta Vens
d13b808471 Public concept tally export with one-origin CORS
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>
2026-10-10 19:59:51 +02:00
Meta Vens
b17436ce4f Concept subject registry and concepts plan|apply host command
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>
2026-10-10 19:58:04 +02:00
Meta Vens
bd06ef0c74 ConceptAppraisalServiceTests: a recast through a fresh context persists the changed stance 2026-10-10 09:56:52 +02:00
Meta Vens
eca71f589c Startup validation: tag secret minimum length and prefix lengths inside the address family, naming keys not values
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:56:34 +02:00
Meta Vens
162d7b1f0d Purge audit: Detail carries window and count, never the network tag the member dashboard would render
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:56:08 +02:00
Meta Vens
abb0986508 VoterIdentity: anchor the device id grammar at \z so a trailing newline or control char is no second identity
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 09:55:26 +02:00
Meta Vens
d171713ab1 Concept vote tests: close the mutation survivors in view, purge window, slug and prefix masking
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 08:42:55 +02:00
Meta Vens
214f555781 ConceptAppraisalServiceTests: build actors fully before saving; order after ToList
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 07:59:42 +02:00
Meta Vens
270ab95cc7 Migration AddConceptVotes, generated by dotnet-ef 8.0.0
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>
2026-10-10 06:39:59 +02:00
Meta Vens
3c135b8e67 Concept votes: subjects, appraisals, voter identity, network tag and their one writer
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>
2026-10-10 06:31:43 +02:00
Meta Vens
bdff1a06a1 HostTrustTests: key ring comes only from KeysPath, canary can fail, Dockerfile switch guarded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:58:34 +02:00
Meta Vens
c259b91e69 HostTrustTests: pin the forward limit and the exact-loopback trust set
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:39:16 +02:00
Meta Vens
da3e73ad4d HostTrustTests: give the probe context an http scheme to start from
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:31:21 +02:00
Meta Vens
5093ba81aa HostTrustTests: import ForwardedHeadersOptions namespace
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:27:40 +02:00
Meta Vens
2e0de9601c Trust loopback forwarded headers and pin the Data Protection key ring
UseForwardedHeaders runs first with KnownProxies exactly loopback and
ForwardLimit 1; Data Protection always uses application name "Bifrost";
the startup validator refuses production without DataProtection:KeysPath.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:26:38 +02:00
Meta Vens
d4e6137537 Test migration discovery: every Migration subclass is listed, in order
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 05:17:49 +02:00
Meta Vens
9b28e9b27a Watchdog notice reader test: status reads the same fake clock as the runs
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 02:25:13 +02:00
Meta Vens
fcf81ea564 Watchdog notice reader test: no environment variable moves the clock
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 02:19:14 +02:00
Meta Vens
0312e8bbac Watchdog notice reader: a future stamp is eligible now; no production clock seam
A failed entry stamped ahead of the clock (host clock stepped forward then
corrected) is eligible now instead of waiting out the skew; the next attempt
rewrites the stamp. The WATCHDOG_NOTICE_NOW_MS env var is deleted: the reader
reads Date.now(), and tests fix it with a --import preload (tests/fake-clock.mjs).
The unknown-entry tests now rerun far past the backoff so a retried unknown fails.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 02:19:01 +02:00
Meta Vens
c468f05eaf Watchdog notice reader test: the closure posted beside a late opening has one attempt
The finally-sends test expected six attempts on all three journal rows, but the
closure entry is first tried in the run that completes its opening, so it has
one. Test-only fix; the previous commit's test failed on this line.

The previous commit (69e12e3867) builds; its
suite has one failing test, fixed here.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 01:53:18 +02:00
Meta Vens
69e12e3867 Watchdog notice reader: a failed send is retried forever with capped backoff
Ruling notice-retry-policy. The five-attempt cap and its terminal
"exhausted" state are gone. A failed entry is eligible again once
min(2^(attempts-1), 60) minutes have passed since its last journal
update; a run inside the delay skips it without spawning the bridge.
Every attempt keeps the same nonce. The exit status is non-zero while
any entry is unknown or has failed 3 or more times, and retries go on.
status shows nextEligibleAt for failed entries.

The clock is one now() that WATCHDOG_NOTICE_NOW_MS can override, like
the bridge timeout override, so tests drive the backoff without sleeping.
The process summary field "exhausted" is renamed "failing". A journal
entry whose updatedAt is not a date is now refused as
journal-entry-invalid, since the delay is measured from it.

All commits build.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-01 01:48:44 +02:00
Meta Vens
ff087a554b Watchdog notice reader: pin timeout, spawn-error, 5xx/429 and guard behaviour; say what non-2xx is
Tests only, plus wording. No change to what the reader or bridge does.

- A spawn timeout and a spawn error (ENOBUFS from a bridge that floods
  stdout) record unknown, are never re-posted, and block the closure.
  WATCHDOG_NOTICE_BRIDGE_TIMEOUT_MS overrides the 60 s timeout so the test
  reaches that branch; the default is unchanged.
- A 500/502/503/429 answer to the message POST exits 75 from the bridge, and
  through the reader is retried with the same nonce until it completes.
- allowed_mentions {parse: []} is asserted in the posted body; status exits
  non-zero while an entry is unknown and zero when none is.
- The bridge comment and docs/watchdog-notice.md no longer call a non-2xx
  answer "definite": it is retried with the same nonce, relying on
  enforce_nonce inside Discord's window, and may double-send if Discord acted
  on a 5xx outside it.

Builds. Two tests fail on Windows (SIGKILL status), as before; they pass on
Yggdrasil.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 22:56:27 +02:00
Meta Vens
1f001e11d2 Watchdog notice reader: the journal owns "sent"; only exit 75 is retried
Fix batch for Soul pass s1 (spec r3):
- Delete prune-on-absence and its test. Absence from Idunn's store no longer
  deletes a journal entry, so an empty or restored store never re-sends.
- discord-dm exits 75 only when no message can have been sent (arguments,
  token, DM channel open, non-2xx on the message POST). The reader records
  failed for 75 only; any other non-success without a message id is unknown
  and is never re-posted.
- Subject grammar is Idunn's require_id; the notice puts it in backticks.
- Times are bounded to the Date range; notice text is built before the
  running entry is written.

Builds and passes on Linux. On Windows the two tests that SIGKILL the reader
cannot pass (process.kill does not deliver a signal there).

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 21:54:23 +02:00
Meta Vens
7e92687716 Watchdog notice tests: canary the refused record's bytes, not the recipient
The egress test searched for the substring CANARY, which the recipient double
also carries, so it failed on its own input.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 21:20:47 +02:00
Meta Vens
417454c28f Watchdog notice reader: Idunn incidents become owner DMs through Bifrost's own journal
tools/watchdog-notice.mjs is a one-shot reader. It reads Idunn's incident
store unlocked with SingleFileMessagePackBackingStore.pullAll, sends one opening
and one closing DM per incident through bifrost-bridge.mjs, and keeps a
bifrost.watchdog_notice_execution.v1 journal: a running entry becomes unknown
and is never re-posted, a failed one is retried with the same nonce up to five
times, terminal entries are pruned once Idunn retires the incident. The exit
status is the delivery-failure signal.

discord-dm accepts --nonce (at most 25 chars) and sends nonce with
enforce_nonce so a retry inside Discord's window returns the original message.

The tests run the CLI against the store bytes Idunn wrote (fixture from
GameCult/Idunn 7f7528b3) with a counting bridge double, and once through the
real bridge with fetch stubbed. docs/watchdog-notice.md states the CultLib
>= 8cb3b728 floor.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 21:15:18 +02:00
Meta Vens
4152676ebb Merge watchdog bifrost-suite: the node suite loads against current CultLib
Eureka idunn-watchdog cut bifrost-suite. Soul verdict
idunn-watchdog:verdict:cut-bifrost-suite.s1 holds: 24 tests, 22 pass,
0 fail, 2 skipped with reason. Bifrost now requires CultLib >= 8cb3b728.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-30 18:40:35 +02:00
Meta Vens
e8483c056b Bifrost suite: drop the hard-coded CARGO_TARGET_DIR override from the Rust fixture tests
The two fixture tests forced a workstation-only target dir
(C:\Users\Meta\.cargo-target-codex); the child now inherits process.env.
Follow-up to 868df354, which missed this deletion. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 17:16:55 +02:00
Meta Vens
868df35449 Bifrost suite: load @gamecult/cultcache-ts; skip Rust fixture tests with a stated reason
CultLib 8cb3b728 renamed only cultcache-ts to @gamecult/cultcache-ts; the
suite and three tools still required the bare name. Rename the require
string in tests/persona-feedback-cli, persona-discord-delivery,
persona-discord-crossing-rust-smoke, tools/persona-feedback (:114),
agent-transport and governance-threads. No fallback: a pre-8cb3b728 CultLib
fails loudly at import. operator-notification.mjs is untouched (retire cut).

The two Rust fixture tests skip, naming the missing producer (Epiphany
removed both fixture bins in 387afe49), and drop the hard-coded
CARGO_TARGET_DIR override. Builds.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 17:16:39 +02:00
Meta Vens
9c954e7502 Bifrost pump: one verb, one path; refuse anything else with a failed receipt
With discord-dm gone the verb set, listCommandRecords filter, resolveBridgeVerb
throw and the verb variable decided nothing, and the filter hid non-discord-post
commands so they stayed pending with no receipt. Delete all of it: a command
whose verb is not discord-post now reaches processOneCommand and is refused
with a failed receipt (error names no input value). Payload staging moves
inside the try so a refusal cannot escape as a thrown error.

Adds tests/cultmesh-bridge-commands.test.mjs: discord-dm refused with failed
receipt and non-ok result, canary-free error, discord-post still reaches the
actuator.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-09-30 16:59:51 +02:00
Meta Vens
8b9ab65b3f Delete Epiphany operator bridge 2026-08-22 06:16:39 +02:00
Meta Vens
cb3239aaac persona: receipt Discord bridge commands 2026-08-08 21:26:13 +01:00