Cycles
Design · c65

control-center-v2

activecreated 2026-08-12· last activity 2026-09-11

Shift the control center from infinitely-configurable controls to a compliance-driven system of pre-defined Policies — research the framework↔policy connection, then mock the policy catalog and per-policy config pages

Why

c64 consolidated qdash around the flexible control model and shipped the V5 expand-card authoring flow — and in doing so made the cost of that flexibility visible: every control is a hand-built rule (signal + clauses + decisions + actions + packs), which is more complexity and manual configuration than the product wants to put in front of an operator. c65 deliberately reverses the emphasis: the infinite configurability moves behind a curated set of pre-defined Policies — narrow in scope, activated/deactivated with a toggle, each with focused context-specific configuration (e.g. the egress allow-list policy gets a page for managing the list). The /policy page had already started down this path; we veer back toward it, minus its enforcement-mode/violation-handling cascade (that becomes a global function, out of scope here). Compliance frameworks are the driver: frameworks are toggled globally (as on /compliance today) and determine global health and security posture; policies exist to satisfy them.

Vocabulary decision (2026-08-12): the pre-defined units are Policies, a distinct concept sitting above the flexible Controls engine — reintroducing the word c64's IA pass retired, now with a real distinction to carry (policy = curated, narrow, toggleable unit; control = underlying executable rule).

Objective

Four deliverables: (1) research-frameworks.md — in-depth analysis of the 12-framework union catalog (rules.rs PACKS ∪ frontend catalog): what each framework demands that is runtime-addressable, provable/attestation/out-of-scope split, and the policy mappings it implies; (2) policy-definitions.md — the canonical policy roster with stable P-ids: purpose, underlying control rule, config shape + fields, framework mappings, provenance; (3) /pages/policy-catalog — the main mock: global framework toggles + posture rollup over a categorized policy table with toggles and framework-gap emphasis; (4) first-pass config pages — one page per policy, built almost entirely from ~5 shared config-shape template components (list editor, threshold, level select, detector list, toggle + exceptions), egress allow-list as the deep exemplar. Explicitly NOT solving enforcement modes, violation handling/alerting, or qdash implementation.

Scope

  • cycles/c65.control-center-v2/ — research-frameworks.md, policy-definitions.md
  • app/pages/pages/policy-catalog.vue + app/pages/pages/policy-config-*.vue + page-registry entries
  • app/components/policy/ — site-local config shell + shape components (layer extraction is a later cycle)
  • Read-only inputs: qcontrol crates/qdash/ui (policy.vue, compliance.vue, framework.vue, controls.vue, GovernSheet.vue, utils/frameworks.ts), crates/qdash/src/rules.rs + db.rs seeds, docs/plan/qdash-information-architecture.md §7.5; bob-wire c17-governance.ts + c17-frameworks.ts; design c54/c56/c64 cycles
  • Out: qdash code changes, enforcement/violation-handling design, layer changes beyond necessity

