Internal Documentation internal
TalkIDE internal documentation

PROJECT issues jsou zobrazitelné ve třech lokacích — Workspace tab (per-project), Studio dashboard widget (cross-project preview) a dedikovaná list stránka /studio/issues (full cross-project list). Všechny lokace jsou scoped na přihlášeného tenantu — uživatel nikdy nevidí issues jiného tenantu.

  • Existující GET /api/issues endpoint (UC-09002) se rozšiřuje o query parametry targetType=PROJECT a projectId=<uuid> pro per-project view.
  • Cross-project view (Studio widget + list stránka) posílá targetType=PROJECT&tenantScoped=true — BE vrátí všechny PROJECT issues daného tenantu bez filtru na projekt.
  • Žádná nová DB migrace — pouze BE query logika a FE komponenty.
  • Scoping: BE vždy filtruje přes tenant_id z JWT — cross-tenant přístup není možný.

Flow 1 — Workspace tab Issues (per-project view)

sequenceDiagram
    actor User

    User->>+FE: otevře Workspace tab "Issues" pro projekt X

    FE->>+BE: GET /api/issues?targetType=PROJECT&projectId={id}&status=OPEN
    Note over FE,BE: Authorization: Bearer {userJWT}

    BE->>BE: ověř JWT, extrahuj tenant_id
    BE->>DB: SELECT issues WHERE target=PROJECT AND project_id={id} AND tenant_id=<z JWT><br/>AND status=OPEN ORDER BY reported_at DESC LIMIT 50

    BE-->>-FE: 200 OK [ IssueSummary[] ]

    FE->>-User: zobrazí list issues pro projekt X (kind badge, severity badge, title, reported_at, status)

Flow 2 — Studio dashboard widget (cross-project preview)

sequenceDiagram
    actor User

    User->>+FE: otevře Studio dashboard

    FE->>+BE: GET /api/issues?targetType=PROJECT&tenantScoped=true&status=OPEN&pageSize=5
    Note over FE,BE: Authorization: Bearer {userJWT}

    BE->>BE: ověř JWT, extrahuj tenant_id
    BE->>DB: SELECT issues WHERE target=PROJECT AND tenant_id=<z JWT><br/>AND status=OPEN ORDER BY severity DESC, reported_at DESC LIMIT 5

    BE-->>-FE: 200 OK { items: [...], total: 12, page: 1, pageSize: 5 }

    FE->>-User: zobrazí sekci ISSUES na dashboardu: top-5 issues + "View All (12) →" link
    Note over FE: "12" = response.total — žádný separátní /count request

Flow 3 — Dedikovaná list stránka /studio/issues (cross-project full list)

sequenceDiagram
    actor User

    User->>+FE: naviguje na /studio/issues (nebo klikne "View All →" z dashboardu)

    FE->>+BE: GET /api/issues?targetType=PROJECT&tenantScoped=true
    Note over FE,BE: s aktivními filtry: &projectId=&status=&query=

    BE->>BE: ověř JWT, extrahuj tenant_id
    BE->>DB: SELECT issues WHERE target=PROJECT AND tenant_id=<z JWT><br/>s aplikovanými filtry ORDER BY severity DESC, reported_at DESC LIMIT 100

    BE-->>-FE: 200 OK [ IssueSummary[] ]

    FE->>-User: zobrazí full list s filter barem (projekt, status, kind, search)

REST API

GET /api/issues (rozšíření Phase 3)

Autentizace: User JWT nebo Agent JWT.

Nové query params (Phase 3):

ParamTypPopis
targetTypestringPROJECT nebo PLATFORM (alternativa k stávajícímu target — oba přijaty)
projectIdUUIDPer-project filter; vrátí issues pouze pro daný projekt
tenantScopedbooleanPokud true, vrátí všechny PROJECT issues tenantu bez filtru na projekt
limitintegerMax počet výsledků; default 50, max 100

Pozn.: Parametry targetType / target jsou aliasy — BE akceptuje oba pro zpětnou kompatibilitu. Nový kód preferuje targetType.

Scoping pravidla:

  • Vždy: tenant_id = <z JWT> — žádný cross-tenant přístup.
  • projectId přítomen: filtruj jen na daný projekt (+ ověř project.tenant_id = tenant_id z JWT).
  • tenantScoped=true: vrátí issues pro všechny projekty tenantu.
  • Bez parametrů: chování jako Phase 1 (scoped na reporter_user_id).

Příklad — per-project:

GET /api/issues?targetType=PROJECT&projectId=a1b2c3d4-0000-0000-0000-000000000001&status=OPEN
Authorization: Bearer <userJWT>

Příklad — cross-project (Studio list):

GET /api/issues?targetType=PROJECT&tenantScoped=true
Authorization: Bearer <userJWT>

200 OK:

{
  "items": [
    {
      "id": "660f9511-e3ac-42d5-b827-557766551234",
      "target": "PROJECT",
      "project_id": "a1b2c3d4-0000-0000-0000-000000000001",
      "project_name": "my-app",
      "kind": "BUG",
      "severity": "HIGH",
      "status": "OPEN",
      "title": "SQL query vrací duplicitní řádky při JOIN bez DISTINCT",
      "reporter_agent": "MARA",
      "reported_at": "2026-05-14T08:30:00Z",
      "url": "https://talkide.app/studio/issues/660f9511-e3ac-42d5-b827-557766551234",
      "reporter_email": null,
      "tenant_slug": "my-tenant"
    }
  ],
  "total": 12,
  "page": 1,
  "pageSize": 50
}

project_name je nové pole v IssueSummary pro PROJECT issues — BE JOIN-uje na projects.name. PLATFORM issues mají project_name: null.

