basquetWi + New ticket

New ticket

Sub-ticket of PLUTO-191 Access-request PM-triage loop (DB-fed) — adopted bs-mqotdmmk6b5 2026-06-22, Pluto access-leg only (no support-ticket surface exists in Pluto). GOAL: on access-request submit, app DMs pm-pluto-cc in aro:pluto a DB row-summary so PM triages from the DB (never the URL) before Elazar sees a cold email. BUILD (piece 1, coder + applog lane): on accessRequests INSERT (createdVia=access_request, via /solicitar-acceso → access-request-status-sql.ts / auth-actions.ts / admin-actions.ts), emit a PM-addressed aro:pluto DM carrying {requestId, requester name, email, requested role/context, institutional domain} — REUSE the applog NOTIFY→listener→hub-DM rail just extended for EVO-28 (new category/action, e.g. category=user/action=accessRequestSubmitted; per-app COPY). OPERATIONAL workflow (PM behavior, no code): PM reads the accessRequests row → runs canonicalizeEmail/emailCanonical dedup (NEW vs DUPLICATE-of-existing-user Z under gmail-dot/+tag/googlemail/institutional variant — capability already BUILT via PLUTO-152) → checks isAllowlistedEmail domain → hands Elazar a verdict: 'requester/email / NEW vs DUPLICATE-of-Z / domain ok? / recommend APPROVE|REJECT|MERGE — go?'. GATES: approveRequest GRANT (users/userRoles INSERT + sendAccessRequestApproved email) = Elazar-gated (hits both auth/allowlist-grant + real-audience email; Pluto=LIVE clinical users since 2026-06-09, erroneous grant/denial hits a real person). reject/requestMissingInfo (real-audience email) → PM drafts, sends if routine, escalates exact text if material. Upstream read/dedup/classify = PM-autonomous, visible in aro:pluto (show-work-in-aro). DEPS: applog rail (EVO-28 piece-1 ebb593b live). Pre-implementation audit ping (touches accessRequests trigger-archived table + auth-adjacent path) before coder builds. · pluto