docs: add multi-operator governance section
This commit is contained in:
102
ARCHITECTURE.md
102
ARCHITECTURE.md
@@ -42,7 +42,49 @@ There is no bootstrap mechanism for SDK clients. They must be explicitly approve
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 3. Server Identity
|
## 3. Multi-Operator Governance
|
||||||
|
|
||||||
|
When more than one User Agent is registered, the vault is treated as having multiple operators. In that mode, sensitive actions are governed by voting rather than by a single operator decision.
|
||||||
|
|
||||||
|
### 3.1 Voting Rules
|
||||||
|
|
||||||
|
Voting is based on the total number of registered operators:
|
||||||
|
|
||||||
|
- **1 operator:** no vote is needed; the single operator decides directly.
|
||||||
|
- **2 operators:** full consensus is required; both operators must approve.
|
||||||
|
- **3 or more operators:** quorum is `floor(N / 2) + 1`.
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
- **3 operators:** 2 approvals required
|
||||||
|
- **4 operators:** 3 approvals required
|
||||||
|
|
||||||
|
### 3.2 Actions Requiring a Vote
|
||||||
|
|
||||||
|
In multi-operator mode, a successful vote is required for:
|
||||||
|
|
||||||
|
- approving new SDK clients
|
||||||
|
- granting an SDK client visibility to a wallet
|
||||||
|
- approving a one-off transaction
|
||||||
|
- approving creation of a persistent grant
|
||||||
|
- approving server updates
|
||||||
|
- updating Shamir secret-sharing parameters
|
||||||
|
|
||||||
|
### 3.3 Special Rule for Key Rotation
|
||||||
|
|
||||||
|
Key rotation always requires full quorum, regardless of the normal voting threshold.
|
||||||
|
|
||||||
|
This is stricter than ordinary governance actions because rotating the root key requires every operator to participate in coordinated share refresh/update steps. The root key itself is not redistributed directly, but each operator's share material must be changed consistently.
|
||||||
|
|
||||||
|
### 3.4 Root Key Custody
|
||||||
|
|
||||||
|
When the vault has multiple operators, the vault root key is protected using Shamir secret sharing.
|
||||||
|
|
||||||
|
This ensures that root-key recovery and governance-sensitive changes are aligned with the multi-operator model rather than delegated to a single operator-held secret.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4. Server Identity
|
||||||
|
|
||||||
The server proves its identity using TLS with a self-signed certificate. The TLS private key is generated on first run and is long-term; no rotation mechanism exists yet due to the complexity of multi-peer coordination.
|
The server proves its identity using TLS with a self-signed certificate. The TLS private key is generated on first run and is long-term; no rotation mechanism exists yet due to the complexity of multi-peer coordination.
|
||||||
|
|
||||||
@@ -55,9 +97,9 @@ Peers verify the server by its **public key fingerprint**:
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 4. Key Management
|
## 5. Key Management
|
||||||
|
|
||||||
### 4.1 Key Hierarchy
|
### 5.1 Key Hierarchy
|
||||||
|
|
||||||
There are three layers of keys:
|
There are three layers of keys:
|
||||||
|
|
||||||
@@ -72,19 +114,19 @@ This layered design enables:
|
|||||||
- **Password rotation** without re-encrypting every wallet key (only the root key is re-encrypted).
|
- **Password rotation** without re-encrypting every wallet key (only the root key is re-encrypted).
|
||||||
- **Root key rotation** without requiring the user to change their password.
|
- **Root key rotation** without requiring the user to change their password.
|
||||||
|
|
||||||
### 4.2 Encryption at Rest
|
### 5.2 Encryption at Rest
|
||||||
|
|
||||||
The database stores everything in encrypted form using symmetric AEAD. The encryption scheme is versioned to support transparent migration — when the vault unseals, Arbiter automatically re-encrypts any entries that are behind the current scheme version. See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the specific scheme and versioning mechanism.
|
The database stores everything in encrypted form using symmetric AEAD. The encryption scheme is versioned to support transparent migration — when the vault unseals, Arbiter automatically re-encrypts any entries that are behind the current scheme version. See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the specific scheme and versioning mechanism.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 5. Vault Lifecycle
|
## 6. Vault Lifecycle
|
||||||
|
|
||||||
### 5.1 Sealed State
|
### 6.1 Sealed State
|
||||||
|
|
||||||
On boot, the root key is encrypted and the server cannot perform any signing operations. This state is called **Sealed**.
|
On boot, the root key is encrypted and the server cannot perform any signing operations. This state is called **Sealed**.
|
||||||
|
|
||||||
### 5.2 Unseal Flow
|
### 6.2 Unseal Flow
|
||||||
|
|
||||||
To transition to the **Unsealed** state, a User Agent must provide the password:
|
To transition to the **Unsealed** state, a User Agent must provide the password:
|
||||||
|
|
||||||
@@ -95,7 +137,7 @@ To transition to the **Unsealed** state, a User Agent must provide the password:
|
|||||||
- **Success:** The root key is decrypted and placed into a hardened memory cell. The server transitions to `Unsealed`. Any entries pending encryption scheme migration are re-encrypted.
|
- **Success:** The root key is decrypted and placed into a hardened memory cell. The server transitions to `Unsealed`. Any entries pending encryption scheme migration are re-encrypted.
|
||||||
- **Failure:** The server returns an error indicating the password is incorrect.
|
- **Failure:** The server returns an error indicating the password is incorrect.
|
||||||
|
|
||||||
### 5.3 Memory Protection
|
### 6.3 Memory Protection
|
||||||
|
|
||||||
Once unsealed, the root key must be protected in memory against:
|
Once unsealed, the root key must be protected in memory against:
|
||||||
|
|
||||||
@@ -107,9 +149,9 @@ See [IMPLEMENTATION.md](IMPLEMENTATION.md) for the current and planned memory pr
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 6. Permission Engine
|
## 7. Permission Engine
|
||||||
|
|
||||||
### 6.1 Fundamental Rules
|
### 7.1 Fundamental Rules
|
||||||
|
|
||||||
- SDK clients have **no access by default**.
|
- SDK clients have **no access by default**.
|
||||||
- Access is granted **explicitly** by a User Agent.
|
- Access is granted **explicitly** by a User Agent.
|
||||||
@@ -119,11 +161,45 @@ Each blockchain requires its own policy system due to differences in static tran
|
|||||||
|
|
||||||
Arbiter is also responsible for ensuring that **transaction nonces are never reused**.
|
Arbiter is also responsible for ensuring that **transaction nonces are never reused**.
|
||||||
|
|
||||||
### 6.2 EVM Policies
|
### 7.2 EVM Policies
|
||||||
|
|
||||||
Every EVM grant is scoped to a specific **wallet** and **chain ID**.
|
Every EVM grant is scoped to a specific **wallet** and **chain ID**.
|
||||||
|
|
||||||
#### 6.2.1 Transaction Sub-Grants
|
#### 7.2.0 Transaction Signing Sequence
|
||||||
|
|
||||||
|
The high-level interaction order is:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
autonumber
|
||||||
|
actor SDK as SDK Client
|
||||||
|
participant Server
|
||||||
|
participant UA as User Agent
|
||||||
|
|
||||||
|
SDK->>Server: SignTransactionRequest
|
||||||
|
Server->>Server: Resolve wallet and wallet visibility
|
||||||
|
alt Visibility approval required
|
||||||
|
Server->>UA: Ask for wallet visibility approval
|
||||||
|
UA-->>Server: Vote result
|
||||||
|
end
|
||||||
|
Server->>Server: Evaluate transaction
|
||||||
|
Server->>Server: Load grant and limits context
|
||||||
|
alt Grant approval required
|
||||||
|
Server->>UA: Ask for execution / grant approval
|
||||||
|
UA-->>Server: Vote result
|
||||||
|
opt Create persistent grant
|
||||||
|
Server->>Server: Create and store grant
|
||||||
|
end
|
||||||
|
Server->>Server: Retry evaluation
|
||||||
|
end
|
||||||
|
critical Final authorization path
|
||||||
|
Server->>Server: Check limits and record execution
|
||||||
|
Server-->>Server: Signature or evaluation error
|
||||||
|
end
|
||||||
|
Server-->>SDK: Signature or error
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 7.2.1 Transaction Sub-Grants
|
||||||
|
|
||||||
Arbiter maintains an ever-expanding database of known contracts and their ABIs. Based on contract knowledge, transaction requests fall into three categories:
|
Arbiter maintains an ever-expanding database of known contracts and their ABIs. Based on contract knowledge, transaction requests fall into three categories:
|
||||||
|
|
||||||
@@ -147,7 +223,7 @@ Available restrictions:
|
|||||||
|
|
||||||
These transactions have no `calldata` and therefore cannot interact with contracts. They can be subject to the same volume and rate restrictions as above.
|
These transactions have no `calldata` and therefore cannot interact with contracts. They can be subject to the same volume and rate restrictions as above.
|
||||||
|
|
||||||
#### 6.2.2 Global Limits
|
#### 7.2.2 Global Limits
|
||||||
|
|
||||||
In addition to sub-grant-specific restrictions, the following limits can be applied across all grant types:
|
In addition to sub-grant-specific restrictions, the following limits can be applied across all grant types:
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,52 @@ The central abstraction is the `Policy` trait. Each implementation handles one s
|
|||||||
4. **Evaluate** — `Policy::evaluate` checks the decoded meaning against the grant's policy-specific constraints and returns any violations.
|
4. **Evaluate** — `Policy::evaluate` checks the decoded meaning against the grant's policy-specific constraints and returns any violations.
|
||||||
5. **Record** — If `RunKind::Execution` and there are no violations, the engine writes to `evm_transaction_log` and calls `Policy::record_transaction` for any policy-specific logging (e.g., token transfer volume).
|
5. **Record** — If `RunKind::Execution` and there are no violations, the engine writes to `evm_transaction_log` and calls `Policy::record_transaction` for any policy-specific logging (e.g., token transfer volume).
|
||||||
|
|
||||||
|
The detailed branch structure is shown below:
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
flowchart TD
|
||||||
|
A[SDK Client sends sign transaction request] --> B[Server resolves wallet]
|
||||||
|
B --> C{Wallet exists?}
|
||||||
|
|
||||||
|
C -- No --> Z1[Return wallet not found error]
|
||||||
|
C -- Yes --> D[Check SDK client wallet visibility]
|
||||||
|
|
||||||
|
D --> E{Wallet visible to SDK client?}
|
||||||
|
E -- No --> F[Start wallet visibility voting flow]
|
||||||
|
F --> G{Vote approved?}
|
||||||
|
G -- No --> Z2[Return wallet access denied error]
|
||||||
|
G -- Yes --> H[Persist wallet visibility]
|
||||||
|
E -- Yes --> I[Classify transaction meaning]
|
||||||
|
H --> I
|
||||||
|
|
||||||
|
I --> J{Meaning supported?}
|
||||||
|
J -- No --> Z3[Return unsupported transaction error]
|
||||||
|
J -- Yes --> K[Find matching grant]
|
||||||
|
|
||||||
|
K --> L{Grant exists?}
|
||||||
|
L -- Yes --> M[Check grant limits]
|
||||||
|
L -- No --> N[Start execution or grant voting flow]
|
||||||
|
|
||||||
|
N --> O{User-agent decision}
|
||||||
|
O -- Reject --> Z4[Return no matching grant error]
|
||||||
|
O -- Allow once --> M
|
||||||
|
O -- Create grant --> P[Create grant with user-selected limits]
|
||||||
|
P --> Q[Persist grant]
|
||||||
|
Q --> M
|
||||||
|
|
||||||
|
M --> R{Limits exceeded?}
|
||||||
|
R -- Yes --> Z5[Return evaluation error]
|
||||||
|
R -- No --> S[Record transaction in logs]
|
||||||
|
S --> T[Produce signature]
|
||||||
|
T --> U[Return signature to SDK client]
|
||||||
|
|
||||||
|
note1[Limit checks include volume, count, and gas constraints.]
|
||||||
|
note2[Grant lookup depends on classified meaning, such as ether transfer or token transfer.]
|
||||||
|
|
||||||
|
K -. uses .-> note2
|
||||||
|
M -. checks .-> note1
|
||||||
|
```
|
||||||
|
|
||||||
### Policy Trait
|
### Policy Trait
|
||||||
|
|
||||||
| Method | Purpose |
|
| Method | Purpose |
|
||||||
|
|||||||
Reference in New Issue
Block a user