Skip to content

feat(agent-challenge): remove Phala TEE product path (host-trust only) - #55

Merged
echobt merged 3 commits into
mainfrom
feat/phala-delete
Jul 29, 2026
Merged

feat(agent-challenge): remove Phala TEE product path (host-trust only)#55
echobt merged 3 commits into
mainfrom
feat/phala-delete

Conversation

@echobt

@echobt echobt commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

Dedicated T40 Phala-delete PR: remove Phala TEE product surfaces and necessary rewiring so the product path is unattested / host-trust only.

Implements T39 gate decisions (.omo/evidence/attested-isolated-platform/T39-gate-decisions/DECISIONS.md).

Removed (Phala / TEE-only product path)

  • Dual production flags (phala_attestation_enabledattested_review_enabled) — permanently rejected at settings construction
  • AttestationGate TDX product path → host-trust shim (no quote verify)
  • blackbox_attestation_chain.py
  • Public TEE math product claims (public_tee always unavailable)
  • Selfdeploy Phala CVM client/CLI/lifecycle modules
  • Canonical attested emit / compose / public fullchain / secrets_scan product modules
  • Pure Phala/selfdeploy/quote/dual-flag tests

Kept

  • package_tree_sha compute + DB + plan bind + guest/host recompute
  • AGATE residual materials (rewired: host residual kinds under host-trust)
  • no_phala / unattested honesty path (is_unattested_execution_enabled alias)
  • keyrelease/ sources untouched (score path no longer requires KR grant)
  • Constation family not bulk-deleted (T39 DEFER_CONSTATION)

Rewired

  • Residual admit: host kinds under dual-off / host-trust
  • Score chain: host-trust admit (skip KR + TDX score-domain legs; keep tree + residual policy + AST refuse)
  • Weights: never require attestation_verified
  • Auth plan: KR endpoint optional under no_phala
  • AGENTS.md invariant 6 → host-trust wording
  • Docs: host-trust.md, no-phala-mode honesty banner

Non-claims

This PR does not claim TEE, tamper-proof execution, or independent third-party attestation. Host-trust only.

Test plan

  • Core: test_package_tree_sha, test_no_phala_*, test_llm_rules_residual_gate, test_docs_contract80 passed
  • Broader agent-challenge (deselected live/e2e/keyrelease-heavy) — 1806 passed, 3 skipped
  • keyrelease/ git diff empty vs main
  • CI full suite (residual dual-flag/KR-heavy tests may need T41 follow-up)

Residual risk (T41)

  • Some KR/own_runner decrypt/replay-audit tests still assume dual-flag or CVM emit paths
  • Review compose/deployment modules retained for import graph (dual flags force product path off)
  • Master agent_challenge_attested_routes_enabled remains False (commented)

Summary by CodeRabbit

  • New Features
    • Added host-trust, unattested execution as the supported evaluation path.
    • Added CHALLENGE_UNATTESTED_EXECUTION configuration support (with related aliases).
  • Changes
    • Removed Phala-based attestation/TEE verification, CVM deployment, and self-deployment workflows; related operations now fail closed.
    • Host-trust scoring now relies on package residual rules and package-tree integrity proof.
    • Phala/dual-flag paths remain permanently disabled.
  • Documentation
    • Updated host-trust and no-Phala guidance to match the T40/T41 product path.
  • Tests
    • Removed Phala/TEE-focused canonical and acceptance test coverage.

Delete Phala CVM/selfdeploy/attestation product surfaces and dual-flag
production path. Product path is unattested host-trust (no_phala /
CHALLENGE_UNATTESTED_EXECUTION). Keep package_tree_sha, AGATE residual
(host kinds), and keyrelease/ sources untouched. Score path no longer
requires KR grant or TDX measurement.
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@echobt, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 43 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 6574eb9f-fede-4894-9e70-8f07fb6e8f33

📥 Commits

Reviewing files that changed from the base of the PR and between 64e534c and 89ffc26.

📒 Files selected for processing (24)
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/attested_result.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/live_registry.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/attestation.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/execution_pool.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/no_phala.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/own_runner_backend.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/raw_weight_push.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/runner.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/tbench_integrity.py
  • packages/challenges/agent-challenge/src/agent_challenge/review/or_outcome_bind.py
  • packages/challenges/agent-challenge/src/agent_challenge/review/public_tee.py
  • packages/challenges/agent-challenge/src/agent_challenge/sdk/config.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/lifecycle.py
  • packages/challenges/agent-challenge/tests/test_ac_execution_pool_live.py
  • packages/challenges/agent-challenge/tests/test_docs_contract.py
  • packages/challenges/agent-challenge/tests/test_eval_prepare_dataset_unavailable.py
  • packages/challenges/agent-challenge/tests/test_miner_env_lock.py
  • packages/challenges/agent-challenge/tests/test_no_phala_mode.py
  • packages/challenges/agent-challenge/tests/test_no_phala_pipeline.py
  • packages/challenges/agent-challenge/tests/test_openrouter_review_provider.py
  • packages/challenges/agent-challenge/tests/test_package_tree_sha.py
  • src/base/config/settings.py
  • tests/unit/test_master_embed_env_file.py
📝 Walkthrough

Walkthrough

This change removes Phala TEE/self-deploy and attestation paths, enforces host-trust-only configuration, updates evaluation and scoring admission, and documents the T40 unattested execution model.

Changes

Host-trust execution transition

