# ASSESSOR project guidance
## Implementation plan
- Read `docs/IMPLEMENTATION_PLAN.md` before 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.json` is 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 root `package-lock.json` entry 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 `securityScoring` in 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. See `docs/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 labels `Context`/`Kontext` stay 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 through `ComplianceReadPort` (single Result DB row by project, filtered Result DB pages, project, assessment and scan-run lists) and stores mapping runs, accept/reject decisions and batches only through its own `ComplianceStore`. The existing tables of migration 026 keep their names and data and are owned by the engine; its writes never advance the Core repository revision. The Core project export receives the engine data beside the Core export at the HTTP route. Its extension points are the Finding Reader `Map ISO controls` action and its window, the Finding Reader `ISO controls` section, the Result DB `Map all ISO controls` batch action, the Data Hub ISO corpus tile and the Client Info `ISO controls` section. Explicit user decision 2026-10-05: `Map ISO controls` opens a window like `Accepted Risk` with Accept and Reject per control (no third decision value). The Finding Reader lists the controls whose latest decision is accepted in an `ISO controls` section read like `Description`, 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 exactly those findings in Work. 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 comment `Accepted 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.
- 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) and `Governance` (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 under `docs/` 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 Cluster` Work facet and the Finding Reader `Context` section) 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: [, ]` in the chat message, for example `Core-Freigabe: Evaluation, Store`. `Core-Freigabe: alle` releases every Core area except `Governance`, 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.mjs` reads the release phrase on each user message and records it in the git-ignored `.claude/core-release.json`; `.claude/hooks/core-guard.mjs` blocks Edit, Write, NotebookEdit or a writing shell command on a Core path unless its area is released, and then shows a prominent `CORE-ÄNDERUNG GESPERRT` notice 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 test` before 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.ts` enforces 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 `Engines` button 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 and the Data Hub ISO corpus tile and stops their requests, and re-enabling starts the Finding Reader ISO panel closed. 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 Cluster` Work 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 `Context` section 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 `Context` toolbar 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 configured` and 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`, `PolicyDependencyRule` or `stronger/weaker` hooks. 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 in `Other Deviations (not yet catalogued)`. Recognized and estimated assignments count in clusters, badges and the `Context Cluster` facet; 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 labelled `automatically 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 in `Other 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 mapped` and 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 layer `Context` and uses the English statements (`favours`); German reports use `Kontext` and `begü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 with `fail-means-met` polarity (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.1` lies in `9.1` and `9`) 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: every `fail` or `warning` result 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 visible `Other 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, else `Other 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, and `Not 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-Cluster` filter. The layer defaults to off, and the choice is stored locally per user. The `Kontext-Cluster` Work facet is visible only while the layer is on; `Source: Scan` stays 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`, container `assessor-2_0-postgres-1`, database `assessor`, and volume `assessor-2_0_assessor-postgres-data` on `127.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 `5432` is occupied by a different container, stop and report the conflict instead of spawning or selecting another database.
- `docker-compose.postgres.yml` must 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.md` and the relevant current components and `src/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 use `16px`. For example, the Client Info Directory tile renders `Domain` at 14px and `sevenkingdoms.local` at 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 `20px` from each outer edge.
- Use `--panel-content-inset` through 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 `Problem` block (`Summary` for a passed result) with the outcome-colored marker and a separate `Next step` block with the orange `--next-step-accent` marker 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, `resultSheetRowStatusCells` markers). Split a long remediation only at a paragraph boundary and keep the rest complete behind `Full remediation`. An imported documentation link is offered only as a plain https URL with `noopener 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--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 in `src/shared/windows-codes.ts` and is applied centrally by `PathText`; 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`, or `Result` next to a separate `Status` column) is the `Problem` statement, 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 plain `Description` without a derived-text suffix; the separate field key `common-description` keeps it distinguishable from a native description. A single alert or identical texts keep the original `Description` unchanged, 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`/`Text` modes and in-graph node cards: node text starts on; the toolbar has only the `Text` toggle for turning that text off or on. Selecting, deselecting, marking, extracting, or hovering a node must not change the text setting. `Reset view` restores text on. Keep graph nodes and their compact text in the graph, while node information and actions appear only in the right `Details` panel. Do not render hover or selected-node cards over the graph.
- Explicit user extension 2026-09-25: the right `Details` panel 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, exact `Source 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 or `Mark all` branch alone must not trigger extraction of the whole graph or broaden the selected path. `Exit Extract Path` restores the prior graph selection and view. This supersedes the earlier broad-branch `Extract` behavior; `Mark all` keeps 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 schema` copy block above the metrics and the explanatory sentence beneath `Data 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`, `MD` and `HTML` buttons 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 Workspace` restricts them only when active, alongside ordinary filters and drilldowns. Use exactly two content columns, `Soll-Zustand` and `Abweichungen`, 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 in `docs/REPORT_STRATEGY.md`.
- A unique `Source: Scan` selection is a semantic tool context even when Work remains on the project-wide `All Records` sheet. Visible and active facets must follow the selected tool context rather than the aggregate sheet profile.
- Explicit user correction 2026-09-25: changing `Source: Scan` inside Work, including back to `All`, starts the newly selected source with the clean Work default. Clear the previous search, status override, other facets, record-ID/path restriction and `My Workspace` restriction, restore the standard `Deviation` status 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 only `Result Status`, the available GPO facets `Baseline`, `Comparison`, `Conflict`, `Description source`, `Diagnostics`, `Duplicates`, `Imported`, `Policy section`, `Policy type`, and the permanent final `Source: Scan` control. 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: `Category` is a permanent GPO Work filter in both supported entry paths, including when its only current value is `GPOs`. Keep it directly after `Result Status`. Severity, CIS, MITRE, target, result-message, review and scanner-specific facets remain excluded from the GPO-only context; `Source: Scan` remains last.
- [The `GPO & Baseline` mapping is superseded by the 2026-10-04 Security Domain decision below.] Explicit user extension 2026-09-17: Work also exposes a distinct `Security Domain` facet immediately after `Category`. 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 to `GPO & Baseline`. Domain selection and Client Info drilldown must therefore select the same record identities, while ordinary active Work filters continue to apply. `Source: Scan` remains last.
- [Eight entries and `Unclassified` superseded by the 2026-10-04 decision below: six entries, no `Unclassified`; the remaining rules stay valid.] Explicit user correction 2026-09-18: `Security Domain` always offers all eight Client Info catalog entries in catalog order, including selectable zero-hit domains in mixed Work and both GPO entry paths. `Unclassified` remains 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 & Baseline` and `Unclassified`: 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 through `Source: Scan = GPOs` and 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-CAT `Benchmark section` title path from the same scan report (never the number alone), (3) suite or control ID, (4) GPO technical identity (`Policy type`, `Policy section`, `Registry path` by longest key), (5) the source's own fallback area, else a visible global fallback. Mapping tables are versioned per scanner profile (`src/profiles//-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 Knight `Group Policy Security` is System Hardening. The derived Raw Data fields `Benchmark section` (CIS-CAT) and, for security-template settings without a comparison, `Policy section` and `Registry path` are 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 Status` choices are exactly `All`, `Deviation`, `Passed`, `Not configured`, `No baseline rule`, `Not comparable`, `Conflicts`, and `Duplicates`. 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 rule` and `Not comparable` match the authoritative rolled-up policy verdict; `Conflicts` and `Duplicates` match the corresponding diagnostic category flags. One policy setting may therefore belong to both `Deviation` and `Conflicts` or `Duplicates`.
- Explicit user decision 2026-09-17: `No baseline rule` is 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, otherwise `No baseline rule`. It is distinct from `Not 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 diagnostic `Conflicts`/`Duplicates` flag marks such a setting without replacing its verdict; unresolved identities stay out of this verdict and take `Not comparable` instead.
- Explicit user decision 2026-09-17: `Not comparable` is 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, so `Not comparable` carries 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 `Pass` string must not make a not-configured, review or failed policy setting match `Passed`.
- 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 settings` in 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, a `Rule` reference 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 N` is 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/`) 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 the `confidential-security-posture` handling marker. ATT&CK/D3FEND references and Pathfinder relations never enter the Result DB. Every projection field is classified in `RESULT_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; `Limited` is not a legal form; names with attached versions (`Tls1.2`, `v1.0`), `Windows 95`, `2012-R2` and `step N`, `Option N` and `Page N` references 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