fix(asset-bridge): an empty catalog is an absent one on every family, not just the tree
Phase 7 found this on the tree family and fixed it there. It was inline in THREE
places: the body catalogue (phase 3), statics and land (phase 5), and the tree.
`expected != null` treats "" as a real fingerprint, so a caller that serialises a
missing value as an empty string has EVERY fetch refused -- with a sentence that
names no catalog at all ("catalog is now 8159778b"), which reads as a shard
fault rather than a caller one.
All three now go through one BridgeAssets.CatalogMismatch. Three copies of a
comparison are three chances for the next family to get it wrong in a way only a
differently-written client would ever reveal.
BridgeLeases keeps its own `expected != null` and is deliberately untouched:
there the value is a world property, where an empty string is a legitimate thing
to expect.
Verified against a live shard on a stock ServUO install, every family asked three
ways -- with a real catalog, with the field absent, and with an empty string:
cliloc.table walk 67,496 rows, 12 pages
body manifest / fetch 1,095 rows; ok all three ways
static + land fetch ok all three ways
static/land carry their OWN catalog art 66a112c1 vs body 323f284f
a cross-family catalog refused 422
tree manifest / fetch 141 files incl. BOTH empty ones, all three ways
empty files carry a VALID gzip member 2 rows gunzip to 0 bytes
a STALE catalog still refused on body, static and tree
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016wDDVXWMDz82WqE1i969r4
This commit is contained in:
@@ -421,12 +421,10 @@ namespace Server.Custom.Bridge
|
||||
List<TreeFile> files = Enumerate();
|
||||
string fingerprint = FingerprintOf(files);
|
||||
|
||||
// `IsNullOrEmpty`, not `!= null`. A caller that has no fingerprint to assert sends
|
||||
// the field absent OR empty depending on how its own client serialises a missing
|
||||
// value, and the two must mean the same thing — an empty string compared against a
|
||||
// real id refuses every fetch, with a sentence that names no catalog at all
|
||||
// ("catalog is now 8159778b"). Found by a probe that passed one.
|
||||
if (!String.IsNullOrEmpty(expected) && expected != fingerprint)
|
||||
// Shared with every other family on this plane, because an absent fingerprint and an
|
||||
// empty one have to mean the same thing here and there — see
|
||||
// `BridgeAssets.CatalogMismatch` for what treating them differently costs.
|
||||
if (BridgeAssets.CatalogMismatch(expected, fingerprint))
|
||||
{
|
||||
// The tree moved between the manifest and this fetch. The same refusal the
|
||||
// catalogue makes for a patched client, and for the same reason: these keys were
|
||||
|
||||
Reference in New Issue
Block a user