← Design · c121

plan/02-policy-detail.md

02 · Policy detail (S3) + policies listing (Wave 2)

TL;DR: Snooze goes; the policy's mode becomes ModeUntil, the same control the exception editor uses. Loosening and revoking require a reason (D1); expiry is optional with a nudge (D7). The exception editor shows BlastRadius. "Who does this apply to?" comes off. Header label says "Qpoint recommendation".

Owns: app/pages/pages/phase4/mock/policy-detail.vue, app/components/governance/part/{PolicyExceptions,PolicyMode,PolicyOverview}.vue, app/components/governance/mock/{ModeControl,SeverityPicker}.vue, app/components/governance/live/ControlsPolicies.vue, app/composables/useControlCenterMock.ts. Uses 01's ModeUntil, BlastRadius; 00's stage(), previewChange().

Today

  • Exception sheet: policy-detail.vue l.70–119 (form l.157–176, change l.185–207); bare UxTabGroup l.87 + date l.91; W.6 "required: it loosens" l.92, canApply l.206; reason optional → '—' l.194.
  • Snooze: PolicyMode.vue l.16–35; mode tooltip + strip note "Snoozed: observing until …".
  • ModeControl.vue (UxTabGroup + rollout note + hover tooltip l.74–99); variants ?v.mode=strip|header (policy-detail l.149–154).
  • "Who does this apply to?": PolicyExceptions.vue l.58–77 + why-sentence l.160–173.
  • Duplicated "what it overrides" logic: PolicyExceptions.vue l.117–119 and policy-detail.vue l.166–172 (no D9). Use the fixture's applicability() instead.
  • Header: PolicyOverview.vue l.8–36 — Mode, Frameworks, Organization Severity + "Recommended : sev", Findings count.
  • Listing: ControlsPolicies.vue l.70–75 black mode pill + snooze note.

Steps

  1. Mode section (L, R, I). Replace the Snooze block and the bare mode in PolicyMode with ModeUntil (replaces = current live mode). Changing mode down requires the reason field (D1) in its #reason slot; stage via stage() and show the refusal inline if 00 returns why:'reason'. ModeControl in the strip stays compact (no Until), its note reads "Observe until Nov 15, then Enforce" when set; delete the snooze strings everywhere in owned files.
  2. Exception editor. Use ModeUntil for mode/until. Reason: required when the exception loosens (label "Reason (required: it loosens Enforce → Observe)"), optional otherwise; remove W.6's date requirement and the 2-week prefill (D7). Replace the "Reach / Findings" lines with <BlastRadius variant="full" :impact="previewChange(...)">. Read ?add=user:<id>|team:<id>|org to open the sheet prefilled (04 links here).
  3. Revoke. Revoke opens the sheet with BlastRadius + a required "Reason for revoking" (D1) → exception-revoke with revokeNote. Exceptions table shows revoked rows' note in history.
  4. Remove "Who does this apply to?" and its why-sentence (cascade simulator cut). Remove the duplicated overrides logic; read applicability() for "overrides".
  5. Header (R "locked"). Label "Qpoint recommendation: High" under Organization Severity; keep Frameworks and open Findings. No other header change.
  6. Policies listing. Mode pill shows "Observe · until Nov 15"; drop the snooze note.
  7. Remove any remaining shim calls to previewChangeCounts in owned files.

Done when

/pages/phase4/mock/policy-detail?policy=P-NO-ROOT (until shown), ?policy=P-MCP (exceptions, add one that loosens → reason required, BlastRadius red; add one that tightens → blue, reason optional), revoke flow, ?add=team:finance. Screenshots shots/02-*.png.

Look for (review)

Mode and exception editor read as the same control (Rob: "the org-wide default and the scoped override read as the same familiar pattern"); nothing says "snooze"; no simulator.

Qpoint Brand Style Guide