Aller au contenu principal

ADR-031 — Activation Code Contract

1. Context

Layer 3 user activation (ADR-030) requires a secure, self-serve path from the console welcome page to the browser extension without manual copy-paste when possible. Operators also need a stable API contract for issuing and redeeming short-lived activation codes that map to extension enrollment JWTs.

Prior flows relied on enrollment JWTs pasted manually or backend URLs typed by users. That increases support burden and misconfiguration risk (wrong API host). A dedicated activation-code flow with server-resolved backend_url and single-use redeem closes that gap.

2. Decision

2.1 Code format

Activation codes use the prefix noxys- followed by environment segment and random material:

noxys-{env}-XXXXXXXX

Examples: noxys-prod-A1B2C3D4, noxys-staging-EFGH5678. Only codes matching this prefix are accepted by the API and extension deep-link parser.

2.2 API endpoints

MethodPathAuthPurpose
GET/api/v1/me/activation-codeBearer (user session)Get or create the caller's activation code + expires_at
POST/api/v1/activation/redeemPublic (rate-limited)Redeem code (+ optional device_id) → enrollment JWT

GET /me/activation-code returns ActivationCodeResponse:

{ "code": "noxys-prod-…", "expires_at": "2026-06-06T12:00:00Z" }

POST /activation/redeem accepts RedeemActivationRequest:

{ "code": "noxys-prod-…", "device_id": "optional-stable-id" }

and returns RedeemActivationResponse:

{
"token": "<extension_enrollment_jwt>",
"expires_at": "…",
"backend_url": "https://api.noxys.cloud",
"tenant_id": "…"
}

backend_url is server-resolved from the incoming request host / deployment config — clients must not invent API hosts during redeem. Each code is single-use; a second redeem returns 410 Gone.

When the Chrome extension ID is configured in the console (VITE_NOXYS_CHROME_EXTENSION_ID), the welcome page links and QR encode:

chrome-extension://<extension_id>/onboarding.html?code=<url-encoded-code>

The extension onboarding page (onboarding.html) parses ?code= via parseActivationCodeFromUrl(), accepts only noxys-* values, mounts the wizard at the activate step, and pre-fills #ob-activation-code.

Without a configured extension ID, the console falls back to displaying the raw code and QR (copy-paste flow).

2.4 Enrollment chain

  1. User completes Layer 2 join → lands on /welcome.
  2. Console fetches GET /me/activation-code.
  3. User opens deep link or pastes code in extension activate step.
  4. Extension calls POST /activation/redeem → receives JWT + backend_url.
  5. Extension enrolls via existing device enrollment path (ADR device handlers).
  • ADR-030 — three-layer lifecycle; activation codes implement Layer 3.
  • Device enrollment JWT exchange remains unchanged (POST /auth/enroll).