Files
UmbraAudio/infra/remote_credential_broker/README.md
B.D. Murphy 0c9bea72e0 Add enterprise/infra tooling and repoint Qwen3-TTS submodule to internal fork
Two groups of changes, committed together as the follow-up to the initial push:

1. .gitmodules — submodule Qwen3-TTS now points at the internal Gitea fork
   (ssh://git@mini-eq:2222/umbragit/Qwen3-TTS.git) instead of upstream GitHub,
   so a clone actually gets the UmbraAudio branding/integration commit
   012e452 rather than vanilla upstream.

2. New infra/ tooling for the cross-machine work in spec 21: agent_bridge,
   remote_credential_broker (Keychain-backed, secrets read at runtime and
   generated via read_secret/random_secret — no hardcoded credentials), the
   enterprise bootstrap scripts, and the oldbox SSH/auth prompts. Plus
   backup/ restore scripts, two specs (18 UmbraTrans, 19 enterprise control
   plane), umbraaudio/voices/lmstudio_gate.py, and in-flight edits to the
   discovery/attribution/profiling modules, config, chapter_builder, emotion,
   pronunciation, qwen_tts and routes.

Also adds *.db to .gitignore: SQLite project databases are runtime state and no
.db file was tracked before.

Verified before staging: .env's only change is UMBRA_TTS__QWEN_TTS_HELPER_URL and
the committed copy has zero secret-looking values; the broker ships only
config.example.json.
2026-10-06 06:57:41 -07:00

3.5 KiB

UmbraTrans remote credential broker

This is a standalone local MCP server for the UmbraTrans control plane. It is not imported by UmbraAudio and must be deployed separately on the trusted macOS/OpenCode host.

Security model

  • Passwords are entered in a native macOS hidden-password dialog.
  • Passwords are stored in the macOS login Keychain through the Security framework; they are never written to the repository, environment variables, command-line arguments, logs, or MCP responses.
  • The MCP server exposes no get_password operation.
  • SSH host-key checking is strict. The server does not silently accept an unknown host key.
  • Unprivileged SSH commands are bounded by a timeout and output limit.
  • Sudo commands must exactly match an allowlist entry in the local config.
  • The default configuration does not grant sudo access to arbitrary commands.
  • The server is stdio-only and has no network listener.

The broker is intended to run on the Mac that owns the OpenCode session. The remote umbra account receives an SSH connection; the password is supplied only to the local SSH client/Keychain flow.

Files

  • broker.py — stdio MCP server and command-line popup setup.
  • keychain.py — ctypes macOS Keychain backend.
  • popup.py — native hidden-password prompt.
  • askpass_helper.py — OpenSSH SSH_ASKPASS helper; it prints a secret only to the SSH process pipe.
  • executor.py — bounded SSH/sudo execution and redaction.
  • config.py — non-secret remote profile and sudo allowlist parser.
  • config.example.json — oldbox/umbra example; copy to the user config path.
  • tests/ — dependency-free unit tests.

Local configuration

Copy the example to:

~/.config/umbra-trans/remote-broker.json

Review it. The known_hosts path must already contain the verified oldbox host key. Do not use StrictHostKeyChecking=no or an empty known-hosts file.

The first credential profiles can be entered through the MCP tool credential_set, which opens the popup, or directly from a terminal:

python3 -m remote_credential_broker.broker \
  --credential-profile oldbox-umbra-ssh \
  --purpose "SSH password for umbra@oldbox"
python3 -m remote_credential_broker.broker \
  --credential-profile oldbox-umbra-sudo \
  --purpose "sudo password for umbra@oldbox"

The command prints only whether the profile was stored. It never prints the secret.

OpenCode registration

Run the module from the directory containing the remote_credential_broker package, or use an absolute Python path and package directory. A local server entry has this shape:

{
  "mcp": {
    "servers": {
      "remote-broker": {
        "type": "local",
        "command": [
          "/absolute/path/to/python",
          "-m",
          "remote_credential_broker.broker"
        ],
        "environment": {
          "PYTHONPATH": "/absolute/path/to/package/parent"
        }
      }
    }
  }
}

The current OpenCode installation may use the older top-level mcp object; use the format accepted by the installed version. Do not put a password in the configuration file.

Tools

  • credential_set — opens the native popup and stores a profile.
  • credential_status — reports existence only.
  • credential_delete — removes a profile.
  • remote_exec — runs a command as the configured SSH account.
  • remote_sudo_exec — runs one exact allowlisted command through sudo.
  • remote_status — runs fixed identity/hostname probes.

The model can request a popup or operation, but cannot read the secret entered in the popup.