* clear

* feat: Add everything

* fix: Commenht
This commit is contained in:
Prad Nukala
2025-10-03 14:45:52 -04:00
committed by GitHub
parent 43b4a11c06
commit 13e6c3e84d
1935 changed files with 655061 additions and 40058 deletions
Regular → Executable
-1
View File
@@ -25,7 +25,6 @@ func RegisterLegacyAminoCodec(cdc *codec.LegacyAmino) {
}
func RegisterInterfaces(registry types.InterfaceRegistry) {
registry.RegisterImplementations(
(*sdk.Msg)(nil),
&MsgUpdateParams{},
+99
View File
@@ -0,0 +1,99 @@
package types
import (
"cosmossdk.io/errors"
)
// x/svc module error codes
const (
DefaultCodespace = ModuleName
ErrCodeDomainNotVerified = 1001
ErrCodeInvalidServiceID = 1002
ErrCodeServiceAlreadyExists = 1003
ErrCodeDomainAlreadyBound = 1004
ErrCodeFailedToSaveService = 1005
ErrCodeInvalidPermissions = 1006
ErrCodeUCANValidationFailed = 1007
ErrCodeInvalidUCANDelegation = 1008
ErrCodeFailedToCreateCapability = 1009
ErrCodeInvalidOwnerDID = 1010
ErrCodeServiceNotFound = 1011
ErrCodeServiceNotActive = 1012
ErrCodeOIDCConfigNotFound = 1013
ErrCodeInvalidIssuer = 1014
)
// x/svc module errors
var (
ErrDomainNotVerified = errors.Register(
DefaultCodespace,
ErrCodeDomainNotVerified,
"domain is not verified",
)
ErrInvalidServiceID = errors.Register(
DefaultCodespace,
ErrCodeInvalidServiceID,
"invalid service ID",
)
ErrServiceAlreadyExists = errors.Register(
DefaultCodespace,
ErrCodeServiceAlreadyExists,
"service already exists",
)
ErrDomainAlreadyBound = errors.Register(
DefaultCodespace,
ErrCodeDomainAlreadyBound,
"domain is already bound to another service",
)
ErrFailedToSaveService = errors.Register(
DefaultCodespace,
ErrCodeFailedToSaveService,
"failed to save service",
)
ErrInvalidPermissions = errors.Register(
DefaultCodespace,
ErrCodeInvalidPermissions,
"invalid permissions",
)
ErrUCANValidationFailed = errors.Register(
DefaultCodespace,
ErrCodeUCANValidationFailed,
"UCAN validation failed",
)
ErrInvalidUCANDelegation = errors.Register(
DefaultCodespace,
ErrCodeInvalidUCANDelegation,
"invalid UCAN delegation chain",
)
ErrFailedToCreateCapability = errors.Register(
DefaultCodespace,
ErrCodeFailedToCreateCapability,
"failed to create capability",
)
ErrInvalidOwnerDID = errors.Register(
DefaultCodespace,
ErrCodeInvalidOwnerDID,
"invalid owner DID document",
)
ErrServiceNotFound = errors.Register(
DefaultCodespace,
ErrCodeServiceNotFound,
"service not found",
)
ErrServiceNotActive = errors.Register(
DefaultCodespace,
ErrCodeServiceNotActive,
"service is not active",
)
ErrOIDCConfigNotFound = errors.Register(
DefaultCodespace,
ErrCodeOIDCConfigNotFound,
"OIDC configuration not found",
)
ErrInvalidIssuer = errors.Register(
DefaultCodespace,
ErrCodeInvalidIssuer,
"invalid OIDC issuer",
)
)
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
package types
import (
"context"
didtypes "github.com/sonr-io/sonr/x/did/types"
)
// DIDKeeper interface defines the methods needed from the DID keeper
type DIDKeeper interface {
// ResolveDID resolves a DID to its DID document and metadata
ResolveDID(
ctx context.Context,
did string,
) (*didtypes.DIDDocument, *didtypes.DIDDocumentMetadata, error)
// GetDIDDocument gets a DID document by its ID
GetDIDDocument(ctx context.Context, did string) (*didtypes.DIDDocument, error)
// VerifyDIDDocumentSignature verifies a DID document signature
VerifyDIDDocumentSignature(ctx context.Context, did string, signature []byte) (bool, error)
}
Regular → Executable
+31 -57
View File
@@ -1,78 +1,52 @@
package types
import "fmt"
// DefaultIndex is the default global index
const DefaultIndex uint64 = 1
// DefaultGenesis returns the default genesis state
func DefaultGenesis() *GenesisState {
return &GenesisState{
Params: DefaultParams(),
Params: DefaultParams(),
Capabilities: []ServiceCapability{},
}
}
// Validate performs basic genesis state validation returning an error upon any
// failure.
func (gs GenesisState) Validate() error {
return gs.Params.Validate()
}
// Validate parameters
if err := gs.Params.Validate(); err != nil {
return err
}
// Equal checks if two Attenuation are equal
func (a *Attenuation) Equal(that *Attenuation) bool {
if that == nil {
return false
}
if a.Resource != nil {
if that.Resource == nil {
return false
// Validate capabilities
capabilityIDs := make(map[string]bool)
for i, cap := range gs.Capabilities {
// Check for duplicate capability IDs
if capabilityIDs[cap.CapabilityId] {
return fmt.Errorf("duplicate capability ID at index %d: %s", i, cap.CapabilityId)
}
if !a.Resource.Equal(that.Resource) {
return false
}
}
if len(a.Capabilities) != len(that.Capabilities) {
return false
}
for i := range a.Capabilities {
if !a.Capabilities[i].Equal(that.Capabilities[i]) {
return false
}
}
return true
}
capabilityIDs[cap.CapabilityId] = true
// Equal checks if two Capability are equal
func (c *Capability) Equal(that *Capability) bool {
if that == nil {
return false
}
if c.Name != that.Name {
return false
}
if c.Parent != that.Parent {
return false
}
// TODO: check description
if len(c.Resources) != len(that.Resources) {
return false
}
for i := range c.Resources {
if c.Resources[i] != that.Resources[i] {
return false
// Validate individual capability fields
if cap.CapabilityId == "" {
return fmt.Errorf("capability at index %d has empty ID", i)
}
if cap.ServiceId == "" {
return fmt.Errorf("capability %s has empty service ID", cap.CapabilityId)
}
if cap.Domain == "" {
return fmt.Errorf("capability %s has empty domain", cap.CapabilityId)
}
if cap.Owner == "" {
return fmt.Errorf("capability %s has empty owner", cap.CapabilityId)
}
if len(cap.Abilities) == 0 {
return fmt.Errorf("capability %s has no abilities", cap.CapabilityId)
}
}
return true
}
// Equal checks if two Resource are equal
func (r *Resource) Equal(that *Resource) bool {
if that == nil {
return false
}
if r.Kind != that.Kind {
return false
}
if r.Template != that.Template {
return false
}
return true
return nil
}
+803 -1213
View File
File diff suppressed because it is too large Load Diff
Regular → Executable
+116 -3
View File
@@ -3,7 +3,7 @@ package types_test
import (
"testing"
"github.com/sonr-io/snrd/x/svc/types"
"github.com/sonr-io/sonr/x/svc/types"
"github.com/stretchr/testify/require"
)
@@ -20,9 +20,122 @@ func TestGenesisState_Validate(t *testing.T) {
valid: true,
},
{
desc: "valid genesis state",
desc: "valid genesis state",
genState: &types.GenesisState{
Params: types.DefaultParams(),
Capabilities: []types.ServiceCapability{},
},
valid: true,
},
{
desc: "valid genesis state with capabilities",
genState: &types.GenesisState{
Params: types.DefaultParams(),
Capabilities: []types.ServiceCapability{
{
CapabilityId: "cap_1",
ServiceId: "service_1",
Domain: "example.com",
Owner: "cosmos1abc",
Abilities: []string{"read", "write"},
CreatedAt: 1234567890,
ExpiresAt: 1234567900,
Revoked: false,
},
},
},
valid: true,
},
{
desc: "empty params is invalid",
genState: &types.GenesisState{},
valid: true,
valid: false,
},
{
desc: "duplicate capability IDs is invalid",
genState: &types.GenesisState{
Params: types.DefaultParams(),
Capabilities: []types.ServiceCapability{
{
CapabilityId: "cap_1",
ServiceId: "service_1",
Domain: "example.com",
Owner: "cosmos1abc",
Abilities: []string{"read"},
CreatedAt: 1234567890,
ExpiresAt: 1234567900,
Revoked: false,
},
{
CapabilityId: "cap_1", // duplicate
ServiceId: "service_2",
Domain: "example.org",
Owner: "cosmos1xyz",
Abilities: []string{"write"},
CreatedAt: 1234567891,
ExpiresAt: 1234567901,
Revoked: false,
},
},
},
valid: false,
},
{
desc: "capability with empty ID is invalid",
genState: &types.GenesisState{
Params: types.DefaultParams(),
Capabilities: []types.ServiceCapability{
{
CapabilityId: "", // empty
ServiceId: "service_1",
Domain: "example.com",
Owner: "cosmos1abc",
Abilities: []string{"read"},
CreatedAt: 1234567890,
ExpiresAt: 1234567900,
Revoked: false,
},
},
},
valid: false,
},
{
desc: "capability with empty service ID is invalid",
genState: &types.GenesisState{
Params: types.DefaultParams(),
Capabilities: []types.ServiceCapability{
{
CapabilityId: "cap_1",
ServiceId: "", // empty
Domain: "example.com",
Owner: "cosmos1abc",
Abilities: []string{"read"},
CreatedAt: 1234567890,
ExpiresAt: 1234567900,
Revoked: false,
},
},
},
valid: false,
},
{
desc: "capability with no abilities is invalid",
genState: &types.GenesisState{
Params: types.DefaultParams(),
Capabilities: []types.ServiceCapability{
{
CapabilityId: "cap_1",
ServiceId: "service_1",
Domain: "example.com",
Owner: "cosmos1abc",
Abilities: []string{}, // empty
CreatedAt: 1234567890,
ExpiresAt: 1234567900,
Revoked: false,
},
},
},
valid: false,
},
}
for _, tc := range tests {
Regular → Executable
+2 -4
View File
@@ -6,10 +6,8 @@ import (
ormv1alpha1 "cosmossdk.io/api/cosmos/orm/v1alpha1"
)
var (
// ParamsKey saves the current module params.
ParamsKey = collections.NewPrefix(0)
)
// ParamsKey saves the current module params.
var ParamsKey = collections.NewPrefix(0)
const (
ModuleName = "svc"
Regular → Executable
+4 -13
View File
@@ -7,20 +7,14 @@ import (
var _ sdk.Msg = &MsgUpdateParams{}
// ╭───────────────────────────────────────────────────────────╮
// │ MsgUpdateParams type definition │
// ╰───────────────────────────────────────────────────────────╯
// NewMsgUpdateParams creates new instance of MsgUpdateParams
func NewMsgUpdateParams(
sender sdk.Address,
someValue bool,
params Params,
) *MsgUpdateParams {
return &MsgUpdateParams{
Authority: sender.String(),
Params: Params{
// SomeValue: someValue,
},
Params: params,
}
}
@@ -41,14 +35,11 @@ func (msg *MsgUpdateParams) GetSigners() []sdk.AccAddress {
return []sdk.AccAddress{addr}
}
// Validate does a sanity check on the provided data.
// ValidateBasic does a sanity check on the provided data.
func (msg *MsgUpdateParams) Validate() error {
if _, err := sdk.AccAddressFromBech32(msg.Authority); err != nil {
return errors.Wrap(err, "invalid authority address")
}
return msg.Params.Validate()
}
// ╭───────────────────────────────────────────────────────────╮
// │ Registration Components │
// ╰───────────────────────────────────────────────────────────╯
Regular → Executable
+272 -4
View File
@@ -2,12 +2,51 @@ package types
import (
"encoding/json"
"fmt"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
)
// DefaultParams returns default module parameters.
func DefaultParams() Params {
// TODO:
return Params{}
return Params{
// Service Limits
MaxServicesPerAccount: 10,
MaxDomainsPerService: 5,
MaxEndpointsPerService: 20,
// Timeouts and Intervals (in seconds)
DomainVerificationTimeout: 86400, // 24 hours
ServiceHealthCheckInterval: 300, // 5 minutes
CapabilityDefaultExpiration: 2592000, // 30 days
// Economic Parameters
ServiceRegistrationFee: sdk.NewInt64Coin("usnr", 1000),
DomainVerificationFee: sdk.NewInt64Coin("usnr", 500),
MinServiceStake: sdk.NewInt64Coin("usnr", 10000),
// UCAN and Capability Settings
MaxDelegationChainDepth: 5,
UcanMaxLifetime: 31536000, // 1 year maximum
UcanMinLifetime: 60, // 1 minute minimum
SupportedSignatureAlgorithms: []string{
"ES256", // ECDSA with P-256
"RS256", // RSA with SHA-256
"EdDSA", // EdDSA signatures
},
// Validation Rules
RequireDomainOwnershipProof: true,
RequireHttps: false, // Allow HTTP for development
AllowLocalhost: true, // Development support
MaxServiceDescriptionLength: 1024,
// Rate Limiting
MaxRegistrationsPerBlock: 10,
MaxUpdatesPerBlock: 50,
MaxCapabilityGrantsPerBlock: 100,
}
}
// Stringer method for Params.
@@ -22,8 +61,237 @@ func (p Params) String() string {
// Validate does the sanity check on the params.
func (p Params) Validate() error {
// TODO:
// Validate service limits
if err := validateServiceLimits(p); err != nil {
return err
}
// Validate timeouts
if err := validateTimeouts(p); err != nil {
return err
}
// Validate economic parameters
if err := validateEconomicParams(p); err != nil {
return err
}
// Validate UCAN parameters
if err := validateUCANParams(p); err != nil {
return err
}
// Validate rate limiting
if err := validateRateLimits(p); err != nil {
return err
}
// Validate other parameters
if err := validateOtherParams(p); err != nil {
return err
}
return nil
}
// DefaultAttenuations returns the default Attenuation
// validateServiceLimits validates service-related limits
func validateServiceLimits(p Params) error {
if p.MaxServicesPerAccount == 0 || p.MaxServicesPerAccount > 100 {
return fmt.Errorf(
"max_services_per_account must be between 1 and 100, got %d",
p.MaxServicesPerAccount,
)
}
if p.MaxDomainsPerService == 0 || p.MaxDomainsPerService > 20 {
return fmt.Errorf(
"max_domains_per_service must be between 1 and 20, got %d",
p.MaxDomainsPerService,
)
}
if p.MaxEndpointsPerService == 0 || p.MaxEndpointsPerService > 100 {
return fmt.Errorf(
"max_endpoints_per_service must be between 1 and 100, got %d",
p.MaxEndpointsPerService,
)
}
return nil
}
// validateTimeouts validates timeout parameters
func validateTimeouts(p Params) error {
// Domain verification timeout: 1 hour to 7 days
if p.DomainVerificationTimeout < 3600 || p.DomainVerificationTimeout > 604800 {
return fmt.Errorf(
"domain_verification_timeout must be between 3600 and 604800 seconds, got %d",
p.DomainVerificationTimeout,
)
}
// Service health check interval: 1 minute to 1 hour
if p.ServiceHealthCheckInterval < 60 || p.ServiceHealthCheckInterval > 3600 {
return fmt.Errorf(
"service_health_check_interval must be between 60 and 3600 seconds, got %d",
p.ServiceHealthCheckInterval,
)
}
// Capability default expiration: 1 hour to 1 year
if p.CapabilityDefaultExpiration < 3600 || p.CapabilityDefaultExpiration > 31536000 {
return fmt.Errorf(
"capability_default_expiration must be between 3600 and 31536000 seconds, got %d",
p.CapabilityDefaultExpiration,
)
}
return nil
}
// validateEconomicParams validates economic-related parameters
func validateEconomicParams(p Params) error {
// Validate service registration fee
if p.ServiceRegistrationFee.IsNegative() {
return fmt.Errorf("service_registration_fee cannot be negative")
}
if p.ServiceRegistrationFee.Denom != "usnr" {
return fmt.Errorf(
"service_registration_fee must use usnr denomination, got %s",
p.ServiceRegistrationFee.Denom,
)
}
// Upper bound: 1M usnr
if p.ServiceRegistrationFee.Amount.GT(math.NewInt(1000000)) {
return fmt.Errorf("service_registration_fee exceeds maximum of 1000000 usnr")
}
// Validate domain verification fee
if p.DomainVerificationFee.IsNegative() {
return fmt.Errorf("domain_verification_fee cannot be negative")
}
if p.DomainVerificationFee.Denom != "usnr" {
return fmt.Errorf(
"domain_verification_fee must use usnr denomination, got %s",
p.DomainVerificationFee.Denom,
)
}
// Should be less than or equal to service registration fee
if p.DomainVerificationFee.Amount.GT(p.ServiceRegistrationFee.Amount) {
return fmt.Errorf("domain_verification_fee should not exceed service_registration_fee")
}
// Validate minimum service stake
if !p.MinServiceStake.IsPositive() {
return fmt.Errorf("min_service_stake must be positive")
}
if p.MinServiceStake.Denom != "usnr" {
return fmt.Errorf(
"min_service_stake must use usnr denomination, got %s",
p.MinServiceStake.Denom,
)
}
// Should be greater than registration fee
if p.MinServiceStake.Amount.LTE(p.ServiceRegistrationFee.Amount) {
return fmt.Errorf("min_service_stake should be greater than service_registration_fee")
}
return nil
}
// validateUCANParams validates UCAN-related parameters
func validateUCANParams(p Params) error {
// Max delegation chain depth: 1-10
if p.MaxDelegationChainDepth == 0 || p.MaxDelegationChainDepth > 10 {
return fmt.Errorf(
"max_delegation_chain_depth must be between 1 and 10, got %d",
p.MaxDelegationChainDepth,
)
}
// UCAN lifetime: min 1 minute, max 10 years
if p.UcanMaxLifetime < 60 || p.UcanMaxLifetime > 315360000 {
return fmt.Errorf(
"ucan_max_lifetime must be between 60 and 315360000 seconds, got %d",
p.UcanMaxLifetime,
)
}
if p.UcanMinLifetime < 1 || p.UcanMinLifetime >= p.UcanMaxLifetime {
return fmt.Errorf(
"ucan_min_lifetime must be positive and less than ucan_max_lifetime, got %d",
p.UcanMinLifetime,
)
}
// Validate signature algorithms
if len(p.SupportedSignatureAlgorithms) == 0 {
return fmt.Errorf("at least one signature algorithm must be supported")
}
validAlgorithms := map[string]bool{
"ES256": true, // ECDSA with P-256
"ES384": true, // ECDSA with P-384
"ES512": true, // ECDSA with P-521
"RS256": true, // RSA with SHA-256
"RS384": true, // RSA with SHA-384
"RS512": true, // RSA with SHA-512
"EdDSA": true, // EdDSA signatures
}
for _, algo := range p.SupportedSignatureAlgorithms {
if !validAlgorithms[algo] {
return fmt.Errorf("unsupported signature algorithm: %s", algo)
}
}
return nil
}
// validateRateLimits validates rate limiting parameters
func validateRateLimits(p Params) error {
// Max registrations per block: 1-100
if p.MaxRegistrationsPerBlock == 0 || p.MaxRegistrationsPerBlock > 100 {
return fmt.Errorf(
"max_registrations_per_block must be between 1 and 100, got %d",
p.MaxRegistrationsPerBlock,
)
}
// Max updates per block: 1-1000
if p.MaxUpdatesPerBlock == 0 || p.MaxUpdatesPerBlock > 1000 {
return fmt.Errorf(
"max_updates_per_block must be between 1 and 1000, got %d",
p.MaxUpdatesPerBlock,
)
}
// Max capability grants per block: 1-500
if p.MaxCapabilityGrantsPerBlock == 0 || p.MaxCapabilityGrantsPerBlock > 500 {
return fmt.Errorf(
"max_capability_grants_per_block must be between 1 and 500, got %d",
p.MaxCapabilityGrantsPerBlock,
)
}
return nil
}
// validateOtherParams validates miscellaneous parameters
func validateOtherParams(p Params) error {
// Max service description length: 10-10000 characters
if p.MaxServiceDescriptionLength < 10 || p.MaxServiceDescriptionLength > 10000 {
return fmt.Errorf(
"max_service_description_length must be between 10 and 10000, got %d",
p.MaxServiceDescriptionLength,
)
}
// Validation rules are boolean, no special validation needed
// but we can add logical checks
if !p.AllowLocalhost && !p.RequireHttps {
// This is a valid configuration for production
}
return nil
}
+427
View File
@@ -0,0 +1,427 @@
package types_test
import (
"testing"
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/sonr-io/sonr/x/svc/types"
)
func TestDefaultParams(t *testing.T) {
params := types.DefaultParams()
// Test default values - Service Limits
require.Equal(t, uint32(10), params.MaxServicesPerAccount)
require.Equal(t, uint32(5), params.MaxDomainsPerService)
require.Equal(t, uint32(20), params.MaxEndpointsPerService)
// Timeouts and Intervals
require.Equal(t, int64(86400), params.DomainVerificationTimeout)
require.Equal(t, int64(300), params.ServiceHealthCheckInterval)
require.Equal(t, int64(2592000), params.CapabilityDefaultExpiration)
// Economic Parameters
require.Equal(t, sdk.NewInt64Coin("usnr", 1000), params.ServiceRegistrationFee)
require.Equal(t, sdk.NewInt64Coin("usnr", 500), params.DomainVerificationFee)
require.Equal(t, sdk.NewInt64Coin("usnr", 10000), params.MinServiceStake)
// UCAN and Capability Settings
require.Equal(t, uint32(5), params.MaxDelegationChainDepth)
require.Equal(t, int64(31536000), params.UcanMaxLifetime)
require.Equal(t, int64(60), params.UcanMinLifetime)
require.Equal(t, []string{"ES256", "RS256", "EdDSA"}, params.SupportedSignatureAlgorithms)
// Validation Rules
require.True(t, params.RequireDomainOwnershipProof)
require.False(t, params.RequireHttps)
require.True(t, params.AllowLocalhost)
require.Equal(t, uint32(1024), params.MaxServiceDescriptionLength)
// Rate Limiting
require.Equal(t, uint32(10), params.MaxRegistrationsPerBlock)
require.Equal(t, uint32(50), params.MaxUpdatesPerBlock)
require.Equal(t, uint32(100), params.MaxCapabilityGrantsPerBlock)
}
func TestParams_Validate(t *testing.T) {
tests := []struct {
name string
modifyFunc func(*types.Params)
expectError bool
errorMsg string
}{
{
name: "default params are valid",
modifyFunc: func(p *types.Params) {},
expectError: false,
},
// Service Limits Tests
{
name: "zero max services per account",
modifyFunc: func(p *types.Params) {
p.MaxServicesPerAccount = 0
},
expectError: true,
errorMsg: "max_services_per_account must be between 1 and 100",
},
{
name: "excessive max services per account",
modifyFunc: func(p *types.Params) {
p.MaxServicesPerAccount = 101
},
expectError: true,
errorMsg: "max_services_per_account must be between 1 and 100",
},
{
name: "zero max domains per service",
modifyFunc: func(p *types.Params) {
p.MaxDomainsPerService = 0
},
expectError: true,
errorMsg: "max_domains_per_service must be between 1 and 20",
},
{
name: "excessive max domains per service",
modifyFunc: func(p *types.Params) {
p.MaxDomainsPerService = 21
},
expectError: true,
errorMsg: "max_domains_per_service must be between 1 and 20",
},
{
name: "zero max endpoints per service",
modifyFunc: func(p *types.Params) {
p.MaxEndpointsPerService = 0
},
expectError: true,
errorMsg: "max_endpoints_per_service must be between 1 and 100",
},
{
name: "excessive max endpoints per service",
modifyFunc: func(p *types.Params) {
p.MaxEndpointsPerService = 101
},
expectError: true,
errorMsg: "max_endpoints_per_service must be between 1 and 100",
},
// Timeout Tests
{
name: "domain verification timeout too low",
modifyFunc: func(p *types.Params) {
p.DomainVerificationTimeout = 3599
},
expectError: true,
errorMsg: "domain_verification_timeout must be between 3600 and 604800 seconds",
},
{
name: "domain verification timeout too high",
modifyFunc: func(p *types.Params) {
p.DomainVerificationTimeout = 604801
},
expectError: true,
errorMsg: "domain_verification_timeout must be between 3600 and 604800 seconds",
},
{
name: "service health check interval too low",
modifyFunc: func(p *types.Params) {
p.ServiceHealthCheckInterval = 59
},
expectError: true,
errorMsg: "service_health_check_interval must be between 60 and 3600 seconds",
},
{
name: "service health check interval too high",
modifyFunc: func(p *types.Params) {
p.ServiceHealthCheckInterval = 3601
},
expectError: true,
errorMsg: "service_health_check_interval must be between 60 and 3600 seconds",
},
{
name: "capability expiration too low",
modifyFunc: func(p *types.Params) {
p.CapabilityDefaultExpiration = 3599
},
expectError: true,
errorMsg: "capability_default_expiration must be between 3600 and 31536000 seconds",
},
{
name: "capability expiration too high",
modifyFunc: func(p *types.Params) {
p.CapabilityDefaultExpiration = 31536001
},
expectError: true,
errorMsg: "capability_default_expiration must be between 3600 and 31536000 seconds",
},
// Economic Parameters Tests
{
name: "negative service registration fee",
modifyFunc: func(p *types.Params) {
p.ServiceRegistrationFee = sdk.Coin{Denom: "usnr", Amount: math.NewInt(-1)}
},
expectError: true,
errorMsg: "service_registration_fee cannot be negative",
},
{
name: "wrong denom for service registration fee",
modifyFunc: func(p *types.Params) {
p.ServiceRegistrationFee = sdk.NewInt64Coin("snr", 1000)
},
expectError: true,
errorMsg: "service_registration_fee must use usnr denomination",
},
{
name: "excessive service registration fee",
modifyFunc: func(p *types.Params) {
p.ServiceRegistrationFee = sdk.NewInt64Coin("usnr", 1000001)
},
expectError: true,
errorMsg: "service_registration_fee exceeds maximum of 1000000 usnr",
},
{
name: "negative domain verification fee",
modifyFunc: func(p *types.Params) {
p.DomainVerificationFee = sdk.Coin{Denom: "usnr", Amount: math.NewInt(-1)}
},
expectError: true,
errorMsg: "domain_verification_fee cannot be negative",
},
{
name: "domain fee exceeds service fee",
modifyFunc: func(p *types.Params) {
p.ServiceRegistrationFee = sdk.NewInt64Coin("usnr", 100)
p.DomainVerificationFee = sdk.NewInt64Coin("usnr", 200)
},
expectError: true,
errorMsg: "domain_verification_fee should not exceed service_registration_fee",
},
{
name: "zero min service stake",
modifyFunc: func(p *types.Params) {
p.MinServiceStake = sdk.NewInt64Coin("usnr", 0)
},
expectError: true,
errorMsg: "min_service_stake must be positive",
},
{
name: "min stake less than registration fee",
modifyFunc: func(p *types.Params) {
p.ServiceRegistrationFee = sdk.NewInt64Coin("usnr", 1000)
p.MinServiceStake = sdk.NewInt64Coin("usnr", 999)
},
expectError: true,
errorMsg: "min_service_stake should be greater than service_registration_fee",
},
// UCAN Parameters Tests
{
name: "zero delegation chain depth",
modifyFunc: func(p *types.Params) {
p.MaxDelegationChainDepth = 0
},
expectError: true,
errorMsg: "max_delegation_chain_depth must be between 1 and 10",
},
{
name: "excessive delegation chain depth",
modifyFunc: func(p *types.Params) {
p.MaxDelegationChainDepth = 11
},
expectError: true,
errorMsg: "max_delegation_chain_depth must be between 1 and 10",
},
{
name: "UCAN max lifetime too low",
modifyFunc: func(p *types.Params) {
p.UcanMaxLifetime = 59
},
expectError: true,
errorMsg: "ucan_max_lifetime must be between 60 and 315360000 seconds",
},
{
name: "UCAN max lifetime too high",
modifyFunc: func(p *types.Params) {
p.UcanMaxLifetime = 315360001
},
expectError: true,
errorMsg: "ucan_max_lifetime must be between 60 and 315360000 seconds",
},
{
name: "UCAN min lifetime zero",
modifyFunc: func(p *types.Params) {
p.UcanMinLifetime = 0
},
expectError: true,
errorMsg: "ucan_min_lifetime must be positive and less than ucan_max_lifetime",
},
{
name: "UCAN min lifetime exceeds max",
modifyFunc: func(p *types.Params) {
p.UcanMaxLifetime = 100
p.UcanMinLifetime = 101
},
expectError: true,
errorMsg: "ucan_min_lifetime must be positive and less than ucan_max_lifetime",
},
{
name: "no signature algorithms",
modifyFunc: func(p *types.Params) {
p.SupportedSignatureAlgorithms = []string{}
},
expectError: true,
errorMsg: "at least one signature algorithm must be supported",
},
{
name: "invalid signature algorithm",
modifyFunc: func(p *types.Params) {
p.SupportedSignatureAlgorithms = []string{"INVALID"}
},
expectError: true,
errorMsg: "unsupported signature algorithm: INVALID",
},
// Rate Limiting Tests
{
name: "zero max registrations per block",
modifyFunc: func(p *types.Params) {
p.MaxRegistrationsPerBlock = 0
},
expectError: true,
errorMsg: "max_registrations_per_block must be between 1 and 100",
},
{
name: "excessive max registrations per block",
modifyFunc: func(p *types.Params) {
p.MaxRegistrationsPerBlock = 101
},
expectError: true,
errorMsg: "max_registrations_per_block must be between 1 and 100",
},
{
name: "zero max updates per block",
modifyFunc: func(p *types.Params) {
p.MaxUpdatesPerBlock = 0
},
expectError: true,
errorMsg: "max_updates_per_block must be between 1 and 1000",
},
{
name: "excessive max updates per block",
modifyFunc: func(p *types.Params) {
p.MaxUpdatesPerBlock = 1001
},
expectError: true,
errorMsg: "max_updates_per_block must be between 1 and 1000",
},
{
name: "zero max capability grants per block",
modifyFunc: func(p *types.Params) {
p.MaxCapabilityGrantsPerBlock = 0
},
expectError: true,
errorMsg: "max_capability_grants_per_block must be between 1 and 500",
},
{
name: "excessive max capability grants per block",
modifyFunc: func(p *types.Params) {
p.MaxCapabilityGrantsPerBlock = 501
},
expectError: true,
errorMsg: "max_capability_grants_per_block must be between 1 and 500",
},
// Other Parameters Tests
{
name: "service description length too low",
modifyFunc: func(p *types.Params) {
p.MaxServiceDescriptionLength = 9
},
expectError: true,
errorMsg: "max_service_description_length must be between 10 and 10000",
},
{
name: "service description length too high",
modifyFunc: func(p *types.Params) {
p.MaxServiceDescriptionLength = 10001
},
expectError: true,
errorMsg: "max_service_description_length must be between 10 and 10000",
},
// Valid edge cases
{
name: "all minimum valid values",
modifyFunc: func(p *types.Params) {
p.MaxServicesPerAccount = 1
p.MaxDomainsPerService = 1
p.MaxEndpointsPerService = 1
p.DomainVerificationTimeout = 3600
p.ServiceHealthCheckInterval = 60
p.CapabilityDefaultExpiration = 3600
p.ServiceRegistrationFee = sdk.NewInt64Coin("usnr", 0)
p.DomainVerificationFee = sdk.NewInt64Coin("usnr", 0)
p.MinServiceStake = sdk.NewInt64Coin("usnr", 1)
p.MaxDelegationChainDepth = 1
p.UcanMaxLifetime = 60
p.UcanMinLifetime = 1
p.MaxRegistrationsPerBlock = 1
p.MaxUpdatesPerBlock = 1
p.MaxCapabilityGrantsPerBlock = 1
p.MaxServiceDescriptionLength = 10
},
expectError: false,
},
{
name: "all maximum valid values",
modifyFunc: func(p *types.Params) {
p.MaxServicesPerAccount = 100
p.MaxDomainsPerService = 20
p.MaxEndpointsPerService = 100
p.DomainVerificationTimeout = 604800
p.ServiceHealthCheckInterval = 3600
p.CapabilityDefaultExpiration = 31536000
p.ServiceRegistrationFee = sdk.NewInt64Coin("usnr", 1000000)
p.DomainVerificationFee = sdk.NewInt64Coin("usnr", 1000000)
p.MinServiceStake = sdk.NewInt64Coin("usnr", 1000001)
p.MaxDelegationChainDepth = 10
p.UcanMaxLifetime = 315360000
p.UcanMinLifetime = 315359999
p.MaxRegistrationsPerBlock = 100
p.MaxUpdatesPerBlock = 1000
p.MaxCapabilityGrantsPerBlock = 500
p.MaxServiceDescriptionLength = 10000
},
expectError: false,
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
params := types.DefaultParams()
tc.modifyFunc(&params)
err := params.Validate()
if tc.expectError {
require.Error(t, err)
if tc.errorMsg != "" {
require.Contains(t, err.Error(), tc.errorMsg)
}
} else {
require.NoError(t, err)
}
})
}
}
// TestParamsString tests the String method of Params
func TestParamsString(t *testing.T) {
params := types.DefaultParams()
str := params.String()
// Test that string representation contains key fields
require.Contains(t, str, "max_services_per_account")
require.Contains(t, str, "max_domains_per_service")
require.Contains(t, str, "service_registration_fee")
require.Contains(t, str, "max_delegation_chain_depth")
require.Contains(t, str, "max_registrations_per_block")
}
+3792 -384
View File
File diff suppressed because it is too large Load Diff
+549 -44
View File
@@ -51,8 +51,8 @@ func local_request_Query_Params_0(ctx context.Context, marshaler runtime.Marshal
}
func request_Query_OriginExists_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryOriginExistsRequest
func request_Query_DomainVerification_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryDomainVerificationRequest
var metadata runtime.ServerMetadata
var (
@@ -62,24 +62,24 @@ func request_Query_OriginExists_0(ctx context.Context, marshaler runtime.Marshal
_ = err
)
val, ok = pathParams["origin"]
val, ok = pathParams["domain"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "origin")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "domain")
}
protoReq.Origin, err = runtime.String(val)
protoReq.Domain, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "origin", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "domain", err)
}
msg, err := client.OriginExists(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.DomainVerification(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_OriginExists_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryOriginExistsRequest
func local_request_Query_DomainVerification_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryDomainVerificationRequest
var metadata runtime.ServerMetadata
var (
@@ -89,24 +89,24 @@ func local_request_Query_OriginExists_0(ctx context.Context, marshaler runtime.M
_ = err
)
val, ok = pathParams["origin"]
val, ok = pathParams["domain"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "origin")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "domain")
}
protoReq.Origin, err = runtime.String(val)
protoReq.Domain, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "origin", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "domain", err)
}
msg, err := server.OriginExists(ctx, &protoReq)
msg, err := server.DomainVerification(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_ResolveOrigin_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryResolveOriginRequest
func request_Query_Service_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceRequest
var metadata runtime.ServerMetadata
var (
@@ -116,24 +116,24 @@ func request_Query_ResolveOrigin_0(ctx context.Context, marshaler runtime.Marsha
_ = err
)
val, ok = pathParams["origin"]
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "origin")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.Origin, err = runtime.String(val)
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "origin", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := client.ResolveOrigin(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.Service(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ResolveOrigin_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryResolveOriginRequest
func local_request_Query_Service_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceRequest
var metadata runtime.ServerMetadata
var (
@@ -143,18 +143,288 @@ func local_request_Query_ResolveOrigin_0(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["origin"]
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "origin")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.Origin, err = runtime.String(val)
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "origin", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := server.ResolveOrigin(ctx, &protoReq)
msg, err := server.Service(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_ServicesByOwner_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServicesByOwnerRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["owner"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner")
}
protoReq.Owner, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner", err)
}
msg, err := client.ServicesByOwner(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ServicesByOwner_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServicesByOwnerRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["owner"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "owner")
}
protoReq.Owner, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "owner", err)
}
msg, err := server.ServicesByOwner(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_ServicesByDomain_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServicesByDomainRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["domain"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "domain")
}
protoReq.Domain, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "domain", err)
}
msg, err := client.ServicesByDomain(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ServicesByDomain_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServicesByDomainRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["domain"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "domain")
}
protoReq.Domain, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "domain", err)
}
msg, err := server.ServicesByDomain(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_ServiceOIDCDiscovery_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceOIDCDiscoveryRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := client.ServiceOIDCDiscovery(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ServiceOIDCDiscovery_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceOIDCDiscoveryRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := server.ServiceOIDCDiscovery(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_ServiceOIDCJWKS_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceOIDCJWKSRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := client.ServiceOIDCJWKS(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ServiceOIDCJWKS_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceOIDCJWKSRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := server.ServiceOIDCJWKS(ctx, &protoReq)
return msg, metadata, err
}
func request_Query_ServiceOIDCMetadata_0(ctx context.Context, marshaler runtime.Marshaler, client QueryClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceOIDCMetadataRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := client.ServiceOIDCMetadata(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_Query_ServiceOIDCMetadata_0(ctx context.Context, marshaler runtime.Marshaler, server QueryServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq QueryServiceOIDCMetadataRequest
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["service_id"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "service_id")
}
protoReq.ServiceId, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "service_id", err)
}
msg, err := server.ServiceOIDCMetadata(ctx, &protoReq)
return msg, metadata, err
}
@@ -188,7 +458,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
})
mux.Handle("GET", pattern_Query_OriginExists_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_Query_DomainVerification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -199,7 +469,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_OriginExists_0(rctx, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_Query_DomainVerification_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
@@ -207,11 +477,11 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
return
}
forward_Query_OriginExists_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_Query_DomainVerification_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ResolveOrigin_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_Query_Service_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
@@ -222,7 +492,7 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ResolveOrigin_0(rctx, inboundMarshaler, server, req, pathParams)
resp, md, err := local_request_Query_Service_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
@@ -230,7 +500,122 @@ func RegisterQueryHandlerServer(ctx context.Context, mux *runtime.ServeMux, serv
return
}
forward_Query_ResolveOrigin_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_Query_Service_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServicesByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ServicesByOwner_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServicesByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServicesByDomain_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ServicesByDomain_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServicesByDomain_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServiceOIDCDiscovery_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ServiceOIDCDiscovery_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServiceOIDCDiscovery_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServiceOIDCJWKS_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ServiceOIDCJWKS_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServiceOIDCJWKS_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServiceOIDCMetadata_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_Query_ServiceOIDCMetadata_0(rctx, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServiceOIDCMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -295,7 +680,7 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
})
mux.Handle("GET", pattern_Query_OriginExists_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_Query_DomainVerification_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
@@ -304,18 +689,18 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_OriginExists_0(rctx, inboundMarshaler, client, req, pathParams)
resp, md, err := request_Query_DomainVerification_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_OriginExists_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_Query_DomainVerification_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ResolveOrigin_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("GET", pattern_Query_Service_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
@@ -324,14 +709,114 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ResolveOrigin_0(rctx, inboundMarshaler, client, req, pathParams)
resp, md, err := request_Query_Service_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ResolveOrigin_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_Query_Service_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServicesByOwner_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ServicesByOwner_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServicesByOwner_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServicesByDomain_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ServicesByDomain_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServicesByDomain_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServiceOIDCDiscovery_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ServiceOIDCDiscovery_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServiceOIDCDiscovery_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServiceOIDCJWKS_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ServiceOIDCJWKS_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServiceOIDCJWKS_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle("GET", pattern_Query_ServiceOIDCMetadata_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_Query_ServiceOIDCMetadata_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_Query_ServiceOIDCMetadata_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -341,15 +826,35 @@ func RegisterQueryHandlerClient(ctx context.Context, mux *runtime.ServeMux, clie
var (
pattern_Query_Params_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"svc", "v1", "params"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_OriginExists_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"svc", "v1", "origins", "origin"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_DomainVerification_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 2}, []string{"svc", "v1", "domain"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ResolveOrigin_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"svc", "v1", "origins", "origin", "record"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_Service_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"svc", "v1", "service", "service_id"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ServicesByOwner_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 3}, []string{"svc", "v1", "services", "owner"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ServicesByDomain_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 3}, []string{"svc", "v1", "services", "domain"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ServiceOIDCDiscovery_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"svc", "v1", "service", "service_id", "oidc", "discovery"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ServiceOIDCJWKS_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"svc", "v1", "service", "service_id", "oidc", "jwks"}, "", runtime.AssumeColonVerbOpt(false)))
pattern_Query_ServiceOIDCMetadata_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 2, 5}, []string{"svc", "v1", "service", "service_id", "oidc", "metadata"}, "", runtime.AssumeColonVerbOpt(false)))
)
var (
forward_Query_Params_0 = runtime.ForwardResponseMessage
forward_Query_OriginExists_0 = runtime.ForwardResponseMessage
forward_Query_DomainVerification_0 = runtime.ForwardResponseMessage
forward_Query_ResolveOrigin_0 = runtime.ForwardResponseMessage
forward_Query_Service_0 = runtime.ForwardResponseMessage
forward_Query_ServicesByOwner_0 = runtime.ForwardResponseMessage
forward_Query_ServicesByDomain_0 = runtime.ForwardResponseMessage
forward_Query_ServiceOIDCDiscovery_0 = runtime.ForwardResponseMessage
forward_Query_ServiceOIDCJWKS_0 = runtime.ForwardResponseMessage
forward_Query_ServiceOIDCMetadata_0 = runtime.ForwardResponseMessage
)
+3686 -499
View File
File diff suppressed because it is too large Load Diff
+1266 -119
View File
File diff suppressed because it is too large Load Diff
+382
View File
@@ -0,0 +1,382 @@
package types
import (
"fmt"
"strings"
"github.com/sonr-io/sonr/crypto/ucan"
)
// UCAN Action Constants for Service operations
const (
// Core Service Actions
UCANRegisterService = "register-service" // Register new service
UCANUpdateService = "update-service" // Update service details
UCANDeactivateService = "deactivate-service" // Deactivate service
UCANDeleteService = "delete-service" // Delete service
// Domain Verification Actions
UCANInitiateDomainVerification = "initiate-domain-verification" // Start domain verification
UCANVerifyDomain = "verify-domain" // Complete domain verification
UCANRevokeDomainVerification = "revoke-domain-verification" // Revoke domain verification
// Service Discovery Actions
UCANQueryService = "query-service" // Query service details
UCANListServices = "list-services" // List all services
UCANSearchServices = "search-services" // Search services
// Standard CRUD Actions (for compatibility)
UCANCreate = "create" // Create service
UCANRead = "read" // Read service
UCANUpdate = "update" // Update service
UCANDelete = "delete" // Delete service
UCANAdmin = "admin" // Administrative actions
UCANAll = "*" // Wildcard for all actions
)
// ServiceOperation represents the type of service operation being performed
type ServiceOperation string
const (
ServiceOpRegister ServiceOperation = "register"
ServiceOpUpdate ServiceOperation = "update"
ServiceOpDeactivate ServiceOperation = "deactivate"
ServiceOpDelete ServiceOperation = "delete"
ServiceOpInitiateDomainVerification ServiceOperation = "initiate_domain_verification"
ServiceOpVerifyDomain ServiceOperation = "verify_domain"
ServiceOpRevokeDomainVerification ServiceOperation = "revoke_domain_verification"
ServiceOpQuery ServiceOperation = "query"
ServiceOpList ServiceOperation = "list"
ServiceOpSearch ServiceOperation = "search"
)
// String returns the string representation of the service operation
func (op ServiceOperation) String() string {
return string(op)
}
// UCANCapabilityMapper provides conversion between Service operations and UCAN capabilities
type UCANCapabilityMapper struct{}
// NewUCANCapabilityMapper creates a new capability mapper
func NewUCANCapabilityMapper() *UCANCapabilityMapper {
return &UCANCapabilityMapper{}
}
// GetUCANCapabilitiesForOperation returns UCAN-specific capabilities for a Service operation
func (m *UCANCapabilityMapper) GetUCANCapabilitiesForOperation(operation ServiceOperation) []string {
switch operation {
case ServiceOpRegister:
return []string{UCANRegisterService, UCANCreate}
case ServiceOpUpdate:
return []string{UCANUpdateService, UCANUpdate}
case ServiceOpDeactivate:
return []string{UCANDeactivateService, UCANUpdate}
case ServiceOpDelete:
return []string{UCANDeleteService, UCANDelete, UCANAdmin}
case ServiceOpInitiateDomainVerification:
return []string{UCANInitiateDomainVerification, UCANUpdate}
case ServiceOpVerifyDomain:
return []string{UCANVerifyDomain, UCANUpdate}
case ServiceOpRevokeDomainVerification:
return []string{UCANRevokeDomainVerification, UCANUpdate, UCANAdmin}
case ServiceOpQuery:
return []string{UCANQueryService, UCANRead}
case ServiceOpList:
return []string{UCANListServices, UCANRead}
case ServiceOpSearch:
return []string{UCANSearchServices, UCANRead}
default:
return []string{UCANRead} // Default to read permission
}
}
// CreateServiceResourceURI builds a Service resource URI for UCAN validation
func (m *UCANCapabilityMapper) CreateServiceResourceURI(serviceID string) string {
return fmt.Sprintf("svc:%s", serviceID)
}
// CreateDomainResourceURI builds a domain resource URI for UCAN validation
func (m *UCANCapabilityMapper) CreateDomainResourceURI(domain string) string {
return fmt.Sprintf("domain:%s", domain)
}
// CreateServiceAttenuation creates a UCAN attenuation for Service operations
func (m *UCANCapabilityMapper) CreateServiceAttenuation(
actions []string,
serviceID string,
caveats []string,
) ucan.Attenuation {
resourceURI := m.CreateServiceResourceURI(serviceID)
resource := &ucan.SimpleResource{
Scheme: "svc",
Value: serviceID,
URI: resourceURI,
}
// Use MultiCapability for multiple actions
var capability ucan.Capability
if len(actions) == 1 {
capability = &ucan.SimpleCapability{
Action: actions[0],
}
} else {
capability = &ucan.MultiCapability{
Actions: actions,
}
}
return ucan.Attenuation{
Capability: capability,
Resource: resource,
}
}
// CreateDomainBoundAttenuation creates a UCAN attenuation for domain-bound operations
func (m *UCANCapabilityMapper) CreateDomainBoundAttenuation(
actions []string,
domain string,
serviceID string,
) ucan.Attenuation {
// Create a domain-specific resource
resourceURI := m.CreateDomainResourceURI(domain)
resource := &ucan.SimpleResource{
Scheme: "domain",
Value: domain,
URI: resourceURI,
}
// Use MultiCapability for domain-bound operations
// Note: domain binding is enforced through resource matching
var capability ucan.Capability
if len(actions) == 1 {
capability = &ucan.SimpleCapability{
Action: actions[0],
}
} else {
capability = &ucan.MultiCapability{
Actions: actions,
}
}
return ucan.Attenuation{
Capability: capability,
Resource: resource,
}
}
// CreateRateLimitedAttenuation creates a UCAN attenuation with rate limiting
func (m *UCANCapabilityMapper) CreateRateLimitedAttenuation(
actions []string,
serviceID string,
rateLimit uint64,
windowSeconds uint64,
) ucan.Attenuation {
// Rate limiting will be handled at validation layer
// For now, create a standard service attenuation
return m.CreateServiceAttenuation(actions, serviceID, nil)
}
// ValidateUCANCapabilities validates that a UCAN capability grants the required Service actions
func (m *UCANCapabilityMapper) ValidateUCANCapabilities(
capability ucan.Capability,
requiredActions []string,
) bool {
return capability.Grants(requiredActions)
}
// ValidateDomainBoundCapability validates domain-bound UCAN capabilities
func (m *UCANCapabilityMapper) ValidateDomainBoundCapability(
capability ucan.Capability,
domain string,
) error {
// Domain validation will be handled through resource matching
// Check if capability has appropriate actions for domain operations
actions := capability.GetActions()
for _, action := range actions {
if action == UCANInitiateDomainVerification ||
action == UCANVerifyDomain ||
action == UCANRevokeDomainVerification {
return nil
}
}
return fmt.Errorf("capability does not include domain verification actions")
}
// IsUCANAction checks if an action string is a valid UCAN action
func IsUCANAction(action string) bool {
validActions := []string{
UCANRegisterService, UCANUpdateService, UCANDeactivateService, UCANDeleteService,
UCANInitiateDomainVerification, UCANVerifyDomain, UCANRevokeDomainVerification,
UCANQueryService, UCANListServices, UCANSearchServices,
UCANCreate, UCANRead, UCANUpdate, UCANDelete, UCANAdmin, UCANAll,
}
for _, validAction := range validActions {
if action == validAction {
return true
}
}
return false
}
// GetServiceCapabilityTemplate returns a preconfigured capability template for Service
func GetServiceCapabilityTemplate() *ucan.CapabilityTemplate {
return ucan.StandardServiceTemplate()
}
// UCANPermissionRegistry extends the basic permission registry with UCAN capabilities
type UCANPermissionRegistry struct {
operationCapabilities map[ServiceOperation][]string
mapper *UCANCapabilityMapper
}
// NewUCANPermissionRegistry creates a new UCAN-aware permission registry
func NewUCANPermissionRegistry() *UCANPermissionRegistry {
registry := &UCANPermissionRegistry{
operationCapabilities: make(map[ServiceOperation][]string),
mapper: NewUCANCapabilityMapper(),
}
// Initialize default capabilities
registry.initializeDefaultCapabilities()
return registry
}
// initializeDefaultCapabilities sets up default capability mappings
func (r *UCANPermissionRegistry) initializeDefaultCapabilities() {
operations := []ServiceOperation{
ServiceOpRegister, ServiceOpUpdate, ServiceOpDeactivate, ServiceOpDelete,
ServiceOpInitiateDomainVerification, ServiceOpVerifyDomain, ServiceOpRevokeDomainVerification,
ServiceOpQuery, ServiceOpList, ServiceOpSearch,
}
for _, op := range operations {
r.operationCapabilities[op] = r.mapper.GetUCANCapabilitiesForOperation(op)
}
}
// GetRequiredUCANCapabilities returns UCAN-specific capabilities for a Service operation
func (r *UCANPermissionRegistry) GetRequiredUCANCapabilities(operation ServiceOperation) ([]string, error) {
capabilities, exists := r.operationCapabilities[operation]
if !exists {
capabilities = r.mapper.GetUCANCapabilitiesForOperation(operation)
}
if len(capabilities) == 0 {
return nil, fmt.Errorf("no UCAN capabilities defined for operation: %s", operation.String())
}
return capabilities, nil
}
// CreateServiceAttenuation creates a UCAN attenuation for Service operations
func (r *UCANPermissionRegistry) CreateServiceAttenuation(
actions []string,
serviceID string,
caveats []string,
) ucan.Attenuation {
return r.mapper.CreateServiceAttenuation(actions, serviceID, caveats)
}
// CreateDomainBoundAttenuation creates a domain-bound attenuation
func (r *UCANPermissionRegistry) CreateDomainBoundAttenuation(
actions []string,
domain string,
serviceID string,
) ucan.Attenuation {
return r.mapper.CreateDomainBoundAttenuation(actions, domain, serviceID)
}
// CreateRateLimitedAttenuation creates a rate-limited attenuation
func (r *UCANPermissionRegistry) CreateRateLimitedAttenuation(
actions []string,
serviceID string,
rateLimit uint64,
windowSeconds uint64,
) ucan.Attenuation {
return r.mapper.CreateRateLimitedAttenuation(actions, serviceID, rateLimit, windowSeconds)
}
// Helper functions
// CreateServiceResourcePattern creates a Service resource pattern for matching
func CreateServiceResourcePattern(serviceType, serviceID string) string {
if serviceID == "*" {
return fmt.Sprintf("%s:*", serviceType)
}
return fmt.Sprintf("%s:%s", serviceType, serviceID)
}
// MatchesServicePattern checks if a service ID matches a given pattern
func MatchesServicePattern(serviceID, pattern string) bool {
if pattern == "*" {
return true
}
// Handle wildcard patterns like "api:*"
if strings.HasSuffix(pattern, ":*") {
prefix := strings.TrimSuffix(pattern, ":*")
return strings.HasPrefix(serviceID, prefix+":")
}
return serviceID == pattern
}
// CreateGaslessServiceAttenuation creates a UCAN attenuation that supports gasless transactions
func CreateGaslessServiceAttenuation(
actions []string,
serviceID string,
gasLimit uint64,
) ucan.Attenuation {
mapper := NewUCANCapabilityMapper()
baseAttenuation := mapper.CreateServiceAttenuation(actions, serviceID, nil)
// Wrap capability with gasless support
gaslessCapability := &ucan.GaslessCapability{
Capability: baseAttenuation.Capability,
AllowGasless: true,
GasLimit: gasLimit,
}
return ucan.Attenuation{
Capability: gaslessCapability,
Resource: baseAttenuation.Resource,
}
}
// Domain verification helpers
// CreateDomainVerificationURI creates a resource URI for domain verification operations
func CreateDomainVerificationURI(domain string, verificationMethod string) string {
return fmt.Sprintf("domain:%s/verify/%s", domain, verificationMethod)
}
// ValidateDomainVerificationCapability validates domain verification capability
func ValidateDomainVerificationCapability(
capability ucan.Capability,
domain string,
verificationMethod string,
) error {
// Check for domain verification actions
actions := capability.GetActions()
hasVerificationAction := false
for _, action := range actions {
if action == UCANInitiateDomainVerification || action == UCANVerifyDomain {
hasVerificationAction = true
break
}
}
if !hasVerificationAction {
return fmt.Errorf("capability does not include domain verification actions")
}
// Domain validation will be handled through resource matching
return nil
}