// Package api is the Bootnode subsystem entry point. It exposes // Mount(r, deps) per HIP-0106 so superbase can fold Bootnode into the // unified Hanzo Cloud binary, and a standalone main shim // (cmd/bootnode) wires the same Mount onto a fresh chi.Mux. // // No business logic lives in main — everything routes through Mount, // every cross-subsystem call goes through deps, and every typed // surface is defined in ../schema/bootnode.zap. package api import ( "context" "log/slog" ) // Deps is the cross-subsystem contract Bootnode consumes. Every // non-trivial dependency is a typed ZAP client (in-process or RPC) // resolved by superbase at startup. Subsystems that aren't enabled // pass nil — handlers fail closed. // // The struct deliberately uses interface fields so superbase can hand // us in-process implementations (direct Go calls through the local // ZAP dispatcher) and a future split deployment can hand us an RPC // client without touching this package. type Deps struct { // Brand identifies the deployment (hanzo / lux / zoo / bootnode). // Drives logo, CORS allow-list, KMS prefix, IAM org default. Brand string // Logger is the structured logger plumbed in by superbase. Required. Logger *slog.Logger // IAM authenticates incoming JWTs. nil → fail-closed at the // auth middleware. The interface mirrors hanzo/iam/zap.Client; we // keep a local interface so the Bootnode module doesn't take a // hard dependency on the IAM module until the import graph is wired. IAM IAMClient // KMS resolves secrets. nil → secrets cannot be loaded; the // affected handlers return 503. KMS KMSClient // Base is the per-tenant SQLite gateway (HIP-0302). nil → store // layer falls back to an in-memory map (dev only). Base BaseClient // O11y emits traces/metrics/logs through the shared OTEL pipeline. // nil → telemetry middleware no-ops. O11y O11yClient // Commerce is the upstream billing service Bootnode reports usage // to. nil → usage records accumulate locally and never sync. Commerce CommerceClient } // IAMClient is the minimal interface Bootnode needs from hanzo/iam. // Once the iam Go module exposes its zap client we replace this with // a type alias to `iamzap.Client`. type IAMClient interface { // VerifyJWT validates a bearer token and returns the canonical // (orgID, userID, email) tuple. Implementations MUST fail closed // on signature mismatch / expiry / unknown issuer. VerifyJWT(ctx context.Context, bearer string) (orgID, userID, email string, err error) } // KMSClient is the minimal interface Bootnode needs from hanzo/kms. type KMSClient interface { GetSecret(ctx context.Context, ref string) (string, error) } // BaseClient is the per-tenant SQLite gateway (HIP-0302). Bootnode // asks for a connection scoped to (orgID, "bootnode") and stores its // projects / api_keys / webhooks / usage there. type BaseClient interface { // Open returns a per-tenant database handle. The opaque type is a // chosen-by-Base value (e.g. *sql.DB or a typed wrapper); we keep // it `any` here to avoid pulling in database/sql before the Base // module's public ZAP client lands. Open(ctx context.Context, orgID, namespace string) (any, error) } // O11yClient is the minimal observability surface. Implementations // should be safe to call with a nil receiver — handlers should never // have to nil-check. type O11yClient interface { RecordRequest(ctx context.Context, route string, status int, durationMs int64) } // CommerceClient mirrors the commerce ZAP RecordUsage shape so we can // report compute-unit accounting upstream. type CommerceClient interface { RecordUsage(ctx context.Context, orgID, projectID, chain, method string, computeUnits int32) error }