From 8f9f1eaeb56349fd9558f1a510f3b3da84f6993a Mon Sep 17 00:00:00 2001 From: Glenn Gore Date: Sat, 29 Aug 2026 21:56:40 +0800 Subject: [PATCH] feat(demo-rp): a test website for the wallet's RP login paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both RP-login flows — REST SIOPv2 (`login`) and DIDComm (`loginDidcomm`) — could only be exercised against a real deployment, so in practice they were not exercised at all. One of them was broken for an unknown length of time as a direct result: the wallet sent a retired `authenticate` Type URI the control plane no longer routes, a site-initiated login failed after the user had already approved the consent prompt, and nothing surfaced it (#139). This is the missing half of that loop. A page that calls `window.vtaWallet` the way a relying party does, against a control plane of your choosing — the live one, or a `did-hosting-control` on localhost — and shows what came back. It asserts nothing. The point is to make the round-trip observable next to the wallet's own console, which is where the diagnosis actually happens; a harness that judged the result would just be a worse unit test with a network dependency. Kept out of `server.mjs` deliberately: that is a password-login target for the VTA's `vault/proxy-login` driver and shares nothing with this but a workspace. It also reports when no provider is present rather than leaving a dead button — content scripts are registered per granted origin and never reach a tab that is already open, so a first visit after granting needs a reload, and that is a confusing five minutes if the page says nothing. Signed-off-by: Glenn Gore --- packages/demo-rp/login-harness.mjs | 137 +++++++++++++++++++++++++++++ packages/demo-rp/package.json | 3 +- 2 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 packages/demo-rp/login-harness.mjs diff --git a/packages/demo-rp/login-harness.mjs b/packages/demo-rp/login-harness.mjs new file mode 100644 index 0000000..d9ec9dd --- /dev/null +++ b/packages/demo-rp/login-harness.mjs @@ -0,0 +1,137 @@ +// A test website for the RP login paths. +// +// The wallet's two RP-login flows — REST SIOPv2 (`login`) and DIDComm +// (`loginDidcomm`) — had no way to be exercised outside a real deployment, and +// one of them was broken for an unknown length of time because of it: the +// plugin sent a retired `authenticate` Type URI that the control plane no +// longer routes, and nothing noticed, because nothing drove the flow (plugin +// #139). +// +// This is the missing half of that loop. It serves a page that calls +// `window.vtaWallet` exactly as a real relying party would, against a control +// plane of your choosing — the live one, or a `did-hosting-control` on +// localhost — and shows what came back. It asserts nothing itself: the point is +// to make the round-trip observable, with the wallet's own console alongside. +// +// It is deliberately NOT part of `server.mjs`. That one is a password-login +// target for the VTA's `vault/proxy-login` driver and shares nothing with this +// but a workspace. +// +// node packages/demo-rp/login-harness.mjs +// +// Env: +// PORT 4041 +// HOST 127.0.0.1 +// CONTROL_DID the RP's control DID, prefilled into the form +// MEDIATOR_DID the RP's mediator DID, prefilled into the form +// BASE_URL the RP's REST base, for the SIOP path + +import { createServer } from "node:http"; + +const PORT = Number(process.env.PORT ?? 4041); +const HOST = process.env.HOST ?? "127.0.0.1"; +const CONTROL_DID = process.env.CONTROL_DID ?? ""; +const MEDIATOR_DID = process.env.MEDIATOR_DID ?? ""; +const BASE_URL = process.env.BASE_URL ?? ""; + +const page = ` + +RP login harness + +

RP login harness

+

Drives window.vtaWallet against a did-hosting control plane, the +way a relying party would. Keep the wallet's offscreen console open beside this.

+ +

Looking for the wallet…

+ + + + + + + + + + + + + +

Result

+
+ + +`; + +createServer((req, res) => { + if (req.url === "/favicon.ico") { + res.writeHead(204).end(); + return; + } + res.writeHead(200, { "content-type": "text/html; charset=utf-8" }).end(page); +}).listen(PORT, HOST, () => { + console.log(`[login-harness] http://${HOST}:${PORT}`); + if (!CONTROL_DID) { + console.log("[login-harness] set CONTROL_DID / MEDIATOR_DID / BASE_URL to prefill the form"); + } +}); diff --git a/packages/demo-rp/package.json b/packages/demo-rp/package.json index e15dbf8..3a6a95b 100644 --- a/packages/demo-rp/package.json +++ b/packages/demo-rp/package.json @@ -7,7 +7,8 @@ "main": "./server.mjs", "scripts": { "start": "node server.mjs", - "dev": "node --watch server.mjs" + "dev": "node --watch server.mjs", + "login-harness": "node login-harness.mjs" }, "engines": { "node": ">=24"