Skip to content

fix(agent-challenge): stop forwarding operator OpenRouter key after cutoff - #67

Open
echobt wants to merge 1 commit into
mainfrom
fix/stop-operator-openrouter-key-forward-post-cutoff
Open

fix(agent-challenge): stop forwarding operator OpenRouter key after cutoff#67
echobt wants to merge 1 commit into
mainfrom
fix/stop-operator-openrouter-key-forward-post-cutoff

Conversation

@echobt

@echobt echobt commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Stop injecting the operator OPENROUTER_API_KEY into miner evaluation containers for new submissions so miners pay for their own inference.
  • Grandfather submissions created before a configurable cutoff so in-flight evaluations keep working.
  • Post-cutoff missing keys fail with a clear error naming the var (not a silent zero score).

Why

The operator was paying for miner inference: harbor_forward_env_vars (prod: OPENROUTER_API_KEY) was read from the validator process env and injected into every terminal-bench job. That forward also shadowed any miner-supplied key of the same name. Product requirement: miners must put their API key in submission env for upcoming submissions only.

Behavior

Submission created_at Operator key forwarded? Miner key
before cutoff yes (unchanged) shadowed by operator if both present (legacy)
at/after cutoff no flows via sanitize_miner_env_for_job; not shadowed
at/after cutoff, no key n/a ValueError naming the missing var

Cutoff keying: submission.created_at, not evaluation start time. Re-evaluating an old submission later still grandfathers it. Boundary instant (created_at == cutoff) is post-cutoff.

Config (prod):

  • Field: operator_env_forward_cutoff_at
  • Env: CHALLENGE_OPERATOR_ENV_FORWARD_CUTOFF_AT (ISO-8601 UTC, e.g. 2026-07-30T12:00:00+00:00)
  • Unset / null = legacy always-forward (safe until ops sets the cutoff)

Changes

  • sdk/config.py — new optional datetime setting
  • evaluation/runner.py_should_forward_operator_env, cutoff-aware _terminal_bench_env, plumb submission.created_at at all call sites
  • tests/test_operator_env_forward_cutoff.py — pre/post/boundary/missing-key/env-override
  • config.example.yaml, test_config.py default assertion

Test plan

  • RED: 6 new tests failed before implementation (missing attribute)
  • GREEN: 6 new tests pass after implementation
  • Adjacent: test_miner_env_lock, test_llm_model_reaches_agent, test_terminal_bench_env_keeps_controlled_writable_cache, test_normal_validator_defaults
  • Full agent-challenge suite A/B vs main baseline:
    • main: 24 failed, 2307 passed, 4 skipped
    • branch: 24 failed, 2313 passed, 4 skipped (+6 new; zero new failures)
  • ruff check + ruff format on touched files

CI

  • Waiting for required checks to go green on this head SHA.

Notes

  • Does not touch ac-keyrelease-ratls, emission shares, weights, or metagraph.
  • Does not deploy or rotate keys.
  • Ops must set CHALLENGE_OPERATOR_ENV_FORWARD_CUTOFF_AT at deploy time to the desired grandfather boundary (typically deploy time).

Summary by CodeRabbit

  • New Features

    • Added an optional cutoff time for forwarding operator environment variables to submissions.
    • Submissions created before the cutoff retain the existing forwarding behavior.
    • Submissions created at or after the cutoff use miner-provided values and require necessary variables to be supplied.
    • Added support for configuring the cutoff through challenge settings or an environment variable.
  • Bug Fixes

    • Prevented operator credentials from overriding miner-provided credentials after the configured cutoff.
    • Added clear validation errors when required credentials are missing.

…utoff

The operator was paying for miner inference by injecting OPENROUTER_API_KEY
from the validator process into every evaluation container via
harbor_forward_env_vars, and that forward also shadowed any miner-supplied
key. Miners must supply their own key for new submissions.

Grandfather submissions created before operator_env_forward_cutoff_at so
in-flight work keeps the previous behavior. Comparison uses
submission.created_at (not evaluation start) so a later re-eval of an old
submission stays grandfathered. The boundary instant is post-cutoff.
Post-cutoff missing keys raise a ValueError that names the var and is
surfaced through the existing terminal-bench failure path.

