Add NRC (Nostr Relay Connect) protocol and web UI (v0.48.9)
Some checks failed
Go / build-and-release (push) Has been cancelled
Some checks failed
Go / build-and-release (push) Has been cancelled
- Implement NIP-NRC protocol for remote relay access through public relay tunnel - Add NRC bridge service with NIP-44 encrypted message tunneling - Add NRC client library for applications - Add session management with subscription tracking and expiry - Add URI parsing for nostr+relayconnect:// scheme with secret and CAT auth - Add NRC API endpoints for connection management (create/list/delete/get-uri) - Add RelayConnectView.svelte component for managing NRC connections in web UI - Add NRC database storage for connection secrets and labels - Add NRC CLI commands (generate, list, revoke) - Add support for Cashu Access Tokens (CAT) in NRC URIs - Add ScopeNRC constant for Cashu token scope - Add wasm build infrastructure and stub files Files modified: - app/config/config.go: NRC configuration options - app/handle-nrc.go: New API handlers for NRC connections - app/main.go: NRC bridge startup integration - app/server.go: Register NRC API routes - app/web/src/App.svelte: Add Relay Connect tab - app/web/src/RelayConnectView.svelte: New NRC management component - app/web/src/api.js: NRC API client functions - main.go: NRC CLI command handlers - pkg/bunker/acl_adapter.go: Add NRC scope mapping - pkg/cashu/token/token.go: Add ScopeNRC constant - pkg/database/nrc.go: NRC connection storage - pkg/protocol/nrc/: New NRC protocol implementation - docs/NIP-NRC.md: NIP specification document 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -172,6 +172,13 @@ type C struct {
|
||||
CashuScopes string `env:"ORLY_CASHU_SCOPES" default:"relay,nip46" usage:"comma-separated list of allowed token scopes"`
|
||||
CashuReauthorize bool `env:"ORLY_CASHU_REAUTHORIZE" default:"true" usage:"re-check ACL on each token verification for stateless revocation"`
|
||||
|
||||
// Nostr Relay Connect (NRC) configuration - tunnel private relay through public relay
|
||||
NRCEnabled bool `env:"ORLY_NRC_ENABLED" default:"false" usage:"enable NRC bridge to expose this relay through a public rendezvous relay"`
|
||||
NRCRendezvousURL string `env:"ORLY_NRC_RENDEZVOUS_URL" usage:"WebSocket URL of the public relay to use as rendezvous point (e.g., wss://relay.example.com)"`
|
||||
NRCAuthorizedKeys string `env:"ORLY_NRC_AUTHORIZED_KEYS" usage:"comma-separated list of authorized client pubkeys (hex) for secret-based auth"`
|
||||
NRCUseCashu bool `env:"ORLY_NRC_USE_CASHU" default:"false" usage:"use Cashu access tokens for NRC authentication instead of static secrets"`
|
||||
NRCSessionTimeout string `env:"ORLY_NRC_SESSION_TIMEOUT" default:"30m" usage:"inactivity timeout for NRC sessions"`
|
||||
|
||||
// Cluster replication configuration
|
||||
ClusterPropagatePrivilegedEvents bool `env:"ORLY_CLUSTER_PROPAGATE_PRIVILEGED_EVENTS" default:"true" usage:"propagate privileged events (DMs, gift wraps, etc.) to relay peers for replication"`
|
||||
|
||||
@@ -404,6 +411,29 @@ func MigrateRequested() (requested bool, fromType, toType, targetPath string) {
|
||||
return
|
||||
}
|
||||
|
||||
// NRCRequested checks if the first command line argument is "nrc" and returns
|
||||
// the NRC subcommand parameters.
|
||||
//
|
||||
// Return Values
|
||||
// - requested: true if the 'nrc' subcommand was provided
|
||||
// - subcommand: the NRC subcommand (generate, list, revoke)
|
||||
// - args: additional arguments for the subcommand
|
||||
func NRCRequested() (requested bool, subcommand string, args []string) {
|
||||
if len(os.Args) > 1 {
|
||||
switch strings.ToLower(os.Args[1]) {
|
||||
case "nrc":
|
||||
requested = true
|
||||
if len(os.Args) > 2 {
|
||||
subcommand = strings.ToLower(os.Args[2])
|
||||
if len(os.Args) > 3 {
|
||||
args = os.Args[3:]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// KV is a key/value pair.
|
||||
type KV struct{ Key, Value string }
|
||||
|
||||
@@ -775,3 +805,39 @@ func (cfg *C) GetBboltConfigValues() (
|
||||
cfg.BboltNoSync,
|
||||
cfg.BboltMmapSizeMB * 1024 * 1024
|
||||
}
|
||||
|
||||
// GetNRCConfigValues returns the NRC (Nostr Relay Connect) configuration values.
|
||||
// This avoids circular imports with pkg/protocol/nrc while allowing main.go to construct
|
||||
// the NRC bridge configuration.
|
||||
func (cfg *C) GetNRCConfigValues() (
|
||||
enabled bool,
|
||||
rendezvousURL string,
|
||||
authorizedKeys []string,
|
||||
useCashu bool,
|
||||
sessionTimeout time.Duration,
|
||||
) {
|
||||
// Parse session timeout
|
||||
sessionTimeout = 30 * time.Minute // Default
|
||||
if cfg.NRCSessionTimeout != "" {
|
||||
if d, err := time.ParseDuration(cfg.NRCSessionTimeout); err == nil {
|
||||
sessionTimeout = d
|
||||
}
|
||||
}
|
||||
|
||||
// Parse authorized keys
|
||||
if cfg.NRCAuthorizedKeys != "" {
|
||||
keys := strings.Split(cfg.NRCAuthorizedKeys, ",")
|
||||
for _, k := range keys {
|
||||
k = strings.TrimSpace(k)
|
||||
if k != "" {
|
||||
authorizedKeys = append(authorizedKeys, k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return cfg.NRCEnabled,
|
||||
cfg.NRCRendezvousURL,
|
||||
authorizedKeys,
|
||||
cfg.NRCUseCashu,
|
||||
sessionTimeout
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user