Files
UmbraAudio/infra/oldbox-agent-communication-prompt.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

5.5 KiB

Build a secure oldbox ↔ Mac agent communication MCP server

You are the OpenCode agent running on oldbox. The Mac-side agent needs a reliable way to exchange sanitized instructions and reports with you without requiring repeated clipboard copy/paste.

Objective

Create a standalone, local stdio MCP server named agent-comm under the UmbraTrans workspace on oldbox. It must use a shared, append-only inbox/outbox on the NAS2 netbackup/UmbraTrans share. Do not create an unauthenticated network listener.

The first purpose is to send the pending SSH-authentication diagnostic report back to the Mac agent without exposing passwords or other secrets.

Security requirements

  • Never accept, return, log, or transmit passwords, sudo passwords, private keys, API tokens, Keychain data, or /etc/shadow contents.
  • No secret values may appear in MCP arguments, environment variables, command lines, filenames, reports, or logs.
  • The server must be stdio-only. It must not listen on a TCP or UDP port.
  • Use the NAS share only for sanitized text/JSON messages.
  • Message files must be written atomically (temporary file + rename).
  • Use restrictive directory/file permissions and refuse symlink paths.
  • Validate and bound all message sizes.
  • Do not change SSH, sudoers, firewall, Docker, Qwen, or existing services.
  • Do not install a system-wide daemon yet.
  • Do not grant NOPASSWD: ALL or any broad sudo rule.

Discovery phase

Before creating the server, perform read-only discovery:

  1. Locate the NAS2 mount for the netbackup share.
  2. Locate or propose the UmbraTrans subdirectory.
  3. Confirm the path is writable by umbra.
  4. Report the exact path and permissions.
  5. Do not write any message until the path is confirmed in the report.

Use a conservative search such as find, mount, and df; do not modify mounts or credentials. If the share is not visible, report that and stop rather than guessing a path.

Shared mailbox layout

Once the path is confirmed, use this layout below the confirmed UmbraTrans directory:

agent-mailbox/
  inbox/       # sanitized instructions from Mac to oldbox
  outbox/      # sanitized reports from oldbox to Mac
  processed/   # messages already handled by oldbox
  archive/     # optional processed message archive

Each message is one UTF-8 JSON file with this shape:

{
  "schema_version": 1,
  "id": "UUID",
  "created_at": "ISO-8601 UTC",
  "sender": "oldbox",
  "kind": "diagnostic|report|instruction|ack",
  "correlation_id": "optional UUID",
  "title": "short non-secret title",
  "body": "sanitized text, maximum 64 KiB",
  "attachments": []
}

Do not allow arbitrary attachment paths in version 1.

MCP tools

Implement these tools:

agent_status

Return only:

  • server version
  • configured mailbox path
  • whether inbox/outbox are readable/writable
  • number of pending messages
  • last health-check time
  • no secret values

send_report

Arguments:

  • title: non-secret string
  • body: sanitized report text
  • correlation_id: optional non-secret string
  • kind: default report

Write a validated JSON message to outbox/ using an atomic rename. Return the message ID and path, never the secret contents.

read_instructions

Read up to a bounded number of JSON messages from inbox/. Validate each message, return only sanitized metadata/body, and move successfully handled messages to processed/ using an atomic rename. Never execute commands from a message automatically.

send_ack

Accept only a correlation ID and short non-secret text. Write an ack message to outbox/.

Current diagnostic report

After the server is implemented and tested, use it to send one report covering:

  • the successful manual SSH path
  • the broker's Permission denied (publickey,password) result
  • the fact that no authorized key or certificate is configured
  • the account/password state already observed
  • the exact unresolved question: whether the broker supplied a wrong password or supplied no usable password to OpenSSH

Do not include any password or hash. Do not ask the Mac agent to guess.

Implementation requirements

  • Python 3.11+ standard library is sufficient; do not add dependencies unless necessary.
  • Use type hints, from __future__ import annotations, logging to stderr, and no print() for debug output except the CLI's intentional status output.
  • Include a README with the exact OpenCode local-server configuration.
  • Include unit tests for JSON validation, atomic writes, path traversal, symlink refusal, size limits, inbox/outbox behavior, and secret-pattern redaction.
  • Add a --check mode that performs only read-only checks.
  • Run the tests and --check before sending the first report.

OpenCode configuration to document

The configuration should be equivalent to:

{
  "mcp": {
    "servers": {
      "agent-comm": {
        "type": "local",
        "command": [
          "/absolute/path/to/python",
          "-m",
          "agent_comm"
        ],
        "environment": {
          "AGENT_COMM_ROOT": "/confirmed/nas2/path/agent-mailbox"
        }
      }
    }
  }
}

Do not add secrets to the configuration.

Completion response

Return a concise report containing:

  1. Confirmed mailbox path and permissions.
  2. Files created.
  3. Test results.
  4. OpenCode configuration path/snippet.
  5. The first outbox report message ID.
  6. Any unresolved issue.

Do not claim the Mac agent has received the message until the Mac-side reader has been configured and verified.