Add signed invites, hang links, multi-share, and EXTENSIONS.md

- Signed invites: waste: URI gains inviter+sig fields (Ed25519); hello
  carries the invite so receiving peers can verify against known keys
- RequireInvite per-network flag: rejects peers without valid signed invite
- Hash-based hang links: #waste:base64 fragment pre-fills join form without
  server-side leakage of network name
- Multi-share: shares.json (daemon) + waste_shares localStorage (browser);
  IPC add_share/remove_share/list_shares commands
- EXTENSIONS.md: addendum documenting all waste-go protocol deviations from
  YAW/2; all extensions are additive and backward compatible

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Fredrik Johansson
2026-06-26 22:05:56 +02:00
parent 0e8ddbf4f4
commit 31e13fd509
12 changed files with 382 additions and 37 deletions

View File

@@ -139,12 +139,16 @@ type FileOffer struct {
// HelloMessage is the first message sent on the "yaw" DataChannel.
// The signature binds this identity to the specific DTLS session.
// The Invite field is a waste-go extension (§ waste-go/extensions.md):
// when RequireInvite is enabled on a network, peers that omit or present
// an invalid signed invite are disconnected. YAW/2-only peers ignore this field.
type HelloMessage struct {
Type string `json:"type"` // always "hello"
ID string `json:"id"` // hex pubkey
Nick string `json:"nick"` // alias
Caps []string `json:"caps"` // capability list, e.g. ["chat","file"]
Sig string `json:"sig"` // hex ed25519 sig over HelloBindString
Type string `json:"type"` // always "hello"
ID string `json:"id"` // hex pubkey
Nick string `json:"nick"` // alias
Caps []string `json:"caps"` // capability list, e.g. ["chat","file"]
Sig string `json:"sig"` // hex ed25519 sig over HelloBindString
Invite string `json:"invite,omitempty"` // waste-go ext: signed waste: invite string
}
// HelloBindString returns the bytes the hello signature covers:
@@ -276,9 +280,11 @@ type IpcMessage struct {
Body string `json:"body,omitempty"`
// join_network / leave_network
NetworkName string `json:"network_name,omitempty"`
NetworkHash string `json:"network_hash,omitempty"` // 64-char hex (yaw2 `net` field); alternative to network_name
ShareDir string `json:"share_dir,omitempty"` // optional per-network share directory
NetworkName string `json:"network_name,omitempty"`
NetworkHash string `json:"network_hash,omitempty"` // 64-char hex (yaw2 `net` field); alternative to network_name
ShareDir string `json:"share_dir,omitempty"` // optional per-network share directory
RequireInvite bool `json:"require_invite,omitempty"` // waste-go ext: reject peers without valid signed invite
InviteString string `json:"invite_string,omitempty"` // waste-go ext: the invite used to join (stored in mesh)
// send_file / set_share_dir / file_complete path
Path string `json:"path,omitempty"`
@@ -301,7 +307,7 @@ type IpcMessage struct {
// multi-network: all joined networks (additive)
Networks []NetworkInfo `json:"networks,omitempty"`
ErrorMessage string `json:"error_message,omitempty"`
InviteString string `json:"invite,omitempty"`
InviteGenerated string `json:"invite,omitempty"`
Files []FileEntry `json:"files,omitempty"`
Shares []ShareEntry `json:"shares,omitempty"`
ShareNetworks []string `json:"networks,omitempty"` // for add_share command