---
id: w3/m1/t001
title: Logs Core verb + client-go pod-log backend + RBAC
worker: worker3
status: done
estimate: 45m
depends_on: []
---

## Objective

Add a read-only `Logs` verb to bex-api's `Core` that streams pod logs for an App's Deployment via client-go, aggregating across replicas, with tail/limit and since-time options.

## Context

- bex-api one-Core/two-adapter shape: `operator/internal/api/core.go` is the only implementation; adapters call it (`docs/ADR006-bex-api.md`).
- An App reconciles to a Deployment in `bex-system`; pods carry the App's selector labels (see `operator/internal/controller/app_controller.go`).
- Pod logs via client-go `CoreV1().Pods(ns).GetLogs(pod, &PodLogOptions{TailLines, SinceTime, Timestamps})`.
- api Deployment RBAC today is "App access only" — reading logs needs new rules.

## Steps

1. Add `Logs(ctx, appID, opts)` to `Core` (new `operator/internal/api/logs.go`), returning normalized `{timestamp, instance, message}` lines.
2. Resolve the App → its pods (label selector), fan out `GetLogs` across replicas, merge by timestamp, honor `TailLines`/`SinceTime`/`limit`.
3. Extend api RBAC (`operator/config/api/`) with `pods` (get/list) and `pods/log` (get) in `bex-system`.

## Files

- `operator/internal/api/logs.go` (new), `operator/internal/api/core.go`
- `operator/config/api/` (RBAC role)

## Acceptance criteria

- [ ] `Core.Logs` returns merged, timestamp-ordered lines across an App's replicas.
- [ ] Tail/limit and since-time options honored.
- [ ] api RBAC grants `pods` + `pods/log` in `bex-system`; binary reads logs without escalation.

## Out of scope

- REST/GraphQL adapters (t002/t005), live follow (t003), request-log sourcing (t004).
