feat: contract ops reorg signing process#182
Conversation
- Use shared isSafePathSegment from path-validation in install-deps route instead of a duplicated local regex - Restore dropped id assertion in upgrades route test - Eliminate double README read in getUpgradeOption by removing redundant defaultDate pre-computation (readDeploymentInfoFromReadme already derives the date from the content it reads) - Remove redundant hasTaskLayout guard inside getUpgradeOption; the caller getUpgradeOptions already confirms the tasks directory exists before invoking this function Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
| - **Optional README parsing**: If `<network>/<task>/README.md` exists, the tool may parse it to display status and execution links. | ||
| - **Validation configs**: Place config files under `active/evm/tasks/<task-id>/config/<network>/validations/` with concise human-readable names, such as `coinbase-signer.json` or `security-council-signer.json`. | ||
| - **Script execution**: Validation commands run from `active/evm/`, so validation `cmd` values should reference scripts relative to that directory. | ||
| - **Task origin verification**: Task-origin signatures are verified over `active/evm/`, which is the same directory used for simulation. |
There was a problem hiding this comment.
Not quite .. task origin signatures should be over the network config
There was a problem hiding this comment.
Refer to this: #177 (comment)
I think it should be all over active/evm/
There was a problem hiding this comment.
I disagree and have already talked to security about this
- Sign over network config dir instead of active/evm (comment 1) - Remove network selection step; auto-select from task option (comment 6) - Delete availableNetworksForTask derived state (comment 7) - Remove unreachable empty-state branch in NetworkSelection (comment 8) - Remove options param from readDeploymentInfoFromReadme; preserve folder date for date-prefixed tasks (comments 3, 4) - Inline and delete getUpgradeForNetwork one-liner (comment 5) - Revert upgrades sort to by-id (comment 11) - Remove unnecessary String() cast on upgradeId (comment 10) Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
- Use shared isSafePathSegment from path-validation in install-deps route instead of a duplicated local regex - Restore dropped id assertion in upgrades route test - Eliminate double README read in getUpgradeOption by removing redundant defaultDate pre-computation (readDeploymentInfoFromReadme already derives the date from the content it reads) - Remove redundant hasTaskLayout guard inside getUpgradeOption; the caller getUpgradeOptions already confirms the tasks directory exists before invoking this function Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
Test placeholder upgradeIds were renamed to real-looking task names
('2026-06-18-beryl-1') but this was unnecessary. Restored:
- upgrade-config tests: back to 'test'
- validate tests: back to '2025-08-01-upgrade-qux'
The path traversal test values ('foo/bar', '../...') are kept as-is
since they intentionally test those specific characters.
Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
Replace real-looking task IDs (beryl-1, beryl-2, jasper-1) with generic names (2025-06-04-upgrade-foo, 2025-07-12-upgrade-bar) across test files and README. Expand config/ tree in README to show multiple networks (mainnet, zeronet, sepolia). Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
- Sign over network config dir instead of active/evm (comment 1) - Remove network selection step; auto-select from task option (comment 6) - Delete availableNetworksForTask derived state (comment 7) - Remove unreachable empty-state branch in NetworkSelection (comment 8) - Remove options param from readDeploymentInfoFromReadme; preserve folder date for date-prefixed tasks (comments 3, 4) - Inline and delete getUpgradeForNetwork one-liner (comment 5) - Revert upgrades sort to by-id (comment 11) - Remove unnecessary String() cast on upgradeId (comment 10) Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
…athSegment - Revert taskOriginDir to scriptPath (active/evm/) matching PR #181 - Revert README signing example to --task-folder active/evm - Remove isSafePathSegment from install-deps route (removed in PR #181) - Drop path separator tests from validate route (no longer enforced at route layer) Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
973cb34 to
64a8d5c
Compare
jackchuma
left a comment
There was a problem hiding this comment.
This PR still seems to be trying to do way too much and still has significant bloat. What are the minimal changes needed to support the new active/evm/ directory structure?
| } | ||
|
|
||
| const actualNetwork = network.toLowerCase(); | ||
| const actualUpgradeId = upgradeId; |
There was a problem hiding this comment.
Why are we re-assigning upgradeId to actualUpgradeId ?
|
|
||
| const handleUpgradeSelection = (upgrade: Upgrade) => { | ||
| const handleUpgradeSelection = (taskOption: TaskOption) => { | ||
| const network = taskOption.networks[0]; |
There was a problem hiding this comment.
Why are we selecting the network on behalf of the user? The previous UI showed all ready to sign tasks, regardless of network. We should not change this
There was a problem hiding this comment.
I'm not following why any of the diff in this file is necessary
There was a problem hiding this comment.
The user doesn't "pick a network". The UI displays all ready-to-sign tasks regardless of network and the user selects one. This is how it was already working so we should not change that
There was a problem hiding this comment.
I actually think this entire component can just be removed
There was a problem hiding this comment.
Why do we need a NetworkSummary now?
There was a problem hiding this comment.
I don't follow why any of this file's diff is necessary either
| - **Optional README parsing**: If `<network>/<task>/README.md` exists, the tool may parse it to display status and execution links. | ||
| - **Validation configs**: Place config files under `active/evm/tasks/<task-id>/config/<network>/validations/` with concise human-readable names, such as `coinbase-signer.json` or `security-council-signer.json`. | ||
| - **Script execution**: Validation commands run from `active/evm/`, so validation `cmd` values should reference scripts relative to that directory. | ||
| - **Task origin verification**: Task-origin signatures are verified over `active/evm/`, which is the same directory used for simulation. |
There was a problem hiding this comment.
I disagree and have already talked to security about this
| return isDirectory(path.join(root, 'active', 'evm', 'tasks')); | ||
| } | ||
|
|
||
| export function findContractDeploymentsRoot(startDir: string = process.cwd()): string { |
There was a problem hiding this comment.
Why are we adding a startDir input param that is never used? Unnecessary diff
| - **Validation configs**: Place config files under `active/evm/tasks/<task-id>/config/<network>/validations/` with concise human-readable names, such as `coinbase-signer.json` or `security-council-signer.json`. | ||
| - **Script execution**: Validation commands run from `active/evm/`, so validation `cmd` values should reference scripts relative to that directory. | ||
| - **Task origin verification**: Task-origin signatures are verified over `active/evm/`, which is the same directory used for simulation. | ||
| - **Signature storage**: Store signatures in `active/evm/tasks/<task-id>/config/<network>/signatures/`. The signer tool excludes the nested `signatures/` directory from the signed tarball, so generating signatures does not change the attested payload. |
There was a problem hiding this comment.
Need to update the signatures location here
…ouping NetworkSelection and NetworkSummary were dead code — exported but never imported in page.tsx. TaskOption/groupUpgradesByTask was built for an explicit network-selection step that was never wired up; auto-picking networks[0] was a silent alphabetically-first bug. UpgradeSelection now renders Upgrade[] directly, one card per upgrade. Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
- Remove actualUpgradeId no-op alias in install-deps route - Remove startDir param from findContractDeploymentsRoot (no callers pass it) - Remove deriveDateFromContent and folderHasDate logic (task folders always have date prefix) - Remove redundant sort in upgrades route (getUpgradeOptions already sorts) - Revert StepIndicator CSS change (unrelated to this PR) - Update README: task-origin signatures are over the network config folder, not active/evm Generated with Claude Code Co-Authored-By: Claude <noreply@anthropic.com>
f6e330e to
d99a7fe
Compare
Summary
This updates the signing process for the new Contract Ops active EVM task layout.
The signer UI now discovers active EVM task folders and keeps task, network, and signer profile selection explicit:
active/evmactive/evm/tasks/<task-id>active/evm/tasks/<task-id>/config/<network>/validationsactive/evm/tasks/<task-id>/config/<network>/signaturesStacked on #181.
What changed
Task discovery
active/evm/tasks/<task-id>.getUpgradeOptions(network)now returns active tasks that have validation configs for the selected network.active/evm/tasks/<task-id>/config/<network>/README.md,active/evm/tasks/<task-id>/README.md, oractive/evm/README.mdwhen present.Signer flow
upgradeIdremains part of the app contract because multiple active tasks can exist at the same time.API changes
/api/upgrades?readyToSign=truereturns ready-to-sign active task/network pairs./api/upgrade-configacceptsnetworkandupgradeId./api/install-depsacceptsnetworkandupgradeId, verifies the selected task exists, and runsmake depsfromactive/evm.Docs
active/evm/tasks/<task-id>/config/<network>layout.Tests
Verification
npm testnpm run lintnpm run buildAll checks passed locally.