Skip to content

Out-of-band approval at the commit gate: host-verified, non-destructive sensitive keys only #911

Description

@VijitSingh97

Part of #786 (sub-issue C; decision record in the 2026-08-13 comment there). Post-GA fast-follow — the pre-GA bar is A+B+D.

Goal

The commit gate's flat refusal of non-allowlisted keys becomes a pending, host-verified, out-of-band approval: the dashboard proposes ("change payout wallet to 4A…xyz — approve?"), the operator approves on Telegram, the host verifies, deny-on-timeout, per-operator rate limit. The #338 semantics, extended from its two fixed verbs to gate-refused config commits, reusing its shipped surface (telegram.control.allowed_ids / confirm_timeout).

Hard constraints (unchanged from the decomposition)

  1. The host verifies the approval. The shipped ControlGate lives in the dashboard container and is documented as UX, not the boundary — a wallet swap cannot trust a container-relayed "approved". The host runner holds the bot token via config.json and drives its own confirm exchange. This split — container proposes, host independently verifies — has no peer precedent (none of Talos/HAOS/TrueNAS/OPNsense/Synology/UniFi/umbrel run a comparable model). It is the highest-engineering-risk item in the parity roadmap; do not estimate it as "add more keys to Telegram two-way control commands (restart / apply) with access control #338".
  2. The never-approve set stays refused even with approval (decision Q2): ssh.enabled/ssh.authorized_key; the approval channel's own identity as a block (telegram.bot_token/chat_id/telegram.control.*); dashboard.control.enabled; the tamper-evidence toggles (telegram.events.wallet_changed, clearnet_exposed); and dashboard.auth.password — it doubles as the root console password every boot, so changing it is root-credential rotation and stays physical-only (D). Peer evidence is convergent: no studied project lets the admin channel's own trust anchor be changed through itself.
  3. DEST-flagged destructive changes stay refused in v1 (decision Q5): node local↔remote switches and the Data-dir moves are now dashboard-confirmable but assert_safe_dir is a blocklist, not an allowlist #728 data-dir destination rule are reachable only via D or a local session. No peer extends remote approval to its most destructive actions; TrueNAS instead adds typed re-entry friction locally. A future destructive-ops channel needs its own threat model, not a bundled extension of this one.

v1 approvable set

The non-DEST sensitive keys: wallet addresses, view keys/scan heights, healthchecks.ping_url, notifications.*, stratum password/TLS/bind, node credentials, onion exposure, LAN-access toggles. Config editor surfaces the class as _approval_keys, same pattern as _editable_keys/_confirm_keys.

Known accepted limitation

Telegram is the only approval channel and its identity is in the never-approve set — a lost or rotated bot token disables C until a D (physical) recovery. Same shape as Talos's CA: no revocation list, physical rotation only. Stated here so it is a decision, not a discovery.

Coverage

Tier 1 heavy (the gate is pure shell, the prompt/diff logic pure Python); tier 4 for one live Telegram approval round-trip on the bench.

Dependencies

Nothing in code; operationally requires Telegram already configured — a box without it bootstraps via D, by design.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    appliancePithead OS appliance work — image, installer, RAUC updatesenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions