4.3 KiB
Website (Test)
The test website is a minimal HTML page that exercises the full LOCQR session flow end-to-end. It is a permanent development artifact — not a prototype of a real product — and will not be replaced by a production website. Its only purpose is to provide a realistic SDK integration target for testing the extension, the web companion stub, and the Node server stub together.
What it does
- Initialises the SDK with the test domain's registration certificate
- Presents a simple login form
- Calls
locqr.requestCredential()on form focus or button press - Displays the delivered credential to confirm end-to-end delivery worked
- Exercises error paths — unregistered domain, invalid cert, session failure — to confirm the extension's error states and UI behave correctly
It is intentionally bare. No styling beyond readability; no application logic beyond triggering and displaying LOCQR flows.
A visible event log panel is a core part of the test page, not an optional addition. Every SDK event, Promise resolution, rejection, and error — including the full payload — is appended to the log in real time with a timestamp. The log is the primary debugging tool for the development environment; it should capture everything the SDK surfaces, including security-class errors and their reasons.
Development environment
The test site is one part of a four-piece local development environment:
| Component | Implementation |
|---|---|
| Website | This test site |
| Extension | The real extension, loaded unpacked |
| Backend | Node.js server stub |
| Companion | Web companion stub (mobile browser or desktop) |
Running all four together constitutes a complete local LOCQR environment.
Start order, environment variables, shared configuration, and the one-time
setup script are documented in ../dev.md.
HTTPS requirement
externally_connectable requires a secure context. Service workers require
HTTPS. The test site must be served over HTTPS even in local development.
Options:
mkcert— creates a locally-trusted CA and issues certs for custom local domains. Recommended: clean, no browser warnings, no external dependency.- Self-signed cert with manual trust — works but requires trusting the cert in each browser profile used for testing.
- Tunnel (ngrok, Cloudflare Tunnel) — provides a real HTTPS domain; useful for testing on physical mobile devices for the companion stub. Adds an external dependency.
Local domain
The registration certificate is domain-scoped. localhost is unsuitable —
it cannot hold a meaningful domain cert and is treated specially by browsers.
A custom local domain (e.g. test.locqr.dev) with a hosts file entry and a
mkcert-issued cert is the recommended approach.
The same domain must appear in:
- The registration certificate issued by the Node server stub at startup
- The
externally_connectableorigins list in the extension manifest - The SDK
locqr.init({ cert })call in the test page
Extension ID in development
The unpacked extension has a different ID from the Store-published version. The test site initialises the SDK with the dev extension ID:
locqr.init({
cert: TEST_CERT,
extensionId: DEV_EXTENSION_ID
});
DEV_EXTENSION_ID is stable as long as the same key.pem is used for the
unpacked extension. Pinning key.pem in the repo (non-secret for dev builds)
keeps it consistent across machines.
SSL certificates for stubs
The Node server stub also needs HTTPS — the extension and companion both
communicate with it over HTTPS. A second mkcert cert for the local server
domain (e.g. api.locqr.dev) covers this. The companion web stub, if opened
in a mobile browser over a tunnel, needs the tunnel's HTTPS certificate.
A shared mkcert setup script that issues certs for all local domains and
places them where each stub expects them would reduce per-developer setup
friction. Deferred until the dev environment stabilises.
Registration certificate
The test domain's ML-DSA-44 registration certificate is generated by the Node server stub at startup (using its pre-generated signing key) and either:
- Written to a known location for the test site to copy-paste into its
locqr.init()call, or - Served by the stub at a known endpoint so the test site can fetch it on load
The exact mechanism is deferred; either works for development purposes.