Reintroduce houdini 2 - #528
Conversation
There was a problem hiding this comment.
Pull request overview
Reintroduces Houdini v2 across the Console frontend after a prior revert, updating generated query behavior, route typings, and UI components to match Houdini 2’s masking and “non-exhaustive” union/interface type patterns.
Changes:
- Bumps Houdini packages to stable v2 releases and updates Houdini/Vite/SvelteKit integration points (
houdini.config.js,vite.config.ts, hooks/client). - Updates many route queries and pages to use Houdini 2 caching defaults (
CacheAndNetwork), new facets shapes, and@mask_disablewhere unmasked presenter data is expected. - Refactors UI components to avoid interface-fragment pitfalls (adds shared
IssueFragment.gql, centralizes issue resource derivation, and introducesexhaustive()helper for non-exhaustive union/interface variants).
Reviewed changes
Copilot reviewed 102 out of 104 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| vite.config.ts | Ensures schema endpoint env var is available at build/runtime for Houdini schema fetching. |
| src/routes/userInfo.gql | Adds __typename to align with Houdini 2 interface/union handling. |
| src/routes/team/[team]/valkey/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/valkey/create/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/valkey/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/unleash/+page.svelte | Uses Houdini runtime GraphQLError type instead of a local copy. |
| src/routes/team/[team]/settings/service_accounts/[serviceAccountID]/token/create/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/settings/service_accounts/[serviceAccountID]/binding/add/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/settings/confirm_delete/+page.svelte | Moves QueryResult typing to houdini/runtime. |
| src/routes/team/[team]/settings/+page.svelte | Moves QueryResult typing to houdini/runtime. |
| src/routes/team/[team]/secrets/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/secrets/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/repositories/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/postgres/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/postgres/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/opensearch/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/opensearch/create/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/opensearch/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/members/AddMember.svelte | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/kafka/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/kafka/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/jobs/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/jobs/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/issues/query.gql | Reworks issues query to use facets + shared IssueFragment unmasked. |
| src/routes/team/[team]/issues/metadata.gql | Removes redundant metadata query (replaced by facets). |
| src/routes/team/[team]/issues/+page.ts | Drops metadata loader and updates Houdini input type imports. |
| src/routes/team/[team]/issues/+page.svelte | Consumes facets for filters and updates IssueType/severity handling. |
| src/routes/team/[team]/configs/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/configs/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/buckets/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/buckets/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/bigquery/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/bigquery/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/applications/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/applications/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/alerts/query.gql | Switches to facets-based filtering and expands Prometheus alert fields. |
| src/routes/team/[team]/alerts/PrometheusAlarmDetail.svelte | Moves ValueOf typing to houdini/runtime. |
| src/routes/team/[team]/alerts/metadata.gql | Removes redundant metadata query (replaced by facets). |
| src/routes/team/[team]/alerts/+page.ts | Drops metadata loader and updates Houdini input type imports. |
| src/routes/team/[team]/alerts/+page.svelte | Consumes facets and simplifies Prometheus alert rendering. |
| src/routes/team/[team]/activity-log/query.gql | Switches cache policy to CacheAndNetwork. |
| src/routes/team/[team]/activity-log/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/[env]/valkey/[valkey]/edit/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/valkey/[valkey]/edit/+page.server.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/[env]/valkey/[valkey]/delete/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/valkey/[valkey]/(single)/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/postgres/[postgres]/delete/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/opensearch/[opensearch]/edit/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/opensearch/[opensearch]/edit/+page.server.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/[env]/opensearch/[opensearch]/delete/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/opensearch/[opensearch]/(single)/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/job/[job]/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/job/[job]/logs/query.gql | Expands log destination inline fragments to satisfy Houdini 2 masking. |
| src/routes/team/[team]/[env]/job/[job]/logs/JobLogs.svelte | Uses generated $result type instead of manual prop typing. |
| src/routes/team/[team]/[env]/job/[job]/issues/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/job/[job]/issues/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/[env]/job/[job]/activity-log/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/[env]/cloudsql/[cloudsql]/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/app/[app]/utilization/query.gql | Moves shared fields into inline fragments to satisfy Houdini 2 masking. |
| src/routes/team/[team]/[env]/app/[app]/utilization/+page.svelte | Introduces exhaustive() usage and adapts to data payload shape changes. |
| src/routes/team/[team]/[env]/app/[app]/resize/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/app/[app]/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/app/[app]/logs/query.gql | Expands log destination inline fragments to satisfy Houdini 2 masking. |
| src/routes/team/[team]/[env]/app/[app]/logs/Logs.svelte | Uses generated $result typing and exhaustive() for safe iteration. |
| src/routes/team/[team]/[env]/app/[app]/issues/query.gql | Uses shared IssueFragment unmasked for issue presenters. |
| src/routes/team/[team]/[env]/app/[app]/issues/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/team/[team]/[env]/app/[app]/image/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/team/[team]/[env]/app/[app]/activity-log/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/deployments/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/admin/userSyncLog/query.gql | Refactors interface selection into inline fragments for Houdini 2. |
| src/routes/admin/userSyncLog/+page.svelte | Uses exhaustive() to iterate safely over interface/union results. |
| src/routes/admin/teams/+page.ts | Updates Houdini input type imports for v2. |
| src/routes/admin/service_accounts/[serviceAccountID]/token/create/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/admin/service_accounts/[serviceAccountID]/binding/add/+page.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/admin/+layout.svelte | Migrates route typing import to SvelteKit $types. |
| src/routes/+layout.svelte | Migrates route typing import to SvelteKit $types. |
| src/lib/utils/houdini.ts | Adds exhaustive() helper + Exhaustive<T> type for non-exhaustive variants. |
| src/lib/domain/vulnerability/SuppressFinding.svelte | Moves ValueOf typing to houdini/runtime. |
| src/lib/domain/vulnerability/BulkSuppressCVE.svelte | Moves ValueOf typing to houdini/runtime. |
| src/lib/domain/list-items/IssueListItem.svelte | Switches to unmasked presenter data + centralized issue resource mapping. |
| src/lib/domain/list-items/DeploymentWithTeamListItem.svelte | Moves ValueOf typing to houdini/runtime. |
| src/lib/domain/list-items/DeploymentListItem.svelte | Moves ValueOf typing to houdini/runtime. |
| src/lib/domain/list-items/ActivityLogListItem.svelte | Flattens type-keyed payload props for text components under Houdini 2. |
| src/lib/domain/issues/IssuesFacets.svelte | Updates facets prop shapes to include counts. |
| src/lib/domain/issues/issueResource.ts | Adds shared issue “resource” derivation and IssueDisplayData contract. |
| src/lib/domain/issues/IssueFragment.gql | Adds a shared fragment used with @mask_disable for issue presenters. |
| src/lib/domain/issues/CriticalIssuesCard.svelte | Updates issue typing to shared presenter contract. |
| src/lib/domain/issues/CriticalIssues.svelte | Switches to shared fragment and updated row component props. |
| src/lib/domain/issues/CriticalIssueRow.svelte | Refactors to shared issue resource mapping + safer link handling. |
| src/lib/domain/alerts/AlertsFacets.svelte | Updates environment facets prop shape to include counts. |
| src/lib/domain/activity/TeamActivityCard.svelte | Updates Houdini input type imports for v2. |
| src/lib/domain/activity/shared/texts/types.ts | Updates activity log entry typing model for Houdini 2 interface fragments. |
| src/lib/domain/activity/shared/texts/PostgresDeletedActivityLogEntryText.svelte | Adjusts typing to match Houdini 2 fragment data structure. |
| src/lib/domain/activity/shared/texts/DefaultText.svelte | Adjusts typing to match Houdini 2 fragment data structure. |
| src/hooks.server.ts | Reworks GraphQL request rewriting + cookie forwarding for Houdini 2 client behavior. |
| src/client.ts | Removes custom endpoint switching and tightens SSE handler typing. |
| src/app.d.ts | Extends App namespace types for GraphQL error extension codes. |
| schema.graphql | Updates generated schema content (auto-generated). |
| pnpm-workspace.yaml | Allows Houdini builds and adjusts minimum release age exclusions. |
| package.json | Updates Houdini packages and GraphQL version. |
| houdini.config.js | Adjusts Houdini v2 config (url, defaults, removes imperativeCache feature). |
| Dockerfile | Adjusts build stage base image and keeps runtime stages on alpine. |
| AGENTS.md | Documents Houdini 2 patterns (non-exhaustive variants, interface fragments, presenter strategy). |
* Improve search modal defaults * Replace team picker with global search * Polish search modal interactions * Refactor help toggle functionality in search component * Improve search modal filters * Remove search team filter on backspace * Complete search team filter with tab * Remove stale team slug label * Polish search help chips * Clarify search help team scope * Explain search team tab completion * Add favorites mode to search modal * Address search modal review comments * Update generated GraphQL schema * Clean up search token styles * Normalize generated GraphQL schema * Fix search help shortcut and favorites badges * Clarify team-scoped search * Mention favorites in search modal * Update favorites help action * Harden search shortcut parsing * Address search review follow-ups * Tighten team slug token parsing * Use declarative search shortcut binding * Avoid duplicate search input ids * Add search modal header * Mount search shortcuts only when enabled * Add team search modal header * Fix search modal query parsing * Show selected state for button search results * Use Svelte class directives for search results * Autofocus search input on modal open
* fix: improve documentation clarity for service account and team inputs * fix: enhance layout responsiveness in WorkloadImageCard component
- **Activity log**: all ten service account entry types fell back to `DefaultText` and showed the raw server message; adds text components for each. - **Broken bindings and tokens**: adds a `Missing workload` tag, fixes the method count under-reporting past the page size, and shows `Never expires`. - **Workload ↔ account links**: neither direction was navigable; adds a sidebar card on app/job pages and links binding rows to their workload. - **One account per workload**: the Add button was enabled for workloads already bound elsewhere; now a disabled `Bound to <account>`. - **Token expiry**: replaces the date picker with presets defaulting to 1 year, resolved server-side. The "Custom" option shows the date picker.
* chore: update action versions in workflows for consistency * Upgraded deps * chore: update cronstrue dependency to version 3.24.0 * Upgrade deps * Upgrade deps * Upgrade deps * chore: address dependency review feedback * style: format after prettier upgrade * refactor: update legend snippet context type for clarity * style: add spacing between cost sections * chore: remove stale release age exclusions
- Adds an activity feed to service account detail pages and team-level service account activity to the list page. - Entries name what was touched: token name in update entries, a link to the workload in binding added/removed entries. - Breadcrumbs show the account name instead of the ID.
* Improve instance group list text wrapping and columns
…sidebar mode to fix hydration mismatch warning
…on and ensure proper fragment usage
…and lint-staged to 17.2.0; adjust pnpm workspace exclusions
…dundant fields from query
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 100 out of 102 changed files in this pull request and generated no new comments.
Suppressed comments (4)
src/routes/team/[team]/settings/service_accounts/[serviceAccountID]/query.gql:12
workloadBindings { ... }is selected here and also insideServiceAccountAuthenticationFragment(seeServiceAccountAuthentications.svelte). Duplicating the same field selection can cause Houdini fragment masking/field-ownership conflicts and adds extra payload. Prefer relying on the fragment’s selection unless this page needs a different shape/args.
src/routes/admin/service_accounts/[serviceAccountID]/query.gql:12workloadBindings { ... }is selected here and also insideServiceAccountAuthenticationFragment(seeServiceAccountAuthentications.svelte). Duplicating the same field selection can cause Houdini fragment masking/field-ownership conflicts and adds extra payload. Prefer relying on the fragment’s selection unless this page needs a different shape/args.
src/routes/team/[team]/[env]/job/[job]/logs/JobLogs.svelte:4- This file now relies on Houdini 2 generated result types, which include the non-exhaustive catch-all for interface/union arrays.
team.environment.job.logDestinationsis iterated later with(logDestination.id)as the key; consider filtering withexhaustive()(like the app logs page does) to avoid type errors and future runtime issues if newLogDestinationvariants are introduced.
src/lib/utils/houdini.ts:9 exhaustive()hard-codes the non-exhaustive typename string twice and uses double quotes, which is inconsistent with the rest of the TS files. Introduce a sharedNON_EXHAUSTIVE_TYPENAMEconstant and reuse it in both the type and the predicate (also avoids typos).
type NonExhaustive = { readonly __typename: "non-exhaustive; don't match this" };
export type Exhaustive<T> = T extends NonExhaustive ? never : T;
export function exhaustive<T extends { __typename: string }>(items: readonly T[]): Exhaustive<T>[] {
… cache policy to CacheAndNetwork
CacheAndNetwork is the default policy in houdini.config.js, so explicit annotations are no-ops. Remove them to reduce noise.
The CriticalIssues component was fetching via $effect, which meant no data on first navigation and an unnecessary re-fetch cycle. Load the query in +page.ts and pass the store as a prop instead. Also fix delete alert spacing on the team overview page.
- Upgraded '@sveltejs/vite-plugin-svelte' from 7.2.0 to 7.3.0 - Updated eslint from 10.7.0 to 10.8.0 across multiple dependencies - Changed globals version from 17.7.0 to 17.8.0 - Updated '@eslint/config-helpers' from 0.6.0 to 0.7.0 - Updated 'layerchart' and 'runed' dependencies to reflect the new version of '@sveltejs/vite-plugin-svelte' - Updated 'magic-string' from 0.30.21 to 1.1.0
…#550) * chore: upgrade pnpm version to 11.21.0 in configuration and Dockerfile * upgrade deps * chore: downgrade graphql version from 17.0.2 to 16.14.2 in package.json and pnpm-lock.yaml
… node-with-deps stage
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 122 out of 124 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
src/routes/team/[team]/alerts/query.gql:50
teamEnvironment { environment { name } }is selected twice (inside the... on PrometheusAlertblock and again at the alert/interface level). This is redundant and risks masking/ownership issues in Houdini; keep the field selected in one place.
src/lib/domain/activity/ActivityTimeline.svelte:22- The timeline list is keyed by index (
(i)), which can cause DOM/state to be reused for the wrong entry if the list changes (e.g. filter change, refresh, or insertion). Since activity log entries have stable IDs, key byentry.idand reflect that in the prop typing.
{#if entries.length > 0}
{#each entries as entry, i (i)}
<ActivityLogListItem item={entry} {mode} />
{/each}
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 122 out of 124 changed files in this pull request and generated no new comments.
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
src/lib/domain/activity/ActivityTimeline.svelte:20
- Keying activity log entries by array index can cause incorrect DOM reuse when new entries are inserted or removed (e.g., live updates / pagination), leading to mismatched content or preserved UI state on the wrong entry. Since entries include
id(viaActivityLogEntryFragment), use that as the key instead ofi.
{#each entries as entry, i (i)}
src/lib/domain/list-items/IssueListItem.svelte:201
- After switching
IssueFragmentto Houdini 2's type-keyed interface fragment shape (e.g.OpenSearchIssue,ValkeyIssue, etc.), the remaining fallback checks ('openSearch' in d,'sqlInstance' in d, etc.) reference properties that are no longer part of$data. This is likely to fail type-checking and is dead/unreachable at runtime. Remove these legacy branches and keep the final default return.
if ('openSearch' in d && d.openSearch) return OpenSearchIcon;
if ('sqlInstance' in d && d.sqlInstance) return DatabaseIcon;
if ('valkey' in d && d.valkey) return ValkeyIcon;
if ('unleash' in d && d.unleash) return UnleashIcon;
if ('job' in d && d.job) return BriefcaseClockIcon;
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 122 out of 124 changed files in this pull request and generated 1 comment.
Files not reviewed (1)
- pnpm-lock.yaml: Generated file
Suppressed comments (2)
src/routes/team/[team]/alerts/+page.svelte:180
- This section assumes
alert.alarmsis always present, butalarmsis only selected inside the... on PrometheusAlertfragment in the query. If an alert node is not a Prometheus alert,alert.alarmscan beundefinedat runtime, causing errors when reading.lengthor iterating. Consider defaultingalarmsto an empty array (or guarding this entire block to Prometheus alerts only).
src/lib/domain/activity/ActivityTimeline.svelte:20 - The
{#each}block is keyed by the loop index ((i)), butentriesitems have a stableid(fromActivityLogEntryFragment). Keying by index can cause incorrect DOM reuse if items are inserted/removed/reordered (e.g. when paginating or refetching).
{#each entries as entry, i (i)}
Revert revert houdini 2 (#527)"
This reverts commit 320b248.