Internal Documentation internal
TalkIDE internal documentation

Přihlášený uživatel klikne na tlačítko “Nahlásit problém” ve Studio toolbaru, vyplní modal formulář a odešle report TalkIDE platformního bugu nebo feature requestu. BE rozšiřuje reporter_agent whitelist o hodnotu USER a aplikuje rate limit 5 reportů za hodinu per-user-id.

  • Přístup pouze pro přihlášené uživatele — user JWT povinný. Bez JWT → 401 Unauthorized.
  • severity = CRITICAL uživatel nastavit nemůže — dropdown nabízí jen LOW / MEDIUM / HIGH. CRITICAL je admin-only (UC-09004).
  • target je vždy PLATFORM — uživatel nevidí volbu. Modal posílá výhradně target=PLATFORM (Phase 2 scope). BE endpoint validuje PROJECT cestu per UC-09005 (Phase 3, live).
  • kind = INCIDENT není dostupný — přijde s environments feature (#84).
  • Rate limit scope je reporter_user_id (ne session_id — user v tuto chvíli nemusí mít aktivní Mara konverzaci).
  • Dedup okno 10 minut (stejný klíč jako UC-09001): (tenant_slug, target, SHA256(title.lowercase().trim())) + reported_at > now() - 10 min.
  • Pokud je user ve Studiu otevřeného projektu, BE obohacuje kontext o project_id přes volitelný header X-Current-Project.
  • UX záměrně odděluje “Report TalkIDE bug” (tato UC) od “Report bug v aplikaci” (Phase 3 UC-09005) — uživatel nesmí zaměnit scope.

Scope poznámka: Tento UC pokrývá FE-initiated PLATFORM reporting flow (tlačítko ve Studio/Workspace). BE endpoint POST /api/issues je sdílený i s UC-09005 (USER+PROJECT, Phase 3). Modal v této Phase 2 implementaci posílá výhradně target=PLATFORM, ale BE endpoint validuje obě cesty. USER + target=PROJECT s validním project_id je plně podporováno v BE — viz UC-09005 a IssueTrackingTestCases (5 regresních testů USER+PROJECT → 201).


Flow — Uživatel reportuje nový PLATFORM issue

sequenceDiagram
    actor User

    User->>+FE: klikne na "🐛 Nahlásit problém" v Studio toolbaru

    FE->>FE: otevře ReportIssueModal
    Note over FE: Prefill: title prázdný<br/>kind = BUG (default)<br/>severity = MEDIUM (default)<br/>X-Current-Project header<br/>připraven z aktivního projektu (pokud existuje)

    User->>FE: vyplní title, description, kind, severity a odešle formulář

    FE->>FE: validace formuláře
    alt formulář nevalidní (prázdné pole, title > 80 znaků)
        FE-->>User: zobrazí inline chybové hlášky pod poli
    end

    FE->>+BE: POST /api/issues <br/> Authorization: Bearer {userJWT} <br/> X-Reporter-Agent: USER <br/> X-Current-Project: {projectId} (Long, volitelný) <br/> { target, kind, title, description, severity }

    BE->>BE: ověří JWT → extrahuje reporter_user_id
    alt JWT chybí nebo je neplatný
        BE-->>FE: 401 Unauthorized
    end

    BE->>BE: validuje X-Reporter-Agent header
    alt X-Reporter-Agent není USER
        BE-->>FE: 400 Bad Request (VALIDATION)
    end

    BE->>BE: validuje request body (target, kind, title, severity)
    Note over BE: target=PROJECT bez project_id → 400 ISSUE_PROJECT_ID_REQUIRED<br/>target=PROJECT s validním project_id → povoleno (UC-09005 cesta)
    alt nevalidní tělo requestu
        BE-->>FE: 400 Bad Request (VALIDATION)
    end

    BE->>DB: rate limit check: COUNT issues WHERE reporter_user_id=? AND reported_at > now()-60min
    alt >= 5 reportů za hodinu
        BE-->>FE: 429 Too Many Requests (RATE_LIMIT_EXCEEDED)
        FE-->>User: "Dosáhl jsi limitu 5 reportů za hodinu. Zkus to znovu za chvíli."
    end

    BE->>DB: dedup query: EXISTS issues WHERE tenant_slug=? AND target=? AND SHA256(title)=?<br/>AND reported_at > now() - interval '10 minutes'
    alt dedup hit
        BE->>DB: INSERT issue_comments (author_agent=USER, body="Nahlásil jsem znovu. [kontext]")
        BE-->>FE: 200 OK { id, url, deduplicated: true, comment_id }
        FE-->>User: "Stejný problém byl nahlášen před chvílí jako #ID. Přidali jsme tvou poznámku."
    end

    BE->>BE: server-side context enrichment (synchronní, fail-soft)
    Note over BE: context_jsonb:<br/>· projectState: tenant_slug, projectId (z X-Current-Project), deploy URL, last build SHA<br/>· (k8sEvents a podLogSnippet pouze pokud X-Current-Project přítomen)

    BE->>DB: INSERT issues (id=UUID, target=PLATFORM, tenant_slug, reporter_user_id,<br/>reporter_agent=USER, session_id=NULL, title, description,<br/>kind, severity, status=OPEN, context_jsonb, reported_at=now())

    BE-->>-FE: 201 Created { id, url, deduplicated: false }

    FE->>FE: zavře modal
    FE-->>-User: toast "Problém nahlášen. ID: #{zkrácenéId}" (prvních 8 znaků id; bez klickatelného odkazu)

REST API

POST /api/issues

Autentizace: User JWT (Bearer token). Chybějící nebo neplatný JWT → 401 Unauthorized.

Povinné headery:

HeaderHodnotaPoznámka
AuthorizationBearer <userJWT>Povinný
X-Reporter-AgentUSERPovinný; BE akceptuje MARA nebo USER (Phase 1 whitelist rozšířen touto UC)
X-Current-Project<projectId> (Long, číselné ID projektu, např. 42)Volitelný; přítomný pokud uživatel reportuje ze Studio konverzace s otevřeným projektem; umožňuje BE enrichment o project state; pokud hodnota není parsovatelná jako Long, BE ji ignoruje (fail-soft) a issue se uloží bez project_id enrichmentu + warn log

Request body:

{
  "target": "PLATFORM",
  "kind": "BUG",
  "title": "Build selhává — Kaniko nemůže zapisovat do registry",
  "description": "Po kliknutí na Deploy se zobrazí chyba `unauthorized: authentication required`. Opakoval jsem deploy třikrát, stejný výsledek. Naposledy to fungovalo včera odpoledne.",
  "severity": "HIGH"
}

201 Created (nový issue):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://talkide.app/studio/issues/550e8400-e29b-41d4-a716-446655440000",
  "deduplicated": false
}

