From 80050cd2a861b7a350caaa7a4b1ffa4e91687881 Mon Sep 17 00:00:00 2001 From: Worph Date: Sun, 26 Jul 2026 18:49:27 +0200 Subject: [PATCH] update vector with card locator --- internal/cid/cid-rank-vectors.json | 8 +++++++- internal/cid/rank.go | 12 ++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/internal/cid/cid-rank-vectors.json b/internal/cid/cid-rank-vectors.json index 84de7f4..324a992 100644 --- a/internal/cid/cid-rank-vectors.json +++ b/internal/cid/cid-rank-vectors.json @@ -22,7 +22,7 @@ "25": "nzb-posting - content-derived (Message-ID set digest), but not itself fetchable", "20": "BitTorrent infohashes - swarm interop", "10": "midhash256 - the record address", - "5": "opaque locators (nzb-release, url) - never outrank a real digest", + "5": "opaque locators (nzb-release, url, card) - never outrank a real digest", "0": "weak/unknown digests, unparseable input" }, "tieBreak": "lexicographically smaller cid wins", @@ -110,6 +110,12 @@ "rank": 5, "note": "codec 0x1006 + IDENTITY multihash 0x00. Same tier/reasoning as nzb-release." }, + { + "name": "card-locator", + "cid": "bagdsaaanar2g2zdcor3duojvgq3ts", + "rank": 5, + "note": "codec 0x1007 + IDENTITY multihash 0x00, digest = varint(len(source)) || source || id — here (\"tmdb\",\"tv:95479\"). Same codec-slot rule as nzb-release/url: match on the CODEC, never the mh. The limit case of the family — the only CID in MetaMesh with NO bytes behind it anywhere, ever: it addresses a *work* (a series, a film), not a file, so the byte path 404s by design and bitswap never offers it (seeding is gated on sha2-256). Tier 5 is load-bearing for the planned cross-source merge: one card record may carry BOTH a TMDB and a MyAnimeList locator, and if a real card body is ever added (see card-tier-search.md §4.3) its sha2-256 must win the canonical election over both locators without any addressing change. Ranking it 0 instead would still lose to a digest, but would put the implementations back out of agreement — which is the exact failure this fixture exists to prevent." + }, { "name": "sha1", "cid": "baeircff3eqvxxaqqot2lt242stkdtk3gq4c2vra", diff --git a/internal/cid/rank.go b/internal/cid/rank.go index 6dfe90b..93c4cb8 100644 --- a/internal/cid/rank.go +++ b/internal/cid/rank.go @@ -49,6 +49,14 @@ const ( // these — matching on mh would see 0x00 and rank them 0. CodeNzbRelease = 0x1005 // custom — self-describing Newznab release locator CodeURL = 0x1006 // custom — identity-multihash CID wrapping an http(s) URL + // CodeCard is the limit case of the family: the only CID with NO bytes + // behind it anywhere, ever. It addresses a *work* (a series, a film) via + // varint(len(source))‖source‖id — ("tmdb","tv:95479") — so `/api/file/{cid}` + // correctly 404s and bitswap never offers it. Ranking it here (rather than + // letting it fall to RankUnknown) is what makes the planned "one card, two + // CIDs" cross-source merge safe: a TMDB and a MyAnimeList locator can sit on + // one record, and a real digest added later still wins the election. + CodeCard = 0x1007 // custom — identity-multihash CID wrapping a card (work) id // CodeNzbPosting is the INVERSE trap of the two above: its multihash is a // REAL sha2-256 digest (over the normalised, sorted article Message-ID @@ -134,7 +142,7 @@ func Decode(cidStr string) (codec uint64, mhCode uint64, err error) { // swarm interop, not strength. // - midhash256 is the floor among real *digests*: internally meaningful, // externally invisible. -// - opaque locators (nzb-release, url) sit BELOW midhash. They are not +// - opaque locators (nzb-release, url, card) sit BELOW midhash. They are not // content-derived — two URLs to the same bytes yield two different locator // CIDs — so a locator must never displace a real digest as the identity a // record is advertised under. Tier 5 means a locator wins the election only @@ -157,7 +165,7 @@ func Rank(cidStr string) int { } // Opaque locators. Codec-only: their multihash is identity (0x00), so // there is nothing to match on the mh side. - if codec == CodeNzbRelease || codec == CodeURL { + if codec == CodeNzbRelease || codec == CodeURL || codec == CodeCard { return RankLocator } // nzb-posting: codec-only, checked BEFORE the mh switch below — its