Skip to content

feat(nats-mcp): wire NATS_CREDS into pmoves-nats-fleet — spec §7b / §9 Phase 6 - #2937

Merged
POWERFULMOVES merged 4 commits into
mainfrom
feat/nats-mcp-creds-wiring
Sep 5, 2026
Merged

POWERFULMOVES merged 4 commits into
mainfrom
feat/nats-mcp-creds-wiring

Conversation

@POWERFULMOVES

Copy link
Copy Markdown
Owner

Summary

pmoves-nats-mcp v0.2 (PR #1490) already implements the two-gate path — NATS_CREDS env → CORE-account .creds connect (transport gate) + CHIT-signed publish for CHIT-aware subjects chit.*, tokenism.prosodic.*, geometry.* (payload gate, via the canonical signer, no fake CHIT). But its .claude/mcp.json registration passes only NATS_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): adds NATS_CREDS=${NATS_CREDS} + a _NOTE documenting the two-gate semantics and the graceful fallback (unset var → literal path → tools.py::_nats_creds() returns None → legacy path; honest X-CHIT-Signed: false when the signer is unavailable)
  • env.shared.example: documents NATS_CREDS custody — SECRET, CHIT-vault-held, materialized to /etc/nats/creds/ per node per spec §8, never committed

Two-gate model (spec §11)

  • Transport gate: the NATS account (nsc-minted .creds) — which trust zone may join the bus
  • Payload gate: CHIT signature inside the message — who exactly said this, with provenance trail

No 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 of nats:pmoves + fleet-shared HMAC, closing the identity loop this review surfaced.

Verification

  • JSON valid post-edit
  • Anchors ratchet: 0 new findings

Companion: #2936 (Phase 2 hub compose). Spec: pmoves/docs/specs/nats-accounts-leaf-topology-v0-spec-2026-08-07.md §7b/§8/§11.

… 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
@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • coderabbit

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Team

Run ID: cac43380-1b20-47cc-9b70-e0ca68613f35

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T17:38:39.693350Z cf07763 PR opened
ℹ️ 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" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread .claude/mcp.json Outdated
Comment thread .claude/mcp.json Outdated
Comment thread pmoves/env.shared.example
… 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
@POWERFULMOVES
POWERFULMOVES merged commit 38a23a0 into main Sep 5, 2026
29 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the feat/nats-mcp-creds-wiring branch September 5, 2026 13:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant