# Client registration and controlled installation runbook ## Lifecycle 1. An administrator creates one legal registration. 2. One or more tenant accounts are attached to that registration. 3. A time-bound license defines package, user, and installation limits. 4. An activation key is generated, stored only as a BCrypt hash, and emailed. The recipient is always the primary contact email stored on the client registration; API callers cannot redirect the key to another address. 5. The Technobee Service Installer blocks unless Docker, Docker Engine, and Compose v2 work. 6. The installer validates the key, generates an RSA-3072 installation key, and registers the installation in one database transaction. 7. The plaintext activation key is neither returned again nor written locally. 8. Runtime token issuance requires an active registration, tenant, license, and installation. 9. An administrator can decommission or revoke an old installation before activating its replacement. ## Database migration Apply `004_client_registration_activation.sql` after identity migrations 001–003. The migration is additive and idempotent. Always back up production before applying it and validate the constraints on a staging copy first. ## Required cloud configuration - Database and Redis variables already used by the cloud service - JWT and assertion encryption key locations - `CYGNUS_MAIL_HOST`, `CYGNUS_MAIL_PORT`, `CYGNUS_MAIL_USERNAME`, `CYGNUS_MAIL_PASSWORD`, and `CYGNUS_REGISTRATION_EMAIL_FROM` - Optional `CYGNUS_ACTIVATION_MAX_ATTEMPTS` and `CYGNUS_ACTIVATION_RATE_WINDOW` The cloud service can start without SMTP, but the activation-key email endpoint will reject delivery until SMTP is configured. ## Administrative API order All administration endpoints require an access token with `cygnus.admin` scope. 1. `POST /api/v1/admin/client-registrations` 2. `POST /api/v1/admin/client-registrations/{registrationId}/tenants` 3. `POST /api/v1/admin/tenants/{tenantId}/licenses` 4. `POST /api/v1/admin/tenants/{tenantId}/licenses/{licenseId}/activation-key` The activation-key request contains only `expiresAt`. The cloud service reads the delivery address from `client_registration_details.primary_contact_email`. For replacements: - `POST /api/v1/admin/tenants/{tenantId}/installations/{id}/decommission` - `POST /api/v1/admin/tenants/{tenantId}/installations/{id}/revoke` Both require a non-empty reason, invalidate the cached installation, increment its security version, and write an audit event. ## Running the Technobee Service Installer ```bash mvn -pl cygnus-installer -am package TECHNOBEE_INSTALLER_CONFIG=cygnus-installer/config/cygnus-installer.ini \ java -jar cygnus-installer/target/technobee-service-installer-1.0.0-SNAPSHOT.jar ``` This opens the Swing installation wizard. Add `--cli` when running on a headless server or when the terminal workflow is preferred. Select Matrix or Cygnus using the INI `product` property. The INI also supplies the cloud URL, installation API base path, environment, output directory, and the product profile. No cloud URL, route, service name, or filesystem path is compiled into the installer workflow. The installer asks for the Matrix or Cygnus Docker image and writes it to `.env` using the selected profile's image variable. After a successful run, review `compose.yml` and `.env`, then start with `docker compose up -d`. It also asks for the registry host, username, and password and performs `docker login --password-stdin`. The password is not stored in the generated installation package. The installer asks for the output directory. Press Enter to accept the INI `output_directory`. It creates: - `compose.yml` - `.env` - `config/installation.yml` - `config/machine-assertion.jwt` - `config/keys/client-signing-private.pem` - `config/keys/client-signing-public.pem` The generated private key must remain readable only by the service account. Never email or copy it to the cloud. The encrypted machine assertion and private key remain on premises; the cloud receives and stores only the public key. The generated service configuration records the returned client ID, installation ID/code, cloud URL, assertion path, and key paths. The installer does not connect directly to PostgreSQL or Redis. Registration, license enforcement, and installation identity remain the selected cloud service's responsibility. ## Operational checks - Alert on repeated HTTP 429 activation responses. - Alert on failed SMTP delivery and keep activation-key issue events auditable. - Review installations that have stale `last_seen_at`. - Revoke suspected keys/installations immediately. - Do not increase `max_installations` to recover a failed server. Decommission the old installation with a reason, then activate the replacement. - Back up registration, tenant, license, installation, activation-key, session, and installation-audit tables together.