← All frames
Flow 4 · Marketplace publish · Frame (f) · app detail (/apps/:appId)

Publish to marketplace

A Publishing panel on app detail shows the app's tier (private → organization → marketplace) and its marketplace review state from GET /apps/{slug}/publication. Private and organization are the existing visibility edit; only the marketplace step is a request a platform admin reviews. Each review state has exactly one next action.

(f1) status: none — request action available (caller has apps:write)

Publishing

organization

Visible to every member of Acme Corp. Publish to the FuzeFront marketplace to let any FuzeFront user or organization discover and install it. A platform admin reviews each request.

(f2) Request dialog — POST /apps/{slug}/publication-requests { target: marketplace, notes? }
(f3) status: pending — awaiting review; no second request possible

Publishing

In review
Requested
2 Oct 2026 by Dana Levi
Your notes
Used daily by our finance team for six months…
Tier now
organization until approved
(f4) status: approved — tier = marketplace

Publishing

marketplace
(f5) status: rejected — reason shown verbatim; resubmit allowed

Publishing

Not approved
(f6) 409 on submit — ALREADY_PENDING / ALREADY_PUBLISHED (someone acted first): refetch and show that state
(f7) Read-only — caller can view the app but lacks apps:write; GET /publication answers 404 → panel not rendered

App detail renders with no Publishing panel and no “Publish to marketplace” control — never a button that only fails on click. Same when fuzefront.apps.marketplace-publishing is OFF (503 feature_disabled, or the flag read client-side first).

(f8) 403 on submit — authority revoked since load: in place, control removed after

Data. AppPublication: tier (Visibility) drives the tier badge; status ∈ none | pending | approved | rejected drives the panel; rejection.reason is shown as text (escaped, never HTML). Names for requestedBy come from the creator/member lookup where available; otherwise the date alone is shown.
Visibility of the panel. Rendered only when the flag is ON and GET /apps/{slug}/publication returns 200 — the contract answers 404 to anyone who can merely read the app, so a 404 means “no panel”, not an error. A 409 on submit is a race, not a failure: refetch and render (f3)/(f4).
Test hooks: [data-frame='06-publish-request'] · [data-panel='app-publication'] · [data-publication-status='none'] · [data-action='request-publication'] · [data-panel='publication-request-dialog'] · [data-input='publication-notes'] · [data-action='submit-publication-request'] · [data-publication-status='pending'] · [data-publication-status='approved'] · [data-publication-status='rejected'] · [data-field='rejection-reason'] · [data-error-code='ALREADY_PENDING'] · [data-error-code='ALREADY_PUBLISHED'] · [data-state='read-only'] · [data-http='403'].

← Creator & ownershipAdmin review queue →
Review · app-builder approve or reject each flow ↓
build-entrypendingApproveReject
build-sessionpendingApproveReject
creator-ownershippendingApproveReject
marketplace-publishpendingApproveReject