# Web UI Implementation Plan: SSH CA, Transit, and User Engines ## Overview Three engines (SSH CA, Transit, User) are fully implemented at the core, gRPC, and REST layers but have no web UI. This plan adds browser-based management for each, following the patterns established by the PKI engine UI. ## Architecture The web UI is served by `metacrypt-web`, a separate binary that talks to the API server over gRPC. All data access flows through the gRPC client — the web server has no direct database or barrier access. Authorization is enforced by the API server; the web UI only controls visibility (e.g. hiding admin-only forms from non-admin users). ### Existing Patterns (from PKI reference) | Concern | Pattern | |---------|---------| | Template composition | `layout.html` defines `"layout"` block; page templates define `"title"` and `"content"` blocks | | Template rendering | `renderTemplate(w, "page.html", data)` — parses `layout.html` + page template, injects CSRF func | | gRPC calls | `ws.vault.Method(ctx, token)` via `vaultBackend` interface; token from cookie | | CSRF | Signed double-submit cookie; `{{csrfField}}` in every form | | Error display | `{{if .Error}}
{{.Error}}
{{end}}` at top of content | | Success display | `
...
` inline after action | | Mount discovery | `findCAMount()` pattern — iterate `ListMounts()`, match on `.Type` | | Tables | `.table-wrapper` > `` with ``/`` | | Detail views | `.card` with `.card-title` + `.kv-table` for metadata | | Admin actions | `{{if .IsAdmin}}` guards around admin-only cards | | Forms | `.form-row` > `.form-group` > `