fix(web): resolve fragment masking type warnings in routes and auth

Quentin Gliech and Claude Opus 4.6 (1M context) created

- Select fields directly alongside fragment spreads in route queries
  so they're accessible without unmasking (BugSummary, IdentitySummary,
  LabelFields in bug list, bug detail, and user profile queries).
- Fix useAuth query to spread ...IdentitySummary with direct field
  selections instead of @unmask (preserves $fragmentRefs brand).
- Fix StatusFilter | null type in applyFilters.
- Fix CommentData type to union of create + add-comment fragments.

Lint warnings: 148 → 33 (remaining are oxlint limitations with
makeFragmentData generics in stories + eslint unsafe assertions in
file-viewer).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Change summary

webui2/src/__generated__/gql.ts                  |  5 +--
webui2/src/__generated__/graphql.ts              | 23 ++++++++++++++---
webui2/src/components/bugs/timeline.tsx          |  2 
webui2/src/routes/$repo/_issues/issues/$id.tsx   | 10 +++++++
webui2/src/routes/$repo/_issues/issues/index.tsx | 10 +++++++
webui2/src/routes/$repo/_issues/user/$id.tsx     |  8 ++++++
6 files changed, 49 insertions(+), 9 deletions(-)

Detailed changes

webui2/src/__generated__/gql.ts 🔗

