diff --git a/harnesses/contexts/airouter/v1/bin/anthropic-compat-wrapper.sh b/harnesses/contexts/airouter/v1/bin/anthropic-compat-wrapper.sh new file mode 100755 index 0000000..118dac8 --- /dev/null +++ b/harnesses/contexts/airouter/v1/bin/anthropic-compat-wrapper.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Anthropic-compat wrapper for airouter harness (Phase 9 ESO-managed secrets) +# Reads airouter credentials from /run/agent/secrets/airouter/ and passes them +# as env vars to the underlying Claude runner. +set -euo pipefail + +exec env \ + ANTHROPIC_AUTH_TOKEN="$(cat /run/agent/secrets/airouter/auth_token)" \ + ANTHROPIC_BASE_URL="$(cat /run/agent/secrets/airouter/base_url)" \ + claude "$@" \ No newline at end of file diff --git a/harnesses/contexts/airouter/v1/harness.yaml b/harnesses/contexts/airouter/v1/harness.yaml index eedffad..7e4b3d5 100644 --- a/harnesses/contexts/airouter/v1/harness.yaml +++ b/harnesses/contexts/airouter/v1/harness.yaml @@ -8,7 +8,11 @@ provides: [agentic-runner] env: OPENAI_BASE_URL: "https://api.airouter.ch/v1" -secrets_files: - - source: ./provider.sops.env - target: /opt/harness/secrets/airouter/provider.sops.env - encrypted: true +secrets_required: + - name: airouter + account_ref: "airouter" + mount_path: /run/agent/secrets/airouter + mode: "0400" + +scripts: + init: ./init.sh diff --git a/harnesses/contexts/airouter/v1/init.sh b/harnesses/contexts/airouter/v1/init.sh new file mode 100755 index 0000000..0fc4919 --- /dev/null +++ b/harnesses/contexts/airouter/v1/init.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# airouter init — Phase 9 ESO-managed secret mount. +# +# Verifies the ESO-mounted secret files exist; the wrapper +# (`bin/anthropic-compat-wrapper.sh`) reads them at exec time. +# +# Per H-SECRET-4: NO `export` of credentials here. The earlier draft of this +# file exported ANTHROPIC_AUTH_TOKEN and ANTHROPIC_BASE_URL from this script, +# which runs as root under uid-wrapper.sh — even though the export was +# subshell-scoped, the secret was briefly resident in /proc//environ of +# a root process. The wrapper's `exec env VAR=...` pattern is the only +# acceptable credential delivery point. +set -euo pipefail + +SECRETS_DIR="/run/agent/secrets/airouter" + +if [ ! -d "$SECRETS_DIR" ]; then + echo "ERROR: Secret directory $SECRETS_DIR not found. ESO mount may have failed." >&2 + exit 1 +fi + +for f in auth_token base_url; do + if [ ! -r "$SECRETS_DIR/$f" ]; then + echo "ERROR: $SECRETS_DIR/$f not readable. Check ESO ExternalSecret for airouter." >&2 + exit 1 + fi +done + +echo "airouter secrets verified at $SECRETS_DIR" diff --git a/harnesses/contexts/gitea-admin/v1/bin/gitea-admin-wrapper.sh b/harnesses/contexts/gitea-admin/v1/bin/gitea-admin-wrapper.sh new file mode 100755 index 0000000..23d94eb --- /dev/null +++ b/harnesses/contexts/gitea-admin/v1/bin/gitea-admin-wrapper.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# gitea-admin-wrapper.sh — reads the ESO-mounted gitea-admin token at exec time +# and prefixes it as a transient env var to the underlying tool. +# +# M22 Phase 9: token mounted at /run/agent/secrets/gitea-admin/token (read-only, +# tmpfs, mode 0400). The token NEVER enters the wrapper's parent shell — only +# the exec'd tool's environment via `exec env VAR=value cmd`. The brief +# presence in /proc//environ of the tool process is the accepted +# floor (per spec/secrets-runtime.md SR-DISP-7 / H-SECRET-4). +set -euo pipefail + +TOKEN_FILE="/run/agent/secrets/gitea-admin/token" + +# git-credential-helper subcommand: read token and emit git credential format. +# Git invokes us as `gitea-admin-wrapper.sh git-credential-helper get` and +# expects key=value lines on stdout terminated by a blank line. +git_credential_helper() { + if [[ ! -r "$TOKEN_FILE" ]]; then + echo "gitea-admin-wrapper: token file not readable at $TOKEN_FILE" >&2 + exit 1 + fi + local base_url="${GITEA_BASE_URL:-https://gitea.oreillyit.nz}" + local host + host=$(echo "$base_url" | sed 's|https\?://||') + # Trailing blank line per git credential-helper protocol. + printf 'protocol=https\nhost=%s\nusername=git\npassword=%s\n\n' "$host" "$(cat "$TOKEN_FILE")" + exit 0 +} + +case "${1:-}" in + git-credential-helper) + git_credential_helper + ;; + *) + if [[ ! -r "$TOKEN_FILE" ]]; then + echo "gitea-admin-wrapper: token file not readable at $TOKEN_FILE" >&2 + exit 1 + fi + # `exec env VAR=...` keeps the secret out of the wrapper's parent shell + # — it lands only in the exec'd tool's /proc//environ. NEVER use + # `export VAR=` here, which would leak the secret to the wrapper's + # ancestors (H-SECRET-4 violation). + exec env GITEA_ADMIN_TOKEN="$(cat "$TOKEN_FILE")" "$@" + ;; +esac diff --git a/harnesses/contexts/gitea-admin/v1/harness.yaml b/harnesses/contexts/gitea-admin/v1/harness.yaml index 0da19d0..a449dfa 100644 --- a/harnesses/contexts/gitea-admin/v1/harness.yaml +++ b/harnesses/contexts/gitea-admin/v1/harness.yaml @@ -17,11 +17,18 @@ ssh_hosts: identity_secret: SSH_KEY_AI_ENABLEMENT secrets_required: + # ESO-managed gitea-admin token (M22 Phase 9) + - name: gitea-admin + account_ref: "gitea-admin" + mount_path: /run/agent/secrets/gitea-admin + mode: "0400" + # Legacy SSH key (file-based, already delivered as mount) - name: SSH_KEY_AI_ENABLEMENT mount: /home/agent/.ssh/id_ed25519 mode: "0600" -secrets_files: - - source: ./provider.sops.env - target: /opt/harness/secrets/gitea-admin/provider.sops.env - encrypted: true \ No newline at end of file +env: + GITEA_BASE_URL: "https://gitea.oreillyit.nz" + +scripts: + init: ./init.sh \ No newline at end of file diff --git a/harnesses/contexts/gitea-admin/v1/init.sh b/harnesses/contexts/gitea-admin/v1/init.sh new file mode 100755 index 0000000..1e14f2b --- /dev/null +++ b/harnesses/contexts/gitea-admin/v1/init.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# init.sh for gitea-admin harness (M22 Phase 9) +# Sets up non-secret env vars and configures git credential helper. +# Credential token is NOT exported here — only read at exec time by the wrapper. + +set -euo pipefail + +# Non-secret configuration +export GITEA_BASE_URL="${GITEA_BASE_URL:-https://gitea.oreillyit.nz}" + +# Ensure SSH directory exists with correct permissions +mkdir -p /home/agent/.ssh +chmod 700 /home/agent/.ssh + +# Configure git to use the gitea-admin credential helper wrapper +# The wrapper reads the ESO-mounted token at exec time +git config --global credential.helper "!/opt/harness/contexts/gitea-admin/v1/bin/gitea-admin-wrapper.sh git-credential-helper" + +echo "[gitea-admin] init complete" diff --git a/harnesses/contexts/gitea-https/v1/harness.yaml b/harnesses/contexts/gitea-https/v1/harness.yaml index b41e49a..d6c3d56 100644 --- a/harnesses/contexts/gitea-https/v1/harness.yaml +++ b/harnesses/contexts/gitea-https/v1/harness.yaml @@ -12,7 +12,8 @@ git_identity: scripts: init: "./init.sh" -secrets_files: - - source: ./provider.sops.env - target: /opt/harness/secrets/gitea-https/provider.sops.env - encrypted: true +secrets_required: + - name: gitea-https + account_ref: "gitea-https" + mount_path: /run/agent/secrets/gitea-https + mode: "0400" diff --git a/harnesses/contexts/gitea-https/v1/init.sh b/harnesses/contexts/gitea-https/v1/init.sh index f1f4151..d999f56 100755 --- a/harnesses/contexts/gitea-https/v1/init.sh +++ b/harnesses/contexts/gitea-https/v1/init.sh @@ -1,8 +1,8 @@ #!/bin/bash -# Configure git to use GITEA_TOKEN for HTTPS cloning/pushing to gitea.oreillyit.nz +# Configure git to use git credential helper for gitea.oreillyit.nz via HTTPS. # -# Uses a credential helper script that reads the token from the environment. -# This avoids embedding the token in clone URLs (which would appear in logs). +# The token is read from /run/agent/secrets/gitea-https/token at every git +# invocation (not at init time). This avoids the token appearing in logs. set -euo pipefail @@ -11,14 +11,16 @@ CRED_HELPER="/opt/harness/contexts/gitea-https/v1/git-credential-gitea.sh" # Create the credential helper script cat > "$CRED_HELPER" << 'HELPER_EOF' #!/bin/bash -# Git credential helper that provides GITEA_TOKEN for gitea.oreillyit.nz -if [ -z "${GITEA_TOKEN:-}" ]; then - exit 1 -fi +# Git credential helper that provides the token from a mounted file +# for gitea.oreillyit.nz. +# This reads the file at EVERY git invocation, not at init time. +set -euo pipefail +SECRET_FILE=/run/agent/secrets/gitea-https/token +[ -r "$SECRET_FILE" ] || exit 1 echo "protocol=https" echo "host=gitea.oreillyit.nz" echo "username=token" -echo "password=${GITEA_TOKEN}" +echo "password=$(cat $SECRET_FILE)" HELPER_EOF chmod +x "$CRED_HELPER" @@ -26,4 +28,4 @@ chmod +x "$CRED_HELPER" # Configure git to use this credential helper for gitea.oreillyit.nz git config --global credential.https://gitea.oreillyit.nz.helper "$CRED_HELPER" -echo "Git HTTPS credential helper configured for gitea.oreillyit.nz" +echo "Git HTTPS credential helper configured for gitea.oreillyit.nz" \ No newline at end of file diff --git a/harnesses/contexts/gitea-ssh-accelerators/v1/harness.yaml b/harnesses/contexts/gitea-ssh-accelerators/v1/harness.yaml index 78d5a13..dae5536 100644 --- a/harnesses/contexts/gitea-ssh-accelerators/v1/harness.yaml +++ b/harnesses/contexts/gitea-ssh-accelerators/v1/harness.yaml @@ -18,7 +18,8 @@ ssh_hosts: scripts: init: "./init.sh" -secrets_files: - - source: ./ssh-key.sops.env - target: /opt/harness/secrets/gitea-ssh-accelerators/ssh-key.sops.env - encrypted: true +secrets_required: + - name: gitea-ssh-accelerators + account_ref: "gitea-ssh-accelerators" + mount_path: /run/agent/secrets/gitea-ssh-accelerators + mode: "0400" diff --git a/harnesses/contexts/gitea-ssh-accelerators/v1/init.sh b/harnesses/contexts/gitea-ssh-accelerators/v1/init.sh index 9539f8d..b1f3a0d 100755 --- a/harnesses/contexts/gitea-ssh-accelerators/v1/init.sh +++ b/harnesses/contexts/gitea-ssh-accelerators/v1/init.sh @@ -1,29 +1,21 @@ #!/bin/bash +# gitea-ssh-accelerators init: copy the ESO-mounted SSH key to the path the +# harness-init `~/.ssh/config` expects (`IdentityFile /home/agent/.ssh/gitea-oreillyit-nz-accelerators`). +# +# Per H-SECRET-4: NO `export` of credentials. (The earlier draft set +# `GIT_SSH_COMMAND` here — a path, not a credential — but that export dies +# with the subshell and the harness-init's SSH config is the load-bearing +# path anyway.) set -euo pipefail -# Extract SSH private key from decrypted env file for the accelerators identity. -# The meta-init script generates ~/.ssh/config with -# IdentityFile /home/agent/.ssh/gitea-oreillyit-nz-accelerators -# matching the ssh_hosts alias in harness.yaml. +SSH_KEY_SRC="/run/agent/secrets/gitea-ssh-accelerators/id_ed25519" +SSH_KEY_DST="/home/agent/.ssh/gitea-oreillyit-nz-accelerators" -SSH_KEY_FILE="/home/agent/.ssh/gitea-oreillyit-nz-accelerators" - -for env_file in /opt/harness/secrets/gitea-ssh-accelerators/*.decrypted.env /opt/harness/secrets/gitea-ssh-accelerators/*.env; do - [ -f "$env_file" ] || continue - while IFS='=' read -r key value; do - [[ "$key" =~ ^[[:space:]]*# ]] && continue - [[ -z "$key" ]] && continue - if [ "$key" = "GITEA_SSH_KEY" ]; then - mkdir -p /home/agent/.ssh - echo "$value" | base64 -d > "$SSH_KEY_FILE" - chmod 600 "$SSH_KEY_FILE" - chown agent:agent "$SSH_KEY_FILE" - echo "SSH key written to $SSH_KEY_FILE" - break 2 - fi - done < "$env_file" -done - -if [ ! -f "$SSH_KEY_FILE" ]; then - echo "WARNING: GITEA_SSH_KEY not found in any env file under /opt/harness/secrets/gitea-ssh-accelerators/" +if [ ! -r "$SSH_KEY_SRC" ]; then + echo "ERROR: SSH key not found at $SSH_KEY_SRC — ESO ExternalSecret not Ready?" >&2 + exit 1 fi + +mkdir -p /home/agent/.ssh +install -m 0600 -o agent -g agent "$SSH_KEY_SRC" "$SSH_KEY_DST" +echo "gitea-ssh-accelerators: SSH key staged at $SSH_KEY_DST (0600 agent:agent)" diff --git a/harnesses/contexts/gitea-ssh-homelab/v1/harness.yaml b/harnesses/contexts/gitea-ssh-homelab/v1/harness.yaml index 9adadd2..186a129 100644 --- a/harnesses/contexts/gitea-ssh-homelab/v1/harness.yaml +++ b/harnesses/contexts/gitea-ssh-homelab/v1/harness.yaml @@ -18,7 +18,8 @@ ssh_hosts: scripts: init: "./init.sh" -secrets_files: - - source: ./ssh-key.sops.env - target: /opt/harness/secrets/gitea-ssh-homelab/ssh-key.sops.env - encrypted: true +secrets_required: + - name: gitea-ssh-homelab + account_ref: "gitea-ssh-homelab" + mount_path: /run/agent/secrets/gitea-ssh-homelab + mode: "0400" \ No newline at end of file diff --git a/harnesses/contexts/gitea-ssh-homelab/v1/init.sh b/harnesses/contexts/gitea-ssh-homelab/v1/init.sh index 603f3ba..c8ad514 100755 --- a/harnesses/contexts/gitea-ssh-homelab/v1/init.sh +++ b/harnesses/contexts/gitea-ssh-homelab/v1/init.sh @@ -1,29 +1,30 @@ #!/bin/bash +# gitea-ssh-homelab init: copy the ESO-mounted SSH key to the path the +# harness-init `~/.ssh/config` expects. +# +# The harness-init dispatcher (`entrypoint/harness_init.py`) writes +# `~/.ssh/config` from the harness's `ssh_hosts:` block; for this provider +# the entry is `Host gitea.oreillyit.nz-homelab` with +# `IdentityFile /home/agent/.ssh/gitea-oreillyit-nz-homelab`. +# +# We only need to materialise the key file at that path. We MUST NOT append +# our own SSH config block — doing so would (a) duplicate harness-init's +# config (SSH first-match-wins, so the appended block becomes dead) and +# (b) any unaliased `Host gitea.oreillyit.nz` block would collide with +# other gitea harnesses (gitea-https, gitea-admin) when composed. +# +# Per H-SECRET-4: NO `export` of credentials here. The path to the key is +# not a secret; the key content is, and it stays in the file. set -euo pipefail -# Extract SSH private key from decrypted env file for the homelab identity. -# The meta-init script generates ~/.ssh/config with -# IdentityFile /home/agent/.ssh/gitea-oreillyit-nz-homelab -# matching the ssh_hosts alias in harness.yaml. +SSH_KEY_SRC="/run/agent/secrets/gitea-ssh-homelab/id_ed25519" +SSH_KEY_DST="/home/agent/.ssh/gitea-oreillyit-nz-homelab" -SSH_KEY_FILE="/home/agent/.ssh/gitea-oreillyit-nz-homelab" - -for env_file in /opt/harness/secrets/gitea-ssh-homelab/*.decrypted.env /opt/harness/secrets/gitea-ssh-homelab/*.env; do - [ -f "$env_file" ] || continue - while IFS='=' read -r key value; do - [[ "$key" =~ ^[[:space:]]*# ]] && continue - [[ -z "$key" ]] && continue - if [ "$key" = "GITEA_SSH_KEY" ]; then - mkdir -p /home/agent/.ssh - echo "$value" | base64 -d > "$SSH_KEY_FILE" - chmod 600 "$SSH_KEY_FILE" - chown agent:agent "$SSH_KEY_FILE" - echo "SSH key written to $SSH_KEY_FILE" - break 2 - fi - done < "$env_file" -done - -if [ ! -f "$SSH_KEY_FILE" ]; then - echo "WARNING: GITEA_SSH_KEY not found in any env file under /opt/harness/secrets/gitea-ssh-homelab/" +if [ ! -r "$SSH_KEY_SRC" ]; then + echo "ERROR: SSH key not found at $SSH_KEY_SRC — ESO ExternalSecret not Ready?" >&2 + exit 1 fi + +mkdir -p /home/agent/.ssh +install -m 0600 -o agent -g agent "$SSH_KEY_SRC" "$SSH_KEY_DST" +echo "gitea-ssh-homelab: SSH key staged at $SSH_KEY_DST (0600 agent:agent)" diff --git a/harnesses/contexts/gitea-ssh/v1/harness.yaml b/harnesses/contexts/gitea-ssh/v1/harness.yaml index c053f3a..44a4930 100644 --- a/harnesses/contexts/gitea-ssh/v1/harness.yaml +++ b/harnesses/contexts/gitea-ssh/v1/harness.yaml @@ -18,7 +18,8 @@ ssh_hosts: scripts: init: "./init.sh" -secrets_files: - - source: ./ssh-key.sops.env - target: /opt/harness/secrets/gitea-ssh/ssh-key.sops.env - encrypted: true +secrets_required: + - name: gitea-ssh + account_ref: "gitea-ssh" + mount_path: /run/agent/secrets/gitea-ssh + mode: "0400" diff --git a/harnesses/contexts/gitea-ssh/v1/init.sh b/harnesses/contexts/gitea-ssh/v1/init.sh index 69ab84a..ef21962 100755 --- a/harnesses/contexts/gitea-ssh/v1/init.sh +++ b/harnesses/contexts/gitea-ssh/v1/init.sh @@ -1,32 +1,27 @@ #!/bin/bash +# gitea-ssh init: copy the ESO-mounted SSH key to the path the harness-init +# `~/.ssh/config` expects. +# +# The harness-init dispatcher writes `~/.ssh/config` with +# IdentityFile /home/agent/.ssh/gitea-oreillyit-nz-ai-enablement +# so the key must end up at that path with mode 0600 owned by agent. +# +# The ESO mount at /run/agent/secrets/gitea-ssh/private_key is read-only +# (V1VolumeMount(read_only=True)), so chmod against it would fail with EROFS. +# install(1) handles permissions/ownership atomically against the destination. +# +# Per M22 Phase 9 file-only delivery (H-SECRET-4): no credential value enters +# an env var. set -euo pipefail -# Extract SSH private key from decrypted env file and write to the per-host -# identity file path. The meta-init script generates ~/.ssh/config with -# IdentityFile /home/agent/.ssh/gitea-oreillyit-nz-ai-enablement -# matching the ssh_hosts alias in harness.yaml. +SSH_KEY_SRC="/run/agent/secrets/gitea-ssh/private_key" +SSH_KEY_DST="/home/agent/.ssh/gitea-oreillyit-nz-ai-enablement" -SSH_KEY_FILE="/home/agent/.ssh/gitea-oreillyit-nz-ai-enablement" - -# Find the decrypted env file (dispatcher decrypts SOPS at dispatch time for K8s, -# or the meta-init script decrypts for Docker) -for env_file in /opt/harness/secrets/gitea-ssh/*.decrypted.env /opt/harness/secrets/gitea-ssh/*.env; do - [ -f "$env_file" ] || continue - while IFS='=' read -r key value; do - # Skip comments and blank lines - [[ "$key" =~ ^[[:space:]]*# ]] && continue - [[ -z "$key" ]] && continue - if [ "$key" = "GITEA_SSH_KEY" ]; then - mkdir -p /home/agent/.ssh - echo "$value" | base64 -d > "$SSH_KEY_FILE" - chmod 600 "$SSH_KEY_FILE" - chown agent:agent "$SSH_KEY_FILE" - echo "SSH key written to $SSH_KEY_FILE" - break 2 - fi - done < "$env_file" -done - -if [ ! -f "$SSH_KEY_FILE" ]; then - echo "WARNING: GITEA_SSH_KEY not found in any env file under /opt/harness/secrets/gitea-ssh/" +if [ ! -r "$SSH_KEY_SRC" ]; then + echo "ERROR: SSH key not found at $SSH_KEY_SRC — ESO ExternalSecret not Ready?" >&2 + exit 1 fi + +mkdir -p /home/agent/.ssh +install -m 0600 -o agent -g agent "$SSH_KEY_SRC" "$SSH_KEY_DST" +echo "gitea-ssh: SSH key staged at $SSH_KEY_DST (0600 agent:agent)" diff --git a/harnesses/contexts/minimax/v1/bin/anthropic-compat-wrapper.sh b/harnesses/contexts/minimax/v1/bin/anthropic-compat-wrapper.sh new file mode 100755 index 0000000..a0b11c3 --- /dev/null +++ b/harnesses/contexts/minimax/v1/bin/anthropic-compat-wrapper.sh @@ -0,0 +1,9 @@ +#!/bin/bash +# Anthropic-compat wrapper for MiniMax (Phase 9 ESO-managed secrets). +# Reads the api_key file and passes it as ANTHROPIC_AUTH_TOKEN to claude. +# ANTHROPIC_BASE_URL is set in harness.yaml `env:` and flows through. +set -euo pipefail + +exec env \ + ANTHROPIC_AUTH_TOKEN="$(cat /run/agent/secrets/minimax/api_key)" \ + claude "$@" diff --git a/harnesses/contexts/minimax/v1/harness.yaml b/harnesses/contexts/minimax/v1/harness.yaml index a599dc8..1d50c07 100644 --- a/harnesses/contexts/minimax/v1/harness.yaml +++ b/harnesses/contexts/minimax/v1/harness.yaml @@ -11,9 +11,13 @@ env: CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1" DISABLE_PROMPT_CACHING: "1" -secrets_files: - - source: ./provider.sops.env - target: /opt/harness/secrets/minimax/provider.sops.env - encrypted: true +secrets_required: + - name: minimax + account_ref: "minimax" + mount_path: /run/agent/secrets/minimax + mode: "0400" -# TODO: Add network_hosts for api.minimax.io when context harnesses support it \ No newline at end of file +scripts: + init: ./init.sh + +# TODO: Add network_hosts for api.minimax.io when context harnesses support it diff --git a/harnesses/contexts/minimax/v1/init.sh b/harnesses/contexts/minimax/v1/init.sh new file mode 100755 index 0000000..4fcd3f2 --- /dev/null +++ b/harnesses/contexts/minimax/v1/init.sh @@ -0,0 +1,18 @@ +#!/bin/bash +set -euo pipefail + +# Verify the ESO-managed MiniMax api_key file is mounted. The wrapper +# (`bin/anthropic-compat-wrapper.sh`) reads it at exec time and exports +# ANTHROPIC_AUTH_TOKEN to the claude subprocess. +# +# ANTHROPIC_BASE_URL is set in harness.yaml `env:` (not in the K8s Secret), +# so no file check is required for it. + +API_KEY_FILE="/run/agent/secrets/minimax/api_key" + +if [ ! -r "$API_KEY_FILE" ]; then + echo "ERROR: $API_KEY_FILE not readable. Check ESO ExternalSecret acct-." >&2 + exit 1 +fi + +echo "minimax api_key verified at $API_KEY_FILE" diff --git a/harnesses/contexts/z-ai/v1/bin/anthropic-compat-wrapper.sh b/harnesses/contexts/z-ai/v1/bin/anthropic-compat-wrapper.sh new file mode 100755 index 0000000..4a6f4bc --- /dev/null +++ b/harnesses/contexts/z-ai/v1/bin/anthropic-compat-wrapper.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# z-ai Anthropic-compatible wrapper — injects ESO-mounted credentials +# M22 Phase 9 Wave 4 +# Files at /run/agent/secrets/z-ai/ are mounted by the dispatcher via ESO K8s Secret +set -euo pipefail + +SECRETS_DIR="/run/agent/secrets/z-ai" + +exec env \ + ANTHROPIC_AUTH_TOKEN="$(cat "$SECRETS_DIR/auth_token")" \ + ANTHROPIC_BASE_URL="$(cat "$SECRETS_DIR/base_url")" \ + claude "$@" diff --git a/harnesses/contexts/z-ai/v1/harness.yaml b/harnesses/contexts/z-ai/v1/harness.yaml index c307c3c..cb9ca62 100644 --- a/harnesses/contexts/z-ai/v1/harness.yaml +++ b/harnesses/contexts/z-ai/v1/harness.yaml @@ -11,9 +11,13 @@ env: CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: "1" DISABLE_PROMPT_CACHING: "1" -secrets_files: - - source: ./provider.sops.env - target: /opt/harness/secrets/z-ai/provider.sops.env - encrypted: true +secrets_required: + - name: z-ai + account_ref: "z-ai" + mount_path: /run/agent/secrets/z-ai + mode: "0400" + +scripts: + init: "./init.sh" # TODO: Add network_hosts for api.z.ai when context harnesses support it \ No newline at end of file diff --git a/harnesses/contexts/z-ai/v1/init.sh b/harnesses/contexts/z-ai/v1/init.sh new file mode 100755 index 0000000..4153594 --- /dev/null +++ b/harnesses/contexts/z-ai/v1/init.sh @@ -0,0 +1,16 @@ +#!/bin/bash +# z-ai harness init — verifies ESO secret mount exists +# M22 Phase 9 Wave 4 +set -euo pipefail + +echo "=== z-ai/v1 init ===" + +SECRETS_DIR="/run/agent/secrets/z-ai" +if [ ! -d "$SECRETS_DIR" ]; then + echo "ERROR: ESO secret mount not found at $SECRETS_DIR" >&2 + echo "Has the dispatcher been configured with ESO-managed secrets?" >&2 + exit 1 +fi + +echo "z-ai ESO secret mount verified at $SECRETS_DIR" +echo "=== z-ai/v1 init complete ==="