feat(nats-mcp): wire NATS_CREDS into pmoves-nats-fleet — spec §7b / §9 Phase 6 - #2937
Conversation
… spec §7b/§9 Phase 6 pmoves-nats-mcp v0.2 already implements the two-gate path (NATS_CREDS env → CORE-account .creds connect + CHIT-signed publish for CHIT-aware subjects) — shipped in PR #1490, registered in .claude/mcp.json since. But the registration passes only NATS_URL (legacy plaintext user/pass), so the creds gate exists in code yet is never exercised. This wires it: - .claude/mcp.json (pmoves-nats-fleet): + NATS_CREDS=${NATS_CREDS} + a _NOTE documenting the two-gate semantics and the graceful fallback (Claude Code treats ${VAR} as literal when unset → tools.py _nats_creds() returns None → legacy NATS_URL path; no fake CHIT, X-CHIT-Signed: false otherwise) - env.shared.example: documents NATS_CREDS custody (SECRET: CHIT-vault-held, materialized to /etc/nats/creds/ per node per spec §8, never committed) No behavior change until the operator sets NATS_CREDS (spec §9 Phase 6, after Phase 2 hub + Phase 3 CORE migration). The identity grant this unlocks: an agent connecting as its account, signing as itself — instead of nats:pmoves with a fleet-shared HMAC. Spec: pmoves/docs/specs/nats-accounts-leaf-topology-v0-spec-2026-08-07.md §7b
|
Important Review skippedAuto reviews are limited based on label configuration. 🏷️ Required labels (at least one) (1)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Team Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf07763d58
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
… importable
Addresses two P1 review findings on the NATS_CREDS wiring:
1. Legacy fallback was only *assumed*. A bare mcp.json "${NATS_CREDS}" survives
literally on a node where the var is unset, and that string is truthy, so
_connect() passed it to nats-py as user_credentials -> nats-py tries to open a
file literally named ${NATS_CREDS} and every publish/subscribe fails instead of
falling back to NATS_URL. _nats_creds() now returns None for an empty value AND
for an unresolved ${...} placeholder, guarding ALL launch paths (not just Claude
Code's ${VAR} expansion). mcp.json also uses ${NATS_CREDS:-} where the launcher
supports default-expansion, and the note now states the guarantee is code-enforced.
2. The canonical CHIT signer silently degraded to None. Launched via
`uv --directory ./pmoves-nats-mcp`, the package dir is on sys.path but the repo
root is not, so `from pmoves.tools.chit_security import sign_cgp` failed and every
CHIT-aware publish shipped X-CHIT-Signed: false — the two-gate model was never
achieved. tools.py now walks up to the dir holding pmoves/tools/chit_security.py
and puts the repo root on sys.path (depth-robust; no-op outside the monorepo).
Verified: signer imports from the package cwd; _nats_creds() -> None for
unset/blank/"${NATS_CREDS}", real path otherwise.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017g8jC7dupS2ubafo6zPQY6
Summary
pmoves-nats-mcpv0.2 (PR #1490) already implements the two-gate path —NATS_CREDSenv → CORE-account.credsconnect (transport gate) + CHIT-signed publish for CHIT-aware subjectschit.*,tokenism.prosodic.*,geometry.*(payload gate, via the canonical signer, no fake CHIT). But its.claude/mcp.jsonregistration passes onlyNATS_URL— the legacy plaintext user/pass — so the creds gate exists in code and is never exercised.This PR supplies the missing env:
.claude/mcp.json(pmoves-nats-fleet): addsNATS_CREDS=${NATS_CREDS}+ a_NOTEdocumenting the two-gate semantics and the graceful fallback (unset var → literal path →tools.py::_nats_creds()returns None → legacy path; honestX-CHIT-Signed: falsewhen the signer is unavailable)env.shared.example: documentsNATS_CREDScustody — SECRET, CHIT-vault-held, materialized to/etc/nats/creds/per node per spec §8, never committedTwo-gate model (spec §11)
.creds) — which trust zone may join the busNo behavior change until enabled
Unset
NATS_CREDS= today's behavior, byte-for-byte. Activation is spec §9 Phase 6, gated on the Phase 2 hub (#2936) + Phase 3 CORE migration. When it lands, an agent connects as its account and signs as itself — instead ofnats:pmoves+ fleet-shared HMAC, closing the identity loop this review surfaced.Verification
Companion: #2936 (Phase 2 hub compose). Spec:
pmoves/docs/specs/nats-accounts-leaf-topology-v0-spec-2026-08-07.md§7b/§8/§11.