Skip to content

Let admin components run administration flows and lifecycle actions - #141

Merged
brionmario merged 1 commit into
thunder-id:mainfrom
brionmario:feat-admin-components-flow-mode
Oct 28, 2026
Merged

brionmario merged 1 commit into
thunder-id:mainfrom
brionmario:feat-admin-components-flow-mode

Conversation

@brionmario

@brionmario brionmario commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Purpose

The admin components call the management API directly. An app that cleans up runtime state through the server's administration flows (revoking grants and ending sessions before a record changes), such as the ThunderID Admin App, could not use them. They also had no way to suspend, unsuspend or unlock an identity, which only work through flows.

Approach

  • administrationMode (default 'native') on UserDetails, GroupMembers, RoleAssignments and ApplicationDetails. It is passed to the operations that already accept it: user deletion, group member removal, role assignment removal, and application deletion and client secret regeneration. AgentDetails has no such prop because deleteAgent has no flow.
  • lifecycleActions (default false) on UserDetails, AgentDetails and ApplicationDetails. When it is on:
    • The component reads the configured flows (/server-config/flow, /flows). It reads them only then.
    • It offers the actions the record's status allows (ACTIVE → suspend; LOCKED → unlock, suspend; SUSPENDED → unsuspend) whose flow is configured. Applications are never locked.
    • Suspend and unsuspend confirm inline, and a suspension of a user or an agent takes an optional operator note (up to 100 characters). Unlock runs straight away.
    • The record and its list are refetched afterwards.
  • Errors: a failed read of the configured flows shows admin.common.lifecycle.load_error, and a failed action shows admin.common.lifecycle.error.
  • Base variants and custom renders receive lifecycleActions, onLifecycleAction and isRunningLifecycleAction. Lifecycle actions change only runtime state, so they apply to read-only records too.
  • Status label: the access status shows as a translated label, next to the organization unit for users and as a Status row for agents and applications.
  • Core (@thunderid/javascript, re-exported through browser, react and vue):
    • the AccessStatus model on ManagedUser and Agent
    • AccountLifecycleAction, AccountLifecycleSubjectKind and AccountLifecycleFlowConfigKey
    • getAccountLifecycleActions(kind, status, configuredFlows)
    • runAccountLifecycleAction({action, kind, subject, operatorNote}), which dispatches to the existing suspendUser, unlockAgent and similar functions so each keeps its own error codes
    • new admin.common.status.*, admin.common.lifecycle.* and admin.common.columns.status strings in every bundled locale
  • Frameworks: React and Vue both implement this. Next.js and Nuxt wrap them.
  • Playgrounds: the React and Vue UserDetails stories gain lifecycleActions, status and administrationMode controls, plus "Suspended" and "Live through administration flows" stories.

Known limit: the Next.js/Nuxt management relay doesn't forward /flow/execute, so administrationMode: 'flow' and the lifecycle actions don't work through the relay yet. The same is true of the flow-mode API functions released earlier. Opening the relay to flow execution needs its own security review, so it is out of scope here.

Related Issues

Related PRs

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (TSDoc on the new props and functions, and playground stories)
  • Tests provided.
    • Unit Tests: core getAccountLifecycleActions and runAccountLifecycleAction (17), React and Vue admin components (10 each)
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.
  • Cross-SDK parity. Exactly one of parity/prs-raised or parity/prs-not-needed added.
    • If parity/prs-raised, the port links are posted as a reply on the parity check's comment.

Security checks

  • Followed secure coding standards.
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown

🔀 Cross-SDK feature parity, ports raised

This pull request is labelled parity/prs-raised, so the capability it introduces is expected in the other ThunderID SDKs as well.

Ports (DO NOT EDIT)

  • thunder-id/ios-sdks, iOS => #36
  • thunder-id/android-sdks, Android => #44
  • thunder-id/flutter-sdks, Flutter => #57

3 of 3 sibling SDKs accounted for.

Every sibling SDK is accounted for.

The contract is in the SDK development specification.

The admin components called the management API directly, so an app that
cleans up runtime state through administration flows (revoking grants and
ending sessions) could not use them, and they had no way to suspend,
unsuspend or unlock an identity.

- `administrationMode` prop (default `native`) on UserDetails,
  GroupMembers, RoleAssignments and ApplicationDetails, passed to the
  delete, member removal, assignment removal and secret regeneration calls.
- `lifecycleActions` prop on UserDetails, AgentDetails and
  ApplicationDetails. When on, the component reads the configured flows and
  offers only the actions the identity's status allows and whose flow is
  configured. Suspend and unsuspend confirm inline, a suspension of a user
  or agent takes an optional operator note, and unlock runs straight away.
  The Base variants and custom renders get `lifecycleActions`,
  `onLifecycleAction` and `isRunningLifecycleAction`.
- The access status is typed on users and agents (`AccessStatus`) and
  shown as a translated label.
- Core: `getAccountLifecycleActions`, `runAccountLifecycleAction` and
  `AccountLifecycleFlowConfigKey`, shared by React and Vue; new strings in
  every bundled locale.
- React and Vue ports, with tests, and playground controls for the
  UserDetails story.

Signed-off-by: Brion <info@brionmario.com>
@brionmario

Copy link
Copy Markdown
Member Author

@brionmario
brionmario merged commit e5b7864 into thunder-id:main Oct 28, 2026
8 of 10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

parity/prs-raised Ports exist in the other SDKs, or are recorded as not applying there

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants