Skip to content

fix(orchestration): bind E2 campaign approval identity - #167

Merged
mirror29 merged 5 commits into
mirror29:codex/evolution-task27from
TheBayoumi:fix/e2-campaign-authorization
Sep 1, 2026
Merged

fix(orchestration): bind E2 campaign approval identity#167
mirror29 merged 5 commits into
mirror29:codex/evolution-task27from
TheBayoumi:fix/e2-campaign-authorization

Conversation

@TheBayoumi

@TheBayoumi TheBayoumi commented Aug 30, 2026

Copy link
Copy Markdown

What this PR does / 这个 PR 做了什么

修复 E2 事件演化 campaign 的经济授权身份断链:evolver.run_event_campaign 不再走自动 allow + 独立 randomUUID(),而是复用 trusted approval 路径,并把一次显式 owner 审批绑定到一个有界的 E2 五代 campaign。

审批产生的 durable operation ID 继续绑定 signed event_campaign grant,并作为 Evolver Idempotency-Key 使用。campaign 内部五代执行保持自动,不增加逐代审批。

This PR also closes the retry/durability issues identified during maintainer and Codex review:

  • a lost /start response is recoverable without starting the same campaign twice;
  • one E2 approval permits the initial execution plus at most one matching compensation retry within two minutes;
  • the durable retry entitlement is atomically consumed across restart/concurrency;
  • concurrent initial calls for the same approval identity are serialized;
  • migration 0045 permits evolver.run_event_campaign in the shared approval-operation ledger.

This remains a maintainer-aligned authorization-boundary fix. No public issue was opened because the repository security policy directs permission/authorization bypass reports to private channels.

Problem

At the stacked base, E1 and E2 used different economic authorization models.

E1:

permission ask → explicit trusted approval → durable operation ID → request/LLM-bound grant → Idempotency-Key → run

E2 before this PR:

permission allow → getAutomaticEventCampaignContext() → randomUUID() → grant → Idempotency-Key → campaign

An E2 campaign can perform cost-bearing proposer calls across a fixed five-generation run, so creating the economic operation identity independently of owner approval breaks the authorization/provenance chain.

Two additional retry/durability gaps were identified during review:

  1. if /start committed but its response was lost, whole-tool retry could hit CAMPAIGN_STATE_CONFLICT;
  2. the initial durable-approval reuse inherited a 24-hour reusable capability instead of the repository contract of one compensation retry within two minutes, and concurrent initial consumers could race.

Invariant

One explicit owner approval authorizes one bounded E2 campaign.

approval → operation ID → signed event_campaign grant → Idempotency-Key → campaign

After approval:

  • the five internal generations execute automatically;
  • there is no approval per generation, hypothesis, or proposer call;
  • the initial operation may be followed by at most one matching compensation retry within two minutes;
  • that retry reuses the same durable operation identity;
  • restart/concurrent recovery cannot consume the retry entitlement more than once.

Implementation

  • Move evolver.run_event_campaign from allow to ask in both permission representations.
  • Bind approval identity to eventSnapshotId, optional sourceRunId, complete campaign config, and the frozen non-secret LLM snapshot.
  • Require APPROVAL_OPERATION_ID_KEY in getApprovedEventCampaignContext().
  • Remove E2's independent post-authorization economic randomUUID().
  • Keep the purpose-separated event_campaign Ed25519 grant.
  • Pass the approved operation ID unchanged as Evolver Idempotency-Key.
  • Keep the five-generation execution loop unchanged.
  • Make whole-operation retry idempotent:
    • idempotent create returning a non-draft campaign returns that campaign without another /start;
    • an exact concurrent CAMPAIGN_STATE_CONFLICT is reconciled through owner-scoped GET;
    • the conflict remains an error if the campaign is still draft.
  • Add an E2-specific bounded recovery policy:
    • initial execution + one matching retry;
    • two-minute retry window;
    • atomic durable retry claim via DELETE ... RETURNING;
    • same-identity initial consumption serialized to prevent two initial executions.
  • Add Alembic migration 0045_e2_campaign_approval_operations.py to expand the approval-ledger tool_name constraint for E2.
  • Leave E1's pre-existing durable reuse behavior unchanged.

Security model

The normal path fails closed at two layers:

  1. permission middleware requires explicit trusted approval plus verified owner/session/frozen LLM context;
  2. E2 context construction refuses to mint a campaign grant without the approval-derived operation ID.

The signed grant binds owner, approved operation ID, grant_purpose=event_campaign, LLM config identity, and canonical campaign request digest. Evolver requires grant operation_id to match the backend Idempotency-Key.

Existing (owner_account_id, idempotency_key) uniqueness prevents a second economic campaign under the same operation.

The recovery entitlement is separately bounded: exactly one matching retry within two minutes, atomically consumed across restart/concurrency. This preserves durable recovery without turning one explicit approval into a reusable long-lived capability.

