153 lines
4.6 KiB
Markdown
153 lines
4.6 KiB
Markdown
# Agent Guidelines for Motr Enclave
|
|
|
|
**Generated:** 2026-01-10 | **Commit:** 1c8b908 | **Branch:** main
|
|
|
|
## Overview
|
|
|
|
Go 1.25+ Extism WASM plugin (`wasip1`) providing encrypted key storage for Nebula wallet. SQLite-centric architecture where database acts as "DID CPU" with custom crypto functions.
|
|
|
|
## Structure
|
|
|
|
```
|
|
motr-enclave/
|
|
├── cmd/enclave/ # WASM entry: generate, load, exec, query, ping
|
|
├── internal/
|
|
│ ├── keybase/ # DB layer + SQLite functions + action handlers
|
|
│ ├── crypto/{mpc,ucan,bip44} # Threshold sigs, UCAN v1.0.0-rc.1, derivation
|
|
│ ├── types/ # JSON I/O structs
|
|
│ ├── state/ # WASM singleton state
|
|
│ └── migrations/ # Schema + SQLC queries (embedded)
|
|
├── src/ # TypeScript SDK (@sonr/motr-enclave)
|
|
└── example/ # Browser demo (Vite)
|
|
```
|
|
|
|
## Where to Look
|
|
|
|
| Task | Location | Notes |
|
|
|------|----------|-------|
|
|
| Add WASM export | `cmd/enclave/main.go` | `//go:wasmexport` + pdk pattern |
|
|
| Add exec action | `internal/keybase/exec.go` | Add to `handlers` map |
|
|
| New action handler | `internal/keybase/actions_*.go` | `handle<Resource><Action>` signature |
|
|
| SQLite custom func | `internal/keybase/functions.go` | `conn.CreateFunction` pattern |
|
|
| DB schema change | `internal/migrations/schema.sql` | Then `make generate` |
|
|
| New query | `internal/migrations/query.sql` | SQLC annotations |
|
|
| MPC operations | `internal/crypto/mpc/` | 2-of-2 threshold ECDSA |
|
|
| UCAN builders | `internal/crypto/ucan/` | v1.0.0-rc.1 DAG-CBOR |
|
|
| SDK wrapper | `src/enclave.ts` | Extism JSON bridge |
|
|
|
|
## Code Map
|
|
|
|
### WASM Exports (cmd/enclave/main.go)
|
|
| Function | Purpose |
|
|
|----------|---------|
|
|
| `ping` | Health check |
|
|
| `generate` | Create identity + MPC key from WebAuthn credential |
|
|
| `load` | Hydrate from encrypted DB blob |
|
|
| `exec` | Resource-action dispatcher |
|
|
| `query` | Return DID document |
|
|
|
|
### Exec Filter Syntax
|
|
```
|
|
resource:<name> action:<action> [subject:<value>]
|
|
```
|
|
|
|
| Resource | Actions |
|
|
|----------|---------|
|
|
| `accounts` | list, get, sign |
|
|
| `enclaves` | list, get, sign, rotate, archive, delete |
|
|
| `delegations` | list, list_received, list_command, get, revoke, verify, cleanup |
|
|
| `credentials` | list, get |
|
|
| `sessions` | list, revoke |
|
|
| `grants` | list, revoke |
|
|
| `services` | list, get, get_by_id |
|
|
|
|
### SQLite Functions (DID CPU)
|
|
| Function | Purpose |
|
|
|----------|---------|
|
|
| `bip44_derive(pubkey_hex, chain)` | Address from pubkey |
|
|
| `bip44_derive_from_enclave(id, chain)` | Address from stored enclave |
|
|
| `mpc_sign(enclave_id, data)` | Threshold signature |
|
|
|
|
## Conventions
|
|
|
|
### Import Order
|
|
```go
|
|
import (
|
|
"stdlib"
|
|
|
|
"external/deps"
|
|
|
|
"enclave/internal"
|
|
)
|
|
```
|
|
|
|
### Naming
|
|
- Types: `PascalCase` | JSON: `snake_case`
|
|
- Handlers: `handle<Resource><Action>`
|
|
- Errors: prefix with function name
|
|
|
|
### Extism Plugin Pattern
|
|
```go
|
|
//go:wasmexport functionName
|
|
func functionName() int32 {
|
|
pdk.Log(pdk.LogInfo, "functionName: starting")
|
|
var input InputType
|
|
if err := pdk.InputJSON(&input); err != nil {
|
|
pdk.SetError(fmt.Errorf("functionName: %w", err))
|
|
return 1
|
|
}
|
|
// ...
|
|
pdk.OutputJSON(output)
|
|
return 0
|
|
}
|
|
```
|
|
|
|
### ActionManager Pattern
|
|
```go
|
|
func (am *ActionManager) DoThing(ctx context.Context, params) (Result, error) {
|
|
am.kb.mu.RLock() // or Lock() for writes
|
|
defer am.kb.mu.RUnlock()
|
|
return am.queries.SomeQuery(ctx, params)
|
|
}
|
|
```
|
|
|
|
## Anti-Patterns
|
|
|
|
| Forbidden | Reason |
|
|
|-----------|--------|
|
|
| Edit `*.sql.go` files | SQLC generated - `make generate` |
|
|
| `as any` / type suppression | Type safety critical for crypto |
|
|
| Log/return raw key material | Security - shares never leave enclave |
|
|
| Skip mutex in ActionManager | WASM single-threaded but state persists |
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
make build # GOOS=wasip1 GOARCH=wasm
|
|
make generate # SQLC code gen
|
|
make test-plugin # Extism CLI validation
|
|
make sdk # Build TypeScript SDK
|
|
make start # Full setup + dev server
|
|
```
|
|
|
|
## Data Boundaries
|
|
|
|
### Stored in Enclave
|
|
- WebAuthn credentials, MPC key shares, UCAN delegations
|
|
- Sessions, grants, DID document cache, multi-chain accounts
|
|
|
|
### NOT in Enclave (fetch from APIs)
|
|
- Token balances, transaction history, NFT holdings, prices
|
|
|
|
## Build Constraints
|
|
|
|
- `cmd/enclave/`, `internal/state/`: `//go:build wasip1` only
|
|
- Target: `GOOS=wasip1 GOARCH=wasm -buildmode=c-shared`
|
|
- Encryption: AES-256-GCM via WebAuthn PRF key derivation
|
|
|
|
## Notes
|
|
|
|
- No `*_test.go` files currently - tests in `example/` browser suite
|
|
- UCAN uses DAG-CBOR envelopes, not JWT (v1.0.0-rc.1)
|
|
- Database serialized as single encrypted blob for storage
|