niko_trust/cmd/server/main.go
Niko Marmeladkov e23a3cab59 refactor: drop PoW, checkpoint chain, gossip, light node and BFT; keep WS
The decentralization stack overcomplicated the project. Removed:
internal/pow, internal/smt, internal/checkpoint, internal/bft,
internal/lightnode, cmd/lightnode, relay gossip/checkpoint/proof/BFT
endpoints, their docs, vectors and the blake3 dependency.

Kept: WebSocket streaming on the relay, the full protocol v1 object set
including DelegationClaim (0x07) and KeyRotation request/confirm
(0x08/0x09) with chain resolution in verify.Graph, TrustedIssuers,
batch fetch, stable cursor pagination, per-type metrics.

INV-1 reverts to its original form: the relay holds no keys again.
Everything removed remains reachable at commit 20cc52c.
2026-08-26 00:42:53 +03:00

86 lines
2.3 KiB
Go

// Command server runs the trust relay over HTTP using the JSON transport.
//
// It holds no signing key: it stores and serves signed TCE objects and brokers
// authentication, but never forges (INV-1) and never decides authorization
// (INV-5).
package main
import (
"context"
"flag"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"git.n1ko.dev/Niko/niko_trust/internal/server"
)
func main() {
configPath := flag.String("config", "config.yaml", "path to YAML config (missing file => defaults)")
addr := flag.String("addr", "", "listen address (overrides config)")
audience := flag.String("audience", "", "server audience bound into auth assertions (overrides config)")
data := flag.String("data", "", "directory to persist objects (overrides config)")
flag.Parse()
cfg, err := server.LoadConfig(*configPath)
if err != nil {
// A missing default config is fine; only a present-but-unreadable or
// malformed file is fatal.
if *configPath != "config.yaml" || !os.IsNotExist(err) {
slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError})).
Error("load config", "path", *configPath, "err", err)
os.Exit(1)
}
}
// Flags override the file.
if *addr != "" {
cfg.ListenAddr = *addr
}
if *audience != "" {
cfg.Audience = *audience
}
if *data != "" {
cfg.DataDir = *data
}
logger := slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{Level: logLevel(cfg.LogLevel)}))
srv := server.New(cfg)
h := &http.Server{
Addr: cfg.ListenAddr,
Handler: srv.Handler(),
ReadHeaderTimeout: 10 * time.Second,
}
go func() {
logger.Info("trust relay listening", "addr", cfg.ListenAddr, "audience", cfg.Audience, "data_dir", cfg.DataDir)
if err := h.ListenAndServe(); err != nil && http.ErrServerClosed != err {
logger.Error("listen", "err", err)
os.Exit(1)
}
}()
sig := make(chan os.Signal, 1)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
<-sig
logger.Info("shutting down")
ctx2, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := h.Shutdown(ctx2); err != nil {
logger.Error("shutdown", "err", err)
}
logger.Info("stopped")
}
func logLevel(s string) slog.Level {
var l slog.Level
if err := l.UnmarshalText([]byte(s)); err != nil {
return slog.LevelInfo
}
return l
}