From 408f96562980556f1d8a59b0674103432fa771f4 Mon Sep 17 00:00:00 2001 From: Local Dev Date: Mon, 7 Sep 2026 00:18:07 +0200 Subject: [PATCH] =?UTF-8?q?feat(bns):=20'p'=20reverse-proxy=20record=20typ?= =?UTF-8?q?e=20=E2=80=94=20mirror=20an=20upstream=20URL=20under=20a=20BNS?= =?UTF-8?q?=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New record kind alongside h / s3 / ip / u: `p` reverse-proxies the request to a full upstream URL while keeping the BNS host in the address bar. Unlike `ip` (which pins the upstream to a raw IP + on-chain TLS fingerprint), `p` uses the upstream's own DNS + public CA cert and sends `Host:` of the upstream so vhost-based origins answer correctly. Argus (record-picker.js): - Placed AFTER `ip` in the apex chain: a name carrying both keeps its existing pinned-IP behavior; names with only `p` get honored instead of falling through to `u` and 302-ing away. - Not applied to subdomain inheritance — `p` is single-URL by intent, and inheriting through a subdomain would silently mangle the target. Theseus (main.js serveBns): - Fetches the upstream (path prefix from the `p` URL is preserved) and returns the response body/status/content-type verbatim. Provenance label "mirror" appears in the source badge. Tests: record-picker.test.mjs covers `p`-only, `p`+ip precedence, and the subdomain-suppression rule. --- src/lib/record-picker.js | 13 ++++++++++++- test/record-picker.test.mjs | 38 +++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/lib/record-picker.js b/src/lib/record-picker.js index e2f6260..1f9071b 100644 --- a/src/lib/record-picker.js +++ b/src/lib/record-picker.js @@ -26,11 +26,21 @@ /** * Decide which record wins. + * + * `p` semantics — added 2026-08-31. "Reverse-proxy this name to the URL in + * the `p` record; address bar stays on the BNS name." Complementary to `ip` + * (which pins the upstream to a raw IP + on-chain TLS fingerprint): `p` uses + * the upstream's own DNS + public CA cert. Placed AFTER `ip` in the apex chain + * so a name carrying both keeps its pre-existing pinned-IP behavior; names + * that ONLY carry `p` get honored instead of falling through to `u` and 302-ing + * away. Not applied to subdomain inheritance — `p` is single-URL by intent, so + * inheriting it through a subdomain query would silently mangle the target. + * * @param {object} records `entry.records` from the resolver * @param {object} opts * @param {boolean} opts.isSubdomain true iff the requested name has labels * above the registered `