Layer / File(s) Summary
Host-trust configuration and mode selection
AGENTS.md, packages/challenges/agent-challenge/config.example.yaml, packages/challenges/agent-challenge/src/agent_challenge/{sdk/config.py,evaluation/no_phala.py}, src/base/config/settings.py
Attestation flags are forced off, CHALLENGE_UNATTESTED_EXECUTION is added with precedence, and host-trust mode gains canonical aliases and updated policy text.
Host-trust admission and scoring
packages/challenges/agent-challenge/src/agent_challenge/evaluation/{authorization.py,llm_rules_residual.py,score_chain_gate.py,weights.py}
Evaluation authorization, residual checks, score admission, and weighting use host-trust rules while retaining package_tree_sha handling and skipping Phala-specific verification.
Attestation and public TEE removal
packages/challenges/agent-challenge/src/agent_challenge/{canonical/attested_result.py,evaluation/attestation.py,evaluation/own_runner_backend.py,review/*}
Quote emission and verification, measured review admission, and public TEE projections are removed or replaced with fail-closed stubs.
Self-deploy shutdown
packages/challenges/agent-challenge/docker/review/phala_pre_launch.sh, packages/challenges/agent-challenge/src/agent_challenge/{canonical/entrypoint.py,selfdeploy/*}, packages/challenges/agent-challenge/tests/{test_no_phala_mode.py,test_eval_prepare_dataset_unavailable.py}
Phala pre-launch and self-deploy interfaces now fail as removed, and tests expect removed module imports or updated configuration errors.
Host-trust product documentation and test wiring
packages/challenges/agent-challenge/docs/*, packages/challenges/agent-challenge/tests/{test_keyrelease_durable_state.py,test_replay_audit_*.py,test_report_http_status_envelope.py}, tests/unit/test_master_embed_env_file.py
Documentation and tests describe host-trust execution, disabled replay sampling, required package-tree proofs, and isolated unattested environment variables.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.72% 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 change: removing the Phala TEE path in favor of host-trust-only execution.
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 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Fix failing CI checks
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/phala-delete

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.

Drop pure-Phala guest KR tests and rewrite dual-flag fixtures for
host-trust-only settings. Restore review pre-launch stub header, pin
dood socket constants without canonical.compose, and scrub docs/config
templates so no TEE product path remains. Full AC suite: 2216 passed
with live/e2e/network deselected only.

@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: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/challenges/agent-challenge/src/agent_challenge/evaluation/score_chain_gate.py (1)

546-557: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Require package residual on host-trust score admission too.

require_package_residual=False if host_trust else bool(dual_flags_on) reaches admit_eval_cvm_fresh_review(...), but after the dual_flags_on refuse at line 468 host-trust is always True, so this always passes False. The existing dual-flag path requires residual before TEE/eval prepare, but production host-trust score admission currently does not enforce the package residual when the dual-flag path is unavailable.

🤖 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/src/agent_challenge/evaluation/score_chain_gate.py`
around lines 546 - 557, Update the require_package_residual argument in the
admit_eval_cvm_fresh_review call so host-trust score admission also requires
package residual when the dual-flag path is unavailable. Remove the
host_trust-based false override and preserve the existing dual_flags_on
requirement semantics.

Source: Coding guidelines

🧹 Nitpick comments (4)
packages/challenges/agent-challenge/src/agent_challenge/sdk/config.py (1)

405-423: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Validator correctly hard-forbids dual flags; downstream production guards become permanent no-ops.

validate_attested_topology now correctly rejects any attempt to enable phala_attestation_enabled/attested_review_enabled. As a consequence, require_eval_result_signer_for_production, require_review_evidence_encryption_for_production, and require_dcap_qvl_binary_for_production (unchanged, lines 466-531) can never execute their body anymore — their guard condition attested_review_enabled and phala_attestation_enabled can never be true post-construction. Same dead-code pattern recurs in weights.py (require_attestation) and score_chain_gate.py. Consider removing/deprecating these now-unreachable methods in this PR or a fast T41 follow-up, rather than leaving vestigial fail-closed checks that no longer fail closed on anything.

🤖 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/src/agent_challenge/sdk/config.py` around
lines 405 - 423, The new validate_attested_topology invariant makes the
attestation-dependent guards unreachable. Remove or deprecate
require_eval_result_signer_for_production,
require_review_evidence_encryption_for_production, and
require_dcap_qvl_binary_for_production, and track the equivalent
require_attestation and score_chain_gate checks for the same cleanup in this PR
or a fast follow-up.
packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py (1)

423-455: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Redundant branch: if not host_trust returns the same value as the fallthrough.

In the unknown-residual-kind elif branch, the if not host_trust: return REFUSE_RESIDUAL_KIND(...) and the unconditional fallthrough return REFUSE_RESIDUAL_KIND(...) right below it construct identical PackageResidualAdmission objects. The conditional is dead — both branches behave the same, which is correct (unknown kinds always refuse) but reads as if host_trust matters here when it doesn't. Simplify by dropping the redundant early return.

🤖 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/src/agent_challenge/evaluation/llm_rules_residual.py`
around lines 423 - 455, In the unknown residual-kind branch of the admission
logic, remove the redundant “if not host_trust” conditional and its duplicate
return. Keep a single unconditional PackageResidualAdmission return with
reason_code REFUSE_RESIDUAL_KIND, while preserving the host-only handling and
measured-kind flow.
packages/challenges/agent-challenge/src/agent_challenge/evaluation/weights.py (1)

244-321: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Functionally correct for host-trust — eligibility no longer requires attestation/review verification, matching the "no TEE, no attestation" model. require_attestation-guarded blocks (267-289, 253-265) are now unreachable; see consolidated dead-code note.

🤖 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/src/agent_challenge/evaluation/weights.py`
around lines 244 - 321, Remove the now-unreachable attestation-specific logic
from get_weights: eliminate the constant require_attestation guard, the
direct-population fallback, and the attestation_verified/review_status
population blocks. Preserve the host-trust eligibility flow using
scoring_evaluation_jobs_statement, required_task_count, and
is_reward_eligible_job without attestation or review checks.
packages/challenges/agent-challenge/src/agent_challenge/evaluation/score_chain_gate.py (1)

623-687: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

KR/score-domain verification branches are unreachable, and their outputs silently become None under host-trust.

Given dual_flags_on=True is already refused at line 468-475, host_trust is always True by the time execution reaches lines 623-687 — the not host_trust branches calling verify_key_release_grant / verify_score_domain_binding can never run in this function as currently wired. That's dead code (fold into the same cleanup as weights.py/sdk/config.py), but more importantly kr_hex and score_rd are now always None here, and get returned as ScoreChainAdmission.key_release_binding_hex / score_report_data_hex — fields that previously always carried a computed hex digest on success. Please confirm downstream consumers (e.g. own_runner_backend.py, persistence/serialization of ScoreChainAdmission) tolerate None for these fields.

🤖 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/src/agent_challenge/evaluation/score_chain_gate.py`
around lines 623 - 687, Update the score-chain admission flow around
verify_key_release_grant, verify_score_domain_binding, and ScoreChainAdmission
so host-trust success does not silently emit None for key_release_binding_hex or
score_report_data_hex. Inspect downstream consumers such as
own_runner_backend.py and ScoreChainAdmission persistence/serialization, then
either preserve the required computed digests or explicitly update and validate
the consumers’ optional-field contract. Remove the unreachable non-host-trust
branches if no longer supported.
🤖 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/config.example.yaml`:
- Around line 56-61: Confirm the host-trust behavior in ChallengeSettings and
replay_audit_sampler_from_settings: either document that replay auditing is
intentionally disabled despite the configured replay_audit_* rates, or rewire
the host-trust path so those rates can enable sampling without
phala_attestation_enabled. Keep the existing fail-closed behavior for mixed or
single-sided attestation settings.

In `@packages/challenges/agent-challenge/docs/no-phala-mode.md`:
- Around line 1-3: Update the no-phala-mode documentation to consistently
describe the permanent host-trust product path: remove or revise “temporary
escape hatch” and production-weight prohibition language, and align mode/status
and scoring guidance with host-trust.md’s production host-trust-only policy. Do
not retain contradictory TEE, attestation, or legacy-status claims unless the
document is explicitly marked as deprecated.

In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/attestation.py`:
- Around line 82-106: Update the agent-hash validation in the attestation
decision flow to reject verification when either expected or submitted hash is
empty. In the logic after computing expected and got within the surrounding
attestation method, return AttestationOutcome.VERIFICATION_FAILED before the
mismatch check, using an appropriate missing-hash reason; only admit VERIFIED
when both hashes are present and equal.

In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py`:
- Around line 500-518: Update the authorization preparation flow around
_authorized_review_digest to require residual validation for host-trust
evaluations even when dual TEE flags are disabled. Set require_residual to true,
and pass the computed package_residual into
admit_eval_cvm_launch_from_assignment(); preserve package_tree_sha proof
validation and ensure no_phala/unattested_execution paths fail closed when
residual is missing or not allowed.

In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/own_runner_backend.py`:
- Around line 232-235: Update the forced fallback around
_phala_attestation_enabled so every fallback result is explicitly marked
unattested, ensuring _emit_job_result produces attested=false and
attestation_status=unattested even when host-trust aliases are unset. Keep
is_no_phala_enabled() limited to optional artifact-proof behavior rather than
controlling the result-attestation marker.

---

Outside diff comments:
In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/score_chain_gate.py`:
- Around line 546-557: Update the require_package_residual argument in the
admit_eval_cvm_fresh_review call so host-trust score admission also requires
package residual when the dual-flag path is unavailable. Remove the
host_trust-based false override and preserve the existing dual_flags_on
requirement semantics.

---

Nitpick comments:
In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py`:
- Around line 423-455: In the unknown residual-kind branch of the admission
logic, remove the redundant “if not host_trust” conditional and its duplicate
return. Keep a single unconditional PackageResidualAdmission return with
reason_code REFUSE_RESIDUAL_KIND, while preserving the host-only handling and
measured-kind flow.

In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/score_chain_gate.py`:
- Around line 623-687: Update the score-chain admission flow around
verify_key_release_grant, verify_score_domain_binding, and ScoreChainAdmission
so host-trust success does not silently emit None for key_release_binding_hex or
score_report_data_hex. Inspect downstream consumers such as
own_runner_backend.py and ScoreChainAdmission persistence/serialization, then
either preserve the required computed digests or explicitly update and validate
the consumers’ optional-field contract. Remove the unreachable non-host-trust
branches if no longer supported.

In
`@packages/challenges/agent-challenge/src/agent_challenge/evaluation/weights.py`:
- Around line 244-321: Remove the now-unreachable attestation-specific logic
from get_weights: eliminate the constant require_attestation guard, the
direct-population fallback, and the attestation_verified/review_status
population blocks. Preserve the host-trust eligibility flow using
scoring_evaluation_jobs_statement, required_task_count, and
is_reward_eligible_job without attestation or review checks.

In `@packages/challenges/agent-challenge/src/agent_challenge/sdk/config.py`:
- Around line 405-423: The new validate_attested_topology invariant makes the
attestation-dependent guards unreachable. Remove or deprecate
require_eval_result_signer_for_production,
require_review_evidence_encryption_for_production, and
require_dcap_qvl_binary_for_production, and track the equivalent
require_attestation and score_chain_gate checks for the same cleanup in this PR
or a fast follow-up.
🪄 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: 66a5cde0-ac90-42eb-adaa-8eb7b34f1e34

📥 Commits

Reviewing files that changed from the base of the PR and between 32fd012 and 17215e5.

📒 Files selected for processing (104)
  • AGENTS.md
  • packages/challenges/agent-challenge/config.example.yaml
  • packages/challenges/agent-challenge/docker/review/phala_pre_launch.sh
  • packages/challenges/agent-challenge/docs/host-trust.md
  • packages/challenges/agent-challenge/docs/no-phala-mode.md
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/attested_result.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/compose.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/entrypoint.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/public_client_fullchain.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/secrets_scan.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/attestation.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/blackbox_attestation_chain.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/no_phala.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/own_runner_backend.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/score_chain_gate.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/weights.py
  • packages/challenges/agent-challenge/src/agent_challenge/review/or_outcome_bind.py
  • packages/challenges/agent-challenge/src/agent_challenge/review/public_tee.py
  • packages/challenges/agent-challenge/src/agent_challenge/sdk/config.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/__init__.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/__main__.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/cli.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/eval.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/lifecycle.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/measurements.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/phala.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/plan.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/result.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/review.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/run.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/shapes.py
  • packages/challenges/agent-challenge/tests/phala_quote_golden_vector.json
  • packages/challenges/agent-challenge/tests/test_acceptance_permanent_park_shortcircuit.py
  • packages/challenges/agent-challenge/tests/test_agate_tee_auth_after_verify.py
  • packages/challenges/agent-challenge/tests/test_canonical_attested_result.py
  • packages/challenges/agent-challenge/tests/test_canonical_compose.py
  • packages/challenges/agent-challenge/tests/test_canonical_image_repro.py
  • packages/challenges/agent-challenge/tests/test_canonical_measurement.py
  • packages/challenges/agent-challenge/tests/test_canonical_report_data.py
  • packages/challenges/agent-challenge/tests/test_challenge_acceptance_gating.py
  • packages/challenges/agent-challenge/tests/test_cross_integration_compat_offline.py
  • packages/challenges/agent-challenge/tests/test_cross_integration_e2e_offline.py
  • packages/challenges/agent-challenge/tests/test_direct_eval_verification.py
  • packages/challenges/agent-challenge/tests/test_direct_result_admission_hardening.py
  • packages/challenges/agent-challenge/tests/test_dualflag_evalrun_task_rows.py
  • packages/challenges/agent-challenge/tests/test_eval_authorization_ledger.py
  • packages/challenges/agent-challenge/tests/test_eval_compose_hash_determine.py
  • packages/challenges/agent-challenge/tests/test_eval_compose_phala_provision_parity.py
  • packages/challenges/agent-challenge/tests/test_eval_deploy_shape_pin_loud_fail.py
  • packages/challenges/agent-challenge/tests/test_eval_deploy_token_handoff.py
  • packages/challenges/agent-challenge/tests/test_eval_keyrelease_ratls_bootstrap.py
  • packages/challenges/agent-challenge/tests/test_eval_prepare_dataset_unavailable.py
  • packages/challenges/agent-challenge/tests/test_eval_progress_env_wiring.py
  • packages/challenges/agent-challenge/tests/test_eval_wire_contracts.py
  • packages/challenges/agent-challenge/tests/test_evaluation_lazy_import.py
  • packages/challenges/agent-challenge/tests/test_golden_encrypted_at_rest.py
  • packages/challenges/agent-challenge/tests/test_image_backward_compat_flagoff.py
  • packages/challenges/agent-challenge/tests/test_kr_host_pin.py
  • packages/challenges/agent-challenge/tests/test_live_registry.py
  • packages/challenges/agent-challenge/tests/test_no_phala_mode.py
  • packages/challenges/agent-challenge/tests/test_ordered_selfdeploy_cli.py
  • packages/challenges/agent-challenge/tests/test_os_image_hash_identity_reconcile.py
  • packages/challenges/agent-challenge/tests/test_own_runner_backend_phala.py
  • packages/challenges/agent-challenge/tests/test_phala_client_auth_region.py
  • packages/challenges/agent-challenge/tests/test_phala_create_ack_and_cli_token.py
  • packages/challenges/agent-challenge/tests/test_post_grant_stage_markers_and_score_quote_normalize.py
  • packages/challenges/agent-challenge/tests/test_product_blackbox_attestation_chain.py
  • packages/challenges/agent-challenge/tests/test_product_durable_kr_grant_score.py
  • packages/challenges/agent-challenge/tests/test_product_eval_agent_openrouter_measured.py
  • packages/challenges/agent-challenge/tests/test_product_gateway_free_policy.py
  • packages/challenges/agent-challenge/tests/test_product_or_outcome_bind.py
  • packages/challenges/agent-challenge/tests/test_product_score_chain_failclosed.py
  • packages/challenges/agent-challenge/tests/test_public_client_fullchain_export.py
  • packages/challenges/agent-challenge/tests/test_public_tee_math.py
  • packages/challenges/agent-challenge/tests/test_quote_golden_vector.py
  • packages/challenges/agent-challenge/tests/test_quote_measurement_mismatch_diag.py
  • packages/challenges/agent-challenge/tests/test_quote_mismatch_prefix_emit.py
  • packages/challenges/agent-challenge/tests/test_replay_audit_attested_population.py
  • packages/challenges/agent-challenge/tests/test_residual_orch_probes.py
  • packages/challenges/agent-challenge/tests/test_review_api_base_hardcode.py
  • packages/challenges/agent-challenge/tests/test_review_deployment.py
  • packages/challenges/agent-challenge/tests/test_runtime_image_dcap_qvl_bake.py
  • packages/challenges/agent-challenge/tests/test_runtime_image_phala_pre_launch_package.py
  • packages/challenges/agent-challenge/tests/test_score_event_log_event_id_project.py
  • packages/challenges/agent-challenge/tests/test_score_gate_key_provider_and_canonical_emit.py
  • packages/challenges/agent-challenge/tests/test_score_vm_config_project.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_cli.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_client_auth_hardening.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_deploy.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_docs_accuracy.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_live_registry_wiring.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_measurements.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_optin.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_ordered_trust_hardening.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_rejection_observability.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_run_result.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_shapes_disk.py
  • packages/challenges/agent-challenge/tests/test_selfdeploy_teardown_http.py
  • packages/challenges/agent-challenge/tests/test_sizing_compose_hash_freeze.py
  • packages/challenges/agent-challenge/tests/test_tbench_integrity_policy.py
  • packages/challenges/agent-challenge/tests/test_weights_canonical_population.py
  • src/base/config/settings.py
💤 Files with no reviewable changes (29)
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/main.py
  • packages/challenges/agent-challenge/tests/phala_quote_golden_vector.json
  • packages/challenges/agent-challenge/tests/test_agate_tee_auth_after_verify.py
  • packages/challenges/agent-challenge/tests/test_canonical_compose.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/secrets_scan.py
  • packages/challenges/agent-challenge/tests/test_canonical_attested_result.py
  • packages/challenges/agent-challenge/tests/test_acceptance_permanent_park_shortcircuit.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/run.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/compose.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/eval.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/measurements.py
  • packages/challenges/agent-challenge/tests/test_canonical_report_data.py
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/public_client_fullchain.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/result.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/shapes.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/cli.py
  • packages/challenges/agent-challenge/tests/test_cross_integration_e2e_offline.py
  • packages/challenges/agent-challenge/tests/test_challenge_acceptance_gating.py
  • packages/challenges/agent-challenge/tests/test_canonical_measurement.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/plan.py
  • packages/challenges/agent-challenge/tests/test_canonical_image_repro.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/review.py
  • packages/challenges/agent-challenge/src/agent_challenge/selfdeploy/phala.py
  • packages/challenges/agent-challenge/tests/test_dualflag_evalrun_task_rows.py
  • packages/challenges/agent-challenge/tests/test_direct_eval_verification.py
  • packages/challenges/agent-challenge/tests/test_direct_result_admission_hardening.py
  • packages/challenges/agent-challenge/tests/test_cross_integration_compat_offline.py
  • packages/challenges/agent-challenge/src/agent_challenge/evaluation/blackbox_attestation_chain.py
  • packages/challenges/agent-challenge/tests/test_eval_prepare_dataset_unavailable.py

Comment thread packages/challenges/agent-challenge/config.example.yaml
Comment on lines +1 to +3
> **T40 product path:** Phala TEE dual flags and CVM attestation are **removed**.
> This document describes the **host-trust unattested** product mode.
> Never claim TEE, tamper-proof execution, or independent verification.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Align this document with the permanent host-trust product path.

The new introduction conflicts with later “temporary escape hatch” language and its prohibition on production weight use, while host-trust.md states production scoring is host-trust only. Update the remaining mode/status and weighting guidance, or clearly label this as a deprecated legacy document.

🤖 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/docs/no-phala-mode.md` around lines 1 -
3, Update the no-phala-mode documentation to consistently describe the permanent
host-trust product path: remove or revise “temporary escape hatch” and
production-weight prohibition language, and align mode/status and scoring
guidance with host-trust.md’s production host-trust-only policy. Do not retain
contradictory TEE, attestation, or legacy-status claims unless the document is
explicitly marked as deprecated.

Comment on lines 82 to 106
if not nonce_outstanding:
return AttestationDecision.of(AttestationOutcome.VERIFICATION_FAILED)
if consume_nonce:
if self.nonce_validator is None:
return AttestationDecision.of(AttestationOutcome.VERIFICATION_FAILED)
if self.nonce_validator.consume(eval_plan["score_nonce"]) is not NonceState.OK:
return AttestationDecision.of(AttestationOutcome.VERIFICATION_FAILED)
return AttestationDecision.of(AttestationOutcome.VERIFIED)

def _verify(
self,
execution_proof: Mapping[str, Any],
binding: Mapping[str, Any],
expected_agent_hash: str,
) -> AttestationOutcome:
attestation = execution_proof.get("attestation")
if not isinstance(attestation, Mapping):
return AttestationOutcome.VERIFICATION_FAILED

quote = attestation.get("tdx_quote")
event_log = attestation.get("event_log")
if not isinstance(quote, str) or not quote or not isinstance(event_log, list):
return AttestationOutcome.VERIFICATION_FAILED

# -- the run identity the VALIDATOR expects (never trusted blindly) ---- #
agent_hash = binding.get("agent_hash")
task_ids = binding.get("task_ids")
scores = binding.get("scores")
scores_digest = binding.get("scores_digest")
nonce = binding.get("validator_nonce")
if (
not isinstance(agent_hash, str)
or not isinstance(task_ids, list)
or not isinstance(scores, Mapping)
or not isinstance(scores_digest, str)
or not isinstance(nonce, str)
or not nonce
):
return AttestationOutcome.VERIFICATION_FAILED

# scores_digest must be the digest of the scores the result reports, so a
# score cannot be altered without breaking the report_data binding.
if rd.scores_digest(scores) != scores_digest:
return AttestationOutcome.VERIFICATION_FAILED
# the attested agent must be the submission actually under evaluation.
if agent_hash != expected_agent_hash:
return AttestationOutcome.VERIFICATION_FAILED

# dependencies missing -> fail closed (never accept-any).
if self.quote_verifier is None or not self.allowlist or self.nonce_validator is None:
return AttestationOutcome.VERIFICATION_FAILED

try:
report = parse_td_report(quote)
except QuoteStructureError:
return AttestationOutcome.VERIFICATION_FAILED

# cryptographic signature/cert-chain + TCB posture (trust root).
try:
verdict = self.quote_verifier.verify(quote)
except (AttestationVerifierUnavailable, QuoteVerifierUnavailable):
return AttestationOutcome.VERIFIER_UNAVAILABLE
except QuoteVerificationError:
return AttestationOutcome.VERIFICATION_FAILED
except Exception: # noqa: BLE001 - any verifier error fails closed
return AttestationOutcome.VERIFICATION_FAILED
if verdict.tcb_status not in self.acceptable_tcb:
return AttestationOutcome.VERIFICATION_FAILED

# RTMR3 validated by content: replay the event log to the signed RTMR3.
try:
replay = replay_rtmr3(event_log)
except QuoteVerificationError:
return AttestationOutcome.VERIFICATION_FAILED
if replay.rtmr3 != report.rtmr3 or replay.compose_hash is None:
return AttestationOutcome.VERIFICATION_FAILED

# measurement reconstructed from the SIGNED registers must be allowlisted.
measurement = {
"mrtd": report.mrtd,
"rtmr0": report.rtmr0,
"rtmr1": report.rtmr1,
"rtmr2": report.rtmr2,
"compose_hash": replay.compose_hash,
"os_image_hash": os_image_hash_from_registers(report.mrtd, report.rtmr1, report.rtmr2),
}
if not self.allowlist.contains(measurement):
return AttestationOutcome.VERIFICATION_FAILED

# report_data must bind exactly (measurement, agent, task set, scores, nonce).
expected_report_data = rd.report_data_hex(
canonical_measurement=measurement,
agent_hash=agent_hash,
task_ids=task_ids,
scores_digest=scores_digest,
validator_nonce=nonce,
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="score_nonce_not_outstanding",
)
plan = eval_plan or {}
plan_hash = str(plan.get("agent_hash") or "").strip()
expected = (expected_agent_hash or plan_hash).strip()
got = ""
if isinstance(validated, Mapping):
proof = validated.get("execution_proof")
if isinstance(proof, Mapping):
got = str(proof.get("agent_hash") or "").strip()
if not got:
got = str(validated.get("agent_hash") or "").strip()
if expected and got and expected != got:
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="agent_hash_mismatch",
)
# Host-trust software admit (unattested). Callers must mark envelopes.
return AttestationDecision.of(
AttestationOutcome.VERIFIED,
reason="host_trust_plan_admit_unattested",
)

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 | 🟠 Major | ⚡ Quick win

Require both agent hashes before admitting.

An outstanding nonce with an empty expected hash or empty submitted hash reaches VERIFIED; this is not a plan-hash match. Reject missing values before the equality check.

Proposed fix
         expected = (expected_agent_hash or plan_hash).strip()
         got = ""
         if isinstance(validated, Mapping):
             proof = validated.get("execution_proof")
             if isinstance(proof, Mapping):
                 got = str(proof.get("agent_hash") or "").strip()
             if not got:
                 got = str(validated.get("agent_hash") or "").strip()
-        if expected and got and expected != got:
+        if not expected or not got:
+            return AttestationDecision.of(
+                AttestationOutcome.VERIFICATION_FAILED,
+                reason="agent_hash_missing",
+            )
+        if expected != got:
             return AttestationDecision.of(
                 AttestationOutcome.VERIFICATION_FAILED,
                 reason="agent_hash_mismatch",
             )
📝 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
if not nonce_outstanding:
return AttestationDecision.of(AttestationOutcome.VERIFICATION_FAILED)
if consume_nonce:
if self.nonce_validator is None:
return AttestationDecision.of(AttestationOutcome.VERIFICATION_FAILED)
if self.nonce_validator.consume(eval_plan["score_nonce"]) is not NonceState.OK:
return AttestationDecision.of(AttestationOutcome.VERIFICATION_FAILED)
return AttestationDecision.of(AttestationOutcome.VERIFIED)
def _verify(
self,
execution_proof: Mapping[str, Any],
binding: Mapping[str, Any],
expected_agent_hash: str,
) -> AttestationOutcome:
attestation = execution_proof.get("attestation")
if not isinstance(attestation, Mapping):
return AttestationOutcome.VERIFICATION_FAILED
quote = attestation.get("tdx_quote")
event_log = attestation.get("event_log")
if not isinstance(quote, str) or not quote or not isinstance(event_log, list):
return AttestationOutcome.VERIFICATION_FAILED
# -- the run identity the VALIDATOR expects (never trusted blindly) ---- #
agent_hash = binding.get("agent_hash")
task_ids = binding.get("task_ids")
scores = binding.get("scores")
scores_digest = binding.get("scores_digest")
nonce = binding.get("validator_nonce")
if (
not isinstance(agent_hash, str)
or not isinstance(task_ids, list)
or not isinstance(scores, Mapping)
or not isinstance(scores_digest, str)
or not isinstance(nonce, str)
or not nonce
):
return AttestationOutcome.VERIFICATION_FAILED
# scores_digest must be the digest of the scores the result reports, so a
# score cannot be altered without breaking the report_data binding.
if rd.scores_digest(scores) != scores_digest:
return AttestationOutcome.VERIFICATION_FAILED
# the attested agent must be the submission actually under evaluation.
if agent_hash != expected_agent_hash:
return AttestationOutcome.VERIFICATION_FAILED
# dependencies missing -> fail closed (never accept-any).
if self.quote_verifier is None or not self.allowlist or self.nonce_validator is None:
return AttestationOutcome.VERIFICATION_FAILED
try:
report = parse_td_report(quote)
except QuoteStructureError:
return AttestationOutcome.VERIFICATION_FAILED
# cryptographic signature/cert-chain + TCB posture (trust root).
try:
verdict = self.quote_verifier.verify(quote)
except (AttestationVerifierUnavailable, QuoteVerifierUnavailable):
return AttestationOutcome.VERIFIER_UNAVAILABLE
except QuoteVerificationError:
return AttestationOutcome.VERIFICATION_FAILED
except Exception: # noqa: BLE001 - any verifier error fails closed
return AttestationOutcome.VERIFICATION_FAILED
if verdict.tcb_status not in self.acceptable_tcb:
return AttestationOutcome.VERIFICATION_FAILED
# RTMR3 validated by content: replay the event log to the signed RTMR3.
try:
replay = replay_rtmr3(event_log)
except QuoteVerificationError:
return AttestationOutcome.VERIFICATION_FAILED
if replay.rtmr3 != report.rtmr3 or replay.compose_hash is None:
return AttestationOutcome.VERIFICATION_FAILED
# measurement reconstructed from the SIGNED registers must be allowlisted.
measurement = {
"mrtd": report.mrtd,
"rtmr0": report.rtmr0,
"rtmr1": report.rtmr1,
"rtmr2": report.rtmr2,
"compose_hash": replay.compose_hash,
"os_image_hash": os_image_hash_from_registers(report.mrtd, report.rtmr1, report.rtmr2),
}
if not self.allowlist.contains(measurement):
return AttestationOutcome.VERIFICATION_FAILED
# report_data must bind exactly (measurement, agent, task set, scores, nonce).
expected_report_data = rd.report_data_hex(
canonical_measurement=measurement,
agent_hash=agent_hash,
task_ids=task_ids,
scores_digest=scores_digest,
validator_nonce=nonce,
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="score_nonce_not_outstanding",
)
plan = eval_plan or {}
plan_hash = str(plan.get("agent_hash") or "").strip()
expected = (expected_agent_hash or plan_hash).strip()
got = ""
if isinstance(validated, Mapping):
proof = validated.get("execution_proof")
if isinstance(proof, Mapping):
got = str(proof.get("agent_hash") or "").strip()
if not got:
got = str(validated.get("agent_hash") or "").strip()
if expected and got and expected != got:
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="agent_hash_mismatch",
)
# Host-trust software admit (unattested). Callers must mark envelopes.
return AttestationDecision.of(
AttestationOutcome.VERIFIED,
reason="host_trust_plan_admit_unattested",
)
if not nonce_outstanding:
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="score_nonce_not_outstanding",
)
plan = eval_plan or {}
plan_hash = str(plan.get("agent_hash") or "").strip()
expected = (expected_agent_hash or plan_hash).strip()
got = ""
if isinstance(validated, Mapping):
proof = validated.get("execution_proof")
if isinstance(proof, Mapping):
got = str(proof.get("agent_hash") or "").strip()
if not got:
got = str(validated.get("agent_hash") or "").strip()
if not expected or not got:
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="agent_hash_missing",
)
if expected != got:
return AttestationDecision.of(
AttestationOutcome.VERIFICATION_FAILED,
reason="agent_hash_mismatch",
)
# Host-trust software admit (unattested). Callers must mark envelopes.
return AttestationDecision.of(
AttestationOutcome.VERIFIED,
reason="host_trust_plan_admit_unattested",
)
🤖 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/src/agent_challenge/evaluation/attestation.py`
around lines 82 - 106, Update the agent-hash validation in the attestation
decision flow to reject verification when either expected or submitted hash is
empty. In the logic after computing expected and got within the surrounding
attestation method, return AttestationOutcome.VERIFICATION_FAILED before the
mismatch check, using an appropriate missing-hash reason; only admit VERIFIED
when both hashes are present and equal.

Comment on lines +500 to +518
# T40: dual TEE flags permanently off. Defaults are host-trust.
dual_on = False
require_residual = False
expected_tree: str | None = getattr(submission, "package_tree_sha", None)
if isinstance(expected_tree, str):
expected_tree = expected_tree.strip() or None
else:
expected_tree = None
if settings is not None:
phala = bool(getattr(settings, "phala_attestation_enabled", True))
review = bool(getattr(settings, "attested_review_enabled", True))
phala = bool(getattr(settings, "phala_attestation_enabled", False))
review = bool(getattr(settings, "attested_review_enabled", False))
dual_on = phala and review
# Residual is mandatory for production dual-flag prepare; flag-off still
# fails later emit gates but residual check runs when dual_on.
require_residual = dual_on
no_phala = bool(
getattr(settings, "no_phala", False)
or getattr(settings, "unattested_execution", False)
)
# Host-trust: residual optional at prepare (software policy when present).
# dual_on is always False after T40 settings force-off.
require_residual = bool(dual_on)

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 | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate file and references =="
git ls-files | rg '(^|/)authorization\.py$|AGENTS\.md$|agent_challenge/evaluation' || true

echo "== relevant authorization excerpt =="
if [ -f packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py ]; then
  wc -l packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py
  sed -n '460,545p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py | cat -n
fi

echo "== hard invariant references =="
rg -n "Hard Invariant|package LLM rules|residual|package_tree_sha|no_phala|unattested_execution|phala_attestation_enabled|attested_review_enabled" -S .

Repository: BaseIntelligence/base

Length of output: 50378


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== exact invariant text =="
sed -n '105,125p' AGENTS.md | cat -n

echo "== host-trust / no-phala docs relevant excerpts =="
sed -n '1,120p' packages/challenges/agent-challenge/docs/host-trust.md | cat -n
sed -n '1,220p' packages/challenges/agent-challenge/docs/no-phala-mode.md | cat -n
sed -n '1,45p' packages/challenges/agent-challenge/README.md | cat -n

echo "== admission gateway excerpt =="
sed -n '430,525p' src/base/master/app_proxy.py | cat -n

echo "== authorizing fresh review gate definition excerpts =="
fd -a 'fresh_review_gate.py|no_phala.py|llm_rules_residual.py' packages/challenges/agent-challenge/src/agent_challenge/evaluation | xargs -r printf '\n--- %s\n' {} \; -exec sh -c 'echo "--- $1"; ast-grep outline "$1" || true; sed -n "1,280p" "$1" | cat -n' sh {} \;

echo "== read-only semantic probe of current assignment-authorizer logic =="
python3 - <<'PY'
from pathlib import Path
import ast

path = Path("packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py")
src = path.read_text().splitlines()
start = 511
end = 516
print("lines 511-516:")
for i in range(start, end + 1):
    print(f"{i}: {src[i-1]}")

tree = ast.parse(path.read_text())
for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef) and node.name == "_authorized_review_digest":
        names = {
            name.lineno: name.id
            for name in ast.walk(node)
            if isinstance(name, ast.Name) and isinstance(name.ctx, ast.Store)
        }
        readers = {
            name.lineno: name.id
            for name in ast.walk(node)
            if isinstance(name, ast.Name) and isinstance(name.ctx, ast.Load)
        }
        print("stored local names in function:", {k: v for k, v in names.items() if 500 <= k <= 520})
        print("loaded same names:", {k: v for k, v in readers.items() if k in names})
        for lineno, name in names.items():
            if 500 <= lineno <= 520:
                print(f"definition location has loads: {[(k,v) for k,v in readers.items() if k >= lineno and k <= 520 and v==name]}")
        print("call kwargs nearby:")
        for call in ast.walk(node):
            if isinstance(call, ast.Call) and getattr(call.func, 'attr', None) == 'admit_eval_cvm_launch_from_assignment':
                for kw in call.keywords:
                    print(kw.arg, ast.get_source_segment("\n".join(src), kw.value).strip())
PY

Repository: BaseIntelligence/base

Length of output: 16715


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== fresh_review_gate outline and excerpt =="
ast-grep outline packages/challenges/agent-challenge/src/agent_challenge/evaluation/fresh_review_gate.py || true
sed -n '1,280p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/fresh_review_gate.py | cat -n

echo "== no_phala excerpt =="
sed -n '1,240p' packages/agent_challenge/src/agent_challenge/evaluation/no_phala.py 2>/dev/null || sed -n '1,240p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/no_phala.py | cat -n

echo "== llm_rules_residual outline and relevant excerpts =="
ast-grep outline packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py || true
sed -n '1,260p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py | cat -n

echo "== read-only semantic probe of current authorizer compute and callsite =="
python3 - <<'PY'
from pathlib import Path
import ast

path = Path("packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py")
src = path.read_text().splitlines()
tree = ast.parse(path.read_text(), filename=str(path))

for node in ast.walk(tree):
    if isinstance(node, ast.FunctionDef) and node.name == "_authorized_review_digest":
        stored = {ast.get_source_segment(path.read_text(), x): (x.lineno, ast.unparse(x)) for x in ast.walk(node) if isinstance(x, ast.Assign) and len(x.targets) == 1 and isinstance(x.targets[0], ast.Name)}
        load_names = {line: [] for line in range(node.lineno, node.end_lineno + 1)}
        for x in ast.walk(node):
            if isinstance(x, ast.Name) and isinstance(x.ctx, ast.Load):
                if x.lineno in load_names:
                    load_names[x.lineno].append(x.id)
        print(f"assigned locals in function:")
        for line, seg in sorted(stored.items(), key=lambda kv: kv[1][0]):
            print(f"  line {line[0]}: {seg}")
        print(f"loads on lines containing assignments:")
        for line, names in load_names.items():
            if names:
                print(f"  line {line}: {', '.join(set(names))} -- {src[line-1].strip()}")
        call_kwargs = []
        for call in ast.walk(node):
            if isinstance(call, ast.Call) and getattr(call.func, 'attr', None) == 'admit_eval_cvm_launch_from_assignment':
                for kw in call.keywords:
                    call_kwargs.append((kw.lineno, kw.arg, ast.get_source_segment(path.read_text(), kw.value)))
        print("admit_eval_cvm_launch_from_assignment kwargs:")
        for call_kwargs_item in call_kwargs:
            print(f"  line {call_kwargs_item[0]}: {call_kwargs_item[1]}={call_kwargs_item[2]}")
PY

Repository: BaseIntelligence/base

Length of output: 38591


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== fresh_review_gate residual requirements and allow path =="
sed -n '267,340p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/fresh_review_gate.py | cat -n

echo "== authorizer callsite and relevant flow =="
sed -n '430,525p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py | cat -n

echo "== llm_rules_residual admission helpers =="
sed -n '340,527p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py | cat -n

echo "== llm_rules_residual residual material validation helpers =="
sed -n '480,570p' packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py | cat -n

echo "== targeted read-only probe of fresh_review_gate/admission code =="
python3 - <<'PY'
from pathlib import Path
import ast

paths = [
    Path("packages/challenges/agent-challenge/src/agent_challenge/evaluation/fresh_review_gate.py"),
    Path("packages/challenges/agent-challenge/src/agent_challenge/evaluation/llm_rules_residual.py"),
    Path("packages/challenges/agent-challenge/src/agent_challenge/evaluation/authorization.py"),
]
for path in paths:
    src = path.read_text()
    tree = ast.parse(src, filename=str(path))
    print(f"\n--- {path} ---")
    for node in ast.walk(tree):
        name = getattr(node, "name", "")
        if name in {
            "admit_eval_cvm_fresh_review", "admit_package_residual_for_eval",
            "require_package_residual_for_eval", "_authorized_review_digest",
        }:
            seg = ast.get_source_segment(src, node)
            print(f"function {name}")
            # basic predicate extraction for requested names in function body
            for child in ast.walk(node):
                if isinstance(child, (ast.Compare, ast.Call, ast.IfStatement, ast.If, ast.Assign)):
                    tokens = []
                    try:
                        code = ast.get_source_segment(src, child)
                        if any(tok in (code or "") for tok in ["require_package_residual", "package_residual", "admitted", "host_analyzer_allow"]):
                            tokens.append(code.strip().replace("\n", " "))
                    except Exception:
                        pass
                    if tokens:
                        for token in tokens:
                            if len(token) < 800:
                                print(f"line {child.lineno}: {token}")
PY

Repository: BaseIntelligence/base

Length of output: 21452


Require residual for host-trust eval preparation

With TEE flags disabled, _authorized_review_digest always computes dual_on = False and sets require_residual = bool(dual_on), so admit_eval_cvm_launch_from_assignment() skips the package residual gate. AGATE host-trust still requires host-allowed residual plus package_tree_sha proof; host-analyzer allow alone must not pass. Set require_residual = True for host-trust and include package_residual = ... in the admission call so no_phala/unattested_execution paths are fail-closed when residual is missing or nonallowing.

🧰 Tools
🪛 GitHub Actions: Challenge images / 2_agent-challenge-checks.txt

[error] 512-514: ruff: F841 Local variable no_phala is assigned to but never used. Remove assignment to unused variable no_phala.

🪛 GitHub Actions: Challenge images / agent-challenge-checks

[error] 512-514: ruff reported F841: Local variable no_phala is assigned to but never used; remove assignment to unused variable no_phala.

🤖 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/src/agent_challenge/evaluation/authorization.py`
around lines 500 - 518, Update the authorization preparation flow around
_authorized_review_digest to require residual validation for host-trust
evaluations even when dual TEE flags are disabled. Set require_residual to true,
and pass the computed package_residual into
admit_eval_cvm_launch_from_assignment(); preserve package_tree_sha proof
validation and ensure no_phala/unattested_execution paths fail closed when
residual is missing or not allowed.

Source: Coding guidelines

Comment on lines +232 to +235
def _phala_attestation_enabled(*_a, **_k) -> bool:
"""T40: Phala attestation permanently disabled."""

return False

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Always mark the forced fallback as unattested.

This hard-disable sends every run through _emit_job_result’s legacy branch. When host-trust aliases are unset, that branch skips mark_result_unattested, contradicting the host-trust contract that results carry attested=false and attestation_status=unattested. Mark the fallback unconditionally; retain is_no_phala_enabled() only for optional artifact-proof behavior.

🤖 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/src/agent_challenge/evaluation/own_runner_backend.py`
around lines 232 - 235, Update the forced fallback around
_phala_attestation_enabled so every fallback result is explicitly marked
unattested, ensuring _emit_job_result produces attested=false and
attestation_status=unattested even when host-trust aliases are unset. Keep
is_no_phala_enabled() limited to optional artifact-proof behavior rather than
controlling the result-attestation marker.

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/challenges/agent-challenge/tests/test_report_http_status_envelope.py (1)

353-377: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Fail closed for host-trust review evidence storage.

This line codifies an encryption-gate bypass, but ReviewEvidenceObject still persists raw review transport evidence as Fernet ciphertext, and _evidence_fernet() requires a loadable key. Make host-trust mode reject encryption-key-less evidence stores, or require the encryption key for any production evidence storage profile.

🤖 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_report_http_status_envelope.py`
around lines 353 - 377, Update
ChallengeSettings.require_review_evidence_encryption_for_production and the
associated ReviewEvidenceObject/_evidence_fernet storage path so host-trust
production evidence storage cannot proceed without a loadable encryption key.
Remove the current no-op behavior when attestation flags are disabled, instead
rejecting key-less configurations or requiring the key for every production
evidence profile while preserving the existing dual-flag validation.

Source: Coding guidelines

🤖 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/docs/miner/self-deploy.md`:
- Line 1: Replace the historical Phala/TEE lifecycle in
packages/challenges/agent-challenge/docs/miner/self-deploy.md:1-1 with a concise
host-trust miner pointer, removing obsolete flags, CVM, key-release, and
quote-verification guidance. Replace the Phala attestation and RA-TLS
instructions in
packages/challenges/agent-challenge/docs/validator/self-deploy.md:1-1 with a
short validator/Compose host-trust note; keep both documents minimal and
unsuitable as shipping guidance.

---

Outside diff comments:
In
`@packages/challenges/agent-challenge/tests/test_report_http_status_envelope.py`:
- Around line 353-377: Update
ChallengeSettings.require_review_evidence_encryption_for_production and the
associated ReviewEvidenceObject/_evidence_fernet storage path so host-trust
production evidence storage cannot proceed without a loadable encryption key.
Remove the current no-op behavior when attestation flags are disabled, instead
rejecting key-less configurations or requiring the key for every production
evidence profile while preserving the existing dual-flag validation.
🪄 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: 0e977b35-4f14-42b5-8e7d-eac0ead1945a

📥 Commits

Reviewing files that changed from the base of the PR and between 17215e5 and 64e534c.

📒 Files selected for processing (15)
  • packages/challenges/agent-challenge/README.md
  • packages/challenges/agent-challenge/config.example.yaml
  • packages/challenges/agent-challenge/docker/review/phala_pre_launch.sh
  • packages/challenges/agent-challenge/docs/miner/self-deploy.md
  • packages/challenges/agent-challenge/docs/validator/self-deploy.md
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/attested_result.py
  • packages/challenges/agent-challenge/tests/test_keyrelease_durable_state.py
  • packages/challenges/agent-challenge/tests/test_own_runner_backend_decrypt.py
  • packages/challenges/agent-challenge/tests/test_own_runner_backend_failclosed_surface.py
  • packages/challenges/agent-challenge/tests/test_own_runner_backend_keyrelease.py
  • packages/challenges/agent-challenge/tests/test_own_runner_dood_launch.py
  • packages/challenges/agent-challenge/tests/test_replay_audit_compare.py
  • packages/challenges/agent-challenge/tests/test_replay_audit_sampler.py
  • packages/challenges/agent-challenge/tests/test_report_http_status_envelope.py
  • tests/unit/test_master_embed_env_file.py
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/challenges/agent-challenge/docker/review/phala_pre_launch.sh
  • packages/challenges/agent-challenge/config.example.yaml
  • packages/challenges/agent-challenge/src/agent_challenge/canonical/attested_result.py

@@ -1,3 +1,5 @@
> **T40/T41 product path:** Phala TEE dual flags and CVM attestation are **removed**. Host-trust / unattested only. Do not treat historical Phala CVM / TEE sections below as a shipping product path.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟠 Major | 🏗️ Heavy lift

Replace the obsolete Phala/TEE deployment guides rather than prefixing them.

The banner conflicts with the detailed production instructions immediately below it, which still direct operators to enable removed flags, provision CVMs, release keys, and verify TEE quotes. Reduce these files to short host-trust notes or archival redirects so they cannot be followed as shipping guidance.

  • packages/challenges/agent-challenge/docs/miner/self-deploy.md#L1-L1: replace the historical Phala self-deploy lifecycle with a short host-trust miner pointer.
  • packages/challenges/agent-challenge/docs/validator/self-deploy.md#L1-L1: replace Phala/attestation and RA-TLS operational guidance with a short validator/Compose host-trust note.

As per coding guidelines, “Keep shipping documentation minimal: use a short root README, miner getting-started material, and a short validator/Compose note.”

📍 Affects 2 files
  • packages/challenges/agent-challenge/docs/miner/self-deploy.md#L1-L1 (this comment)
  • packages/challenges/agent-challenge/docs/validator/self-deploy.md#L1-L1
🤖 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/docs/miner/self-deploy.md` at line 1,
Replace the historical Phala/TEE lifecycle in
packages/challenges/agent-challenge/docs/miner/self-deploy.md:1-1 with a concise
host-trust miner pointer, removing obsolete flags, CVM, key-release, and
quote-verification guidance. Replace the Phala attestation and RA-TLS
instructions in
packages/challenges/agent-challenge/docs/validator/self-deploy.md:1-1 with a
short validator/Compose host-trust note; keep both documents minimal and
unsuitable as shipping guidance.

Source: Coding guidelines

Import AttestationEmissionError in own_runner_backend, stub fail-closed
emit helpers on attested_result, and auto-fix UP035/F401/E501/format
so agent-challenge-checks and monorepo ruff/format CI go green.
@echobt
echobt merged commit 22b2448 into main Jul 29, 2026
43 checks passed
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