diff --git a/AGENTS.md b/AGENTS.md index cf229bb..8e9d8b1 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,195 +1,152 @@ # Agent Guidelines for Motr Enclave -This document provides guidelines for AI coding agents working in this repository. +**Generated:** 2026-01-10 | **Commit:** 1c8b908 | **Branch:** main -## Project Overview +## Overview -Motr Enclave is an Extism WebAssembly plugin written in Go, compiled with Go 1.25+ for the `wasip1` target. It provides encrypted key storage for the Nebula wallet with an embedded SQLite database. +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. -## Build Commands +## Structure -```bash -# Build WASM plugin (primary build command) -make build - -# Build with debug symbols -make build-debug - -# Build optimized (requires wasm-opt) -make build-opt - -# Generate SQLC database code -make generate - -# Full rebuild -make clean && make generate && make build +``` +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) ``` -## Test Commands +## Where to Look -```bash -# Run all tests -make test +| 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` 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 | -# Run tests with coverage -make test-cover +## Code Map -# Run a single test -go test -v -run TestFunctionName ./... +### 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 | -# Run tests in a specific package -go test -v ./db/... - -# Test the compiled plugin with Extism CLI -make test-plugin +### Exec Filter Syntax +``` +resource: action: [subject:] ``` -## Lint and Format +| 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 | -```bash -# Run all linters -make lint +### 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 | -# Format code -make fmt - -# Run go vet -make vet - -# Run all checks (fmt, vet, lint, test) -make verify -``` - -## Code Style Guidelines - -### Imports - -Order imports in three groups separated by blank lines: -1. Standard library -2. External dependencies -3. Internal packages +## Conventions +### Import Order ```go import ( - "encoding/json" - "errors" - "fmt" + "stdlib" - "github.com/extism/go-pdk" + "external/deps" - "enclave/db" + "enclave/internal" ) ``` -### Naming Conventions - -| Element | Convention | Example | -|---------|------------|---------| -| Exported types | PascalCase | `GenerateInput`, `QueryOutput` | -| Unexported types | PascalCase | `FilterParams` (internal use ok) | -| Struct fields | PascalCase | `CredentialID`, `ChainID` | -| JSON tags | snake_case | `json:"credential_id"` | -| Functions | camelCase for private, PascalCase for exported | `parseFilter`, `Generate` | -| Constants | PascalCase or ALL_CAPS | `MaxRetries` | -| Variables | camelCase | `credentialBytes`, `didDoc` | - -### Type Definitions - -Define input/output types for each exported function: - -```go -type GenerateInput struct { - Credential string `json:"credential"` -} - -type GenerateOutput struct { - DID string `json:"did"` - Database []byte `json:"database"` -} -``` - -### Extism Plugin Functions - -Exported functions must: -1. Use `//go:wasmexport` directive -2. Return `int32` (0 = success, 1 = error) -3. Use `pdk.InputJSON()` for input parsing -4. Use `pdk.OutputJSON()` for output -5. Use `pdk.SetError()` for error reporting -6. Log with `pdk.Log()` +### Naming +- Types: `PascalCase` | JSON: `snake_case` +- Handlers: `handle` +- 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: failed to parse input: %w", err)) - return 1 - } - - // ... implementation ... - - if err := pdk.OutputJSON(output); err != nil { - pdk.SetError(fmt.Errorf("functionName: failed to output: %w", err)) + pdk.SetError(fmt.Errorf("functionName: %w", err)) return 1 } + // ... + pdk.OutputJSON(output) return 0 } ``` -### Error Handling - -1. Wrap errors with context using `fmt.Errorf("context: %w", err)` -2. Prefix error messages with function name -3. Return early on errors -4. Use `errors.New()` for static errors - +### ActionManager Pattern ```go -if err != nil { - pdk.SetError(fmt.Errorf("generate: failed to initialize: %w", err)) - return 1 +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) } ``` -### SQL Queries (SQLC) +## Anti-Patterns -- Schema in `db/schema.sql` -- Queries in `db/query.sql` -- Use SQLC annotations: `-- name: QueryName :one|:many|:exec` -- JSON columns use `json.RawMessage` type override +| 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 | -### Comments +## Commands -- Only add comments for complex logic, security implications, or TODOs -- Avoid obvious comments -- Use `// TODO:` for planned implementations - -## File Structure - -``` -motr-enclave/ -├── cmd/ -│ └── enclave/ -│ └── main.go # Plugin entry point (WASM-only, go-pdk imports) -├── internal/ -│ ├── keybase/ # Database access layer -│ ├── crypto/ # Cryptographic operations -│ ├── state/ # Plugin state management (WASM-only) -│ ├── types/ # Input/output type definitions -│ └── migrations/ # Database migrations -├── sqlc.yaml # SQLC configuration -├── Makefile # Build commands -└── go.mod # Go module +```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 ``` -Note: Files with `//go:build wasip1` constraint (cmd/enclave/, internal/state/) only compile for WASM target. +## Data Boundaries -## Dependencies +### Stored in Enclave +- WebAuthn credentials, MPC key shares, UCAN delegations +- Sessions, grants, DID document cache, multi-chain accounts -Install with `make deps`: -- `sqlc` - Database code generation -- `golangci-lint` - Linting -- `gofumpt` - Formatting -- Extism CLI - Plugin testing +### 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 diff --git a/TODO.md b/TODO.md index e9d11a0..94d293b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,622 +1,162 @@ # Implementation TODO -Remaining tasks from [MIGRATION.md](./MIGRATION.md) for the Nebula Key Enclave. - -## Status Summary - -| Category | Status | Notes | -|----------|--------|-------| -| Schema (10 tables) | Complete | `internal/migrations/schema.sql` - Updated for v1.0.0-rc.1 | -| SQLC Queries | Complete | `internal/migrations/query.sql` - CID-based queries added | -| Generated Code | Complete | `internal/keybase/*.go` | -| Basic Plugin Functions | Complete | `generate`, `load`, `exec`, `query`, `ping` | -| **Encryption** | **Complete** | `internal/enclave/` - WebAuthn PRF key derivation + AES-256-GCM | -| **UCAN v1.0.0-rc.1** | **Complete** | Core types, builders, policies, DB actions all complete | -| UCAN DB Actions | Complete | `actions_delegation.go`, `actions_invocation.go` | -| MPC Key Shares | Complete | `actions_keyshare.go` - Full key share management | -| **Database Serialization** | **Complete** | Native SQLite serialization via `ncruces/go-sqlite3/ext/serdes` | -| **BIP44 Multi-Chain** | **Complete** | SQLite functions: `bip44_derive()`, `bip44_derive_from_enclave()` | -| **MPC Signing** | **Complete** | `SignWithEnclave()` via exec handlers | +Remaining tasks for the Nebula Key Enclave. See [AGENTS.md](./AGENTS.md) for architecture overview and [CHANGELOG.md](./CHANGELOG.md) for completed work. --- -## Architecture: SQLite as DID CPU +## 1. UCAN v1.0.0-rc.1 Remaining Work -The enclave uses a **SQLite-centric architecture** where custom functions, JSON1 extension, and encryption at rest make the database the central computation engine for DID operations. +### 1.1 SQLite Functions for Policy & Validation -### Core Principles +- [ ] `ucan_policy_match(policy_json, args_json)` - Evaluate policy against args +- [ ] `ucan_cmd_subsumes(parent_cmd, child_cmd)` - Check command hierarchy +- [ ] `ucan_chain_valid(invocation_cid)` - Recursive CTE proof chain validation +- [ ] `ucan_parse_envelope(envelope_blob)` - Extract fields from DAG-CBOR as JSON -1. **Custom SQLite Functions** - Crypto operations live in the database layer - - `bip44_derive(pubkey, chain)` - BIP44 address derivation - - `bip44_derive_from_enclave(enclave_id, chain)` - Derive from stored enclave - - `enclave_sign(enclave_id, data)` - Sign with MPC key (planned) - - `ucan_*` functions for UCAN operations (planned) +### 1.2 SQLite Functions for UCAN Signing -2. **JSON1 Extension** - UCAN envelope manipulation in SQL - - Extract fields from DAG-JSON encoded envelopes - - Policy evaluation via JSON path queries - - Build query results as JSON directly - -3. **Encryption at Rest** - Application-level AES-256-GCM - - `Serialize()` → `EncryptBytes()` → storage - - WebAuthn PRF key derivation for encryption key - - Full database encrypted as single blob - -4. **Generated Columns & Views** - Computed DID state - - `is_expired`, `is_active` for delegation status - - `valid_delegations` view for chain validation - - Recursive CTEs for proof chain traversal - -### Implemented SQLite Functions - -| Function | Location | Purpose | -|----------|----------|---------| -| `bip44_derive(pubkey_hex, chain)` | `functions.go` | Derive address from public key | -| `bip44_derive_from_enclave(enclave_id, chain)` | `functions.go` | Derive address from stored enclave | - -### Planned SQLite Functions - -| Function | Purpose | -|----------|---------| -| `enclave_sign(enclave_id, data)` | Sign data with enclave's MPC key | -| `ucan_sign(enclave_id, payload)` | Sign UCAN payload, return varsig | -| `ucan_seal(enclave_id, delegation_json)` | Build complete sealed envelope | -| `ucan_parse_envelope(blob)` | Extract UCAN fields as JSON | -| `ucan_policy_match(policy, args)` | Evaluate policy against args | -| `ucan_cmd_subsumes(parent, child)` | Check command hierarchy | -| `ucan_chain_valid(invocation_cid)` | Validate full proof chain | - ---- - -## 1. UCAN v1.0.0-rc.1 Migration (CRITICAL PRIORITY) - -> **Status**: Core implementation complete using `github.com/ucan-wg/go-ucan v1.1.0`. Deprecated JWT-based files deleted. Remaining work is database integration and MPC signing. - -### Completed Implementation - -The following files implement UCAN v1.0.0-rc.1 using the official go-ucan library: - -| File | Status | Description | -|------|--------|-------------| -| `ucan.go` | ✅ Complete | Type re-exports, Sonr commands, pre-parsed constants | -| `policy.go` | ✅ Complete | PolicyBuilder fluent API, Sonr-specific policy helpers | -| `delegation.go` | ✅ Complete | DelegationBuilder fluent API, Sonr delegation helpers | -| `invocation.go` | ✅ Complete | InvocationBuilder fluent API, Sonr invocation helpers | -| `types.go` | ✅ Complete | ValidationError, Capability, ExecutionResult, Sonr types | - -### Dependencies Added - -- `github.com/ucan-wg/go-ucan v1.1.0` - Official UCAN library -- `github.com/ipld/go-ipld-prime v0.21.0` - IPLD encoding -- `github.com/MetaMask/go-did-it v1.0.0-pre1` - DID handling (indirect) -- `github.com/ipfs/go-cid v0.5.0` - Content addressing (indirect) - -### Deleted (Deprecated JWT-based) - -- ~~`jwt.go`~~ - Removed -- ~~`capability.go`~~ - Removed -- ~~`verifier.go`~~ - Removed -- ~~`source.go`~~ - Removed -- ~~`internal/crypto/mpc/spec/`~~ - Entire directory removed - -### 1.1 Core Data Structures - -- [x] Create `internal/crypto/ucan/types.go` - v1.0.0-rc.1 types - - [x] Re-export `Delegation` and `Invocation` from go-ucan - - [x] `Task` struct (sub, cmd, args, nonce) - - [x] `ReceiptPayload` struct (iss, ran, out, fx, meta, iat) - - [x] `RevocationPayload` struct - - [x] `ValidationError` with error codes matching TypeScript - - [x] `Capability` struct (sub, cmd, pol) - - [x] `ExecutionResult[T, E]` generic type - - [x] Sonr-specific types: `VaultCapability`, `DIDCapability`, `DWNCapability` - -- [x] Create `internal/crypto/ucan/policy.go` - Policy Language - - [x] `PolicyBuilder` fluent API with all operators - - [x] `Equal`, `NotEqual` - equality statements - - [x] `GreaterThan`, `LessThan`, etc. - inequality statements - - [x] `Like` - glob pattern matching - - [x] `Not`, `And`, `Or` - logical connectives - - [x] `All`, `Any` - quantifiers - - [x] Sonr helpers: `VaultPolicy`, `DIDPolicy`, `ChainPolicy`, `AccountPolicy` - -- [x] Create `internal/crypto/ucan/ucan.go` - Command types - - [x] `Command` type re-exported from go-ucan - - [x] Sonr commands: `/vault/*`, `/did/*`, `/dwn/*`, `/ucan/revoke` - - [x] Pre-parsed command constants: `VaultRead`, `VaultWrite`, `DIDUpdate`, etc. - - [x] `CommandSubsumes()` helper using go-ucan's `Covers()` method - -### 1.2 Envelope Format & Encoding - -- [x] Envelope handling via go-ucan library - - [x] `ToSealed()` method produces DAG-CBOR bytes + CID - - [x] `ToDagCbor()`, `ToDagJson()` encoding methods - - [x] CID computation handled by go-ucan - -- [x] Varsig support via go-ucan library - - [x] Ed25519, P-256, secp256k1 via `go-did-it/crypto` - -### 1.3 Delegation Operations - -- [x] Create `internal/crypto/ucan/delegation.go` - Delegation creation/validation - - [x] `DelegationBuilder` fluent API - - [x] `NewDelegation`, `NewRootDelegation`, `NewPowerlineDelegation` re-exports - - [x] `BuildSealed(privKey)` for signing - - [x] Sonr helpers: `NewVaultDelegation`, `NewDIDDelegation`, `NewDWNDelegation` - - [x] Temporal options: `ExpiresAt`, `ExpiresIn`, `NotBefore`, `NotBeforeIn` - -### 1.4 Invocation Operations - -- [x] Create `internal/crypto/ucan/invocation.go` - Invocation creation/validation - - [x] `InvocationBuilder` fluent API - - [x] `NewInvocation` re-export - - [x] `BuildSealed(privKey)` for signing - - [x] Proof chain management: `Proof()`, `Proofs()` - - [x] Sonr helpers: `VaultReadInvocation`, `VaultSignInvocation`, `DIDUpdateInvocation` - -### 1.5 Policy Evaluation Engine - -> **Architecture**: Use SQLite JSON1 extension for policy evaluation in queries. - -- [x] Policy evaluation via go-ucan's `invocation.ExecutionAllowed(loader)` -- [ ] Create `ucan_policy_match(policy_json, args_json)` SQLite function - - [ ] Evaluate policy statements against invocation args - - [ ] Support all UCAN policy operators (==, !=, <, >, like, glob) -- [ ] Create `ucan_cmd_subsumes(parent_cmd, child_cmd)` SQLite function - - [ ] Check command hierarchy (e.g., `/vault/*` covers `/vault/read`) -- [ ] Add computed columns/indexes for common policy queries - -### 1.6 Proof Chain Validation - -> **Architecture**: SQLite recursive CTEs for chain traversal, JSON extraction for envelope parsing. - -- [x] Chain validation via go-ucan library -- [x] Delegation storage in SQLite via `actions_delegation.go` - - [x] `GetDelegationByCID`, `GetDelegationEnvelope` methods - - [x] `ListDelegations*` methods for chain traversal -- [ ] Create `ucan_chain_valid(invocation_cid)` SQLite function - - [ ] Recursive CTE to walk proof chain via `prf` field - - [ ] Check each delegation's expiry, revocation, and policy - - [ ] Return validation result as JSON -- [ ] Create `ucan_parse_envelope(envelope_blob)` SQLite function - - [ ] Extract iss, aud, sub, cmd, pol, exp, nbf from DAG-CBOR - - [ ] Return as JSON for SQL queries -- [ ] Implement `delegation.Loader` interface backed by SQLite queries - -### 1.7 Revocation - -- [x] `RevocationInvocation()` helper in `invocation.go` -- [x] Revocation storage via `actions_delegation.go` - - [x] `RevokeDelegation(ctx, params)` - Create revocation record - - [x] `IsDelegationRevoked(ctx, cid) (bool, error)` - Query revocation status -- [ ] Create `internal/crypto/ucan/revocation.go` - Revocation checker for go-ucan - - [ ] Implement revocation checking interface - - [ ] Integration with chain validation via `ExecutionAllowed()` - -### 1.8 Database Integration - -- [x] Update `internal/migrations/schema.sql` for v1.0.0-rc.1 - - [x] `ucan_delegations` table (cid, envelope BLOB, iss, aud, sub, cmd, pol, nbf, exp, is_root, is_powerline) - - [x] `ucan_invocations` table (cid, envelope BLOB, iss, sub, aud, cmd, prf, exp, iat, executed_at, result_cid) - - [x] `ucan_revocations` table (delegation_cid, revoked_by, invocation_cid, reason) - - [x] Indexes on iss, aud, sub, cmd for efficient queries - -- [x] Update `internal/migrations/query.sql` for v1.0.0-rc.1 - - [x] `CreateDelegation`, `GetDelegationByCID`, `GetDelegationEnvelopeByCID` - - [x] `ListDelegationsByDID`, `ListDelegationsByIssuer`, `ListDelegationsByAudience`, `ListDelegationsBySubject` - - [x] `ListDelegationsForCommand`, `ListRootDelegations`, `ListPowerlineDelegations` - - [x] `CreateInvocation`, `GetInvocationByCID`, `GetInvocationEnvelopeByCID` - - [x] `ListInvocationsByDID`, `ListInvocationsByIssuer`, `ListInvocationsForCommand` - - [x] `MarkInvocationExecuted`, `ListPendingInvocations` - - [x] `CreateRevocation`, `IsDelegationRevoked`, `GetRevocation`, `ListRevocationsByRevoker` - -- [x] Create `internal/keybase/actions_delegation.go` - Delegation action handlers - - [x] `StoreDelegation`, `GetDelegationByCID`, `GetDelegationEnvelope` - - [x] `ListDelegations`, `ListDelegationsByIssuer`, `ListDelegationsByAudience` - - [x] `ListDelegationsForCommand`, `IsDelegationRevoked`, `RevokeDelegation` - - [x] `DeleteDelegation`, `CleanExpiredDelegations` - -- [x] Create `internal/keybase/actions_invocation.go` - Invocation action handlers - - [x] `StoreInvocation`, `GetInvocationByCID`, `GetInvocationEnvelope` - - [x] `ListInvocations`, `ListInvocationsByCommand`, `ListPendingInvocations` - - [x] `MarkInvocationExecuted`, `CleanOldInvocations` - -### 1.9 MPC Signing Integration - -> **Architecture**: Leverage SQLite custom functions for UCAN signing, keeping crypto operations in the database layer. - -- [ ] Create `ucan_sign(enclave_id, payload)` SQLite function - - [ ] Sign DAG-CBOR encoded delegation/invocation payloads - - [ ] Return varsig-encoded signature bytes -- [ ] Create `ucan_seal(enclave_id, delegation_json)` SQLite function - - [ ] Build sealed envelope from JSON input - - [ ] Compute CID and return complete envelope +- [ ] `ucan_sign(enclave_id, payload)` - Sign delegation/invocation payloads +- [ ] `ucan_seal(enclave_id, delegation_json)` - Build complete sealed envelope - [ ] Integrate with go-ucan's `crypto.Signer` interface via SQLite bridge -### 1.10 Testing +### 1.3 Revocation Checker + +- [ ] Implement revocation checking interface for go-ucan +- [ ] Integration with chain validation via `ExecutionAllowed()` + +### 1.4 Testing - [ ] Unit tests for builders (DelegationBuilder, InvocationBuilder) -- [ ] Unit tests for policy helpers -- [ ] Unit tests for Sonr-specific invocations - [ ] Interoperability tests against TypeScript implementation - [ ] Test vectors from UCAN spec --- -## 2. Encryption Strategy +## 2. Remaining Actions -> Reference: MIGRATION.md lines 770-814 -> **Status**: ✅ Complete - Implemented in `internal/enclave/` +### 2.1 Sync Checkpoint Actions -### 2.1 WebAuthn PRF Key Derivation +- [ ] `GetSyncCheckpoint(ctx, resourceType)` +- [ ] `UpsertSyncCheckpoint(ctx, params)` +- [ ] `ListSyncCheckpoints(ctx)` -- [x] Implement `DeriveEncryptionKey(prfOutput []byte) ([]byte, error)` -- [x] Use HKDF with SHA-256 to derive 256-bit encryption key -- [x] Salt with `"nebula-enclave-v1"` as info parameter -- [x] `DeriveKeyWithContext()` for purpose-specific key derivation +### 2.2 Invocation Validation -### 2.2 Database Encryption - -- [x] Implement application-level AES-256-GCM encryption for serialized pages -- [x] Add encryption wrapper around `Serialize()` output (`EncryptBytes()`) -- [x] Add decryption wrapper for `Load()` input (`DecryptBytes()`) -- [x] Store encryption metadata (version, nonce, auth tag) with serialized data -- [x] `SecureZero()` for memory clearing of sensitive data - -### 2.3 Encrypted Database Wrapper - -- [x] Create `internal/enclave/enclave.go` - Encrypted database wrapper - - [x] `Enclave` struct wrapping `Keybase` with encryption key - - [x] `SerializeEncrypted()` - Export encrypted database - - [x] `LoadEncrypted()` - Load from encrypted bytes - - [x] `Export()` / `Import()` - Full bundle operations with DID - - [x] `EncryptedBundle` struct with JSON marshaling -- [x] Create `internal/enclave/crypto.go` - WebAuthn PRF key derivation - - [x] `Encrypt()` / `Decrypt()` with `EncryptedData` struct - - [x] `EncryptBytes()` / `DecryptBytes()` convenience functions - - [x] `GenerateNonce()` for secure random nonce generation -- [x] Integrate with existing `internal/keybase` package via `FromExisting()` +- [ ] `ValidateInvocation(ctx, invocation)` - Requires delegation.Loader --- -## 3. Database Serialization +## 3. Plugin Extensions -> **Status**: ✅ Complete - Using native SQLite serialization via `ncruces/go-sqlite3/ext/serdes` +### 3.1 Exec Handlers -### 3.1 Native SQLite Serialization - -- [x] `Serialize()` using `serdes.Serialize(conn, "main")` - Binary database export -- [x] Full database state captured as byte slice -- [x] No SQL parsing needed - direct database format -- [x] Preserves all data types, indexes, and constraints - -### 3.2 Native SQLite Deserialization - -- [x] `Load()` using `serdes.Deserialize(conn, "main", data)` - Binary import -- [x] `RestoreFromDump()` for encrypted bundle loading -- [x] Automatic DID context restoration after load -- [x] Integrated with `internal/enclave` for encrypted storage - ---- - -## 4. Action Manager Extensions - -> Reference: `internal/keybase/actions.go` - -### 4.1 Key Share Actions - -- [x] `CreateKeyShare(ctx, params) (*KeyShareResult, error)` -- [x] `ListKeyShares(ctx) ([]KeyShareResult, error)` -- [x] `GetKeyShareByID(ctx, shareID) (*KeyShareResult, error)` -- [x] `GetKeyShareByKeyID(ctx, keyID) (*KeyShareResult, error)` -- [x] `RotateKeyShare(ctx, shareID) error` -- [x] `ArchiveKeyShare(ctx, shareID) error` -- [x] `DeleteKeyShare(ctx, shareID) error` - -### 4.2 UCAN Token Actions (v1.0.0-rc.1) - -- [x] `StoreDelegation(ctx, params) (*DelegationResult, error)` -- [x] `ListDelegations(ctx) ([]DelegationResult, error)` -- [x] `GetDelegationByCID(ctx, cid) (*DelegationResult, error)` -- [x] `GetDelegationEnvelope(ctx, cid) ([]byte, error)` -- [x] `ListDelegationsByIssuer(ctx, issuer) ([]DelegationResult, error)` -- [x] `ListDelegationsByAudience(ctx, audience) ([]DelegationResult, error)` -- [x] `ListDelegationsForCommand(ctx, cmd) ([]DelegationResult, error)` -- [x] `StoreInvocation(ctx, params) (*InvocationResult, error)` -- [x] `GetInvocationByCID(ctx, cid) (*InvocationResult, error)` -- [x] `GetInvocationEnvelope(ctx, cid) ([]byte, error)` -- [x] `ListInvocations(ctx, limit) ([]InvocationResult, error)` -- [x] `ListInvocationsByCommand(ctx, cmd, limit) ([]InvocationResult, error)` -- [x] `ListPendingInvocations(ctx) ([]InvocationResult, error)` -- [x] `MarkInvocationExecuted(ctx, cid, resultCID) error` -- [x] `RevokeDelegation(ctx, params) error` -- [x] `IsDelegationRevoked(ctx, cid) (bool, error)` -- [x] `DeleteDelegation(ctx, cid) error` -- [x] `CleanExpiredDelegations(ctx) error` -- [x] `CleanOldInvocations(ctx) error` -- [ ] `ValidateInvocation(ctx, invocation) (*ValidationResult, error)` - Requires delegation.Loader - -### 4.3 Verification Method Actions - -- [x] `CreateVerificationMethod(ctx, params) (*VerificationMethodResult, error)` -- [x] `ListVerificationMethodsFull(ctx) ([]VerificationMethodResult, error)` -- [x] `GetVerificationMethod(ctx, methodID) (*VerificationMethodResult, error)` -- [x] `DeleteVerificationMethod(ctx, methodID) error` - -### 4.4 Service Actions - -- [x] `CreateService(ctx, params) (*ServiceResult, error)` -- [x] `GetServiceByOrigin(ctx, origin) (*ServiceResult, error)` -- [x] `GetServiceByID(ctx, serviceID) (*ServiceResult, error)` -- [x] `UpdateService(ctx, params) error` -- [x] `ListVerifiedServices(ctx) ([]ServiceResult, error)` - -### 4.5 Grant Actions (Extend Existing) - -- [x] `CreateGrant(ctx, params) (*GrantResult, error)` -- [x] `GetGrantByService(ctx, serviceID) (*GrantResult, error)` -- [x] `UpdateGrantScopes(ctx, grantID, scopes, accounts) error` -- [x] `UpdateGrantLastUsed(ctx, grantID) error` -- [x] `SuspendGrant(ctx, grantID) error` -- [x] `ReactivateGrant(ctx, grantID) error` -- [x] `CountActiveGrants(ctx) (int64, error)` - -### 4.6 Account Actions (Extend Existing) - -- [x] `CreateAccount(ctx, params) (*AccountResult, error)` -- [x] `ListAccountsByChain(ctx, chainID) ([]AccountResult, error)` -- [x] `GetDefaultAccount(ctx, chainID) (*AccountResult, error)` -- [x] `SetDefaultAccount(ctx, accountID, chainID) error` -- [x] `UpdateAccountLabel(ctx, accountID, label) error` -- [x] `DeleteAccount(ctx, accountID) error` - -### 4.7 Credential Actions (Extend Existing) - -- [x] `CreateCredential(ctx, params) (*CredentialResult, error)` -- [x] `UpdateCredentialCounter(ctx, credentialID, signCount) error` -- [x] `RenameCredential(ctx, credentialID, name) error` -- [x] `DeleteCredential(ctx, credentialID) error` -- [x] `CountCredentialsByDID(ctx) (int64, error)` - -### 4.8 Session Actions (Extend Existing) - -- [x] `GetSessionByID(ctx, sessionID) (*SessionResult, error)` -- [x] `GetCurrentSession(ctx) (*SessionResult, error)` -- [x] `UpdateSessionActivity(ctx, sessionID) error` -- [x] `SetCurrentSession(ctx, sessionID) error` -- [x] `DeleteExpiredSessions(ctx) error` - -### 4.9 Sync Checkpoint Actions - -- [ ] `GetSyncCheckpoint(ctx, resourceType) (*SyncCheckpointResult, error)` -- [ ] `UpsertSyncCheckpoint(ctx, params) error` -- [ ] `ListSyncCheckpoints(ctx) ([]SyncCheckpointResult, error)` - ---- - -## 5. MPC Key Share Management - -> Reference: MIGRATION.md lines 823-824 - -### 5.1 Key Share Storage - -- [x] Parse key share data from MPC protocol - `KeyShareInput` in generate -- [x] Store public key and chain code - `CreateKeyShare` action -- [x] Track party index and threshold - stored in `key_shares` table -- [ ] Encrypt share data before storage - PRF key derivation needed - -### 5.2 Account Derivation - -- [x] Basic address derivation from public key - `deriveCosmosAddress()` -- [x] Create initial account during generate - `createInitialAccount()` -- [x] Implement BIP44 derivation path parsing - `bip44_derive()` SQLite function -- [x] Support multiple chains (Cosmos 118, Ethereum 60, Bitcoin 0) - `initializeWithMPC()` -- [x] Generate proper bech32 address encoding per chain - `bip44_derive_from_enclave()` SQLite function - -### 5.3 Key Rotation - -- [x] Implement key rotation workflow - `RotateKeyShare` action -- [x] Archive old shares - `ArchiveKeyShare` action -- [x] Status transitions - managed in database -- [ ] Handle rotation failures gracefully - ---- - -## 6. Plugin Function Extensions - -> Reference: `main.go` - -### 6.1 Extend `exec` Resource Handlers - -- [x] Add `key_shares` resource handler (list, get, rotate, archive, delete) -- [x] Add `ucans` resource handler (v1.0.0-rc.1 delegations - list, get, revoke, verify, cleanup) -- [x] Add `delegations` resource handler (v1.0.0-rc.1 - list, list_received, list_command, get, revoke, verify) -- [ ] Add `invocations` resource handler (v1.0.0-rc.1) -- [x] Add `verification_methods` resource handler (list, get, delete) -- [x] Add `services` resource handler (list, get, get_by_id) +- [ ] Add `invocations` resource handler - [ ] Add `sync_checkpoints` resource handler -### 6.2 Extend `generate` Function +### 3.2 Generate Function -- [x] Accept optional MPC keyshare data in input -- [x] Create initial keyshare if provided -- [x] Create initial account from keyshare - [ ] Parse WebAuthn credential properly (CBOR/COSE format) - [ ] Extract public key from credential - [ ] Create initial verification method - [ ] Create initial credential record -### 6.3 Signing Function +### 3.3 SQLite Functions -- [x] Support signing with MPC key shares - `SignWithEnclave()` in `actions_enclave.go` -- [x] Return signature in appropriate format - hex-encoded secp256k1 signature -- [x] Log signing operations for audit - logged via keybase actions -- [ ] Implement dedicated `sign` wasmexport function (currently via `exec` handlers) -- [ ] Add `enclave_sign()` SQLite function for in-query signing +- [ ] `enclave_sign(enclave_id, data)` - Sign in queries +- [ ] Dedicated `sign` wasmexport function --- -## 7. Capability Delegation (v1.0.0-rc.1) +## 4. Capability Delegation (v1.0.0-rc.1) -> **Architecture**: SQLite triggers and views for real-time delegation validation. +SQLite triggers and views for real-time delegation validation. -### 7.1 Delegation Chain Management +### 4.1 Schema Enhancements -- [ ] Create `delegation_depth` generated column using recursive CTE -- [ ] Add CHECK constraint for max depth (e.g., 10 levels) -- [ ] Create `valid_delegations` view joining chain validation -- [ ] Index on `(aud, cmd)` for efficient capability lookups +- [ ] `delegation_depth` generated column using recursive CTE +- [ ] CHECK constraint for max depth (e.g., 10 levels) +- [ ] `valid_delegations` view joining chain validation +- [ ] `is_expired` / `is_active` generated columns +- [ ] Partial index on `is_active = 1` -### 7.2 Policy Attenuation (SQLite Functions) +### 4.2 Policy Functions - [ ] `ucan_policy_subsumes(parent_pol, child_pol)` - Check attenuation - [ ] `ucan_cmd_covers(parent_cmd, child_cmd)` - Command hierarchy -- [ ] Add trigger `BEFORE INSERT ON ucan_delegations` to validate attenuation - -### 7.3 Delegation Status (SQLite Automation) - -- [ ] `is_expired` generated column: `exp IS NOT NULL AND exp < unixepoch()` -- [ ] `is_active` generated column: `NOT is_expired AND NOT is_revoked` -- [ ] Create `expired_delegations` view for cleanup queries -- [ ] Add partial index on `is_active = 1` for fast lookups +- [ ] Trigger `BEFORE INSERT ON ucan_delegations` to validate attenuation --- -## 8. DID State Sync - -> Reference: MIGRATION.md line 827 - -### 8.1 Sync Infrastructure +## 5. DID State Sync - [ ] Create `internal/enclave/sync.go` - DID state sync logic -- [ ] Implement checkpoint tracking -- [ ] Store last synced block height -- [ ] Track last processed transaction hash - -### 8.2 Sync Operations - +- [ ] Checkpoint tracking (block height, tx hash) - [ ] Fetch DID document updates from chain -- [ ] Validate on-chain document hash -- [ ] Update local state on changes - [ ] Handle reorgs and rollbacks --- -## 9. TypeScript SDK +## 6. TypeScript SDK -> Reference: README.md, `src/` directory +### 6.1 Core SDK (Partial - Basic wrappers exist) -### 9.1 Core SDK +- [ ] Full type definitions for all responses +- [ ] Error handling improvements +- [ ] Documentation and examples -- [ ] Implement `createEnclave(wasmPath)` factory -- [ ] Implement `generate(credential)` wrapper -- [ ] Implement `load(database)` wrapper -- [ ] Implement `exec(filter, token?)` wrapper -- [ ] Implement `query(did?)` wrapper +### 6.2 UCAN SDK -### 9.2 UCAN SDK (v1.0.0-rc.1) - -- [ ] Delegation builder using `src/ucan.ts` types -- [ ] Invocation builder +- [ ] Delegation/Invocation builders - [ ] Policy builder helpers -- [ ] Envelope encoding/decoding (DAG-CBOR) +- [ ] DAG-CBOR encoding/decoding - [ ] CID computation -### 9.3 WebAuthn Integration +### 6.3 WebAuthn Integration - [ ] Helper for credential creation -- [ ] Helper for PRF extension output -- [ ] Proper encoding/decoding utilities +- [ ] PRF extension output helper --- -## 10. Testing +## 7. Testing -### 10.1 Unit Tests - -- [ ] Test all ActionManager methods -- [ ] Test serialization/deserialization roundtrip -- [ ] Test encryption/decryption -- [ ] Test UCAN policy evaluation -- [ ] Test UCAN envelope encoding - -### 10.2 Integration Tests - -- [ ] Test full generate -> load -> exec flow -- [ ] Test credential lifecycle -- [ ] Test session management -- [ ] Test grant management -- [ ] Test UCAN delegation chain - -### 10.3 Plugin Tests - -- [ ] Extend `make test-plugin` with all functions -- [ ] Add error case testing -- [ ] Test with various input formats - -### 10.4 Interoperability Tests - -- [ ] Go <-> TypeScript UCAN envelope compatibility -- [ ] CID computation consistency -- [ ] Policy evaluation consistency +- [ ] Unit tests for ActionManager methods +- [ ] Serialization roundtrip tests +- [ ] UCAN policy evaluation tests +- [ ] Integration tests (generate -> load -> exec) +- [ ] Go <-> TypeScript interoperability --- -## 11. Security Hardening +## 8. Security Hardening -### 11.1 Input Validation - -- [ ] Validate all JSON inputs against schemas -- [ ] Sanitize SQL-sensitive characters in serialization -- [ ] Validate DID format on all inputs -- [ ] Validate base64 encoding - -### 11.2 Cryptographic Security - -- [ ] Use constant-time comparison for sensitive data -- [ ] Clear sensitive data from memory after use -- [ ] Validate key sizes and formats -- [ ] Implement proper nonce generation - -### 11.3 Access Control - -- [ ] Enforce DID ownership on all mutations -- [ ] Validate session before sensitive operations -- [ ] Check grant scopes before data access -- [ ] Log security-relevant operations +- [ ] JSON schema validation +- [ ] DID format validation +- [ ] Constant-time comparison for sensitive data +- [ ] Session validation before sensitive ops +- [ ] Grant scope checking --- ## Priority Order -1. **CRITICAL (Spec Compliance)** - ✅ Complete - - ~~UCAN v1.0.0-rc.1 Migration (Section 1)~~ ✅ All core items complete - - ~~Core data structures (1.1)~~ ✅ Using go-ucan v1.1.0 - - ~~Envelope format (1.2)~~ ✅ Handled by go-ucan - - ~~Delegation operations (1.3)~~ ✅ DelegationBuilder complete - - ~~Invocation operations (1.4)~~ ✅ InvocationBuilder complete - - ~~Database integration (1.8)~~ ✅ Schema, queries, and actions complete - - ~~MPC Key Derivation (5.2)~~ ✅ BIP44 SQLite functions complete - - ~~MPC Signing (6.3)~~ ✅ SignWithEnclave via exec handlers +1. **High Priority (SQLite Functions)** + - `ucan_sign()` / `ucan_seal()` for UCAN signing + - `ucan_parse_envelope()` for JSON extraction + - `ucan_chain_valid()` for proof validation + - `enclave_sign()` for general signing + - `invocations` exec handler -2. **High Priority (SQLite Functions)** - Next Phase - - `ucan_sign()` / `ucan_seal()` SQLite functions (1.9) - - `ucan_parse_envelope()` for JSON extraction (1.6) - - `ucan_chain_valid()` for proof validation (1.6) - - `enclave_sign()` for general signing (6.3) - - Invocations exec handler (6.1) +2. **Medium Priority (SQLite Automation)** + - Generated columns for delegation status + - Policy evaluation functions + - Delegation depth constraints -3. **Medium Priority (SQLite Automation)** - - Generated columns for delegation status (7.3) - - Policy evaluation functions (1.5, 7.2) - - Delegation depth constraints (7.1) - - Revocation cascade triggers (1.7) - -4. **Lower Priority (Enhancement)** - - TypeScript SDK (9.x) - - DID State Sync (8.x) - - Testing (10.x) - - Security Hardening (11.x) +3. **Lower Priority (Enhancement)** + - TypeScript SDK completion + - DID State Sync + - Testing + - Security Hardening ---