Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4b974a2
feat: add governance SDK functions — transferOwnership, scheduleUpgra…
crypt0fairy Mar 6, 2026
12e2770
feat: add CLI commands — app ownership transfer, upgrade schedule, up…
crypt0fairy Mar 6, 2026
764f38a
feat: rename governed→timelocked, add ownership/upgrade governance co…
crypt0fairy Mar 6, 2026
0b144a1
feat: add cancelUpgrade, team grant/revoke/list commands
crypt0fairy Mar 12, 2026
7801973
add command identity matrix
crypt0fairy Mar 12, 2026
5898936
feat: identity-centric auth — EOA/Safe/Timelock identities with activ…
crypt0fairy Mar 14, 2026
62efff3
feat: check for existing canonical Timelock before deploying in auth new
crypt0fairy Mar 14, 2026
9e20d85
fix: default Timelock proposer to signing key for EOA; prompt only fo…
crypt0fairy Mar 14, 2026
df38ffc
feat: safe identity flows, consistent warnings, show existing key bef…
crypt0fairy Mar 14, 2026
c230f0a
fix: read scheduled Release from chain event instead of rebuilding
crypt0fairy Mar 23, 2026
2cd50ad
test: add unit tests for getScheduledRelease
crypt0fairy Mar 23, 2026
55cf774
feat: add ecloud SDK and CLI support for timelocked governance operat…
crypt0fairy Mar 23, 2026
a2d92c3
docs: update identity command matrix with new governance commands and…
crypt0fairy Mar 24, 2026
402428c
refactor: split auth into keyring management + identity management
crypt0fairy Apr 10, 2026
021997b
docs: add identity limits and examples to auth flow map
crypt0fairy Apr 10, 2026
57ae775
feat: discover Timelock for both EOA and Safe proposers
crypt0fairy Apr 10, 2026
1ce68f8
docs: clarify Timelock CREATE2 determinism for both EOA and Safe
crypt0fairy Apr 10, 2026
395e930
feat: compute app list groups apps by identity, no private key required
crypt0fairy Apr 10, 2026
05ebcf0
feat: compute app list with identity grouping and API auth
crypt0fairy Apr 10, 2026
543f657
feat: identity-aware transaction routing for start/stop/terminate
crypt0fairy Apr 13, 2026
a8510ac
refactor: remove per-operation timelock commands, add identity routin…
crypt0fairy Apr 15, 2026
237fe9c
feat: use factory deployer registry for identity recovery on login
crypt0fairy Apr 15, 2026
908606c
fix: discover Safe-deployed Timelocks during login identity scan
crypt0fairy Apr 15, 2026
aab26c6
fix: use factory registry for identity discovery, fix whoami hints
crypt0fairy Apr 16, 2026
5ab224e
fix: allow deploying additional timelocks when one already exists
crypt0fairy Apr 16, 2026
85666b1
feat: support random salt for deploying multiple timelocks from same EOA
crypt0fairy Apr 16, 2026
7fa73f1
fix: use delay-derived deterministic salt instead of random
crypt0fairy Apr 16, 2026
c2e80f4
fix: require unit in delay input, validate at prompt
crypt0fairy Apr 16, 2026
574babb
fix: let runtime BUILD_TYPE env var override build-time constant
crypt0fairy Apr 16, 2026
8d28d8a
fix: show delay alongside address in existing timelock list and selector
crypt0fairy Apr 16, 2026
d5e0a4e
fix: update sepolia-dev AppController address after redeploy
crypt0fairy Apr 16, 2026
28489f4
feat: add auth sync command to rebuild identities from chain
crypt0fairy Apr 16, 2026
35056f9
fix: add identity creation hint to whoami output
crypt0fairy Apr 16, 2026
fc1479b
auth: identity UX overhaul — Safe/Timelock governance, sync command, …
crypt0fairy Apr 16, 2026
4fef5d6
feat: identity routing for team roles + lifecycle governance fixes
crypt0fairy Apr 17, 2026
201a547
feat: show pending Timelock ops in whoami + update AppController address
crypt0fairy Apr 17, 2026
7078024
fix: resolve Timelock(Safe) identity by checking PROPOSER_ROLE on-chain
crypt0fairy Apr 17, 2026
803f2ed
feat: add --execute and --cancel flags for Timelock operations
crypt0fairy Apr 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
505 changes: 505 additions & 0 deletions docs/auth-flow-map.md

Large diffs are not rendered by default.

201 changes: 201 additions & 0 deletions docs/governance-commands.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
# Timelocked Upgrade Commands

EigenCloud supports two upgrade flows depending on who owns the app:

- **EOA or Safe owner** — direct upgrade via `upgradeApp`, controller acts immediately (Safe handles threshold approval externally)
- **Timelock owner** — two-step flow: schedule → wait → execute

Timelocked mode is set automatically when ownership is transferred to a Timelock deployed by `SafeTimelockFactory`.

---

## Commands

### `ecloud compute app ownership transfer`

Transfer ownership of an app to a new address.

```
ecloud compute app ownership transfer --app=<id> --to=<address>
```

| Flag | Required | Description |
|------|----------|-------------|
| `--app` | yes | App ID or name |
| `--to` | yes | New owner address |

If `--to` is a Timelock deployed by `SafeTimelockFactory`, **timelocked mode is enabled automatically** and direct upgrades are blocked. Transferring to a Safe or EOA does not enable timelocked mode.

**Examples:**

