mirror of
https://github.com/hanzoai/kms.git
synced 2026-10-17 11:18:16 +00:00
The coupling was one string. Mount(app, deps) took hanzoai/cloud's Deps and read exactly two fields out of it: a logger, which luxfi/log already publishes as a process default and which Embed has always used, and a data root. Everything else in that struct crossed the boundary to be discarded. An init() then pushed this package into cloud's registry so cloud could call Mount back. That points the dependency the wrong way. It makes the graph circular, since cloud imports kms in order to mount it, and it fixes the set of possible hosts at one: two editions of hanzoai/cloud declare the same module path, so cloud.Deps names a different type in each, and a package that takes it can be composed by one of them and never the other. kms.App(root) now builds the app and returns it, and a host composes it with app.Use. Routes are absolute, so composition neither moves nor shadows them; the bridge test runs through a host app with middleware in front of it to hold that. Teardown travels with the app rather than with the process: the Embedded server drains on a shutdown hook, and zip makes a parent drain the children it composed, so kms.Shutdown and the package global it read are gone. The readyz branch that answered 503 when that global was nil went with them, since a failed Embed returns an error and no app at all. The daemon read the host's config too, and that was a live bug: it bound $CLOUD_LISTEN, default :8080, while its own image sets KMS_LISTEN=:8443 and its HEALTHCHECK curls 8443. It now reads its own, through the one function that resolves that address for both the daemon and Embed. zip moves from v1.10.0 to v1.27.2, the version the host already selects, because Use taking a Component is what makes an app composable at all. middleware.Logger and the KMS_LOG_LEVEL=debug opt-in around it go with the bump; zip logs every request itself now, so that report is no longer something a binary can be missing. Dropping cloud drops what it dragged in. goja, esbuild and a sourcemap parser leave the graph: a secret store no longer links a JavaScript engine. Both go.sum files carried a pre-retag hash for luxfi/vm v1.3.1 that no longer matches the bits the proxy serves, which failed every build outside the workspace. Corrected against the checksum database, which agrees with the download. Co-authored-by: Hanzo Dev <[email protected]>
75 lines
2.1 KiB
Go
75 lines
2.1 KiB
Go
// Hanzo KMS daemon.
|
|
//
|
|
// All assembly logic, route handlers, JWT verification, audit log, version CAS
|
|
// and ZAP transport live in package kms. This binary composes kms.App under a
|
|
// listener of its own and drains it on a signal. The unified cloud binary
|
|
// composes the same kms.App the same way; standalone exists for deploys where
|
|
// running the whole cloud surface is overkill.
|
|
//
|
|
// It reads no host's config. It used to call cloud.LoadConfig, which meant the
|
|
// daemon bound $CLOUD_LISTEN (default :8080) while its own image documents
|
|
// KMS_LISTEN=:8443 and its HEALTHCHECK curls 8443 — the container's stated
|
|
// configuration was not the one the process used.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"os"
|
|
"os/signal"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/luxfi/log"
|
|
"github.com/zap-proto/zip"
|
|
"github.com/zap-proto/zip/middleware"
|
|
|
|
kms "github.com/hanzoai/kms"
|
|
)
|
|
|
|
// version is overridden at build time via -ldflags "-X main.version=...".
|
|
// We propagate it into the package-level kms.Version so /healthz and
|
|
// /v1/kms/health report the same string.
|
|
var version = "dev"
|
|
|
|
func main() {
|
|
kms.Version = version
|
|
|
|
ctx := context.Background()
|
|
shutdown := initTelemetry(ctx, "hanzo-kms")
|
|
defer shutdown(ctx)
|
|
|
|
kmsApp, err := kms.App("")
|
|
if err != nil {
|
|
log.Crit("kms: build", "err", err)
|
|
}
|
|
|
|
app := zip.New(zip.Config{AppName: "kmsd"})
|
|
app.Use(middleware.Recover())
|
|
app.Use(middleware.RequestID())
|
|
app.Use(kmsApp)
|
|
|
|
// Listen in a goroutine so we can intercept SIGINT/SIGTERM and drain the
|
|
// in-process server gracefully. Shutting the outer app down drains the
|
|
// composed one, which drains Embed.
|
|
addr := kms.ListenAddr()
|
|
listenErr := make(chan error, 1)
|
|
go func() {
|
|
log.Info("kms: listening", "addr", addr)
|
|
listenErr <- app.Listen("http://" + addr)
|
|
}()
|
|
|
|
sig := make(chan os.Signal, 1)
|
|
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
|
|
|
|
select {
|
|
case s := <-sig:
|
|
log.Info("kms: shutting down", "signal", s)
|
|
case err := <-listenErr:
|
|
log.Crit("kms: listen failed", "err", err)
|
|
}
|
|
|
|
stopCtx, stopCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer stopCancel()
|
|
_ = app.ShutdownWithContext(stopCtx)
|
|
}
|