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.
Searchable, filterable, paginated table/grid of every app: name, slug, lifecycle state, visibility, owning org. Row → detail.
Loading, empty, no-results, error, and read-only / permission-denied (fail-closed — no edit affordances that only 403 on save).
Overview of one app + lifecycle actions (activate / suspend). Built-ins non-deletable. Tabs into settings and installations.
Edit display name, icon, visibility, routing/entry and config attributes. Slug immutable. Single PUT of the manifest.
Read-only, suspended app (limited actions), built-in immutable, no editable settings, and save 422 / 409 / 403.
View / add / remove where an app is installed (org / portal / user) and at what scope level. Typed references, not bare ids.
Loading, empty, error, read-only, orphaned target (removed/suspended portal → status, not crash), remove confirm, cross-tenant 403.
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).
AppManagementListFlowAppConsoleShellAppsToolbarAppSearchInputAppFilters
AppsTableAppRowAppGridAppCard
AppStateBadgeVisibilityBadgeOwningOrgCell
AppsPaginationAppsEmptyStateReadOnlyNotice
AppDetailFlowAppDetailHeaderAppDetailTabsAppLifecycleActions
AppSettingsFormAppIconUploaderVisibilitySelect
RoutingFieldsAppAttributesEditorAttributeRow
BuiltInLockNoticeSuspendAppDialogActivateAppDialogSaveBar
AppInstallationsFlowInstallationsTableInstallationRowScopeLevelBadge
InstallationStatusBadgeAddInstallationDialogScopeTargetPicker
RemoveInstallationDialogOrphanedTargetNotice
@fuzefront/app-management-ui (new)@fuzefront/app-registry-client (existing — consumed)Tabs — detail tab strip; not in DS todayStatusPill — lifecycle / visibility / installation stateDataTable — sortable, paginated listSearchInput — debounced search fieldKeyValueEditor — attribute key/value rowsFileDrop — icon uploader
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>.