@@ -43,10 +43,10 @@ type Documents = {
     "\n  query CodePageReadme($repo: String, $ref: String!, $path: String!) {\n    repository(ref: $repo) {\n      blob(ref: $ref, path: $path) {\n        text\n      }\n    }\n  }\n": typeof types.CodePageReadmeDocument,
     "\n  query AllIdentities($ref: String) {\n    repository(ref: $ref) {\n      allIdentities(first: 1000) {\n        nodes {\n          id\n          humanId\n          name\n          email\n          login\n          displayName\n          avatarUrl\n        }\n      }\n    }\n  }\n": typeof types.AllIdentitiesDocument,
     "\n  query ValidLabels($ref: String) {\n    repository(ref: $ref) {\n      validLabels {\n        nodes {\n          name\n          color {\n            R\n            G\n            B\n          }\n          ...LabelFields\n        }\n      }\n    }\n  }\n": typeof types.ValidLabelsDocument,
-    "\n  query BugDetail($ref: String, $prefix: String!) {\n    repository(ref: $ref) {\n      bug(prefix: $prefix) {\n        ...BugSummary\n        lastEdit\n        participants(first: 20) {\n          nodes {\n            ...IdentitySummary\n          }\n        }\n        timeline(first: 250) {\n          ...TimelineItems\n        }\n      }\n    }\n  }\n": typeof types.BugDetailDocument,
-    "\n  query BugList(\n    $ref: String\n    $openQuery: String!\n    $closedQuery: String!\n    $listQuery: String!\n    $first: Int\n    $after: String\n  ) {\n    repository(ref: $ref) {\n      openCount: allBugs(query: $openQuery, first: 1) {\n        totalCount\n      }\n      closedCount: allBugs(query: $closedQuery, first: 1) {\n        totalCount\n      }\n      bugs: allBugs(query: $listQuery, first: $first, after: $after) {\n        totalCount\n        pageInfo {\n          hasNextPage\n          endCursor\n        }\n        nodes {\n          ...BugSummary\n        }\n      }\n    }\n  }\n": typeof types.BugListDocument,
+    "\n  query BugDetail($ref: String, $prefix: String!) {\n    repository(ref: $ref) {\n      bug(prefix: $prefix) {\n        ...BugSummary\n        humanId\n        title\n        status\n        createdAt\n        labels { name ...LabelFields }\n        author { humanId displayName }\n        lastEdit\n        participants(first: 20) {\n          nodes {\n            ...IdentitySummary\n            id\n            humanId\n            displayName\n            avatarUrl\n          }\n        }\n        timeline(first: 250) {\n          ...TimelineItems\n        }\n      }\n    }\n  }\n": typeof types.BugDetailDocument,
+    "\n  query BugList(\n    $ref: String\n    $openQuery: String!\n    $closedQuery: String!\n    $listQuery: String!\n    $first: Int\n    $after: String\n  ) {\n    repository(ref: $ref) {\n      openCount: allBugs(query: $openQuery, first: 1) {\n        totalCount\n      }\n      closedCount: allBugs(query: $closedQuery, first: 1) {\n        totalCount\n      }\n      bugs: allBugs(query: $listQuery, first: $first, after: $after) {\n        totalCount\n        pageInfo {\n          hasNextPage\n          endCursor\n        }\n        nodes {\n          ...BugSummary\n          id\n          humanId\n          status\n          title\n          createdAt\n          labels { name ...LabelFields }\n          author { humanId displayName ...IdentitySummary }\n          comments { totalCount }\n        }\n      }\n    }\n  }\n": typeof types.BugListDocument,
     "\n  mutation BugCreate($input: BugCreateInput!) {\n    bugCreate(input: $input) {\n      bug {\n        id\n        humanId\n      }\n    }\n  }\n": typeof types.BugCreateDocument,
-    "\n  query UserProfile(\n    $ref: String\n    $prefix: String!\n    $openQuery: String!\n    $closedQuery: String!\n    $listQuery: String!\n    $after: String\n  ) {\n    repository(ref: $ref) {\n      identity(prefix: $prefix) {\n        id\n        humanId\n        name\n        email\n        login\n        displayName\n        avatarUrl\n        isProtected\n      }\n      openCount: allBugs(query: $openQuery, first: 1) {\n        totalCount\n      }\n      closedCount: allBugs(query: $closedQuery, first: 1) {\n        totalCount\n      }\n      bugs: allBugs(query: $listQuery, first: 25, after: $after) {\n        totalCount\n        pageInfo {\n          hasNextPage\n          endCursor\n        }\n        nodes {\n          ...BugSummary\n        }\n      }\n    }\n  }\n": typeof types.UserProfileDocument,

webui2/src/__generated__/graphql.ts 🔗

@@ -1381,8 +1381,11 @@ export type BugDetailQueryVariables = Exact<{
 
 
 export type BugDetailQuery = { repository: { __typename: 'Repository', bug: (
-      { __typename: 'Bug', lastEdit: string, participants: { __typename: 'IdentityConnection', nodes: Array<(
-          { __typename: 'Identity' }
+      { __typename: 'Bug', humanId: string, title: string, status: Status, createdAt: string, lastEdit: string, labels: Array<(
+        { __typename: 'Label', name: string }
+        & { ' $fragmentRefs'?: { 'LabelFieldsFragment': LabelFieldsFragment } }
+      )>, author: { __typename: 'Identity', humanId: string, displayName: string }, participants: { __typename: 'IdentityConnection', nodes: Array<(
+          { __typename: 'Identity', id: string, humanId: string, displayName: string, avatarUrl: string | null }
           & { ' $fragmentRefs'?: { 'IdentitySummaryFragment': IdentitySummaryFragment } }
         )> }, timeline: (
         { __typename: 'BugTimelineItemConnection' }
@@ -1402,7 +1405,13 @@ export type BugListQueryVariables = Exact<{
 
 
 export type BugListQuery = { repository: { __typename: 'Repository', openCount: { __typename: 'BugConnection', totalCount: number }, closedCount: { __typename: 'BugConnection', totalCount: number }, bugs: { __typename: 'BugConnection', totalCount: number, pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, endCursor: string }, nodes: Array<(
-        { __typename: 'Bug' }
+        { __typename: 'Bug', id: string, humanId: string, status: Status, title: string, createdAt: string, labels: Array<(
+          { __typename: 'Label', name: string }
+          & { ' $fragmentRefs'?: { 'LabelFieldsFragment': LabelFieldsFragment } }
+        )>, author: (
+          { __typename: 'Identity', humanId: string, displayName: string }
+          & { ' $fragmentRefs'?: { 'IdentitySummaryFragment': IdentitySummaryFragment } }
+        ), comments: { __typename: 'BugCommentConnection', totalCount: number } }
         & { ' $fragmentRefs'?: { 'BugSummaryFragment': BugSummaryFragment } }
       )> } } | null };
 
@@ -1424,7 +1433,13 @@ export type UserProfileQueryVariables = Exact<{
 
 
 export type UserProfileQuery = { repository: { __typename: 'Repository', identity: { __typename: 'Identity', id: string, humanId: string, name: string | null, email: string | null, login: string | null, displayName: string, avatarUrl: string | null, isProtected: boolean } | null, openCount: { __typename: 'BugConnection', totalCount: number }, closedCount: { __typename: 'BugConnection', totalCount: number }, bugs: { __typename: 'BugConnection', totalCount: number, pageInfo: { __typename: 'PageInfo', hasNextPage: boolean, endCursor: string }, nodes: Array<(
-        { __typename: 'Bug' }
+        { __typename: 'Bug', id: string, humanId: string, status: Status, title: string, createdAt: string, labels: Array<(
+          { __typename: 'Label', name: string }
+          & { ' $fragmentRefs'?: { 'LabelFieldsFragment': LabelFieldsFragment } }
+        )>, author: (
+          { __typename: 'Identity', humanId: string }
+          & { ' $fragmentRefs'?: { 'IdentitySummaryFragment': IdentitySummaryFragment } }
+        ), comments: { __typename: 'BugCommentConnection', totalCount: number } }
         & { ' $fragmentRefs'?: { 'BugSummaryFragment': BugSummaryFragment } }
       )> } } | null };
 
@@ -1470,9 +1485,9 @@ export const CodePageLastCommitsDocument = {"kind":"Document","definitions":[{"k

webui2/src/components/bugs/timeline.tsx 🔗

@@ -171,7 +171,7 @@ export function Timeline({ repo, bugPrefix, timeline }: TimelineProps) {
 
 type CreateNode = Extract<TimelineNode, { __typename: "BugCreateTimelineItem" }>;
 type AddCommentNode = Extract<TimelineNode, { __typename: "BugAddCommentTimelineItem" }>;
-type CommentData = ResultOf<typeof BUG_CREATE_COMMENT_FRAGMENT>;
+type CommentData = ResultOf<typeof BUG_CREATE_COMMENT_FRAGMENT> | ResultOf<typeof BUG_ADD_COMMENT_FRAGMENT>;
 
 function CreateCommentItem({ item, bugPrefix, repo }: { item: CreateNode; bugPrefix: string; repo: string | null }) {
   const data = useFragment(BUG_CREATE_COMMENT_FRAGMENT, item);

webui2/src/routes/$repo/_issues/issues/$id.tsx 🔗

@@ -10,10 +10,20 @@ const BUG_DETAIL_QUERY = graphql(`
     repository(ref: $ref) {
       bug(prefix: $prefix) {
         ...BugSummary
+        humanId
+        title
+        status
+        createdAt
+        labels { name ...LabelFields }
+        author { humanId displayName }
         lastEdit
         participants(first: 20) {
           nodes {
             ...IdentitySummary
+            id
+            humanId
+            displayName
+            avatarUrl
           }
         }
         timeline(first: 250) {

webui2/src/routes/$repo/_issues/issues/index.tsx 🔗

@@ -32,6 +32,14 @@ const BUG_LIST_QUERY = graphql(`
         }
         nodes {
           ...BugSummary
+          id
+          humanId
+          status
+          title
+          createdAt
+          labels { name ...LabelFields }
+          author { humanId displayName ...IdentitySummary }
+          comments { totalCount }
         }
       }
     }
@@ -185,7 +193,7 @@ function RouteComponent() {
 
   // Apply structured filters → build query string → navigate
   function applyFilters(
-    status: StatusFilter,
+    status: StatusFilter | null,
     labels: string[],
     authorQuery: string | null,
     text: string,

webui2/src/routes/$repo/_issues/user/$id.tsx 🔗

@@ -46,6 +46,14 @@ const USER_PROFILE_QUERY = graphql(`
         }
         nodes {
           ...BugSummary
+          id
+          humanId
+          status
+          title
+          createdAt
+          labels { name ...LabelFields }
+          author { humanId ...IdentitySummary }
+          comments { totalCount }
         }
       }
     }