mirror of
https://github.com/hanzoai/ui-customization.git
synced 2026-10-30 18:18:42 +00:00
The architectural reference for console's tRPC->ZAP migration. Replaces the in-process tRPC UiCustomization router with a standalone Go binary built on Hanzo Base (embedded encrypted SQLite + plugins) exposing a typed ZAP capability-RPC interface. 11+ services follow this pattern. - proto/ui-customization.zap: canonical schema (zap-spec dialect), source of truth, compiled to Go via zapgen (make zap-gen, idempotent). - server/: ZAP RPC handler at msgType 200. Three decoupled wire layers (transport / envelope / typed payload); capability carried as opaque bytes. Single auth chokepoint (Kind + PermSessionRead bitmask); signature verify gated on a wired issuer registry (TODO -> SPEC.md 2.3). Get + GetModules read from the ui_customization Base collection. Promise-pipelining via an await/resolve table. - main.go: base.New() + vault (per-org encrypted SQLite) + ZAP router. HTTP :8090 (Base health/metrics), ZAP :9999. - cmd/probe/: out-of-process smoke probe. Tests: 4/4 pass (Get, GetModules, permission-denied, pipelining proof showing the dependent call ships before the first answer resolves). Pure-Go (CGO_ENABLED=0); zap-gen + build reproducible. No Prisma/Postgres/Mongo/tRPC.
2.8 KiB
2.8 KiB
CLAUDE.md — contract for AI helpers
This is the reference Hanzo Base-native Go service. Keep it lean and exemplary; 11+ services clone this pattern.
The one rule
The .zap schema is the source of truth. proto/ui-customization.zap
defines the data structs; gen/ is its Go projection via make zap-gen. Never
hand-edit gen/. Change the schema, regenerate, then update server/.
Two schema dialects (do not conflate)
proto/ui-customization.zapis the zap-spec dialect (package … / Field Type @off) thatgithub.com/zap-proto/go/cmd/zapgencompiles to Go. This is what THIS repo (a Go service) consumes.- The console keeps a capnp-es dialect copy (file-id +
interface { method @n () -> (…) }) that capnp-es compiles to TS. The two are NOT interchangeable (zapgen has nointerface; capnp-es has no barestruct … @off). Each toolchain owns the encoding it parses; the field set is the shared contract.
Build / test
- Pure-Go always:
CGO_ENABLED=0. CGO pulls blst/accel C deps that need a full toolchain and break reproducibility.makesets this +GOWORK=off. GOWORK=off: this repo is self-contained via go.modreplaces; a parentgo.workmust not capture it.make zap-genandmake buildare idempotent (byte-identical regen, reproducible binary). Keep them so — no timestamps/paths in generated output.make testruns the in-process ZAP RPC + permission + pipelining suite. Show it passing; don't claim "done" without it.
Architecture invariants (DRY, orthogonal, decomplected)
- Three wire layers, separated: transport (
luxfi/zapNode, msgType 200) / envelope (server/wire.go) / payload (gen/typed views). The capability is carried as OPAQUE bytes through all three — auth is a value, not a place. - One auth chokepoint:
Server.authorize. Kind +PermSessionReadbitmask always enforced; signature verify gated on a wired issuer registry (TODO → SPEC.md §2.3). Do not scatter permission checks into the method handlers. - One backend: Hanzo Base. No Prisma, Postgres-as-source-of-truth, Mongo,
Redis, tRPC, nginx. Data lives in the
ui_customizationBase collection (encrypted SQLite via the vault plugin when--vaultDiris set). - Pipelining is real:
getModulescan targetget's promise; the server's promise table (await/resolve) joins them. Genuine in-flight pipelining needs the two calls on SEPARATE connections (the transport is FIFO per connection) — seeClient.Pipelineand the pipelining test.
Do not
- Build Docker images locally (CI does, multi-arch → ghcr.io/hanzoai).
- Push to GitHub from here unless asked.
- Add plugins this one service doesn't need. Lean binary.
- Touch the console — wiring is documented in README, not done here.