Release v1.1.0

This commit is contained in:
thakares committed 2026-09-02 15:19:19 +05:30
1 parent 34227efd2b
commit edc710cbd2
46 files changed
+5324 -190

No files matched your search

+10 -4
View File
@@ -61,13 +61,16 @@ All non-2xx responses return a structured JSON error body:
- `PUT /api/v1/system/settings`: Upsert setting `{ "key": "wireguard.server_host", "value": "vpn.thakares.com", "is_secret": false, "description": "..." }`. Supports `wireguard.server_host`, `wireguard.server_port`, and `wireguard.server_endpoint_enabled`.
### WireGuard Interfaces
- `GET /api/v1/interfaces`: List all WireGuard interfaces.
- `POST /api/v1/interfaces`: Create interface `{ "name": "wg0", "address_v4": "10.100.0.1/24", "listen_port": 51820, "mtu": 1420 }`.
- `GET /api/v1/interfaces`: List all WireGuard interfaces (includes `role`: `"overlay"` | `"upstream"` and `listen_port`: `u16 | null`).
- `POST /api/v1/interfaces`: Create standard Overlay interface `{ "name": "wg0", "address_v4": "10.100.0.1/24", "listen_port": 51820, "mtu": 1420 }`.
- `POST /api/v1/interfaces/upstreams/preview`: Dry-run validate and preview third-party WireGuard `.conf` `{ "name": "proton0", "config": "[Interface]\n..." }`. Returns parsed interface and provider peer metadata with secrets redacted. Does not mutate database.
- `POST /api/v1/interfaces/upstreams/import`: Import third-party WireGuard `.conf` `{ "name": "proton0", "config": "[Interface]\n..." }`. Atomically creates Upstream interface and provider peer in SQLite, syncs kernel device with dynamic local listen port, and triggers reconciliation.
- `GET /api/v1/interfaces/{id}`: Get interface details.
- `PUT /api/v1/interfaces/{id}`: Update interface configuration (preserves private/public cryptographic identity).
- `DELETE /api/v1/interfaces/{id}`: Delete interface (cascades to peers).
- `DELETE /api/v1/interfaces/{id}`: Delete interface (tears down kernel device via Netlink and cascades to peers in database; protected against `wg0`).
- `POST /api/v1/interfaces/{id}/enable`: Set interface `IFF_UP`.
- `POST /api/v1/interfaces/{id}/disable`: Set interface `IFF_DOWN`.
- `POST /api/v1/interfaces/{id}/disable`: Set interface `IFF_DOWN` (protected against `wg0`).
- `POST /api/v1/interfaces/{id}/restart`: Restart interface (tears down kernel link and re-synchronizes desired configuration and peers).
- `GET /api/v1/interfaces/{id}/status`: Query live kernel netlink telemetry.
### Peers & Client Configs
@@ -123,6 +126,9 @@ All non-2xx responses return a structured JSON error body:
### Audit Trail
- `GET /api/v1/audit`: List append-only security and operational audit records.
### SPA CLI Console
- `POST /api/v1/cli/execute`: Execute a structured read-only CLI command `{ "command": "interface", "subcommand": "upstream", "sub_subcommand": "list", "target": null, "parameters": {} }`. Enforces a strict read-only allowlist and sanitizes output against secret leakage. Mutating commands and arbitrary shell execution are strictly rejected.
---
## 4. Real-Time WebSocket Protocol (`/api/v1/ws`)
+54 -1
View File
@@ -102,5 +102,58 @@ flowchart TD
1. **Subprocess Isolation**: Zero invocations of `std::process::Command` or shell scripts across the entire production codebase.
2. **Persistence Authority**: SQLite remains the single authoritative source of truth. Kernel state is continuously reconciled to match database state.
3. **Firewall Isolation**: All nftables operations are confined to `table inet nx9_wg`. Unmanaged host tables are untouched.
4. **Route Safety**: Default gateway routes and host networking routes are protected against accidental deletion or flushing.
4. **Route Safety**: Default gateway routes and physical host networking routes are protected against accidental deletion or flushing.
5. **Secret Redaction**: Private keys, preshared keys, password hashes, and token hashes are masked in `Debug` formatters, CLI outputs, and API responses.
---
## 4. Interface Roles & Upstream Architecture
`nx9-wg` implements explicit `InterfaceRole` categorization across domain models, Netlink device configuration, and reconciliation:
```
┌────────────────────────────────────────────────────────────────────────────────────────┐
│ Linux Host Network │
│ │
│ ┌────────────────────────────────┐ ┌──────────────────────────────────┐ │
│ │ Primary Overlay (wg0) │ │ Optional Upstream (proton0) │ │
│ │ Role: Overlay │ │ Role: Upstream │ │
│ │ Local Listen Port: 51820 │ │ Local Listen Port: Auto (Dyn) │ │
│ │ Peers: 1..N Clients (Mobile) │ │ Peers: Exactly 1 Provider Peer │ │
│ │ Cryptokey AllowedIPs: /32 │ │ Cryptokey AllowedIPs: 0/0, ::0 │ │
│ └────────────────────────────────┘ └──────────────────────────────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌────────────────────────────────┐ ┌──────────────────────────────────┐ │
│ │ Private Overlay Clients │ │ Remote Provider Endpoint │ │
│ │ (10.100.0.0/24 Subnet) │ │ (37.19.199.155:51820) │ │
│ └────────────────────────────────┘ └──────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────┐ │
│ │ Physical WAN Default Route (eno2) │ │
│ │ Gateway: 192.168.1.1 (FIB Unchanged) │ │
│ └────────────────────────────────────────┘ │
└────────────────────────────────────────────────────────────────────────────────────────┘
```
### A. Role Discriminator & Invariants
- **`InterfaceRole::Overlay`**: The primary private WireGuard overlay network. Exactly one instance exists (`wg0`). It binds to an explicit listen port (`51820`), hosts enrolled client peers, and is protected from deletion or disabling.
- **`InterfaceRole::Upstream`**: Optional third-party WireGuard VPN interfaces (e.g. `proton0`). Zero or more instances may exist concurrently. Each Upstream interface connects NX9-WG to an external service provider through exactly one provider peer.
### B. Optional Local Listen Port & Ephemeral Kernel Binding
- `Interface.listen_port` is modeled as `Option<u16>`.
- Standard third-party `.conf` imports (e.g. ProtonVPN) omit `[Interface] ListenPort`. NX9-WG preserves `listen_port = None` without defaulting to `51820`.
- In `configure_device`, omitting the `WireguardAttribute::ListenPort` Netlink attribute signals the Linux kernel to assign an ephemeral dynamic UDP port automatically.
- This prevents local UDP port contention and allows `wg0` (51820) and `proton0` (dynamic) to coexist without `-EADDRINUSE` errors.
- Dynamic kernel ports produce 0 false drift actions in the reconciliation engine when desired `listen_port` is `None`.
### C. Cryptokey Routing vs. Linux FIB Default Routes
- An Upstream provider peer often specifies `AllowedIPs = 0.0.0.0/0, ::/0` in its `.conf`.
- In WireGuard, `AllowedIPs` defines the device-level cryptokey packet routing filter; it does **not** install a Linux kernel route.
- NX9-WG preserves `0.0.0.0/0, ::/0` on the `proton0` WireGuard device without modifying the server's Linux FIB default gateway (`192.168.1.1`).
- The provider endpoint (`37.19.199.155:51820`) remains reachable via the host physical WAN interface.
### D. NAT Masquerade Isolation
- Outbound NAT masquerading compiled into `table inet nx9_wg` is strictly scoped to Overlay client subnets (`10.100.0.0/24`).
- Upstream tunnel addresses (`10.2.0.2/32`) are not treated as client subnets and do not trigger unsolicited global masquerading.
+12 -3
View File
@@ -76,15 +76,24 @@ nx9-wg system settings set wireguard.server_endpoint_enabled true
- `nx9-wg admin sessions revoke-all`: Invalidate all active sessions.
### 6. `interface`
- `nx9-wg interface list`: List all WireGuard interfaces.
- `nx9-wg interface list`: List all WireGuard interfaces (displays Role: Overlay vs Upstream).
- `nx9-wg interface create <NAME> --address-v4 <CIDR> [--address-v6 <CIDR>] [--port PORT] [--mtu MTU] [--dns DNS]`: Create interface.
- `nx9-wg interface show <NAME_OR_ID>`: Show interface details.
- `nx9-wg interface update <NAME_OR_ID> [--port P] [--address-v4 A] [--address-v6 A] [--mtu M] [--dns D] [--enabled BOOL]`: Update interface.
- `nx9-wg interface enable <NAME_OR_ID>`: Enable interface (`IFF_UP`).
- `nx9-wg interface disable <NAME_OR_ID>`: Disable interface (`IFF_DOWN`).
- `nx9-wg interface delete <NAME_OR_ID>`: Delete interface (cascades to peers).
- `nx9-wg interface disable <NAME_OR_ID>`: Disable interface (`IFF_DOWN`; `wg0` cannot be disabled).
- `nx9-wg interface restart <NAME_OR_ID>`: Restart interface (tears down kernel device and re-applies desired configuration and peers).
- `nx9-wg interface delete <NAME_OR_ID>`: Delete interface (removes kernel device via Netlink and cascades to peers in database; `wg0` cannot be deleted).
- `nx9-wg interface status <NAME_OR_ID>`: Show live interface status and peer metrics.
- `nx9-wg interface reconcile <NAME_OR_ID>`: Reconcile specific interface with kernel.
- `nx9-wg interface upstream list`: List all Upstream WireGuard interfaces.
- `nx9-wg interface upstream show <NAME_OR_ID>`: Show Upstream interface configuration and provider peer details.
- `nx9-wg interface upstream import <NAME> [--file <PATH> | --config <CONF_STR>]`: Import third-party WireGuard `.conf` configuration (e.g. ProtonVPN) and create an Upstream interface.
- `nx9-wg interface upstream status <NAME_OR_ID>`: Show live kernel status and handshake for an Upstream interface.
- `nx9-wg interface upstream enable <NAME_OR_ID>`: Enable an Upstream interface.
- `nx9-wg interface upstream disable <NAME_OR_ID>`: Disable an Upstream interface.
- `nx9-wg interface upstream restart <NAME_OR_ID>`: Restart an Upstream interface (teardown + re-sync).
- `nx9-wg interface upstream delete <NAME_OR_ID>`: Delete an Upstream interface.
### 7. `peer`
- `nx9-wg peer list [--interface NAME_OR_ID]`: List enrolled peers.
+2 -2
View File
@@ -23,8 +23,8 @@ Download and extract the official release archive:
```bash
# 1. Download release archive (replace with current version/arch)
tar -xzf nx9-wg-v1.0.0-linux-x86_64.tar.gz
cd nx9-wg-v1.0.0-linux-x86_64
tar -xzf nx9-wg-v1.1.0-linux-x86_64.tar.gz
cd nx9-wg-v1.1.0-linux-x86_64
# 2. Run the automated installer as root
sudo bash install.sh
+10 -7
View File
@@ -29,13 +29,14 @@ Unlike traditional WireGuard management tools that spawn external CLI processes
### B. WireGuard Generic Netlink Protocol
- Resolves the dynamic Generic Netlink family ID for `"wireguard"`.
- **`WG_CMD_SET_DEVICE`**: Atomically configures the interface private key, UDP listen port, and peer list.
- **`WG_CMD_SET_DEVICE`**: Atomically configures the interface private key, UDP listen port (if explicitly configured), and peer list.
- **Optional ListenPort**: If `interface.listen_port` is `Some(port)` and `port != 0`, `WGDEVICE_A_LISTEN_PORT` is emitted. If `None` (standard for Upstream interfaces like `proton0`), the attribute is omitted, allowing the Linux kernel to automatically bind an ephemeral dynamic UDP port.
- **`WG_CMD_GET_DEVICE`**: Queries live kernel device state, active listen port, public key, peer public keys, endpoints, allowed IPs, last handshake timestamps, and transfer byte counters.
- **`WGDEVICE_F_REPLACE_PEERS`**: When syncing peers, setting this flag instructs the kernel to atomically replace all existing peers with the supplied desired set, removing stale peers in a single transaction.
---
## 2. Peer Cryptographic Synchronization
## 2. Peer Cryptographic Synchronization & Role-Aware AllowedIPs
```mermaid
sequenceDiagram
@@ -45,9 +46,9 @@ sequenceDiagram
participant Kernel as Linux Kernel (wireguard.ko)
Engine->>Genl: Send WG_CMD_SET_DEVICE (Interface wg0, ReplacePeers=true)
Note over Engine,Genl: Encodes ListenPort, PrivateKey, Peer Array
Note over Engine,Genl: Encodes ListenPort (if Some), PrivateKey, Peer Array
Genl->>Kernel: Transmit Netlink Message
Kernel->>Kernel: Validate Keys, Bind UDP Port, Apply Peers
Kernel->>Kernel: Validate Keys, Bind UDP Port (or dynamic), Apply Peers
Kernel-->>Genl: NLMSG_ERROR (error=0 / Success)
Genl-->>Engine: Ok(())
@@ -57,10 +58,12 @@ sequenceDiagram
Genl-->>Engine: Live Telemetry (Handshakes, Bytes Tx/Rx)
```
### Cryptographic Attribute Encoding:
### Role-Aware Cryptographic Attribute Encoding:
- **Keys**: 32-byte binary Curve25519 keys (`WGPEER_A_PUBLIC_KEY`, `WGPEER_A_PRESHARED_KEY`).
- **Allowed IPs**: Nested attributes (`WGALLOWEDIP_A_FAMILY`, `WGALLOWEDIP_A_IPADDR`, `WGALLOWEDIP_A_CIDR_MASK`).
- **Endpoint**: `sockaddr_in` (IPv4) or `sockaddr_in6` (IPv6) socket address structures.
- **Role-Aware Allowed IPs**:
- **Overlay Peers**: Scoped to `/32` (IPv4) or `/128` (IPv6) derived from the peer's assigned tunnel address.
- **Upstream Provider Peers**: Preserves full-tunnel AllowedIPs (`0.0.0.0/0, ::/0`) on the WireGuard device without modifying the server's Linux FIB default routing table.
- **Endpoint**: `sockaddr_in` (IPv4) or `sockaddr_in6` (IPv6) socket address structures representing the remote destination (e.g. `37.19.199.155:51820`), independent of the local interface listen port.
- **Persistent Keepalive**: Interval in seconds (`WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL`).
---
+13 -1
View File
@@ -72,19 +72,24 @@ pub struct ReconciliationPlan {
### A. WireGuard Interfaces
- Checks if desired interfaces (`Interface`) exist in kernel links via RTNETLINK.
- Detects missing interfaces, wrong MTU, or down status.
- Detects missing interfaces, wrong MTU, down status, or public key mismatch.
- **Dynamic Port Drift Tolerance**: When desired `listen_port` is `None` (standard for Upstream interfaces), the reconciler accepts kernel-selected ephemeral dynamic ports without generating false drift.
- **Orphan Interface Detection**: Scans live kernel WireGuard interfaces; any interface present in kernel but absent from SQLite desired state is scheduled for removal (`delete_orphan_interface`).
### B. Cryptographic Peers
- Queries live WireGuard device via `WG_CMD_GET_DEVICE`.
- Detects missing peers, changed public keys, altered allowed IPs, or mismatched persistent keepalive intervals.
- **Role-Aware Cryptokey Routing**: Overlay peers are checked against assigned `/32` or `/128` tunnel addresses, while Upstream provider peers are checked against configured full-tunnel AllowedIPs (`0.0.0.0/0, ::/0`).
### C. Kernel Routes
- Queries active kernel routes via `RTM_GETROUTE`.
- Evaluates exact equality on destination CIDR, gateway IP, interface name, and route metric.
- Protects host default gateway (`192.168.1.1`) and physical WAN interfaces from unwanted modifications.
### D. nftables Firewall & NAT
- Compares desired rules in SQLite against live rules in `table inet nx9_wg`.
- Detects missing rules, priority shifts, or altered NAT masquerade subnet policies.
- Outbound NAT masquerading remains scoped exclusively to Overlay client subnets.
### E. IP Forwarding
- Inspects `/proc/sys/net/ipv4/ip_forward` and `/proc/sys/net/ipv6/conf/all/forwarding`.
@@ -105,3 +110,10 @@ Reconciliation mutations are protected by an asynchronous Mutex:
1. **Clean Cold-Start Recovery**: When `nx9-wg` starts or restarts, the background daemon queries the kernel, detects unapplied state from SQLite, and applies all interfaces, peers, routes, and firewall rules in one unified cycle.
2. **Idempotent Convergence**: Running `reconcile apply` multiple times in succession produces zero mutations (NOOP) once convergence is achieved.
3. **Telemetry Protection**: Live kernel telemetry (transfer bytes, handshake timestamps) is ingested into memory/events and NEVER overwrites authoritative desired configuration in SQLite.
---
## 6. Orphan Interface Removal & Empty-State Guard
- **Deterministic Orphan Cleanup**: When an interface is deleted or an unmanaged kernel device is detected, `apply()` removes the orphan interface from the Linux kernel.
- **Empty-Desired-State Safety Guard**: If SQLite returns zero desired interfaces while live kernel interfaces are present, `apply()` aborts immediately with an error rather than mass-deleting kernel interfaces, protecting against catastrophic link destruction during transient database read errors.
+5 -5
View File
@@ -13,22 +13,22 @@ bash scripts/package-release.sh
```
### Packaging Outputs in `target/dist/`:
- `nx9-wg-v1.0.0-linux-x86_64.tar.gz` (Standard gzip archive)
- `nx9-wg-v1.0.0-linux-x86_64.tar.xz` (High-compression XZ archive)
- `nx9-wg-v1.0.0-linux-x86_64.sha256` (Cryptographic SHA-256 checksums)
- `nx9-wg-v1.1.0-linux-x86_64.tar.gz` (Standard gzip archive)
- `nx9-wg-v1.1.0-linux-x86_64.tar.xz` (High-compression XZ archive)
- `nx9-wg-v1.1.0-linux-x86_64.sha256` (Cryptographic SHA-256 checksums)
---
## 2. Release Documentation
The release documentation is versioned with the source tree. `CHANGELOG.md` records release-level changes, while `docs/TESTING.md` is the authoritative v1.0.0 testing and acceptance specification.
The release documentation is versioned with the source tree. `CHANGELOG.md` records release-level changes, while `docs/TESTING.md` is the authoritative v1.1.0 testing and acceptance specification.
## 3. Release Archive Contents
Every release archive contains everything required for a standalone, offline production deployment:
```
nx9-wg-v1.0.0-linux-x86_64/
nx9-wg-v1.1.0-linux-x86_64/
├── nx9-wg (Native executable binary, mode 0755)
├── nx9-wg.service (Hardened systemd unit file, mode 0644)
├── config.example.toml (Production configuration template, mode 0644)
+4 -1
View File
@@ -57,8 +57,11 @@
## 6. Secret Redaction & Memory Safety
- Custom `std::fmt::Debug` implementations enforce `[REDACTED]` for `WireGuardPrivateKey`, `WireGuardPresharedKey`, `Admin`, and `ApiToken`.
- **Upstream Import Secret Safety**: Third-party `.conf` previews and import responses never return private keys or preshared keys in cleartext. Sensitive keys are stored strictly in the database and submitted to the kernel over Netlink.
- **Reconciliation Plan & Report Scrubbing**: Dry-run plans and reconciliation convergence reports scrub private keys and preshared keys to prevent accidental leakage into logs or event streams.
- **SPA CLI Console Output Sanitization**: The read-only SPA CLI execution endpoint runs an automated secret scrubber over command outputs, stripping private keys and credentials before returning output to the browser.
- Web UI and REST API responses redact private keys and token hashes.
- CLI status output strictly redacts sensitive hashes.
- CLI status output strictly redacts sensitive cryptographic keys and password hashes.
---
+6 -6
View File
@@ -1,4 +1,4 @@
# NX9-WG v1.0.0 — Comprehensive Testing Specification
# NX9-WG v1.1.0 — Comprehensive Testing Specification
This document is the authoritative testing and release-acceptance specification for NX9-WG.
@@ -46,7 +46,7 @@ Run:
cargo test --workspace
```
The v1.0.0 documentation baseline records **162 passing workspace tests**. The final release count must always be regenerated after code changes; documentation must never assume that the historical count remains unchanged.
The v1.1.0 documentation baseline records **195 passing workspace tests**. The final release count must always be regenerated after code changes; documentation must never assume that the historical count remains unchanged.
Focused crates may be run independently:
@@ -373,7 +373,7 @@ For WAN road-warrior certification:
## 22. Release Acceptance Matrix
| Acceptance Gate | v1.0.0 Evidence Status |
| Acceptance Gate | v1.1.0 Evidence Status |
|---|---|
| Real Android handshake | **PASS — operator verified** |
| Tunnel control connectivity | **PASS — operator verified** |
@@ -430,8 +430,8 @@ bash scripts/package-release.sh
Verify:
- Package name contains `v1.0.0`.
- Binary reports `1.0.0`.
- Package name contains `v1.1.0`.
- Binary reports `1.1.0`.
- README and CHANGELOG are included.
- `docs/TESTING.md` is included.
- Installation scripts are executable.
@@ -451,7 +451,7 @@ git diff --check
Historical backup/runtime artifacts are not release documentation and must not be packaged as source or distribution state.
All current release-facing references must identify v1.0.0.
All current release-facing references must identify v1.1.0.
## 26. Final Release Command Set
+13 -3
View File
@@ -20,7 +20,7 @@
| Hash Route | Navigation Label | Purpose & Operational Features |
| :--- | :--- | :--- |
| `#dashboard` | **Dashboard** | System status, uptime, interface/peer counts, diagnostics health, and reconciliation status cards. |
| `#interfaces` | **Interfaces** | List WireGuard interfaces, "+ Create Interface" modal, interface "Edit" action (with cryptographic key preservation), enable/disable toggle, and delete interface. |
| `#interfaces` | **Interfaces** | List WireGuard interfaces with explicit **Role** badges (`Overlay` vs `Upstream`), "+ Create Interface" modal with tabbed **Standard Overlay** vs **Import Upstream VPN** (`.conf` parser & live preview), interface **Edit** action (preserves private/public key identity), **Restart** action (link teardown + re-sync), enable/disable toggle, delete action (protected against `wg0`), `Auto (Dynamic)` listen port display, and embedded read-only CLI console. |
| `#peers` | **Peers** | Enrolled peer table with real-time handshakes, status filter, "+ Add Peer" modal with MTU profile resolution, client configuration export, and live SVG QR rendering. |
| `#networks` | **Networks** | Subnet network ranges, CIDR masks, "+ Create Network" modal, and deletion. |
| `#routes` | **Routes** | Routing table entries, gateway assignments, "+ Create Route" modal, and deletion. |
@@ -37,7 +37,7 @@
---
## 3. Interactive Modals & Client Transport Profiles
## 3. Interactive Modals & Upstream Workflows
### A. Client Profile & MTU Resolution Modal
When enrolling a new peer (`#peers`), the modal automatically queries `/api/v1/client-profiles/resolve` based on selected Device (Android, iOS, Linux, Windows, macOS) and Connection (Mobile Cellular 4G/5G, Wi-Fi, Wired Ethernet) to determine optimal MTU (1280 vs 1360 vs 1420) and persistent keepalive (25s).
@@ -52,7 +52,17 @@ When opening the export modal for a peer, the UI automatically:
- **Interactive Vector QR Code**: Inline SVG rendering for scanning directly with the official WireGuard mobile app.
- **Downloadable `.conf` File**: Standard WireGuard client configuration file formatted for instant download or clipboard copy.
### C. One-Time API Token Delivery Modal
### C. Third-Party Upstream Import Modal (`#interfaces`)
The "+ Create Interface" modal provides a dedicated **Import Upstream VPN** tab:
1. Accepts interface name (e.g. `proton0`) and raw `.conf` content from third-party VPN providers (e.g. ProtonVPN).
2. Provides a **Preview Configuration** button triggering `/api/v1/interfaces/upstreams/preview` to dry-run validate the configuration and display parsed tunnel addresses, DNS, MTU, listen port (showing `Auto (Dynamic)` when omitted), and provider peer details before writing to SQLite.
3. Secret redaction: Private keys and PSKs are never echoed back in preview responses or displayed in cleartext in the UI.
4. On submission, atomically saves desired state, provisions the kernel interface, and triggers reconciliation.
### D. Embedded Read-Only CLI Console (`#interfaces`)
Provides an in-browser interactive terminal to execute read-only operational and status commands (e.g., `nx9-wg interface upstream list`, `nx9-wg diagnostics all`). Enforces a strict server-side command allowlist and output secret sanitizer.
### E. One-Time API Token Delivery Modal
Generates a new API token, calculates its SHA-256 digest for SQLite storage, and presents the raw token string once in an interactive modal with a copy button.
---