mirror of
https://github.com/hanzoai/base.git
synced 2026-10-21 03:41:50 +00:00
core.App.Logger() now returns logger.Logger (the new shim interface) instead of *slog.Logger, so every consumer talks to the same backend-agnostic surface and stops pinning itself to log/slog. The raw *slog.Logger is still reachable as App.SlogLogger() for the in-app BatchHandler reload hook and the two tests that type-assert the underlying handler — that's the only sanctioned escape hatch. Plugins and network code that previously held *slog.Logger fields move to luxlog.Logger (kms, vault, zap-transport, base-network/transport_zap, network/archive_writer, tools/tasks/client). luxfi/zap's Logger field was a pure transit dependency; we drop it from base call sites since zaplib has its own default. Remaining "log/slog" imports — 11 files — are confined to the adapter/handler bridge (tools/logger and core/log_printer/base/app) and to two tests that exercise the slog.Handler contract directly. Those are the irreducible boundary where slog is the language of the interface.
142 lines
3.6 KiB
Go
142 lines
3.6 KiB
Go
// Copyright (C) 2020-2026, Hanzo AI Inc. All rights reserved.
|
|
// See the file LICENSE for licensing terms.
|
|
|
|
package kms
|
|
|
|
import (
|
|
"github.com/hanzoai/base/core"
|
|
"github.com/hanzoai/base/tools/hook"
|
|
sdk "github.com/hanzoai/kms/sdk/go"
|
|
luxlog "github.com/luxfi/log"
|
|
)
|
|
|
|
// MustRegister registers the KMS plugin with a Base app and panics on error.
|
|
//
|
|
// Usage:
|
|
//
|
|
// kms.MustRegister(app, kms.Config{
|
|
// Nodes: []string{"https://kms-mpc-0:9999", "https://kms-mpc-1:9999", "https://kms-mpc-2:9999"},
|
|
// OrgSlug: "my-org",
|
|
// Threshold: 2,
|
|
// EncryptedCollections: map[string][]string{
|
|
// "credentials": {"api_key", "api_secret"},
|
|
// },
|
|
// FHESearchable: map[string][]string{
|
|
// "credentials": {"name"},
|
|
// },
|
|
// })
|
|
func MustRegister(app core.App, config Config) {
|
|
if err := Register(app, config); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Register registers the KMS plugin with a Base app. The plugin provides:
|
|
// - Zero-knowledge encrypted secret management via REST API
|
|
// - Transparent field-level encryption on configured collections
|
|
// - FHE-encrypted indexes for querying encrypted fields without decryption
|
|
func Register(app core.App, config Config) error {
|
|
if !config.Enabled {
|
|
return nil
|
|
}
|
|
|
|
if err := config.validate(); err != nil {
|
|
return err
|
|
}
|
|
|
|
client, err := sdk.NewClient(sdk.Config{
|
|
Nodes: config.Nodes,
|
|
OrgSlug: config.OrgSlug,
|
|
Threshold: config.Threshold,
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
p := &plugin{
|
|
app: app,
|
|
config: config,
|
|
client: client,
|
|
logger: luxlog.New("component", "kms"),
|
|
}
|
|
|
|
// Build lookup maps for fast hook checks.
|
|
p.encFieldSet = make(map[string]map[string]struct{}, len(config.EncryptedCollections))
|
|
for col, fields := range config.EncryptedCollections {
|
|
m := make(map[string]struct{}, len(fields))
|
|
for _, f := range fields {
|
|
m[f] = struct{}{}
|
|
}
|
|
p.encFieldSet[col] = m
|
|
}
|
|
|
|
p.fheFieldSet = make(map[string]map[string]struct{}, len(config.FHESearchable))
|
|
for col, fields := range config.FHESearchable {
|
|
m := make(map[string]struct{}, len(fields))
|
|
for _, f := range fields {
|
|
m[f] = struct{}{}
|
|
}
|
|
p.fheFieldSet[col] = m
|
|
}
|
|
|
|
// Bootstrap: auto-unlock if configured.
|
|
app.OnBootstrap().Bind(&hook.Handler[*core.BootstrapEvent]{
|
|
Id: "__kmsBootstrap__",
|
|
Func: func(e *core.BootstrapEvent) error {
|
|
if err := e.Next(); err != nil {
|
|
return err
|
|
}
|
|
|
|
if config.AutoUnlock {
|
|
passphrase := config.resolvePassphrase()
|
|
if passphrase != "" {
|
|
if unlockErr := client.Unlock(passphrase); unlockErr != nil {
|
|
p.logger.Warn("kms: auto-unlock failed", "error", unlockErr)
|
|
} else {
|
|
p.logger.Info("kms: auto-unlock succeeded")
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
})
|
|
|
|
// Serve: register routes and record hooks.
|
|
app.OnServe().Bind(&hook.Handler[*core.ServeEvent]{
|
|
Id: "__kmsServe__",
|
|
Func: func(e *core.ServeEvent) error {
|
|
// Store reference for programmatic access.
|
|
app.Store().Set("kms", p)
|
|
|
|
p.registerRoutes(e.Router)
|
|
p.registerHooks()
|
|
|
|
return e.Next()
|
|
},
|
|
})
|
|
|
|
// Terminate: lock CEK on shutdown.
|
|
app.OnTerminate().Bind(&hook.Handler[*core.TerminateEvent]{
|
|
Id: "__kmsTerminate__",
|
|
Func: func(e *core.TerminateEvent) error {
|
|
p.logger.Info("kms: locking CEK on shutdown")
|
|
client.Lock()
|
|
return e.Next()
|
|
},
|
|
})
|
|
|
|
return nil
|
|
}
|
|
|
|
type plugin struct {
|
|
app core.App
|
|
config Config
|
|
client *sdk.Client
|
|
logger luxlog.Logger
|
|
|
|
// Pre-computed field sets for O(1) lookup in hooks.
|
|
encFieldSet map[string]map[string]struct{} // collection -> field -> struct{}
|
|
fheFieldSet map[string]map[string]struct{} // collection -> field -> struct{}
|
|
}
|