ATHANOR
RU GitHub ↗

8 / 8

End-to-end flows and diagnostics

Every earlier chapter looked at one part of the system on its own. This one pulls them together into a single picture and doubles as a reference to come back to when something isn't behaving.

The whole system at once

                         ┌────────────────────────┐
                         │      athanor.yaml       │  public key, expose flags,
                         │  (not secret, safe to   │  access_mode, deploy.remote_path
                         │   commit to git)        │
                         └───────────┬────────────┘
                                     │ describes policy for
                                     ▼
   athanor init ──► age identity ──► ~/.config/athanor/identity.txt
   (shared across      (private          │ the only way
    all projects,        key)            │ to decrypt
    unless --own-key)                    ▼
                                  ┌──────────────────┐
   athanor add ───────stdin─────►│  internal/store   │◄──── Store.Get/Set/Run
   (value never          (json)  │  (in the           │      single entry point
    an argument!)          │     │   process's mem.)  │      for every channel
                          ▼      └─────────┬──────────┘
                    sops --encrypt         │
                    (age recipient)        │ Store.Run(): injects into
                          │                │ the child's exec.Cmd.Env
                          ▼                │
                 secrets.enc.yaml ◄────────┘
                 (always encrypted)
                          │
            ┌─────────────┼──────────────────┬───────────────────┐
            ▼             ▼                  ▼                   ▼
        athanor list  athanor tui      athanor serve-mcp    athanor deploy
        (names only,  (human,          (agent, untrusted     (copies binary +
         no values)    trusted local   context — Exposable() manifest + secrets.enc.yaml
                        context)        checked only for       + identity.txt to the VPS)
                                        get_secret)

Access channels: who sees what

Channel Checks expose? What the consumer ultimately sees Writes to the audit log?
athanor list — (never returns values at all) secret names only no
athanor tui (enter/y) no — trusted local context the secret's value no
athanor run -- CMD no CMD's environment; the command can print or transmit the secret yes
MCP get_secret yes the secret's value as text (only if Exposable(name)) no
MCP run_with_secrets no CMD's environment and output; the command can print or transmit the secret yes
athanor deploy <host> — (moves the whole set at once) the server receives both the ciphertext and the key itself no

Diagnostic order

When something isn't behaving as expected, check things in this order — from the foundation up:

  1. Nothing decrypts (athanor list/run/tui fail with a sops error) — check that the identity file exists where it's expected (./identity.txt if the project used --own-key, otherwise ~/.config/athanor/identity.txt), and that its public key matches recipient in athanor.yaml. A mismatched key and recipient is the most common cause.
  2. get_secret refuses, but you expected a value — check expose for that specific secret in athanor.yaml, and access_mode at the top of the manifest. --full-access on serve-mcp and access_mode: full in the file produce the same effect through two independent paths.
  3. run_with_secrets runs fine, but the value isn't in the output — that's not a bug: the secret lives in an environment variable inside the running process, and the tool's output is just that process's stdout/stderr. If the command doesn't print the variable, the tool has nothing to show. If the command prints a lot of data, also check stdoutTruncated/stderrTruncated: each stream is capped at 1 MiB.
  4. A secret shared between projects isn't staying in sync — check that both athanor.yaml files point at the exact same secrets_file — the path resolves relative to each manifest separately, and it's easy to end up with two different files that just look similar.
  5. athanor deploy fails the smoke test — try ssh <host> by hand, the same way deploy does (the alias or key from ~/.ssh/config). Deploy doesn't fix SSH access problems, only reports them.

Checkpoint question. You have two projects on different VPSes. One has a secret marked expose: true, but calling get_secret through the other project's MCP server can't reach it. Is that a bug?

Answer: no. athanor serve-mcp, started from one project's directory, only ever works with that project's manifest and secrets_file — even if both projects share the same age identity, each manifest's expose flags and its own list of secrets are independent, unless both explicitly point at the same secrets_file.