twenty/.github/workflows
Félix Malfait 75848ff8ea
Some checks are pending
CD deploy main / deploy-main (push) Waiting to run
CI Create App E2E minimal / changed-files-check (push) Waiting to run
CI Create App E2E minimal / create-app-e2e-minimal (push) Blocked by required conditions
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Blocked by required conditions
CI Emails / emails-test (push) Blocked by required conditions
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Blocked by required conditions
CI Example App Postcard / changed-files-check (push) Waiting to run
CI Example App Postcard / example-app-postcard (push) Blocked by required conditions
CI Example App Postcard / ci-example-app-postcard-status-check (push) Blocked by required conditions
Push translations to Crowdin / Extract and upload translations (push) Waiting to run
CI Create App / changed-files-check (push) Waiting to run
CI Create App / create-app-test (lint) (push) Blocked by required conditions
CI Create App / create-app-test (test) (push) Blocked by required conditions
CI Create App / create-app-test (typecheck) (push) Blocked by required conditions
CI Create App / ci-create-app-status-check (push) Blocked by required conditions
CI Docs / changed-files-check (push) Waiting to run
CI Docs / docs-lint (push) Blocked by required conditions
CI Emails / changed-files-check (push) Waiting to run
CI Emails / ci-emails-status-check (push) Blocked by required conditions
CI Example App Hello World / changed-files-check (push) Waiting to run
CI Example App Hello World / example-app-hello-world (push) Blocked by required conditions
feat: move admin panel to dedicated /admin-panel GraphQL endpoint (#19852)
## Summary

Splits admin-panel resolvers off the shared `/metadata` GraphQL endpoint
onto a dedicated `/admin-panel` endpoint. The backend plumbing mirrors
the existing `metadata` / `core` pattern (new scope, decorator, module,
factory), and admin types now live in their own
`generated-admin/graphql.ts` on the frontend — dropping 877 lines of
admin noise from `generated-metadata`.

## Why

- **Smaller attack surface on `/metadata`** — every authenticated user
hits that endpoint; admin ops don't belong there.
- **Independent complexity limits and monitoring** per endpoint.
- **Cleaner module boundaries** — admin is a cross-cutting concern that
doesn't match the "shared-schema configuration" meaning of `/metadata`.
- **Deploy / blast-radius isolation** — a broken admin query can't
affect `/metadata`.

Runtime behavior, auth, and authorization are unchanged — this is a
relocation, not a re-permissioning. All existing guards
(`WorkspaceAuthGuard`, `UserAuthGuard`,
`SettingsPermissionGuard(SECURITY)` at class level; `AdminPanelGuard` /
`ServerLevelImpersonateGuard` at method level) remain on
`AdminPanelResolver`.

## What changed

### Backend
- `@AdminResolver()` decorator with scope `'admin'`, naming parallels
`CoreResolver` / `MetadataResolver`.
- `AdminPanelGraphQLApiModule` + `adminPanelModuleFactory` registered at
`/admin-panel`, same Yoga hook set as the metadata factory (Sentry
tracing, error handler, introspection-disabling in prod, complexity
validation).
- Middleware chain on `/admin-panel` is identical to `/metadata`.
- `@nestjs/graphql` patch extended: `resolverSchemaScope?: 'core' |
'metadata' | 'admin'`.
- `AdminPanelResolver` class decorator swapped from
`@MetadataResolver()` to `@AdminResolver()` — no other changes.

### Frontend
- `codegen-admin.cjs` → `src/generated-admin/graphql.ts` (982 lines).
- `codegen-metadata.cjs` excludes admin paths; metadata file shrinks by
877 lines.
- `ApolloAdminProvider` / `useApolloAdminClient` follow the existing
`ApolloCoreProvider` / `useApolloCoreClient` pattern, wired inside
`AppRouterProviders` alongside the core provider.
- 37 admin consumer files migrated: imports switched to
`~/generated-admin/graphql` and `client: useApolloAdminClient()` is
passed to `useQuery` / `useMutation`.
- Three files intentionally kept on `generated-metadata` because they
consume non-admin Documents: `useHandleImpersonate.ts`,
`SettingsAdminApplicationRegistrationDangerZone.tsx`,
`SettingsAdminApplicationRegistrationGeneralToggles.tsx`.

### CI
- `ci-server.yaml` runs all three `graphql:generate` configurations and
diff-checks all three generated dirs.

## Authorization (unchanged, but audited while reviewing)

Every one of the 38 methods on `AdminPanelResolver` has a method-level
guard:
- `AdminPanelGuard` (32 methods) — requires `canAccessFullAdminPanel ===
true`
- `ServerLevelImpersonateGuard` (6 methods: user/workspace lookup + chat
thread views) — requires `canImpersonate === true`

On top of the class-level guards above. No resolver method is accessible
without these flags + `SECURITY` permission in the workspace.

## Test plan

- [ ] Dev server boots; `/graphql`, `/metadata`, `/admin-panel` all
mapped as separate GraphQL routes (confirmed locally during
development).
- [ ] `nx typecheck twenty-server` passes.
- [ ] `nx typecheck twenty-front` passes.
- [ ] `nx lint:diff-with-main twenty-server` and `twenty-front` both
clean.
- [ ] Manual smoke test: log in with a user who has
`canAccessFullAdminPanel=true`, open the admin panel at
`/settings/admin-panel`, verify each tab loads (General, Health, Config
variables, AI, Apps, Workspace details, User details, chat threads).
- [ ] Manual smoke test: log in with a user who has
`canImpersonate=false` and `canAccessFullAdminPanel=false`, hit
`/admin-panel` directly with a raw GraphQL request, confirm permission
error on every operation.
- [ ] Production deploy note: reverse proxy / ingress must route the new
`/admin-panel` path to the Nest server. If the proxy has an explicit
allowlist, infra change required before cutover.

## Follow-ups (out of scope here)

- Consider cutting over the three
`SettingsAdminApplicationRegistration*` components to admin-scope
versions of the app-registration operations so the admin page is fully
on the admin endpoint.
- The `renderGraphiQL` double-assignment in
`admin-panel.module-factory.ts` is copied from
`metadata.module-factory.ts` — worth cleaning up in both.
2026-04-19 20:55:10 +02:00
..
cd-deploy-main.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
cd-deploy-tag.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
changed-files.yaml Migrate from ESLint to OxLint (#18443) 2026-03-06 01:03:50 +01:00
ci-ai-catalog-sync.yaml chore: trigger automerge for AI catalog sync PRs (#18855) 2026-03-23 13:33:19 +01:00
ci-breaking-changes.yaml Flush Redis between server runs in breaking changes CI (#19491) 2026-04-09 12:56:24 +02:00
ci-create-app-e2e-hello-world.yaml Add application-logs module with driver pattern for logic function log persistence (#19486) 2026-04-09 14:35:24 +00:00
ci-create-app-e2e-minimal.yaml Add application-logs module with driver pattern for logic function log persistence (#19486) 2026-04-09 14:35:24 +00:00
ci-create-app-e2e-postcard.yaml Add application-logs module with driver pattern for logic function log persistence (#19486) 2026-04-09 14:35:24 +00:00
ci-create-app.yaml Migrate from ESLint to OxLint (#18443) 2026-03-06 01:03:50 +01:00
ci-docs.yaml Migrate from ESLint to OxLint (#18443) 2026-03-06 01:03:50 +01:00
ci-emails.yaml Re-enable disabled lint rules and right-size CI runners (#18461) 2026-03-06 13:33:02 +00:00
ci-example-app-hello-world.yaml Add application-logs module with driver pattern for logic function log persistence (#19486) 2026-04-09 14:35:24 +00:00
ci-example-app-postcard.yaml Add application-logs module with driver pattern for logic function log persistence (#19486) 2026-04-09 14:35:24 +00:00
ci-front-component-renderer.yaml [SDK] Extract twenty-front-component-renderer outside of twenty-sdk ( 2.8MB ) (#19021) 2026-03-30 17:06:06 +00:00
ci-front.yaml feat: Send email from UI — inline reply composer & SendEmail mutation (#19363) 2026-04-07 08:43:48 +02:00
ci-merge-queue.yaml Replace twentycrm/twenty-postgres-spilo with official postgres:16 in CI (#19182) 2026-03-31 21:41:42 +02:00
ci-release-create.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
ci-release-merge.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
ci-sdk.yaml Fix sdk-e2e-test: ensure DB is ready before server starts (#19583) 2026-04-11 16:02:12 +02:00
ci-server.yaml feat: move admin panel to dedicated /admin-panel GraphQL endpoint (#19852) 2026-04-19 20:55:10 +02:00
ci-shared.yaml Re-enable disabled lint rules and right-size CI runners (#18461) 2026-03-06 13:33:02 +00:00
ci-test-docker-compose.yaml Improve getting started doc (#19138) 2026-04-01 20:39:44 +00:00
ci-ui.yaml Fix visual regression dispatch for fork PRs (#18921) 2026-03-24 18:13:00 +01:00
ci-utils.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
ci-website.yaml Replace twentycrm/twenty-postgres-spilo with official postgres:16 in CI (#19182) 2026-03-31 21:41:42 +02:00
ci-zapier.yaml Deprecate IS_RECORD_TABLE_WIDGET_ENABLED feature flag (#19662) 2026-04-13 21:13:15 +00:00
claude.yml Migrate from ESLint to OxLint (#18443) 2026-03-06 01:03:50 +01:00
docs-i18n-pull.yaml chore: improve i18n workflow to prevent stale compiled translations (#18850) 2026-03-23 12:53:31 +01:00
docs-i18n-push.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
i18n-pull.yaml chore: improve i18n workflow to prevent stale compiled translations (#18850) 2026-03-23 12:53:31 +01:00
i18n-push.yaml chore: improve i18n workflow to prevent stale compiled translations (#18850) 2026-03-23 12:53:31 +01:00
post-ci-comments.yaml Harden GitHub Actions: fix injections, isolate privileged operations to ci-privileged repo (#18318) 2026-03-02 10:57:14 +01:00
preview-env-dispatch.yaml Migrate CI runners from Depot back to GitHub-hosted runners (#18347) 2026-03-03 14:14:27 +01:00
preview-env-keepalive.yaml fix: invalidate rolesPermissions cache + add Docker Hub auth to CI (#19044) 2026-03-27 17:32:53 +01:00
visual-regression-dispatch.yaml Fix visual regression dispatch for fork PRs (#18921) 2026-03-24 18:13:00 +01:00