docs(guide): add technical.feedback — the last uncovered service (#26) #31

Merged
hiveiq merged 1 commits from docs/26-technical-feedback into develop 2026-07-17 09:12:13 -04:00
Owner

Refs #26 (and hiveops-feedback#13).

Why

hiveops-feedback has been live in production since 2026-07-09 with no Guide module. coverage-reconcile.py has been reporting it as MISSING the whole time.

Guide coverage — 127 documented modules across 19 apps
✅ no missing services / agent modules / SPAs

That was the first thing to fail today: technical.feedback 404'd, and because GlobalExceptionHandler turns a bad path into a 500, I spent a while convinced the Guide itself was down. It wasn't — the module simply didn't exist.

Shape

Matches the other 19 technical.* modules exactly: single overview.md, tab=Overview, audience=dev, order=10, sections Responsibility / Data / Kafka / API surface / Gotchas. Written from source (develop @ ea81eb4), not from memory or the repo README.

audience: dev means BCOS_ADMIN only — it will not ship to production, which serves the customer tier.

What it records

The Gotchas are the point. Things that have actually bitten, with issue numbers:

  • Split DB vars (DB_HOST/DB_PORT/DB_NAME) — not DB_URL like journal/devices. Copying the sibling pattern here does not work.
  • Two auth realmsX-Submit-KeyROLE_SUBMITTER for intake, JWT MSP/BCOS for triage. RELOCATED is terminal; accept()/review() 409 against it.
  • Label lookups are silently lossy (feedback#14) — collectLabels swallows exceptions at log.debug, so a token without read:organization drops org labels with no error and creates the issue under-labelled.
  • Rate limiting trusts X-Forwarded-For blindly (feedback#5) — xff.split(",")[0], no trusted-proxy check. Also per-instance Caffeine: not shared, resets on restart.
  • /h2-console/** is permitAll unconditionally (feedback#7) — the console is only enabled on dev, but the permit rule ships regardless.
  • The list endpoint has NO institution scoping (feedback#19, unfixed) — every MSP admin sees every customer's submissions. FeedbackPrincipal has institutionKey and never consults it. QDS log in as MSP_ADMIN. This caused a real exposure on 2026-07-09.
  • POST /submit carries no user JWT — shared key, so a submission has no institution attached at all. That is why #19 cannot be fixed by scoping the read alone.
  • Accept never worked in production until 2026-07-16%2F path → 405, then an empty GITEA_TOKEN → unauthenticated → Gitea 404 (not 403) on a private repo → opaque 500.
  • Two PAN maskers existSanitizerService here is not the same code as journal's PciSanitizer.
  • No Kafka. No close-sync with Gitea — a RELOCATED row stays listed forever after its issue closes; pruning is manual.

Checks

  • coverage-reconcile.pygreen, no missing entries.
  • Frontmatter matches siblings (module/tab/audience/order) and parses under the same rules MarkdownGuideService.parse applies.
  • Existing content untouched — this PR only adds one file.

🤖 Generated with Claude Code

Refs #26 (and hiveops-feedback#13). ## Why `hiveops-feedback` has been **live in production since 2026-07-09** with no Guide module. `coverage-reconcile.py` has been reporting it as MISSING the whole time. ``` Guide coverage — 127 documented modules across 19 apps ✅ no missing services / agent modules / SPAs ``` That was the **first thing to fail today**: `technical.feedback` 404'd, and because `GlobalExceptionHandler` turns a bad path into a 500, I spent a while convinced the Guide itself was down. It wasn't — the module simply didn't exist. ## Shape Matches the other 19 `technical.*` modules exactly: single `overview.md`, `tab=Overview`, `audience=dev`, `order=10`, sections **Responsibility / Data / Kafka / API surface / Gotchas**. Written from source (`develop` @ `ea81eb4`), not from memory or the repo README. `audience: dev` means **BCOS_ADMIN only** — it will not ship to production, which serves the `customer` tier. ## What it records The Gotchas are the point. Things that have actually bitten, with issue numbers: - **Split DB vars** (`DB_HOST`/`DB_PORT`/`DB_NAME`) — **not** `DB_URL` like journal/devices. Copying the sibling pattern here does not work. - **Two auth realms** — `X-Submit-Key` → `ROLE_SUBMITTER` for intake, JWT MSP/BCOS for triage. `RELOCATED` is terminal; `accept()`/`review()` 409 against it. - **Label lookups are silently lossy** (feedback#14) — `collectLabels` swallows exceptions at `log.debug`, so a token without `read:organization` drops org labels **with no error** and creates the issue under-labelled. - **Rate limiting trusts `X-Forwarded-For` blindly** (feedback#5) — `xff.split(",")[0]`, no trusted-proxy check. Also per-instance Caffeine: not shared, resets on restart. - **`/h2-console/**` is `permitAll`** unconditionally (feedback#7) — the console is only *enabled* on `dev`, but the permit rule ships regardless. - **The list endpoint has NO institution scoping** (feedback#19, **unfixed**) — every MSP admin sees every customer's submissions. `FeedbackPrincipal` has `institutionKey` and never consults it. QDS log in as MSP_ADMIN. This caused a real exposure on 2026-07-09. - **`POST /submit` carries no user JWT** — shared key, so a submission has no institution attached at all. That is *why* #19 cannot be fixed by scoping the read alone. - **Accept never worked in production until 2026-07-16** — `%2F` path → 405, then an empty `GITEA_TOKEN` → unauthenticated → Gitea **404** (not 403) on a private repo → opaque **500**. - **Two PAN maskers exist** — `SanitizerService` here is not the same code as journal's `PciSanitizer`. - **No Kafka. No close-sync with Gitea** — a `RELOCATED` row stays listed forever after its issue closes; pruning is manual. ## Checks - `coverage-reconcile.py` → **green**, no missing entries. - Frontmatter matches siblings (`module`/`tab`/`audience`/`order`) and parses under the same rules `MarkdownGuideService.parse` applies. - Existing content untouched — this PR only adds one file. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
hiveiq added 1 commit 2026-07-17 09:07:22 -04:00
hiveops-feedback has been live in production since 2026-07-09 and had no Guide
module; coverage-reconcile.py has been reporting it as MISSING. Coverage is now
green: 127 modules across 19 apps, no missing services/agent modules/SPAs.

Written from source (develop @ ea81eb4), matching the technical.* shape:
single overview.md, tab=Overview, audience=dev, order=10.

Records the things that actually cost time rather than restating the obvious:

- Split DB vars (DB_HOST/DB_PORT/DB_NAME), NOT DB_URL like journal/devices.
- Two auth realms: X-Submit-Key -> ROLE_SUBMITTER for intake; JWT MSP/BCOS for
  triage. RELOCATED is terminal and immutable (409 on accept/review).
- Gitea relay: label lookups swallow their exceptions, so a token without
  read:organization silently drops org labels (feedback#14).
- Rate limiting trusts X-Forwarded-For blindly and is per-instance Caffeine
  (feedback#5). /h2-console/** is permitAll unconditionally (feedback#7).
- The list endpoint has NO institution scoping — every MSP admin sees every
  customer's submissions, and QDS log in as MSP_ADMIN (feedback#19, unfixed).
- Accept never worked in prod until 2026-07-16: %2F path -> 405, then an empty
  GITEA_TOKEN -> unauthenticated -> Gitea 404 on a private repo -> opaque 500.
- No Kafka, no close-sync with Gitea.

Refs #26
johannes approved these changes 2026-07-17 09:08:00 -04:00
hiveiq merged commit ab717062d6 into develop 2026-07-17 09:12:13 -04:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: hiveiq-src/hiveops-guide#31