115 KiB
ASSESSOR project guidance
Implementation plan
- Read
docs/IMPLEMENTATION_PLAN.mdbefore architecture changes, broad refactors, persistence changes, importer/profile work, or server-readiness work. - State which plan phase the requested work belongs to and keep the change within the user's requested scope.
- Preserve the currently working local application while moving toward the documented browser/server target architecture.
- Do not mark a milestone or phase complete until its acceptance criteria have been verified.
- After a material, verified implementation step, update the plan's status, decisions, risks, and change log in the same change. Do not rewrite historical decisions silently.
- If the requested implementation conflicts with the plan, explain the conflict and update the plan only with the user's agreement or when the request explicitly supersedes it.
ASSESSOR product version
package.jsonis the single source of truth for the visible ASSESSOR product version. Header, About dialog and backend health response must continue to read that shared value; keep the rootpackage-lock.jsonentry and version contract tests synchronized.- Reassess the product version after every material, verified implementation batch. Increment the patch version for backward-compatible corrections and refinements, the minor version for a backward-compatible capability release, and the major version only for an intentionally breaking product or deployment contract.
- Do not increment the product version for documentation-only edits, test-only maintenance, unfinished work or every individual commit. Batch related work into one release version and record the decision in
docs/IMPLEMENTATION_PLAN.md. - A version change is complete only after the product-version UI/API tests and both production builds pass. Historical reports retain the version they documented at creation time and must not be rewritten.
Binding agreements and rule conflicts
- Treat documented user decisions, this file, and the implementation plan as binding acceptance criteria. Before changing an affected behavior, identify and preserve every relevant agreement; later work must not silently weaken, replace, or bypass it.
- If a requested change conflicts with a binding project rule, security boundary, or documented decision, stop that conflicting part and tell the user which rule blocks it and why. Do not implement a quiet approximation. Change the governing rule only after the user explicitly agrees, or when the request explicitly supersedes it.
- Every regression fix for a documented agreement must add a synthetic behavioral test for the exact user interaction that regressed, not only a lower-level helper or adjacent route. Keep that test as a permanent acceptance check.
- When requirements appear ambiguous, distinguish the supported interaction paths explicitly. Do not claim an agreement is fulfilled when only one path satisfies it and another normal path exposes different behavior.
Architectural boundaries
- Keep format parsing, structural analysis, semantic mapping, normalization, comparison, persistence, and presentation separated.
- Preserve original source values and provenance; normalized values must not destroy source data.
- Known tool profiles must extend the generic import pipeline rather than bypass it.
- Every new or extended scanner profile must first check its supported report formats for a usable native overall score. Declare
securityScoringin the profile with exact mapped properties, overall scope, scale, direction and result-population semantics, or an explicit reason why no usable native score is available. Native values take priority over calculated pass rates through the shared scoring engine; never infer overall-score semantics from an arbitrary field named score, a category score or a finding weight. Preserve source values and file/run provenance, version extraction changes and verify native priority, missing/invalid/conflicting values and safe fallback with synthetic fixtures. Seedocs/SCORING_MODEL.md. - React components must not contain source-specific parsing or direct database logic.
- Treat Tauri as the current local shell and a possible optional future shell. Do not make new domain logic depend on Tauri when a platform-neutral boundary is possible.
- The target deployment is an internal browser application with a backend and PostgreSQL. The browser must not access the database directly.
Core Engine and engines
- Explicit user decision 2026-10-01: ASSESSOR with all its existing functions is the Core Engine. The context enrichment (Phase 13E, "context engine"/"Kontext-Engine" in earlier text) is the Context Engine. The read-only Report Engine (Phase 7,
src/reporting/,server/reporting/) is an engine in the same sense. Future features arrive as further engines that provide a capability without changing the Core. The UI labelsContext/Kontextstay unchanged. - Explicit user decision 2026-10-05: the regulatory control mapping (Phase 13F, ISO mapping) is the Compliance Engine (
src/compliance/,server/compliance/,tests/compliance/). It is framework-neutral by intent: ISO/IEC 27001/27002 is its first corpus, later frameworks such as BSI or DORA arrive inside this engine without a Core change. It reads the Core only throughComplianceReadPort(single Result DB row by project, filtered Result DB pages, project, assessment and scan-run lists; explicit user decision 2026-10-05: additionally the internal-analysispolicy-evaluationrows of the same project and timeslot, used solely to read the GPO technical setting ID that the Result DB withholds, so a GPO setting counts once like its rolled-up Work record and the Work ISO facets match it; that ID is never displayed or exported and no other internal field is read) and stores mapping runs, accept/reject decisions, batches and AI overview runs only through its ownComplianceStore. Explicit user decision 2026-10-05: all AI integration belongs to this engine. The AI overview (service, model, Client Info panel) moved from the Core into it, and the Result DBExport JSONis the engine's 1:1 copy of what its AI features receive: the exact AI overview input built by the same function the overview sends to the model, and every distinct ISO mapping query with the Result DB rows that produce it (the retrieved candidate controls depend on the index and are not exported). The shared model clientserver/ai/litellm-client.tsstays Core platform code. The existing tables of migrations 025 (AI overview runs) and 026 keep their names and data and are owned by the engine; its writes never advance the Core repository revision. Because the Core deletes scan runs and assessments without knowing the engine, the engine removes AI overview runs of a deleted timeslot from its own table on start and on read. The Core project export receives the engine data, including succeeded AI overview runs, beside the Core export at the HTTP route. Its extension points are the Finding ReaderMap ISO controlsaction and its window, the Finding ReaderISO controlssection, the Result DBMap all ISO controlsbatch action andExport JSONaction, the Data Hub ISO corpus tile, the Client InfoCompliancetab (formerly theCompliancerow and before that theISO controlssection) andAI Overviewtab, and the WorkISO controlandISO themefacets. Switched off, the engine also removes the AI overview tab and its requests and theExport JSONaction. Explicit user decision 2026-10-05:Map ISO controlsopens a window likeAccepted Riskwith Accept and Reject per control (no third decision value). The Finding Reader lists the controls whose latest decision is accepted in anISO controlssection read likeDescription, after the summary fields. Client Info shows the accepted controls of the selected timeslot directly below the Context heatmap in the same tile layout without severity colour, each with its ISO 27002 theme and the number of deviation findings (a GPO setting counts once); a tile opens Work with theDeviationstatus and that control selected in theISO controlfacet, like a Context heatmap cell. Explicit user decision 2026-10-06 supersedes only the tile layout of that Client Info section, after feedback that it grows too large: the accepted controls are grouped by ISO 27002 theme in ISO order (Organizational, People, Physical, Technological; a theme without hits is omitted). Each full-width theme heading states its number of controls and of distinct findings (a finding counts once per theme) and opens Work with theDeviationstatus and that theme selected in theISO themefacet. Below it, its controls flow in columns of twice the compact tile width, one compact row per control sorted by finding count, showing the Annex A ID, the complete title (wrapped, never truncated) and the authoritative count, without an amount bar (removed the same day because it cost title width); a row opens Work exactly like the former tile. A theme shows its top six controls; a keyboard-accessibleShow all N controlsbutton below expands that theme andShow top 6collapses it again, and every theme starts collapsed for a new timeslot. The theme heading still opens all of its controls in Work. Explicit user decision 2026-10-06, later the same day, supersedes the in-page list and its top-six cap: Client Info shows aCompliancerow below the Context heatmap with one tile per framework, in the exact environment tile geometry and fact grid (its ownclient-compliance-gridwith the same tile rules; the environment row keeps exactly its six tiles), so later frameworks such as BSI or DORA add a tile instead of a section. TheISO 27001/27002tile showsControls(accepted controls),Findings(distinct findings) and the two themes with the most findings, each with its finding count (fewer when fewer themes have hits; an em dash while loading, never zero). ItsResultsbutton opens the shared Results window with the complete grouped list described above, without a cap; a theme heading or row there closes the window and opens Work as described. Explicit user decision 2026-10-06, again later the same day, supersedes the two-theme selection of the tile: afterControlsandFindingsthe tile shows all four themes in ISO order (Organizational, People, Physical, Technological), each with its finding count (0 findingswithout hits, an em dash while loading). A theme with hits is one click target over its whole fact cell and opens Work with theDeviationstatus and that theme selected in theISO themefacet; a theme without hits is not clickable, because the facet offers only values with hits. Hover changes only the cell surface; keyboard focus shows the blue focus ring. All six facts stay visible in this tile at every width, unlike the environment tiles, which show two facts below their measured four-fact width. Explicit user decision 2026-10-05: Work offers the Compliance Engine facetsISO control(one value per accepted control,A.8.20 · Networks security) andISO theme(Organizational, People, Physical, Technological) in mixed Work and in both GPO entry paths, directly before the permanent finalSource: Scan; this extends the GPO-only facet list. They read the accepted controls of every mappable finding of the timeslot (scanner findings by occurrence, GPO settings by scope and technical identity), offer only values with hits, count against the other active filters, keep an active selection while loading, and disappear with their filter cleared when the engine is off. Decisions stay global per scanner rule. Provisional explicit user decision 2026-10-05 (may change later): after a mapping succeeds, single or batch, the engine accepts its first two proposals in the model's order automatically, only the one if there is a single proposal, with the commentAccepted automatically: one of the first two proposals of the mapping.; a control that already has a decision keeps it, so a manual reject is never overridden, and a failure of this step never fails the mapping. Explicit user decision 2026-10-08: the Data Hub ISO corpus tile carries the switchMap new scans automatically(default off), stored only in the engine's own settings fileregulatory-corpora/auto-mapping.json, never in a Core table. While it is on, an engine-side backend watcher (server/compliance/regulatory-auto-mapping.ts) checks every 10 seconds throughComplianceReadPortonly: the active (not superseded) scan runs and, because GPO backups create no scan run, the GPO deviation rows of every timeslot as filtered Result DB pages. For each new scan run it starts the existing ISO batch over that run's deviations, and for each timeslot with new GPO deviation rows a batch over that timeslot's GPO deviations, each with a stable idempotency key. Rules with a succeeded or active mapping of the current pipeline versions are reused, so only new rules reach the model; failed mappings are retried, and the provisional auto-acceptance applies unchanged. What exists when the watcher starts or is switched on is the baseline and is not mapped retroactively; new imports wait while mapping is unavailable. Switching the Compliance Engine off in the Engines popup also switches this server-wide setting off (once, from any view); switching the engine on again leaves it off. Already started batches are never cancelled. Explicit user decision 2026-10-08 supersedes only the placement of the 2026-10-06 Client InfoCompliancerow: it is its own Client Info tabCompliance, after Overview (and Microsoft Defender for IoT) and beforeAI Overview, shown while the engine is on and the backend can deliver the timeslot; the Overview no longer contains it. The tab keeps the framework tile row exactly as decided, including each tile'sResultsbutton and window, so later frameworks add a tile there. Explicit user decision 2026-10-08, later the same day (supersedes the timeslot-only, batch-only history first agreed): because mappings and decisions are global per rule, the tab heading carries aLast mappingbutton showing the newest mapping of any client (Last mapping: <date, time> · Automatic|Manual|Single finding, followed byOther timeslot,Other clientorUnknownwhen it is not this timeslot and by the status while not completed, or plainNo mapping yet). It opens the windowISO mapping historywith at most 50 entries, newest first: every mapping batch of every client and every single finding mapping (Map ISO controlsin the Finding Reader). Columns: Started, Trigger, Scope, Status and the content-free counts Findings (a batch's own eligible findings; an em dash for a single mapping), Sent to model, Reused, Succeeded and Failed. Entries carry no client, rule, scope ID, filter or key. A batch is Automatic when the watcher started it (idempotency key prefixesauto:/auto-gpo:), otherwise Manual. Explicit user correction 2026-10-08: Scope names where an entry came from relative to the shown timeslot:This timeslot(a batch whose scope shares an assessment or scan run with it, or a single mapping started there),Other timeslot(same client, another timeslot),Other client, orUnknown(a single mapping without a recorded origin).Map ISO controlssends the timeslot the Finding Reader shows; the server validates it against the client and stores only SHA-256 origin tokens of the client and of each assessment and scan run, never their ids, because mapping runs are global and exported with every client; an invalid timeslot leaves only the client as origin. Every mapping run records its trigger (singleorbatch) in the engine's own run data; runs from before 2.21.0 record none and are not listed as single mappings, because they cannot be told apart from batch runs. While a listed entry runs, the tab refreshes every five seconds without falling back to em dashes. Returning to the tab shows the last overview of that client and timeslot at once from a bounded in-memory cache of at most eight timeslots and always requests a fresh one, which replaces it; a failed refresh keeps the shown values. - Engines may read the Core without restriction but never write to, change or override it. They read only through a declared read-only port and the read-only database access, never through Core tables or internal modules directly. What an engine shows or exports still obeys the Core's privacy and Result DB disclosure rules.
- Dependencies point one way: an engine depends on the Core, the Core never depends on an engine. The Core works unchanged with every engine switched off; each engine keeps a permanent on/off invariance test like the Context layer's. Engines do not build on each other except through another engine's published results.
- An engine that needs storage gets its own schema or tables after separate approval with backup and migration, never columns in Core tables. An engine cannot create findings: new scanner profiles, importers and parsers write Core data and are always Core changes.
- Explicit Core consent: a change to the Core requires that the user names the Core or releases the affected Core area for the current request (for example
Core-Freigabe: Evaluation). Consent applies to that request only and does not carry over. When a chat request would change the Core without such consent, stop that part, name the affected Core area and ask for explicit consent; do not implement a quiet approximation through an engine. - Core areas:
Ingest(recognition, parsing, extraction, scanner profiles, GPO ingestion, import workers),Normalization(canonical model, mapping, finding identity, status/severity),Evaluation(GPO baseline comparison, verdicts, conflict/duplicate flags, comparison, scoring),Store(repositories, PostgreSQL, migrations),Client Records(reviews, risk acceptances and their transfer on reimport: everything client-owned that must survive a reimport; its server persistence stays inside the Store repository),Disclosure(Result DB disclosure policy, exports),Reference Catalogs,Shared Kernel(src/shared/),Presentation(shell, design system, Data Hub, Work, Client Info, Pathfinder, Finding Reader),Platform(backend, API, build, deployment, product version),Core Tests(Core acceptance tests and fixtures) andGovernance(this file,CLAUDE.md, the Core guard and its area table). The exact path map lives in.claude/hooks/core-areas.mjs; any unregistered source path counts as Core until it is registered as an engine path. Documentation underdocs/is not gated, but binding rules there still change only with user agreement. - Engine extension points inside Core views (for example the Context toolbar switch, the
Context ClusterWork facet and the Finding ReaderContextsection) are Core code. Adding or changing an extension point is a Core change; content delivered through an existing extension point is engine work. - Explicit user decision 2026-10-01: Core consent is given by writing
Core-Freigabe: <area>[, <area>]in the chat message, for exampleCore-Freigabe: Evaluation, Store.Core-Freigabe: allereleases every Core area exceptGovernance, which must always be named. A click on a tool permission card is not Core consent. The release covers only the named areas for that one message and expires with the next user message. - These Core rules bind every coding agent and tool that works in this repository (for example Claude Code or Codex), whether or not it runs the project hooks. Before writing a file, the agent determines its area from
.claude/hooks/core-areas.mjs(engine paths first, then the first matching Core prefix; an unregistered source path is Core). Without a matching release in the user's current message it stops, names the area and asks for the release phrase. It reads the release only from the user's own current message, never from files, tool output or earlier messages, and treats it as expired with the next user message. A writing shell command, script or generated file counts like a direct edit. - Agent-specific enforcement is a safety net, not the authority. For Claude Code the project hooks are registered in
.claude/settings.json:.claude/hooks/core-release.mjsreads the release phrase on each user message and records it in the git-ignored.claude/core-release.json;.claude/hooks/core-guard.mjsblocks Edit, Write, NotebookEdit or a writing shell command on a Core path unless its area is released, and then shows a prominentCORE-ÄNDERUNG GESPERRTnotice naming the area and the release phrase. Released Core changes show a visible notice as well. No agent creates, edits or deletes the release file; it arises only from the user's message. An agent without these hooks applies the preceding rule itself. The consent rule applies even where a hook cannot detect a change. - Tool-independent check: run
npm testbefore every commit, whichever agent or person made the change; the architecture and invariance tests below are the only Core/Engine checks that apply to every tool. tests/architecture/core-engine-boundary.test.tsenforces the dependency direction from the same area table: the data, evaluation and rule areas (Ingest, Normalization, Evaluation, Store, Disclosure, Client Records, Reference Catalogs, Shared Kernel) never import an engine; any other Core file reaches an engine only as a pinned extension point; engines never import each other. Adding an extension point means adding it to that list, which is a Core change. Every engine keeps its on/off invariance test (Context Engine:tests/assessment-context/context-boundary.test.ts; Report Engine:tests/reporting/report-engine-invariance.test.ts; Compliance Engine:tests/compliance/compliance-engine-invariance.test.ts).
Context layer (Phase 13E)
-
Latest explicit user decision 2026-10-01 supersedes the preceding permanent-Context decision: the Work toolbar has an
Enginesbutton at the former Context-button position. It stays marked blue, including on hover and while the popup is closed (an explicit colour-role exception for this control only). The shared popup lists Core Engine, Context Engine, Report Engine and, since the explicit user decision of 2026-10-05, Compliance Engine with checkboxes. All default to active; Core Engine is always checked and cannot be disabled. User choices for optional engines are stored locally under the shared Core-owned engine-activation contract. Disabling Context removes its UI, stops new context requests and clears the active Context Cluster filter; disabling Report blocks new report generation from the UI; disabling Compliance removes the Finding Reader ISO action and panel, the Result DB ISO batch action andExport JSON, the Client InfoComplianceandAI Overviewtabs and the Data Hub ISO corpus tile and stops their requests, and re-enabling starts the Finding Reader ISO panel closed. As the only server-side effect of this local preference (explicit user decision 2026-10-08), disabling Compliance also switches the automatic ISO mapping of new uploads off for the whole server; re-enabling does not switch it on again. Already submitted backend work is not cancelled by this local preference; its late UI output is suppressed. Cluster badges still select the exact Work filter, and the Context detail section still starts collapsed. Engine independence and Core invariance remain binding. -
Explicit user decision 2026-10-01 supersedes the earlier Context on/off, default-off, locally saved switch, hover-button and badge-scroll agreements: Context is permanently active and the global toolbar Context button is removed. Ignore obsolete locally saved on/off preferences. Clicking a Finding Reader Context cluster badge selects that exact
Context ClusterWork facet value, replacing the previous cluster selection while preserving other filters. The Context detail section still starts collapsed for each finding and opens through its own summary. All read-only, provenance and verdict/score boundaries remain binding; only an explicit cluster-filter selection restricts the Work record set. -
Explicit user correction 2026-10-01: the Finding Reader
Contextsection is collapsed by default, including after changing the finding or re-enabling the layer. Its summary opens and closes it with mouse or keyboard. A Context cluster badge opens the section before scrolling to it. This disclosure is separate from the global Context layer switch. -
Explicit user correction 2026-09-30: the
Contexttoolbar button keeps its neutral surface on hover while off. Yellow marks only the enabled state after activation; hovering must neither darken the button nor introduce/remove the yellow active state. A second click restores the neutral surface even while the pointer remains over the button. Verify both themes. -
Explicit user decision 2026-09-30: the context engine is a parallel, derived and switchable second reading of stored ASSESSOR results. The technical view stays authoritative. Context never changes, overrides or questions a verdict, score, technical filter or status, review, risk acceptance, Result DB row or Priority Finding. The authoritative ASSESSOR verdict is only displayed next to context, never re-derived. Context produces no pass/fail, no secure/insecure judgement, no platform-default misconfiguration from
Not configuredand no normalized priority. The remediation lever is a plain count of affected conditions and clusters, with no rank, effort or risk score. -
The data flow is one-way: ASSESSOR results -> context engine -> UI and Report Engine. The engine lives in a platform-neutral module, runs in the backend and reads through a read-only repository port and read-only database access. It never writes to ASSESSOR data and never populates the evaluator's
PolicyRiskRule,PolicyDependencyRuleorstronger/weakerhooks. It has no own persistence until separately approved with backup and migration. UI and reports read the same context results with the same engine and catalog version. -
Explicit user decision 2026-10-01, later the same day (supersedes the separation of tier 2 in the following rule and "never guessed" / "no title or similarity heuristic" in the rule after it): the goal is context for every deviation, accepting that a recognized or estimated assignment is not always correct, because a deterministic, reproducible heuristic is preferred over an LLM. The engine assigns every scanner and GPO deviation to a cluster in this fixed order and stops at the first tier that yields one: (1)
catalogued- catalogue rule, CIS report section or a declared technique; (2)recognized- a distinctive term of the recognition vocabulary in the rule text or setting name; (3)recognized- at least two terms of one cluster in description or recommendation, or a technical anchor (setting name, registry value or user right the catalogue knows); (4)estimated- the most similar already assigned finding or catalogued text (local TF-IDF); (5)estimated- the cluster most often assigned to the same scanner category in the same scope. Only a deviation without any usable signal stays inOther Deviations (not yet catalogued). Recognized and estimated assignments count in clusters, badges and theContext Clusterfacet; every assignment carries its confidence (catalogued,recognized,estimated), method and evidence, which badges and the Finding Reader show as text without a new colour. Identical input always yields identical assignments, independent of input order. Context still never changes a verdict, score, status, Work count outside the context facet, Result DB row or Priority Finding, and still uses no external service or AI model. The gap list becomes a review list of recognized and estimated assignments; confirming one makes it a catalogued rule through a reviewed source change. -
Explicit user decision 2026-10-01 (supersedes "never guessed" and "no title or similarity heuristic" in the next rule, only for the two tiers named here; its separation of tier 2 is superseded by the preceding rule): the Context Engine recognizes context automatically beyond the catalogued rules, as validly as possible. (1) Declared technique: a deviation whose scanner itself declares an active ATT&CK technique ID (evidence
declared, exact ID) joins the cluster the catalog maps that exact technique to; this tier counts like a catalogued rule. A tactic or a mentioned reference never assigns a cluster, and a parent technique covers a sub-technique only where the catalog lists it. (2) Recognized from rule text: a deviation that no rule, report section or declared technique assigns is matched locally and deterministically against a versioned recognition vocabulary of distinctive technical terms per cluster. Each result is labelledautomatically recognized, names the matched term and the vocabulary version, is phrased as a suggestion, and stays separate from catalogued evidence: it never changes a cluster state, condition count, Work facet count, badge, score, Result DB row or report statement of the catalogued tier, and the finding additionally stays inOther Deviations (not yet catalogued). Recognition never uses an external service or AI model. Its precision is measured against already catalogued findings (synthetic fixtures and the released Dummy client); a term whose matches contradict the catalogue is removed or narrowed. Showing the recognized tier in a Core view is a separate Presentation change. -
Every context statement comes from a versioned catalog rule with a cited, offline-stored source. Uncatalogued settings stay
not semantically mappedand are never guessed. Statements carry catalog version and source and are phrased as favouring, never as exploitable or confirmed. Explicit user decision 2026-09-30: the English application UI labels the layerContextand uses the English statements (favours); German reports useKontextandbegünstigt. Unknown conditions are shown separately and never count as satisfied or unsatisfied. Explicit user decision 2026-09-30: context covers findings of all scanners, not only GPOs. Scanner evidence comes only from a catalogued exact tool and rule ID withfail-means-metpolarity (a benchmark rule additionally names its exact setting as a renumbering guard); pass refutes, every other outcome stays unknown, and no title or similarity heuristic links findings. Explicit user decision 2026-09-30: ATT&CK references link findings in the context layer only when the scanner itself declares them (declared, active catalog ID, exact ID); mentioned references never do. Such a grouping states the same declared tactic or technique according to the scanners, never a common attack path or cause. Explicit user decision 2026-09-30: D3FEND countermeasures the scanner itself declares (declared, active catalog ID, exact ID) group findings the same way, separately from ATT&CK; such a grouping states the same countermeasure according to the scanners, never a common cause. Explicit user decision 2026-09-30: CIS-CAT findings are also grouped by their CIS control area, derived only from the exact rule-number hierarchy (9.1.1lies in9.1and9) inside the same scan run, because other benchmarks reuse the numbering. Section titles and stated Pass/Fail counts come from that scan report's section-score table; an ambiguous title or count is left out. Such a grouping states the same benchmark section, never a proven attack chain. Explicit user decision 2026-09-30: for every scanner, the official scan report is authoritative. Rule IDs, rule text and outcomes it states are accepted as they are; no separate verification against vendor documentation is required. Exact rule-ID matching and the rule that non-executed checks stay unknown remain unchanged. Exclusions are based on a rule's meaning or polarity, never on missing documentation. Explicit user decision 2026-09-30 supersedes polarity-based exclusions: everyfailorwarningresult is a finding that ASSESSOR never questions, and it enters the context structure. The condition wording states exactly what the finding asserts, never a stronger claim. Assignment order: exact tool and rule ID; for CIS-CAT otherwise the most specific benchmark section title of the same scan report; otherwise the visibleOther Deviations (not yet catalogued)cluster. A pass refutes; not-run and similar outcomes stay unknown. The context structure is the user's primary working tool for a cross-scanner overview, not an optional add-on. The same applies to GPO settings: a setting whose authoritative rolled-up baseline verdict is a deviation enters the context through that verdict, read as it is and never re-derived (a pass refutes). A catalogued value semantic takes precedence; otherwise the most specific catalogued setting or registry key decides, elseOther Deviations (not yet catalogued). Declared GPO evidence and observed scanner evidence stay separately attributed and their disagreement is shown. GPO facts describe backup configuration only, never effective host state. They are kept per backup instance with no asserted precedence, andNot linked, conflicts and duplicates stay marked. ATT&CK and relationship derivations never enter the Result DB. -
Switched off means no request, no computation, no rendered context element and no active context filter. Switching off removes an active
Kontext-Clusterfilter. The layer defaults to off, and the choice is stored locally per user. TheKontext-ClusterWork facet is visible only while the layer is on;Source: Scanstays last. Context uses existing tokens and no pass/fail status colors. -
Keep a permanent acceptance test: Work, Client Info, score and Result DB show identical counts and verdicts with the layer on and off, and an engine run leaves stored data unchanged. Scope, UI order and acceptance criteria are in
docs/IMPLEMENTATION_PLAN.md, Phase 13E.
Canonical local PostgreSQL
- The single canonical local ASSESSOR datastore for this workspace is the existing Docker Compose project
assessor-2_0, containerassessor-2_0-postgres-1, databaseassessor, and volumeassessor-2_0_assessor-postgres-dataon127.0.0.1:5432. - Every local App/Backend start must reuse that datastore. Never create an alternative ASSESSOR database, Compose project, PostgreSQL volume, or fallback port for this workspace.
- If the canonical datastore is unavailable or port
5432is occupied by a different container, stop and report the conflict instead of spawning or selecting another database. docker-compose.postgres.ymlmust keep the canonical Compose project name and external volume binding. Never delete, replace, recreate, or initialize the canonical volume as an empty datastore.- Before an approved persistence migration or destructive database operation, create and verify a backup. Unrelated Docker applications, containers, and volumes remain out of scope.
Binding ASSESSOR design language
- Explicit user correction 2026-09-18: the current, user-approved Data Hub, Work, and Pathfinder screens are the binding visual references for ASSESSOR's Ableton-inspired design language. This applies to every view, explicitly including Client Info, and to proposals, generated images, prototypes, and production implementation.
- Before any visual task, read
.claude/skills/assessor-ui/SKILL.mdand the relevant current components andsrc/styles/ui-tokens.css. The approved views and these current project agreements take precedence over older skill examples, copied asset templates, and superseded Client Info exceptions. - Use Data Hub for flat square tiles, full-circle donuts, compact action buttons and branding; Work for list/detail hierarchy, typography, badges and reading surfaces; Pathfinder for stable filter/work/detail zones and compact controls. Preserve these approved views as references; do not redesign them as a side effect of Client Info work.
- Keep the current neutral theme surfaces, transparent segments, flat tiles, subtle separators, local Inter typography, shared 20px panel inset and shared control geometry. Reuse existing tokens and components. Do not reinterpret Ableton as a new palette, a literal copy of another application, or a return to obsolete UI dimensions.
- Use the shared yellow/amber roles for primary actions and persistent selection, with the explicitly blue table-row reading marker documented below; blue remains the keyboard-focus role elsewhere. Use semantic status colors for the established status and data-visualization roles. A tool or graph-category color does not authorize a new selection or button color. No gradients, decorative shadows, glass effects, hover lift, generic rounded dashboard cards, new navigation shell, new logo, or Client-Info-only visual theme. The 2026-09-25 user rollback removes the short-lived donut-ring shadow exception; arcs remain solid colors without gradients.
- Improve quick comprehension through grouping, alignment, readable labels, a small set of relevant overview values and existing detail/disclosure patterns. Never shrink body text or structured data below their agreed roles to fit more content, stretch sparse tiles across unused space, or invent metrics to populate a layout.
- All mockups must use the approved views as actual visual references, preserve the existing shell and metric meanings, and clearly identify synthetic example data. A rejected generated image is not a design reference. The three generic Client Info mockups rejected on 2026-09-18 are explicitly not approved.
- Visual acceptance: a Client Info proposal or implementation must be recognizable as the same application as Data Hub, Work and Pathfinder even without its logo. Check the shared surfaces, typography, buttons, selection, spacing and donut geometry at normal application zoom; inspect both themes for implementation. Distinguish a documented rule, a proposal and an implemented/verified UI change.
UI typography
- Use the locally bundled Inter variable font as the application typeface. Do not introduce view-specific display, condensed or serif families; hierarchy comes from size and weight. Explicit user exception: paths use the shared technical-path textbox and local system monospace stack; other content remains Inter. Do not download additional fonts.
- Use only the visual weights Regular 400, Semibold 600, and Bold 700. Bold is reserved for branding and exceptional emphasis.
- Use the semantic typography roles: H1 56px/600, H2 32px/600, H3 18px/600, detail titles 20px/600, H4 16px/600, continuous prose and readable tile values 16px/400, structured table/Grid/Raw Data content and informational field labels 14px/400, compact control labels and metadata 12px, badges 11px, and buttons/controls 13px/600.
- Preserve normal title case for H1-H4, field labels, and buttons. Uppercase is limited to compact table headers, badges/categories, and the ASSESSOR wordmark.
- Explicit user decision 2026-09-20: the smallest text intended to communicate application information is
14px; this includes table cells, table headings, tile content and informational field labels. Readable values and continuous prose use16px. For example, the Client Info Directory tile rendersDomainat 14px andsevenkingdoms.localat 16px. Do not demote either role to a metadata or compact-control token merely to fit more content. - Compact interface text such as button captions, technical metadata, badges and comparable control annotations may use a smaller type size. These exceptions must not carry primary table, tile, field-label or prose information.
- When adding or changing styles, preserve this distinction instead of reducing content text to a compact UI-label token.
UI panel spacing
- The Work panel is the binding spacing reference: content inside every rounded main panel starts
20pxfrom each outer edge. - Use
--panel-content-insetthrough its compatibility alias--panel-inset; do not introduce local substitute values for existing or future main panels. - Apply the inset exactly once on the view's root content container. Split panes and edge-to-edge structures belong inside that inset and must not add a second outer inset.
- Keep the 20px outer inset at responsive breakpoints unless the user explicitly changes this standard.
UI Finding Reader first read
- Explicit user decision 2026-09-25: every Finding Reader states within seconds what is wrong and what to do. Directly below the setting or rule heading, a
Problemblock (Summaryfor a passed result) with the outcome-colored marker and a separateNext stepblock with the orange--next-step-accentmarker precede all explanatory text; both markers use--marker-width. Background (description, technical explanation, rationale) follows openly, references and documentation after it; work tracking and Additional Information stay collapsed at the end. - Scanner profiles declare their first-read fields in
presentation.firstRead; React components never name scanner-specific fields. Use only retained source values: a missing field removes its line and nothing is summarized, rephrased or invented. Counts come from explicit source counts or linked result tables; a result row is red or green only where the source marks it (CIS-CAT criterion/evaluated rows with the finding outcome,resultSheetRowStatusCellsmarkers). Split a long remediation only at a paragraph boundary and keep the rest complete behindFull remediation. An imported documentation link is offered only as a plain https URL withnoopener noreferrer. - Explicit user decision 2026-09-25: every documented standard Windows code shown as text carries its meaning directly after it, in muted regular text: well-known SIDs, standardized domain RIDs (
S-1-5-21-<domain>-500/512/...; the domain part is never resolved), User Rights Assignment constants (SeNetworkLogonRight->Access this computer from the network) and registry type codes (4->REG_DWORD). The single list lives insrc/shared/windows-codes.tsand is applied centrally byPathText; the original code stays unchanged and authoritative, unknown or customer-specific codes stay plain, and a meaning already stated next to the code is not repeated. - Explicit user decision 2026-09-28 supersedes the Results-only part of the 2026-09-25 Maester rule: the first prose paragraph of Maester's native test result (
ResultDetail, orResultnext to a separateStatuscolumn) is theProblemstatement, verbatim, cut only where a heading or table begins. Its tables and the complete text stay in Results; source-marked row counts and the https documentation link remain. A bare status word is never a statement. GPO findings use the GPO problem summary rules above. - Explicit user exception 2026-09-30 (Microsoft Defender for IoT Alerts): when the alerts of one alert type carry different native descriptions, the finding shows the whitespace-separated words shared by every description in source order, each differing part replaced by
…. Nothing is added or rephrased. Explicit user correction of the same date: it is labeled plainDescriptionwithout a derived-text suffix; the separate field keycommon-descriptionkeeps it distinguishable from a native description. A single alert or identical texts keep the originalDescriptionunchanged, including addresses (user decision); if no word is shared, no derived text appears. Every original description stays unchanged in the Alerts Results table. This exception applies to no other scanner or field. - Explicit user correction 2026-09-25: when a scanner's first-read remediation explicitly introduces a PowerShell command, render that command in its own readable, contained block beneath the explanatory sentence. Keep the original command text complete and copyable, do not rewrite its parameters or split the remaining remediation before the original paragraph boundary, and retain the full source field unchanged.
UI Pathfinder graph text and details
-
Explicit user decision 2026-10-01 supersedes the right-hand placement below: Pathfinder uses the shared horizontal Work filter controls above the graph. Details occupy the former filter column on the left, including at narrow widths. Search, My Workspace and Path Snapshot remain available. The shared blue Engines button is available in Work, Client Info and Pathfinder with identical persisted choices. Preserve all graph text, selection and extraction behavior.
-
Explicit user correction 2026-09-25 supersedes the earlier Pathfinder
Off/Labels/Textmodes and in-graph node cards: node text starts on; the toolbar has only theTexttoggle for turning that text off or on. Selecting, deselecting, marking, extracting, or hovering a node must not change the text setting.Reset viewrestores text on. Keep graph nodes and their compact text in the graph, while node information and actions appear only in the rightDetailspanel. Do not render hover or selected-node cards over the graph. -
Explicit user extension 2026-09-25: the right
Detailspanel shows the same severity-colored Finding hexagon as the Work tile next to a Finding title. Add concise, source-backed context there when available: native source status, tool, exactSource Rule ID, category and MITRE ATT&CK IDs. Omit missing fields; do not place a Finding hexagon or Finding facts on relation nodes. Keep the full Finding and evidence available through the existing Work and Results actions. -
Explicit user correction 2026-09-25: the Pathfinder action is named
Extract Path. It is available only for a selected graph node and isolates that node, its directly connected nodes, and only their connecting edges. A filter orMark allbranch alone must not trigger extraction of the whole graph or broaden the selected path.Exit Extract Pathrestores the prior graph selection and view. This supersedes the earlier broad-branchExtractbehavior;Mark allkeeps its separate branch semantics. -
Explicit user correction 2026-09-25: Pathfinder Details facts must give values a readable column at the normal inspector width. Do not cap that column to a fraction of its own auto width or break ordinary words and numeric values inside a line. Wrap multiword values at spaces; allow long unbroken technical identifiers to scroll within their own value area without clipping adjacent content.
UI DB Structure table flow
- Explicit user correction 2026-09-25: every table button in the DB Structure data-flow diagram opens that table's columns and relationships in the shared floating popup, instead of adding an inline detail section below the diagram. Referencing-table buttons inside the popup navigate to that table within the same window; Close and Escape dismiss it and leave the flow intact. This supersedes only the inline-detail placement from the DB-Structure flow implementation. The separate layered table dictionary retains its disclosure behavior.
- Explicit user correction 2026-09-25: DB Structure omits the redundant introductory
Database dictionary/Relational schemacopy block above the metrics and the explanatory sentence beneathData flow. Keep the schema status and refresh action, metric tiles, flow heading, table buttons, popup and dictionary disclosure.
UI Work filter context
-
Explicit user extension 2026-09-18: the Work toolbar's
CSV,MDandHTMLbuttons export the complete current filtered/sorted Work record set, including the same linked and embedded Results used by the Results window. Marking alone does not select export rows;My Workspacerestricts them only when active, alongside ordinary filters and drilldowns. Use exactly two content columns,Soll-ZustandandAbweichungen, with source-backed remediation/verification, original technical facts, scoped GPO provenance, and explicit missing-evidence notices. Preserve neutral verdicts and review-versus-rescan boundaries. Build the frozen projection only on export, not on navigation. Oversized CSV cells use explicitly identified continuation rows of the same finding without truncation. This view snapshot is separate from the curated Arbeitsgrundlage indocs/REPORT_STRATEGY.md. -
A unique
Source: Scanselection is a semantic tool context even when Work remains on the project-wideAll Recordssheet. Visible and active facets must follow the selected tool context rather than the aggregate sheet profile. -
Explicit user correction 2026-09-25: changing
Source: Scaninside Work, including back toAll, starts the newly selected source with the clean Work default. Clear the previous search, status override, other facets, record-ID/path restriction andMy Workspacerestriction, restore the standardDeviationstatus and normal sort, then apply the selected source. Keep the current Work view mode and current client/timeslot. This applies to an in-Work source change, not to an incoming Client Info or Pathfinder drilldown before the user changes Source. -
For a GPO-only Work context, whether reached through the dedicated GPO sheet or
Source: Scan = GPOs, show onlyResult Status, the available GPO facetsBaseline,Comparison,Conflict,Description source,Diagnostics,Duplicates,Imported,Policy section,Policy type, and the permanent finalSource: Scancontrol. Do not show CIS, severity, category, MITRE, target, result-message, review, or scanner-specific facets. -
Explicit user correction 2026-09-17 supersedes only the category exclusion in the preceding GPO-context rule:
Categoryis a permanent GPO Work filter in both supported entry paths, including when its only current value isGPOs. Keep it directly afterResult Status. Severity, CIS, MITRE, target, result-message, review and scanner-specific facets remain excluded from the GPO-only context;Source: Scanremains last. -
[The
GPO & Baselinemapping is superseded by the 2026-10-04 Security Domain decision below.] Explicit user extension 2026-09-17: Work also exposes a distinctSecurity Domainfacet immediately afterCategory. It must use the exact shared Client Info security-domain catalog and record assignment, never a second filter-only categorization. It is available in mixed Work and both GPO entry paths; a pure GPO scope maps toGPO & Baseline. Domain selection and Client Info drilldown must therefore select the same record identities, while ordinary active Work filters continue to apply.Source: Scanremains last. -
[Eight entries and
Unclassifiedsuperseded by the 2026-10-04 decision below: six entries, noUnclassified; the remaining rules stay valid.] Explicit user correction 2026-09-18:Security Domainalways offers all eight Client Info catalog entries in catalog order, including selectable zero-hit domains in mixed Work and both GPO entry paths.Unclassifiedremains an additional option only when present in the loaded sheet. Counts respect the other active filters; a zero-hit selection must not silently remove itself, the active status, or another still-valid facet selection. A Client Info domain-deviation drilldown uses this visible domain facet rather than a fixed record-ID path, so the user can change domains in Work. Explicit review-only and individual-finding paths retain their separate scope semantics. -
Explicit user decision 2026-10-04 supersedes the eight-domain catalog, the text-pattern assignment,
GPO & BaselineandUnclassified: there are exactly six Security Domains in this order:Identity & Authentication,Privileged Access & Delegation,AD Infrastructure & PKI,System Hardening,Cloud & Collaboration,Monitoring & Recovery. GPO is a delivery path, not a domain; the GPO view stays available throughSource: Scan = GPOsand the GPO facets. One classifier in Evaluation (src/evaluation/security-domains.ts) serves Work, the Work facet, Client Info and the report projection. It reads only the fields Raw Data shows for a record and never the title, description, remediation prose or the outcome, so pass and fail follow the same rules. Each check gets exactly one domain from the first tier with a hit: (1) native category, exact rule ID or native tag, (2) CIS-CATBenchmark sectiontitle path from the same scan report (never the number alone), (3) suite or control ID, (4) GPO technical identity (Policy type,Policy section,Registry pathby longest key), (5) the source's own fallback area, else a visible global fallback. Mapping tables are versioned per scanner profile (src/profiles/<tool>/<tool>-security-domains.ts); a new scanner brings its table or lands deliberately in tier 5. Every assignment carries tier, method and deciding field; per source, the tier-5 share shows where a table needs entries. Entra checks (EIDSCA, CISA MS.AAD, Maester/Entra, Conditional Access, MFA, Identity Protection) are Identity & Authentication; Exchange, Teams, SharePoint, ORCA, Intune and other tenant configuration are Cloud & Collaboration; Purple KnightGroup Policy Securityis System Hardening. The derived Raw Data fieldsBenchmark section(CIS-CAT) and, for security-template settings without a comparison,Policy sectionandRegistry pathare display projections of retained facts; they need no reimport. The assignment never depends on the Context Engine. -
Explicit user decision 2026-09-17 supersedes the previous six-value list: the GPO
Result Statuschoices are exactlyAll,Deviation,Passed,Not configured,No baseline rule,Not comparable,Conflicts, andDuplicates. Keep the seven non-All choices selectable at zero hits; never merge scanner-only status vocabularies into a GPO-only context.Deviation,Passed,Not configured,No baseline ruleandNot comparablematch the authoritative rolled-up policy verdict;ConflictsandDuplicatesmatch the corresponding diagnostic category flags. One policy setting may therefore belong to bothDeviationandConflictsorDuplicates. -
Explicit user decision 2026-09-17:
No baseline ruleis the score-neutral verdict for a retained customer setting whose resolved technical identity has no applicable Microsoft baseline recommendation in the compared baseline set. Every aggregated customer state must reach Work under exactly one verdict: an evaluated verdict where a baseline rule exists, otherwiseNo baseline rule. It is distinct fromNot configured, which is a recommended baseline setting absent from the analyzed backup set, and it must never be presented as a deviation, remediation obligation or score input. A diagnosticConflicts/Duplicatesflag marks such a setting without replacing its verdict; unresolved identities stay out of this verdict and takeNot comparableinstead. -
Explicit user decision 2026-09-17:
Not comparableis the score-neutral verdict for a retained customer setting whose delivery mechanism has no comparable technical policy identity. Today this is always a Group Policy Preference. Never resolve a preference into a policy identity and never compare it with a Microsoft baseline recommendation: its action, item-level targeting and apply-once semantics differ from a policy setting, so a baseline verdict over it would be invented. Keep the retained CSE, action and item-level targeting readable in the agreed GPO columns; do not add a GPO Work column or facet for them. Identical or differing preference instructions are not proven duplicates or conflicts, soNot comparablecarries no diagnostic flag. The observation-level unresolved-identity gap reporting stays in place and must report each observation once with its authoritative resolver reason, never restated a second time by snapshot aggregation. -
Never infer a GPO verdict from comparison prose, historical results, baseline text, guidance or evidence. Use only the authoritative rolled-up policy verdict and explicit conflict/duplicate flags. A foreign
Passstring must not make a not-configured, review or failed policy setting matchPassed. -
When the selected tool context makes an existing facet filter invalid, remove that incompatible filter so it cannot remain invisibly active. Removing the tool restriction restores the appropriate aggregate facets without changing source data.
-
Explicit user extension 2026-09-17: also offer
GPO backups with failing settingsin the GPO Work context. Its all-counted and individual-backup selections use the Processing tile's exact project/assessment/backup-instance identity and select source-linked Fail comparisons, not inferred per-backup verdicts. Keep all contributing evidence, conflict/duplicate flags and historical evaluation readiness intact; Source: Scan remains last. This extends the facet list above.
UI Result DB filter consistency
-
Binding user requirement 2026-09-28 (supersedes the 2026-09-25 decision to retain the concrete GPO Istwert, exact scanner values and baseline releases): the Result DB (UI, API and JSONL) must be privacy-compliant and must not provide an attack guide. It carries no value that fingerprints the assessed environment or calibrates attack effort. Retain the public rule ID when validated, tool, result/severity/outcome, result type, deviation/IOE, public scanner guidance, the GPO technical setting ID, Sollwert, comparison relation and baseline family. Withhold the GPO customer value (Istwert) and every principal in it, customer-value placeholders, GPO source counts, concrete baseline releases (only the family, for example
Microsoft Security Baseline - Windows Server), client-owned review/priority/risk-acceptance state and supplemental counts, scores, functional levels and versions (only binary configuration states cross). In non-benchmark scanner prose, exact counts, dates, times and durations become[count],[date],[time]and[duration]; public technical tokens (dotted versions, CVE/KB/ATT&CK/rule IDs, product names, ports, event IDs, public SIDs) stay. Explicit user correction 2026-09-28: redaction must not damage public guidance. Numbered steps (1.,2)) stay; the recommendation field alone keeps vendor thresholds (at least 8 characters,more than 180 days,15 or more), while titles and descriptions stay fully redacted. Group Policy and registry paths (Computer Configuration\...,HKLM\...,System\CurrentControlSet\..., GP node paths, hard-wrapped path lines) and documented Windows authorities (BUILTIN,NT AUTHORITY,NT SERVICE,NT VIRTUAL MACHINE,RESTRICTED SERVICES,Window Manager,Font Driver Host) are not accounts. Only standalone IPv4 addresses are redacted: never part of a longer dotted sequence, aRulereference or a CIS rule number, and never a documented range boundary (RFC 1918, loopback, link-local and the public space around RFC 1918). Explicit user correction 2026-09-28 (policy 3.2.0): inline ordered lists (a run 1, 2, 3 ... of at least two items, tolerating one repeated or skipped source number) and documented attribute flags (adminCount=1) stay;set to Nis a retained recommendation value only in the recommendation field. Vendor and standards documentation links and host names stay (microsoft.com and cloud.microsoft, azure.com, office.com, windows.com, aka.ms, github.com, maester.dev, cisa.gov, dhs.gov, whitehouse.gov, cisecurity.org, mitre.org, nist.gov, pingcastle.com, semperis.com, citrix.com, owasp.org, ietf.org, rfc-editor.org, bsi.bund.de) unless the link carries an@, a tenant marker (onmicrosoft,sharepoint), a private literal or another non-public host. Tenant hosts (*.onmicrosoft.com,*.sharepoint.com,login.microsoftonline.com/<tenant>) and every other host stay redacted. Document/program names (pfirewall.log), ScubaGear IDs (MS.AAD.2.3), Microsoft Graph permissions,System.*/Microsoft.*/Windows.*namespaces, PascalCase code identifiers, code property access and sentence joins with a listed sentence starter are not domains. CIS-CAT prose is benchmark text and keeps its public recommendation values. Identical baseline expectations are collapsed so their count does not reveal compared releases; the JSONL carries only the export date and theconfidential-security-posturehandling marker. ATT&CK/D3FEND references and Pathfinder relations never enter the Result DB. Every projection field is classified inRESULT_DB_FIELD_DISCLOSURE; unclassified fields never cross. Explicit user correction 2026-09-29 (policy 3.3.1): per-finding scanner scores are withheld because they scale with the affected objects; client-owned review fields never appear in the trace's withheld-field list, so a row does not reveal whether it was triaged; CIS numbers keep all seven levels;Limitedis not a legal form; names with attached versions (Tls1.2,v1.0),Windows 95,2012-R2andstep N,Option NandPage Nreferences stay; documented Microsoft GUIDs from the public catalog (ASR rules, first-party application IDs, built-in role templates) stay while every other GUID remains[id]. Explicit user correction 2026-09-29 (policy 3.4.0): the recommendation field alone also keeps documented vendor values:set <object> to Nwithin one sentence without other numbers,value is N,the number/value/flag N,assign N,N as the Value,N for <name> mode, attribute filters such asadmincount=1,zero (0),N+,N methods/ways/optionsandonly N will be listed. Titles and descriptions stay fully redacted, and an observed count in a recommendation remains[count]. Binding user requirement 2026-09-28: the Result DB is checked and stored when it is created (materialized tableassessor_result_db_rows, rebuilt after start and after every committed change; reads wait for a current state and never serve an outdated one), so UI, API, single reads and JSONL show exactly the same stored content. Each row carries a content-free trace (field, rule, count, withheld fields; never an original value), shown in the row detail withOpen original in Work; the Result DB never shows originals. A per-client identity guard removes the client's own names (client name, domain/forest/host/tenant properties, account forms, identity-shaped assets, review owners) from every row and withholds a field when such a name survives in another spelling; report vocabulary, registry paths, public groups and template names are never identities. Concrete person, account, tenant, customer and system identities remain excluded. Keep complete originals in Work and internal analysis. -
Explicit user correction 2026-09-20: in linked CIS-CAT Results evidence, an evaluated source row must follow the actual finding outcome. Highlight the confirmed configured row with the shared green match treatment when the finding outcome is
Pass, and use the red violation treatment only when the outcome isFail; unknown, neutral or unavailable outcomes must not be guessed into either state. The criterion row remains the separately identified expected state. -
Explicit user correction 2026-09-18: Result DB uses the shared Work vocabulary for its GPO
Result Statusfilter and details:Deviation,Passed,Not configured,Conflicts, andDuplicates;Review requiredremains an independent unresolved result. Stored classification/query values stay unchanged. Status facet counts must honor all other active filters, including Deviation; only their own status selection is excluded to keep alternatives reachable. Selecting or clearing a status must never silently reset Deviation. Selected zero-hit values stay visible and removable. This supersedes the earlier Result DB exception that ignored and automatically cleared Deviation. Result DB still counts individual comparisons, while Work counts rolled-up settings; explicit user decision 2026-10-06 (policy 3.8.0, supersedes the same day's 3.7.0 collapse of identical rows) supersedes this for GPO baseline comparisons: like Work, the Result DB stores one row per GPO setting (project, aggregation run, scope and technical identity; the identity is used for grouping only and stays withheld), never one per compared baseline release. The row lists every compared baseline family, carries every distinct expectation, takes the strongest verdict in Work's order (Fail before Review required before Pass before Not configured), keeps the id of the member Work references first and records a content-freebaseline-comparisons-combinedtrace entry. A real GPO duplicate stays one setting with itsDuplicatesflag; different settings are never combined, even with identical visible content; the concrete release stays withheld; no extra public observation types or invented statuses are introduced.
GPO Registry baseline comparison
- Treat retained
Registry.poldelete-value,delete-all-values, andcreate-keyinstructions as explicit, comparable target states rather than unavailable baseline values. The comparison remains scoped to imported backup configuration and must never claim effective endpoint registry state. - A delete-value requirement passes when that value is absent from the analyzed backup set or explicitly deleted, and fails when the value is set. A delete-all-values requirement passes only when no value is configured below that key or the delete-all instruction is explicit; any retained configured child value fails it. A create-key requirement passes when the key is explicitly created or a retained configured child proves its presence, and fails when the key is absent.
- A typed empty
REG_SZorREG_EXPAND_SZis a present value. Compare its registry type and exact empty content; never convert it to missing/unavailable. Missing required presence is Fail, while ordinary missing value recommendations remain score-neutralNot configured. - Preserve contributing child-state IDs and observation provenance for key-level comparisons. Unsupported Registry.pol special operations remain
Review required; do not guess their semantics.
GPO analysis and scoring scope
-
Explicit user decision 2026-09-17: the Finding Reader must immediately show contributing GPO backup instances and attribute every retained operation/value to its source, including deletion instructions. Group by exact project/assessment/backup-instance identity, not title, registry value or observation count; retain source-local sequence and never present different GPOs as one execution chain. Show retained native GPO/backup IDs; do not infer missing friendly names from paths. This inline source attribution supersedes any earlier Results-only hiding of these sources, while Results remains available for variant comparisons.
-
Explicit user decision 2026-09-17: render that inline attribution as one flat table with the columns
GPO source,Operation,Data,Type, andEvidence, one row per exact backup identity, a compact status marker, and expandableShow source details. The expansion retains full GPO/backup identity, source-local sequence, safe evidence reference, key, value name and every original instruction. Bold Operation and Data. MarkConflicting contributiononly when the retained current baseline variants independently prove that single source member differs; mark alignment only when every retained variant independently matches. Do not derive source markers from historical evaluations, multiple instructions inside one backup, GPO precedence or endpoint effectiveness. -
Explicit user correction 2026-09-17 supersedes the flat table presentation above: show each exact GPO backup identity again as a complete, vertically stacked source section with Evidence, source-local sequence and every original instruction immediately visible. Use a restrained red background and red leading accent for a source section only when the retained current baseline variants independently prove that single source member differs. Keep aligned, unassessed and ambiguous sections neutral; retain the same historical, precedence and endpoint-effectiveness boundaries.
-
Explicit user correction 2026-09-17 supersedes the whole-section red treatment above: keep every GPO source section neutral and apply the restrained red background only to the exact displayed field value proven different from every retained current baseline variant. Highlight
Operationfor an operation mismatch,Datafor a data mismatch andType codefor a registry-type mismatch; several fields may be marked only when each is independently proven. Do not highlight a whole source, heading, path, key, value name or conflict badge, and do not guess a field when variants disagree about the cause. -
Explicit user correction 2026-09-25 supersedes the always-visible source sections above in one case only: when the Finding Reader's first-read problem summary is shown and several GPO backups retain literally the same instruction (registry key/value-name letter case aside), the complete source sections sit in a collapsed
Show the N identical source instructionsdisclosure below the source count and notice. The problem summary states the shared value and names every contributing backup; nothing is removed, and field-specific red value markers are unchanged inside the disclosure. A later 2026-09-25 correction extends this to different instructions: the visible value overview names every distinct instruction with its contributing backups, and the complete sections sit in a collapsedShow the N source instructionsdisclosure. A single source and historical or unstructured comparisons keep every source section immediately visible. -
Explicit user decision 2026-09-25: the GPO first-read
Problemblock and the separateNext stepblock each carry one leading marker at the shared--marker-width. Problem uses the outcome color (--outcome-failfor Fail,--outcome-passfor Pass, neutral otherwise); Next step uses the orange--next-step-accentrole, which reuses the existing--sev-highorange. No other status fill. -
Explicit user extension 2026-09-17: every proven GPO source-value deviation must receive the same restrained red value treatment. Keep registry-policy differences field-specific for
Operation,DataandType code, including simultaneous differences. For other comparable GPO value kinds, or when all retained variants prove a difference but no one field is the common cause, mark the displayed source value as a whole without asserting a narrower cause. Review-required, unassessed and aligned values remain neutral; never color the whole source section, heading, evidence path or diagnostic badge. -
Explicit user decision 2026-09-25 supersedes only the neutral treatment of aligned values in the preceding rules: wrong settings are red and correct settings are green, so right and wrong are visible at a glance. Green uses the same restrained value treatment with the success color and requires the same proof as red in the opposite direction: a whole value matching every retained current baseline variant, or a principal-set member present in the expected value of every retained variant. A value or member that matches only some templates, review-required, unassessed and historical values stay neutral; never guess from GPO precedence, endpoint effectiveness or an inferred role. The rule applies to the GPO source sections, the Finding Reader problem summary and the GPO conflict/duplicate variants in Results (a variant is colored only when every one of its sources has the same proven relation). Apply it to other scanner Results only where the source proves correctness per value or row; CIS-CAT keeps its existing evaluated-row treatment.
-
Explicit user correction 2026-09-17: a principal-set is a collection comparison, not one indivisible value block. Mark only configured principals absent from every retained current baseline variant. A principal also present in the expected baseline remains neutral even when neighboring principals deviate. If the deviation consists only of a missing expected principal, do not color an existing configured principal as its substitute; the expected-baseline block remains the evidence for that absence.
-
For versioned member comparisons, derive the Conflict flag from the retained authoritative customer state, not from a set-value-only subset of original instructions. Reduced-identical contributions from multiple backups may be Duplicate; multiple earlier instructions inside a single backup are not duplicate GPOs or independent current conflicts. Keep these diagnostic flags separate from the policy verdict and preserve historical evaluation readiness.
-
An additional indeterminate GPO must not hide an independently proven difference between other GPO backups. Retain that diagnostic only when distinct, unambiguous backup contributions of the same technical setting prove different supported signatures also present in retained compared values. Exclude the whole uncertain backup from that proof; its earlier writes may remain in retained values and must not be mistaken for separate GPOs. The overall verdict remains Review required.
-
Explicit user decision 2026-09-25: a GPO backup whose own
GPReport.xmllists no enabled link to the domain or an OU is shown asNot linked(source badge and note,No effectline in the problem summary when every contributing GPO is unlinked, count in GPO Processing). Retain only link counts, never OU or domain names. It is a backup-report fact, not effective device state, and it changes neither verdicts, conflict/duplicate flags nor the score. Backups processed before metadata parser 1.4.0 show no link status until reprocessed. The measured decision of the same date not to introduce a per-GPO target role stands; no role is derived from links beyond this presentation. -
The operational GPO assessment is misconfiguration-first and limited to customer settings that are actually configured, technically comparable and in the explicitly applicable Microsoft-baseline scope. Do not turn every recommended but absent baseline setting into an operational finding, remediation obligation or score penalty. A complete-baseline rollout is a separate, explicitly commissioned hardening track.
-
Not configuredremains a score-neutral policy verdict.DuplicatesandConflictsremain visible, mutually distinct diagnostic categories on a policy setting; they are not alternative verdicts that can suppressPassed,FailorReview required. -
Roll member comparisons up once per technical policy-setting identity. If at least one independently comparable, in-scope configured member value is a valid
Fail, the whole policy setting verdict isFail, while its conflict/duplicate flags remain visible. If every applicable member passes, the policy verdict isPassed. If member applicability, precedence or comparison is unresolved, useReview requiredrather than inventing a fail. Source multiplicity, duplicate rows and diagnostic flags must never multiply the setting's score weight. -
Label the GPO score as conformance of configured, comparable in-scope settings. Never describe it as full Microsoft-baseline compliance, baseline coverage or proof that all recommended settings are implemented.
-
Keep absent recommended settings available under
Not configuredfor transparent inspection, but exclude them from Priority Findings, default remediation scope and score unless the user explicitly starts a separate baseline-hardening scope. -
Not configuredis scoped to the analyzed GPO backup set: if an applicable baseline recommendation has no observed configured value in that set, keep it filterable asNot configuredeven when the import is a selected subset. Retain a scope-limit diagnostic and never turn this into a domain-wide or effective-device absence claim without complete collection evidence or RSoP/GP Results.
UI table row marking
- Explicit user decision 2026-09-25: clicking any data row in an application table marks the entire row so its cells remain visually connected during horizontal scrolling. This includes native tables in Work, Client Info and Results windows and the row-based Result DB table. Header and virtualization spacer rows are not selectable.
- Keep one reading marker per table until another data row in that table is clicked. Explicit user correction 2026-09-25 supersedes the yellow row color only: use the dedicated blue
--table-row-markingand its translucent surface in both themes. This row-reading exception does not change the yellow selection role of tiles and controls or the separate blue keyboard-focus role. Preserve existing pass/fail/evidence colors and text. Marking must not replace an existing row action such as opening details, following a link or resizing columns. Virtualized Work Grid rows restore their marker when scrolled out and back.
UI segments and tiles
- Treat segments and tiles as a binding two-level visual grammar independent of their content. A segment is a transparent grouped layout; a tile is a flat, square-cornered surface inside it.
- Use only the shared
--segment-*and--tile-*tokens for segment surfaces, borders, radii, insets, gaps, tile surfaces, shadows, widths, hover states, and selected contours. Do not create view-local substitute geometry. - Segments are visually transparent and have no visible border or shadow. They retain
--segment-radius, one uniform inset, and one uniform gap as shared layout geometry. - Tiles use the common white or theme-equivalent surface without a visible normal-state border, radius, or shadow. Hover changes the surface only and must not add a decorative contour, lift, or translation.
- Explicit user correction 2026-09-20: in the light theme, tile surfaces use the shared neutral gray
--tile-surfaceinstead of pure or near white to reduce glare; the current approved value is#F5F5F7. Keep the surrounding app surface, input surface and established hierarchy distinct; do not reproduce this with view-local overrides. - Explicit user correction 2026-09-25 supersedes the no-visible-border rule above for the light theme only: because the approved light tile surface and app background differ only slightly and neither color may change, every tile carries one neutral 1px hairline through the shared
--tile-bordertoken (#DCDDE3). The dark theme keeps--tile-border: transparent, where the surface luminance step separates tiles. Keep every surface color unchanged. The hairline is a neutral contour, not a status, selection or focus signal: persistent yellow selection and blue keyboard focus stay distinct, hover changes only the surface (--tile-surface-hover, slightly lighter) and keeps the same contour, and shadows, lift and gradients remain excluded. Dividers inside a tile use--tile-divider; do not darken the global--border-subtle, which also draws the approved Work list separators. Apply the contour only through these tokens, never through view-local values. - Explicit user correction 2026-09-25: the Client Info
Datatile's nestedDeviationsdonut action has no visible rectangular contour. Keep the outerDatatile's shared contour; the donut uses the transparent shared segment-border role in both themes. Its blue keyboard focus outline remains available. - Status color belongs only in a small accent line, marker, data visualization, or selected contour. Never fill the complete tile with a status color.
- Keyboard focus and selected tiles use the shared functional focus or selected outline. Action tiles and add tiles use the same flat geometry as content tiles.
- Explicit user correction 2026-09-20: the persistent yellow outline of the selected Data Hub tenant tile is one hairline thicker than the shared 2px selection outline, composed from
--bw-emphasisplus--bw-hairline. This is a scoped Data Hub tenant-selection exception; keyboard focus remains the separate shared blue 2px outline, and no other tile-selection width changes. - The persistent marking and selection color is the shared yellow
--marking-colorin both themes, except for the explicitly blue table-row reading marker documented above. Purple must not be used for selected contours or markers. Blue is otherwise reserved for keyboard focus, while green, red, orange, and severity colors remain domain status signals rather than selection colors. - Keep unused segment space intentionally empty: lay tiles out from the start at their shared compact or content width and never stretch a partial final row merely to fill the container.
- Explicit user correction 2026-09-20: the Data Hub result-donut row and the client/add-tile row below share the exact same six-column track geometry at wide widths. Every column start, width and gap must align vertically without cumulative horizontal offset; all six result donuts remain on one line. At narrower widths both rows return to the same compact responsive tile contract.
- Tile content must never cross the tile boundary or cover a neighboring tile. Nothing may be clipped, clamped, truncated, or replaced by an ellipsis. Text and actions reflow inside the tile; media scales within the available inner area. If content does not fit, enlarge or reflow the tile.
- Avoid line breaks in compact tile labels where practical. If wrapping is necessary, wrap only at word boundaries: never split ordinary words or numeric values across lines. Use a wider or responsive tile whenever a complete word or value cannot fit.
- Explicit user decision 2026-09-20: purple/violet is removed as a UI role entirely, not only as a selection color. The
--accent/--accent-hover/--accent-active/--accent-on/--accent-subtletokens insrc/styles/ui-tokens.cssmust not resolve to a violet value and must not be read wherever the consuming rule means keyboard focus (use--focus-ring) or active/selected state (use--marking-colorand its existing selection/marker roles). A tool- or graph-category tone (for example the PKI chart tone) that previously reused--accentgets its own dedicated, non-violet, non-focus, non-marking category color instead of being retargeted onto focus or marking roles. This closes the drift documented in Client Info/Work/Pathfinder screenshots reviewed 2026-09-20, where the same segmented-tab-selection component rendered amber in one view and violet in another because--accentwas simultaneously documented (supersededassessor-uiskill text) as meaning both "primary action / active view / selection" and used in code for:focus-visible, conflicting with the yellow-marking/blue-focus rule above.
UI donut charts
- Every donut chart uses the same full 360-degree geometry: a continuous neutral-gray track and a colored clockwise value arc starting at 12 o'clock.
- Explicit user correction 2026-09-25 supersedes the 2026-09-24 image-reference presentation: restore the prior donut design with titles outside the rings, the prior compact Data Hub ring size, and no ring shadow. Preserve each metric's count/percentage or score semantics and the meaning of segmented distributions. Keep the later explicit loading-state behavior so pending values are not shown as zero.
- Donut arcs use flat ends and the shared
--donut-ring-stroke,--donut-track, value, and typography tokens. Do not introduce 270-degree gauges, open gaps, rounded arc caps, or local substitute geometry. - Explicit user correction 2026-09-25: calculate every donut arc from the unrounded share. A positive share below 2% also receives a narrow, flat, same-tone radial mark so it remains visible at the compact ring size; a true zero has no mark. A positive share that rounds below 1% is labeled
<1%, never0%. Keep the exact share in the arc and existing count/score semantics in the readout. - Explicit user correction 2026-09-20: every count/percentage donut places the absolute count as the bold first line and the percentage as a regular-weight second line below it. Every donut readout, including score rings, keeps a visible safety gap from the inner edge of the ring at every supported ring size and value width. A score ring such as Overall Score retains its score-specific
/100semantics instead of inventing an absolute count. - Center the complete two-line readout as one unit inside the ring without letting either line shift horizontally. Keep every text element fully within the clear inner area and never let it touch or overlap the ring at any supported value width.
- Multi-segment distributions retain their categorical segments, but use the same track, stroke proportion, start position, centered value treatment, and shared tokens as single-value donuts.
UI Client Info dashboard
- Explicit user correction 2026-09-26: the proposed Work-style dashboard rearrangement was rejected and fully reverted. Preserve the existing tile layout, Overall Score, domain connections and Results popups. Reduce information only by removing duplicate overview facts within the existing tiles: Domain, Forest, both functional levels and DC OS stay in Domain Information; NetBIOS, schema version, domain creation and Entra identity stay in Directory; aggregate counts stay in Data. Remove repeated counts from Directory, Domain Information and Inventory only when they match the same fact already shown elsewhere; retain differing or non-numeric source values. Equal values for distinct facts (for example Domain and Forest) are not duplicates. Directory and Inventory Results retain their complete facts and original tables. This supersedes only earlier requirements to repeat those facts in several overview tiles.
- Explicit user correction 2026-09-20: the former Client Info
Priority Findingstile is namedData, sits to the left ofDomain Information, and shows the totalDeviationsvalue plus the separate additional-result-state row only. Do not show duplicateCriticalorHighsummary values in that tile. The remaining deviation value occupies the full header width and is a keyboard-accessible button that opens Work with the standardDeviationfilter. - Explicit user correction 2026-09-18 supersedes the previous Client Info visual exception:
.client-command-centerfollows the same Ableton-inspired ASSESSOR language as the approved Data Hub, Work and Pathfinder. Client Info may organize its own domain content, but has no exception for palette, surfaces, tiles, typography, controls, selection, branding, spacing or chart geometry. Existing--client-info-*roles are legacy implementation details, not authority for a separate visual theme; reuse the shared roles when bringing this view into conformity. - Treat Client Info as one connected executive security-posture canvas, not as a collection of unrelated report cards or a spreadsheet. Its stable reading order is overall posture, security domains, Data and Domain Information, then source evidence.
- Keep environment facts in a compact evidence rail, using the same neutral theme-aware tiles as Data Hub. Wrap at readable widths instead of forcing one tiny-text row. The former mandatory dark-tile treatment is superseded by the 2026-09-18 correction.
- Explicit user correction 2026-09-20 supersedes the separate evidence rail above: AD Domains, Entra Tenant, User Accounts, Computer Objects, Domain Controllers and GPOs live inside the
Datatile as one flat 3-by-2 fact grid, retaining their existing glyphs. Do not render a separate top-level Environment Facts tile row. The six facts are not nested tiles; use transparent cells and subtle separators insideData. - Present Overall Score and Security Domains together on one shared posture surface. Overall Score is the dominant visual anchor; domain scores form a visibly connected branch or spine beside it and must not look like a conventional data table.
- Explicit user correction 2026-09-20: at wide desktop widths, the posture surface and action rail each use exactly one half of the available row width. This supersedes the earlier two-to-one proportion. Every tile aligned in one row must always share the same height and bottom edge; never use intrinsic-height staggering within a row. This also supersedes the earlier instruction to keep the posture surface shorter than the action rail.
- Explicit user correction 2026-09-25 supersedes the earlier action-rail geometry:
Datasits to the left ofDomain Informationin an exact 50/50 row with identical height. The separateAssessment Gapstile is removed; the authoritativeGapscount and its Work drilldown remain inData. The adjacent posture surface has the same bottom edge as this row. Domain Information contains every fact from the Environment DetailDirectorygroup—Domain, NetBIOS name, Forest, Domains, domain functional level, forest functional level, schema version, domain created and Entra ID—plus the separately requested domain-controller count. All values come only from the same normalized Environment Snapshot. Missing facts remain an em dash and must never be inferred as zero. - Explicit user correction 2026-09-25: In
Domain Information, show the Domain first across the full width, then pair NetBIOS name with Forest, Domains with Domain controllers, Domain functional level with Forest functional level, DC OS with Schema version, and Domain created with Entra ID. This changes only presentation order; keep the source-backed values and unknown-value semantics. - Explicit user correction 2026-09-20: the Overall Score block does not repeat a textual score status below the ring and does not repeat the critical-finding count already present in Priority Findings. Assessment Coverage uses at most 70% of the Overall zone and never exceeds the shared compact tile-content width; it must end before the curved domain connectors, which may never cross its label, bar or supporting count.
- Explicit user correction 2026-09-20: the Overall Score block also omits the secondary
UnassessedandLowest domain pass ratefields completely, including their divider container. The unassessed count remains visible asGapsin Data; domain pass rates remain visible on their individual Security Domain nodes. - Explicit user decision 2026-09-18: preserve the thin curved fan connections from Overall Score to every displayed Security Domain during the Ableton-style alignment. They are a binding visual feature, not optional decoration. Derive their endpoints from the rendered ring and domain nodes and remeasure on resize/content changes. Preserve the existing stacked narrow-screen fallback; never keep desktop coordinates on a stacked layout.
- [Eight domains superseded by the six-domain decision of 2026-10-04 in
UI Work filter context; the compact-row rule applies to all six.] Explicit user correction 2026-09-25: Security Domain rows are compact enough for all eight domains to fit beside Data without clipping. Domain names use the shared H3 role; the score node and right-hand deviation or review count remain, without the former metadata line. The Overall Score ring is a keyboard-accessible entry to Work's clean remediation default: clear prior search, source, domain, severity, record-ID and workspace filters, selectDeviation, and open the standard Work overview. - Explicit user correction 2026-09-20: Every displayed Security Domain row carries a subtle amount bar in its own shared grid column between the longest rendered domain label and the widest rendered amount. Keep the shared gap on both sides so a bar can never grow into text or behind a number. All bars share one right edge and extend left from that edge. The later color correction supersedes the preceding categorical-color decision: every amount bar uses the exact current semantic color of the Overall Score donut and changes with that score's critical, medium, passed, or unknown tone. Do not use selection, focus, per-domain score, or a separate palette. Bar width is that row's displayed deviation amount divided by the sum of the displayed domain amounts; review-only rows use their already-displayed review amount. Keep the exact right-aligned number visible as the authoritative value, make the bar decorative and hidden from assistive technology, and never change counts, scoring, classification, or drilldown semantics to produce the visualization.
- Explicit user correction 2026-09-25: Within each Client Info Security Domain row, center the domain name, amount bar and amount number vertically on the center of that row's score circle. They belong to one grid row; do not let the circle span an unused second row that shifts the other elements upward.
- Explicit user correction 2026-09-20 supersedes the transparent Client-Info donut treatment above: the total
Deviationsdonut in Client Info'sDatatile uses the exact Data Hubdatahub-reference-knobvisual variant, including its tile surface, dimensions, spacing, title and hover state. Data Hub and Client Info derive its count and percentage denominator from the same selected mixed-timeslot project sheet, including assessment-bound GPO/policy observations as well as scanner records; never calculate the Data Hub value from scanner run IDs alone. The complete donut remains a keyboard-accessible action to Work with theDeviationfilter. - Explicit user correction 2026-09-25 supersedes only the Client Info
Datadonut dimensions and spacing in the preceding rule: expand its ring to the largest size that fits above the result states and environment facts without increasing the shared tile height or clipping content. Keep the Data Hub donut component, external title, colors, value semantics, hover state and Work interaction. - Explicit user extension 2026-09-20: Client Info's Operating systems table shows PingCastle's row-bound
Nb Active,Nb Inactive,Nb EnabledandNb Disabledcounts besideNb OS. Join each value only to the exact retained report, source table and row of that operating-system entry; never derive one state from another, borrow a value from a different row or add overlapping inventories. Missing values render as an em dash. Other scanners and older imports remain visible without invented state counts. - Keep Client Info immediately scannable: Environment Detail starts collapsed with its evidence/restriction counts visible; the Accepted Risks master/detail summary remains visible, while its complete context, controls, approval, evidence and decision history are individually expandable. Disclosure must remain keyboard accessible and must not change source data, scoring, risk decisions or drilldown identity.
- Explicit user correction 2026-09-20: every Environment Detail tile heading, including Source Overview and Operating systems, carries one restrained existing ASSESSOR line glyph before its title. All fact groups reuse Source Overview's list spacing and row padding for one consistent, airy rhythm; fixed tile heights, the four-column grid and internal scrolling remain unchanged.
- Explicit user correction 2026-09-20: Accepted Risks adopts the Data Hub
Manage Clientmaster/detail interaction and geometry. The fixed-width, independently scrolling navigation on the left owns the register heading, count, selection and compact state/date rows; the equally tall information pane on the right owns the selected risk, summary and expandable detail groups. Yellow marks persistent selection, risk state remains a separate text-and-dot signal, Arrow Up/Down/Home/End move the selected risk, andOpen findingopens that exact record in Work. At narrow widths the panes stack without horizontal overflow. - Explicit user correction 2026-09-20: Accepted Risks adopts the Data Hub
Manage Clientmaster/detail interaction and geometry. The fixed-width, independently scrolling navigation on the left owns the register heading, count, selection and compact state/date rows; the equally tall information pane on the right owns the selected risk, summary and expandable detail groups. Yellow marks persistent selection, risk state remains a separate text-and-dot signal, Arrow Up/Down/Home/End move the selected risk, andOpen findingopens that exact record in Work. At narrow widths the panes stack without horizontal overflow. - Explicit user correction 2026-09-20: Accepted Risks reuses the Data Hub client-detail geometry one-to-one: a fixed compact selection rail at the left using
clamp(420px, 27vw, 520px), the information surface at the right, and the established stacked narrow-screen fallback. Do not reintroduce a proportional wide list column. - Keep Data and Domain Information in the dedicated action rail. Use status color only for finding markers, score arcs, score nodes, and progress bars; avoid large colored fills and nested card stacks.
- Explicit user correction 2026-09-20 supersedes the standalone Source Overview rail: source scores live inside the expanded
Environment Detailas one compact plain list with separators, never as tiles. Preserve every source's actual versioned ASSESSOR score contribution, method label, native context and Work drilldown. A run/file-bound native score takes priority when supported and pass rate is the fallback; PingCastle uses the explicit100 - native riskconvention and retains raw risk as secondary context. Never insert a raw lower-is-better risk value directly into the overall scale. Followdocs/SCORING_MODEL.md; Security Domain values are pass rates, not a decomposition of the mixed-method index. - Explicit user extension 2026-09-20 supersedes only the preceding container geometry: all expanded Environment Detail groups form an equal four-column tile grid.
Source Overviewoccupies one group tile while its individual source entries remain the agreed plain separated list, never individual source tiles. The six fact groups and Operating systems each occupy one tile. Every tile is exactly three quarters of the currently rendered Overall Score tile height; derive that height from the rendered element and keep overflow inside the affected tile with a scrollbar. Preserve four columns on narrow layouts through horizontal grid scrolling rather than changing tile width or column count. - [Tile count, tile width and per-tile fact count superseded: six equal square tiles with at most four facts each, see the 2026-10-01 decision below.] Explicit user correction 2026-09-25 supersedes the preceding Environment Detail disclosure and tile geometry: remove the disclosure heading and keep all eight group tiles permanently visible. Use compact square tiles at the shared compact width, wrapping with available space. Show only one or two source-backed overview facts per tile; complete facts, source contributions, original sections, observations and operating-system tables remain available through the tile's
Resultsaction. Keep source drilldowns and scoring methodology reachable from Source Overview Results. Never clip tile content or shrink informational labels below 14px and values below 16px. - [Tile count superseded:
Source metricswas also removed on 2026-09-25, leaving six tiles; see the 2026-10-01 decision below. The Source Overview removal and its Results access stay valid.] Explicit user correction 2026-09-25 supersedes the Source Overview tile in the preceding rule: remove that tile entirely, leaving seven permanent square environment tiles. Keep the full source-score contributions, source-linked Work drilldowns, restricted-section explanation, original scanner evidence and scoring methodology accessible from a compactResultsaction besideOverall Score. Directory's compact preview shows the source-backed domain count so its value fits without splitting the domain name; the full name remains in Domain Information and Directory Results. - [Tile width, fact counts and the
Source metricstile superseded by the 2026-10-01 decision directly below; the two-column fact layout, type roles and no-clipping rule stay valid.] Explicit user correction 2026-09-25 supersedes the seven tiles' compact width and single-fact preview above: use twice the shared compact tile edge and show the initial source-backed hard facts in a space-efficient two-column layout. Inventory shows all eight facts, including enabled/disabled accounts and the assessed host, directly in its tile. Directory shows its first six facts; its remaining facts are visible in Domain Information and Directory Results. Source metrics shows up to eight available metrics, while Results retains the complete list. Operating systems shows available group totals and first source rows; its full table remains in Results. Keep 14px information labels, 16px values, natural growth for longer content and no clipping. - Explicit user decision 2026-10-01 confirms the 2026-09-29 implementation and supersedes the tile count, tile width and fact counts in the preceding rules: the environment overview has six tiles (Directory, Resilience, Inventory, Password policy, Certificates & PKI, Operating systems;
Source metricswas removed on 2026-09-25). The six tiles share one row of equal square tiles at full width and scroll horizontally inside the grid at narrower widths instead of wrapping. Each tile shows at most four source-backed facts, two in narrow squares, taken in order after removing values already shown identically in Data or Domain Information; every further fact and source table stays complete in the tile'sResults. This limit applies only to these environment tiles, not to Data, Overall Score or Domain Information. - Explicit user correction 2026-09-25 supersedes the earlier H3 Security Domain names and larger Domain Information/Environment tile headings: every Client Info dashboard tile except Overall Score follows Data's 16px title/value and 14px informational-label roles. Bring Data's own 12px informational labels up to the binding 14px minimum. Give each fact in Domain Information and the seven environment tiles a separate flat cell with the same subtle separators as Data; each Security Domain row also receives a subtle cell contour. Preserve the current source-backed content, interactions, semantic chart colors, 14px minimum for information and natural growth without clipping. The Accepted Risks master/detail workspace remains its separately agreed Work-style reading surface.
- Explicit user correction 2026-09-20: Source Overview never renders a
Tabular Datatile. Generic tabular imports remain available through their supported data and filter paths, but they are not a security-scoring source tile. - Unknown or unavailable facts render as an em dash and never as an inferred zero. Keep the dashboard English-only and omit explanatory prose that does not support an immediate first-meeting statement or action.
- The content hierarchy, score semantics, source provenance and drilldowns remain binding. Their layout must use the shared ASSESSOR components and tokens; a connected briefing layout does not permit a dedicated palette or geometry. Source Overview, Environment Detail and Accepted Risks obey this same rule, including their collapsed, expanded and selected states.
UI branding position
- Use the Data Hub header as the binding position reference for the ASSESSOR logo, wordmark, and version.
- Keep the brand container geometry identical across every application view; do not add area- or view-specific brand padding, margin, alignment, height, or transforms.
- Switching views must never move the logo, wordmark, or version.
UI backend connection state
- Data Hub, Result DB and DB Structure must present a checking or unavailable local backend through the shared ASSESSOR dialog rather than an embedded page banner.
- Keep that dialog dismissible so the user can inspect the underlying view. The application continues its existing automatic health checks; reconnecting removes the offline branch without requiring a reload.
- Keep the copy limited to the affected capability and the automatic connection check. Do not expose response bodies, project data or imported content in this technical connection state.
Navigation and rendering performance
-
Explicit user correction 2026-09-26:
Catalog referencesstarts collapsed for a current client, with a small green dot before its heading and beforeUp to date/Update successful. Pending work or a failed check/update opens it automatically and uses an orange heading dot; checking, processing and empty clients never get a green success signal. ATT&CK/D3FEND versions remain visible while collapsed. Keep the success message open after updating and retain manual disclosure and keyboard operation. Center the Timeslots heading and add action on the same horizontal line with equal top/bottom spacing. -
Explicit user extension 2026-09-26: Timeslot entries name Purple Knight scopes explicitly as
Purple Knight for Active Directory,Purple Knight for Entra ID, or the existing combined name. Use canonical scope names first, otherwise already retained file metadata or run/file-local environment observations. Never guess from file names, finding titles, other scans or another scanner. This is a display projection only; stored scanner identity, Result DB disclosure and scoring remain unchanged. A historical scan without retained scope facts keeps its source name until reimport supplies them. -
Explicit user correction 2026-09-26:
Catalog referencesomits its generic explanation paragraph and states the next action plainly:Please updatefor pending work,Up to datewithNo action needed.for a current client, andUpdate successfulonly after successful execution and a fresh status check with no remaining work. Keep ATT&CK and D3FEND catalog versions visible. The action is now namedUpdate references; this supersedes the earlierRecognize referencescaption while retaining its left-side placement and red-when-needed/yellow-otherwise color rule. Empty, checking and failure states must not claim success. -
Explicit user correction 2026-09-26:
Catalog referencesbelongs in the Data Hub client navigation on the left, directly aboveTimeslots, including while client master data is being edited. TheRecognize referencesbutton is red when recognition is pending or retry is needed, otherwise it uses the standard yellow action treatment. This is an explicit color exception for this reference action; other action and selection colors remain unchanged. Pending references also participate in the client card's processing status (yellow point and highlighted Manage); an actual recognition failure uses the existing red error state. Successful recognition refreshes the card without hiding unrelated import or GPO issues. -
Explicit user correction 2026-09-25: begin preloading Data Hub's six result summaries while the client overview metadata is loading, before a client is selected. Reuse completed and in-flight summaries across selections and Data Hub revisits. Keep speculative requests and retained values bounded, prioritize a selected scope, and key reuse by repository revision plus exact project/assessment/scan scope. Refresh on import/data/GPO changes; stale responses must never overwrite another selection. Load summaries only, not complete source models into the browser.
-
Treat area switches as a performance-sensitive path. Measure the first visit and repeated visits separately after the workspace has loaded; distinguish main-thread rendering from asynchronous API readiness. Use the local procedure in
docs/architecture/navigation-performance.md. -
Share expensive filtering, sorting and facet counts between their consumers. Component-local
useMemodoes not survive an area unmount. Use bounded, dataset/sheet-owned caches with immutable input identities and all semantic dependencies (profile, dataset, reviews, filters, search, sort and timeslot/path scope); never cache solely by a reusable entity ID. Verify invalidation as well as reuse. -
Build raw text, detailed result projections, graph layouts and other large derived content only when the corresponding view needs it. Virtualized views must not serialize or derive presentation fields for every offscreen record. The initial render must also be bounded by the viewport plus overscan.
-
Large native selectors must not mount thousands of unused options during area navigation. Show the current selection immediately and prepare the complete option list before pointer opening or keyboard focus; verify keyboard access and selection preservation. Construct export payloads only after the export action.
-
Classify shared headers once per derivation, normalize sort keys once per record, and count facets in a shared pass. Rejected numbered column groups must not trigger repeated scans of all their siblings. Stop category eligibility checks once their cardinality limit is exceeded, while preserving exact counts for eligible facets.
-
Retained views mount on their first activation. While hidden, freeze their input context and stop geometry observers and animation frames; resume with current inputs when activated. Reset retained state when the workspace scope changes. Keep selections and original source values intact.
-
Polling an unchanged health/status value must return the existing state instead of rerendering the application. Do not introduce keep-alive polling or data caches without explicit freshness and invalidation behavior.
-
For performance fixes, add behavioral cost checks (for example, zero source-field reads on an unchanged repeat visit, bounded mounted rows, and fresh results after changed inputs). Record wall-clock measurements as observations rather than fragile CI assertions; run browser comparisons without simultaneous builds or load tests.
-
Follow the privacy-safe testing rules below. Local opt-in measurements may contain only area names, durations, counters and technical states; no report text, tenant identifiers, filenames, external telemetry or production instrumentation.
Security and verification
-
HTML attribute readers must advance monotonically across boolean, quoted, unquoted, malformed, and long valueless attributes; do not use unanchored
name=valuesearches that retry every suffix. Resolve repeated internal IDs/names through an import-local index tied to the exact protected markup, preserving duplicate diagnostics, target order, and source offsets. Guard character work and complete source coverage with synthetic regressions; validate timeout fixes in the built isolated worker without raising its time or memory limits. -
Context-only extractors must not consume finding tables elsewhere in the same workbook. Compose them with the generic table extractor, keep original table indices, and verify summary, findings, and supporting sheets together through canonical projection and result linking.
-
Embedded scanner globals must be located lexically outside strings, comments, HTML attributes, and other raw-text containers. Missing IDs, unreadable payloads, conflicting assignments, repeated IDs, and declared-count mismatches require explicit diagnostics. A declared empty report is distinct from an unreadable nonempty report; explicit null result tables with zero results are valid.
-
Keep native detail timestamps at their full precision and preserve exact source values and field paths, including explicit nulls and unknown fields. Derived display fields reference their real input objects; never invent native paths for generated compatibility columns. Test source-path resolution and detail-cell equality, not only row counts.
-
Scanner coverage must be verified against independently counted source records and source status totals, not just a successful parser return. Preserve declared totals and emit a diagnostic when they disagree with individual results; never drop records to make totals agree.
-
Preserve XML attributes as exact name/value pairs with attribute-level source paths, including namespaces, zero, false and empty values. Explicitly empty leaves must remain distinguishable from absent data; never reconstruct attributes from an ambiguous display serialization.
-
Lexical HTML readers must respect quoted attribute boundaries, raw-text elements and malformed/unquoted attributes without treating tooltip markup as visible tags. Sanitize complete attributes, not attribute-like strings inside other values. Bounded excerpts must not expose a partial trailing tag or discard subsequent source sections. Verify table/section coverage as well as clean cell text in both runtimes.
-
Missing native rule IDs must fail explicitly. Diagnose repeated IDs even when an established first-presentation policy retains one finding. Compare matched counts by category, not catalog size; preserve the original counters and distinguish a declared empty report from an announced but unreadable result set.
-
Embedded report data is inert input. Support only an explicitly bounded static data grammar; never evaluate scripts, calls, getters, spreads, computed properties or template substitutions. Unsupported or malformed recognized reports must fail explicitly instead of becoming successful zero-finding imports. Keep production/browser and server behavior aligned.
-
Mapping rules for ambiguous labels must include their table or candidate context. In Maester,
ResultbesideStatusis evidence; nativeResultwithout a separate status column is the status. Preserve original values and exact source paths through both variants. -
Retain scanner-level metadata separately from findings, including unknown nested fields. Distinguish scanner-runtime machine information from assessed-environment assets. Version extraction/mapping changes and recommend reimport without rewriting historic imports.
-
Apply
docs/REIMPORT_POLICY.mdto every importer and profile change. Any change to recognition, parsing/extraction coverage, persisted context/evidence, finding identity, mapping, normalization, status/outcome/severity/IOE, completeness diagnostics, or newly captured score inputs must add an append-only processing manifest version and mark affected historical imports for reimport. Presentation-only changes over already retained facts do not require reimport. -
A reimport may replace scanner-derived records only. Preserve complete client-owned review objects, including future fields and accepted-risk data, through a unique scanner/rule/asset identity. Keep the prior review and surface a persistent unresolved state when matching is absent or ambiguous; never guess by title or position.
-
Preserve local-only behavior until a server transition is explicitly implemented and documented.
-
Do not introduce external uploads, telemetry, CDN assets, network APIs, shell access, or broader Tauri capabilities without explicit user approval and a security-model update.
-
Treat imported HTML, XML, Excel, JSON, and CSV files as untrusted input. Never execute active content from imported files.
-
Use
npm testandnpm run buildas the baseline verification commands for relevant changes. -
Preserve unrelated user changes and keep implementation-plan updates factual and concise.
Client Info table interaction correction (2026-09-25)
- All Client Info Results categories use the same table interaction: retained base tables, including historical imports without presentation metadata, are immediately readable inline. Do not replace them with repeated
Open tablebuttons or anAdditional source tablesgate. - Preserve original column values and native section/table headings; do not add invented
Table N of Mtitles. Historical flattened source prose belongs in a separateSource textdisclosure, with the retained text still accessible. - Explicit user correction 2026-09-25 supersedes the
Source textdisclosure above: omit that generated control and historical flattened prose from Client Info Results. Preserve the stored source text. Never display importer-generatedTabelle N,Table N, or ordinal suffixes as native headings, whether they arrive through table title, name, subsection observations, row-count labels, or a linked popup/inline target. If no native table heading is retained, show the complete table under its section heading without inventing a replacement. Structured native explanatory prose remains visible. - Native links inside table cells open their exact target as a popup; native links outside tables expand their target inline. Resolve all links within the exact scan-run and import-file identity, and retain every table in a linked target. Missing historical link metadata must never be reconstructed from table order, counts, or guessed group names.
- Apply the shared 14px table/field-label and 16px value/prose roles, 20px window inset, compact fact cells and contained horizontal table scrolling in both themes. Regression tests must open each category through its actual Results action.
Privacy-safe testing
- Treat all real tenant, customer, project, scan, finding, and imported-file data as sensitive.
- Never inspect, extract, log, quote, summarize, screenshot, or otherwise expose real file names, finding titles, field values, raw report content, or rendered report text during testing or debugging.
- Use synthetic fixtures for content-level, parser, importer, mapping, and UI tests.
- Against a real running application, verify functionality only through content-free technical signals such as HTTP status, health state, anonymized counts, boolean DOM state, control availability, and element existence.
- Do not read
innerText, response bodies containing domain data, or screenshots of populated views merely to prove that a feature works. - If real content inspection is genuinely unavoidable, stop and obtain the user's explicit permission for the minimum required scope before accessing it.
- Remove temporary browser profiles and test artifacts immediately after an approved real-application check.