pub struct SourceId(/* private fields */);Expand description
0.8.20 Slice 5c (R-20-E3) — the provenance of a canonical row: which source
document it is attributable to, and therefore what excise_source must erase
when that source is withdrawn.
Why a newtype and not Option<String>. Erasure runs through provenance:
a row whose source_id is NULL is reachable by NO excise_source call and
is therefore un-erasable. Before 0.8.20 the public PreparedWrite
carried source_id: Option<String>, so a caller could express “no
provenance” and silently create such a row. A runtime rejection would not
have closed this: the facade crate re-exports PreparedWrite and
Engine::write is pub, so a caller can build the value directly and skip
any validation the engine performs. Replacing the field’s type is what makes
the absence of provenance inexpressible rather than merely rejected —
the guarantee is enforced by rustc, not by a branch. tests/ui/ in the
facade crate holds the compile-fail witness.
This is a BREAKING change, shipped ON by default as part of the 0.8.20 coordinated breaking-pair release. There is deliberately no compatibility shim and no deprecation window: a shim would re-open the hole it closes.
Reserved namespace. Ids beginning with _ belong to the engine and are
rejected by SourceId::new. Two are currently minted internally:
SourceId::ENGINE_PREFIX(_engine:) — rows the engine derives for itself (EXP-S coverage/graph substrate rows), which never pass throughPreparedWrite(design §4 item 6).SourceId::LEGACY_PRE_0_8_20(_legacy:pre-0.8.20) — stamped by schema migration step 21 onto pre-0.8.20 rows that were stored with NULL provenance, so they become erasable (R-20-E8). Gated to UNGOVERNED rows only (logical_id IS NULL); a governed row keeps NULLsource_idand stayspurge-addressable by itslogical_id(TC-11 pin).
source_id must not be PII. It survives the erasure it authorises: the
excise_source audit row in operational_mutations records it verbatim, and
while 0.8.20 makes that audit row durable (design §2 defect D-A) the rule was
always that the handle you erase BY must not itself be the thing needing
erasure. Use an opaque document id, not an email address.
Implementations§
Source§impl SourceId
impl SourceId
Sourcepub const ENGINE_PREFIX: &'static str = "_engine:"
pub const ENGINE_PREFIX: &'static str = "_engine:"
Reserved prefix for engine-derived rows (design §4 item 6).
Sourcepub const LEGACY_PRE_0_8_20: &'static str = "_legacy:pre-0.8.20"
pub const LEGACY_PRE_0_8_20: &'static str = "_legacy:pre-0.8.20"
Reserved provenance stamped by schema migration step 21 onto pre-0.8.20 UNGOVERNED rows that were stored with NULL provenance (R-20-E8).
Sourcepub fn new(id: impl Into<String>) -> Result<Self, EngineError>
pub fn new(id: impl Into<String>) -> Result<Self, EngineError>
The single public constructor. Rejects the two ways a caller could express “effectively no provenance”:
- an empty or whitespace-only id — it names no source, and
excise_sourcealready refuses the empty string, so such a row would be un-erasable in practice; - an id in the engine’s reserved
_-prefixed namespace — a caller who could mint_legacy:pre-0.8.20could hide rows among the migration’s back-filled ones, or mint_engine:rows that read as engine substrate.
§Errors
EngineError::WriteValidation for either rejection above.
Sourcepub fn into_string(self) -> String
pub fn into_string(self) -> String
Consume into the owned on-disk text.