style: format docs, fix user_permissions variable scoping in auth middleware

Apply ruff line-wrapping formatting to docs and test files.
Clarify auth middleware: extract user_permissions once before
subsystem check, removing conditional variable scoping.
This commit is contained in:
2026-07-27 18:37:11 +00:00
parent d4213fb93b
commit ca110c321d
9 changed files with 640 additions and 26 deletions
+88
View File
@@ -264,6 +264,94 @@ acme.sh stores its state under `data/acme/` (the ACME home directory). Key files
The application reads `.account.conf` to determine registration status. If the file is missing or lacks required keys, the account is considered unregistered.
## Auth Configuration
**File**: `config/auth/config.json`
This file defines JWT settings and WebAuthn Relying Party configuration for the authentication system.
```json
{
"jwt": {
"access_token_ttl": 900,
"refresh_token_ttl": 604800,
"algorithm": "HS256"
},
"webauthn": {
"rp_name": "Vacuum Wall",
"rp_id": "<management-domain>",
"origin": "https://<management-domain>"
}
}
```
### JWT Fields
| Field | Type | Required | Description |
|---|---|---|---|
| `access_token_ttl` | integer | No | Access token lifetime in seconds. Default: `900` (15 minutes). |
| `refresh_token_ttl` | integer | No | Refresh token lifetime in seconds. Default: `604800` (7 days). |
| `algorithm` | string | No | JWT signing algorithm. Default: `"HS256"`. |
**Note:** JWT signing secrets are per-user, not shared. Each user's secret is auto-generated as a 32-byte base64url token (`secrets.token_urlsafe(32)`) and stored in the `users.jwt_secret` database column. Secrets are rotated on password change to invalidate all prior sessions.
### WebAuthn Fields
| Field | Type | Required | Description |
|---|---|---|---|
| `rp_name` | string | Yes | Display name for the WebAuthn Relying Party. Shown during credential registration. |
| `rp_id` | string | Yes | Domain for WebAuthn credential binding. Must match the management domain. |
| `origin` | string | Yes | HTTPS URL for WebAuthn origin check. Must match `https://<rp_id>`. |
## Database Schema
The SQLite database at `data/auth.db` stores authentication data across four tables. Created automatically on first access via `get_db()`.
### users
| Column | Type | Description |
|---|---|---|
| `id` | INTEGER | Auto-increment primary key |
| `username` | TEXT | Unique username |
| `password_hash` | TEXT | Argon2id password hash |
| `jwt_secret` | TEXT | Per-user JWT signing secret (32-byte base64url) |
| `created_at` | INTEGER | Unix timestamp (auto-set) |
### permissions
| Column | Type | Description |
|---|---|---|
| `id` | INTEGER | Auto-increment primary key |
| `username` | TEXT | Foreign key to `users.username` (CASCADE on delete) |
| `subsystem` | TEXT | Subsystem name (e.g., `"firewall"`, `"dhcp"`, `"auth"`) |
| `level` | TEXT | Permission level: `"read"` or `"rw"` |
UNIQUE constraint on `(username, subsystem)`.
### token_blacklist
| Column | Type | Description |
|---|---|---|
| `jti` | TEXT | Primary key — JWT unique identifier |
| `token_type` | TEXT | `"access"` or `"refresh"` |
| `expires` | INTEGER | Unix timestamp of token expiry |
Used to invalidate tokens on logout and password change. Expired entries are cleaned on every refresh operation.
### webauthn_creds
| Column | Type | Description |
|---|---|---|
| `id` | INTEGER | Auto-increment primary key |
| `username` | TEXT | Foreign key to `users.username` (CASCADE on delete) |
| `credential_id` | TEXT | Base64url-encoded credential ID |
| `public_key` | TEXT | Base64url-encoded public key |
| `sign_count` | INTEGER | Signature counter (replay prevention) |
| `name` | TEXT | User-assigned display name |
| `transports` | TEXT | JSON array of transport types |
UNIQUE constraint on `(username, credential_id)`.
## WireGuard Configuration
**File**: `config/wireguard/config.json`