feat: support contract ops task layout#177
Conversation
Co-authored-by: Codex <codex-noreply@coinbase.com>
🟡 Heimdall Review Status
|
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com>
Co-authored-by: Codex <codex-noreply@coinbase.com> # Conflicts: # __tests__/genTaskOriginSig.test.ts
| assertWithinDir(upgradePath, CONTRACT_DEPLOYMENTS_ROOT); | ||
|
|
||
| ): Promise<{ cfg: TaskConfig; scriptPath: string; taskOriginDir: string; signatureDir: string }> { | ||
| const scriptPath = assertWithinDir( |
There was a problem hiding this comment.
task-origin validation no longer attests to the code that is actually executed. This signs/verifies active/evm/tasks/<task>/config/<network>, but cfg.cmd runs from shared active/evm, leaving script/, foundry.toml, Makefile, lib/, and other execution-time inputs outside the signed payload. A post-signature change to those files can affect or fake validation output while task-origin signatures still pass. Please either include all execution-affecting inputs in the signed payload, execute only from signed per-task content, or verify a signed manifest for the shared code/deps before simulation.
|
|
||
| const { command, args, env: envAssignments } = this.extractCommandDetails(forgeCmdParts); | ||
| const spawnEnv = { ...process.env, ...envAssignments }; | ||
| const spawnEnv = { ...process.env, ...envAssignments, RECORD_STATE_DIFF: 'true' }; |
There was a problem hiding this comment.
With this PR, every validation in a checkout runs from active/evm, while StateDiffClient still reads and deletes a fixed stateDiff.json under that workdir. Even if the operational model is one branch/check-out per task, concurrent validations in the same signer-tool instance, for example two tabs, retries, profiles, or networks, can overwrite or delete each other’s diff and cause one request to parse another request’s output. Please use a unique state-diff output path per validation, isolate each validation in a temp workdir, or enforce a process-level validation lock.
| return { | ||
| cfg: parsedConfig.config, | ||
| scriptPath, | ||
| taskOriginDir: networkConfigDir, |
There was a problem hiding this comment.
Because the signed task-origin directory is now config/<network>, createDeterministicTarball will derive names like mainnet.tar / sepolia.tar in process.cwd(). Multiple tasks on the same network can collide during signing or verification, especially concurrently. Please create tarballs in a unique temp file/dir, ideally with cleanup after use.
| ); | ||
| const configFileName = `${opts.taskConfigFileName}.json`; | ||
| const configPath = path.join(upgradePath, 'validations', configFileName); | ||
| const configPath = path.join(configDir, configFileName); |
There was a problem hiding this comment.
taskConfigFileName is request-controlled via /api/validate, and this only asserts the resulting path is inside the repo root. A value containing ../ can escape the selected validations directory while still remaining under CONTRACT_DEPLOYMENTS_ROOT, decoupling the validation config being executed from the selected task/network signatures. Please reject path separators/.. for upgradeId and userType, and assert configPath is within configDir rather than only within the repo root.
| continue; | ||
| } | ||
|
|
||
| grouped.set(upgrade.id, { |
There was a problem hiding this comment.
Grouping by upgrade.id keeps the first Upgrade object and only appends later networks. Since the API can populate metadata from config/<network>/README.md, selecting a different network can still show the first network's title/description/status/date in the task card, summary, and confirmation. Please store metadata per network and swap selectedUpgrade after network selection, or render only task-level metadata before the network is selected.
| onChange?: () => void; | ||
| } | ||
|
|
||
| const formatNetworkName = (network: NetworkType) => |
There was a problem hiding this comment.
Nit: this formatNetworkName helper is duplicated in the new network components and deployments.ts. If this formatting is now shared UI behavior, consider moving it to one helper to avoid drift.
| }; | ||
|
|
||
| const handleUpgradeSelection = (upgrade: Upgrade) => { | ||
| const handleUpgradeSelection = (upgrade: Upgrade, networks: NetworkType[]) => { |
There was a problem hiding this comment.
Test gap: the split task/network flow has no frontend regression coverage. Please add tests for grouping by task id, preserving the correct network list, clearing downstream state when task/network changes, and ensuring validation receives the selected upgradeId and network.
Summary
This updates
task-signing-toolfor the new Contract Ops active EVM task layout.The tool now discovers one or more active EVM task folders and keeps task, network, and signer profile selection explicit in the UI:
active/evmactive/evm/tasks/<task-id>active/evm/tasks/<task-id>/config/<network>/validationsactive/evm/tasks/<task-id>/config/<network>active/evm/tasks/<task-id>/config/<network>/signaturesWhat 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.Validation flow
upgradeId,network, and selected user config.active/evm/tasks/<task-id>/config/<network>/validations/<user>.json.active/evm, so validationcmdvalues should be relative to that directory.active/evm/tasks/<task-id>/config/<network>.active/evm/tasks/<task-id>/config/<network>/signatures.signatures/folder is excluded from deterministic tarballs so generated signatures do not alter the signed payload.API changes
/api/upgrades?readyToSign=truereturns ready-to-sign active task/network pairs./api/upgrade-configacceptsnetworkandupgradeId./api/validateacceptsupgradeId,network, anduserType./api/install-depsacceptsnetworkandupgradeId, verifies the selected task exists, and runsmake depsfromactive/evm.Docs and scripts
active/evm/tasks/<task-id>/config/<network>layout.Tests
signatures/directories are excluded.Verification
npm testnpm run lintnpm run buildAll checks passed locally.