Env: CHALLENGE_OPERATOR_ENV_FORWARD_CUTOFF_AT (ISO-8601 UTC). Unset keeps
legacy always-forward until ops configures a cutoff.
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The challenge configuration now accepts an optional UTC cutoff timestamp. Terminal-Bench environment construction uses submission creation time to disable operator environment forwarding at or after the cutoff, validates required miner variables, and propagates timestamps through all execution paths.

Operator environment forwarding cutoff

Layer / File(s) Summary
Cutoff configuration contract
packages/challenges/agent-challenge/src/agent_challenge/sdk/config.py, packages/challenges/agent-challenge/config.example.yaml, packages/challenges/agent-challenge/tests/test_config.py, packages/challenges/agent-challenge/tests/test_operator_env_forward_cutoff.py
Adds the optional operator_env_forward_cutoff_at setting, documents its environment variable, and verifies default and environment-driven parsing.
Forwarding decision and validation
packages/challenges/agent-challenge/src/agent_challenge/evaluation/runner.py, packages/challenges/agent-challenge/tests/test_operator_env_forward_cutoff.py
Uses submission timestamps to control operator environment injection, treats the cutoff instant as post-cutoff, preserves miner keys, and raises errors for missing required keys.
Submission timestamp propagation
packages/challenges/agent-challenge/src/agent_challenge/evaluation/runner.py
Passes submission.created_at through task, durable runner, wrapper, and no-phala host execution paths.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Submission
  participant TerminalBenchRunner
  participant ChallengeSettings
  participant TerminalBenchEnv
  Submission->>TerminalBenchRunner: provide created_at
  TerminalBenchRunner->>ChallengeSettings: read operator_env_forward_cutoff_at
  TerminalBenchRunner->>TerminalBenchEnv: build environment with forwarding decision
  TerminalBenchEnv-->>TerminalBenchRunner: return validated environment
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main behavior change: stopping operator OpenRouter key forwarding after a cutoff.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/stop-operator-openrouter-key-forward-post-cutoff

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.

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@packages/challenges/agent-challenge/tests/test_operator_env_forward_cutoff.py`:
- Around line 21-22: Replace the API-key-shaped literals assigned to
OPERATOR_KEY and MINER_KEY with clearly non-secret sentinel fixture strings that
do not resemble real OpenRouter tokens, while preserving their distinct roles in
the tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 35f1af22-7d44-4e50-86d3-dca3b2e0ab7c

📥 Commits

Reviewing files that changed from the base of the PR and between 7b076d3 and f253f19.

📒 Files selected for processing (5)
  • packages/challenges/agent-challenge/config.example.yaml
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/runner.py
  • packages/challenges/agent-challenge/src/agent_challenge/sdk/config.py
  • packages/challenges/agent-challenge/tests/test_config.py
  • packages/challenges/agent-challenge/tests/test_operator_env_forward_cutoff.py

Comment on lines +21 to +22
OPERATOR_KEY = "sk-or-v1-operator-forward-test-value"
MINER_KEY = "sk-or-v1-miner-supplied-test-value"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Replace API-key-shaped test literals with non-secret sentinels.

These literals mimic full OpenRouter API tokens, which violates the repository rule even in test evidence. Use clearly non-secret fixture values instead.

Proposed fix
-OPERATOR_KEY = "<redacted API-key-shaped value>"
-MINER_KEY = "<redacted API-key-shaped value>"
+OPERATOR_KEY = "operator-test-sentinel"
+MINER_KEY = "miner-test-sentinel"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
OPERATOR_KEY = "sk-or-v1-operator-forward-test-value"
MINER_KEY = "sk-or-v1-miner-supplied-test-value"
OPERATOR_KEY = "operator-test-sentinel"
MINER_KEY = "miner-test-sentinel"
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@packages/challenges/agent-challenge/tests/test_operator_env_forward_cutoff.py`
around lines 21 - 22, Replace the API-key-shaped literals assigned to
OPERATOR_KEY and MINER_KEY with clearly non-secret sentinel fixture strings that
do not resemble real OpenRouter tokens, while preserving their distinct roles in
the tests.

Source: Coding guidelines

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