Repository navigation
feat(plugins): add tenant plugin platform and Projects Gantt - #3931
Merged
Merged
Conversation
Add a versioned, tenant-scoped plugin platform and its first plugin, Projects, for planning tenant work on a timeline. Backend: - sequent-plugin-api: the versioned contract (Manifest, Plugin, scoped RecordStore/Audit/Clock ports, stable errors, HistoryScope). - sequent-plugin-host: compiled-in registry, per-operation permissions, lifecycle with role provisioning before commit, PostgreSQL adapter bound to the verified tenant and plugin, optimistic versions, append-only history with the parent at write time. - sequent-plugin-projects: projects and tasks, RFC 4180 CSV preview, atomic import and spreadsheet-safe export, project and task history that keeps deleted tasks. - Harvest gateway (/plugins, /plugins/state, /plugins/execute) behind three Hasura actions; plugin tables are not tracked by Hasura. - projects-read/write/manage permissions in sequent-core, the Admin Portal and the default tenant realm. Admin Portal: - Plugin host: provider, lazy routes, menu items after Templates, a Settings > Plugins tab appended after the existing tabs. - Projects: list, create, import and export; a full-width timeline with hover and focus previews; details and editing below the timeline; keyboard, pointer and touch moves; unsaved-edit, conflict and in-flight-write handling; viewer read-only mode. - A data router so screens can hold navigation with unsaved changes. - Translations in all portal languages, stories and tests. Docs for plugin authors and tenant administrators. Parent issue: sequentech/meta#14274 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review: 2
Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
|
- Regenerate the committed sequent-core WASM package and its yarn.lock entries with `step-dev wasm --release-package`: it embeds the realm template and permission sources this branch changed. - Format hasura/metadata/actions.graphql with the hasura package's Prettier. - Log plugin changes in the tenant's admin audit log: the gateway names the admin with audit::act_for and the plugin tables carry the audit_change trigger. - Check the operation's permission, or tenant-write, before the gateway contacts any backend, and pin both plugin routes in the guarded-route inventory and route-permission cases. - Give every plugin widget its Storybook section (PluginRoute, PluginMenu, PluginSettings, Projects, ProjectView, Timeline, TaskEditor, History, ImportProject); exclude the non-visual provider, guard and app root with their reasons. - The import dialog's file chooser is a real button for a labelled, hidden file input. Parent issue: sequentech/meta#14274 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
- Route tests for the plugin gateway against the migrated test database: turning Projects on provisions its roles in Keycloak and commits, every change is an AdminChange entry of the tenant's log, a Keycloak failure leaves Projects off and unlogged, and operations are refused while off, versioned, and refused without their permission. - The production journeys answer TenantPlugins with Projects turned off, expect the Settings > Plugins tab after Previews, and smoke-test the plugin route. Parent issue: sequentech/meta#14274 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
…ng tenant-write The card printed a literal "API" and "· admin" although plugins.api and plugins.adminGroup are translated in every language, and administrators without tenant-write saw a disabled button with no reason. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
The portal compiles to ES5, where an Error subclass loses its prototype, so `instanceof PluginRequestError` was always false in production: a stale save showed the raw message instead of the conflict view with "Load their version", and every coded plugin error became generic. Storybook compiles natively, which hid it. Found in the real-stack acceptance run. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
…roject in the URL Both found by the real-stack acceptance run, where tokens carry Keycloak user IDs and the portal is reloaded: - History, "Last change" and the conflict notice showed the actor's user ID. Records and history now also store the username at the time of the change (updated_by_name, actor_name), taken from the verified token; the stable ID stays the actor. The columns join the plugin migration, which has not been released. - The open project lived only in component state, so a reload or a link returned to the list. Under the plugin route it is now /plugins/projects/<id>. Discarding changes to go back waits for the discarded draft to render, so the navigation guard does not ask twice. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
Screen, RoutedProjects and LocalProjects only choose between the list and a project; the Projects and PluginRoute stories render them. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0129Cs8ygVE7UH6N1XzXk8WP
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Parent issue: https://github.com/sequentech/meta/issues/14274
Adds a tenant plugin platform with Projects as its first bundled plugin. Tenant administrators can enable it in Settings → Plugins, then create independent project timelines, edit tasks beneath the timeline, and import or export CSV plans.
The backend exposes versioned ports for records, history, and time. Harvest derives tenant and actor from the verified token, checks each operation's permission and the tenant's enablement, and scopes storage to that tenant and plugin. Enabling provisions realm permissions before committing; disabling retains records, roles, and history. Three new tables remain untracked by Hasura and are accessed through three authenticated actions. Planning operations do not modify election schedules or state. The gateway checks each operation's permission, or
tenant-writefor a state change, before contacting any backend, and every plugin change is also anAdminChangeentry in the tenant's audit log throughaudit::act_forand theaudit_changetrigger.The Admin Portal loads Projects as a lazy contribution after Templates. The timeline fills the content width, supports keyboard, pointer, and touch interaction, and keeps details/editing below it. The implementation includes project timezones, milestones, task versions and explicit conflict recovery, unsaved-edit navigation guards, read-only access, archive/restore, and history that retains deleted tasks. CSV imports preview row errors and atomically create a new project; exports round-trip safely through spreadsheets. All portal translations and developer/admin documentation are included.
Validation ran in the isolated Felix3 worktree:
sequent-corerealm permission testsstories:inventory --checkexits 0hasura/Prettier), ESLint, REUSEsequent-coreWASM packagestep-dev wasm --release-package;--check-packageexits 0Browser checks render the actual portal components with schema-validated GraphQL fixtures. Regression coverage includes rapid task moves, pending writes, focus preservation, unsaved navigation, timezone gaps/ambiguities, and phone overflow.
The full Admin Portal Jest run passes 2,275 of 2,282 tests. The same seven failures reproduce on the untouched base in six suites:
buildEnvironment,ImportScreen,signingSettings,ImportFileSelection,Password, andtransmissionPackage. The main TypeScript check reports the same 511 errors in the same files on the base with this fresh dependency install, including unbuilt workspace packages; this change adds none.The migration, Hasura metadata, Harvest, and portal changes ship together. Bundled plugins start disabled for each tenant; enabling Projects is a tenant administrator action.
CI follow-ups:
286ff90fa7regenerates the committed WASM package, formats the Hasura action types, logs plugin changes in the admin audit, authorizes before any backend, and gives every plugin widget its Storybook section;929563dbc2adds the gateway route tests that keep Harvest coverage from decreasing and updates the production journeys for the plugin query, the appended Settings tab, and the plugin route. At929563dbc2, all 107 checks pass (3 skipped), including the Backend E2E journeys.