Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
a525188
app operations + trust model implementation
solimander Dec 10, 2025
afe309b
docs: clarify EOA role description in app operations trust model
solimander Dec 10, 2025
c7ea6e4
refactor: migrate TimelockController deployment from Create2 to minim…
solimander Dec 13, 2025
bdecd2a
docs: simplify auth login flow in app operations trust model document…
solimander Jan 5, 2026
fa00bfa
feat: add v1.4.0-governance release scripts, tests, and bindings
crypt0fairy Mar 3, 2026
3a24e39
chore: add Safe infrastructure addresses to sepolia-dev deployment
crypt0fairy Mar 3, 2026
7db5ee7
refactor: rename defaultFallbackHandler to safeFallbackHandler
crypt0fairy Mar 3, 2026
4421d8a
fix: set upgrade.json from version to 1.3.0
crypt0fairy Mar 3, 2026
abed93f
feat: add governed upgrade flow and Safe-detected ownership transfer
crypt0fairy Mar 6, 2026
f7a1458
test: add governance flow tests (transferOwnership, scheduleUpgrade, …
crypt0fairy Mar 6, 2026
29aae11
feat: add getAppGoverned view function to IAppController and AppContr…
crypt0fairy Mar 6, 2026
4a416bc
fix: governed flag set only for Safe owners, not Timelock — Timelock …
crypt0fairy Mar 6, 2026
c1047ad
feat: add cancelUpgrade to AppController
crypt0fairy Mar 12, 2026
0c98eb0
feat: enforce timelock-only access for transferOwnership, terminateAp…
crypt0fairy Mar 23, 2026
1ad801c
chore: run forge fmt
crypt0fairy Apr 8, 2026
4681f6d
fix: resolve AppConfigStorage rename and missing safeTimelockFactory …
crypt0fairy Apr 8, 2026
395aece
chore: regenerate Go bindings
crypt0fairy Apr 8, 2026
1b81574
refactor: remove scheduleUpgrade/executeUpgrade, route all sensitive …
crypt0fairy Apr 15, 2026
c8acadd
chore: run forge fmt
crypt0fairy Apr 15, 2026
cef7b48
chore: regenerate Go bindings after scheduleUpgrade removal
crypt0fairy Apr 15, 2026
8200b7a
ci: pin GitHub Actions to full commit SHAs per org policy
crypt0fairy Apr 15, 2026
ba6c46a
feat: add deployer-indexed registry to SafeTimelockFactory
crypt0fairy Apr 15, 2026
bd975f8
chore: update sepolia-dev deployment output with new contract addresses
crypt0fairy Apr 15, 2026
04197e8
fix: pass real Safe addresses to SafeTimelockFactory constructor
crypt0fairy Apr 16, 2026
349714d
feat: add pending op enumeration to TimelockControllerImpl + redeploy…
crypt0fairy Apr 17, 2026
1a04556
fix: include factory address in _deriveSalt to prevent cross-factory …
crypt0fairy Apr 17, 2026
ce741ba
feat: validate Timelock targets at schedule-time via ICallValidator
crypt0fairy Apr 20, 2026
b98bfde
chore: run forge fmt
crypt0fairy Apr 20, 2026
2153dbe
chore: regenerate Go bindings
crypt0fairy Apr 20, 2026
b5fde69
chore: bump governance release to v1.5.0
crypt0fairy Apr 23, 2026
53c13bd
fix: set timelocked at app creation + bump release version
crypt0fairy Apr 23, 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
6 changes: 3 additions & 3 deletions .github/workflows/bindings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ jobs:
name: Check Go Bindings
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
submodules: recursive

- name: Set up Go
uses: actions/setup-go@v4
uses: actions/setup-go@f111f3307d8850f501ac008e886eec1fd1932a34 # v4
with:
go-version: '1.24'

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1

- name: Build contracts
run: forge build --no-metadata
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ jobs:
name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
uses: foundry-rs/foundry-toolchain@82dee4ba654bd2146511f85f0d013af94670c4de # v1

- name: Show Forge version
run: |
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@ out/

/broadcast/

# Docs
docs/

# Dotenv file
.env
.idea
Expand Down
2 changes: 2 additions & 0 deletions bin/compile-bindings.sh
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ contracts=(
"IReleaseManager"
"IPermissionController"
"USDCCredits"
"SafeTimelockFactory"
"TimelockControllerImpl"
)

forge b --no-metadata
Expand Down
206 changes: 206 additions & 0 deletions docs/APP_OPERATIONS_TRUST_MODEL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
# App Operations & Trust Model

> **Note:** This branch includes a POC implementation of the changes described in this spec.

## Overview

This spec describes a new operational model for Eigen Compute apps, focusing on team operations and trust guarantees. The goals are:

1. Make the operational structure legible for teams building on Eigen Compute
2. Enable teams to make verifiable commitments to their users (e.g., upgrade delays that can't be bypassed)

## Design Principles

1. **Role-based, not function-based** - Simpler to reason about than per-function permissions
2. **Team-scoped** - Roles are granted per-team (owner address), not per-app
3. **Legibility** - Trust configurations must be displayable on all interfaces
4. **Factory-deployed primitives** - Timelocks and multisigs deployed via factories can be verified as legitimate

## Team Model

An app owner's address IS the team identity. This is similar to GitHub or Vercel teams, but the team is built around the owner address rather than a separate entity. This keeps things simple - no team entity to create, straightforward billing tied to the owner, and works naturally for the common case of a single EOA or multisig. Ownership can be transferred to a new address if the team structure changes (see Future Additions).

Any role (including the team owner) can be:
- An EOA (solo dev)
- A multisig (shared control)
- An EOA or multisig behind a timelock (for enforced delays on sensitive operations)

This also enables a cleaner UX: manage your team once, and all apps under that team inherit the same permissions. App-level permissions would require managing access separately for each app, and wouldn't align with billing which is at the owner level.

## Roles

Roles are scoped to the team via `keccak256(abi.encode(teamAddress, TeamRole))`.

| Role | Capabilities |
|------|-------------|
| `ADMIN` | Full access: create apps, upgrade, start, stop, terminate, manage roles |
| `PAUSER` | Stop apps (emergency response) |
| `DEVELOPER` | Update metadata, view logs, submit builds |

Admins implicitly have all other roles. The last admin cannot be revoked or renounced (prevents accidental lockout).

## SafeTimelockFactory

Factory for deploying verified Gnosis Safes and OZ TimelockControllers. Deployed contracts can be verified via `isSafe()` and `isTimelock()`.

### Why a factory?

- Factory deployment guarantees unmodified OZ TimelockController (no bypasses)
- Enables UIs to display accurate delay information with confidence
- Supports atomic Safe + Timelock setup via EIP-7702: predict Safe address, deploy both, and configure Safe as proposer in a single transaction

### Safe Deployment

```solidity
struct SafeConfig {
address[] owners;
uint256 threshold;
}

deploySafe(config, salt) → deterministic address
```

### Timelock Deployment

```solidity
struct TimelockConfig {
uint256 minDelay;
address[] proposers;
address[] executors;
}

deployTimelock(config, salt) → deterministic address
```

## Typical Configurations

| Setup | Admin Entity | Delay |
|-------|-------------|-------|
| Dev/testing | EOA | 0 |
| Production | Multisig behind timelock | >0 |

For emergency response, grant `PAUSER` to a lower-threshold multisig or EOA that can stop apps without going through the timelock.

## CLI Integration

### Identity (`ecloud auth`)

**Login to existing identity:**

```
ecloud auth login

> Connect wallet or enter EOA address: 0x1234...

> Select an identity:
1. 0x1234... (your wallet)
───
2. 0xABCD... (Timelock, 24h) via 2/3 Safe
3. 0x9999... (3/5 Safe)

> Select: 1

> Logged in as: 0x1234...
```

**Create new identity:**

```
ecloud auth new

> What would you like to create?
1. EOA (new private key)
2. Gnosis Safe
3. Timelock (for existing EOA or Safe)

# For Safe:
> Enter owner addresses: 0x1111..., 0x2222..., 0x3333...
> Enter threshold (e.g., 2 of 3): 2

> Add timelock delay? (y/N) y
> Enter minimum delay (e.g., "24h", "7d"): 24h

> Deploying Safe + Timelock via factory...

# For Timelock:
> Enter proposer/executor address (your EOA or Safe): 0x1234...
> Enter minimum delay (e.g., "24h", "7d"): 24h

> Deploying Timelock via factory...
> Your new identity: 0x5678... (timelock)
> Proposer/Executor: 0x1234...
```

When a timelock is configured, the CLI deploys via SafeTimelockFactory with the specified address as both proposer and executor.

**App actions with Safe:**

When logged in as a Safe, app actions propose a transaction and link to the Safe UI:

```
ecloud compute app upgrade

> Transaction proposed to Safe.
> View and sign at: https://app.safe.global/transactions/queue?safe=eth:0x1234...
```

**Viewing trust configuration:**

```
ecloud compute app info <app-id>

> App: my-app
> Owner: 0x1234... (3/5 Safe behind 24h timelock)
> Status: STARTED
>
> Team Roles:
> ADMIN: 0x1234... (3/5 Safe behind 24h timelock)
> 0xabcd... (EOA)
> PAUSER: 0x5678... (2/3 Safe, no delay)
> DEVELOPER: 0x9999... (EOA)
```

### Team Management (`ecloud compute team`)

Manage roles for your team:

```
ecloud compute team grant <address> [role]
ecloud compute team revoke <address> [role]
ecloud compute team list
```

**Grant (interactive):**

```
ecloud compute team grant 0x1234...

> Select role to grant:
1. ADMIN - Full access: create apps, upgrade, start, stop, terminate, manage roles
2. PAUSER - Stop apps (emergency response)
3. DEVELOPER - Update metadata, view logs, submit builds

> Role granted successfully.
```

**Revoke (interactive):**

```
ecloud compute team revoke 0x1234...

> 0x1234... has: PAUSER, DEVELOPER
> Select role to revoke:
1. PAUSER
2. DEVELOPER

> Role revoked successfully.
```

## Migration

`migrateAdmins(apps[])` is a one-time state migration performed by Eigen admins to bridge existing PermissionController admins to AccessControl.

## Future Additions

- **Timelock Operations CLI** (`ecloud compute tx list`, `ecloud compute tx execute`) - View pending operations and execute when ready. Requires Safe Transaction Service integration and event indexing.
- **[App Ownership Transfer](future/APP_OWNERSHIP_TRANSFER.md)** - Two-step transfer pattern to move apps between teams (useful for acquisitions, team restructuring)
Loading
Loading