200 OK (dedup hit — stejný issue nahlášen v posledních 10 minutách):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "url": "https://talkide.app/studio/issues/550e8400-e29b-41d4-a716-446655440000",
  "deduplicated": true,
  "comment_id": "661f9511-f3ac-52e5-b827-557766551111"
}

400 Bad Request (validace):

{
  "code": "VALIDATION",
  "message": "title must not exceed 80 characters"
}

401 Unauthorized (chybí nebo neplatný JWT):

{
  "code": "UNAUTHORIZED",
  "message": "Authentication required"
}

403 Forbidden (severity=CRITICAL nebo nepovolený X-Reporter-Agent):

{
  "code": "FORBIDDEN",
  "message": "CRITICAL severity can only be set by admin during triage"
}

429 Too Many Requests (rate limit):

{
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Maximum 5 issue reports per hour exceeded. Try again later."
}

Auto-context enrichment (server-side, synchronní, fail-soft)

Pokud je přítomen header X-Current-Project, BE synchronně sbírá a ukládá do context_jsonb:

PoleZdrojDetail
projectStateTalkIDE DBtenant_slug, projectId (z X-Current-Project), aktuální deploy URL, SHA posledního úspěšného buildu. Pokud enrichProjectState selže (DB exception), context_jsonb obsahuje projectState = null a errors["projectStateError"] s popisem chyby.
k8sEventsKubernetes API (fabric8)Warning/Error eventy za posledních 5 minut z tenant-<slug> namespace + talkide namespace (max 20 položek)
podLogSnippetKubernetes API (fabric8)WARN/ERROR řádky za posledních 2 minuty, max ~200 řádků celkem, pody v talkide namespace
errorsBE enrichmentKlíče projectStateError, k8sEventsError, podLogSnippetError — přítomny pouze při selhání dílčího sběru; hodnota = string popis chyby

