Contract. The header + overview bind to GET /api/v1/app-registry/apps/{slug}
(the AppManifest). Lifecycle actions are state-driven: an activated app
shows Suspend (POST /apps/{slug}/suspend); a registered or
suspended app shows Activate (POST /apps/{slug}/activate) — never both.
Requires the apps:activate scope; a caller without it sees the buttons
read-only/absent (fail-closed, frame f). Edit settings → frame (c). Built-in apps
(builtin: true) hide Delete entirely — the slug, builtin flag and manifest core are
immutable on PUT. Health derives from GET /apps/{slug}/heartbeat.