diff --git a/crates/aura-core/src/node.rs b/crates/aura-core/src/node.rs index 969f792..4b7f089 100644 --- a/crates/aura-core/src/node.rs +++ b/crates/aura-core/src/node.rs @@ -370,7 +370,8 @@ pub fn doc_gate(name: &str, doc: &str) -> Result<(), DocGateFault> { .map(|c| c.to_ascii_lowercase()) .collect() } - if norm(doc) == norm(name) { + let short_name = name.rsplit("::").next().unwrap_or(name); + if norm(doc) == norm(name) || norm(doc) == norm(short_name) { return Err(DocGateFault::RestatesName); } Ok(()) diff --git a/docs/design/contracts/c29-self-description.md b/docs/design/contracts/c29-self-description.md index 19d765f..3d7db7e 100644 --- a/docs/design/contracts/c29-self-description.md +++ b/docs/design/contracts/c29-self-description.md @@ -6,7 +6,9 @@ everything entering the content-addressed store describes itself; a refusal for a missing description names the entry, the field, and the rule. One shared deterministic gate — `doc_gate` in aura-core, importable by every seam per [C28](c28-stratification.md); it fails on an empty/whitespace doc -and on a doc that normalizes to the entry's own name +and on a doc that normalizes to the entry's own name — the full id or its +bare display segment after the last `::`, so a namespaced extension entry +cannot pass its short-name alibi (`DocGateFault::{Empty, RestatesName}`) — guards three seams: 1. **Compile/unit seam (engine-shipped).** `NodeSchema.doc` is a required