Files
waste-go/internal/invite/invite.go
Fredrik Johansson abc6bf46ce Add invite strings (waste: URI) for peer onboarding
- internal/invite: Encode/Decode waste:<base64json{anchor,network}>
- proto: CmdGenerateInvite + EvtInviteGenerated + InviteString field
- ipc: track active network name; handle generate_invite (returns invite
  string when joined to a network, errors if not joined or no anchor)
- daemon: --join <invite> flag — decodes anchor URL + network name,
  sets anchor and auto-joins on startup
- tui: --join <invite> flag — extracts network name, skips -network
  requirement; ctrl+i generates invite and shows it full-screen;
  Esc dismisses the invite overlay
- FUTURE.md: document multi-network derived-identity design

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-21 18:56:24 +02:00

55 lines
1.6 KiB
Go

// Package invite encodes and decodes waste invite strings.
// An invite carries the anchor URL and network name needed to join a network.
// Format: "waste:<url-safe-base64(json)>"
package invite
import (
"encoding/base64"
"encoding/json"
"fmt"
"strings"
)
const prefix = "waste:"
// Invite holds the information needed to join a network.
type Invite struct {
Anchor string `json:"anchor"` // WebSocket anchor URL
Network string `json:"network"` // plaintext network name
}
// Encode returns a waste: invite string for the given anchor URL and network name.
func Encode(anchor, network string) (string, error) {
if anchor == "" {
return "", fmt.Errorf("anchor URL is required")
}
if network == "" {
return "", fmt.Errorf("network name is required")
}
b, err := json.Marshal(Invite{Anchor: anchor, Network: network})
if err != nil {
return "", err
}
return prefix + base64.URLEncoding.EncodeToString(b), nil
}
// Decode parses a waste: invite string and returns the Invite.
func Decode(s string) (Invite, error) {
s = strings.TrimSpace(s)
if !strings.HasPrefix(s, prefix) {
return Invite{}, fmt.Errorf("not a waste invite (expected 'waste:' prefix)")
}
b, err := base64.URLEncoding.DecodeString(strings.TrimPrefix(s, prefix))
if err != nil {
return Invite{}, fmt.Errorf("invalid invite: %w", err)
}
var inv Invite
if err := json.Unmarshal(b, &inv); err != nil {
return Invite{}, fmt.Errorf("invalid invite payload: %w", err)
}
if inv.Anchor == "" || inv.Network == "" {
return Invite{}, fmt.Errorf("invite is missing anchor or network name")
}
return inv, nil
}