Files
twenty/packages
Félix Malfait 72e2301697 fix(settings): unbreak the AI tools table and validate page-level graphql documents (#23731)
## Problem

Opening Settings > AI (tools tab) fails with a misleading error:

```
{"errors":[{"message":"App version mismatch.","extensions":{"code":"APP_VERSION_MISMATCH"}}]}
```

The real error is a GraphQL validation failure. Both queries on that
page select a `logo` field that no longer exists:

- `FindManyApplicationsForToolTable` selects `Application.logo`
- `FindManyMarketplaceAppsForToolTable` selects `MarketplaceApp.logo`

#23411 renamed `MarketplaceApp.logo` to `logoUrl` and stopped exposing
`logo` on `Application`, but missed these two queries (added in #21121)
and the types/component behind them. So the schema exposes `logoUrl`
while the AI settings page still asks for `logo`.

The reason the error says "App version mismatch" is that
`useGraphQLErrorHandlerHook.onValidate` does not return validation
errors as-is: when a document fails validation and the request's
`x-app-version` is semver-lower than the server's `APP_VERSION`, it
throws `APP_VERSION_MISMATCH` instead. On an instance where the frontend
build trails the backend, every genuine query bug on that instance
surfaces as this message, and refreshing never helps because the query
is wrong in the code.

## Why nothing caught it

Two gaps lined up:

1. **The documents were invisible to codegen.** `codegen-metadata.cjs`
lists documents as an explicit allow-list of
`./src/modules/*/graphql/**` entries; nothing under `./src/pages/**` was
ever in it. Codegen validates every matched document against the live
schema and CI fails on drift, so the rename would have been caught had
these two queries been in the matched set.
2. **The response types were hand-written.**
`SettingsAgentToolApplication` / `SettingsAgentToolMarketplaceApp` were
free-standing object types declaring `logo?: string | null`, passed as
the `useQuery` generic. Nothing tied them to the schema, so they kept
compiling after the field was gone.

## Changes

Fix:

- Select `logoUrl` instead of `logo` in
`findManyApplicationsForToolTable` and
`findManyMarketplaceAppsForToolTable`.

Prevention:

- Add `./src/pages/**/graphql/**/*.{ts,tsx}` to `codegen-metadata.cjs`,
so page-level documents are validated by the CI codegen check and get
generated operation types.
- Add three more previously-unvalidated metadata modules to the same
list: `metadata-store`, `sse-db-event`, `geo-map`.
- Derive `SettingsAgentToolApplication` /
`SettingsAgentToolMarketplaceApp` from the generated operation types
instead of hand-writing them.
- Type `SettingsToolIcon`'s `ApplicationInfo` / `MarketplaceAppInfo` as
`Pick` of those, so a field disappearing from the schema is a compile
error rather than a silently-optional property.
- Regenerate `generated-metadata/graphql.ts` (additive: operation types
+ typed document nodes for the five newly covered documents).

App logos in the tools table also render again, which they hadn't since
#23411.

## Verification

Swept every file containing a `gql` document in twenty-front (484)
against the document globs of all three codegen configs. 65 are
uncovered, most legitimately so (runtime-generated record queries,
mocks, tests, stories). The static documents no config validated were
the two fixed here (broken), `metadata-store` / `sse-db-event` /
`geo-map` (valid, now covered), and `information-banner` /
`settings/legal` (valid, core schema — left alone since `codegen.cjs`
targets a schema that can't be validated offline; worth a follow-up).

Validated the fixed documents against the checked-in metadata SDL, and
reproduced `generated-metadata/graphql.ts` with the pinned codegen
toolchain to confirm the regenerated file matches what CI produces. CI's
own codegen check (`server-validation`) then confirmed it against a live
server, alongside front typecheck, lint, jest and builds.

## Follow-up, not in this PR

The error masking in `use-graphql-error-handler.hook.ts` is worth
revisiting:

- It discards the original validation errors, so a real query bug is
unreportable on any deployment where the frontend trails the backend.
Attaching the underlying errors (or at least logging them) would have
made this a one-minute diagnosis.
- The `x-schema-version` branch above it is dead: no client in the repo
sends that header.

---
_Generated by [Claude
Code](https://claude.ai/code/session_01FuH2fAvLct7NvTUEnAWPSV)_
2026-08-04 13:54:04 +02:00
..