Skip to content

Plugin group config in group requests#502

Open
barborico wants to merge 5 commits into
mainfrom
brynna/plugin_group_config_in_requests
Open

Plugin group config in group requests#502
barborico wants to merge 5 commits into
mainfrom
brynna/plugin_group_config_in_requests

Conversation

@barborico

@barborico barborico commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Summary

Lets users supply (and resolvers edit) app-group-lifecycle plugin group config when requesting an app group, validates it at submit and approval, and applies it to the group created on approval so the plugin's group_created hook runs against a configured group. The detail view surfaces the config under Requested/Approved details.

Urgency: 5 days
Expected review effort: MEDIUM

Motivation

App-group-lifecycle plugins can require per-group config (e.g. a Google Group plugin needs an email prefix + display name). Today that config is only collectable in the direct group-create/edit flow. When a user requests a group for such an app, there is nowhere to supply it, so approval creates the group unconfigured. This adds a generic "plugin-config-in-requests" capability.

Description of Changes

  • Model + migration: requested_plugin_data / resolved_plugin_data JSON columns on GroupRequest (JSONB on Postgres), mirroring the existing requested_*/resolved_* pairs. Config is stored in the group plugin_data shape {plugin_id: {configuration: {...}}}.
  • Create: CreateGroupRequest persists requested_plugin_data; the POST endpoint validates it against the app's plugin (400 on invalid/missing-required).
  • Approve: ApproveGroupRequest resolves resolved_plugin_data or requested_plugin_data, re-validates, and sets it on the new AppGroup before CreateGroup runs, so group_created sees the config. Invalid config → 400 via the PUT handler.
  • Resolve (PUT): accepts a resolver's resolved_plugin_data edits.
  • Frontend: the create form renders the existing plugin config form for app-group requests whose app has a plugin (fetching AppDetail via useAppById, since search summaries omit the plugin id) and submits requested_plugin_data; the detail view shows the config under Requested and Approved details (resolver-changed values as old → new); the resolver can edit before approving; the config header is hidden when a plugin declares no group fields. DOM-free helpers with unit tests. Client plugin_data fields hand-added to apiSchemas.ts (the resolved codegen renames generics across the whole client; drift-check workflow permits hand-editing). Also fixes a stale jest-dom import that blocked vitest.

Validation of Changes

  • Backend (uv run pytest): feature file + regressions 119 passed (test_group_request, test_group_request_plugin_config, test_app_group_lifecycle_plugin). uv run ruff check/ruff format clean; uv run ty check clean. Migration verified up + down; single alembic head.
  • Frontend: tsc --noEmit clean; 14 vitest unit tests pass; prettier clean.
  • Manual UI check: resolver form pre-fills the requester's submitted config.

Guidance for Reviewers

Rebased onto current main (which had moved through the async DB/Okta refactor + Okta SDK v3); the feature and its tests were ported to the async APIs, and the migration re-chained to the current head. Review commit-by-commit — five commits by layer: (1) model + migration, (2) schemas, (3) async operations + router + backend tests, (4) TS client, (5) frontend. Most worth a look: ApproveGroupRequest setting new_group.plugin_data before CreateGroup(...).execute() so the async group_created hook sees it.

🤖 Generated with Claude Code

barborico and others added 5 commits July 17, 2026 20:26
Store requester- and resolver-supplied app-group-lifecycle plugin
config on the group request, mirroring the requested_/resolved_ pair
used for every other field. Adds the alembic migration (JSONB on
Postgres) chained to the current head.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CreateGroupRequest persists requested_plugin_data; the POST endpoint
validates it against the app's lifecycle plugin (400 on invalid/missing
required). ApproveGroupRequest resolves resolved-over-requested config,
re-validates, and sets it on the AppGroup before CreateGroup runs so the
group_created hook sees a configured group; the PUT endpoint accepts a
resolver's resolved_plugin_data edits. Includes async coverage of every
path (persistence, 400, approval application, resolver override).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Hand-added rather than via codegen: the resolved @openapi-codegen
renames the paginated generics across the whole client, burying this
under unrelated churn; the drift-check workflow permits hand-editing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The create form prompts for the app's plugin group config (fetching app
detail for the plugin id, since search summaries omit it) and submits it
as requested_plugin_data; the detail view renders the config under
Requested and Approved details, showing resolver-changed values as
old -> new; and the resolver can edit config before approving. Hides the
config header when a plugin has no group fields. Adds DOM-free helpers
with unit tests and fixes a stale jest-dom import that blocked vitest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@barborico
barborico force-pushed the brynna/plugin_group_config_in_requests branch from dd025c7 to 082a071 Compare July 17, 2026 20:27
@barborico
barborico marked this pull request as ready for review July 19, 2026 02:46
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