acdp_types/anchor.rs
1//! Typed external anchors — `acdp-common.schema.json` (RFC-ACDP-0016, 0.5.0).
2//!
3//! An anchor is a producer-signed, content-addressed reference from an
4//! ACDP body to a non-ACDP external artifact (a commitment record, a
5//! sealed decision, anything identified by its own digest). It is part
6//! of ProducerContent (RFC-ACDP-0001 §5.7) — included in the
7//! `content_hash` preimage exactly like any other producer-controlled
8//! field, with no special-casing in the hash pipeline.
9//!
10//! Anchors are opaque to core verification (RFC-ACDP-0016 §6): a
11//! verifier that does not recognize an anchor's `scheme` MUST ignore it
12//! for resolution purposes while still treating it as signed content.
13//! `uri` is an advisory locator hint only — it MUST NOT be dereferenced
14//! by any ACDP-level verification code path; the binding is
15//! `content_hash`, never `uri`.
16
17use acdp_primitives::primitives::ContentHash;
18use serde::{Deserialize, Serialize};
19
20/// One entry in `Body::anchors` / `PublishRequest::anchors`.
21///
22/// `additionalProperties: true` per RFC-ACDP-0016 §4: a future
23/// anchor-scheme-specific field is automatically signed under the
24/// RFC-ACDP-0001 §5.7 unknown-field rule without a schema update, so
25/// unknown keys are preserved in [`Self::extensions`] rather than
26/// rejected.
27#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
28pub struct AnchorEntry {
29 /// Dotted-namespace identifier of the external artifact's system
30 /// (e.g. `macp.commitment`), pattern
31 /// `^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)+$` (the same structured-locator
32 /// scheme grammar as RFC-ACDP-0002 §6.2). Opaque to core
33 /// verification — an unrecognized scheme has zero effect on the
34 /// body's ACDP-level verification verdict (RFC-ACDP-0016 §6).
35 pub scheme: String,
36 /// The external artifact's own content digest
37 /// (`"sha256:" + 64 lowercase hex`) — an independent digest,
38 /// unrelated to the body's own `content_hash` field. This is the
39 /// anchor's genesis identity (RFC-ACDP-0016 §4, §7).
40 pub content_hash: ContentHash,
41 /// Optional locator hint for resolving the artifact. Advisory
42 /// only: the binding is `content_hash`, not `uri`. MUST NOT be
43 /// dereferenced by any ACDP-level verification code path
44 /// (RFC-ACDP-0016 §6, NORMATIVE) — no code in this crate reads
45 /// this field for anything but (de)serialization.
46 #[serde(default, skip_serializing_if = "Option::is_none")]
47 pub uri: Option<String>,
48 /// Forward-compatible passthrough for anchor-scheme-specific
49 /// fields not yet known to this crate (RFC-ACDP-0016 §4's
50 /// `additionalProperties: true`).
51 #[serde(flatten)]
52 pub extensions: serde_json::Map<String, serde_json::Value>,
53}