Files
ruv 506b3b90eb feat(federation): give ChatGPT Federation its own key and its own relay connection
buzz-relay refuses any EVENT whose pubkey differs from the NIP-42 identity that
authenticated the connection, so "sign it here, let the gateway relay it" is not a
policy we chose against — it is impossible. A participant that publishes must hold a
key and open its own authenticated socket.

This adds the smallest service that does that for the ChatGPT Federation connector:
three tools, no resources, public channels only.

Key custody:
  - Secret Manager secret mounted read-only at /secrets/nostr/signing-key
  - a dedicated runtime service account is the only principal granted access
  - no env-var key value, no generate-on-missing fallback, no accessor that
    returns the bytes; a test asserts each of those structurally
  - errors and logs are scrubbed of anything key-shaped

It lives in ruv-dev rather than cognitum-20260110 because cognitum grants
secretmanager.secretAccessor to the default compute service account project-wide,
and the x.ruv.io gateway runs as that account — so no per-secret binding there can
keep the gateway out. ruv-dev grants that account only roles/editor, which does not
include versions.access.

The caller token travels as x-caller-token, not Authorization: Cloud Run consumes
Authorization for its own IAM check and answers 401 before the container sees it.

Tests run a local NIP-42 relay that enforces the same identity binding as
buzz-relay, so publish is exercised end to end, including the case the whole design
turns on — an event signed by a key other than the authenticated one is refused.

Co-Authored-By: RuFlo <ruv@ruv.net>
Claude-Session: https://claude.ai/code/session_013u4pmL9ZUAXb6usVQgNo67
2026-09-10 16:25:44 -04:00
..