Pokud X-Current-Project header chybí (uživatel reportuje mimo kontext projektu), context_jsonb obsahuje pouze { "projectState": null }.

K8s sběr je fail-soft: selhání enrichmentu nesmí zablokovat vytvoření issue. Nedostupné pole = null + záznam v errors["<poleName>Error"]. Issue se vždy uloží.


UX Guidelines

Studio toolbar tlačítko

  • Umístění: toolbar vpravo nahoře, vedle uživatelského menu.
  • Label: ”🐛 Nahlásit problém” (desktop) nebo jen ikona 🐛 (mobilní breakpoint).
  • Viditelné vždy — ve Studiu i na dashboard stránkách (není vázáno na konkrétní projekt).

ReportIssueModal — wireframe (textový)

┌─────────────────────────────────────────────────────────┐
│  🐛 Nahlásit problém s TalkIDE              [×] zavřít  │
├─────────────────────────────────────────────────────────┤
│  ℹ️  Reportuješ bug nebo nápad pro tým TalkIDE.         │
│     Pokud hledáš bug v tvé aplikaci, jdi do             │
│     záložky "Problémy aplikace" → [odkaz] (Phase 3)     │
├─────────────────────────────────────────────────────────┤
│  Název *                                                │
│  ┌───────────────────────────────────────────────────┐  │
│  │ Stručný popis problému (max 80 znaků)             │  │
│  └───────────────────────────────────────────────────┘  │
│  [Zbývá: 80 znaků] — live counter                       │
│                                                          │
│  Popis *                                                │
│  ┌───────────────────────────────────────────────────┐  │
│  │ Markdown editor — co se stalo, kroky reprodukce,  │  │
│  │ co jsi očekával a co se stalo místo toho          │  │
│  │                                                    │  │
│  └───────────────────────────────────────────────────┘  │
│                                                          │
│  Typ              Závažnost                             │
│  ┌─────────────┐  ┌─────────────┐                       │
│  │ BUG       ▼│  │ MEDIUM    ▼│                       │
│  └─────────────┘  └─────────────┘                       │
│   BUG / FEATURE    LOW / MEDIUM / HIGH                   │
│                                                          │
│                        [Zrušit]  [Odeslat report]        │
└─────────────────────────────────────────────────────────┘