Non-goals

This PR does not address:

  • Forward evidence authority
  • global event-ledger service identity
  • holdout crash durability
  • lease fencing
  • deterministic champion locking
  • frozen bars
  • owner-blind holdout visibility
  • per-LLM-call provenance
  • dashboard cleanup
  • promotion / Runner startup / order execution

Scope / 涉及范围

Acceptance criteria

  • evolver.run_event_campaign requires explicit approval.
  • Missing owner/session/frozen LLM approval context fails closed.
  • Material campaign input is bound to approval.
  • Frozen LLM configuration is bound to approval and signed grant.
  • Approval-derived operation ID reaches grant minting unchanged.
  • The same operation ID is used as backend Idempotency-Key.
  • Retrying the same approved operation resolves the same campaign identity.
  • Lost /start response recovery does not issue a second start after the campaign advanced.
  • Concurrent start conflict is recovered only when owner-scoped GET proves the campaign advanced.
  • A start conflict remains an error while the campaign is still draft.
  • E2 approval permits only one matching compensation retry within two minutes.
  • Durable retry entitlement is atomically consumed across restart/concurrency.
  • Concurrent initial consumers cannot both become initial executions.
  • The durable ledger accepts evolver.run_event_campaign after migration 0045.
  • Input, owner, or LLM snapshot substitution cannot consume the prior approval.
  • E1/E2 credential purpose separation remains enforced.
  • E1 durable reuse behavior is unchanged.
  • Five internal generations remain automatic after the one campaign approval.
  • No promotion, Runner startup, live execution, or order path is introduced.

Tests / 验证

Validated on final contribution SHA e1ec52ec48c3c6889c7faac0b8393bf1ec06f4bb:

  • orchestration typecheck + unit tests: 54 files / 551 tests passed
    • E2 campaign authorization: 8/8
    • approval-store tests: 12/12
    • Evolver client/grant/idempotency/retry tests: 8/8
  • orchestration agent eval: passed
  • E1 Evolver regression suite: passed
  • migration apply + round-trip verification: passed, including migration 0045
  • E1 Paper regression suite: passed
  • Python ruff/mypy: data, paper, research, factor, evolver passed
  • web typecheck/build: passed
  • dashboard typecheck/tests/build: passed
  • scripts/check-consistency.sh: passed
  • self-host build + health smoke: passed

Fork CI run on the exact final head: 33384343793success.

A validation-only fork PR was used to run exact repository CI and was closed without merging: TheBayoumi/inalpha#1.

Codex review

Codex reviewed the contribution iteratively and identified three P1 issues during development:

  1. E2 approval reuse was broader than the one-retry/two-minute contract;
  2. the approval-operation ledger schema did not yet accept evolver.run_event_campaign;
  3. concurrent initial approval consumption could race before persistence.

All three were fixed and regression-tested.

Final Codex review on e1ec52ec48:

Codex Review: Didn't find any major issues. Nice work!

No actionable P0/P1/P2 findings remain in the final Codex pass.

Reproducibility

  • Upstream: mirror29/inalpha
  • PR feat(evolution): E2 事件驱动自动演化研究预览 #164 / contribution base: b75928d57fbeb7c978ccd33b84812921ca65408a
  • Contribution head: TheBayoumi:fix/e2-campaign-authorization
  • Final head: e1ec52ec48c3c6889c7faac0b8393bf1ec06f4bb
  • Intended base: mirror29:codex/evolution-task27

Commits:

  1. 89d586c161297a49c65ff59512a5e31079e9562cfix(orchestration): 绑定 E2 campaign 审批操作身份
  2. e1d10d9623885f4d458c67ddb138187dc40e8c8bfix(orchestration): 使 E2 campaign 启动重试幂等
  3. e2196c5dedd01ffce43ac125018a5b1c1bdc1ed3fix(orchestration): 收紧 E2 campaign 补偿重试
  4. 28eaea0ec3f57ba397115d7e163649bcb2bbca18fix(orchestration): 封闭 E2 审批并发与持久化约束
  5. e1ec52ec48c3c6889c7faac0b8393bf1ec06f4bbtest(orchestration): 校正 E2 并发重试声明

Current upstream gate

PR #167 remains Draft because the upstream fork workflow is still action_required. The implementation, fork CI, migration verification, and final Codex review are complete; the remaining external gate is maintainer approval/run of the upstream workflow.

@mirror29
mirror29 marked this pull request as ready for review September 1, 2026 07:27
@mirror29
mirror29 self-requested a review as a code owner September 1, 2026 07:27
@mirror29 mirror29 changed the title fix(orchestration): 绑定 E2 campaign 审批操作身份 fix(orchestration): bind E2 campaign approval identity Sep 1, 2026
@mirror29
mirror29 merged commit 83f5f11 into mirror29:codex/evolution-task27 Sep 1, 2026
1 check failed
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.

2 participants