Key Changes

  • Kick-off + decisions (2026-08-12): vocabulary = Policies above Controls; framework catalog = union of 12 (rules.rs PACKS ∪ frontend catalog — adds HIPAA/GDPR and NIST CSF/ISO 27001 to one list); config pages = one page per policy leaning on ~5 shared shape templates; custom-control engine kept as a de-emphasized escape hatch.
  • research-frameworks.md (2026-08-12): per-framework runtime-addressability analysis for all 12 (provable/attestation/out-of-scope per IA doc §7.5, ok/partial/out fits following the OWASP LLM01–10 exemplar), a reverse view ranking policies by compliance weight (P8 Credential Protection carries 9 frameworks; P10/P1/P2/P9 next), findings R1–R6 (framework-list drift, hipaa/gdpr missing from valid_pack(), casing drift, crosswalk too coarse, only OWASP LLM has a requirements mapping, framework kind should shape the UI).
  • policy-definitions.md (2026-08-12): the canonical roster — 17 policies (P1–P17) in 5 categories (adds Cost & Consumption to /policy's 4), each with purpose, executable underlying rule (rules.rs vocabulary), config shape + fields, defaults (seeded-backed → on), severity, remediation, 12-framework matrix, provenance. Config-shape taxonomy: list editor (P5/P6/P10/P14), threshold (P15/P16/P17), level select (P7/P11), detector list (P8/P9/P12/P13), toggle + exceptions (P1–P4). Exceptions replace enforcement modes — scoped, reasoned, expiring carve-outs instead of the Audit/Enforce cascade. Capability gaps fed back to qcontrol: G1 no negated set operator (allow-lists need the egress allowlisted derived-flag pattern), G2 no injection/PII detector families on content, G3 hipaa/gdpr unrecognized packs. Not carried forward: targets/campaigns, the /policy cascade, per-framework control toggles.
  • /pages/policy-catalog (2026-08-12): the main mock (app/pages/pages/policy-catalog.vue, registered) — 12-framework toggle grid (kind icon, live completeness bar, per-framework "N gaps — enable" bulk close), 4-tile posture rollup (posture % = active ÷ required across active frameworks), categorized policy table in the /policy toggle idiom with Enforcement/Alerting columns replaced by compliance chips (active-framework requirements, red when the policy is off = gap), mono underlying-rule line per row, Configure→ links to the config pages, quiet custom-controls footer. One shared reactive model — framework toggles, policy toggles, gaps, and posture all recompute live.
  • Config shell + 5 shape components (2026-08-12): app/components/policy-config/ (site-local; layer extraction deferred) — Shell (back-link, name + activation toggle, meta strip with SecuritySeverity + satisfies chips, <details> underlying-control disclosure, body dims when inactive, remediation footer), Exceptions (shared section on every policy — scope/value/reason/expiry with add/remove), ListEditor (mutates the passed reactive array so page-level flows can push into it), Threshold (ceiling/floor via dir, observed-value breach state), LevelSelect (ordered floor, below-floor blast-radius preview), DetectorList (families, per-detector toggle + severity + 24h hits, enable-all).
  • 17 config pages (2026-08-12): policy-config-<slug>.vue for P1–P17, all registered — thin shell+shape instantiations from the P-id specs. Deep exemplar = policy-config-egress-allowlist (the prompt's named case): pending non-allowlisted destinations (83-match c64 snapshot framing) with a live approve→list flow, scoped entries (global/host/agent per EgressDecisionModal). Toggle-shaped pages carry a live status band (shadow installs, static-key runs, root runs, never-ask runs). Verified: all 18 routes 200 on the running dev server, SSR content present, no stale classes. Two vocabulary fixes along the way: error-surface/warning-surface don't exist in the layer tokens (swapped for error/10-style tints) and there is no arrow-left icon (back-link uses the precedent's character).
  • Catalog iteration (2026-08-12): "Show inactive (N)" toggle on the framework strip header — hides non-activated framework cards, live count, defaults to showing all. Later same-day passes: description into its own column (4-col table), shrink-to-fit Policy/Config columns (width:1% + nowrap), align-middle rows, bare-dash empty state replaced with "N mapped frameworks — none active" text, Compliance column header renamed by Mark.
  • /pages/compliance-frameworks (2026-08-12): visual-semantics iteration page (compliance-frameworks.vue, registered) — the policy-catalog framework grid duplicated as baseline with the kind label dropped and ComplianceFrameworkIcon replaced by the new compliance-shield art (via <img>, own brand purples). Inactive state got its own grey-variant svg (compliance-shield-grey.svg, light half #d4d4d4 — a filter can't split the two halves). Iteration same-day: V2 "surface semantics" set added (shared state with V1) — active = white card + grape-400 border, inactive = dashed stroke-strong border on surface-sunken-subtle (one step lighter than the page's surface-sunken); gaps tag → "Enable Required Policies" outline button; progress bar de-semanticized (grey-400 fill via inline style — arbitrary Tailwind classes aren't generated on this page — grape-500 only at 100%); toggle micro→tiny with -mr-3 flush-right fix (UxToggle keeps its label wrapper's pl-2 + root gap-1 even with an empty label slot — layer nit worth fixing upstream).
  • Layer fix — UxToggle empty-label gap (2026-08-12): q-nuxt-layer/components/ux/Toggle.vue — the label wrapper div rendered unconditionally, so a label-less toggle carried a 12px phantom on the right (wrapper pl-2 + root gap-1 as an empty flex item). Root cause of the V2-card alignment issue; the root's inline-flex is load-bearing (track/label row, items-center, gap, reverse mode) and must stay. Fix: v-if="$slots.label" on the wrapper. The -mr-3 page hack removed; labeled toggles verified unaffected. Rides along with ComplianceTag in the next layer release.
  • /pages/policy-catalog-v2 (2026-08-12): expand-row variation (policy-catalog-v2.vue, registered, non-destructive) — Config column dropped to a 3-column table; each policy row is a UxTableListExpandRow whose card carries the underlying rule (mono, sunken box + custom-control escape hatch), the FULL framework mapping as small ComplianceTags (inactive frameworks dimmed at 40%, error state only when an active framework is unmet), severity + P-id + maturity + remediation, and the "Open config page →" link. Activation toggle wrapped in @click.stop so it doesn't fight the row expand. Framework strip/posture rollup identical to v1.
  • /pages/policy-catalog-v3 (2026-08-12): inline-config variation (policy-catalog-v3.vue, registered) — direct duplicate of v2 with the expand row hosting the policy's ACTUAL config controls: shape components (<component :is> over a shape→component map — explicit imports, since resolveComponent can't see auto-imports) + the shared Exceptions section, fed by the same config snapshots the policy-config-* pages carry (CONFIGS/EXCEPTIONS keyed by P-id). Identity strip (rule · severity · P-id · maturity · escape hatch) above the config; config dims at 50% when the policy is off (the config-shell idiom). Poses the open question: do the standalone config pages survive, or is the catalog the config surface?
  • Gap-cluster + pill polish (2026-08-12): exclaim circle sized up to h-5 with an italic muted "Required" label after it (gap rows only); Beta pill iterated warning-amber → grey → light blue → grey body with a #318bc4/60% blue border (Roadmap = full grey) — blue applied via style binding since one-off arbitrary color classes don't generate on pages; #318bc4 is a token candidate if a layer blue ramp ever lands.
  • ComplianceTag gap variant (2026-08-12): third state on the tag — gap: muted grey pill + grey shield for required-but-off, with ONE page-side exclaim circle (UxIcon exclaim in a red-tinted rounded-full span) placed inline after the tag cluster rather than marking every tag. All three catalog pages swapped from :error to :gap + cluster exclaim; the red error variant remains for loud failure contexts. Demo + registry docs updated.
  • ComplianceToggleCard extraction + component docs (2026-08-12): the settled framework card extracted to the layer as compliance/ToggleCard.vue (props name/active/percent/satisfied/required/gaps/gapTitle, emits toggle + enable-gaps; shield art from layer assets, grey bar fill inline to dodge consumer-scan issues); both grids (policy-catalog, compliance-frameworks V2) now consume it — V1 stays inline as the baseline artifact. ComplianceTag gained error (red two-tone shield compliance-shield-error.svg + error border/text) and size ('small' | 'medium', UxToggle convention); small got a py bump; catalog table gap chips → <ComplianceTag size="small" error>. Both components documented: new compliance group in component-registry (also fixes ComplianceFrameworkIcon's dangling group id), registry entries with coverage, interactive demos (_demos/ComplianceTag.vue, _demos/ComplianceToggleCard.vue), and a Compliance section on the /components visual index.
  • Layer component — ComplianceTag (2026-08-12): q-nuxt-layer/components/compliance/Tag.vue — small reusable compliance tag: shield mark + framework name in a grape-50 pill (grape-400 border, grape-600 bold label), optional removable ✕ emitting @remove, label via default slot. Shield asset resolved from the layer's own assets at build (?url import, AgentPawn pattern). Demo strip added to /pages/compliance-frameworks (static, removable, and live-wired tags that deactivate frameworks on remove). Confirmed the design dev server runs NUXT_LOCAL_LAYER (picked the component up without a release). Not yet in a layer release — run /release-layer (→ v0.9.8) before tarball consumers can use it; component not yet added to the design-site component docs.
  • qcontrol application (2026-08-12): qcontrol-application.md written (reuse model, hybrid persistence map, backend backlog B1–B8, supersession map). The six policy-config components extracted to the layer as controlled components (emit contracts: add/remove/change/toggle/toggle-all/floor; arbitrary classes → inline styles; Shell gained the white bg-surface content box + backTo/backLabel props + ComplianceTag satisfies chips) — design locals deleted, all 17 config pages + v3 rewired to the new contracts (v3 imports via #components), registry policy-config group + 6 entries + 6 demos added. Layer v0.9.8 released (commit 4708cf2, tag-driven CI publish, all 5 consumer lockfiles re-resolved — qcontrol's git#main ref included). qdash c13 executed: /controls replaced by the policy catalog (framework strip + 17-policy expand-row table + custom-controls escape section), /policy deleted, one controls/detail.vue (?policyId=) serving all policies, hybrid persistence (egress via /api/egress-decisions, P15/P17 thresholds via real control rule rewrites with dry-run, rest via usePolicyState localStorage). Verified: 11/11 headless DOM checks, live API round-trips, 137 vitest, dist regenerated. See qcontrol crates/qdash/ui/cycles/c13.control-policies/CYCLE.md.

Outcome

The full arc shipped in one cycle: research (12-framework analysis + P1–P17 policy definitions with stable IDs) → design-site mocks (policy-catalog v1/v2/v3, 17 config pages, compliance-frameworks iteration surface) → layer components (ComplianceTag, ComplianceToggleCard, the policy-config six, UxToggle fix — released as v0.9.8) → qcontrol application (qdash c13: /controls IS the policy catalog, /policy retired). Backend follow-ons specified in qcontrol-application.md (B1–B8). Design-site mocks remain as the iteration surface; qdash work sits uncommitted on feat/control-center for review.

Visual record

27 captures — heroes, page slices, and full-page renders. Click to view.

Policy Config — Egress Allow-List — c65 P10 — list-editor shape, the deep exemplar: pending non-allowlisted destinations with live approve-into-list flow, scope
Policy Config — Egress Allow-List — c65 P10 — list-editor shape, the deep exemplar: pending non-allowlisted destinations with live approve-into-list flow, scope
Policy Config — Agent Registration — c65 P1 — toggle + exceptions shape, shadow-AI status band, scoped carve-outs with reason + expiry
Policy Config — Agent Registration — c65 P1 — toggle + exceptions shape, shadow-AI status band, scoped carve-outs with reason + expiry
Policy Config — Org-Backed Identity — c65 P2 — toggle + exceptions shape, static-key run status, service-account exception
Policy Config — Org-Backed Identity — c65 P2 — toggle + exceptions shape, static-key run status, service-account exception
Policy Config — No Root Execution — c65 P3 — toggle + exceptions shape, live privileged-run status
Policy Config — No Root Execution — c65 P3 — toggle + exceptions shape, live privileged-run status
Policy Config — Require Tool Approval — c65 P4 — toggle + exceptions shape, never-ask run status, batch-pipeline exception
Policy Config — Require Tool Approval — c65 P4 — toggle + exceptions shape, never-ask run status, batch-pipeline exception
Policy Config — Tool Allow-List — c65 P5 — list-editor shape, approved tools with glob patterns and global/agent scope
Policy Config — Tool Allow-List — c65 P5 — list-editor shape, approved tools with glob patterns and global/agent scope
Policy Config — MCP Server Allow-List — c65 P6 — list-editor shape, approved MCP servers (the tool-supply-chain control)
Policy Config — MCP Server Allow-List — c65 P6 — list-editor shape, approved MCP servers (the tool-supply-chain control)
Policy Config — Sandbox Required — c65 P7 — level-select shape, sandbox-mode floor with live below-floor blast radius
Policy Config — Sandbox Required — c65 P7 — level-select shape, sandbox-mode floor with live below-floor blast radius
Policy Config — Credential Protection — c65 P8 — detector-list shape, sensitive-path categories with severity + 24h opens
Policy Config — Credential Protection — c65 P8 — detector-list shape, sensitive-path categories with severity + 24h opens
Policy Config — Data Redaction — c65 P9 — detector-list shape, Secrets + PII/PHI families (the HIPAA/GDPR carrier)
Policy Config — Data Redaction — c65 P9 — detector-list shape, Secrets + PII/PHI families (the HIPAA/GDPR carrier)
Policy Config — TLS Floor — c65 P11 — level-select shape, TLS version ladder with SP 800-52 minimum and weak-TLS counts
Policy Config — TLS Floor — c65 P11 — level-select shape, TLS version ladder with SP 800-52 minimum and weak-TLS counts
Policy Config — Prompt Inspection — c65 P12 — detector-list shape, injection heuristics (detect & contain, honest-partial)
Policy Config — Prompt Inspection — c65 P12 — detector-list shape, injection heuristics (detect & contain, honest-partial)
Policy Config — Output Validation — c65 P13 — detector-list shape, output detectors before downstream tools act
Policy Config — Output Validation — c65 P13 — detector-list shape, output detectors before downstream tools act
Policy Config — Provenance Pinning — c65 P14 — list-editor shape, pinned model/tool sources (pin-at-load, honest-partial)
Policy Config — Provenance Pinning — c65 P14 — list-editor shape, pinned model/tool sources (pin-at-load, honest-partial)
Policy Config — Spend Ceiling — c65 P15 — threshold shape, fleet/per-run ceilings with observed values and breach state
Policy Config — Spend Ceiling — c65 P15 — threshold shape, fleet/per-run ceilings with observed values and breach state
Policy Config — Quota Compliance — c65 P16 — threshold shape, quota warning levels; overage rejections always flag
Policy Config — Quota Compliance — c65 P16 — threshold shape, quota warning levels; overage rejections always flag
Policy Config — Posture Floor — c65 P17 — threshold shape with floor direction, minimum posture score vs fleet reality
Policy Config — Posture Floor — c65 P17 — threshold shape with floor direction, minimum posture score vs fleet reality
POL-701 — Independent verification that agent connections are governed
POL-701 — Independent verification that agent connections are governed
c65 iteration — Config column dropped; policy rows expand (UxTableListExpandRow) to the underlying rule, full framework mapping with inactive dimmed, severity/remediation, and the config-page link
c65 iteration — Config column dropped; policy rows expand (UxTableListExpandRow) to the underlying rule, full framework mapping with inactive dimmed, severity/remediation, and the config-page link
c65 iteration — direct duplicate of v2 with the config controls inside the expand row: shape components (list editor / threshold / level select / detector list) + Exceptions inline, config dims when the policy is off
c65 iteration — direct duplicate of v2 with the config controls inside the expand row: shape components (list editor / threshold / level select / detector list) + Exceptions inline, config dims when the policy is off
c65 iteration surface — the policy-catalog framework grid as baseline: kind label dropped, compliance-shield art in place of the kind icon, same live completeness/gap mechanics
c65 iteration surface — the policy-catalog framework grid as baseline: kind label dropped, compliance-shield art in place of the kind icon, same live completeness/gap mechanics
c65 hero
c65 full
c65 full
c65 full
c65 full
c65 full

In the archive

Artifacts

  • initial-prompt.md
  • initial-prompt.md
  • policy-definitions.md
  • qcontrol-application.md
  • research-frameworks.md

Qpoint Brand Style Guide