Add register-by-signature, web fixes, bin scripts, docs
CI / test (push) Successful in 5s

- Register by signing service key: GET /v1/service-key, POST /v1/auth/register-by-signature
- Login auto-attempts register first for new users
- Web: default API URL momswap.produktor.duckdns.org, /libs/ static handler
- Docker: webbuild stage for geo-api-client, copy web+libs to runtime
- Bin scripts: test.sh, run.sh, up.sh, down.sh
- docs/ed25519-security-use-cases.md: use cases, message formats, examples
- SERVICE_PUBLIC_KEY env (defaults to ADMIN_PUBLIC_KEY)

Made-with: Cursor
This commit is contained in:
2026-03-01 12:58:44 +00:00
parent 978e0403eb
commit a5a97a0ad9
19 changed files with 405 additions and 41 deletions
+29 -4
View File
@@ -29,12 +29,13 @@ type Config struct {
}
type Service struct {
store *store.MemoryStore
config Config
store *store.MemoryStore
config Config
servicePublicKey string
}
func NewService(memoryStore *store.MemoryStore, cfg Config) *Service {
return &Service{store: memoryStore, config: cfg}
func NewService(memoryStore *store.MemoryStore, cfg Config, servicePublicKey string) *Service {
return &Service{store: memoryStore, config: cfg, servicePublicKey: servicePublicKey}
}
type InvitationPayload struct {
@@ -55,6 +56,30 @@ func (s *Service) BootstrapAdmin(publicKey string) {
})
}
func (s *Service) ServicePublicKey() string {
return s.servicePublicKey
}
func (s *Service) RegisterBySignature(publicKey, signature string) error {
if s.servicePublicKey == "" {
return fmt.Errorf("%w: registration by signature not configured", ErrBadRequest)
}
if publicKey == "" {
return fmt.Errorf("%w: missing public key", ErrBadRequest)
}
if _, err := s.store.GetUser(publicKey); err == nil {
return ErrAlreadyUser
}
if err := auth.VerifySignature(publicKey, s.servicePublicKey, signature); err != nil {
return fmt.Errorf("%w: signature verification failed", ErrBadRequest)
}
s.store.UpsertUser(store.User{
PublicKey: publicKey,
CreatedAt: time.Now().UTC(),
})
return nil
}
func (s *Service) CreateChallenge(publicKey string) (string, error) {
if publicKey == "" {
return "", fmt.Errorf("%w: missing public key", ErrBadRequest)