Skip to content

feat: add ExO permission section on remote-mcp config screen [AIS-187]#11062

Open
Tyler Pina (tylerpina) wants to merge 14 commits into
masterfrom
ais-187-exo-config-rows
Open

feat: add ExO permission section on remote-mcp config screen [AIS-187]#11062
Tyler Pina (tylerpina) wants to merge 14 commits into
masterfrom
ais-187-exo-config-rows

Conversation

@tylerpina

@tylerpina Tyler Pina (tylerpina) commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

AIS-187

Summary

Render permission rows for the five ExO entities (Component types, Experiences, Templates, Data assemblies, Fragments) on the remote-mcp app config screen, with action whitelists matching the server side (AIS-186) verbatim.

The ExO rows live in their own "Experience orchestration actions" accordion section, with an inline note that these tools only function in ExO-compatible spaces.

Why not gate rows by space type?

The original plan was to detect ExO/classic/empty client-side (porting the server's componentType.getManycontentType.getMany probe) and hide ExO rows in classic spaces. This is not possible from within an app, and we verified it end-to-end:

  • On the config screen, sdk.cma.componentType.getMany throws "You can not access the entity type ComponentType from within an app."
  • App identities can only touch a fixed CMA entity allowlist (Asset, ContentType, EditorInterface, Entry, Locale, Release, ReleaseAction, ScheduledAction, Snapshot, Tag, Task, AppInstallation — see App Identity docs). No ExO entity types are on it. sdk.cma enforces this at the App SDK host boundary before the request ever reaches the API.
  • So the probe always failed closed → ExO rows were hidden even in genuine ExO spaces.
  • Relying on remote-mcp-server to compute disposition instead doesn't generalize either: once this app is installable from the marketplace, it can land in an ExO space without ever hitting our server.

Given that, detection is dropped. ExO rows are always rendered in their own section, and the note sets expectations. The server-side permission guard remains the real enforcement boundary — enabling an ExO permission in a non-ExO space simply has no effect.

Changes

  • Remove the client-side detector: useSpaceType hook, spaceType.ts util, and their specs.
  • Add an "Experience orchestration actions" accordion section rendering the five ExO matrices, with a neutral Note about ExO compatibility.
  • Scope the column / select-all handlers to an explicit entity list so the classic and ExO tables toggle independently; select-all state is derived per table.
  • Remove the "Migration permissions" section entirely — the server never registered migration tools (Cloudflare Workers can't do the local filesystem I/O they need) or read those params, so the fields were dead weight. Drops MigrationPermissions.tsx, the hook state/handler, and the migrateWithinSpace / migrateBetweenSpaces install parameters.

Notes

  • This app is config-screen-only (App.tsx registers only LOCATION_APP_CONFIG) — there is no auth/OAuth screen, so the "ExO rows must not appear on the auth screen" requirement holds by construction.
  • Follow-up (platform dependency): to actually detect ExO from within an app, the App SDK / App Framework team needs to add ExO entities (at minimum ComponentType read) to the app-identity CMA allowlist. This is a prerequisite for ExO-aware marketplace apps generally, and it's already directionally on the roadmap (ECO ExO Toolbar RFC; PROD Fractional PRD "Extensibility for ExO"). Until then, "always show + note" is the correct interim behavior.

Test plan

  • tsc --noEmit — only the pre-existing set-up/index.ts error (present on master), 0 new
  • vitest --run — 10/10 pass (ExO section + rows always render; migration section absent; section-scoped toggle regressions)
  • vite build succeeds
  • Reviewer: manual check that both sections render and toggles are independent

Coordination

⚠️ Do not merge until AIS-186 (remote-mcp-server, PR contentful/remote-mcp-server#89) is ready. The server defines the ExO buckets + is the enforcement boundary that makes this UI safe; this PR renders the matching rows. Merge together.

🤖 Generated with Claude Code

@tylerpina Tyler Pina (tylerpina) requested review from a team as code owners July 9, 2026 19:21
@tylerpina Tyler Pina (tylerpina) changed the title feat: gate ExO permission rows by space type on remote-mcp config screen [AIS-187] feat: add ExO permission section on remote-mcp config screen [AIS-187] Jul 9, 2026
Tyler Pina (tylerpina) and others added 14 commits July 10, 2026 13:32
…dead useCMA [AIS-187]

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…AIS-187]

Client-side ExO detection is impossible from within an app: sdk.cma blocks
reads of ExO entity types at the App SDK host boundary ("You can not access
the entity type ComponentType from within an app"), per the app-identity
entity allowlist. The probe always failed closed, hiding ExO rows even in
ExO spaces. Marketplace installs also mean we can't rely on remote-mcp-server
to compute disposition.

- Remove useSpaceType hook, spaceType util, and their specs
- Add an "Experience orchestration actions" accordion section rendering the
  five ExO entity matrices, with a Note that the tools only function in
  ExO-compatible spaces
- Scope column/select-all handlers to an explicit entity list so the classic
  and ExO tables toggle independently; derive select-all per table
- Remove the Migration permissions section (server never registered migration
  tools or read those params)
- Update tests for the new behavior

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… revert mockCma [AIS-187]

- Add EXO_ACTIONS constant (STANDARD_ACTIONS filtered to actions used by
  at least one ExO entity: read/edit/create/delete/publish/unpublish),
  dropping archive, unarchive, and invoke columns from the ExO section
- Add visibleActions prop to ContentLifecyclePermissionsTable (defaults to
  STANDARD_ACTIONS) and pass EXO_ACTIONS for the ExO table
- Fix Note top border in the ExO accordion section by adding marginTop: 12px
  to counteract the parent div's -12px marginTop
- Revert mockCma to empty object now that the componentType probe is gone

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…fields [AIS-187]

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…sionsTable

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant