u/s3/ip/h/p for the apex of a BNS name no longer require a chain
transaction to change. They live alongside the subdomain hosts and the
apex DNS block in the owner-signed _records.json on Sia, verified by
the gateway against the current NFT holder. The chain keeps the NFT
identity and one `s3` pointer that anchors the manifest file; every
other edit is a wallet signature with zero satoshis spent.
The trust boundary is unchanged — a signature verified against the
on-chain owner is cryptographically equivalent to a chain update, and
the manifest's seq monotonicity + name-field binding keep replay out.
Legacy names and v1/v2 manifests stay valid; the apex merge is a
no-op when nothing declares it.
Argus:
- manifest.js: SUPPORTED_VERSIONS gains 3; new validateApex and
effectiveRecords; verifyManifest validates apex and refuses it in v<3
- registrar.js: signRecordsManifest accepts v=3
- public-gateway.mjs: serve() loads manifestFor unconditionally and
merges chain + apex before pickRecord; /api/dns/<name> response adds
the verified apex block for clients to merge on their side; a
successful /api/records POST busts the serve cache so a swap takes
effect immediately rather than at the 60 s TTL
- test/manifest-apex.test.mjs: 21 tests — validator shape rules,
merge semantics, v3 round-trip, cross-version refusal, legacy still
verifies, replay refused
Ariadne daemon:
- cache carries apex alongside the DNS block; mergedRecords(entry, key)
is the one place the precedence lives. HTTP app and the DNS-answer
bcnrAnswerFor both read merged records, so an apex ip swap changes
what the OS gets without waiting on a chain update
Ariadne mobile:
- Entry and DnsCached carry apex; static Bns.mergedRecords(entry) is
the Java mirror of effectiveRecords; BchFetcher.serve picks from
the merged view
Hermes.x is the first candidate: chain has `s3: bns/hermes/` + a
redirect `u`, both can collapse to one signed-manifest edit once the
owner publishes their first v3.