PRD: UX Debt Remediation — Client Portal
Status: Draft — Awaiting Approval
Version: 1.0
Author: Product Manager Agent
Date: 2026-04-22
Repo Scope: upsquad-ai/upsquad-client (UI surfaces only)
Audit Source: /tmp/ux-audit-client-portal.md (2026-04-22 — Director-of-Ops persona walk)
Pilot Stage: Slots between pilot acceptance and paid-MVP cutover
Changelog
- v1.0 (2026-04-22) — Initial draft. Translates the 2026-04-22 client-portal UX audit (1 P0 already remediated in part, 7 P1, 13 P2, 7 P3) into a structural remediation programme of five waves (U1–U5). Defines persona target, top-10 cross-cutting fixes, severity rubric, success metrics, and explicit boundaries against PRDs #553, #573, and #552.
1. Problem Statement
The UpsQuad client portal exposes backend primitives directly to end-users. Forms ask Directors and Team Leads for UUIDs, raw RBAC permission slugs, proto enum values, and JSON. Page copy uses internal jargon ("cascade", "sticky-deny", "org_unit", "Quad", "Pillar") with no glossary. RPC names leak through <ComingSoon> placeholders. Permission gates show integers (L3) instead of human labels.
The 2026-04-22 audit, conducted in the role of a Director of Operations, surfaced:
- 1 P0 —
/admin/guardrailsis unusable by non-engineers (raw policy form with UUID input, JSON conditions, integer clearance, RPC names in copy). The OnboardingOverlay dev-identity leak (a separate P0) has already been remediated via client#117/#123. The guardrails P0 itself is the anchor case for this PRD's Wave U1. - 7 P1 — sidebar,
/agents/[id],/approvals,/keys,/admin/roles,/admin/conflicts,/admin/org-units/[id], onboarding flow,/chatmock-data leak. - 13 P2 — dashboard, agents list, teams list, billing usage, audit,
/admin/import,/quad,/teams/structure,/settings/users, all<ComingSoon>admin pages (8 total), dev-tools exposure. - 7 P3 — minor polish on already-good pages (
/agents/deploy,/teams/[id]/budget,/billing/*,/workflows,/chat/[agent_id]).
The problem: the portal works for engineers who know the codebase. It does not work for the persona who will pay for it. This blocks paid-MVP cutover after pilot.
A handful of one-off bugs surfaced by the same audit have been filed and closed individually as client#118-122. This PRD is for the structural / cross-cutting remediation — translating backend primitives into domain language with sensible defaults, templates, wizards, pickers, and labels. It is not for one-off bug fixes, which continue to flow through the normal bug pipeline.
2. Goals & Success Metrics
Goals
- A non-engineer end-user can complete the top-10 portal flows without ever seeing a UUID, an enum slug, an integer clearance, an RPC name, or raw JSON.
- The portal's user-facing language matches the persona's mental model (teams, departments, rules, approvals — not org_units, pillars, policies, action_types).
- Every concept-heavy field has a tooltip or first-run explainer; the user does not have to leave the product to understand it.
- The portal is keyboard-navigable and screen-reader-accessible on the top-10 most-used pages.
- The portal renders cleanly on a narrow viewport (>= 375px) for the same top-10 pages.
Success Metrics (binary, measurable, post-Wave-U5)
| Metric | Target | How verified |
|---|---|---|
| UUIDs visible to non-engineers in any form field | 0 | Static lint: placeholder="UUID" count = 0; manual walk |
Raw enum strings (action_type, scope=org_unit, requires_approval literal) shown to user | 0 | Manual walk + grep for known enum literals in JSX |
RPC / service names in user-facing copy (e.g. TenantService, GovernanceService.ConfigureApprovalPolicy) | 0 | Grep <ComingSoon service="..."> and any Service\b in JSX text |
| Time to create first guardrail rule (cold-start, non-engineer persona) | < 2 min | Stopwatch run on persona script |
| Top-10 user flows pass keyboard-only navigation | 100% | Playwright keyboard-only suite |
| Top-10 user flows pass screen-reader smoke (axe-core: 0 critical, 0 serious) | 100% | axe-core in Playwright |
| Top-10 user flows render correctly at 375px viewport | 100% | Playwright responsive snapshot |
clearance-labels.ts adoption coverage (% of clearance display sites) | 100% | grep audit |
Non-Goals
- No backend behavioural changes. This PRD only translates existing RPCs into better UI. If a backend RPC requires a UUID input, the UI takes a picker and resolves it to UUID before calling.
- No new product features. Debt only.
- No security-model changes. Clearance levels, RBAC permissions, scope hierarchy stay as-is. Only their presentation changes.
- No admin portal scope.
upsquad-admin(admin#2) has its own PRD. - No pricing / billing UX changes. PRD #552 owns billing scope.
- No dashboard intelligence redesign. PRD #553 owns dashboard scope; this PRD only handles the id-resolution and clearance-label hygiene leaking into the dashboard today.
- No Quad chat infrastructure changes. PRD #573 (HLD #915) owns Quad. This PRD coordinates the rename "Quad → Copilot" with W8 of that HLD.
3. Persona Target
Primary persona: Non-engineer end-user. Examples: Director of Operations, Team Lead, Head of People, Finance Manager. Same persona that gated PRD #950 walks.
Persona profile:
- Comfortable with computers and SaaS dashboards (Notion, Linear, Workday, Salesforce).
- Has never read a backend service spec.
- Does not know what a UUID, JSON, RBAC, RPC, or proto enum is. May know "JSON" exists but cannot author it.
- Mental model is in domain language: my team, my department, my approvers, my rules, my agents.
- Will close the tab if the form asks them to type a UUID or paste JSON.
Persona quote (from audit):
"As a Director of Operations, when I opened Guardrails to tell my agents they can't send customer emails without my approval, I was shown a form that asked me for a UUID, an
action_typeslug, a number between 1 and 5 with no scale key, and a JSON object. I closed the tab, opened Linear, and filed a ticket asking 'can we just not give any of my team AI agents yet?'."
Secondary persona: Tech-literate admin (DevOps engineer, IT lead). They are happy with raw forms but should not be the only audience that can use the product. They retain access to JSON / advanced views via "Advanced" disclosures, so power-user workflow is preserved.
4. Top-10 Cross-Cutting Fixes (Canonical)
The audit surfaced ten cross-cutting fixes that, taken together, resolve roughly 80% of the friction. Each fix has at least one anchor finding in the audit.
| # | Fix | Touches | Wave |
|---|---|---|---|
| F1 | Replace /admin/guardrails raw policy form with a plain-English wizard ("Block what / for which team / do what / with approval from whom / when"). Hide raw JSON / Advanced fields behind disclosure. Template gallery for first-use. | /admin/guardrails, DryRunPanel | U1 |
| F2 | Eliminate UUIDs from every form field a non-engineer touches. Replace with member, team, unit, and tool pickers. | /admin/guardrails, /agents/[id], /admin/conflicts, /admin/import, /approvals filter, agent dry-run | U3 |
| F3 | Adopt clearance-labels.ts (L1..L5 → Standard / Internal / Sensitive / Privileged / Executive) at every clearance display site. Module exists; partially used. | /admin/guardrails, /admin/import, /teams/[id]/tools, /dashboard approvals list | U2 |
| F4 | Rename user-facing jargon: "Quad" → Copilot (coordinated with PRD #573 W8); "Cascade" / "sticky-deny" → remove; "action_type / target / effect" → plain English; "Org Unit" → Team / Department; "Pillar" → Division / Department; "Conflicts" → Rule Conflicts; "tokens" → add "≈ X pages" co-label. | Sidebar, /quad, /admin/conflicts, /admin/guardrails, /admin/org-units/[id], /teams, /billing/usage | U2 |
| F5 | Add global ⌘K spotlight search across the portal (cmdk library). 40+ pages, no global jump today. | src/components/layout/*, all routes | U4 |
| F6 | Hide raw JSON fields behind "Advanced" disclosure. Default render is structured / human. | /admin/guardrails (conditions), /admin/conflicts (suggested merge), /admin/import (field mapping) | U1, U3 |
| F7 | Resolve every id.slice(0, N) label to a real name. Fall back to "Unnamed agent" / "Pending approval" — never a UUID prefix. | /dashboard approvals, /agents list, /teams list, /admin/conflicts/[id], notified-parties list | U3 |
| F8 | Audit and kill every remaining <ComingSoon> page that leaks an RPC name. (client#124 cleaned 9 call sites; verify residue and finish.) | /admin/org, /admin/users, /admin/teams, /admin/approvals, /admin/metrics, /workflows, /settings, /settings/organization, plus any introduced since | U2 |
| F9 | Tooltip / first-run explainer layer on every concept-heavy field (clearance, scope, target, conditions, status, autonomy). User shouldn't have to Google. Standard tooltip primitive + ? icon convention. | All pages with concept-heavy fields | U4 |
| F10 | Mobile / narrow-viewport rendering pass on the top-10 most-used pages. >= 375px viewport, no horizontal scroll, tap targets >= 44px. | Top-10 pages by usage | U5 |
Top-10 most-used pages (for F10 scope): /dashboard, /agents, /agents/[id], /approvals, /quad (or renamed Copilot), /chat, /teams, /teams/[id]/tools, /billing/usage, /audit. Final list confirmed against analytics during U5 kickoff.
5. Audit Residue (P1 / P2 / P3 carried into LLD tasks)
Every P1/P2/P3 finding in the audit not directly resolved by the top-10 fixes becomes an LLD task under the appropriate wave. Non-exhaustive list — the architect's HLD will enumerate fully:
P1 (must close before paid-MVP)
- Sidebar: rename sections to user mental models, hide ComingSoon items, fix hardcoded
badge: 3, replaceBE/FE/QA/ARagent monograms with tenant-data, add cmd-K. (U2 + U4) /agents/[id]: replace UUID inputs for Supervisor + Org Unit with pickers; rewriteErrorState.detailto plain English; drop "Agent ID: {uuid}" from chat header. (U3)/approvals: move "Session ID" filter behind Advanced; tooltip every status; add "My queue" tab. (U2 + U4)/keys: rewrite "programmatic access" copy; empty-state guidance; show example cURL after creation. (U2)/admin/roles: auto-generate slug; show permission categories not slug list; describe each built-in role; renameagents.register→ "Hire new agents" style. (U2)/admin/conflicts: rename "Conflicts" → "Rule Conflicts"; replace winning/losing layer with English narrative; hide JSON; replace UUID filters with pickers; simplify action buttons to a 2-option radio. (U2 + U3)/admin/org-units/[id]: rename "Org unit" to actual type; hide UUID from subtitle; rename "Effective tools"; rename "Numeric ceiling". (U2)- Onboarding flow: surface org-creation errors with retry CTA; "Skip" should actually skip; add progress indicator. (U2)
/chat: replace hardcodedMOCK_AGENTS(UpsQuad internal team names) withuseAgents(); drop "Agent ID" UUID; replace slash-command approvals with buttons. (U2 + U3)
P2 (close before paid GA)
/dashboard: id-to-name resolution for approvals + agent grid; clearance label adoption; first-time onboarding tile. (U3 + U2)/agents: resolveteamId→ team name; add Status / Last active / Owner columns; filters bar; first-use empty state. (U3)/teams: rename "Pillar" → "Department"; resolve ID → name; clickable rows; "Create team" CTA. (U2 + U3)/teams/[id]/tools: risk labels need icons not just colour; swapL{n}forclearanceLabel(); pretty-print approver_role slugs. (U2)/audit: subhead rewrite;actionTypefilter as human dropdown; export-to-CSV. (U2)/billing/usage: tokens → "≈ X pages"; tooltips on every metric; hide mock breakdowns until real data lands. (U2)/admin/import: rename "SCIM endpoint" → "Connect to your directory"; dropdown picker for field mapping in simple mode; remove TODO comments from JSX; clearance-label adoption. (U2)/quad: first-visit tour ("Hi! I'm Copilot, your org assistant."); more suggestion chips with "See all" gallery; empty-workspace hint. (U2 + U4)/teams/structure: rename sidebar item "Agent Structure" to "Org Chart"; align with page title. (U2)/settings/users: add single-user invite dialog; tooltips on filter values; split Members vs Agents. (U2 + U4)- Dev-tools exposure hardening: Playwright assertion that test buttons / clearance switcher are absent without
NEXT_PUBLIC_DEV_TOOLS. (U2)
P3 (nice-to-have)
/agents/deploy: surface deploy errors via toast; success celebration with "chat with new agent" CTA. (U2)/teams/[id]/budget: hide UUID from breadcrumb when team name not yet loaded. (U3)/billing+/billing/plans+/billing/invoices: minor copy polish (whitelist tier names). (U2)/workflows+/workflows/[workflow_id]: resolves with the central ComingSoon refactor (F8). (U2)/chat/[agent_id]: drop "Agent ID" header line. (U3)
6. Wave Plan
Each wave is independently shippable, ordered by user-facing impact. Each wave is gated by an architect HLD review and a PM product-acceptance review against the success metrics it targets.
Wave U1 — Guardrails Wizard (the largest single user-facing win)
Why first: the audit's only P0 page; the single most cited blocker for paid MVP. The current page is unusable by the target persona.
Scope:
- Replace
/admin/guardrailspolicy editor with a 5-step plain-English wizard: (1) what to control, (2) which team, (3) what should happen, (4) approval routing, (5) when it applies. - Tile-based step 1 with starter categories (Money / Billing, Customer data, Code & deployments, External tools, Everything high-risk).
- Team picker (tree) replacing
unitIdUUID input. - Effect radio with English labels ("Always block", "Pause and ask a human", "Allow freely") replacing
allow / deny / requires_approvalenum. - Clearance label rendering (Standard / Internal / Sensitive / Privileged / Executive) replacing
min_clearanceinteger. - Conditions: chip selector (Always, Outside business hours, Over a dollar threshold) with "Advanced (JSON)" disclosure.
- DryRunPanel: default caller to "me", default action to a recent action from the user's audit log; show verdict as a sentence ("This rule would have blocked 3 actions in the last 7 days").
- Cascade explanation replaced with a stacked-block visualisation.
- Template gallery for first-use empty state (6 starter templates).
- Remove all TODO comments and RPC names from page copy.
Estimate: ~3 weeks (architect HLD + frontend implementation + UX iterations). Depends on: picker primitives from U3 may be reused; for U1 we ship a guardrails-only inline picker and refactor in U3 if needed. Acceptance: non-engineer creates first rule in < 2 min; zero UUIDs / enum strings / RPC names visible.
Wave U2 — Jargon Rename + Clearance Labels + ComingSoon Cleanup
Why second: mostly mechanical, cross-cutting, visible on every page. Highest-leverage low-effort wave. Coordinates with PRD #573 W8 for "Quad → Copilot".
Scope:
- F3:
clearance-labels.tsadoption everywhere. - F4: jargon rename pass — "Quad" → "Copilot" (coordinate with PRD #573 W8), "Conflicts" → "Rule Conflicts", "Org Unit" → "Team" or "Department" by context, "Pillar" → "Division" or "Department", "Cascade" / "sticky-deny" removed from copy, "action_type / target / effect" mapped to English, tokens → "≈ X pages".
- F8: finish the
<ComingSoon>cleanup — refactor the component to drop theserviceprop from display; hide nav items pointing to non-functional pages. - Sidebar polish: section renames, hide ComingSoon items, fix hardcoded
badge: 3, replaceBE/FE/QA/ARagent monograms. - All P1/P2 copy fixes from the audit residue list.
Estimate: ~1.5 weeks.
Depends on: PRD #573 W8 schedule for the rename. If #573 is in flight, coordinate naming strings; if not, U2 ships the rename first and #573 inherits.
Acceptance: zero raw enum strings, zero RPC names, full clearance-label coverage, zero <ComingSoon service="..."> leaks.
Wave U3 — UUID → Picker Migration + ID-to-Name Resolution
Why third: the second-largest user-facing win. Each picker is a small reusable component; many call sites.
Scope:
- F2: ship four reusable pickers —
<MemberPicker>,<TeamPicker>,<UnitPicker>,<ToolPicker>. Tree / typeahead / category-grouped variants. - Migrate all UUID input fields to pickers:
/agents/[id](Supervisor + Org Unit),/admin/conflictsfilters (member_id),/approvals(Session ID filter behind Advanced + replaced by member picker for primary use),/admin/importfield-mapping pickers, dry-run caller picker. - F7: resolve every
id.slice(0, N)label to a real name. Fallbacks are "Unnamed agent" / "Pending approval", never UUID prefix. Affected:/dashboardapprovals + agent grid,/agentsteam column,/teamspillar column,/admin/conflicts/[id]policies, notified-parties. - Hide JSON conditions on
/admin/conflicts/[id]"Suggested merge" behind "View technical details"; default render is before/after rule comparison.
Estimate: ~3 weeks.
Depends on: U1 (picker primitives may originate in U1's guardrails wizard and graduate here).
Acceptance: zero placeholder="UUID" in codebase; zero id.slice(0, N) in JSX text.
Wave U4 — ⌘K Spotlight + Tooltip Layer + First-Run Explainers
Why fourth: quality-of-life multiplier. Adds discoverability across the now-cleaned-up portal.
Scope:
- F5: ⌘K spotlight via
cmdk. Indexes pages, agents, teams, recent approvals, settings, help articles. - F9: tooltip primitive +
?icon convention. Apply to: clearance labels, scope, target, conditions, status, autonomy levels, every approval status, every risk label. - First-run explainers:
/quad(renamed Copilot) tour card; sidebar tooltips on every nav item; "what this role lets someone do" descriptions on/admin/roles. - "My queue" tab on
/approvals.
Estimate: ~2 weeks. Depends on: U2 (renames must land first so tooltip copy is consistent). Acceptance: every concept-heavy field has discoverable explanation; cmd-K reaches every page in the portal in <= 2 keystrokes after open.
Wave U5 — Mobile / Responsive Pass
Why last: lowest user-facing return for pre-paid-MVP, but required for trial-conversion personas using laptops with narrow split views and tablets.
Scope:
- F10: top-10 most-used pages render correctly at 375px viewport. No horizontal scroll. Tap targets >= 44px. Tables collapse to card view at < 768px. Side-sheets become full-screen at < 768px.
- Playwright responsive snapshot tests for the top-10 set.
Estimate: ~2 weeks. Depends on: U1–U4 (rendering pass is faster after the layout has stabilised). Acceptance: top-10 pages pass 375px Playwright snapshots; axe-core reports 0 critical / 0 serious accessibility issues; keyboard-only navigation reaches every actionable element.
7. Severity Rubric (for prioritisation)
| Severity | Definition | Disposition |
|---|---|---|
| P0 | Blocks pilot acceptance — user cannot complete the flow at all, or risk of data leak / fake admin metadata. | Onboarding-overlay P0 already shipped (client#117/#123). The remaining audit P0 is the guardrails page itself, scoped into U1. |
| P1 | Blocks paid-MVP — non-engineer cannot complete a flow without help; trust-eroding. | Must close before customer #2. Scoped into U1 + U2 + U3. |
| P2 | Degrades trial-conversion — flow is completable but feels broken / clunky / opaque. | Close before paid GA. Scoped into U2 + U3 + U4. |
| P3 | Nice-to-have polish; does not block conversion. | Scoped into U5 or deferred to v1.1 of this PRD. |
8. Functional Requirements
Each requirement is a binary, testable condition. Mapped to a wave.
| # | Requirement | Wave |
|---|---|---|
| FR-1 | The /admin/guardrails page presents a wizard with steps {what, who, action, approval, when} as the default editing experience. | U1 |
| FR-2 | The guardrails wizard hides raw JSON conditions behind an explicit "Advanced" disclosure. | U1 |
| FR-3 | The guardrails wizard never displays a UUID, an action_type slug, an effect enum literal, an integer clearance, or the string guardrails.edit to a user with role < L4. | U1 |
| FR-4 | The guardrails dry-run defaults the caller to the current user and pre-fills a recent action from the user's audit log. | U1 |
| FR-5 | A guardrails template gallery offers >= 6 starter policies on first-use empty state. | U1 |
| FR-6 | The portal exposes reusable <MemberPicker>, <TeamPicker>, <UnitPicker>, and <ToolPicker> components. | U3 |
| FR-7 | Every form field that accepts a member, team, unit, or tool ID uses the corresponding picker; no placeholder="UUID" input remains. | U3 |
| FR-8 | Every clearance display site uses clearance-labels.ts (Standard / Internal / Sensitive / Privileged / Executive). No L{n} or bare integer rendering remains. | U2 |
| FR-9 | The <ComingSoon> component does not display the service prop. Pages with no functional backend are removed from sidebar nav. | U2 |
| FR-10 | The user-facing string "Quad" is renamed to "Copilot" across sidebar, page titles, and copy (coordinated with PRD #573 W8). | U2 |
| FR-11 | The user-facing string "Conflicts" (referring to policy cascade) is renamed to "Rule Conflicts" or "Policy Conflicts". | U2 |
| FR-12 | The user-facing strings "Org Unit", "Pillar", "Cascade", "sticky-deny" are removed from copy. Domain replacements are used contextually (Team / Department / Division). | U2 |
| FR-13 | Token-count metrics on /billing/usage carry an "≈ X pages" co-label. | U2 |
| FR-14 | No JSX text in the portal contains the substring id.slice(0, followed by a render. Fallback labels are "Unnamed agent" / "Pending approval" / "Unnamed team". | U3 |
| FR-15 | A global ⌘K command palette is reachable on every portal page. It indexes all pages, agents, teams, recent approvals. | U4 |
| FR-16 | Every clearance, scope, target, conditions, status, autonomy, and risk label has a discoverable tooltip on hover/focus. | U4 |
| FR-17 | First-time visitors to /quad (renamed Copilot) see a tour card explaining the surface. | U4 |
| FR-18 | The /approvals page has a "My queue" tab that filters to approvals awaiting the current user. | U4 |
| FR-19 | The top-10 most-used pages render correctly at 375px viewport with no horizontal scroll. | U5 |
| FR-20 | The top-10 most-used pages pass keyboard-only navigation (every actionable element reachable via Tab). | U5 |
| FR-21 | The top-10 most-used pages pass axe-core with 0 critical and 0 serious findings. | U5 |
| FR-22 | The sidebar's hardcoded badge: 3 is replaced with the live pending-approval count, or removed. | U2 |
| FR-23 | The sidebar's BE/FE/QA/AR agent monograms are replaced with tenant-supplied agent data, or removed. | U2 |
| FR-24 | The /chat index page renders agents from useAgents() rather than the hardcoded MOCK_AGENTS array. | U2 |
| FR-25 | Slash-command approval shortcuts (/approve, /reject) are replaced by structured action buttons in chat. | U3 |
| FR-26 | The <OnboardingOverlay> failure path surfaces an error toast with retry + support CTA; "Skip" defers org creation rather than triggering it. | U2 |
| FR-27 | Dev-tools surfaces (clearance switcher, "Test Onboarding" button) are absent from production builds; verified by Playwright. | U2 |
9. Non-Functional Requirements
- Performance. Picker components must support typeahead with <= 100ms p95 latency on a tenant with 5,000 members / 500 teams. Server-side filter required; full client-side load not acceptable.
- Accessibility. All new components meet WCAG 2.1 AA. axe-core in CI for the top-10 pages.
- Internationalisation readiness. All renamed strings flow through a single copy module so i18n can layer on later. (No translation in scope; only string-extraction discipline.)
- Telemetry. Wave U1 ships an analytics event for "first guardrail created" with elapsed time from page load. Used to verify the < 2 min success metric.
- Backwards compatibility. Power users who relied on raw forms retain access via "Advanced" disclosures. No flow becomes unreachable.
- Build hygiene. Lint rule added to fail CI on
placeholder="UUID"and on<ComingSoon service=literal usage.
10. Scope
In Scope
- The
upsquad-clientNext.js portal undersrc/app/(portal)/**. - Reusable component primitives (pickers, tooltip, command palette, clearance label) under
src/components/**. - Copy module for renamed strings.
- Playwright responsive + accessibility test suite for top-10 pages.
- Lint rules to prevent regressions.
Out of Scope (explicit)
- Backend RPC redesign. The UI translates them; the contract stays.
- New product features.
- Admin portal (
upsquad-admin) — owned by admin#2. - Pricing / billing UX changes — owned by PRD #552.
- Dashboard intelligence overhaul — owned by PRD #553.
- Quad chat infrastructure — owned by PRD #573 (HLD #915). Coordinate the "Quad → Copilot" rename only.
- One-off bug fixes already filed and closed (
client#118-122).
11. Dependencies
| Dependency | Direction | Boundary |
|---|---|---|
| PRD #553 — Dashboard Intelligence (awaiting approval) | Overlap on /dashboard polish | This PRD owns id-resolution + clearance-label hygiene on the dashboard today. PRD #553 owns the broader dashboard redesign. If #553 ships first, this PRD's dashboard changes are absorbed; if this PRD ships first, #553 inherits the cleaner baseline. |
| PRD #573 — Quad / Copilot (approved, HLD #915) | Coordinate the rename "Quad → Copilot" | The rename string lives in W8 of HLD #915. This PRD's U2 wave coordinates with that schedule. Whoever ships first owns the rename; the other inherits. PjM to align. |
client#124 — <ComingSoon> audit (already closed, 9 call sites cleaned) | This PRD verifies residue and finishes the job | Does not redo what client#124 did. Scopes only the remainder. |
| PRD #549 — Org Model v2.3 (HLD #556) | Picker behaviour relies on the org model | Pickers query the v2.3 org-tree shape. No v2.3 model changes from this PRD. |
| PRD #950 — Pre-Onboarding E2E | Same persona target | Success metrics align: PRD #950 verifies behavioural correctness; this PRD verifies UX comprehensibility for the same persona. |
| PRD #552 — Pricing & Packaging | Boundary on /billing/* | This PRD only touches /billing/usage for token co-labelling. All other billing UX is #552's. |
12. Edge Cases & Failure Modes
- Picker fallback when org tree fails to load. Pickers must show an error state with retry, not a blank dropdown. Forms remain submittable only when picker resolves.
- Locale: long names. Picker labels and clearance labels must truncate gracefully with tooltip showing full name.
- Power user wants the JSON. "Advanced" disclosure must persist preference per-user (localStorage) so a returning power user defaults to JSON view.
- First-run tour shown to returning users. Tour-shown flag stored per user × surface to avoid re-display.
MOCK_AGENTSremoval on a tenant with 0 deployed agents. Empty state must point to/agents/deployrather than show "No agents".- Mobile viewport on a flow that demands a wide table. Tables collapse to card view < 768px; column priority documented per page.
- Screen reader announces clearance changes. When the Advanced disclosure expands JSON, it must announce; aria-expanded handled by tooltip primitive.
- Migration period for renames. During the rename rollout, server-side links / emails referencing "Quad" may reach users post-rename. A redirect from
/quadto/copilot(or a renamed route) handles existing bookmarks.
13. Pricing Tier Mapping
This PRD is debt remediation across the existing portal. All tiers benefit equally. No new tier-gated features are introduced. The wizard, pickers, ⌘K, and tooltip layer ship to every tier that has portal access (Starter / Business / Enterprise on Cloud; Standard / Premium / Critical on On-Premise).
14. Estimated Cost
| Wave | Effort | Persons | Calendar |
|---|---|---|---|
| U1 — Guardrails wizard | L | 1 frontend-sme + architect HLD + UX iterations | ~3 weeks |
| U2 — Jargon rename + clearance labels + ComingSoon | M | 1 frontend-sme | ~1.5 weeks |
| U3 — Pickers + id-to-name | L | 1 frontend-sme | ~3 weeks |
| U4 — ⌘K + tooltips + first-run | M | 1 frontend-sme | ~2 weeks |
| U5 — Mobile / responsive | M | 1 frontend-sme | ~2 weeks |
| Total | ~11.5 weeks for a single frontend-sme |
Parallelisation: U1 and U2 can run in parallel if a second frontend-sme is available, compressing the calendar. U5 is strictly last.
15. Open Questions
- Rename target for "Quad". PRD #573 picked Copilot in W8; confirm that's the final choice before U2 ships, since the rename is hard to undo.
- Power-user preference persistence. Per-user (localStorage) or per-org (server)? Recommendation: per-user.
- Top-10 pages list for U5. Should be confirmed against analytics at U5 kickoff. Draft list above is the audit's proxy.
- Telemetry for "time to first guardrail". New event or reuse of existing analytics pipeline? PjM to confirm with analytics architect.
- Coordination with PRD #553. If both ship in the same release window, who absorbs whose dashboard changes? PjM to sequence.
16. Acceptance Criteria (PM Sign-off)
The PRD is considered fully delivered when:
- All 27 functional requirements (FR-1 through FR-27) are verified shipped.
- All 8 success metrics in §2 hit their targets.
- A persona walk by a non-engineer (Director-of-Ops or equivalent) successfully completes the top-10 flows without external help, in a single session.
- No regression on PRD #553 / #573 / #552 scope.
- Lint rules to prevent regressions are active in CI.
17. References
- Audit source:
/tmp/ux-audit-client-portal.md(2026-04-22, frontend-sme, Director-of-Ops persona walk). - Already-shipped P0 fixes: client#117 (
OnboardingOverlaydev-identity leak) merged via client#123. - Already-filed bug residue: client#118-122 (batched + closed).
- Related PRDs: #553 (Dashboard Intelligence), #573 (Quad / Copilot), #549 (Org Model v2.3), #552 (Pricing & Packaging), #950 (Pre-Onboarding E2E).
- Related cleanup issue: client#124 (
<ComingSoon>initial audit, closed).
End of PRD v1.0.