Files
motr-enclave/internal/crypto/ucan/ucan.go

196 lines
6.4 KiB
Go

// Package ucan provides UCAN v1.0.0-rc.1 compliant authorization
// for the Sonr network using the official go-ucan library.
//
// This package wraps github.com/ucan-wg/go-ucan to provide:
// - Delegation creation and validation
// - Invocation creation and validation
// - Policy evaluation
// - Sonr-specific capability types (vault, did, dwn)
//
// UCAN Envelope Format (DAG-CBOR):
//
// [
// Signature, // Varsig-encoded signature
// {
// "h": VarsigHeader, // Algorithm metadata
// "ucan/dlg@1.0.0-rc.1": DelegationPayload // or "ucan/inv@1.0.0-rc.1"
// }
// ]
package ucan
import (
"github.com/ucan-wg/go-ucan/pkg/command"
"github.com/ucan-wg/go-ucan/pkg/policy"
"github.com/ucan-wg/go-ucan/token/delegation"
"github.com/ucan-wg/go-ucan/token/invocation"
)
// Re-export key types from go-ucan for convenience.
// Users should import this package instead of go-ucan directly
// for Sonr-specific functionality.
type (
// Delegation is an immutable UCAN delegation token.
Delegation = delegation.Token
// Invocation is an immutable UCAN invocation token.
Invocation = invocation.Token
// Command is a validated UCAN command string (e.g., "/vault/read").
Command = command.Command
// Policy is a list of policy statements that constrain invocation arguments.
Policy = policy.Policy
// Statement is a single policy statement (equality, like, and, or, etc.).
Statement = policy.Statement
// DelegationOption configures optional fields when creating a delegation.
DelegationOption = delegation.Option
// InvocationOption configures optional fields when creating an invocation.
InvocationOption = invocation.Option
)
// Re-export constructors
var (
// NewDelegation creates a delegation: "(issuer) allows (audience) to perform (cmd+pol) on (subject)".
NewDelegation = delegation.New
// NewRootDelegation creates a root delegation where subject == issuer.
NewRootDelegation = delegation.Root
// NewPowerlineDelegation creates a powerline delegation (subject = nil).
// Powerline automatically delegates all future delegations regardless of subject.
NewPowerlineDelegation = delegation.Powerline
// NewInvocation creates an invocation: "(issuer) executes (command) on (subject)".
NewInvocation = invocation.New
// ParseCommand validates and parses a command string.
ParseCommand = command.Parse
// MustParseCommand parses a command string, panicking on error.
MustParseCommand = command.MustParse
// TopCommand returns "/" - the most powerful capability (grants everything).
TopCommand = command.Top
// NewCommand creates a command from segments (e.g., NewCommand("vault", "read") -> "/vault/read").
NewCommand = command.New
)
// Re-export delegation options
var (
// WithExpiration sets the delegation's expiration time.
WithExpiration = delegation.WithExpiration
// WithExpirationIn sets expiration to now + duration.
WithExpirationIn = delegation.WithExpirationIn
// WithNotBefore sets when the delegation becomes valid.
WithNotBefore = delegation.WithNotBefore
// WithNotBeforeIn sets not-before to now + duration.
WithNotBeforeIn = delegation.WithNotBeforeIn
// WithDelegationMeta adds metadata to the delegation.
WithDelegationMeta = delegation.WithMeta
// WithDelegationNonce sets a custom nonce (default: random 12 bytes).
WithDelegationNonce = delegation.WithNonce
)
// Re-export invocation options
var (
// WithArgument adds a single argument to the invocation.
WithArgument = invocation.WithArgument
// WithAudience sets the invocation's audience (executor if different from subject).
WithAudience = invocation.WithAudience
// WithInvocationMeta adds metadata to the invocation.
WithInvocationMeta = invocation.WithMeta
// WithInvocationNonce sets a custom nonce.
WithInvocationNonce = invocation.WithNonce
// WithEmptyNonce sets an empty nonce for idempotent operations.
WithEmptyNonce = invocation.WithEmptyNonce
// WithInvocationExpiration sets the invocation's expiration time.
WithInvocationExpiration = invocation.WithExpiration
// WithInvocationExpirationIn sets expiration to now + duration.
WithInvocationExpirationIn = invocation.WithExpirationIn
// WithIssuedAt sets when the invocation was created.
WithIssuedAt = invocation.WithIssuedAt
// WithCause sets the receipt CID that enqueued this task.
WithCause = invocation.WithCause
)
// Standard Sonr commands following UCAN v1.0.0-rc.1 command format.
// Commands must be lowercase, start with '/', and have no trailing slash.
const (
// Vault commands
CmdVaultRead = "/vault/read"
CmdVaultWrite = "/vault/write"
CmdVaultSign = "/vault/sign"
CmdVaultExport = "/vault/export"
CmdVaultImport = "/vault/import"
CmdVaultDelete = "/vault/delete"
CmdVaultAdmin = "/vault/admin"
CmdVault = "/vault" // Superuser - grants all vault commands
// DID commands
CmdDIDCreate = "/did/create"
CmdDIDUpdate = "/did/update"
CmdDIDDeactivate = "/did/deactivate"
CmdDID = "/did" // Superuser - grants all DID commands
// DWN commands
CmdDWNRecordsWrite = "/dwn/records/write"
CmdDWNRecordsRead = "/dwn/records/read"
CmdDWNRecordsDelete = "/dwn/records/delete"
CmdDWN = "/dwn" // Superuser - grants all DWN commands
// UCAN meta commands
CmdUCANRevoke = "/ucan/revoke"
// Root command - grants everything
CmdRoot = "/"
)
// Pre-parsed Sonr commands for convenience
var (
VaultRead = command.MustParse(CmdVaultRead)
VaultWrite = command.MustParse(CmdVaultWrite)
VaultSign = command.MustParse(CmdVaultSign)
VaultExport = command.MustParse(CmdVaultExport)
VaultImport = command.MustParse(CmdVaultImport)
VaultDelete = command.MustParse(CmdVaultDelete)
VaultAdmin = command.MustParse(CmdVaultAdmin)
Vault = command.MustParse(CmdVault)
DIDCreate = command.MustParse(CmdDIDCreate)
DIDUpdate = command.MustParse(CmdDIDUpdate)
DIDDeactivate = command.MustParse(CmdDIDDeactivate)
DID = command.MustParse(CmdDID)
DWNRecordsWrite = command.MustParse(CmdDWNRecordsWrite)
DWNRecordsRead = command.MustParse(CmdDWNRecordsRead)
DWNRecordsDelete = command.MustParse(CmdDWNRecordsDelete)
DWN = command.MustParse(CmdDWN)
UCANRevoke = command.MustParse(CmdUCANRevoke)
Root = command.Top()
)
// CommandSubsumes checks if parent command subsumes child command.
// A command subsumes another if the child is a path extension of parent.
// Example: "/vault" subsumes "/vault/read" and "/vault/write"
func CommandSubsumes(parent, child Command) bool {
return parent.Covers(child)
}