locqr/dev.md

6.8 KiB

Development environment

The LOCQR development environment is four components running locally, wired together by a single setup script. Running the script once produces a fully functional environment; re-running it on a new machine reproduces the same environment without regenerating any committed artifacts.


Components

Component Directory Default URL
Test website website/ https://test.locqr.dev:5173
Server (Java/Spring) server/ https://api.locqr.dev:3000
Web companion stub companion/ https://test.locqr.dev:5174
Browser extension extension/ Loaded unpacked in browser

All four must run simultaneously for end-to-end testing. Start order: server stub → extension (load unpacked) → test website → companion stub.


Setup script

scripts/setup-dev.sh (or setup-dev.js) — run once per machine. Idempotent: re-running it on an existing environment is safe and changes nothing if all committed artifacts are already in place.

What it does

1. mkcert

Checks that mkcert is installed; prints install instructions and exits if not. Installs the local CA (mkcert -install) if not already trusted. Exports the root CA certificate to dev/certs/rootCA.pem for sharing with other developers.

Generates TLS certificates if not already present:

  • dev/certs/test.locqr.dev.pem + test.locqr.dev-key.pem
  • dev/certs/api.locqr.dev.pem + api.locqr.dev-key.pem

The generated cert files are committed to the repository. On other machines the script skips generation and just installs the root CA, making the committed certs trusted.

2. Signing keypairs

Checks for committed keypair files. If present, reads them. If absent (first-ever run on a clean checkout), generates them and prints a reminder to commit the result.

  • ML-DSA-44 keypair → dev/keys/ml-dsa-44-public.b64 and dev/keys/ml-dsa-44-secret.b64
  • Ed25519 keypair → dev/keys/ed25519-public.b64 and dev/keys/ed25519-secret.b64

These are dev-only artifacts. The production server never commits key material; the dev stub does. The files are clearly namespaced under dev/ to prevent confusion with production secrets.

3. Pinned constants

Patches the public key constants into the source files that carry them:

Constant File
BACKEND_PUBLIC_KEY_B64 extension/src/constants.ts
ED25519_PUBLIC_KEY_B64 extension/src/constants.ts
ED25519_PUBKEY companion/src/constants.ts (web stub)
ED25519_PUBKEY mobile/src/main/java/.../Constants.kt (native, when it exists)

4. Test registration certificate

Issues a registration certificate for test.locqr.dev signed with the ML-DSA-44 dev key. Writes it to dev/certs/test-registration.b64. The server stub reads this file at startup and serves it from a known endpoint. The test website fetches it on load and passes it to locqr.init().

5. Extension identity

Checks that extension/key.pem is present. If missing (first-ever run), generates it and prints a reminder to commit it. This file pins the unpacked extension's ID; committing it ensures the ID is stable across machines and rebuilds. The test website and the extension manifest both use the ID derived from this key.

6. Environment files

Writes server/.env.dev with the dev signing key paths and local domain config for the non-JVM components (companion web stub, test website), and prints the equivalent as environment variable exports for the server, which reads configuration the Spring way (environment variables / application.yml, not a .env file). Not committed (listed in .gitignore), as paths may differ per machine.

ML_DSA_44_SECRET_KEY_PATH=../../dev/keys/ml-dsa-44-secret.b64
ED25519_SECRET_KEY_PATH=../../dev/keys/ed25519-secret.b64
TEST_DOMAIN=test.locqr.dev
API_PORT=3000

The server's application.yml reads the same four settings from environment variables of the same names, with dev-friendly defaults baked in so it runs locally without them being set explicitly (see server/claude.md).


Hardcoded defaults

These values are baked into the script and into the extension manifest. They can be overridden by passing arguments to the setup script but the defaults are what every developer uses unless there is a specific reason to change them.

Setting Default
Test site domain test.locqr.dev
API domain api.locqr.dev
Test site port 5173
API port 3000
Companion stub port 5174

These domains require a hosts file entry on each machine:

127.0.0.1  test.locqr.dev
127.0.0.1  api.locqr.dev

The setup script checks for these entries and prints instructions if they are missing. It does not modify the hosts file automatically.


Committed artifacts

These files are generated once and committed. They must not be regenerated unless there is a deliberate decision to rotate keys or change domains, as regeneration would invalidate every other developer's environment.

dev/
├── certs/
│   ├── rootCA.pem                    ← mkcert CA cert; import on new machines
│   ├── test.locqr.dev.pem
│   ├── test.locqr.dev-key.pem
│   ├── api.locqr.dev.pem
│   ├── api.locqr.dev-key.pem
│   └── test-registration.b64         ← ML-DSA-44 signed cert for test.locqr.dev
└── keys/
    ├── ml-dsa-44-public.b64
    ├── ml-dsa-44-secret.b64          ← dev only; never use in production
    ├── ed25519-public.b64
    └── ed25519-secret.b64            ← dev only; never use in production
extension/
└── key.pem                           ← pins the unpacked extension ID

Adding a new machine

  1. Install mkcert (OS package manager or https://github.com/FiloSottile/mkcert)
  2. Clone the repository (all committed artifacts are already present)
  3. Run scripts/setup-dev.sh — installs the root CA and writes .env.dev
  4. Add the hosts file entries for test.locqr.dev and api.locqr.dev
  5. Load the extension unpacked from extension/dist/ (or extension/ once built)
  6. cd companion && npm install && npm run build, then node scripts/serve-companion.js — companion/dist/ isn't committed, so this step is required before the companion stub is reachable at all (unlike website/, which has no build step of its own)

Rotating dev keys

If the signing keys must be rotated (e.g. after an accidental exposure):

  1. Delete dev/keys/* and dev/certs/test-registration.b64
  2. Run scripts/setup-dev.sh — regenerates keys, patches constants, reissues the registration cert
  3. Commit all changed files
  4. All other developers re-run scripts/setup-dev.sh on their next pull

The extension constants will change, requiring a rebuild of the extension. The extension ID is unaffected (it is derived from key.pem, which is not rotated).