Contract-freeze · UX approval · FF-EPIC-20

App Management Console · Approval Frames

The management surface FuzeFront has never had. Today the only app UI is a read-only activated-apps menu; there is no way to manage apps. These frames freeze that console: list every registered app (searchable, filterable, paginated), open one to view and edit its settings / attributes and run its lifecycle, and manage where it is installed and at what scope. Distinct from federated-apps (the add/register→activate flow) — this is the surface that runs apps after they exist. Walk each frame; approve per flow.

Flow 1 · App list · route /apps · AppManagementListFlow
Frame (a) · /apps

All applications

Searchable, filterable, paginated table/grid of every app: name, slug, lifecycle state, visibility, owning org. Row → detail.

Frame (e) · /apps

App-list states

Loading, empty, no-results, error, and read-only / permission-denied (fail-closed — no edit affordances that only 403 on save).

Flow 2 · App detail + settings/attributes · route /apps/:appId · AppDetailFlow
Frame (b) · /apps/:appId

App detail

Overview of one app + lifecycle actions (activate / suspend). Built-ins non-deletable. Tabs into settings and installations.

Frame (c) · /apps/:appId/settings

Settings & attributes

Edit display name, icon, visibility, routing/entry and config attributes. Slug immutable. Single PUT of the manifest.

Frame (f) · /apps/:appId

Detail & editor states

Read-only, suspended app (limited actions), built-in immutable, no editable settings, and save 422 / 409 / 403.

Flow 3 · Installations / scopes · route /apps/:appId/installations · AppInstallationsFlow
Frame (d) · /apps/:appId/installations

Installations & scopes

View / add / remove where an app is installed (org / portal / user) and at what scope level. Typed references, not bare ids.

Frame (g) · /apps/:appId/installations

Installation states

Loading, empty, error, read-only, orphaned target (removed/suspended portal → status, not crash), remove confirm, cross-tenant 403.

Build inventory

Approving a flow approves its component/package plan and its contract binding — implementation cannot quietly invent a different architecture. Mirrored in manifest.json → build. Approval is per flow: the list (Flow 1) can be approved and built independently of the editor (Flow 2) and installations (Flow 3).

AppManagementListFlow

route /apps · flag fuzefront.apps.management-console · approved: false
contract: @fuzefront/app-registry-client (REAL) — GET /api/v1/app-registry/apps → @fuzefront/app-management-ui
AppConsoleShellAppsToolbarAppSearchInputAppFilters AppsTableAppRowAppGridAppCard AppStateBadgeVisibilityBadgeOwningOrgCell AppsPaginationAppsEmptyStateReadOnlyNotice

AppDetailFlow

route /apps/:appId · flag fuzefront.apps.management-console · approved: false
contract: @fuzefront/app-registry-client (REAL) — GET/PUT/DELETE /apps/{slug}, POST /apps/{slug}/activate|suspend → @fuzefront/app-management-ui
AppDetailHeaderAppDetailTabsAppLifecycleActions AppSettingsFormAppIconUploaderVisibilitySelect RoutingFieldsAppAttributesEditorAttributeRow BuiltInLockNoticeSuspendAppDialogActivateAppDialogSaveBar

AppInstallationsFlow

route /apps/:appId/installations · flag fuzefront.apps.installations · approved: false
contract: @fuzefront/app-registry-client (ANTICIPATED installations surface — commissioned by these frames) → @fuzefront/app-management-ui
InstallationsTableInstallationRowScopeLevelBadge InstallationStatusBadgeAddInstallationDialogScopeTargetPicker RemoveInstallationDialogOrphanedTargetNotice

npm packages

  • @fuzefront/app-management-ui (new)
  • @fuzefront/app-registry-client (existing — consumed)

DS primitives needed

  • Tabs — detail tab strip; not in DS today
  • StatusPill — lifecycle / visibility / installation state
  • DataTable — sortable, paginated list
  • SearchInput — debounced search field
  • KeyValueEditor — attribute key/value rows
  • FileDrop — icon uploader
● Awaiting approval — per flow (Flow 1 / 2 / 3)

Design system: @fuzefront/design-system (fuse-seam, tokens only) · Epic: FF-EPIC-20 (App Management Console).
Contracts. Flows 1 & 2 bind to the real @fuzefront/app-registry-client (GET /apps, GET/PUT/DELETE /apps/{slug}, POST /apps/{slug}/activate|suspend) — the app-registry contract already exists. Flow 3 (installations / scopes) is anticipated: a per-target scoping surface (GET/POST/DELETE …/installations) not in the contract today — these frames commission it, modelled on the portal precedent's portal_apps. Every reference carries its type (targetType: organization / portal / user), never a bare id (identifier-standard).
Authz is fail-closed. A caller without the Permit scope (apps:write / apps:activate) sees read-only surfaces with no management affordances — never a control that only 403s on save. A 403 is shown in place; only a 401 re-authenticates.
DS primitives: Tabs, StatusPill, DataTable, SearchInput, KeyValueEditor, FileDrop are not in @fuzefront/design-system today — frontend-engineer (sole editor of design-system/) adds them as foundation PRs; the frames compose them from tokens only in the meantime.
Approve per-flow by setting approved: true on the flow in manifest.json, or reply @claude approve <flow> / @claude reject: <reason>.

Review · app-management approve or reject each flow ↓
app-listpendingApproveReject
app-detailpendingApproveReject
installationspendingApproveReject