Skip to main content

Bilko — Support agent rola + RLS temelj (Faza A, MC #106050/#106051)

Support agent rola + RLS (Support MVP Faza A)

MC: #106050 (A1) + #106051 (A2), parent #106049 · Autor: Bruce Momjian · Red-zone verify: Parisa Tabriz (Securion) PASS · Grana: azdo feat/106051-support-agent-rbac (c4c8b4f4, NIJE main dok se A4/B ne ožiče)

Šta

DB temelj za support osoblje: nova rola support_agent koja vidi tikete SVIH klijenata ali NIŠTA finansijsko.

  • V133 — permission catalog: support_agent dobija TAČNO support_ticket:read + support_ticket:reply (colon-format po V67 CHECK-u). NULA finance/accounting/payroll ključeva. Idempotentno.
  • V134 — RLS + grants: cross-org SELECT na support_tickets gejtован NOVIM GUC-om app.is_support_agent (NAMJERNO NE reciklira app.is_platform_admin — to bi tiho dalo supportu sve što platform-admin tabele daju). Column-scoped UPDATE grant (status, resolution_note, triage_json, external_ref, updated_at — org_id/context_bundle isključeni na GRANT nivou). Usput zakrpio pre-existing gap: support_tickets (V73) nikad nije imao eksplicitan bilko_app GRANT (nevidljivo u prod jer bilko_admin BYPASSRLS).
  • Rola = pravi users.role login, ne service-account (bilko-support-triage je mašinski, bez per-human atribucije).

Sigurnost (Parisa adversarial verify, 6/6 drži)

  1. Finance leak: nema — is_support_agent se ne pojavljuje ni u jednoj finance/audit policy kroz 134 migracije; support konekcija na te tabele vezana istim org_isolation policy-ma. 2. GUC scope: is_support_agent samo u V134, samo na support_tickets policy-ma. 3. Cross-org: samo support_tickets otvoren, ništa drugo. 4. Permission over-grant: resolve() = exact-equality lookup, bez wildcard/prefix; mehanički ne može vratiti više od 2 ključa. 5. Column-scoped grant potvrđen. 6. RLS nigdje globalno ugašen; nema GUC-injection primitiva. Evidence: ~/system/evidence/106051/parisa-adversarial-verify.md.

⚠️ Bitno za sljedeću fazu (A4/B)

Aplikacijski sloj JOŠ ne ožičuje rolu — RLS politike su trenutno nedostižan dead code (siguran failure mode; rute i dalje idu preko app.is_platform_admin). A4 (requireSupportAgent() guard) + B (rute koje SET LOCAL app.is_support_agent) su prvi kod koji stварno pali novi GUC → traže vlastiti adversarial pass, ne voze na ovom verdiktu (Parisa flag).