Chat, Notes, and Schedules still use the old sw.shell.Topbar component, causing a double topbar. Added migration steps to v0.7.3 alongside the headless E2E work — same pattern as the v0.7.0 kernel surface migrations. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
15 KiB
Armature — Roadmap
Current: v0.7.2 — Package Runners + CI Gate
Self-hosted extensible platform. Auth, identity, packages, Starlark sandbox, storage, realtime, and ops are kernel primitives. Everything else is an extension.
Kernel capabilities: Auth (builtin/mTLS/OIDC) · Users/teams/groups/RBAC · Surfaces/extensions/libraries/workflows · Starlark sandbox (capability-gated) · Object storage (PVC/S3) + ext_data tables · WebSocket hub + realtime pub/sub · Audit log · Notifications · Scheduled tasks
Completed history: v0.2.x–v0.5.x fully documented in CHANGELOG.md.
Highlights: RBAC + settings cascade, event bus + triggers, SDK stabilization,
workflow engine (multi-stage, team roles, signoff gate, public entry, SLA),
package distribution, Notes surface (CM6, folders, tags, backlinks, graph),
realtime primitive, Chat surface (chat-core library + surface + polish),
upgrade test harness, cluster registry + HA.
v0.6.x — Completed (MVP + Hardening)
All v0.6.x work is shipped and documented in CHANGELOG.md. Summary:
| Version | Title | Key Deliverables |
|---|---|---|
| v0.6.0 | Cluster Registry + HA | PG-backed node registry, heartbeat sweep, LISTEN/NOTIFY routing, self-eviction |
| v0.6.1 | Backup/Restore + Docs | .swb archive format, server-side backups, docs surface + 5 guides |
| v0.6.2 | Docs Polish + OpenAPI | Dark mode fix, topbar nav, api_schema manifest field, dynamic spec builder |
| v0.6.3 | Dead Code Sweep | Registry install fix, dead Go/JS/HTML deletion, narrowed default bundle |
| v0.6.4 | Admin Health/Metrics | Cluster dashboard merged into Admin tab, block renderer requires removed |
| v0.6.5 | Renderer Pipeline | sw.renderers.register() kernel primitive, unified markdown, docs rewrite |
| v0.6.6 | Final Hardening | Dependency auto-activation, ValidateManifest(), OIDC nonce, ICD/SDK update |
| v0.6.7 | Native mTLS | TLS_MODE config, MTLSNativeProvider, node-to-node mTLS, armature-ca.sh |
| v0.6.8 | Cookie Fix + UI Roadmap | Cookie SameSite fix, UI hardening roadmap published |
| v0.6.9 | Session Lifetime Config | Admin-configurable TTLs, idle timeout, "keep me logged in" |
| v0.6.10 | Viewport Foundation | Single layout model, CSS zoom, 100dvh, dead shell deprecated |
| v0.6.11 | CSS Deduplication | Old primitive system retired, one class per concept |
| v0.6.12 | Extension CSS Isolation | Prefix enforcement via linter, all 12 in-tree packages migrated |
| v0.6.13 | Responsive & Spacing | Spacing token scale (4px grid), tablet breakpoint |
| v0.6.14 | Visual Polish | Stale fallback colors purged, fonts self-hosted, radius tokens |
| v0.6.15 | User Display Audit | Batch user resolve API, sw.users SDK module |
| v0.6.16 | Usability Survey Gate | Four audit scripts, contrast/touch-target fixes |
| v0.6.17 | Bug Fixes & Welcome | Notes folder fix, team member add fix, welcome auto-disable, zero default bundle |
| v0.6.18 | CI Bundle Wiring | BUNDLED_PACKAGES env var wired into Gitea CI pipeline |
v0.7.x — Test Infrastructure + Quality Gate
The v0.6.x series built the kernel. v0.7.x makes it provably correct.
A full surface audit (docs/AUDIT-surfaces.md) found 7 cross-surface issues and 18 surface-specific issues across Settings, Admin, Team Admin, and Docs. Only Docs is properly built. The fix is three phases: (1) establish a shell contract and bring all four primary surfaces to parity, (2) build a runner framework for end-to-end browser tests, (3) automate those runners headlessly in CI.
Design docs:
docs/DESIGN-shell-contract.md— two-slot topbar, three navigation patterns, surface migrationsdocs/DESIGN-surface-runners.md— runner framework, requires declarations, headless E2Edocs/AUDIT-surfaces.md— full audit findings
v0.7.0 — Shell Contract + Surface Audit + Rebrand Cleanup
Design doc: docs/DESIGN-shell-contract.md
Shell Infrastructure
| Step | Status | Description |
|---|---|---|
| Shell topbar (two-slot model) | done | Kernel injects topbar into surface-extension template. Two named slots: left (defaults to manifest title) and center (flex: 1, for tabs/pickers/search). Home link, notification bell, and user menu always present. |
| Topbar customization API | done | sw.shell.topbar.setLeft(vnode) overrides left slot. sw.shell.topbar.setSlot(vnode) sets center slot. sw.shell.topbar.setTitle(str) shorthand for text-only left. sw.shell.topbar.hide() / .show() for full-bleed surfaces. |
| Kernel tab CSS | done | .sw-topbar__tabs and .sw-topbar__tab classes for consistent tab styling in the center slot. Surfaces use these for free or style their own slot content. |
| Notification read broadcast | done | Backend emits notification.read and notification.all_read WS events. Bell listens for .created, .read, .all_read. Cross-surface sync without refetch. |
| User menu reactivity | done | Emit package.changed (install/uninstall/enable/disable) and auth.changed (role/membership) WS events. UserMenu listens and re-fetches surface list. Most impactful single fix. |
| Shell announcement global dismiss | done | Dismissed state persisted to localStorage keyed by content hash. Dismiss once, dismissed everywhere. |
Surface Migrations
| Step | Status | Description |
|---|---|---|
| Settings → Pattern B (flat tabs) | done | Delete custom topbar + sidebar nav. 6 sections become flat tabs in topbar center slot. Content full-width. Fix Teams section: add team admin link, role display, leave action. Remove sessionStorage return URL logic. |
| Admin → Pattern C (category tabs + sidebar) | done | Delete custom admin-topbar. setLeft() for favicon + "Administration". setSlot() for category tabs (People / Workflows / System / Monitoring). Admin sidebar (sub-navigation) unchanged — surface-owned, below the topbar. Bell + user menu come free from shell. Delete bespoke CatIcon renderer if using standard SVGs. |
| Team Admin → Pattern B (flat tabs) | done | Delete custom topbar + sidebar nav. 5 sections (Members / Connections / Workflows / Settings / Activity — Groups removed) become flat tabs. Content full-width. setTitle() for team-specific name. Remove sessionStorage return URL. Fix signoff user display (user_id → sw.users.displayName()). |
| Team Admin: remove Groups tab | done | 37-line dead-end. Read-only "No groups" with no create/docs/link. Remove until team-scoped group management is properly designed. |
| Docs → Pattern A (default) | done | Delete explicit Topbar import. Shell topbar auto-renders with manifest title. Docs sidebar (document list) is in content area, unaffected. |
Error Handling + UX Pass
| Step | Status | Description |
|---|---|---|
| Inline error states | done | Replace catch { toast } with inline error + retry on all list endpoints. New .sw-inline-error CSS primitive. Systematic pass across Settings, Admin, Team Admin. |
| Empty state guidance | done | Every "No X" message gets one-line explanation + primary action (create button or doc link). Admin Groups, Workflows, Teams; Team Admin Workflows; Settings Notifications. |
Bug Fixes
| Step | Status | Description |
|---|---|---|
| evil-chat cleanup | done | ICD security tier: finally cleanup block + tighten 409 assertion. |
| Workflow demo error surfacing | done | Replace silent catch with inline error + retry. |
| Hello dashboard removal | done | Delete packages/hello-dashboard/. |
Rebrand
| Step | Status | Description |
|---|---|---|
| Light-mode icon SVG | done | New favicon-light.svg — square icon, transparent bg, dark node fills. Rename current favicon-light.svg (wordmark) to wordmark.svg. |
| Dark-mode wordmark SVG | done | New wordmark-dark.svg — light text for dark backgrounds. |
| Light-mode raster assets | done | favicon-light-32.png, favicon-light-256.png. |
| PWA manifest description | done | "Self-hosted extension platform — build, compose, and run extensions." |
| REBRAND-SPEC.md | Land into docs/. Find/replace patterns, validation checklist, asset inventory. |
|
| base.html favicon swap | done | Verify theme swap works with new square light icon. |
Tests
| Step | Status | Description |
|---|---|---|
| Shell topbar renders for extensions | done | Home, left slot, center slot, bell, user menu present. |
| Topbar API (setLeft, setSlot, hide) | done | Custom content renders. Hide removes topbar. |
| All 4 surfaces use shell topbar | done | No double topbars. Each pattern (A/B/C) renders correctly. |
| User menu reactive to package install | Install → menu updates without reload. | |
| Notification bell cross-surface sync | Dismiss on Notes → clears on Chat. | |
| Inline error on API failure | Error + retry shown, not empty list. |
v0.7.1 — Surface Runner Framework
Design doc: docs/DESIGN-surface-runners.md
| Step | Status | Description |
|---|---|---|
Runner framework (sw.testing) |
done | SDK module: suite/test/assert, lifecycle hooks, structured JSON results. |
requires declarations |
done | Runner manifests declare dependencies. Missing packages → clean skip. |
| Cleanup enforcement | done | s.track(type, id) auto-deletes in afterAll. No leaked state. |
| Warning tier | done | pass / fail / warning. No silent catch swallowing. |
| ICD runner migration | done | Refactor to sw.testing. Test logic preserved. |
| SDK runner migration | done | Refactor to sw.testing. Domain suites preserved. |
| Runner registry surface | done | /s/test-runners — list runners, run-all, results dashboard. |
v0.7.2 — Package Runners + CI Gate
| Step | Status | Description |
|---|---|---|
| Notes runner | done | requires: ["notes"]. 3 suites (crud, folders, tags-search), 12 tests. |
| Chat runner | done | requires: ["chat", "chat-core"]. 2 suites (conversations, messaging), 9 tests. |
| Schedules runner | done | requires: ["schedules"]. 1 suite (crud), 5 tests. |
| Workflow runner | done | requires: ["content-approval"]. 1 suite (lifecycle), 5 tests. |
| Renderer runner | done | requires: ["mermaid-renderer"]. 1 suite (contract), 4 tests. |
| Runner result API | done | POST/GET /api/v1/admin/test-runners/results. In-memory store, 4 Go tests. |
| CI integration | done | test-runners stage in Gitea CI. Playwright driver, wait-for-healthy.sh. |
v0.7.3 — Extension Shell Migration + Headless E2E
Extension Shell Migration
Chat, Notes, and Schedules still use the old sw.shell.Topbar component,
producing a double topbar (shell-injected + surface-owned). Migrate all
three to the v0.7.0 shell contract (sw.shell.topbar.setTitle/setSlot),
same pattern as the kernel surface migrations.
| Step | Status | Description |
|---|---|---|
| Chat → shell topbar | Delete <Topbar>, use setTitle('Chat') + setSlot() for thread title/people button. |
|
| Notes → shell topbar | Delete <Topbar>, use setTitle('Notes') + setSlot() for sidebar tabs/search. |
|
| Schedules → shell topbar | Delete <Topbar>, use setTitle('Schedules'). Pattern A (title only). |
|
| Update package runner tests | Assert shell topbar present, no double topbar, on migrated surfaces. |
Headless E2E Automation
| Step | Status | Description |
|---|---|---|
| Playwright test harness | ci/e2e-surface-test.sh — docker-compose, chromium, run-all, assert. |
|
| Screenshot-on-failure | Full-page screenshot + console log. CI artifacts. | |
| Navigation smoke test | Playwright visits every surface. Asserts topbar, no JS errors, home link works. | |
| Visual regression baseline | Optional screenshot diff. Not a gate — report for review. | |
| CI pipeline integration | After unit tests + API runners. Failure blocks merge. |
v0.7.4 — Documentation + Deferred Surface Work
| Step | Status | Description |
|---|---|---|
| Permissions & Groups guide | RBAC model, permission slugs with descriptions, group scoping, settings cascade. | |
| Workflows user guide | Entry modes, stages, team roles, signoff gates, SLA, public forms. | |
| Docs content refresh | Review all 5 existing docs for accuracy at v0.7.x. | |
| Extension config section docs | Document config_section manifest field for Settings/Admin extensibility. |
|
| Team Admin Workflows evaluation | 723-line inline designer — extract to surface or split into files. Decision doc if needed. |
Post-v0.7.x
- LLM participation (
llm-bridgeextension) - Rich media extensions: image generation, code sandbox, STT/TTS
- Desktop app (Tauri or Electron)
- Sidecar tier: container-based extensions
- Federation: cross-instance package sharing
- Plugin marketplace with signing and review
Design Decisions Log
| Decision | Rationale |
|---|---|
| Tasks → extension | Three trigger primitives replace the monolithic scheduler. |
| Sessions removed | Workflow instances with dedicated storage replace kernel sessions. |
custom stage mode |
Delegates to a surface package, proving extension composability. |
| Providers removed from kernel | Connections + Starlark provider.complete as the interface. |
| Kernel permissions simplified | 6 platform permissions. Extensions define their own. |
| Preact+htm retained | 3KB runtime, no build step, KISS. |
| Single Docker image | Go binary + assets + migrations. |
| Admin → RBAC group | Grant check replaces role check. |
| Settings cascade | Scope auth + user_overridable. Two orthogonal axes. |
| No new migrations pre-MVP | Proper versioned migrations post-MVP. |
| Chat as extension, not kernel | Zero kernel awareness. Proves extensibility thesis. |
| PG as consensus layer | UNLOGGED node_registry + LISTEN/NOTIFY. No etcd/Consul/Redis. |
| Two trigger tiers | Extension-declared (full sandbox) vs user ad-hoc (restricted). |
| Builtin package rationale | Must enhance kernel surfaces or demonstrate platform capabilities. |
| Two-slot topbar model | Left slot (title/branding) + center slot (flex: 1, tabs/pickers). Two named slots cover every navigation pattern: simple title (Pattern A), flat tabs full-width (Pattern B), category tabs + surface-owned sidebar (Pattern C). Surfaces without sub-items get full content width; surfaces with hierarchical navigation add their own sidebar below the topbar. Shell provides the stage; surface decides the theater. |
| All four primary surfaces migrate to shell topbar | Admin was "keep custom topbar" initially. The two-slot model makes it unnecessary — category tabs fit in the center slot, sidebar is surface-owned below. One topbar implementation replaces four. Bell + user menu + reactivity come free on every surface. |
| Settings / Team Admin → flat tabs (Pattern B) | Both had thin sidebars (~140px) that consumed width without justification. 5–6 sections fit cleanly in topbar tabs. Full-width content is a better use of space for these surfaces. |
| Team Admin Groups removed | 37-line read-only dead-end. Admin Groups has full CRUD. Restore when properly designed. |
| Docs is the reference surface | Only surface with shell Topbar, bell, user menu, inline errors. Others converge. |
| Surface runners over expanding ICD | Different test tier, different failure class. |
| Headless E2E via Playwright | Runners produce structured JSON; Playwright navigates and reads output. |