Files
NATS_Expert/docs/superpowers/specs/2026-08-26-nats-external-apps-user-design.md
T

3.2 KiB

Design: NATS external-apps user

Goal

Add a third NATS user, external-apps, so third-party / external applications can connect to wss://nats.tes.gd with their own credential instead of borrowing the admin or volcanic-agents account.

Scope decisions

  • Permissions: unrestricted. Same shape as the existing admin and volcanic-agents users — no permissions block, so full publish/subscribe on any subject, JetStream management included. Scoped permissions are explicitly out of scope for this change; if we later need to lock down external callers, that's a follow-up.
  • Credential style: password (not opaque bearer token). Env var is NATS_EXTERNAL_APPS_PASSWORD, following the NATS_PASSWORD convention used by admin rather than the ..._TOKEN convention used by volcanic-agents.
  • Wire protocol / transport: unchanged. The user connects the same way as the others (WebSockets at wss://nats.tes.gd, standard user+password auth on the wire).

Change surface

  1. docker-compose.yml — inside configs.nats-conf.content, append one entry to authorization.users:

    { user: "external-apps", password: "${NATS_EXTERNAL_APPS_PASSWORD}" }
    

    Substitution happens at Docker Compose parse time, so NATS sees a static config on disk.

  2. Coolify env var — add NATS_EXTERNAL_APPS_PASSWORD on the nats application (project Volcanic MFEs, app UUID from local deploy.json). Value: a fresh random secret (e.g. openssl rand -hex 32).

  3. credentials.local.json — add a third entry under users:

    "external-apps": { "user": "external-apps", "password": "…", "note": "…" }
    

    Mirrors the Coolify env value. File is gitignored.

  4. CLAUDE.md — update the two spots that enumerate users so the doc stays in sync:

    • The "Connection details (for agents managing this NATS)" intro list.
    • The "Auth" bullet under "What's inside the server". Mention that external-apps is the intended account for third-party callers, unrestricted for now.
  5. Deploy — commit the compose + doc changes on main, then fire-and-forget POST /api/v1/deploy?uuid=<app-uuid> on Coolify. Do not poll.

Ordering constraint

Set the Coolify env var before pushing the compose change. Otherwise the compose parser substitutes an empty string, the config lands as password: "", and until the next deploy anyone who connects with empty credentials for user external-apps is authenticated. Order:

  1. PATCH the env var into Coolify.
  2. Commit + push the compose + doc changes.
  3. Trigger the deploy.

Verification

After the deploy triggers, connect from a workstation with the nats CLI as the new user and confirm auth works:

nats --server=wss://nats.tes.gd \
  --user=external-apps --password="$NATS_EXTERNAL_APPS_PASSWORD" \
  server info

A Server ID response = success. An auth error = the env var didn't land or the substitution failed; check docker logs on the Coolify host per the existing "Gotchas" section of CLAUDE.md.

Out of scope

  • Scoped/restricted permissions for external callers (deliberate — noted above).
  • Rotating the existing admin or volcanic-agents credentials.
  • Adding a UI or self-service flow for provisioning further users.