227 lines
53 KiB
Markdown
227 lines
53 KiB
Markdown
# 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.
|
|
|
|
## 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, blue for keyboard focus, and 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.
|
|
- 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 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.
|
|
- 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.
|
|
- 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.
|
|
- 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-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
|
|
|
|
- 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 is `Fail`; 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 Status` filter and details: `Deviation`, `Passed`, `Not configured`, `Conflicts`, and `Duplicates`; `Review required` remains 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; no extra public observation types or invented statuses are introduced.
|
|
|
|
## GPO Registry baseline comparison
|
|
|
|
- Treat retained `Registry.pol` `delete-value`, `delete-all-values`, and `create-key` instructions 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_SZ` or `REG_EXPAND_SZ` is 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-neutral `Not 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`, and `Evidence`, one row per exact backup identity, a compact status marker, and expandable `Show 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. Mark `Conflicting contribution` only 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 `Operation` for an operation mismatch, `Data` for a data mismatch and `Type code` for 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 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`, `Data` and `Type 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 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.
|
|
|
|
- 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 configured` remains a score-neutral policy verdict. `Duplicates` and `Conflicts` remain visible, mutually distinct diagnostic categories on a policy setting; they are not alternative verdicts that can suppress `Passed`, `Fail` or `Review 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 is `Fail`, while its conflict/duplicate flags remain visible. If every applicable member passes, the policy verdict is `Passed`. If member applicability, precedence or comparison is unresolved, use `Review required` rather 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 configured` for transparent inspection, but exclude them from Priority Findings, default remediation scope and score unless the user explicitly starts a separate baseline-hardening scope.
|
|
- `Not configured` is scoped to the analyzed GPO backup set: if an applicable baseline recommendation has no observed configured value in that set, keep it filterable as `Not configured` even 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 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-surface` instead 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.
|
|
- 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-emphasis` plus `--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 always the shared yellow `--marking-color` in both themes. Purple must not be used for selected contours or markers. Blue remains 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-subtle` tokens in `src/styles/ui-tokens.css` must 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-color` and its existing selection/marker roles). A tool- or graph-category tone (for example the PKI chart tone) that previously reused `--accent` gets 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 `--accent` was simultaneously documented (superseded `assessor-ui` skill 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.
|
|
- 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-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 `/100` semantics 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-20: the former Client Info `Priority Findings` tile is named `Data`, sits to the left of `Domain Information`, and shows the total `Deviations` value plus the separate additional-result-state row only. Do not show duplicate `Critical` or `High` summary values in that tile. The remaining deviation value occupies the full header width and is a keyboard-accessible button that opens Work with the standard `Deviation` filter.
|
|
- Explicit user correction 2026-09-18 supersedes the previous Client Info visual exception: `.client-command-center` follows 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 environment facts, overall posture, security domains, priority findings and assessment gaps, 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 `Data` tile 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 inside `Data`.
|
|
- 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-20: the top of the Client Info action rail is an exact 50/50 row. `Domain Information` sits on the left and `Priority Findings` on the right with identical height; `Assessment Gaps` spans the full action-rail width below. Domain Information contains every fact from the Environment Detail `Directory` group—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-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 `Unassessed` and `Lowest domain pass rate` fields completely, including their divider container. `Unassessed controls` remains visible only in Assessment Gaps; 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.
|
|
- Explicit user correction 2026-09-20: Security Domain rows show the domain name in the shared detail-title role without the former passed/not-configured/duplicate/conflict/review metadata line underneath. The score node and right-hand deviation or review count remain. 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, select `Deviation`, 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-20 supersedes the transparent Client-Info donut treatment above: the total `Deviations` donut in Client Info's `Data` tile uses the exact Data Hub `datahub-reference-knob` visual 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 the `Deviation` filter.
|
|
- Explicit user extension 2026-09-20: Client Info's Operating systems table shows PingCastle's row-bound `Nb Active`, `Nb Inactive`, `Nb Enabled` and `Nb Disabled` counts beside `Nb 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 Client` master/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, and `Open finding` opens 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 Client` master/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, and `Open finding` opens 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 Priority Findings and Assessment Gaps in a 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 Detail` as 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 explicit `100 - native risk` convention and retains raw risk as secondary context. Never insert a raw lower-is-better risk value directly into the overall scale. Follow `docs/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 Overview` occupies 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.
|
|
- Explicit user correction 2026-09-20: Source Overview never renders a `Tabular Data` tile. 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
|
|
|
|
- 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 `useMemo` does 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=value` searches 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, `Result` beside `Status` is evidence; native `Result` without 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.md` to 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 test` and `npm run build` as the baseline verification commands for relevant changes.
|
|
- Preserve unrelated user changes and keep implementation-plan updates factual and concise.
|
|
|
|
## 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.
|