#!/usr/bin/env bash
#
# RELAY-PHASE1 · E (TASK E) — P5 capability-token keypair (Ed25519).
#
# STAGING TEMPLATE. One Ed25519 keypair underpins the whole authz split:
#
#     CONTROL-PLANE SIGNS  ──(mints capability tokens with the PRIVATE key, B6 token-mint)──▶
#                                                                         RELAY VERIFIES
#     The CP admin API (POST /accounts, /pairing-codes) ALSO verifies operator "manage" tokens with
#     the SAME public key. So the public key is deployed to BOTH processes; the private key lives ONLY
#     where tokens are minted (the B6 mint), never on the relay, never committed.
#
# The public key is printed in TWO encodings of the SAME raw 32 bytes (the split is encoding-only):
#     CAPABILITY_SIGN_PUBKEY_B64   raw 32B, standard base64   -> control-plane env (env.ts base64ToBytes)
#     RELAY_AUTH_VERIFY_PUBKEY     raw 32B, base64url (no pad) -> relay env  (loadVerifyKeyFromEnv)
#   These MUST be the SAME key (PLAN §3 linchpin). This script prints both from one keypair so they
#   cannot drift.
#
# The PRIVATE key is written PKCS#8 PEM to a 0600 file for the B6 mint to import (WebCrypto Ed25519).
# It is NEVER printed and NEVER placed in relay.env / control-plane.env.
#
# Config via ENV only:
#     KEY_DIR   output dir for the private key   (default /etc/relay/capability)
#
# Verify (syntax): bash -n deploy/scripts/gen-capability-key.sh
set -euo pipefail

KEY_DIR="${KEY_DIR:-/etc/relay/capability}"
PRIV="${KEY_DIR}/capability-sign.key.pem"

command -v openssl >/dev/null 2>&1 || { echo "FATAL: openssl not found on PATH." >&2; exit 3; }

umask 077
mkdir -p "${KEY_DIR}"

if [[ -f "${PRIV}" ]]; then
  echo "WARN: ${PRIV} already exists — reusing it (delete it to rotate). Rotating INVALIDATES every" >&2
  echo "      minted token AND requires re-deploying the public key to BOTH processes." >&2
else
  openssl genpkey -algorithm ed25519 -out "${PRIV}"
fi
chmod 600 "${PRIV}"

# Raw 32-byte Ed25519 public key = last 32 bytes of the SPKI DER.
PUB_STD_B64="$(openssl pkey -in "${PRIV}" -pubout -outform DER | tail -c 32 | openssl base64 -A)"
# base64url of the SAME bytes, padding stripped (decodeBase64UrlBytes tolerates missing padding).
PUB_B64URL="$(printf '%s' "${PUB_STD_B64}" | tr '+/' '-_' | tr -d '=')"

cat <<SUMMARY

P5 capability keypair ready.

  PRIVATE key (B6 token-mint only; 0600; NEVER commit / NEVER on the relay):
      ${PRIV}

  Put the SAME public key in BOTH env files (they are one key, two encodings):

      # control-plane.env
      CAPABILITY_SIGN_PUBKEY_B64=${PUB_STD_B64}

      # relay.env
      RELAY_AUTH_VERIFY_PUBKEY=${PUB_B64URL}

Sanity check they decode to the same 32 bytes:
      diff <(openssl pkey -in "${PRIV}" -pubout -outform DER | tail -c 32 | xxd -p) \\
           <(printf '%s' "${PUB_STD_B64}" | openssl base64 -d -A | xxd -p) && echo OK
SUMMARY
