Desk feed door doc: read-form fork_too_large, Refused shapes, fork source, gate not live
Soul pass on 66e6fe8: document and fixture the read form of
fork_too_large (live on main; CultLib limitation 13 is stale), the
ResponseTooLarge 503 and a unit-variant Refused; say that only operation
messages have sorted keys, what failure diagnostics and the schema
catalog reply are, where forks come from, and that the listing gate is
not live (no receiver on a Mind with private questions before
cut-desk-feed-listing). Fixtures use a held fork id, synthetic record.
.gitattributes keeps .bin/.msgpack binary and .hex LF.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
66e6fe8d7d
commit
650e5e262e
26 changed files with 121 additions and 27 deletions
|
|
@ -14,14 +14,16 @@ use std::path::PathBuf;
|
|||
use cultnet_rs::{CultNetMessage, CultNetWireContract, encode_cultnet_message_to_vec, encode_frame};
|
||||
use huginn_mind::MindRefusal;
|
||||
use huginn_mind::desk_wire::{
|
||||
AnswerSchema, DeskRequest, DeskResponse, ForkCursor, ForkDeskAnswer, ForkLimit, ForkList, ForkRecord, ForkRefusal, ForkRefusalCode,
|
||||
fork_too_large_read, AnswerSchema, DeskRequest, DeskResponse, ForkCursor, ForkDeskAnswer, ForkLimit, ForkList, ForkRecord, ForkRefusal, ForkRefusalCode,
|
||||
ListSchema, ListStatus, RecordSchema,
|
||||
};
|
||||
use huginn_mind::envelope::{OperationFailure, encode_desk_failure, encode_desk_request, encode_desk_response};
|
||||
use huginn_mind::eureka_pipeline::{DeskAuthority, Short, Slug};
|
||||
|
||||
const RUNTIME: &str = "huginn-eureka";
|
||||
const FORK: &str = "eureka-substrate:question:desk-fork-audience";
|
||||
/// A question Eureka's mind holds (asked 2026-11-11). The answers, notes and hash in `record()` are
|
||||
/// synthetic: the hash is CultLib's sample digest, not this question's.
|
||||
const FORK: &str = "eureka-substrate:question:desk-listing-authority";
|
||||
|
||||
fn s(text: &str) -> Short {
|
||||
Short(text.into())
|
||||
|
|
@ -71,7 +73,7 @@ fn answer(id: &str, outcome: &str, of: Option<&str>, answerer: &str, note: &str,
|
|||
retracts: None,
|
||||
code: None,
|
||||
options_hash: "7d95fc87d532420611fe415c1def27a3447617bb68235f46e3af130aea361c48".into(),
|
||||
choice: Some("campaign-listing".into()),
|
||||
choice: Some("asking-mind".into()),
|
||||
note: Some(note.into()),
|
||||
answered_at: received_at.into(),
|
||||
received_at: received_at.into(),
|
||||
|
|
@ -91,8 +93,8 @@ fn record() -> ForkRecord {
|
|||
options_hash: "7d95fc87d532420611fe415c1def27a3447617bb68235f46e3af130aea361c48".into(),
|
||||
counted_answer_id: Some("n1".into()),
|
||||
answers: vec![
|
||||
answer("n1", "Counted", None, "7", "List by campaign.", "2026-11-11T17:00:00Z"),
|
||||
answer("n2", "Revision", Some("n1"), "12", "Agreed, campaign grain.", "2026-11-11T17:05:00Z"),
|
||||
answer("n1", "Counted", None, "7", "The asker lists her own forks.", "2026-11-11T17:00:00Z"),
|
||||
answer("n2", "Revision", Some("n1"), "12", "Agreed.", "2026-11-11T17:05:00Z"),
|
||||
],
|
||||
}
|
||||
}
|
||||
|
|
@ -150,6 +152,12 @@ fn fixtures() -> Vec<(String, Vec<u8>)> {
|
|||
)
|
||||
.unwrap(),
|
||||
);
|
||||
message("read-too-large.response", encode_desk_response("m-4", "fork", &DeskResponse::NotStored(fork_too_large_read(FORK)), RUNTIME).unwrap());
|
||||
message(
|
||||
"list-response-too-large.response",
|
||||
encode_desk_response("m-1", "forks", &DeskResponse::Refused(MindRefusal::ResponseTooLarge { bytes: 70000, limit: 65536 }), RUNTIME).unwrap(),
|
||||
);
|
||||
message("refused-unit.response", encode_desk_response("m-1", "forks", &DeskResponse::Refused(MindRefusal::MissingIdentity), RUNTIME).unwrap());
|
||||
message(
|
||||
"unavailable.response",
|
||||
encode_desk_response("m-1", "forks", &DeskResponse::Refused(MindRefusal::Unavailable { detail: "the mind store is not readable".into() }), RUNTIME).unwrap(),
|
||||
|
|
|
|||
3
crates/huginn-mind/tests/fixtures/desk-feed/.gitattributes
vendored
Normal file
3
crates/huginn-mind/tests/fixtures/desk-feed/.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
*.bin binary
|
||||
*.msgpack binary
|
||||
*.hex text eol=lf
|
||||
|
|
@ -12,7 +12,12 @@ Each case has up to four files:
|
|||
- `<case>.payload.msgpack` and `<case>.payload.hex`: the base64-decoded `payload` of an operation
|
||||
message (named MessagePack). The `record-*` cases are bare payload fragments with no frame.
|
||||
|
||||
Hex is lowercase with one trailing newline.
|
||||
Hex is lowercase with one trailing newline. The fork id is a question Eureka's mind holds. The
|
||||
record's answers, notes and hash are synthetic.
|
||||
|
||||
**The listing gate is not live.** On `main` every showable question goes to every reader. Do not
|
||||
put a Mind that holds private questions behind a live receiver before `cut-desk-feed-listing`
|
||||
lands (see `docs/desk-feed-door.md`).
|
||||
|
||||
| case | direction | content |
|
||||
|---|---|---|
|
||||
|
|
@ -24,6 +29,9 @@ Hex is lowercase with one trailing newline.
|
|||
| `list-counts.response` | Huginn to Bifrost | the limit-0 answer: open 3, recorded 5, `forks: []` |
|
||||
| `read-unknown.response` | Huginn to Bifrost | `NotStored` `fork_unknown` (Bifrost: 404) |
|
||||
| `list-too-large.response` | Huginn to Bifrost | `NotStored` `fork_too_large` naming the cursor to continue (Bifrost: 422) |
|
||||
| `read-too-large.response` | Huginn to Bifrost | `NotStored` `fork_too_large`, read form: names the fork, no order or cursor (Bifrost: 422) |
|
||||
| `list-response-too-large.response` | Huginn to Bifrost | `Refused` `ResponseTooLarge` (Bifrost: 503) |
|
||||
| `refused-unit.response` | Huginn to Bifrost | `Refused` with a unit variant: a bare string `"MissingIdentity"` (shape only; Bifrost: 503) |
|
||||
| `unavailable.response` | Huginn to Bifrost | `Refused` `Unavailable` (Bifrost: 503 for this Mind) |
|
||||
| `failure.response` | Huginn to Bifrost | operation failure, `payloadSchema` `gamecult.cultnet.operation_failure.v1` (Bifrost: 503) |
|
||||
| `error.response` | Huginn to Bifrost | CultNet `Error` message, no payload (Bifrost: 503) |
|
||||
|
|
|
|||
BIN
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.frame.bin
vendored
Normal file
BIN
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.frame.bin
vendored
Normal file
Binary file not shown.
1
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.frame.hex
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.frame.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
0000012689a96d6573736167654964a36d2d31a96f7065726174696f6ea5666f726b73a77061796c6f6164d944676164535a575a316332566b676242535a584e776232357a5a56527662307868636d646c677156696558526c63383441415246777057787062576c307a6741424141413daf7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b7687567696e6e2e6465736b5f726573706f6e73652e7631ad736368656d6156657273696f6ebd63756c746e65742e6f7065726174696f6e5f726573706f6e73652e7630a9736572766963654964ab687567696e6e2e6465736baf736f7572636552756e74696d654964ad687567696e6e2d657572656b61a6737461747573a872656a6563746564
|
||||
1
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.payload.hex
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.payload.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
81a75265667573656481b0526573706f6e7365546f6f4c6172676582a56279746573ce00011170a56c696d6974ce00010000
|
||||
BIN
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.payload.msgpack
vendored
Normal file
BIN
crates/huginn-mind/tests/fixtures/desk-feed/list-response-too-large.response.payload.msgpack
vendored
Normal file
Binary file not shown.
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
0000020389a96d6573736167654964a36d2d31a96f7065726174696f6ea5666f726b73a77061796c6f6164da012067616c4f62335254644739795a57534472584e6a6147567459565a6c636e4e70623236345a3246745a574e31624851755a6d3979617935795a575a31633246734c6e597770474e765a4757755a6d39796131393062323966624746795a32576c5a584a7962334c5a69575a76636d74666447397658327868636d646c4f69426d62334a7249475631636d56725953317a64574a7a64484a68644755366358566c63335270623234365a47567a6179316d62334a724c5746315a476c6c626d4e6c49474630494739795a4756794944517849476c7a49484268633351676447686c494842685a325567596e566b5a32563049474a3549476c30633256735a6a73675932397564476c756457556764326c306143426a64584a7a62334967597a5178af7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b7687567696e6e2e6465736b5f726573706f6e73652e7631ad736368656d6156657273696f6ebd63756c746e65742e6f7065726174696f6e5f726573706f6e73652e7630a9736572766963654964ab687567696e6e2e6465736baf736f7572636552756e74696d654964ad687567696e6e2d657572656b61a6737461747573a872656a6563746564
|
||||
0000020b89a96d6573736167654964a36d2d31a96f7065726174696f6ea5666f726b73a77061796c6f6164da012867616c4f62335254644739795a57534472584e6a6147567459565a6c636e4e70623236345a3246745a574e31624851755a6d3979617935795a575a31633246734c6e597770474e765a4757755a6d39796131393062323966624746795a32576c5a584a7962334c5a6a575a76636d74666447397658327868636d646c4f69426d62334a7249475631636d56725953317a64574a7a64484a68644755366358566c63335270623234365a47567a6179317361584e306157356e4c57463164476876636d6c306553426864434276636d526c636941304d5342706379427759584e304948526f5a5342775957646c49474a315a47646c644342696553427064484e6c6247593749474e76626e5270626e566c4948647064476767593356796332397949474d304d513d3daf7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b7687567696e6e2e6465736b5f726573706f6e73652e7631ad736368656d6156657273696f6ebd63756c746e65742e6f7065726174696f6e5f726573706f6e73652e7630a9736572766963654964ab687567696e6e2e6465736baf736f7572636552756e74696d654964ad687567696e6e2d657572656b61a6737461747573a872656a6563746564
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
81a94e6f7453746f72656483ad736368656d6156657273696f6eb867616d6563756c742e666f726b2e7265667573616c2e7630a4636f6465ae666f726b5f746f6f5f6c61726765a56572726f72d989666f726b5f746f6f5f6c617267653a20666f726b20657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d666f726b2d61756469656e6365206174206f7264657220343120697320706173742074686520706167652062756467657420627920697473656c663b20636f6e74696e7565207769746820637572736f7220633431
|
||||
81a94e6f7453746f72656483ad736368656d6156657273696f6eb867616d6563756c742e666f726b2e7265667573616c2e7630a4636f6465ae666f726b5f746f6f5f6c61726765a56572726f72d98d666f726b5f746f6f5f6c617267653a20666f726b20657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d6c697374696e672d617574686f72697479206174206f7264657220343120697320706173742074686520706167652062756467657420627920697473656c663b20636f6e74696e7565207769746820637572736f7220633431
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<EFBFBD>NotStored<EFBFBD>schemaVersion經amecult.fork.refusal.v0勺ode宸ork_too_large占rror<6F>fork_too_large: fork eureka-substrate:question:desk-fork-audience at order 41 is past the page budget by itself; continue with cursor c41
|
||||
<EFBFBD>NotStored<EFBFBD>schemaVersion經amecult.fork.refusal.v0勺ode宸ork_too_large占rror<6F>fork_too_large: fork eureka-substrate:question:desk-listing-authority at order 41 is past the page budget by itself; continue with cursor c41
|
||||
BIN
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.frame.bin
vendored
Normal file
BIN
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.frame.bin
vendored
Normal file
Binary file not shown.
1
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.frame.hex
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.frame.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
000001d989a96d6573736167654964a36d2d34a96f7065726174696f6ea4666f726ba77061796c6f6164d9f867616c4f62335254644739795a57534472584e6a6147567459565a6c636e4e70623236345a3246745a574e31624851755a6d3979617935795a575a31633246734c6e597770474e765a4757755a6d39796131393062323966624746795a32576c5a584a7962334c5a616d5a76636d74666447397658327868636d646c4f69426d62334a7249475631636d56725953317a64574a7a64484a68644755366358566c63335270623234365a47567a6179317361584e306157356e4c57463164476876636d6c30655342706379427759584e304948526f5a5342795a584e776232357a5a534269623356755a4342696553427064484e6c6247593daf7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b7687567696e6e2e6465736b5f726573706f6e73652e7631ad736368656d6156657273696f6ebd63756c746e65742e6f7065726174696f6e5f726573706f6e73652e7630a9736572766963654964ab687567696e6e2e6465736baf736f7572636552756e74696d654964ad687567696e6e2d657572656b61a6737461747573a872656a6563746564
|
||||
1
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.payload.hex
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.payload.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
81a94e6f7453746f72656483ad736368656d6156657273696f6eb867616d6563756c742e666f726b2e7265667573616c2e7630a4636f6465ae666f726b5f746f6f5f6c61726765a56572726f72d96a666f726b5f746f6f5f6c617267653a20666f726b20657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d6c697374696e672d617574686f7269747920697320706173742074686520726573706f6e736520626f756e6420627920697473656c66
|
||||
1
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.payload.msgpack
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/read-too-large.response.payload.msgpack
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>NotStored<EFBFBD>schemaVersion經amecult.fork.refusal.v0勺ode宸ork_too_large占rror揂fork_too_large: fork eureka-substrate:question:desk-listing-authority is past the response bound by itself
|
||||
Binary file not shown.
|
|
@ -1 +1 @@
|
|||
0000013587a96d6573736167654964a36d2d34a96f7065726174696f6ea4666f726ba77061796c6f6164d9846761524762334a72684b52746157356b706d5631636d56725961647a64574a715a574e306f54656f5a47566a6157526c636e4f536f5465694d544b6e5a6d3979613139705a4e6b735a5856795a5774684c584e31596e4e30636d46305a5470786457567a64476c76626a706b5a584e724c575a76636d73745958566b615756755932553daf7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b6687567696e6e2e6465736b5f726571756573742e7631ad736368656d6156657273696f6ebc63756c746e65742e6f7065726174696f6e5f726571756573742e7630a9736572766963654964ab687567696e6e2e6465736b
|
||||
0000013987a96d6573736167654964a36d2d34a96f7065726174696f6ea4666f726ba77061796c6f6164d9886761524762334a72684b52746157356b706d5631636d56725961647a64574a715a574e306f54656f5a47566a6157526c636e4f536f5465694d544b6e5a6d3979613139705a4e6b775a5856795a5774684c584e31596e4e30636d46305a5470786457567a64476c76626a706b5a584e724c57787063335270626d6374595856306147397961585235af7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b6687567696e6e2e6465736b5f726571756573742e7631ad736368656d6156657273696f6ebc63756c746e65742e6f7065726174696f6e5f726571756573742e7630a9736572766963654964ab687567696e6e2e6465736b
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
81a4466f726b84a46d696e64a6657572656b61a77375626a656374a137a8646563696465727392a137a23132a7666f726b5f6964d92c657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d666f726b2d61756469656e6365
|
||||
81a4466f726b84a46d696e64a6657572656b61a77375626a656374a137a8646563696465727392a137a23132a7666f726b5f6964d930657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d6c697374696e672d617574686f72697479
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
<EFBFBD>¤Fork„¤mind¦eureka§subject¡7¨deciders’¡7¢12§fork_idÙ,eureka-substrate:question:desk-fork-audience
|
||||
<EFBFBD>¤Fork„¤mind¦eureka§subject¡7¨deciders’¡7¢12§fork_idÙ0eureka-substrate:question:desk-listing-authority
|
||||
|
|
@ -1 +1 @@
|
|||
85ad736368656d6156657273696f6eb767616d6563756c742e666f726b2e7265636f72642e7630a7666f726b5f6964d92c657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d666f726b2d61756469656e6365ac6f7074696f6e735f68617368d94037643935666338376435333234323036313166653431356331646566323761333434373631376262363832333566343665336166313330616561333631633438b1636f756e7465645f616e737765725f6964a26e31a7616e737765727392de0010ad736368656d6156657273696f6eb767616d6563756c742e6465736b5f616e737765722e7630a9616e737765725f6964a26e31a7666f726b5f6964d92c657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d666f726b2d61756469656e6365a76f7574636f6d65a7436f756e746564a26f66c0a87265747261637473c0a4636f6465c0ac6f7074696f6e735f68617368d94037643935666338376435333234323036313166653431356331646566323761333434373631376262363832333566343665336166313330616561333631633438a663686f696365b063616d706169676e2d6c697374696e67a46e6f7465b14c6973742062792063616d706169676e2eab616e7377657265645f6174b4323032362d31312d31315431373a30303a30305aab72656365697665645f6174b4323032362d31312d31315431373a30303a30305aaf636c61696d5f696e5f667574757265c2a8616e737765726572a137a9617574686f72697479a64d656d626572aa726571756573745f6964d92430303030303030302d303030302d343030302d383030302d303030303030303030303031de0010ad736368656d6156657273696f6eb767616d6563756c742e6465736b5f616e737765722e7630a9616e737765725f6964a26e32a7666f726b5f6964d92c657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d666f726b2d61756469656e6365a76f7574636f6d65a85265766973696f6ea26f66a26e31a87265747261637473c0a4636f6465c0ac6f7074696f6e735f68617368d94037643935666338376435333234323036313166653431356331646566323761333434373631376262363832333566343665336166313330616561333631633438a663686f696365b063616d706169676e2d6c697374696e67a46e6f7465b74167726565642c2063616d706169676e20677261696e2eab616e7377657265645f6174b4323032362d31312d31315431373a30353a30305aab72656365697665645f6174b4323032362d31312d31315431373a30353a30305aaf636c61696d5f696e5f667574757265c2a8616e737765726572a23132a9617574686f72697479a64d656d626572aa726571756573745f6964d92430303030303030302d303030302d343030302d383030302d303030303030303030303032
|
||||
85ad736368656d6156657273696f6eb767616d6563756c742e666f726b2e7265636f72642e7630a7666f726b5f6964d930657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d6c697374696e672d617574686f72697479ac6f7074696f6e735f68617368d94037643935666338376435333234323036313166653431356331646566323761333434373631376262363832333566343665336166313330616561333631633438b1636f756e7465645f616e737765725f6964a26e31a7616e737765727392de0010ad736368656d6156657273696f6eb767616d6563756c742e6465736b5f616e737765722e7630a9616e737765725f6964a26e31a7666f726b5f6964d930657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d6c697374696e672d617574686f72697479a76f7574636f6d65a7436f756e746564a26f66c0a87265747261637473c0a4636f6465c0ac6f7074696f6e735f68617368d94037643935666338376435333234323036313166653431356331646566323761333434373631376262363832333566343665336166313330616561333631633438a663686f696365ab61736b696e672d6d696e64a46e6f7465be5468652061736b6572206c6973747320686572206f776e20666f726b732eab616e7377657265645f6174b4323032362d31312d31315431373a30303a30305aab72656365697665645f6174b4323032362d31312d31315431373a30303a30305aaf636c61696d5f696e5f667574757265c2a8616e737765726572a137a9617574686f72697479a64d656d626572aa726571756573745f6964d92430303030303030302d303030302d343030302d383030302d303030303030303030303031de0010ad736368656d6156657273696f6eb767616d6563756c742e6465736b5f616e737765722e7630a9616e737765725f6964a26e32a7666f726b5f6964d930657572656b612d7375627374726174653a7175657374696f6e3a6465736b2d6c697374696e672d617574686f72697479a76f7574636f6d65a85265766973696f6ea26f66a26e31a87265747261637473c0a4636f6465c0ac6f7074696f6e735f68617368d94037643935666338376435333234323036313166653431356331646566323761333434373631376262363832333566343665336166313330616561333631633438a663686f696365ab61736b696e672d6d696e64a46e6f7465a74167726565642eab616e7377657265645f6174b4323032362d31312d31315431373a30353a30305aab72656365697665645f6174b4323032362d31312d31315431373a30353a30305aaf636c61696d5f696e5f667574757265c2a8616e737765726572a23132a9617574686f72697479a64d656d626572aa726571756573745f6964d92430303030303030302d303030302d343030302d383030302d303030303030303030303032
|
||||
|
|
|
|||
Binary file not shown.
BIN
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.frame.bin
vendored
Normal file
BIN
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.frame.bin
vendored
Normal file
Binary file not shown.
1
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.frame.hex
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.frame.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
0000010689a96d6573736167654964a36d2d31a96f7065726174696f6ea5666f726b73a77061796c6f6164d924676164535a575a316332566b7230317063334e70626d644a5a47567564476c3065513d3daf7061796c6f6164456e636f64696e67b26d6573736167657061636b2d626173653634ad7061796c6f6164536368656d61b7687567696e6e2e6465736b5f726573706f6e73652e7631ad736368656d6156657273696f6ebd63756c746e65742e6f7065726174696f6e5f726573706f6e73652e7630a9736572766963654964ab687567696e6e2e6465736baf736f7572636552756e74696d654964ad687567696e6e2d657572656b61a6737461747573a872656a6563746564
|
||||
1
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.payload.hex
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.payload.hex
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
81a752656675736564af4d697373696e674964656e74697479
|
||||
1
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.payload.msgpack
vendored
Normal file
1
crates/huginn-mind/tests/fixtures/desk-feed/refused-unit.response.payload.msgpack
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
<EFBFBD>§Refused¯MissingIdentity
|
||||
|
|
@ -8,6 +8,13 @@ are planned and not built: `raised_at` on the card, and the listing gate that de
|
|||
reader sees. They are cut specs `cut-desk-feed-raised-at` and `cut-desk-feed-listing` in the
|
||||
`eureka-substrate` campaign.
|
||||
|
||||
**Not live: the listing gate.** On `main` today every showable question is returned to every
|
||||
reader, whatever the call's `deciders` say (pinned by
|
||||
`the_whole_record_comes_back_whoever_the_deciders_list_leaves_out` in `desk_wire/reads.rs`).
|
||||
The default of not listed, described under Listing below, holds only once `cut-desk-feed-listing`
|
||||
lands. Until then, neither Bifrost's receiver nor the ops root-run (`desk-door-ops-root-run`) may
|
||||
go live on a Mind that holds private questions.
|
||||
|
||||
This page is the wire contract for the consumer, Bifrost's `UnixSocketDeskDoor` (Bifrost PR #67,
|
||||
`docs/desk-feed-design.md`). The golden bytes are in `crates/huginn-mind/tests/fixtures/desk-feed/`.
|
||||
Huginn's own encoders write them (`crates/huginn-mind/tests/desk_feed_fixtures.rs`), so a decoder
|
||||
|
|
@ -31,6 +38,20 @@ that reads them reads the door. The document shapes inside the payload (`gamecul
|
|||
- Huginn serves only its own Mind. A request whose `mind` is another instance is refused
|
||||
(`Refused(...)`).
|
||||
|
||||
## Where forks come from
|
||||
|
||||
A fork is any question the Mind holds, in any of its campaigns, that is showable. Showable
|
||||
(`showable`, `desk_wire.rs`) means at least two options, no blank option text or `depends` line,
|
||||
and at least one decider on the call. An in-force question is `open`. A question with any
|
||||
resolution in force is `recorded` (a closed card, `ruling` set when an in-force ruling answers it).
|
||||
That set includes the questions holding a spec (`huginn blocked`) and the open questions of every
|
||||
campaign (`huginn open`). Nothing else in the mind is a fork: follow-ups, findings, research and
|
||||
Persona state never reach the desk.
|
||||
|
||||
The fixtures use the fork id `eureka-substrate:question:desk-listing-authority`, a question Eureka's
|
||||
mind holds. The record's answers, notes and `options_hash` are synthetic: the hash is CultLib's
|
||||
sample digest.
|
||||
|
||||
## Framing and envelope
|
||||
|
||||
```
|
||||
|
|
@ -46,8 +67,15 @@ payload = message["payload"], standard base64 of named MessagePack (rmp_serde::
|
|||
`messageId`, `status` `accepted` or `rejected`, and `sourceRuntimeId` (informational: do not
|
||||
compare it). The `payloadSchema` is `huginn.desk_response.v1`, or
|
||||
`gamecult.cultnet.operation_failure.v1` when the envelope or payload did not decode.
|
||||
- Envelope keys are written in sorted order and absent optionals are omitted. Decode by key, not
|
||||
by position.
|
||||
- Operation messages (requests, responses, failures) have their keys written in sorted order,
|
||||
with absent optionals omitted. The CultNet `Error` message does not follow that: its keys come in
|
||||
CultNet's raw order (`schemaVersion`, `error`, `routingHint`, `code`, `details`), and absent
|
||||
values are written as nil (fixture `error.response`). Decode by key, never by position.
|
||||
- An operation failure carries `diagnostics`, a list holding the failure code (fixture
|
||||
`failure.response`). It is absent on every other response.
|
||||
- The door also answers `cultnet.schema_catalog_request.v0` with the catalog of the two desk
|
||||
schemas (`huginn.desk_request.v1`, `huginn.desk_response.v1`, with their JSON Schemas). No
|
||||
fixture pins that reply, because it embeds the schema text.
|
||||
- Frame bound: 65536 bytes each way. A reply past it is refused by name, never truncated.
|
||||
|
||||
## Payloads
|
||||
|
|
@ -72,8 +100,31 @@ Response (`huginn.desk_response.v1`):
|
|||
|---|---|---|
|
||||
| `{"Forks": {list, as_of}}` | one page, `list` is `gamecult.fork.list.v0` | 200 |
|
||||
| `{"Fork": {entry, as_of}}` | one fork, `entry` is `gamecult.fork.entry.v0` | 200 |
|
||||
| `{"NotStored": refusal}` | `gamecult.fork.refusal.v0`: `fork_unknown`, or `fork_too_large` with the cursor to continue | 404 / 422 |
|
||||
| `{"Refused": {"<Variant>": {...}}}` | a Mind refusal (store fault, wrong instance, a response too large) | 503 `unavailable` |
|
||||
| `{"NotStored": refusal}` | `gamecult.fork.refusal.v0`: `fork_unknown`, or `fork_too_large` | 404 / 422 |
|
||||
| `{"Refused": <MindRefusal>}` | a Mind refusal (store fault, wrong instance, a list reply over the cap) | 503 `unavailable` |
|
||||
|
||||
The `Refused` value is opaque to Bifrost: any `Refused` is a 503. Its shape depends on the
|
||||
variant: a variant with fields is a one-key map (`{"Unavailable": {"detail": ...}}`,
|
||||
`{"ResponseTooLarge": {"bytes": ..., "limit": ...}}`), and a unit variant is a bare string
|
||||
(`"MissingIdentity"`, fixture `refused-unit.response`).
|
||||
|
||||
**`fork_too_large` has two forms, and both are live on `main`.**
|
||||
|
||||
- The list form comes from `Mind::desk_forks` when the first entry of a page is alone past the
|
||||
page budget: `fork_too_large: fork <fork_id> at order <N> is past the page budget by itself;
|
||||
continue with cursor c<N>`, or `...; this is the end of the list` at order 0 (fixture
|
||||
`list-too-large.response`).
|
||||
- The read form comes from the door (`respond` in `desk_door.rs`, `fork_too_large_read`) when a
|
||||
read's whole entry is past the 65536-byte reply cap: `fork_too_large: fork <fork_id> is past the
|
||||
response bound by itself`, with no order and no cursor (fixture `read-too-large.response`).
|
||||
CultLib `fork-card.md` limitation 13 still says that an over-cap read reaches Bifrost as
|
||||
`Refused(ResponseTooLarge)`. That text is stale: Huginn main answers the read form. The refusal
|
||||
carries no typed order or fork id. A `ForkTooLarge(ForkId[, Order])` in Bifrost must parse them
|
||||
out of the informational `error` text (CultLib calls the text informational), or use the route's
|
||||
`fork_id` and the request's cursor instead. The second is the safer choice.
|
||||
- Any other reply over the cap, which in practice means a list, is `Refused(ResponseTooLarge)`, a
|
||||
503 (fixture `list-response-too-large.response`). A list should not reach it, because pages are
|
||||
budgeted below the cap.
|
||||
|
||||
## Failure means 503 for that Mind only
|
||||
|
||||
|
|
@ -84,8 +135,8 @@ affected, because each Mind has its own socket and the client asks per Mind:
|
|||
without a reply frame;
|
||||
- no whole reply frame arrives within the deadline;
|
||||
- the reply is a CultNet `Error` message (`cultnet.error.v0`, fixture `error.response`), an
|
||||
operation failure (fixture `failure.response`), or a `Refused` payload (fixture
|
||||
`unavailable.response`).
|
||||
operation failure (fixture `failure.response`), or a `Refused` payload (fixtures
|
||||
`unavailable.response`, `list-response-too-large.response`, `refused-unit.response`).
|
||||
|
||||
An empty list is never served in place of a failure. `open_count: 0` means zero open forks.
|
||||
|
||||
|
|
@ -96,7 +147,10 @@ RFC3339 string or nil, which takes the card from 16 to 17 keys in closed map-mod
|
|||
A string is the question's first-admission time, which never moves. It is outside `options_hash`,
|
||||
which keeps its five members, so the hash vectors do not change. Huginn derives it from the
|
||||
question's admission: the `committed_at` of the receipt that first admitted the question, or for an
|
||||
imported question the source mind's `committed_at` (`imported_from.committed_at`).
|
||||
imported question the source mind's `committed_at` (`imported_from.committed_at`). A value that does not
|
||||
parse as RFC3339 is served as nil. One known limit: after a campaign has moved twice (A to B to C),
|
||||
C sees B's admission time, because an import quotes its source's receipt and B's receipt is B's
|
||||
own (follow-up `desk-raised-at-import-chain`).
|
||||
|
||||
**No fixture here carries card bytes.** The card's key order and hex wait on the CultLib commit that
|
||||
re-pins the card vectors with `raised_at`. Until then the card is opaque to these fixtures, and
|
||||
|
|
@ -115,7 +169,7 @@ CultLib commit.
|
|||
Heimdall 2026-11-11) and strips notes (ruling `desk-read-visibility-whole-record`, `DeskNotes`).
|
||||
Huginn masks nothing.
|
||||
|
||||
## Listing: which forks a reader sees (Huginn's; planned)
|
||||
## Listing: which forks a reader sees (Huginn's; NOT live, see the status above)
|
||||
|
||||
Huginn owns audience and visibility, at its door. The card has no audience key (CultLib), and
|
||||
Bifrost's feed applies no fork filter.
|
||||
|
|
@ -126,17 +180,30 @@ Bifrost's feed applies no fork filter.
|
|||
answers `fork_unknown`, the same bytes as a fork that does not exist. The counts and the cursor
|
||||
are computed over the visible set, which is why the gate is Huginn's: a filter applied after
|
||||
paging would make both wrong.
|
||||
- **Deciders** see every showable fork whether or not it is listed (recommended in question
|
||||
`eureka-substrate:question:desk-unlisted-to-deciders`), because they must see a fork to answer it.
|
||||
The door compares the call's `subject` with its `deciders` to tell. The wire does not change.
|
||||
- **Deciders** see every showable fork whether or not it is listed (ruling
|
||||
`eureka-substrate:ruling:desk-deciders-see-all`), because they must see a fork to answer it. The
|
||||
door compares the call's `subject` with its `deciders` to tell. The wire does not change. An
|
||||
operator or steward who is not on `deciders` sees only listed forks: reads carry no authority, so
|
||||
anyone who must see unlisted forks is put on the Mind's decider list in Bifrost's admin.
|
||||
- **What a non-decider can still infer.** `order` is the fork's rank among all the Mind's
|
||||
questions, and `stamp` is the Mind's head. So a non-decider sees gaps in `order` (some unlisted or
|
||||
unshowable questions exist between two listed ones) and sees `stamp` move on any admission. The
|
||||
gate accepts this leak: no fork's text, id or count leaves the door. Ranking over the visible set
|
||||
only would make `order` depend on the reader and move whenever a fork is listed, which breaks
|
||||
CultLib's rule that an order never changes and breaks every held cursor.
|
||||
- **The listing record** is planned kind `desk_listing`, key `<campaign>:desk_listing:<question-label>`,
|
||||
fields `fork` (the question's id) and `reason` (one line: why members may read it). It is
|
||||
fields `campaign`, `fork` (the question's id, in the same campaign) and `reason` (one line: why
|
||||
members may read it). It is
|
||||
admitted on the Mind's own door, so its receipt records who listed it and when. Unlisting is a
|
||||
`Withdrawn` resolution on it, and relisting withdraws that resolution, which reopens it. Each
|
||||
flip is a document with its own receipt, so the history is `huginn history <listing id>`. No flag
|
||||
is stored anywhere else.
|
||||
- **Who may list or unlist** is question `eureka-substrate:question:desk-listing-authority`. The
|
||||
recommended answer is the asking Mind herself, at her Self.
|
||||
- **Who may list or unlist:** the asking Mind herself (ruling
|
||||
`eureka-substrate:ruling:desk-listing-asking-mind`). A fork that names a person's matter is listed
|
||||
only with that person's say.
|
||||
- **CultLib's text disagrees.** `fork-card.md` (Read and List) says no fork is hidden by
|
||||
`fork_unknown` and every `desk.read` holder sees every card. That is Libby's to amend for the
|
||||
listing gate (follow-up `cultlib-fork-card-listing`).
|
||||
- **Open for Heimdall:** if Bifrost wants any part of the listing (an operator override at the
|
||||
desk, a per-Mind default, a reason shown to members), that is his decision to raise. Nothing in
|
||||
this plan puts listing state in Bifrost.
|
||||
|
|
|
|||
Loading…
Reference in a new issue