Skip to content

fix!: dedicated session signer, retired-signer refusals, AA cleanup - #866

Merged
chrisli30 merged 4 commits into
mainfrom
staging
Oct 22, 2026
Merged

chrisli30 merged 4 commits into
mainfrom
staging

Conversation

@chrisli30

@chrisli30 chrisli30 commented Oct 22, 2026 •

Copy link
Copy Markdown
Member

Deploy prerequisites

  • Required config key. Every gateway config must set session_signer_private_key before this ships; a gateway built from this release refuses to start without it. The production gateway config and its variable are already staged and apply on the next deploy. Older binaries ignore the field.
  • Existing session grants must be granted again. Grants installed before this release name the previous session signer. Execution refuses them with SESSION_POLICY_SIGNER_RETIRED, create and resume return 409 SESSION_POLICY_SIGNER_RETIRED, and the simulate verdict reports no_grant. Owners grant again to install the new signer.
  • make storage-check against origin/main: no breaking storage changes.

Included

Co-authored-by: Chris Li chris@avaprotocol.org

Co-authored-by: Chris Li chris@avaprotocol.org

Co-authored-by: Chris Li chris@avaprotocol.org

Co-authored-by: Chris Li chris@avaprotocol.org

BREAKING CHANGE: gateway configs must set session_signer_private_key; grants installed for the previous session signer must be granted again.

🤖 Generated with Claude Code

chrisli30 and others added 3 commits October 20, 2026 22:26
)

Co-authored-by: Chris Li <chris@avaprotocol.org>
Co-authored-by: Chris Li <chris@avaprotocol.org>
Co-authored-by: Chris Li <chris@avaprotocol.org>
@chrisli30
chrisli30 requested a balanced review from Copilot October 22, 2026 03:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The signing-key rollout requires human validation, and an unresolved cross-chain refusal bug still needs correction.

1 open issue
What changed in this PR

This PR separates the gateway’s session signer from per-network controller keys, adds explicit handling for grants made with a retired signer, and removes obsolete account-abstraction code.

Changes:

  • Require a dedicated session-signing key, with configuration validation, startup diagnostics, and updated test fixtures.
  • Add retired-signer refusals across execution, create/resume checks, and simulation readiness, with API documentation and regression tests.
  • Remove the stale SimpleAccount binding and incorrect CREATE2 address helper.
File Description
version/​version.go Formatting-only change; no behavior change.
PLAN_CROSS_CHAIN_SEQUENCING.md Correct the documented wallet-address lookup reference.
pkg/​erc4337/​preset/​bundler_error.go Classify retired-signer errors as client failures.
pkg/​erc4337/​preset/​bundler_error_test.go Test retired-signer error classification.
docs/​changes/​20261022-retired-session-signer-refusal.md Document refusal behavior and client handling.
docs/​changes/​20261022-dedicated-session-signer.md Explain signer separation and rollout requirements.
docker-compose.yaml Forward the session-signer environment variable.
core/​taskengine/​session_skill.go Add retired-signer readiness and deploy checks.
core/​taskengine/​session_signer_retired_test.go Test refusals, precedence, and readiness.
core/​taskengine/​session_policy.go Use the dedicated signer and stable refusal code.
core/​taskengine/​session_permissions.go Update the session-signer comment.
core/​taskengine/​session_grant_replace_live_test.go Seed grants with the configured session signer.
core/​taskengine/​session_grant_nway_live_test.go Update multi-grant test seeding.
core/​taskengine/​session_grant_native_live_test.go Use the session signer in native-transfer tests.
core/​taskengine/​engine_session_policy.go Derive the configured signer and detect retired grants.
core/​taskengine/​engine_session_policy_test.go Update fixtures and test signer independence.
core/​config/​session_signer_test.go Test key validation and controller-overlap detection.
core/​config/​config.go Require, parse, and log the dedicated signer.
core/​chainio/​aa/​simpleaccount/​simpleaccount.go Delete the stale generated binding.
core/​chainio/​aa/​README.md Remove obsolete binding documentation.
core/​chainio/​aa/​aa.go Remove the incorrect CREATE2 helper; clarify initCode.
core/​chainio/​aa/​aa_test.go Delete tests for the removed helper.
config/​test.example.yaml Add the required test signer setting.
config/​gateway.example.yaml Document the required gateway signer setting.
api/​openapi.yaml Document retired-signer errors and readiness semantics.
aggregator/​rest/​handlers_policies.go Add the retired-signer conflict title.
aggregator/​rest/​handlers_policies_test.go Update fixtures and test HTTP conflict mapping.
aggregator/​rest/​generated/​types.gen.go Refresh generated documentation comments only.
.github/​scripts/​generate-test-config.sh Generate and redact a throwaway CI session key.

Review effort: Balanced

Comment thread core/taskengine/session_skill.go Outdated
if unresolvedRefusal != nil && expiredUntil > 0 {
beatExpiry = true
}
grantAgain := expiredUntil > 0 || retiredPolicyID != ""

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Valid. Fixed in #867. A grant-again refusal on the unreadable target's own chain (beatExpiry) now counts like one elsewhere. The unreadable target wins, and policyId and required both name its chain, with no missingActions. That makes the old sawOrdinary guard unnecessary, so it's removed. Regression test TestDeployCheckUnresolvedTargetOutranksSameChainGrantAgainBesideOrdinaryGap covers the expired and the retired-signer variant; both returned SESSION_POLICY_NOT_COVERING with mixed metadata before the fix. This release PR picks it up once #867 merges into staging.

@chrisli30

Copy link
Copy Markdown
Member Author

Resolution of the review findings:

# Finding Action
Copilot Same-chain grant-again + unreadable target beside an ordinary gap returns mixed metadata Fixed in #867, with a two-chain regression test (expired and retired-signer variants).
Claude 1 firstNonEmpty doc comment misplaced above parseSessionSignerKey Fixed in #867.
Claude 2 sessionSignerRetired fails open with no key No change. NewConfig requires the key, so only hand-built test configs reach that path; it is documented on the function. Logging on every call would add noise for the many test engines.
Claude 3 NewConfig requires the key unconditionally Intended. Its only callers are the gateway (aggregator.go), create-api-key (aggregator/key.go), testutil, and scripts/fixture_wallet, which all load gateway or test configs. Workers use NewWorkerConfig; operators have their own loader.
Claude 4 aa_test.go deletion Confirmed safe. It only tested the removed computeSmartWalletAddress (CREATE2 formula, salts, owners).
Claude 5 REST nil-signer test; SDK release note No change. The nil-signer case is covered at the engine level (TestResolverRefusesRetiredSignerWithStableCode), and the REST mapping is code-based. The 409 code is documented in api/openapi.yaml and docs/changes/20261022-retired-session-signer-refusal.md.

🤖 Generated with Claude Code

#867)

Co-authored-by: Chris Li <chris@avaprotocol.org>
@chrisli30
chrisli30 merged commit d53d205 into main Oct 22, 2026
30 checks passed

This branch was successfully deployed

1 active deployment
Test — d8a840c7 Deployed Oct 22, 2026 by chrisli30 via Unit Test (core/taskengine/trigger) #1647
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