total = celkový počet záznamů vyhovujících filtru (bez stránkování). Studio dashboard používá total pro “View All (N) →” badge — žádný separátní /count endpoint není potřeba.

200 OK (prázdný výsledek):

{
  "items": [],
  "total": 0,
  "page": 1,
  "pageSize": 50
}

401 Unauthorized:

{
  "code": "UNAUTHORIZED",
  "message": "Missing or invalid authentication token"
}

400 Bad Request (neplatné projectId UUID):

{
  "code": "VALIDATION",
  "message": "projectId must be a valid UUID"
}

Frontend

Workspace tab — Issues list

Route: součást Workspace panel pro daný projekt (ne samostatná route).

PrvekPopis
Status filterVýchozí OPEN; volby OPEN, TRIAGED, IN_PROGRESS, RESOLVED, WONTFIX, DUPLICATE, ALL
”Nahlásit problém” buttonOtevře modal z UC-09005
Tabulka issuesKind badge, Severity badge, Title, Reported at (relativní), Status badge

Empty state: Ilustrace + “Zatím žádné issues pro tento projekt.”

Studio dashboard widget — sekce ISSUES

Umístění: Studio dashboard, sekce “ISSUES” (pod Projects).

PrvekPopis
Nadpis”ISSUES” (uppercase, small caps — design pattern dashboardu)
Top-5 issuesŘazeno severity DESC, reported_at DESC; zobrazit: Project name, Severity badge, Title (zkrácený na 60 chars), Status badge
”View All (N) →“Link na /studio/issues; N = response.total z GET /api/issues?pageSize=5 — bez separátního count requestu

Pokud count = 0, sekce ISSUES se na dashboardu nezobrazí (prázdná sekce ruší přehlednost).

Dedikovaná list stránka /studio/issues

Route: /studio/issues

Toolbar:

PrvekPopis
Project filter dropdownVýchozí “All projects”; volby = názvy projektů tenantu
Status filter dropdownVýchozí OPEN; všechny statusy + ALL
Kind filterALL, BUG, FEATURE
Search input?query=; debounce 300 ms
Refresh buttonIkona RefreshCw (lucide-vue-next)

Tabulka — sloupce:

SloupecZdrojPoznámka
Projectproject_nameKliknutelný link → otevře Workspace daného projektu
Severity badgeseverityHIGH=červená, MEDIUM=žlutá, LOW=šedá
KindkindBUG / FEATURE
TitletitleKliknutelný link → detail issue
Reporterreporter_agent iconMARA=robot icon, USER=user icon
Reported atreported_atRelativní čas; hover = absolutní ISO
Status badgestatusBarevné kódy identické s UC-09002 FE sekce

Výchozí řazení: severity DESC, reported_at DESC.

Paging: Bez explicitního stránkování. Limit 100; pokud vráceno přesně 100, notice “Zobrazeno prvních 100 výsledků — zpřesni filtr.”

Validations (FE)

ParamConstraintsNote
projectIdnullable UUID nebo prázdný stringPokud vybrán projekt z dropdownu
statusnullable, in(OPEN, TRIAGED, IN_PROGRESS, RESOLVED, WONTFIX, DUPLICATE)
querynullable, max 200 charsTrim před odesláním

Backend

Validations

ParamConstraintsNote
targetType / targetnullable, in(PLATFORM, PROJECT)Oba aliasy přijaty
projectIdnullable UUIDPokud předán: ověř project.tenant_id = tenant_id z JWT → 403 při mismatch
tenantScopedbooleanPokud true, ignoruje reporter_user_id scope (vrátí celý tenant)
statusnullable, in(OPEN, TRIAGED, IN_PROGRESS, RESOLVED, WONTFIX, DUPLICATE)Neplatná hodnota → 400
querynullable, max 200 charsILIKE %query% nad title a description
limitinteger, default 50, max 100
Tenant scopetenant_id = <z JWT> vždy aplikovánNelze vypnout; cross-tenant přístup zakázán

Test Cases

GIVENWHENTHEN
Projekt má 3 OPEN PROJECT issuesGET /api/issues?targetType=PROJECT&projectId=<id>&status=OPEN200 OK, 3 záznamy; každý má project_id, project_name, kind, severity, status
Tenant má 12 OPEN PROJECT issues napříč 4 projektyGET /api/issues?targetType=PROJECT&tenantScoped=true&status=OPEN200 OK, 12 záznamů; issues ze všech 4 projektů
projectId patří jinému tenantuGET /api/issues?targetType=PROJECT&projectId=<cizi>403 Forbidden nebo prázdný výsledek [] (tenant scope filter eliminuje cizí projekt)
Žádné PROJECT issues pro daný projektGET /api/issues?targetType=PROJECT&projectId=<id>200 OK, prázdné pole []
Chybějící JWTGET /api/issues?targetType=PROJECT&tenantScoped=true401 Unauthorized
Neplatné UUID v projectIdGET /api/issues?projectId=not-a-uuid400 Bad Request, code=VALIDATION
query delší než 200 znakůGET /api/issues?query=...400 Bad Request

References


FEEDBACK

UC pokrývá 3 flows v jednom dokumentu — alternativou bylo 3 separátní UCs, ale všechny tři sdílí jeden endpoint a jeden datový model, takže sloučení dává smysl. Obě ambiguity byly vyřešeny: (1) separátní GET /api/issues/count endpoint se neimplementuje — FE derivuje count z response.total v pagination envelope; (2) Studio dashboard widget fetchuje top-5 s pageSize=5 a total z téhož response použije pro “View All (N) →” badge — jeden request, žádný extra COUNT.


Was this page helpful?

Thanks for the feedback.