Files
brianmcgee 3040e8c758 pkg: implement signed namespaces
It's a variation of the ADR described here: #310.

Namespaces allow peers to publish files under paths like ``<namespace>/<pubkey>`
if they hold a certificate signed by the network key. This enables dynamic,
per-peer file publishing without requiring each file to be pre-configured.

Also cleans up some testing patterns.
2026-03-30 15:42:43 +01:00

75 lines
1.5 KiB
Go

package config
import (
"fmt"
"git.clan.lol/clan/data-mesher/pkg/crypto"
"git.clan.lol/clan/data-mesher/pkg/model"
)
const (
DefaultNetworkName = "home"
)
type Network struct {
ID *crypto.PublicKey `mapstructure:"id"`
Files Files `mapstructure:"files"`
Namespaces []string `mapstructure:"namespaces"`
Name string `mapstructure:"-"`
}
func (n Network) Validate() error {
if n.ID == nil {
return fmt.Errorf("%w: network ID is required", ErrInvalidConfig)
}
if err := n.Files.Validate(); err != nil {
return err
}
if err := validateNamespaces(n.Namespaces); err != nil {
return err
}
return nil
}
func validateNamespaces(namespaces []string) error {
seen := make(map[string]bool, len(namespaces))
for _, ns := range namespaces {
if err := model.ValidateNamespaceName(ns); err != nil {
return fmt.Errorf("%w: %w", ErrInvalidConfig, err)
}
if seen[ns] {
return fmt.Errorf("%w: duplicate namespace: %s", ErrInvalidConfig, ns)
}
seen[ns] = true
}
return nil
}
type ExtraNetworks map[string]Network
func (n ExtraNetworks) Validate() error {
for name, network := range n {
if err := network.Validate(); err != nil {
return fmt.Errorf("extra network %s is invalid: %w", name, err)
}
if name == DefaultNetworkName {
return fmt.Errorf("%w: network name '%s' is reserved", ErrInvalidConfig, name)
}
// set the name based on the key and write back to the map
network.Name = name
n[name] = network
}
return nil
}