refactor(main): extract types into separate package
This commit is contained in:
186
main.go
186
main.go
@@ -9,127 +9,25 @@ import (
|
||||
"strings"
|
||||
|
||||
"enclave/internal/keybase"
|
||||
"enclave/internal/types"
|
||||
|
||||
"github.com/extism/go-pdk"
|
||||
)
|
||||
|
||||
// GenerateInput represents the input for the generate function
|
||||
type GenerateInput struct {
|
||||
Credential string `json:"credential"` // Base64-encoded PublicKeyCredential
|
||||
}
|
||||
|
||||
// GenerateOutput represents the output of the generate function
|
||||
type GenerateOutput struct {
|
||||
DID string `json:"did"`
|
||||
Database []byte `json:"database"`
|
||||
}
|
||||
|
||||
// LoadInput represents the input for the load function
|
||||
type LoadInput struct {
|
||||
Database []byte `json:"database"`
|
||||
}
|
||||
|
||||
// LoadOutput represents the output of the load function
|
||||
type LoadOutput struct {
|
||||
Success bool `json:"success"`
|
||||
DID string `json:"did,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// ExecInput represents the input for the exec function
|
||||
type ExecInput struct {
|
||||
Filter string `json:"filter"` // GitHub-style filter: "resource:accounts action:sign"
|
||||
Token string `json:"token"` // UCAN token for authorization
|
||||
}
|
||||
|
||||
// ExecOutput represents the output of the exec function
|
||||
type ExecOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Result json.RawMessage `json:"result,omitempty"`
|
||||
Error string `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
// QueryInput represents the input for the query function
|
||||
type QueryInput struct {
|
||||
DID string `json:"did"`
|
||||
}
|
||||
|
||||
// QueryOutput represents the output of the query function
|
||||
type QueryOutput struct {
|
||||
DID string `json:"did"`
|
||||
Controller string `json:"controller"`
|
||||
VerificationMethods []VerificationMethod `json:"verification_methods"`
|
||||
Accounts []Account `json:"accounts"`
|
||||
Credentials []Credential `json:"credentials"`
|
||||
}
|
||||
|
||||
// VerificationMethod represents a DID verification method
|
||||
type VerificationMethod struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Controller string `json:"controller"`
|
||||
PublicKey string `json:"public_key"`
|
||||
Purpose string `json:"purpose"`
|
||||
}
|
||||
|
||||
// Account represents a derived blockchain account
|
||||
type Account struct {
|
||||
Address string `json:"address"`
|
||||
ChainID string `json:"chain_id"`
|
||||
CoinType int `json:"coin_type"`
|
||||
AccountIndex int `json:"account_index"`
|
||||
AddressIndex int `json:"address_index"`
|
||||
Label string `json:"label"`
|
||||
IsDefault bool `json:"is_default"`
|
||||
}
|
||||
|
||||
// Credential represents a WebAuthn credential
|
||||
type Credential struct {
|
||||
CredentialID string `json:"credential_id"`
|
||||
DeviceName string `json:"device_name"`
|
||||
DeviceType string `json:"device_type"`
|
||||
Authenticator string `json:"authenticator"`
|
||||
Transports []string `json:"transports"`
|
||||
CreatedAt string `json:"created_at"`
|
||||
LastUsed string `json:"last_used"`
|
||||
}
|
||||
|
||||
// FilterParams parsed from GitHub-style filter syntax
|
||||
type FilterParams struct {
|
||||
Resource string
|
||||
Action string
|
||||
Subject string
|
||||
}
|
||||
|
||||
// Enclave holds the plugin state
|
||||
type Enclave struct {
|
||||
var enclave = &struct {
|
||||
initialized bool
|
||||
did string
|
||||
}
|
||||
|
||||
var enclave = &Enclave{}
|
||||
}{}
|
||||
|
||||
func main() {}
|
||||
|
||||
// PingInput represents the input for the ping function
|
||||
type PingInput struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
// PingOutput represents the output of the ping function
|
||||
type PingOutput struct {
|
||||
Success bool `json:"success"`
|
||||
Message string `json:"message"`
|
||||
Echo string `json:"echo"`
|
||||
}
|
||||
|
||||
//go:wasmexport ping
|
||||
func ping() int32 {
|
||||
pdk.Log(pdk.LogInfo, "ping: received request")
|
||||
|
||||
var input PingInput
|
||||
var input types.PingInput
|
||||
if err := pdk.InputJSON(&input); err != nil {
|
||||
output := PingOutput{
|
||||
output := types.PingOutput{
|
||||
Success: false,
|
||||
Message: fmt.Sprintf("failed to parse input: %s", err),
|
||||
}
|
||||
@@ -137,7 +35,7 @@ func ping() int32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
output := PingOutput{
|
||||
output := types.PingOutput{
|
||||
Success: true,
|
||||
Message: "pong",
|
||||
Echo: input.Message,
|
||||
@@ -156,7 +54,7 @@ func ping() int32 {
|
||||
func generate() int32 {
|
||||
pdk.Log(pdk.LogInfo, "generate: starting database initialization")
|
||||
|
||||
var input GenerateInput
|
||||
var input types.GenerateInput
|
||||
if err := pdk.InputJSON(&input); err != nil {
|
||||
pdk.SetError(fmt.Errorf("generate: failed to parse input: %w", err))
|
||||
return 1
|
||||
@@ -188,7 +86,7 @@ func generate() int32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
output := GenerateOutput{
|
||||
output := types.GenerateOutput{
|
||||
DID: did,
|
||||
Database: dbBytes,
|
||||
}
|
||||
@@ -206,7 +104,7 @@ func generate() int32 {
|
||||
func load() int32 {
|
||||
pdk.Log(pdk.LogInfo, "load: loading database from buffer")
|
||||
|
||||
var input LoadInput
|
||||
var input types.LoadInput
|
||||
if err := pdk.InputJSON(&input); err != nil {
|
||||
pdk.SetError(fmt.Errorf("load: failed to parse input: %w", err))
|
||||
return 1
|
||||
@@ -219,7 +117,7 @@ func load() int32 {
|
||||
|
||||
did, err := loadDatabase(input.Database)
|
||||
if err != nil {
|
||||
output := LoadOutput{
|
||||
output := types.LoadOutput{
|
||||
Success: false,
|
||||
Error: err.Error(),
|
||||
}
|
||||
@@ -230,7 +128,7 @@ func load() int32 {
|
||||
enclave.initialized = true
|
||||
enclave.did = did
|
||||
|
||||
output := LoadOutput{
|
||||
output := types.LoadOutput{
|
||||
Success: true,
|
||||
DID: did,
|
||||
}
|
||||
@@ -249,34 +147,34 @@ func exec() int32 {
|
||||
pdk.Log(pdk.LogInfo, "exec: executing action")
|
||||
|
||||
if !enclave.initialized {
|
||||
output := ExecOutput{Success: false, Error: "database not initialized, call generate or load first"}
|
||||
output := types.ExecOutput{Success: false, Error: "database not initialized, call generate or load first"}
|
||||
pdk.OutputJSON(output)
|
||||
return 0
|
||||
}
|
||||
|
||||
var input ExecInput
|
||||
var input types.ExecInput
|
||||
if err := pdk.InputJSON(&input); err != nil {
|
||||
output := ExecOutput{Success: false, Error: fmt.Sprintf("failed to parse input: %s", err)}
|
||||
output := types.ExecOutput{Success: false, Error: fmt.Sprintf("failed to parse input: %s", err)}
|
||||
pdk.OutputJSON(output)
|
||||
return 0
|
||||
}
|
||||
|
||||
if input.Filter == "" {
|
||||
output := ExecOutput{Success: false, Error: "filter is required"}
|
||||
output := types.ExecOutput{Success: false, Error: "filter is required"}
|
||||
pdk.OutputJSON(output)
|
||||
return 0
|
||||
}
|
||||
|
||||
params, err := parseFilter(input.Filter)
|
||||
if err != nil {
|
||||
output := ExecOutput{Success: false, Error: fmt.Sprintf("invalid filter: %s", err)}
|
||||
output := types.ExecOutput{Success: false, Error: fmt.Sprintf("invalid filter: %s", err)}
|
||||
pdk.OutputJSON(output)
|
||||
return 0
|
||||
}
|
||||
|
||||
if input.Token != "" {
|
||||
if err := validateUCAN(input.Token, params); err != nil {
|
||||
output := ExecOutput{
|
||||
output := types.ExecOutput{
|
||||
Success: false,
|
||||
Error: fmt.Sprintf("authorization failed: %s", err.Error()),
|
||||
}
|
||||
@@ -287,7 +185,7 @@ func exec() int32 {
|
||||
|
||||
result, err := executeAction(params)
|
||||
if err != nil {
|
||||
output := ExecOutput{
|
||||
output := types.ExecOutput{
|
||||
Success: false,
|
||||
Error: err.Error(),
|
||||
}
|
||||
@@ -295,7 +193,7 @@ func exec() int32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
output := ExecOutput{
|
||||
output := types.ExecOutput{
|
||||
Success: true,
|
||||
Result: result,
|
||||
}
|
||||
@@ -314,7 +212,7 @@ func query() int32 {
|
||||
return 1
|
||||
}
|
||||
|
||||
var input QueryInput
|
||||
var input types.QueryInput
|
||||
if err := pdk.InputJSON(&input); err != nil {
|
||||
pdk.SetError(fmt.Errorf("query: failed to parse input: %w", err))
|
||||
return 1
|
||||
@@ -388,8 +286,8 @@ func loadDatabase(data []byte) (string, error) {
|
||||
return did, nil
|
||||
}
|
||||
|
||||
func parseFilter(filter string) (*FilterParams, error) {
|
||||
params := &FilterParams{}
|
||||
func parseFilter(filter string) (*types.FilterParams, error) {
|
||||
params := &types.FilterParams{}
|
||||
parts := strings.FieldsSeq(filter)
|
||||
|
||||
for part := range parts {
|
||||
@@ -419,12 +317,7 @@ func parseFilter(filter string) (*FilterParams, error) {
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func validateUCAN(token string, params *FilterParams) error {
|
||||
// TODO: Decode UCAN token
|
||||
// TODO: Verify signature chain
|
||||
// TODO: Check capabilities match params
|
||||
// TODO: Verify not expired or revoked
|
||||
|
||||
func validateUCAN(token string, params *types.FilterParams) error {
|
||||
if token == "" {
|
||||
return errors.New("token is required")
|
||||
}
|
||||
@@ -433,11 +326,7 @@ func validateUCAN(token string, params *FilterParams) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func executeAction(params *FilterParams) (json.RawMessage, error) {
|
||||
// TODO: Route to appropriate handler based on resource/action
|
||||
// TODO: Execute database queries
|
||||
// TODO: Return results
|
||||
|
||||
func executeAction(params *types.FilterParams) (json.RawMessage, error) {
|
||||
switch params.Resource {
|
||||
case "accounts":
|
||||
return executeAccountAction(params)
|
||||
@@ -452,10 +341,10 @@ func executeAction(params *FilterParams) (json.RawMessage, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func executeAccountAction(params *FilterParams) (json.RawMessage, error) {
|
||||
func executeAccountAction(params *types.FilterParams) (json.RawMessage, error) {
|
||||
switch params.Action {
|
||||
case "list":
|
||||
accounts := []Account{
|
||||
accounts := []types.Account{
|
||||
{
|
||||
Address: "sonr1abc123...",
|
||||
ChainID: "sonr-mainnet-1",
|
||||
@@ -474,10 +363,10 @@ func executeAccountAction(params *FilterParams) (json.RawMessage, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func executeCredentialAction(params *FilterParams) (json.RawMessage, error) {
|
||||
func executeCredentialAction(params *types.FilterParams) (json.RawMessage, error) {
|
||||
switch params.Action {
|
||||
case "list":
|
||||
credentials := []Credential{
|
||||
credentials := []types.Credential{
|
||||
{
|
||||
CredentialID: "cred_abc123",
|
||||
DeviceName: "MacBook Pro",
|
||||
@@ -494,7 +383,7 @@ func executeCredentialAction(params *FilterParams) (json.RawMessage, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func executeSessionAction(params *FilterParams) (json.RawMessage, error) {
|
||||
func executeSessionAction(params *types.FilterParams) (json.RawMessage, error) {
|
||||
switch params.Action {
|
||||
case "list":
|
||||
return json.Marshal([]map[string]any{})
|
||||
@@ -507,7 +396,7 @@ func executeSessionAction(params *FilterParams) (json.RawMessage, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func executeGrantAction(params *FilterParams) (json.RawMessage, error) {
|
||||
func executeGrantAction(params *types.FilterParams) (json.RawMessage, error) {
|
||||
switch params.Action {
|
||||
case "list":
|
||||
return json.Marshal([]map[string]any{})
|
||||
@@ -520,16 +409,11 @@ func executeGrantAction(params *FilterParams) (json.RawMessage, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func resolveDID(did string) (*QueryOutput, error) {
|
||||
// TODO: Query database for DID document
|
||||
// TODO: Fetch verification methods
|
||||
// TODO: Fetch associated accounts
|
||||
// TODO: Fetch credentials
|
||||
|
||||
output := &QueryOutput{
|
||||
func resolveDID(did string) (*types.QueryOutput, error) {
|
||||
output := &types.QueryOutput{
|
||||
DID: did,
|
||||
Controller: did,
|
||||
VerificationMethods: []VerificationMethod{
|
||||
VerificationMethods: []types.VerificationMethod{
|
||||
{
|
||||
ID: did + "#key-1",
|
||||
Type: "Ed25519VerificationKey2020",
|
||||
@@ -538,7 +422,7 @@ func resolveDID(did string) (*QueryOutput, error) {
|
||||
Purpose: "authentication",
|
||||
},
|
||||
},
|
||||
Accounts: []Account{
|
||||
Accounts: []types.Account{
|
||||
{
|
||||
Address: "sonr1abc123...",
|
||||
ChainID: "sonr-mainnet-1",
|
||||
@@ -549,7 +433,7 @@ func resolveDID(did string) (*QueryOutput, error) {
|
||||
IsDefault: true,
|
||||
},
|
||||
},
|
||||
Credentials: []Credential{
|
||||
Credentials: []types.Credential{
|
||||
{
|
||||
CredentialID: "cred_abc123",
|
||||
DeviceName: "MacBook Pro",
|
||||
|
||||
Reference in New Issue
Block a user