---
id: w5/m6/t002
title: logs.graphql query + codegen; historical log panel
worker: worker5
status: done
estimate: 50m
depends_on: [w5/m6/t001]
---

## Objective

Add the `logs(...)` GraphQL query, generate typed operations, and build the historical log panel — a scrollable list of log lines (timestamp / instance / message) with a text filter — in Render's `LogEntry` shape.

## Context

- bex-api GraphQL: `logs(resource, type, text, limit)` → `LogEntry { timestamp message type instance }` (`docs/ADR006-bex-api.md`). Application logs only.
- Codegen: `codegen.ts` → `src/graphql/definitions.ts` (needs `CODEGEN_SESSION_TOKEN`).
- New feature module: `src/features/logs/` (self-contained, per `dashboard/CLAUDE.md`).
- Strings via `useTranslations()`, `logs.*` namespace.

## Steps

1. Create `src/features/logs/api/logs.graphql` with the `logs` query; regenerate codegen.
2. Build the log panel component: virtualized/scrollable line list, timestamp + instance + message columns, text filter bound to the query's `text` arg.
3. Add a `src/features/logs/locales/{en,zh}.ts`; register it in `src/i18n/index.ts`.

## Files

- `src/features/logs/api/logs.graphql` (new)
- `src/features/logs/components/` (log panel)
- `src/graphql/definitions.ts` (regenerated)
- `src/features/logs/locales/{en,zh}.ts`
- `src/i18n/index.ts` (register `logs` namespace)

## Acceptance criteria

- [ ] The panel renders historical logs from the `logs` query in `LogEntry` shape.
- [ ] The text filter narrows results via the query's `text` arg.
- [ ] `yarn typecheck` passes.

## Out of scope

- Live tail (t003), tab wiring (t004).