Klíčové UX detaily:

  • Scope klarifikace: Modal zobrazí informační banner “Reportuješ problém s TalkIDE platformou (build, deploy, Studio). Pokud hledáš bug ve své aplikaci, použij záložku Problémy aplikace.” — zabraňuje záměně scope.
  • Live counter: Pole title zobrazuje zbývající počet znaků do limitu 80 v reálném čase.
  • Markdown preview: Pole description podporuje toggle mezi editačním a preview módem (md rendering).
  • Severity tooltip: Dropdown pro závažnost obsahuje tooltip s rubrikem:
    • LOW: Kosmetické — neblokuje práci
    • MEDIUM (výchozí): Zpomaluje práci, existuje obejití
    • HIGH: Blokuje klíčovou operaci, nelze pokračovat
  • Submit button state: Deaktivovaný dokud title a description nejsou vyplněny.
  • Loading state: Po odeslání tlačítko zobrazuje spinner, formulář je zablokovaný.
  • Po úspěchu: Modal se zavře, zobrazí se toast “Problém nahlášen. ID: #{zkrácenéId}” kde zkrácenéId = prvních 8 znaků id z BE response. Toast neobsahuje klickatelný odkaz na detail — klickatelný link (využije url z response) je naplánován na Phase 3. url je v response přítomna pro budoucí rozšíření.
  • Dedup feedback: Pokud BE vrátí deduplicated: true, modal zobrazí informaci “Stejný problém byl nedávno nahlášen jako #{id}. Přidali jsme tvou poznámku.” místo standardního “odeslán” toastu.
  • Rate limit feedback: 429 → modal zůstane otevřen, zobrazí error banner “Dosáhl jsi limitu 5 reportů za hodinu. Zkus to prosím za chvíli.”
  • Phase 3 placeholder: Odkaz na “Problémy aplikace” záložku v banneru vede na budoucí /studio/issues/project — dokud Phase 3 není live, odkaz je disabled nebo vede na placeholder stránku.

Frontend

Validace

PoleConstraintsVelikostPatternPoznámka
titlenot_blank1–80Live counter; trim před validací
descriptionnot_blank1–10 000Markdown; trim před validací
kindrequired, in(BUG, FEATURE)Výchozí hodnota: BUG
severityrequired, in(LOW, MEDIUM, HIGH)Výchozí hodnota: MEDIUM; CRITICAL skrytý

Headery sestavené FE

HeaderHodnotaKdy
X-Reporter-AgentUSERVždy
X-Current-ProjectString(currentProjectId) — číselné Long ID aktivního projektu (např. "42")Pokud je uživatel v kontextu otevřeného projektu

Backend

Validace

