# Licensing TunnelCAD is distributed under a modular license. The license state is stored locally in `license.json` inside the application's per-user config directory: - **Windows:** `%APPDATA%\TunnelCAD\license.json` - **Linux:** `~/.config/TunnelCAD/license.json` The application ships with a bundled **IQ License** engine that supports three operating modes: **Basic** (free feature set), **Trial** (time-limited access to trial-enabled modules) and **Activated** (serial-bound, module-specific entitlements). The dialog surfacing these states is available from **Home → Help → License** (ribbon) or **Help → License Manager...** (menu). ## License Manager dialog The dialog is divided into three blocks: 1. **Status strip (top)** — Mode, expiry date (if any), and a short machine-ID fingerprint for identification with your reseller. Status colouring: - Green — Activated; - Olive — Trial with days remaining; - Red — Expired; - Default — Basic. 2. **Modules list (middle)** — One line per module registered by the application (Sections, Point Cloud, Analytics). Each line shows the module's active/inactive state and, if the module is module-time-limited, its individual expiry date. 3. **Edit panel (bottom)** — Server URL, Serial Key, and action buttons. ### Server URL The **Server URL** field shows the base URL the engine uses to reach the activation server (for example `https://license.iqsoft.gr/api/v1` or a self-hosted endpoint). Editing the field is non-destructive — the new value is committed to the in-memory config when the user clicks **Activate**, **Deactivate** or **Close**. The URL is persisted into the application's settings file on dialog close so that the next run of TunnelCAD uses the new endpoint without re-prompting. Typical reasons to edit the URL: - Switching between production and staging servers during evaluation. - Pointing at a self-hosted activation server on an internal network. - Working against a different deployment region. ### Serial Key Paste your serial (the letter case is normalised automatically) and click **Activate**. The engine sends an activation request to `/activate` carrying the serial, the product ID and the machine fingerprint. On success the reply is written to `license.json`, the status strip flips to Activated, and the dialog refreshes its module list. ### Buttons | Button | Behaviour | |--------|-----------| | **Activate** | Commits the URL edit, then calls `/activate` on the server. Requires a serial in the Serial Key field. Shows a message dialog with the result. | | **Deactivate** | Standard online deactivation. Commits the URL, confirms with the user, then calls `/deactivate`. On success the license file is removed and the server frees up the activation slot. This is the preferred path when the machine is online. | | **Clear License** | **Local-only wipe.** Removes `license.json` from this PC **without** contacting the activation server. Use this when the server is not reachable (machine offline, endpoint decommissioned, server migration). The server will still count this machine as activated until it is contacted again, so the regular Deactivate path is preferable whenever possible. The button fires only after a confirmation dialog that warns about the side effect. | | **Close** | Persists the edited URL and dismisses the dialog. | ```{warning} Clearing a license locally does **not** free up the activation slot on the server. If you later want to re-activate the same serial on a different machine, you may need to contact your reseller to manually release the slot. ``` ## Troubleshooting **"Serial format invalid"** — The serial-key format validator rejects the key shape before any network round-trip. Re-check the serial on your license certificate; serials are hyphen-grouped and case-insensitive. **"Activation failed: cannot reach server"** — The URL is wrong or the network cannot reach it. Verify the Server URL, then check connectivity with a browser or `curl` to `/health` (or the equivalent health endpoint your server exposes). **"Already activated on another machine"** — The serial is bound to a different fingerprint. Either deactivate the other machine (online) or contact support to release the slot. **"Activated but modules are still marked inactive"** — Some serials entitle only a subset of modules; the About dialog and the License Manager modules list both show which modules are active. Check the expiry dates: expired modules show as inactive even when the license is otherwise valid. ## End-User Licence Agreement TunnelCAD ships with an End-User Licence Agreement that the user must accept on first run (and on every material version bump). **Where the text lives:** - `EULA.md` — authoritative Markdown source in the repository root. - `EULA.txt` — plain-text rendering shipped next to the binary; the in-app dialog reads this file at startup. **Acceptance record:** On acceptance, TunnelCAD writes a small JSON file alongside `license.json`: - **Windows:** `%APPDATA%\TunnelCAD\eula.json` - **Linux:** `~/.config/TunnelCAD/eula.json` The file records the accepted EULA version, the acceptance timestamp (ISO-8601 UTC), the OS username, and the Device fingerprint. It is only ever written on user click-through and read to decide whether the dialog needs to appear again after a version bump. **Re-prompt triggers:** - `eula.json` is missing (e.g. fresh install). - `eula.json` exists but its `version` field is older than the current `EULA_VERSION` compiled into the application (material amendment). **Decline behaviour:** Declining the EULA exits the application without creating the main window. No telemetry is sent on decline. **TODO:** the installer scripts (to be authored) must ship `EULA.txt` alongside the binary — the dialog will otherwise display a diagnostic message in place of the EULA text.