anonpenguin23 f26676db2c feat: add sandbox command and vault guardian build
- integrate Zig-built vault-guardian into cross-compile process
- add `orama sandbox` for ephemeral Hetzner Cloud clusters
- update docs for `orama node` subcommands and new guides
2026-02-27 15:22:51 +02:00

133 lines
3.5 KiB
Go

// Package vault provides HTTP handlers for vault proxy operations.
//
// The gateway acts as a smart proxy between RootWallet clients and
// vault guardian nodes on the WireGuard overlay network. It handles
// Shamir split/combine so clients make a single HTTPS call.
package vault
import (
"context"
"encoding/json"
"fmt"
"net/http"
"time"
"github.com/DeBrosOfficial/network/pkg/client"
"github.com/DeBrosOfficial/network/pkg/logging"
)
const (
// VaultGuardianPort is the port vault guardians listen on (client API).
VaultGuardianPort = 7500
// guardianTimeout is the per-guardian HTTP request timeout.
guardianTimeout = 5 * time.Second
// overallTimeout is the maximum time for the full fan-out operation.
overallTimeout = 15 * time.Second
// maxPushBodySize limits push request bodies (1 MiB).
maxPushBodySize = 1 << 20
// maxPullBodySize limits pull request bodies (4 KiB).
maxPullBodySize = 4 << 10
)
// Handlers provides HTTP handlers for vault proxy operations.
type Handlers struct {
logger *logging.ColoredLogger
dbClient client.NetworkClient
rateLimiter *IdentityRateLimiter
httpClient *http.Client
}
// NewHandlers creates vault proxy handlers.
func NewHandlers(logger *logging.ColoredLogger, dbClient client.NetworkClient) *Handlers {
h := &Handlers{
logger: logger,
dbClient: dbClient,
rateLimiter: NewIdentityRateLimiter(
30, // 30 pushes per hour per identity
120, // 120 pulls per hour per identity
),
httpClient: &http.Client{
Timeout: guardianTimeout,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
},
}
h.rateLimiter.StartCleanup(10*time.Minute, 1*time.Hour)
return h
}
// guardian represents a reachable vault guardian node.
type guardian struct {
IP string
Port int
}
// discoverGuardians queries dns_nodes for all active nodes.
// Every Orama node runs a vault guardian, so every active node is a guardian.
func (h *Handlers) discoverGuardians(ctx context.Context) ([]guardian, error) {
db := h.dbClient.Database()
internalCtx := client.WithInternalAuth(ctx)
query := "SELECT COALESCE(internal_ip, ip_address) FROM dns_nodes WHERE status = 'active'"
result, err := db.Query(internalCtx, query)
if err != nil {
return nil, fmt.Errorf("vault: failed to query guardian nodes: %w", err)
}
if result == nil || len(result.Rows) == 0 {
return nil, fmt.Errorf("vault: no active guardian nodes found")
}
guardians := make([]guardian, 0, len(result.Rows))
for _, row := range result.Rows {
if len(row) == 0 {
continue
}
ip := getString(row[0])
if ip == "" {
continue
}
guardians = append(guardians, guardian{IP: ip, Port: VaultGuardianPort})
}
if len(guardians) == 0 {
return nil, fmt.Errorf("vault: no guardian nodes with valid IPs found")
}
return guardians, nil
}
func writeJSON(w http.ResponseWriter, status int, v interface{}) {
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(status)
json.NewEncoder(w).Encode(v)
}
func writeError(w http.ResponseWriter, status int, msg string) {
writeJSON(w, status, map[string]string{"error": msg})
}
func getString(v interface{}) string {
if s, ok := v.(string); ok {
return s
}
return ""
}
// isValidIdentity checks that identity is exactly 64 hex characters.
func isValidIdentity(identity string) bool {
if len(identity) != 64 {
return false
}
for _, c := range identity {
if !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F')) {
return false
}
}
return true
}