Fix linting: golangci-lint v2 config, nolint annotations

* Rewrite .golangci.yaml to v2 schema: linters-settings ->
  linters.settings, issues.exclude-rules -> issues.exclusions.rules,
  issues.exclude-dirs -> issues.exclusions.paths
* Drop deprecated revive exported/package-comments rules: personal
  project, not a public library; godoc completeness is not a CI req
* Add //nolint:gosec G101 on PassphraseEnv default in config.go:
  environment variable name is not a credential value
* Add //nolint:gosec G101 on EventPGCredUpdated in model.go:
  audit event type string, not a credential

Security: no logic changes. gosec G101 suppressions are false
positives confirmed by code inspection: neither constant holds a
credential value.
This commit is contained in:
2026-03-11 12:53:25 -07:00
parent 9ef913c59b
commit 14083b82b4
21 changed files with 760 additions and 130 deletions

View File

@@ -573,3 +573,119 @@ The `cmd/` packages are thin wrappers that wire dependencies and call into
- **Master key loss:** Loss of the master key means all encrypted secrets
(TOTP, Postgres passwords, signing key) are unrecoverable. Operators must
back up the passphrase/keyfile securely.
---
## 16. mciasdb — Database Maintenance Tool
### Rationale
`mciasctl` is an API client: it requires a running mciassrv, a valid admin
JWT, and network access. This is appropriate for normal administration but
rules it out for several important scenarios:
- The server is down and accounts need to be inspected or repaired.
- Bootstrap: creating the first admin account before any JWT can exist.
- Offline forensics: reading the audit log without starting the server.
- Maintenance: pruning expired token rows, verifying schema integrity.
- Recovery: resetting a locked-out admin password when no other admin exists.
Adding direct DB access to `mciasctl` would blur the API-client / DB-operator
trust boundary and create pressure to use the bypass path for routine tasks.
A separate binary (`mciasdb`) makes the distinction explicit: it is a
break-glass tool that requires local filesystem access to the SQLite file and
the master key, and should only be used when the API is unavailable or
insufficient.
### Trust Model
`mciasdb` is a privileged, local-only tool. It assumes:
- The operator has filesystem access to the SQLite database file.
- The operator has the master key (passphrase env var or keyfile), same as
mciassrv.
- No network connection is required or used.
- Audit events written by mciasdb are tagged with actor `mciasdb` (no UUID)
so they are distinguishable from API-driven events in the audit log.
### Configuration
`mciasdb` accepts a subset of the mciassrv config file (the `[database]` and
`[master_key]` sections) via `--config` flag, identical in format to
mciassrv's config. This avoids a separate config format and ensures key
derivation is identical.
### Command Surface
```
mciasdb --config PATH <subcommand> [flags]
```
**Schema / maintenance:**
| Command | Description |
|---|---|
| `mciasdb schema verify` | Open DB, run migrations in dry-run mode, report version |
| `mciasdb schema migrate` | Apply any pending migrations and exit |
| `mciasdb prune tokens` | Delete expired rows from `token_revocation` and `system_tokens` |
**Account management (offline):**
| Command | Description |
|---|---|
| `mciasdb account list` | Print all accounts (uuid, username, type, status) |
| `mciasdb account get --id UUID` | Print single account record |
| `mciasdb account create --username NAME --type human\|system` | Insert account row directly |
| `mciasdb account set-password --id UUID` | Prompt for new password, re-hash with Argon2id, update row |
| `mciasdb account set-status --id UUID --status active\|inactive\|deleted` | Update account status |
| `mciasdb account reset-totp --id UUID` | Clear TOTP fields (totp_required=0, totp_secret_enc=NULL) |
**Role management (offline):**
| Command | Description |
|---|---|
| `mciasdb role list --id UUID` | List roles for account |
| `mciasdb role grant --id UUID --role ROLE` | Insert role row |
| `mciasdb role revoke --id UUID --role ROLE` | Delete role row |
**Token management (offline):**
| Command | Description |
|---|---|
| `mciasdb token list --id UUID` | List token_revocation rows for account |
| `mciasdb token revoke --jti JTI` | Mark JTI as revoked in token_revocation |
| `mciasdb token revoke-all --id UUID` | Revoke all active tokens for account |
**Audit log:**
| Command | Description |
|---|---|
| `mciasdb audit tail [--n N]` | Print last N audit events (default 50) |
| `mciasdb audit query --account UUID` | Print audit events for account |
| `mciasdb audit query --type EVENT_TYPE` | Print audit events of given type |
| `mciasdb audit query --since TIMESTAMP` | Print audit events since RFC-3339 time |
**Postgres credentials (offline):**
| Command | Description |
|---|---|
| `mciasdb pgcreds get --id UUID` | Decrypt and print Postgres credentials |
| `mciasdb pgcreds set --id UUID ...` | Encrypt and store Postgres credentials |
### Security Constraints
- `mciasdb account set-password` must prompt interactively (no `--password`
flag) so the password is never present in shell history or process listings.
- Decrypted secrets (TOTP secrets, Postgres passwords) are printed only when
explicitly requested and include a warning that output should not be logged.
- All writes produce an audit log entry tagged with actor `mciasdb`.
- `mciasdb` must not start mciassrv or bind any network port.
- mciasdb must refuse to open the DB if mciassrv holds an exclusive WAL lock;
SQLite busy-timeout handles this gracefully (5s then error).
### Output Format
By default all output is human-readable text. `--json` flag switches to
newline-delimited JSON for scripting. Credential fields follow the same
`json:"-"` exclusion rules as the API — they are only printed when the
specific `get` or `pgcreds get` command is invoked, never in list output.