Admin Tool → Content Pipeline: Gap Analysis

Updated: 2026-07-20 · Status: analysis against existing contracts, not yet a proposal

TL;DR — The mental model "the Admin tool feeds the backend JSON, and the backend consumes it to apply the theme, place the containers, and associate items into them" is partially right, but the middle step doesn't exist anywhere yet. Three pieces are already documented and (mostly) real: a client-facing read contract for an already-composed page (the Dynamic Feed), raw content sources the page can pull from (MobileContent's MenuItem/DocumentItem, plus a separate carrier/* API for Reps/Events/Committees), and the current live reality (MEC screens are still hand-coded per airline, not dynamically composed at all). The step that turns "an Admin's authoring decisions" into "a served PageDto" — which is exactly what an Admin tool would produce — is explicitly called out in the existing docs as a backend concern that hasn't been designed. This doc maps what exists, what's missing, and how it likely needs to fit together.

Contents

What already exists

Five things, each documented separately, none of them wired to an Admin-authoring layer:

PieceWhat it isStatus
Dynamic Feed contract The client-facing read shape: PageDto → ContainerDto[] → ItemDto[], fully composed, fully resolved. The client just renders it. Working Design — endpoint not yet built (AB#2133); DTO shape shipped client-side.
Theme Endpoint Flat GET /api/theme/{mecId} — one resolved 45-token map per MEC, fetched once at login. Completely decoupled from page composition. Contract documented; open items mostly resolved (route/version prefix only).
Content Endpoint (MobileContent) Raw content in two shapes — MenuItem (navigation) and DocumentItem (articles/documents). Not placed into any page structure by itself. Model confirmed; the "flattening" step into ItemDto is explicitly marked "a backend concern, out of scope for the client adapter layer."
carrier/* API (newly confirmed, not in the content contract) A third, separate content shape for Representatives, Events, and Committees — mec_cd/lec_cd-keyed, Exchange/calendar-backed for events. Confirmed live in production via network capture. Real, shipped, but not MobileContent and not part of the Dynamic Feed/Content contracts at all.
Page-composition docs Per-MEC, per-screen, Figma-derived slot breakdowns — what a developer currently hand-implements. Explicitly "not a design spec," and not Admin-tool output. Current reality: MEC screens are hand-coded per airline today, not dynamically composed by anything.

Your mental model, mapped onto it

Breaking "feed JSON → apply theme, place containers, associate items" into its three clauses and checking each against what actually exists:

"...apply the theme..."

Partially exists The Theme Endpoint is real, but only at flat per-MEC granularity — one token map per mecId, resolved once at login. The Site → Page cascade proposed in this doc set has no hook point in the shipped contract: PageDto carries no mecId, scopeKey, or themeId field at all today. Applying a Page- or LEC-level theme variation requires adding that link, not just consuming what exists.

"...place the containers..."

Structurally close, but themed differently than assumed PageDto.Containers — an ordered list, each with a ContainerType discriminator (Carousel/Grid/ButtonGroup/Stack) — is exactly the shape an Admin tool authoring "which containers, in what order" would produce. But ContainerDto.BackgroundToken/PaddingToken/CornerRadiusToken are explicitly documented as not editor-set — "the server populates them from the component-type → theme mapping." An Admin would author structure and order, not per-container theme tokens directly, which conflicts with this doc set's earlier Container/Item themeTokenOverrides proposal — see Gap 2 below.

"...and associate the items in their proper containers."

Biggest gap This requires referencing content from at least three heterogeneous sources (MobileContent MenuItem, MobileContent DocumentItem, carrier/* Reps/Events/Committees) that share no common identifier scheme, and the step that turns any of them into an ItemDto is explicitly unspecified. This is the part of your mental model with the least existing scaffolding to build on.

Gaps

Gap 1 — No admin-authoring contract exists; the Dynamic Feed is a read shape, not a write shape. Two designs are plausible and meaningfully different:

(b) is more consistent with the rest of this system's design (single source of truth per content item, resolved at serve time) but is real, undesigned work — it doesn't exist today either way.

Gap 2 — Container/Item theme tokens are explicitly not editor-set today, contradicting this doc set's earlier proposal. theme-token-inheritance.html's themeTokenOverrides assumed an Admin can set a token directly on a specific Container or Item instance. The shipped Dynamic Feed contract says the opposite: those fields come from a server-side "component-type → theme mapping," and that mapping itself isn't documented as data anywhere — it's described in prose, not as a table an Admin tool could read or write. Two ways to reconcile, not yet chosen between:
Gap 3 — PageDto has no scope/theme hook. No mecId, no scopeKey, no themeId. Theme resolution happens once per login, entirely decoupled from which page is rendering. For a Page- or LEC-level theme variation (per this doc set's core proposal) to have any effect, something needs to link a PageDto (or its future Admin-authored counterpart) to a ThemeNode.scopeKey. That link doesn't exist in the current contract.
Gap 4 — Heterogeneous content sources, no shared reference scheme. MenuItem (id/SpecialCode), DocumentItem (FileID, Scope+Category+Grouping), and carrier/* records (alpa_id, comm_cd, an Exchange calendar item id, all mec_cd/lec_cd-scoped) are three structurally different shapes on three different endpoints. An Admin composition needs a uniform way to say "this container slot holds that piece of content" regardless of which source it came from — e.g. a { sourceType, sourceId } pair — and nothing like that exists today.
Gap 5 — MEC/LEC scoping on MenuItem is explicitly unconfirmed. The MEC Customization Mock Guide states outright: "How MenuItem-level MEC-scoping actually works (if it exists at all, distinct from the carrier/* mec_cd/lec_cd pattern) remains an open question — do not build against this field until it's confirmed." This directly undercuts scopeKey values like "UAL/LEC-Denver" for anything tied to content association (as opposed to pure theme-node lookup, which stays fine as an opaque string) — the content layer itself has no confirmed MEC/LEC discriminator for MenuItem, only for carrier/* data.
Gap 6 — No versioning story for Admin-authored compositions. The Dynamic Feed contract's own Open Items list this directly: "Backend needs a last-modified timestamp per page/container to support since queries" — open, not solved. This is the content-composition analog of the modifiedAt/ThemeVersion work already done for themes in this doc set — the same pattern (a per-node modification timestamp feeding a ?since= cache-check) is needed for page composition too, and hasn't been built.
Gap 7 — Ordering and IsSortable need explicit Admin-tool support. The feed contract requires containers/items to be served pre-sorted in admin-defined order, plus a per-container/per-item IsSortable lock flag (device users may freely reorder unless locked). None of this doc set's theme docs addressed composition or ordering at all — they're theme-only. An Admin composition schema needs to capture both array order and the lock flag explicitly.
Gap 8 — The component-type → token mapping isn't documented as data. It's described in prose ("the server populates them from the component-type → theme mapping") but no doc defines what the mapping actually is (which container types get which background token, etc.). If the Admin tool is meant to let someone configure that mapping — rather than just live with a hardcoded one — that's a distinct, undesigned capability, not a gap in existing documentation.

How the pieces likely fit together

Not a final design — a shape consistent with everything found above, offered as a starting point:

  1. The Admin tool authors a lightweight Page Composition record per scope (a ThemeNode.scopeKey-equivalent, closing Gap 3): an ordered list of containers, each with a containerType, layout params, an isSortable flag, and an ordered list of item references{ sourceType, sourceId } pairs (closing Gap 4), not inlined content.
  2. This is a separate, Admin-owned data model from ContainerDto/ItemDto — not a replacement for them. At request time, a server-side resolution step (the same one already flagged as backend-TBD in the content contract) walks the composition, resolves each item reference against its real source (MenuItem, DocumentItem, or carrier/*), resolves theme tokens (via the existing component-type mapping, or a future per-instance override — Gap 2), and flattens the result into the PageDto/ContainerDto/ItemDto shape the client already knows how to render. This mirrors the Theme Endpoint's own name-vs-value separation, applied to content.
  3. Container/Item-level theme overrides, if kept at all (per Gap 2's open choice), live on the composition record's container/item entries — not on the shipped ContainerDto/ItemDto types directly — resolved at the same flattening step. No change to the already-shipped client contract is required either way.
  4. The composition record gets its own modifiedAt, following the exact pattern already adopted for themes, feeding the Dynamic Feed's still-open ?since= differential-update item (Gap 6).

Open questions to take back to backend/design

See also