package seed import ( "crypto/sha256" "encoding/hex" "fmt" "gopkg.in/yaml.v3" ) // signaturemap.go: the ENVELOPE of the owner signature map. // // The map is the one seam artifact another side reads that carried no identity at all — no version and // no way to tell two maps apart without diffing them (17-seam-inbound-law п.3 requires both of every // document that crosses the seam). The body stays the plain seed schema so a row can still be moved // into the owner's mined-delta file by copy-paste; the envelope is two keys on top of it. // SignatureMapVersion versions the SHAPE of the signature map. It is not a snapshot input: the map is // evidence for the owner, never a paid byte. const SignatureMapVersion = "tm-signature-map-v1" // SignatureMap is a whole signature-map document: the envelope plus the inlined seed schema. type SignatureMap struct { Version string `yaml:"map_version"` // ID identifies the map's CONTENT — the sha256 of the rendered body (SignatureMapID). Two maps with // one id offer the same terms, so a consumer can tell "the run re-wrote the same map" from "the run // proposes something else" without diffing documents. It is an identity, not an integrity proof: // recomputing it requires this engine's own renderer. ID string `yaml:"map_id"` File `yaml:",inline"` } // DecodeSignatureMap parses a signature-map document, strict like the other decoders of this schema. // A map written before the envelope existed carries neither key and decodes with both empty — a book // mid-signature across the upgrade must not lose the map it stopped on. func DecodeSignatureMap(raw []byte) (SignatureMap, error) { return decodeStrict[SignatureMap](raw) } // SignatureMapID derives the content identity the envelope carries. Deterministic: yaml.Marshal of the // same document yields the same bytes. func SignatureMapID(f File) (string, error) { b, err := yaml.Marshal(f) if err != nil { return "", fmt.Errorf("seed: marshal the signature-map body for its id: %w", err) } sum := sha256.Sum256(b) return hex.EncodeToString(sum[:]), nil }