Read legacy entry-experience inventory
Read one accessible app’s legacy login and landing presentation, selected draft and migration conflicts.
Action and scope
app_topolo_developers.apps.experience.inventory — GET /api/developer-console/apps/{appId}/experience/inventory. Required permission: app_topolo_developers.apps:read. Authorization mode: static; no platform principal or allowed-service override is declared.
Before using this action
Use the original authenticated organization, accessible Developers workspace and current action permission. Discover the canonical owning app, bind the workspace separately and compare the returned appId. An app identifier, static permission or canWrite projection alone is not an authorization grant.
Shared workspace context requires the app/workspace match and current app access. Reads permit a suspended profile but not revoked access; writes require app.canEdit and a writable profile. These routes do not require completed onboarding. Shared context can initialize a local workspace mirror and developer profile before a later refusal; it does not mint a canonical Auth workspace.
Use the current declared schema and actual actor policy before any authorized call. All examples use fictional identifiers, synthetic state and UNRUN outcomes; they are not receipts, evidence of deployment, a current private app read or a running login/landing UI check.
Requires app_topolo_developers.apps:read and current app.canRead. No acceptance or publication input is part of this read.
The declared execution mode is automatic for inventory and confirmation-required for import/publish. Confirmation and current authorization must be evaluated for the selected action; these offline examples do not approve a mutation.
Inputs
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"appId": {
"type": "string",
"minLength": 1
}
},
"required": [
"appId"
],
"additionalProperties": false
}
Behavior and response
GET /api/developer-console/apps/{appId}/experience/inventory delegates an empty body to the authenticated Developers-to-Auth inventory service. The selected receiver reads login_config and landing_config concurrently. It performs no authoring save, policy update or catalog publication. The imported service guard is required; its transitive implementation was not re-audited here.
Successful HTTP200 is the raw Auth JSON body {success,appId,draft,legacy,conflicts,policy}; it has no Developers message/data wrapper. If the upstream response is not HTTP-success with success:true, Developers forwards the parsed raw body with HTTP503. This is distinct from ordinary console access errors.
The draft selects login.layout, background_type, background_gradient_start, background_gradient_end, background_image_url, background_video_url and background_animation; landing selects background_gradient_start, background_gradient_end, show_topolo_one, pricing_enabled and is_enabled. Null or absent fields are omitted. For non-null landing booleans, only stored integer 1 becomes true; every other non-null value becomes false.
Legacy fields outside each surface allowlist become conflicts with resolution catalog_product_marketing_wins. Only custom_css, custom_head_html, pricing_tiers, footer_links and legal_links set requiresReview:true; false is not proof that an unrecognized field is safe. The legacy object omits id, app_id, created_at, updated_at, allowed_providers, authenticated_home_path and magic_link_delivery_mode. Excluded policy fields are not returned or changed.
Both missing rows produce empty login/landing objects, an empty conflicts array and the policy statement. Inventory reads legacy configuration; it does not return saved authoring state or prove the current catalog or running UI. The Auth receiver requires a canonical app_ identifier matching its lowercase multi-segment pattern, beyond the action input’s nonempty-string constraint.
Errors and recovery
HTTP503 — Upstream Auth HTTP400: receiver returns {error:"Canonical app ID required"}; this selected Developers proxy exposes that raw body as HTTP503, not HTTP400. Preserve the original response; discover the correct canonical app instead of guessing aliases.
HTTP503 — Upstream denial, incomplete read or unavailable inventory is not an empty inventory. Do not import or infer no legacy policy; preserve actual status/body and use the original source owner.
HTTP401 — Restore the original authorized identity.
HTTP403 — Check actual organization/workspace/app access; do not expand scope.
Error code labels in the typed layer are explanatory classifications unless explicitly present in the actual response. Shared authentication, permission, validation and rate-limit refusals may occur before these branches. Ordinary console errors use an error object; inventory forwards raw Auth errors; publication partial-failure responses can use an error string with data.state.
Verification
Retain the original organization/workspace, actual canonical appId, action inputs, status/error and request identifier. Never substitute a fixture identifier, revision, attempt or digest for actual read-back.
The captured output schema is structural and open. The detailed source shapes below explain reviewed branches without replacing the published schema or guaranteeing that every response has every illustrated field.
Compare raw appId, both selected draft surfaces, both legacy surfaces, every conflict and the policy statement. Review legacy material before import; requiresReview:false does not grant import or publication authority.
Recovery
No selected inventory mutation to undo. Preserve shared initialization and dependency uncertainty separately. No import, reset, policy change or publication is automatic recovery.
Synthetic examples — UNRUN
Legacy custom CSS remains a review conflict
Complete source-derived synthetic UNRUN HTTP200. Fictional login row contains layout and custom_css; landing row has is_enabled=1. Excluded policy fields, if present, are not projected.
Input:
{
"appId": "app_docs_fixture"
}
Output:
{
"success": true,
"appId": "app_docs_fixture",
"draft": {
"login": {
"layout": "centered"
},
"landing": {
"is_enabled": true
}
},
"legacy": {
"login": {
"layout": "centered",
"custom_css": ".fixture {}"
},
"landing": {
"is_enabled": 1
}
},
"conflicts": [
{
"surface": "login",
"field": "custom_css",
"resolution": "catalog_product_marketing_wins",
"requiresReview": true
}
],
"policy": "Auth provider and access policy is excluded and preserved."
}
Review the conflict; no draft has been saved.
No legacy rows
Complete source-derived synthetic UNRUN HTTP200. Both fictional SELECT results are absent.
Input:
{
"appId": "app_docs_fixture"
}
Output:
{
"success": true,
"appId": "app_docs_fixture",
"draft": {
"login": {},
"landing": {}
},
"legacy": {
"login": {},
"landing": {}
},
"conflicts": [],
"policy": "Auth provider and access policy is excluded and preserved."
}
Empty selected and legacy surfaces do not establish absence of Auth policy.
Canonical identifier refused by the receiver
Complete source-derived synthetic UNRUN HTTP503. Conditional fixture: an accessible stored app resolves to the noncanonical id invalid and reaches the receiver. This is a proxy mapping example, not proof that such a record exists.
Input:
{
"appId": "invalid"
}
Output:
{
"error": "Canonical app ID required"
}
Do not interpret HTTP503 as an empty inventory or retry with invented ids.
Source provenance and limits
Reviewed 2026-10-23 against immutable Developers source 7b89bd3b39092cdc29f87540847bf99a243f0a40 and retained production declarations. The inventory receiver is independently pinned to Auth e2ea647f225b1842f629aa74f732fbfb6601b3e3. Declaration/source association is not evidence that either revision is serving or that the cross-service pair is deployed together.
The documented application action and examples were not executed for this guide. No private app, Auth inventory, provider, signup/login or runtime UI was accessed. Source imports, tests and builds were not run. Shared prerequisites reuse the accepted source qualification for experience.get/update; transitive service implementations beyond the listed boundaries were not audited.
Automatic Knowledge invocation during relevant builds has not been verified; its reliability remains UNKNOWN. Manual documentation review does not establish automatic build integration.
Change log
- 2026-10-23: Added and published this guide with source-qualified behavior and synthetic, unrun examples. This is a documentation change; no application behavior change is asserted.