Implement Phase 1: core framework, operational tooling, and runbook

Core packages: crypto (Argon2id/AES-256-GCM), config (TOML/viper),
db (SQLite/migrations), barrier (encrypted storage), seal (state machine
with rate-limited unseal), auth (MCIAS integration with token cache),
policy (priority-based ACL engine), engine (interface + registry).

Server: HTTPS with TLS 1.2+, REST API, auth/admin middleware, htmx web UI
(init, unseal, login, dashboard pages).

CLI: cobra/viper subcommands (server, init, status, snapshot) with env
var override support (METACRYPT_ prefix).

Operational tooling: Dockerfile (multi-stage, non-root), docker-compose,
hardened systemd units (service + daily backup timer), install script,
backup script with retention pruning, production config examples.

Runbook covering installation, configuration, daily operations,
backup/restore, monitoring, troubleshooting, and security procedures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-14 20:43:11 -07:00
commit 4ddd32b117
60 changed files with 4644 additions and 0 deletions

77
internal/server/server.go Normal file
View File

@@ -0,0 +1,77 @@
// Package server implements the HTTP server for Metacrypt.
package server
import (
"context"
"crypto/tls"
"fmt"
"log/slog"
"net/http"
"time"
"git.wntrmute.dev/kyle/metacrypt/internal/auth"
"git.wntrmute.dev/kyle/metacrypt/internal/config"
"git.wntrmute.dev/kyle/metacrypt/internal/engine"
"git.wntrmute.dev/kyle/metacrypt/internal/policy"
"git.wntrmute.dev/kyle/metacrypt/internal/seal"
)
// Server is the Metacrypt HTTP server.
type Server struct {
cfg *config.Config
seal *seal.Manager
auth *auth.Authenticator
policy *policy.Engine
engines *engine.Registry
httpSrv *http.Server
logger *slog.Logger
}
// New creates a new server.
func New(cfg *config.Config, sealMgr *seal.Manager, authenticator *auth.Authenticator,
policyEngine *policy.Engine, engineRegistry *engine.Registry, logger *slog.Logger) *Server {
s := &Server{
cfg: cfg,
seal: sealMgr,
auth: authenticator,
policy: policyEngine,
engines: engineRegistry,
logger: logger,
}
return s
}
// Start starts the HTTPS server.
func (s *Server) Start() error {
mux := http.NewServeMux()
s.registerRoutes(mux)
tlsCfg := &tls.Config{
MinVersion: tls.VersionTLS12,
CipherSuites: []uint16{
tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
},
}
s.httpSrv = &http.Server{
Addr: s.cfg.Server.ListenAddr,
Handler: s.loggingMiddleware(mux),
TLSConfig: tlsCfg,
ReadTimeout: 30 * time.Second,
WriteTimeout: 30 * time.Second,
IdleTimeout: 120 * time.Second,
}
s.logger.Info("starting server", "addr", s.cfg.Server.ListenAddr)
err := s.httpSrv.ListenAndServeTLS(s.cfg.Server.TLSCert, s.cfg.Server.TLSKey)
if err != nil && err != http.ErrServerClosed {
return fmt.Errorf("server: %w", err)
}
return nil
}
// Shutdown gracefully shuts down the server.
func (s *Server) Shutdown(ctx context.Context) error {
return s.httpSrv.Shutdown(ctx)
}