```sh
# Transfer to another EOA — no governance change
ecloud compute app ownership transfer \
--app=0xAbc...123 \
--to=0xDef...456

# Transfer to a Timelock — timelocked mode enabled
ecloud compute app ownership transfer \
--app=0xAbc...123 \
--to=0xTimelock...789
```

---

### `ecloud compute app upgrade schedule`

Schedule an upgrade for a timelocked app. Builds the image and commits a hash on-chain. The controller takes no action until `execute` is called after the delay.

```
ecloud compute app upgrade schedule --app=<id> --after=<delay> [build flags]
```

| Flag | Required | Description |
|------|----------|-------------|
| `--app` | yes | App ID or name |
| `--after` | yes | Delay before upgrade can execute: `30s`, `5m`, `2h`, `1d` |
| `--image-ref` | no | Image reference pointing to registry |
| `--dockerfile` | no | Path to Dockerfile (alternative to `--image-ref`) |
| `--env-file` | no | Environment file (default: `.env`) |
| `--instance-type` | no | Machine instance type |
| `--log-visibility` | no | `public`, `private`, or `off` |
| `--resource-usage-monitoring` | no | `enable` or `disable` |

**Example:**

```sh
ecloud compute app upgrade schedule \
--app=0xAbc...123 \
--after=2h \
--image-ref=myrepo/myapp:v2 \
--env-file=.env.prod \
--instance-type=g1-standard-4t \
--log-visibility=public
```

```
App: 0xAbc...123
Delay: 2h (executable after 3/7/2026, 4:00:00 PM)
Image: myrepo/myapp:v2

✅ Upgrade scheduled (tx: 0x...)

Executable after: 3/7/2026, 4:00:00 PM
Run to execute: ecloud compute app upgrade execute --app=0xAbc...123
```

The `AppUpgradeScheduled` event is emitted on-chain. Multi-sig participants can review the pending upgrade during the delay window.

---

### `ecloud compute app upgrade execute`

Execute a previously scheduled upgrade once the delay has elapsed. Must be called with the **same build inputs** used in `schedule` — the release is reconstructed and its hash is verified against the on-chain commitment.

```
ecloud compute app upgrade execute --app=<id> [same build flags as schedule]
```

| Flag | Required | Description |
|------|----------|-------------|
| `--app` | yes | App ID or name |
| `--image-ref` | no | Must match what was used in `schedule` |
| `--dockerfile` | no | Must match what was used in `schedule` |
| `--env-file` | no | Must match what was used in `schedule` |
| `--instance-type` | no | Must match what was used in `schedule` |
| `--log-visibility` | no | Must match what was used in `schedule` |
| `--resource-usage-monitoring` | no | Must match what was used in `schedule` |

**Example:**

```sh
ecloud compute app upgrade execute \
--app=0xAbc...123 \
--image-ref=myrepo/myapp:v2 \
--env-file=.env.prod \
--instance-type=g1-standard-4t \
--log-visibility=public
```

```
Scheduled upgrade is ready. Proceeding with execution...
Note: build inputs must exactly match what was used in 'upgrade schedule'.

✅ App upgraded successfully (id: 0xAbc...123, image: myrepo/myapp:v2)

View your app: https://app.eigencloud.xyz/apps/0xAbc...123
```

**Error cases:**

```
# Delay not elapsed
✗ Upgrade is not ready yet. Executable after 3/7/2026, 4:00:00 PM (6847s remaining).

# No scheduled upgrade
✗ No upgrade is scheduled for this app. Run 'ecloud compute app upgrade schedule' first.

# Release mismatch (wrong inputs)
✗ contract error: ReleaseMismatch
```

---

### `ecloud compute app upgrade` (unchanged for EOA apps)

Direct upgrade — unchanged behavior for non-governed apps.

```
ecloud compute app upgrade --app=<id> [build flags]
```

If called on a timelocked app:

```
✗ App 0xAbc...123 is timelocked (Timelock owner).
Use the two-step timelocked flow instead:
ecloud compute app upgrade schedule --app=0xAbc...123 --after=<delay>
ecloud compute app upgrade execute --app=0xAbc...123
```

---

## Flow summary

```
EOA or Safe-owned app
──────────────────────
ecloud compute app upgrade
└─ upgradeApp() on-chain
└─ AppUpgraded event → controller acts immediately
(Safe handles multi-sig threshold externally before calling this)

Timelock-owned app
───────────────────
ecloud compute app upgrade schedule --after=2h
└─ scheduleUpgrade() on-chain
└─ AppUpgradeScheduled event (no controller action)
└─ [2h delay — participants can review or cancel]

ecloud compute app upgrade execute
└─ executeUpgrade() on-chain (verifies hash, checks delay)
└─ AppUpgraded event → controller acts
```

---

## Ownership transfer flow

```
ecloud compute app ownership transfer --app=<id> --to=<timelock-address>
└─ transferOwnership() on-chain
└─ SafeTimelockFactory.isTimelock(newOwner) → true → timelocked = true
└─ AppOwnershipTransferred event
└─ direct upgradeApp() now blocked for this app

ecloud compute app ownership transfer --app=<id> --to=<safe-address>
└─ transferOwnership() on-chain
└─ SafeTimelockFactory.isTimelock(newOwner) → false → timelocked = false
└─ AppOwnershipTransferred event
└─ direct upgradeApp() still available (Safe handles threshold externally)
```
Loading
Loading