From ea4193e0e4d3a6e6165dec0db14ffd0a384acf5d Mon Sep 17 00:00:00 2001 From: Eureka Date: Wed, 11 Nov 2026 17:42:26 +0000 Subject: [PATCH] Desk feed door: card has 16 keys (17 with raised_at); grammar test kills length and dash mutants Soul on d08b888: CultLib main's card requires 16 keys, not 17. The account-id grammar test now rejects 36 hex digits with no dash, a 37-character id and a dash off position. The reader-view test says it pins mirror types only. Co-Authored-By: Claude Sonnet 5.5 --- .../huginn-mind/tests/desk_feed_fixtures.rs | 20 ++++++++++++++++++- docs/desk-feed-door.md | 4 ++-- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/crates/huginn-mind/tests/desk_feed_fixtures.rs b/crates/huginn-mind/tests/desk_feed_fixtures.rs index 744ce7c..4f79237 100644 --- a/crates/huginn-mind/tests/desk_feed_fixtures.rs +++ b/crates/huginn-mind/tests/desk_feed_fixtures.rs @@ -326,7 +326,21 @@ fn every_account_id_in_the_fixtures_is_a_lowercase_d_format_uuid() { assert!(request.deciders().iter().all(|decider| account_id(&decider.0)), "deciders"); } assert!(record().answers.iter().all(|answer| account_id(&answer.answerer)), "answerer"); - for shape in ["@heimdall:gamecult.org", "meta@gamecult.org", "heimdall", "7", "5F0C2B1E-8A4D-4C3B-9E7F-1A2B3C4D5E6F", "{5f0c2b1e-8a4d-4c3b-9e7f-1a2b3c4d5e6f}", ""] { + for shape in [ + "@heimdall:gamecult.org", + "meta@gamecult.org", + "heimdall", + "7", + "5F0C2B1E-8A4D-4C3B-9E7F-1A2B3C4D5E6F", + "{5f0c2b1e-8a4d-4c3b-9e7f-1a2b3c4d5e6f}", + "", + // 36 hex digits and no dash: the length alone does not make an id. + "5f0c2b1e08a4d04c3b09e7f01a2b3c4d5e6f", + // 37 characters: a valid id with one more digit. + "5f0c2b1e-8a4d-4c3b-9e7f-1a2b3c4d5e6f0", + // A dash moved off its position. + "5f0c2b1e8-a4d-4c3b-9e7f-1a2b3c4d5e6f", + ] { assert!(!account_id(shape), "{shape} is not an account id"); } } @@ -335,6 +349,10 @@ fn holds(bytes: &[u8], text: &str) -> bool { bytes.windows(text.len()).any(|window| window == text.as_bytes()) } +/// This test pins MIRROR TYPES ONLY (`CardViewers`, `WithheldRecord`), the shapes proposed to CultLib. +/// It does not exercise Huginn's projection, which does not withhold ids yet. The tests on real list and +/// read responses land with `cut-desk-feed-listing` (r6). +/// /// A reader who is not a decider gets counts and no account id at all: neither UUID appears /// anywhere in its fragments' bytes. A decider gets every id. (Proposed shapes; the build cut pins /// the same on Huginn's real list and read responses.) diff --git a/docs/desk-feed-door.md b/docs/desk-feed-door.md index c6ab968..e440feb 100644 --- a/docs/desk-feed-door.md +++ b/docs/desk-feed-door.md @@ -102,7 +102,7 @@ refuses any decider not in that form). That is the same grammar Huginn names for handle is never one of them. Bifrost enforces the grammar; Huginn's door does not yet: it reads these fields as `Short` (any text up to 200 bytes) and would accept `@x:server` or an email. A subject is stored as `answerer` on an answer, so a wrong value would enter the mind. Refusing every other -shape at decode is owed by `cut-desk-feed-listing.r5`. The test +shape at decode is owed by `cut-desk-feed-listing.r6`. The test `every_account_id_in_the_fixtures_is_a_lowercase_d_format_uuid` pins the grammar. The fixtures use synthetic UUIDs. @@ -118,7 +118,7 @@ byte; both values are in the account-id format above. Any other reader is a non- Bifrost, withholds account ids from a non-decider and returns a count instead. Bifrost cannot do it, because the card is opaque to it. A decider sees the ids. The superseding ruling is drafted as `desk-read-visibility-withheld-ids`. -- **CultLib cannot carry this yet.** The card has 17 required keys in closed map-mode, and +- **CultLib cannot carry this yet.** The card has 16 required keys in closed map-mode (17 once `raised_at` lands), and `deciders` must hold at least one item. `answerer` is a required, non-null id. The proposal to Libby (follow-up `cultlib-fork-card-reader-counts`): - the card gains a required `decider_count` (an integer). A non-decider gets `deciders: []`; a