Skip to content

UI Runtime Modes: RuntimeContext v2 + capability system (replaces FeatureFlags) #509

Description

@itlackey

Summary

Replace FeatureFlags { admin: boolean } with a two-layer RuntimeContext + capability resolution system. This is the foundation that enables assistant-container mode, PWA mode, and the connection-management refactor.

Background

The current features.admin boolean cannot express:

  • "Chat + assistant settings but no host management" (assistant-container)
  • "Connection management only" (PWA/client-only install)
  • "Full host management without Electron IPC" (browser to host-ui)

Every route currently checks if (features.admin) in scattered locations. There is no single source of truth for what the current deploy mode can do.

Design

Full design in docs/technical/ui-runtime-modes-plan.md.

Two-layer model

Server context (computed at request time, public via /api/runtime):

type ServerRuntimeContext = {
  version: 2;
  hostMode: 'electron-host' | 'host-ui' | 'assistant-container' | 'pwa-static';
  serverCapabilities: Capability[];
  // ... routes, security, versions
};

Client context (detected in the browser — never server-computed):

type ClientContext = {
  displayMode: 'electron' | 'standalone-pwa' | 'browser';
  activeConnection?: { kind, id, grantedCapabilities? };
};

Resolved = resolveCapabilities(serverCaps, clientCtx) — one function, one file.

Capability matrix

hostMode clientDisplayMode Effective capabilities
electron-host electron ALL
host-ui browser ALL (minus Electron IPC)
assistant-container browser / standalone-pwa chat, assistant-settings:read/write
pwa-static standalone-pwa / browser connections:manage, connections:switch, chat, pwa:install

Extension point

activeConnection.grantedCapabilities allows future rules (e.g. "assistant settings when connected to a remote assistant-container") without touching the resolution function structure.

Acceptance criteria

  • lib/server/features.tscomputeServerRuntimeContext(event) returning ServerRuntimeContext
  • lib/runtime-context.svelte.tsresolveCapabilities(serverCaps, clientCtx), hasCapability(cap), reactive runtimeContext store
  • lib/client-context.tsdetectClientDisplayMode() (client-only, never server-computed)
  • routes/+layout.server.ts returns serverRuntimeContext
  • routes/+layout.svelte initializes clientContext and derives effectiveCapabilities
  • routes/api/runtime/+server.ts — public endpoint, no auth required
  • features.admin derived alias preserved so existing code continues to work until migration completes
  • Zero if (features.admin) checks added (all new code uses hasCapability())
  • Capability matrix correct for all four host mode combinations
  • bun run ui:check 0 errors 0 warnings; existing tests pass

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions