4.4 KiB
4.4 KiB
Agent Guidelines for Motr Enclave
This document provides guidelines for AI coding agents working in this repository.
Project 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.
Build Commands
# 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
Test Commands
# Run all tests
make test
# Run tests with coverage
make test-cover
# Run a single test
go test -v -run TestFunctionName ./...
# Run tests in a specific package
go test -v ./db/...
# Test the compiled plugin with Extism CLI
make test-plugin
Lint and Format
# Run all linters
make lint
# 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:
- Standard library
- External dependencies
- Internal packages
import (
"encoding/json"
"errors"
"fmt"
"github.com/extism/go-pdk"
"enclave/db"
)
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:
type GenerateInput struct {
Credential string `json:"credential"`
}
type GenerateOutput struct {
DID string `json:"did"`
Database []byte `json:"database"`
}
Extism Plugin Functions
Exported functions must:
- Use
//go:wasmexportdirective - Return
int32(0 = success, 1 = error) - Use
pdk.InputJSON()for input parsing - Use
pdk.OutputJSON()for output - Use
pdk.SetError()for error reporting - Log with
pdk.Log()
//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))
return 1
}
return 0
}
Error Handling
- Wrap errors with context using
fmt.Errorf("context: %w", err) - Prefix error messages with function name
- Return early on errors
- Use
errors.New()for static errors
if err != nil {
pdk.SetError(fmt.Errorf("generate: failed to initialize: %w", err))
return 1
}
SQL Queries (SQLC)
- Schema in
db/schema.sql - Queries in
db/query.sql - Use SQLC annotations:
-- name: QueryName :one|:many|:exec - JSON columns use
json.RawMessagetype override
Comments
- 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
Note: Files with //go:build wasip1 constraint (cmd/enclave/, internal/state/) only compile for WASM target.
Dependencies
Install with make deps:
sqlc- Database code generationgolangci-lint- Lintinggofumpt- Formatting- Extism CLI - Plugin testing