Pole / KontrolaConstraintsPoznámka
Authorization headerrequired, platný JWTChybí nebo neplatný → 401
X-Reporter-Agent headerrequired, in(MARA, USER)Jiná hodnota → 400 VALIDATION
targetnot_blank, in(PLATFORM, PROJECT)Modal posílá PLATFORM (Phase 2 scope). Endpoint akceptuje i PROJECT per UC-09005; PROJECT bez project_id → 400 ISSUE_PROJECT_ID_REQUIRED
kindnot_blank, in(BUG, FEATURE)INCIDENT → 400 “kind=INCIDENT not yet implemented (see #84)“
titlenot_blank, max 80 charsTrim whitespace před uložením
descriptionnot_blank, max 10 000 charsMarkdown; trim před uložením
severitynullable, default MEDIUM, in(LOW, MEDIUM, HIGH)CRITICAL → 403 Forbidden
Rate limitmax 5 / 60 min / reporter_user_idPočítáno z reported_at v issues pro daný reporter_user_id
Dedup(tenant_slug, target, SHA256(title.lowercase().trim())) + reported_at > now()-10minViz dedup flow; při hitu → 200 OK s komentářem
X-Current-Project headeroptional, Long (číselné ID projektu)Pokud přítomen, BE parsuje hodnotu jako Long a resolvuje projekt z DB pro enrichment; neparsovatelná hodnota (není Long) → BE ignoruje hlavičku, fail-soft, warn log, issue se uloží bez enrichmentu; neexistující projectId → enrichment přeskočen (warn log), issue se uloží

Test Cases

GIVENWHENTHEN
Přihlášený user, platný JWT, vyplněný formulář (title, description, kind=BUG, severity=MEDIUM)POST /api/issues s X-Reporter-Agent: USER, target=PLATFORM201 Created; issue uložen s reporter_agent=USER, status=OPEN, severity=MEDIUM; context_jsonb obsahuje alespoň { "projectState": null }; FE zobrazí toast “Problém nahlášen. ID: #{prvních 8 znaků id}”
Přihlášený user, platný JWT, vyplněný formulář + X-Current-Project header s platným projectIdPOST /api/issues201 Created; context_jsonb.projectState obsahuje projectId a deploy data projektu
User odesílá severity=CRITICAL (manipulace requestu mimo FE)POST /api/issues s X-Reporter-Agent: USER403 Forbidden, code=FORBIDDEN; issue nevznikne
User odesílá target=PROJECT bez project_id (manipulace requestu)POST /api/issues s X-Reporter-Agent: USER400 Bad Request, code=ISSUE_PROJECT_ID_REQUIRED; issue nevznikne. Poznámka: USER + target=PROJECT s validním project_id je podpořeno UC-09005 (Phase 3) — ten case sem nepatří.
User odesílá title delší než 80 znakůPOST /api/issues s X-Reporter-Agent: USER400 Bad Request, code=VALIDATION
User odesílá description delší než 10 000 znakůPOST /api/issues s X-Reporter-Agent: USER400 Bad Request, code=VALIDATION
User odeslal 5 issues za posledních 60 minut6. POST /api/issues s X-Reporter-Agent: USER429 Too Many Requests, code=RATE_LIMIT_EXCEEDED
Issue se stejným (tenant_slug, target, title hash) existuje a reported_at > now()-10minPOST /api/issues se stejným titulem200 OK, deduplicated=true; nový komentář přidán; nový issue nevznikne
Chybí Authorization headerPOST /api/issues401 Unauthorized, code=UNAUTHORIZED
Neplatný JWT (expirace, bad signature)POST /api/issues401 Unauthorized
X-Reporter-Agent header chybí nebo má jinou hodnotu než MARA/USERPOST /api/issues400 Bad Request, code=VALIDATION
X-Current-Project odkazuje na neexistující projectIdPOST /api/issues201 Created; enrichment přeskočen (warn log); context_jsonb.projectState = null
X-Current-Project obsahuje neparsovatelnou hodnotu (např. UUID řetězec místo Long)POST /api/issues201 Created; BE ignoruje hlavičku (fail-soft, warn log); issue uložen bez project_id enrichmentu
K8s API nedostupné při enrichmentuPOST /api/issues s X-Current-Project201 Created; context_jsonb.k8sEvents = null, context_jsonb.errors.k8sEventsError přítomen

BE změna: rozšíření reporter_agent whitelistu

Phase 1 (UC-09001) akceptuje v hlavičce X-Reporter-Agent pouze hodnotu MARA. Tato UC rozšiřuje whitelist na MARA | USER.

Konkrétní změna:

Třída IssueController (nebo middleware pro validaci headeru) rozšiřuje akceptované hodnoty:

Před: X-Reporter-Agent in [MARA]
Po:   X-Reporter-Agent in [MARA, USER]

Auth logika se liší:

  • MARA → Agent JWT (stávající chování UC-09001 beze změny)
  • USER → User JWT — BE extrahuje reporter_user_id ze standardního JWT claimu sub; session_id se ukládá jako NULL (user nemá Mara session UUID)

Rate limit scope:

  • MARA: per session_id (stávající chování)
  • USER: per reporter_user_id (nové chování — user nemá konzistentní session UUID)

References


FEEDBACK

Zadání bylo velmi podrobné — scope, field constraints, rate limit scope a UX nápady byly popsány dostatečně na přímý přepis. Chybělo upřesnění dvou věcí: (1) zda description má i BE limit 10 000 znaků (FE ano, ale BE validační tabulka v UC-09001 limit nezmiňuje — předpokládal jsem symetrii); (2) jak přesně BE resolvuje tenant_slug pro USER reporty (u Mara je to z agent JWT, u USER JWTs to závisí na claims struktuře). Usnadnilo by práci stručná odpověď “user JWT obsahuje / neobsahuje tenant_slug claim” na začátku zadání.


Was this page helpful?

Thanks for the feedback.