locqr/website/claude.md

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_connectable origins 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.