All checks were successful
CI/CD / detect-changes (push) Successful in 4s
CI/CD / e2e-smoke (push) Has been skipped
CI/CD / test-frontend (push) Successful in 6s
CI/CD / test-runners (push) Has been skipped
CI/CD / test-go-pg (push) Successful in 2m48s
CI/CD / test-sqlite (push) Successful in 2m49s
CI/CD / build-and-deploy (push) Successful in 28s
Co-authored-by: Jeffrey Smith <jasafpro@gmail.com> Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
521 lines
32 KiB
Markdown
521 lines
32 KiB
Markdown
# Armature — Roadmap
|
||
|
||
## Current: v0.7.7 — API Tokens + Extension Permissions
|
||
|
||
Self-hosted extensible platform kernel. 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 · Cluster registry + HA
|
||
|
||
**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 migrations
|
||
- `docs/DESIGN-surface-runners.md` — runner framework, requires declarations, headless E2E
|
||
- `docs/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`. |
|
||
| CI DinD networking fix | done | Resolve container IP via `docker inspect` — DinD port mapping doesn't expose to runner localhost. |
|
||
|
||
### v0.7.3 — 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 | done | Delete `<Topbar>`, use `setTitle('Chat')` + `setSlot()` for thread title/people button. |
|
||
| Notes → shell topbar | done | Delete `<Topbar>`, use `setTitle('Notes')` + `setSlot()` for action buttons. |
|
||
| Schedules → shell topbar | done | Delete `<Topbar>`, use `setTitle('Schedules')` + `setSlot()` for count/new button. |
|
||
| Update package runner tests | done | Shell-topbar test suite in each runner — assert no legacy Topbar, uses shell API. |
|
||
|
||
### v0.7.4 — Documentation + Deferred Surface Work
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| Docs category grouping | done | Backend `Category` field on doc entries. Frontend groups sidebar by category with headings. Four categories: Getting Started, Platform, Extension Development, Operations. |
|
||
| Permissions & Groups guide | done | RBAC model, 7 permission slugs, system/custom groups, settings cascade, extension permissions. |
|
||
| Workflows user guide | done | Entry modes, stages, team roles, signoff gates, SLA, public forms, branch rules, Starlark hooks. |
|
||
| Starlark Reference | done | Sandbox constraints, 10 modules with function signatures, permission gates, example hook script. |
|
||
| Frontend JS Guide | done | Preact+htm runtime, 16 SDK modules with API reference, shell topbar patterns, CSS contract. |
|
||
| Extension config_section docs | done | Manifest schema, backend discovery, frontend contract, example component. Added to Extension Guide. |
|
||
| Docs content refresh | done | All 10 user-facing docs reviewed for v0.7.x accuracy: rebrand volume names, stale CSS vars, TLS_MODE env, self-hosted font notes, Architecture frontend section. |
|
||
| Team Admin Workflows split | done | 722-line `workflows.js` split into 3 modules: `workflows.js` (router+CRUD), `workflow-editor.js` (editor+stages), `workflow-monitor.js` (assignments+monitor+signoff). |
|
||
| Stale CSS variable fix | done | `--bg-2` references in `sw-shell.css` and `sw-primitives.css` replaced with `--bg-secondary`. |
|
||
|
||
### v0.7.5 — Headless E2E + CI Gate
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| CI gating redesign | done | Fix path rules: `VERSION`/`scripts/*` deploy-only, `docs/*` no longer skips deploy, test-runners trigger on any code change. |
|
||
| E2E smoke test harness | done | `ci/e2e-smoke-test.sh` + `ci/e2e-smoke-driver.js` — Playwright visits every surface, asserts topbar, no JS errors, home link. |
|
||
| Screenshot-on-failure | done | Full-page screenshot + console log saved as CI artifacts. |
|
||
| CI pipeline integration | done | Re-enable `test-runners` stage, add `e2e-smoke` stage. Failure blocks merge. |
|
||
| Design docs landed | done | `docs/DESIGN-storage-primitives.md`, `docs/DESIGN-extension-composability.md`. Roadmap expanded through v1.0. |
|
||
|
||
### v0.7.6 — Code Hygiene + Test Coverage
|
||
|
||
Codebase analysis (April 2026) found 9 code smells from the chat gut and
|
||
a test coverage gap in the store layer. Fix before v0.8.x kernel expansion.
|
||
|
||
**Critical Fixes**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| Remove channels from allowedViews | done | `db_module.go` — `ext_view_channels` does not exist. `db.view("channels")` crashes. |
|
||
| Fix workflow.html dead routes | done | Template calls `/api/v1/channels/{id}/workflow/*` — routes moved to `/api/v1/public/workflows/`. Update template to match. Also fixed `RenderWorkflow` handler to use route param as entry token. |
|
||
|
||
**Dead Code Removal**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| Delete SeedTestChannel() | done | `database/testhelper.go` — inserts into nonexistent channels table. |
|
||
| Remove RunContext.ChannelID | done | `sandbox/runner.go` — vestigial field, unused by any module. |
|
||
| Remove webhook.ChannelID | done | `webhook/webhook.go` — vestigial struct field from chat era. |
|
||
| Fix stale comments | done | `storage.go` key format, `prometheus.go` route pattern, `workflow_module.go` param name — reference dead `/channels` paths. |
|
||
|
||
**Migration Hygiene**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| Align SQLite migration numbering | done | SQLite 013 placeholder + renumber test_runner_type to 014. Compat rename in migrate.go. |
|
||
| Document missing 008 | done | Comment in both 009 files explaining the gap (merged into 007). |
|
||
|
||
**Test Gap Closure**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| store/ unit tests | | Deferred to v0.7.8. Direct tests for PG + SQLite store implementations. Requires live DB. Target: ≥30% SLOC ratio. |
|
||
| workflow/ routing unit tests | done | 82 tests: ResolveNextStage, ResolveStageByName, ParseStageConfig, evaluateCondition (all operators). |
|
||
| middleware/ unit tests | done | 10 tests: RequirePermission, RequireAdmin, permission caching, RateLimiter (allow/deny/fail-open). |
|
||
| InstallPackage decomposition | | Deferred to v0.7.8. 224 cognitive complexity. Split into: validate → create → DDL → permissions → triggers. |
|
||
|
||
**Bug Fixes**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| Remove Admin Storage tab | done | Dead weight under System — backend endpoint preserved for future Monitoring use. |
|
||
| Fix backup download | done | `sw.auth.token()` → `sw.auth._getToken()`. Both "Download Backup" and server backup download buttons now work. |
|
||
|
||
### v0.7.7 — API Tokens + Extension Permissions
|
||
|
||
Personal access tokens (PATs) for programmatic API access, plus
|
||
extension-declared user permissions for backend RBAC enforcement.
|
||
Unblocks: E2E test auth, CI automation, extension permission gating,
|
||
sidecar auth (v0.10.x).
|
||
|
||
**API Tokens (PATs)**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| `api_tokens` table + migration | done | `id`, `user_id`, `name`, `token_hash`, `permissions` (JSON array), `expires_at`, `last_used_at`, `created_at`. PG + SQLite. |
|
||
| Token store interface | done | `Create`, `GetByHash`, `ListForUser`, `Revoke`, `CleanExpired`, `UpdateLastUsed`. |
|
||
| Token generation endpoint | done | `POST /api/v1/auth/tokens` — name, permissions (subset of user's), expires_at. Returns token once (plain text), stored as SHA-256 hash. |
|
||
| Token management endpoints | done | `GET /api/v1/auth/tokens` (list mine), `DELETE /api/v1/auth/tokens/:id` (revoke). |
|
||
| Admin token endpoint | done | `POST /api/v1/admin/tokens` — creates token for any user. Explicit admin action, audit logged. |
|
||
| Auth middleware update | done | Accept `Bearer arm_pat_...` tokens alongside JWTs. Resolve user + scoped permissions from token. PAT requests skip refresh token flow. |
|
||
| Permission scoping | done | Token permissions ⊆ creating user's resolved permissions at creation time. Validated on create. If user loses a permission later, token retains it until revoked (git model). |
|
||
| Settings UI | done | Settings → API Tokens tab. Create, list, revoke. Show permissions, expiry, last used. Token value shown once on creation. |
|
||
| Admin UI | done | Admin → People → user detail → "Create API Token" action. |
|
||
| E2E test migration | done | Replace `ci/e2e-smoke-test.sh` login flow with PAT-based auth. Seed token via `ARMATURE_BOOTSTRAP_PAT=true`. |
|
||
|
||
**Extension-Declared User Permissions**
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| `user_permissions` manifest field | done | Extensions declare permissions users need: `"user_permissions": ["image-gen.use", "image-gen.admin"]`. |
|
||
| Dynamic permission registry | done | On install: merge into valid permission set. On uninstall: remove. `AllPermissions` becomes `KernelPermissions + ExtensionPermissions`. |
|
||
| Group UI update | done | Admin → Groups → permission checkboxes include extension-registered permissions, grouped by source package. |
|
||
| `permissions` Starlark module | done | `permissions.check(user_id, "image-gen.use")` → resolves user's groups, returns bool. New permission: none required (read-only check against kernel data). |
|
||
| `gate_permission` manifest field | done | Optional. If set, `ext_api.go` checks this permission before calling `on_request`. Extension doesn't execute for unauthorized users. |
|
||
| `req["permissions"]` in request dict | done | `ext_api.go` resolves user permissions and includes them in the request dict. Extensions can check inline without the module. |
|
||
|
||
### v0.7.8 — Deferred Test Coverage
|
||
|
||
Remaining test gap items deferred from v0.7.6.
|
||
|
||
| Step | Status | Description |
|
||
|------|--------|-------------|
|
||
| store/ unit tests | | Direct tests for PG + SQLite store implementations. Priority: packages, ext_data, workflows. Target: ≥30% SLOC ratio. |
|
||
| InstallPackage decomposition | | 224 cognitive complexity. Split into: validate → create → DDL → permissions → triggers. Each independently testable. |
|
||
| workflow/ engine integration tests | | Engine lifecycle tests with mock stores (Start, Advance, Cancel, signoff gate). |
|
||
|
||
---
|
||
|
||
## Planned
|
||
|
||
### v0.8.x — Storage Primitives
|
||
|
||
Design doc: `docs/DESIGN-storage-primitives.md`
|
||
|
||
The last major kernel expansion. Completes the primitive set that the
|
||
entire extension ecosystem builds on. After v0.8.x, the kernel is
|
||
feature-complete for 1.0 — all new capabilities are extensions.
|
||
|
||
**v0.8.0 — `files` Module**
|
||
|
||
Bridge `ObjectStore` (PVC/S3) into the Starlark sandbox. Extension-scoped
|
||
key namespacing (`ext/{packageID}/`). Permissions: `files.read`,
|
||
`files.write`. Metadata companions stored as sibling objects.
|
||
|
||
New: `sandbox/files_module.go`. Modified: runner wiring, permission
|
||
constants.
|
||
|
||
**v0.8.1 — `workspace` Module**
|
||
|
||
Managed disk directories for tools that need a real filesystem (git,
|
||
compilers, media tools). `workspace.create(name)` → scoped path.
|
||
Permission: `workspace.manage`. Quota enforcement via `WORKSPACE_QUOTA_MB`.
|
||
|
||
New: `sandbox/workspace_module.go`. Modified: runner wiring, permission
|
||
constants.
|
||
|
||
**v0.8.2 — Capability Negotiation**
|
||
|
||
Extensions declare environment requirements in manifest (`capabilities.required`,
|
||
`capabilities.optional`). Kernel validates at install time. Runtime query
|
||
via `settings.has_capability()`. Admin endpoint: `GET /admin/capabilities`.
|
||
|
||
Detected capabilities: `pgvector`, `workspace`, `object_storage`, `s3`,
|
||
`postgres`.
|
||
|
||
New: `handlers/capabilities.go`. Modified: install handler, settings module.
|
||
|
||
**v0.8.3 — Vector Column Type**
|
||
|
||
`"vector(N)"` in `db_tables` manifest. Maps to native `vector(N)` on
|
||
PG+pgvector, `JSONB` on PG without, `TEXT` on SQLite. New `db.query_similar()`
|
||
with dual-path dispatch (native operator vs Go-side brute force).
|
||
|
||
Modified: `ext_db_schema.go`, `db_module.go`.
|
||
|
||
**v0.8.4 — Extension Composability**
|
||
|
||
Design doc: `docs/DESIGN-extension-composability.md`
|
||
|
||
Manifest declarations for `slots` (host surfaces declare injection points)
|
||
and `contributes` (extensions declare UI contributions to other packages'
|
||
slots). `lib.require()` relaxed from library-only to any package with
|
||
`exports` — enables full packages (with surfaces, settings, UI) to also
|
||
expose callable backend functions. `sw.slots.renderAll()` SDK helper.
|
||
Admin slot aggregation endpoint.
|
||
|
||
The composability primitive that enables: LLM tool registration, UI
|
||
contribution (toolbar buttons, image actions), and cross-extension
|
||
function calls. No new tables, migrations, or permissions.
|
||
|
||
Modified: `sandbox/lib_module.go` (~1 line), `handlers/extensions.go`,
|
||
`src/js/sw/sdk/slots.js`. New: `handlers/admin_slots.go`.
|
||
|
||
---
|
||
|
||
### v0.9.x — Reference Extensions
|
||
|
||
The kernel is complete. This series proves the platform by shipping
|
||
first-party extensions that exercise every primitive. These are
|
||
**extensions, not kernel code** — they ship as `.pkg` files and can be
|
||
uninstalled.
|
||
|
||
**v0.9.0 — `vector-store` Library**
|
||
|
||
Library extension: document ingestion, chunk storage, embedding persistence,
|
||
semantic similarity search. Three-tier vector strategy (pgvector → JSONB
|
||
fallback → TEXT fallback). Consumes: `db.write`, `files.read`.
|
||
|
||
**v0.9.1 — `llm-bridge` Library**
|
||
|
||
Library extension: model abstraction, tool-use routing, provider BYOK via
|
||
connections. Exposes `complete()`, `embed()`, `classify()`, `register_tool()`
|
||
to consumer extensions. Tool extensions (image-gen, code-exec, web-search)
|
||
register at load time — LLM discovers available tools automatically.
|
||
Consumes: `connections.read`, `api.http`, `db.write`.
|
||
|
||
**v0.9.2 — `file-share` Extension**
|
||
|
||
File upload via `api_routes`, storage via `files` module, download links,
|
||
optional team/group ACLs via resource grants. First extension to exercise
|
||
the full `files` primitive end-to-end.
|
||
|
||
**v0.9.3 — `code-workspace` Extension**
|
||
|
||
Managed code repositories via `workspace` module. Git clone/pull via
|
||
`api.http` to Gitea/GitHub API. File browser surface. Structural indexing
|
||
(AST-aware) for code navigation. Consumes: `workspace.manage`, `files.write`,
|
||
`api.http`.
|
||
|
||
**v0.9.4 — `image-gen` + `image-edit` Extensions**
|
||
|
||
Image generation via external APIs (DALL-E, Stable Diffusion). Registers
|
||
as LLM tool with `llm-bridge`. Contributes regen/edit buttons to
|
||
`chat:image-actions` slot. Image-edit extends with inpaint, outpaint,
|
||
upscale, and style transfer — each contributing action buttons to the
|
||
same slot independently. First full demonstration of the composability
|
||
pattern: three extensions contributing UI to a fourth's surface.
|
||
|
||
**v0.9.5 — Chat System**
|
||
|
||
Generic 1-to-N human messaging. `chat-core` library (conversation/message
|
||
CRUD) + `chat` surface. Declares `chat:message-actions`, `chat:image-actions`,
|
||
`chat:composer-tools` slots for extension contribution. LLM participation
|
||
as a follow-on consuming `llm-bridge`. Consumes: `db.write`,
|
||
`realtime.publish`, `files.write` (attachments).
|
||
|
||
---
|
||
|
||
### v0.10.x — Sidecar Tier + Polish
|
||
|
||
**v0.10.0 — Sidecar Tier**
|
||
|
||
Autonomous out-of-process extensions for workloads that can't run in
|
||
Starlark: ML inference, media transcoding, language servers, local git
|
||
operations. The kernel does NOT manage container lifecycle — sidecars
|
||
are independent processes (Docker, systemd, bare binary) that connect
|
||
inward to the kernel, following the cluster registry pattern:
|
||
|
||
- Sidecar boots with cluster config (instance URLs, credentials).
|
||
- Connects and self-registers, declaring capabilities ("sklearn",
|
||
"gpu", "ffmpeg", "sentence-transformers").
|
||
- Goes inert until an admin authorizes (same flow as extension permissions).
|
||
- Kernel dispatches work; sidecar returns results.
|
||
- Heartbeat keeps registration alive; missed heartbeat = eviction.
|
||
|
||
Communication channel TBD (WebSocket over existing event bus, gRPC, or
|
||
HTTP callback model — design doc required). Authentication via mTLS
|
||
certs or registration tokens.
|
||
|
||
This model eliminates k8s RBAC dependency for local deployments. The
|
||
kernel stays thin — it accepts registrations and dispatches work. The
|
||
sidecar brings its own compute and manages its own lifecycle.
|
||
|
||
**v0.10.1 — Native Dialog Audit**
|
||
|
||
Replace `prompt()`/`confirm()`/`alert()` with `sw.dialog` SDK primitives.
|
||
Accessible, themed, promise-based. Small kernel SDK change that improves
|
||
every surface.
|
||
|
||
**v0.10.2 — Stability + Migration Tooling**
|
||
|
||
Proper versioned migrations (post-MVP discipline). `armature migrate`
|
||
CLI command. Backup/restore validation against reference dataset.
|
||
Pre-1.0 schema freeze.
|
||
|
||
---
|
||
|
||
### v1.0.0 — Stable Release
|
||
|
||
The kernel API surface is frozen. Extensions are the product.
|
||
|
||
Gate criteria:
|
||
|
||
- All kernel Starlark modules documented with examples
|
||
- All `api_routes` covered by OpenAPI spec
|
||
- Upgrade path tested from v0.8.0 → v1.0.0
|
||
- At least 3 reference extensions shipped and tested (vector-store, llm-bridge, chat)
|
||
- At least 1 cross-extension composability demo (image-gen → chat:image-actions)
|
||
- Headless E2E green on PG + SQLite
|
||
- `armature-ca.sh` + mTLS deployment guide
|
||
- Single-binary + Docker + K8s deployment paths documented
|
||
|
||
---
|
||
|
||
## Post-1.0 Horizon
|
||
|
||
These are candidates, not commitments. Each requires a design doc.
|
||
|
||
- **Federation** — cross-instance package sharing, identity federation
|
||
- **Package marketplace** — signing, review, discovery registry
|
||
- **Desktop app** — Tauri wrapper for local-first deployment
|
||
- **Offline/sync** — SQLite-first with PG sync for field deployments
|
||
- **Multi-tenant SaaS mode** — tenant isolation at the team boundary
|
||
|
||
---
|
||
|
||
## Design Principles
|
||
|
||
| Principle | Implication |
|
||
|-----------|-------------|
|
||
| Extensions are the product | Chat, tasks, LLM, vector search, file sharing — all extensions. Zero kernel awareness of domain logic. |
|
||
| Kernel stays thin | New kernel primitives require justification. If it can be an extension, it must be. |
|
||
| Progressive enhancement | Every feature works on SQLite. PG adds performance. pgvector adds native vectors. S3 adds scalable storage. |
|
||
| KISS-first | No unnecessary dependencies. Preact+htm (3KB), single binary, dual-DB from one codebase. |
|
||
| Changeset discipline | Each CS independently CI-green. Design docs as implementation contracts. |
|
||
| Pre-1.0 migration freedom | Schema changes fold into existing migrations. Post-1.0: proper versioned migrations. |
|
||
|
||
---
|
||
|
||
## 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. |
|
||
| `db` module is the structured store | No separate KV primitive. Extensions declare tables — infrastructure exists. |
|
||
| `files` module rides ObjectStore | No new kernel tables. Metadata as companion objects. Works on PVC and S3 identically. |
|
||
| `workspace` for real filesystem | Flat blob store can't serve git/compilers/ffmpeg. Managed disk paths are the explicit escape hatch. |
|
||
| Capability negotiation at install | Fail loud with actionable message, not silently at runtime. |
|
||
| Vector column with three-tier fallback | Works everywhere, works fast with pgvector. Documentation > hard gates. |
|
||
| Sidecar deferred to v0.10.x | HTTP module covers external APIs. Local compute is a v0.10.x concern. Sidecars connect inward (like cluster nodes), not spawned outward (no k8s RBAC needed). |
|
||
| No second scripting runtime | Starlark for glue, HTTP for external compute, sidecars for local compute. Three tiers with clear boundaries. Lua/WASM middle tier rejected — Turing-complete enough to be dangerous, not isolated enough to be trustworthy. |
|
||
| Reference extensions prove the platform | First-party `.pkg` files, not kernel code. Uninstallable. Dogfooding. |
|
||
| Composability via slots + exports, not kernel | `sw.slots` + `sw.actions` + `lib.require()` are the composition primitives. Manifest declarations add admin visibility. No inter-extension message bus — too complex, too fragile. |
|
||
| Gut cleanup before kernel expansion | Codebase analysis found 9 smells from the chat gut. Fix before adding new primitives — dead views and broken templates compound when new code builds on them. |
|
||
| PATs over OAuth client credentials | PATs are simpler (one table, one middleware check), cover all use cases (E2E tests, CI, sidecars, user automation), and follow the git hosting convention users already understand. OAuth adds client registration, token exchange, scopes — complexity without benefit for a self-hosted platform. |
|
||
| Extension-declared user permissions | Extensions register custom permissions in the kernel's group system. Admin assigns them to groups. Backend enforces via `permissions.check()` or `gate_permission`. Frontend hides via `sw.can()`. The kernel owns the permission registry; extensions contribute to it. |
|
||
| Admin token as explicit action | Following Venice.ai pattern — admin token creation is a separate endpoint, audit logged, requires `surface.admin.access`. No ambiguity about the privilege level. | |