From aef0e1bf5ae8bcad7be88e1235e8f6a02ae3dea6 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Wed, 16 Sep 2026 16:54:16 +0200 Subject: [PATCH] Describe the pipeline leaf by its own contract, not by Huginn Doc comments only. The crate doc, `prepare`, `register_pipeline_document_types`, `ForeignDocument`, `PIPELINE_SCHEMA_EPOCH` and `validate_pipeline_write_envelope` spoke of "the memory organ" and "Huginn" in the present tense as a consumer that exists; Huginn's crates are empty stubs at this commit. Each now says what the item does and guarantees, and where a consumer must be named, calls it the organ that will admit these documents. The sentence claiming Huginn pins the foreign-document rule against its real receipt type is gone; no such test exists. `decode` now says what it does not do: it validates neither bounds nor the key. A decoded document is a typed read, and `validate_pipeline_write_envelope` is the check before a write. No code change: `cargo test -p epiphany-pipeline --lib` is 27 passed with no warnings, and `schemas/cultnet/` and `Cargo.lock` are untouched. Co-Authored-By: Claude Fable 5.1 --- epiphany-pipeline/src/lib.rs | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/epiphany-pipeline/src/lib.rs b/epiphany-pipeline/src/lib.rs index ffcd92bd..a2726d4d 100644 --- a/epiphany-pipeline/src/lib.rs +++ b/epiphany-pipeline/src/lib.rs @@ -3,8 +3,9 @@ //! This is a leaf type library, and deliberately nothing else. It owns document //! shape, field bounds, formats, key derivation and the JSON schemas published //! under `schemas/cultnet`; it owns no storage, no admission, no process and no -//! network. That is the whole reason it is a package: the memory organ depends -//! on these types without depending on the harness that used to hold them. +//! network. That is the whole reason it is a package: the organ that will admit +//! these documents depends on these types without depending on the harness +//! that used to hold them. //! //! Every kind is a plain `serde` + `JsonSchema` value inside a one-slot //! `DatabaseEntry` wrapper, always prepared with `prepare_entry_named`, so the @@ -39,9 +40,10 @@ use serde::{Deserialize, Serialize}; /// Typed refusals of the pipeline documents: bounds, formats and key identity /// (D2's document half), and `ForeignStore`, raised by `decode` for an -/// envelope of any other type. The organ's refusals wrap this enum; the -/// store's identity and the schema epoch are refused there, against a store a -/// test can construct. +/// envelope of any other type. This is every refusal the leaf decides; a +/// store's identity and its schema epoch are not decided here, since this +/// crate owns no store, and belong to the organ that will admit these +/// documents. #[derive(Clone, Debug, PartialEq, Eq)] pub enum PipelineRefusal { FieldBound { field: String, limit: u32, actual: u32 }, @@ -469,7 +471,7 @@ macro_rules! pipeline_kinds { match self { $(Self::$variant(value) => value.validate($name)),* } } - /// Prepares the envelope the organ stores: keyed by `pipeline_key`, + /// Prepares the envelope to be stored: keyed by `pipeline_key`, /// payload `[value]` through `prepare_entry_named`. pub fn prepare(&self, cache: &CultCache) -> Result { let key = pipeline_key(self)?; @@ -482,7 +484,9 @@ macro_rules! pipeline_kinds { /// Decodes a stored envelope, type-matched both ways: an envelope of /// any other type is `ForeignStore`, never the kind that happens to - /// parse its payload. + /// parse its payload. It validates neither bounds nor the key: a + /// decoded document is a typed read, and + /// `validate_pipeline_write_envelope` is the check before a write. pub fn decode(envelope: &CultCacheEnvelope) -> Result { let invalid = |error: rmp_serde::decode::Error| format_error("payload", &error.to_string()); $(if envelope.r#type == <$document as DatabaseEntry>::TYPE { @@ -494,7 +498,7 @@ macro_rules! pipeline_kinds { } /// Registers every pipeline kind in a cache, and nothing else: the one - /// door to the crate-private wrappers, so the organ registers exactly + /// door to the crate-private wrappers, so a caller registers exactly /// what this crate publishes. pub fn register_pipeline_document_types(cache: &mut CultCache) -> Result<()> { $(cache.register_entry_type::<$document>()?;)* @@ -505,9 +509,8 @@ macro_rules! pipeline_kinds { /// A document that is not a pipeline document, for the decode refusal and the /// registrar's count to be pinned against something real. It stands in for -/// the commit receipt of any organ: a mind's store legitimately holds one -/// beside pipeline documents, and it is still not a document this library may -/// decode. Huginn pins the same rule against its real receipt type; here the +/// any other document a store may hold beside pipeline documents, a commit +/// receipt say, which is still not a document this library may decode. The /// stand-in carries a receipt-shaped type id and is registered only by the /// tests' own cache, never by the live registrar. #[cfg(test)] @@ -639,8 +642,9 @@ const LOCAL_MAX: usize = 64; /// schemas it names. Evolution is additive and keeps it: a new named field /// with a serde default, or a widened `PipelineKind`, since each reader ships /// with the variants it knows and refuses an unknown kind on the kind, not on -/// the epoch. A breaking change bumps it, and the organ refuses a store -/// written at the old one. +/// the epoch. A breaking change bumps it, so that a store written at the old +/// one can be refused by whoever opens it; this crate owns no store and +/// refuses none. pub const PIPELINE_SCHEMA_EPOCH: &str = "epiphany.pipeline.epoch.v1"; /// Composes and validates a local: every part is a `Label`, and the join is @@ -737,8 +741,10 @@ pub fn pipeline_key(document: &PipelineDocument) -> Result Result<(), PipelineRefusal> { let document = PipelineDocument::decode(envelope)?; document.validate()?;