Skip to content

Automation#202

Draft
sparrowDom wants to merge 42 commits into
mainfrom
automation
Draft

Automation#202
sparrowDom wants to merge 42 commits into
mainfrom
automation

Conversation

@sparrowDom
Copy link
Copy Markdown
Member

No description provided.

apexearth and others added 30 commits March 31, 2026 13:15
Rename 26 Defender action files from src/js/actions/*.js to
src/js/tasks/actions/*.ts in preparation for converting them
from OpenZeppelin Defender handlers to the action() builder pattern.
Both origin-dollar and arm-oeth cron containers use the same KMS signer,
risking nonce collisions when transactions are sent concurrently. This adds
a Postgres-backed nonce lock that wraps the signer transparently via
SELECT ... FOR UPDATE, holding the row lock for the full tx lifecycle.

- nonceQueue.ts: withNonceLock + wrapWithNonceQueue signer wrapper
- action.ts: conditionally wraps signer when DATABASE_URL is set
- docker-compose.yml: adds postgres service for local dev
- cron-supervisor.ts: pool cleanup on shutdown
- Includes integration tests verifying lock serialization
- Replace console logging with winston/Loki logger in supervisor
- Delete log-events.ts emit wrappers, inline structured logging in action.ts
- Extract HTTP API + run tracking into api.ts, slim supervisor to orchestrator
- Add action.start/action.success events to action framework
- Generate run_id (UUID) per action, remove AUTOMATON_RUN_ID env var
- Add real action.test.ts that exercises createActionHandler() with mock signer
- Delete stale test-action.ts, action-runner.test.ts, snapshot
# Conflicts:
#	cron/cron-supervisor.ts
…client

Before: supercronic (cron/) loops hardhat tasks; local nonce queue +
signer code mirror the automaton library. After: @automaton/client
provides all three primitives; hardhat remains the execution engine
for the action files themselves (unchanged).

New:
- runner.ts — calls runContainer({product:"arm-oeth", workdir:"/app"}).
  Library reads schedules from shared Postgres, croner fires them,
  parent spawns each command and captures stdio into run_logs.
- migrations/seed_schedules.sql — 22 rows mirroring cron/cron-jobs.ts.

Modified:
- src/js/tasks/lib/action.ts — uses @automaton/client's
  wrapSignerWithNonceQueueV6 + createDb/createPool instead of the
  deleted local nonceQueue.ts. No change to ActionContext shape.
- src/js/utils/signers.ts — delegates KMS + privkey paths to the
  library's resolveEthersV6Signer (which auto-detects strategy from
  AWS creds, reads KMS_RELAYER_ID / DEPLOYER_PRIVATE_KEY etc.).
  Hardhat-native fork impersonation + explicit-address paths stay.
  Defender fallback dropped.
- dockerfile-actions — bun base (needed by runner.ts), drop
  Foundry (no cast/forge shellouts anywhere) + supercronic (replaced
  by library's schedule loop), pnpm for install.
- docker-compose.yml — drop Loki env, add ACTION_API_BEARER_TOKEN
  and RUNNER_BASE_URL. Env var names unchanged (MAINNET_URL/etc.).
- .env.example — drop Loki + Defender + DEPLOYER_PRIVATE_KEY,
  document the new runtime env.
- hardhat.config.js — drop nothing; auto-load loop for action files
  still registers every action as a hardhat task.
- package.json — add @automaton/client via git-install subpath.

Deleted (all superseded by @automaton/client):
- src/js/tasks/lib/nonceQueue.ts + .test.ts
- src/js/tasks/lib/nonceQueueTxLifecycle.ts + .test.ts
- cron/ (cron-supervisor, cron-jobs, cron-entrypoint.sh, render-crontab,
  api, README, TODO).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Puts the sibling signer code back to its proven purrikey-based chain
(DEPLOYER_PRIVATE_KEY → KMS via @lastdotnet/purrikey → IMPERSONATE →
Defender → hardhat first signer). The library's resolveEthersV6Signer
is no longer imported here — siblings don't need ergonomic signer
construction; they already had a battle-tested one. The library is
reserved for primitives (nonce queue, runtime) rather than signer
ergonomics, matching the layering it was originally designed for.

What the library DOES still provide, via lib/action.ts:
- wrapSignerWithNonceQueueV6(signer, { db, log }) wraps whatever
  signer getSigner() returns, routing sendTransaction through the
  Postgres row-lock + lifecycle when DATABASE_URL is set. Dev runs
  without a DB get an unwrapped signer.
- createDb / createPool for the shared handle.

Logging: winston + winston-loki are gone. The action wrapper builds a
tiny Logger ({ info, warn, error }) backed by console with an
`[action-name]` prefix. Action bodies calling log.info(...) /
log.error(...) keep working unchanged. The utils/logger.js (debug-based)
used by domain helpers is untouched.

Removed files:
- src/js/tasks/lib/logger.ts (winston + loki transport).
- src/js/tasks/lib/action.test.ts + action.snapshot.jsonl (tested the
  winston structured-logging path we're dropping).
- winston + winston-loki devDeps from package.json.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds a concise "Automated Actions (Automaton)" section to the README
covering runner.ts, the seed SQL, and lib/action.ts's library
integration. Calls out that local `pnpm hardhat <action> --network
<chain>` runs open no DB connection because the nonce-queue wrap is
gated on DATABASE_URL.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drop unused pg + @types/pg deps (vendored transitively by
@automaton/client) and remove stale yarn.lock. Fixes Railway
build failing on `pnpm install --frozen-lockfile`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The oven/bun:1 base image ships bun but not node/npm, so
`npm install -g pnpm` failed at build time. Node is also needed
at runtime for `pnpm hardhat ...` subprocesses spawned by runner.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pnpm 10 requires git-hosted deps with a prepare script to be
allowlisted via onlyBuiltDependencies.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Added installation of Foundry (forge/cast/anvil) to the Dockerfile, ensuring the tools are available at Hardhat config load time. This change updates the PATH to include Foundry binaries, facilitating the use of @nomicfoundation/hardhat-foundry in the project.
Resolves to oplabs/talos tarball. Pairs with dd42c5d (package.json rename).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
apexearth and others added 12 commits April 22, 2026 11:22
Actions that delegate to helper modules (src/js/tasks/*) previously re-
fetched a raw signer via getSigner(), bypassing the nonce-queue Proxy
that lib/action.ts set up on ctx.signer. Move the wrap into getSigner()
itself so every caller, regardless of path, gets the wrapped signer.

Every signer.sendTransaction in production now records a row in
nonce_queue_transactions, populating the Transactions page.

Also drops the now-redundant wrap from tasks/lib/action.ts and adds an
ambient declare-module stub so tsc resolves @talos/client imports
without chasing the private @talos/schema workspace dep.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Talos' per-action "Use Defender Relayer signer" checkbox sets this
env var on the dispatch spawn when an operator opts in. Add a branch
in getSigner() before the KMS check that honors it: if the env vars
are missing throw a structured error (so it surfaces cleanly in
talos run_logs instead of as a Defender SDK 401), otherwise call the
existing getDefenderSigner().

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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