model: rename `Ents-Ref` trailer to `Advance-ref`
commit
1ac01b9model: rename `Ents-Ref` trailer to `Advance-ref`
This fits Git trailer naming conventions more closely, and also has the benefit of implying one of our invariants: commits to meta refs MUST be fast-forward only.
Reviews
No reviews of this commit yet — record a verdict below.
Start a review
docs/abstractions.adoc
@@ -39,7 +39,7 @@
Trees stay pure struct representations — no version marker entry.
Ref-level metadata that is not entity content belongs in commit-message trailers, because the commit is already the storage unit.
-Two trailers are reserved: `Schema-Version:` for explicit encoding detection if it is ever needed, and `Ents-Ref:` for refname binding (see 4).
+Two trailers are reserved: `Schema-Version:` for explicit encoding detection if it is ever needed, and `Advance-ref:` for refname binding (see 4).
Versioning or binding in the tree would pollute both the schema and the merge path.
*Tip invariant:* the tip of a meta-ref is always readable by the binary that owns the entity type; a non-owning binary treats the tree as opaque and degrades to generic display (`git store show`); history is archival.
@@ -67,7 +67,7 @@
A commit signature proves authorship; it does not prove placement.
The difference is recovered explicitly:
-* *Refname binding* — an `Ents-Ref:` trailer names the ref the commit was authored for, checked at verification; without it, a signed commit could be replayed as the tip of a different meta-ref.
+* *Refname binding* — an `Advance-ref:` trailer names the ref the commit was authored for, checked at verification; without it, a signed commit could be replayed as the tip of a different meta-ref.
* *Anti-replay* — meta-refs advance fast-forward-only in the DAG sense (the new tip descends from the old), enforced by atomic CAS on the ref store; the parent hash is the freshness binding, so no nonce is needed.
*Tip invariant:* the tip of a meta-ref is signed by a member authorized for that refname.
@@ -91,7 +91,7 @@
[arabic]
. The new tip is signed by a member authorized for this refname.
-. The `Ents-Ref:` trailer matches the refname.
+. The `Advance-ref:` trailer matches the refname.
. The new tip descends from the old tip.
. The update commits via atomic CAS.
docs/design.adoc
@@ -27,7 +27,7 @@
Mutations are author-signed commits, not push certificates.
A push cert signs a transition and evaporates at the transport layer; a commit signature replicates with the repo and verifies in every clone, forever.
Verification evidence is repository state, like everything else.
-Refname binding lives in an `Ents-Ref:` trailer; anti-replay is fast-forward-plus-CAS, with the parent hash as the freshness binding.
+Refname binding lives in an `Advance-ref:` trailer; anti-replay is fast-forward-plus-CAS, with the parent hash as the freshness binding.
Because writing and verifying are separated, local is genuinely offline-first: the local store accepts any write and the gate merely annotates.
You can author while unenrolled, work against an unfetched member list, and accumulate meta-refs the canonical store would reject.
docs/faq.adoc
@@ -150,7 +150,7 @@
Revocation is a state, never a deletion — deleting the entity would merely make their old signatures unverifiable, which is the opposite of what an audit needs.
*I want to verify that nobody tampered with forge state.*
-Every meta-ref tip must be signed by a member authorized for that refname, bound to the ref by an `Ents-Ref:` trailer, descending from the previous tip.
+Every meta-ref tip must be signed by a member authorized for that refname, bound to the ref by an `Advance-ref:` trailer, descending from the previous tip.
`git ents members check` verifies this from any clone, with no server's cooperation.
*I want to know who did what, and when.*
docs/spec/overview.adoc
@@ -67,7 +67,7 @@
Every meta-ref mutation is an author-signed commit whose signature
replicates with the repository and verifies offline in any clone.
-A signature proves authorship, not placement, so an `Ents-Ref:` trailer
+A signature proves authorship, not placement, so an `Advance-ref:` trailer
binds the commit to the ref it was authored for, and adopting someone
else's commit onto a canonical ref is always a merge, never a
cherry-pick, so the author's signature survives intact in ancestry.
@@ -75,7 +75,7 @@
=== 5. Gate
Verification is a pure function over ref-store reads — is the new tip
-signed by a member authorized for this refname, does its `Ents-Ref:`
+signed by a member authorized for this refname, does its `Advance-ref:`
trailer match, does it descend from the old tip, does the update commit
via atomic CAS — evaluated identically at three call sites: hosted CAS
(mandatory, failure aborts the write), local UI verdict (advisory), and
crates/ents-model/src/trailer.rs
@@ -4,7 +4,7 @@
//! commit's trailers, never inside the tree (`meta-ref.typed-tree`) — a
//! comment's author and timestamp are the running example
//! (`model.comment`). Two trailers are reserved: `Schema-Version:`, for
-//! explicit encoding detection if it is ever needed, and `Ents-Ref:`, which
+//! explicit encoding detection if it is ever needed, and `Advance-ref:`, which
//! `ents-gate` (phase 3) compares against the refname actually being
//! updated to bind a signature to its placement.
//!
@@ -17,7 +17,7 @@
/// The reserved trailer key binding a mutation commit to the refname it was
/// authored for.
-pub const ENTS_REF: &str = "Ents-Ref";
+pub const ADVANCE_REF: &str = "Advance-ref";
/// The reserved trailer key for explicit encoding detection.
pub const SCHEMA_VERSION: &str = "Schema-Version";
@@ -25,14 +25,14 @@
/// The two reserved trailers read from (or written to) a mutation commit's
/// message, per `meta-ref.trailers`.
///
-/// A malformed `Ents-Ref:` value — one that fails gitoxide's own refname
+/// A malformed `Advance-ref:` value — one that fails gitoxide's own refname
/// validation — parses as absent rather than as an error: a commit message
/// is untrusted input, and rejecting a bad binding is `ents-gate`'s job
/// (`gate.tip-signed`), not this type's.
// @relation(meta-ref.trailers, scope=file)
#[derive(Debug, Clone, Default, PartialEq, Eq)]
pub struct Trailers {
- /// The refname the commit was authored for, if the `Ents-Ref:` trailer
+ /// The refname the commit was authored for, if the `Advance-ref:` trailer
/// is present and well-formed.
pub ents_ref: Option<FullName>,
/// The raw `Schema-Version:` value, if present.
@@ -47,7 +47,7 @@
/// ```
/// use ents_model::trailer::Trailers;
///
- /// let message = b"Enroll jdc\n\nEnts-Ref: refs/meta/member/jdc\n";
+ /// let message = b"Enroll jdc\n\nAdvance-ref: refs/meta/member/jdc\n";
/// let trailers = Trailers::parse(message);
/// assert_eq!(trailers.ents_ref.expect("present").as_bstr(), "refs/meta/member/jdc");
/// ```
@@ -59,7 +59,7 @@
let mut trailers = Self::default();
for trailer in body.trailers() {
- if trailer.token.eq_ignore_ascii_case(ENTS_REF.as_bytes()) {
+ if trailer.token.eq_ignore_ascii_case(ADVANCE_REF.as_bytes()) {
if let Ok(name) = FullName::try_from(trailer.value.to_string()) {
trailers.ents_ref = Some(name);
}
@@ -87,13 +87,13 @@
/// ents_ref: Some(name),
/// schema_version: None,
/// };
- /// assert_eq!(trailers.render(), "Ents-Ref: refs/meta/member/jdc\n");
+ /// assert_eq!(trailers.render(), "Advance-ref: refs/meta/member/jdc\n");
/// ```
#[must_use]
pub fn render(&self) -> String {
let mut out = String::new();
if let Some(name) = &self.ents_ref {
- out.push_str(ENTS_REF);
+ out.push_str(ADVANCE_REF);
out.push_str(": ");
out.push_str(&name.as_bstr().to_string());
out.push('\n');
@@ -118,12 +118,12 @@
#[rstest]
#[case::both(
- b"Subject\n\nBody line.\n\nEnts-Ref: refs/meta/member/jdc\nSchema-Version: 1\n",
+ b"Subject\n\nBody line.\n\nAdvance-ref: refs/meta/member/jdc\nSchema-Version: 1\n",
Some("refs/meta/member/jdc"),
Some("1")
)]
#[case::ents_ref_only(
- b"Subject\n\nEnts-Ref: refs/meta/issues/42\n",
+ b"Subject\n\nAdvance-ref: refs/meta/issues/42\n",
Some("refs/meta/issues/42"),
None
)]
@@ -133,7 +133,7 @@
Some("refs/meta/comments/1"),
None
)]
- #[case::malformed_ref_is_absent(b"Subject\n\nEnts-Ref: not a refname\n", None, None)]
+ #[case::malformed_ref_is_absent(b"Subject\n\nAdvance-ref: not a refname\n", None, None)]
// @relation(meta-ref.trailers, scope=function, role=Verifies)
fn parse_reads_reserved_trailers_only(
#[case] message: &[u8],