127 lines
20 KiB
Markdown
127 lines
20 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.
|
|
|
|
## 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.
|
|
|
|
## 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 16px/400, structured table/Grid/Raw Data content 14px/400, labels and table headers 12px/600, 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.
|
|
- Render continuous prose such as finding and report text at no less than `16px`. Structured data in tables, Grid, and Raw Data uses the dedicated compact 14px role.
|
|
- Compact interface text such as button captions, field labels, metadata, badges, and comparable control annotations may use a smaller type size.
|
|
- 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 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.
|
|
- 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.
|
|
- 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.
|
|
- 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.
|
|
|
|
## 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.
|
|
- Place the primary numeric value itself on the exact visual center of the ring. Append a percent sign or other short unit to its right on the same baseline in the smaller shared UI size without letting that unit shift the number away from the center. Supporting counts may remain as subdued secondary text inside the ring, but every text element must stay fully within the clear inner area and must never 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
|
|
|
|
- The loaded Client Info view is an explicitly scoped exception to the generic tile composition: `.client-command-center` uses the connected command-center treatment and dedicated accent roles defined by `--client-info-*`, while both its outer page background and every dashboard tile inherit the active theme exactly like Work via `--surface-app`, `--tile-surface`, `--tile-surface-hover`, and the corresponding shared text/line roles. This exception supersedes generic card composition only inside that root; it must never leak into Data Hub, Work, Result DB, Pathfinder, dialogs, or the application shell.
|
|
- 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 one compact, single-row evidence rail of icon-led dark tiles. They may be visually separated like the approved Client Info reference, but must remain substantially smaller than the posture and action areas below.
|
|
- 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.
|
|
- 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.
|
|
- Source Overview is the final evidence rail. Explicit user decision 2026-09-10: show the actual versioned ASSESSOR score contribution as the primary number, using a run/file-bound native score when supported and a pass-rate fallback otherwise. Label the method; PingCastle uses the explicit `100 - native risk` convention and retains the 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.
|
|
- 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 Client Info composition still obeys the shared Inter typography roles, donut geometry, marking semantics, and panel inset. Its dedicated palette, connected geometry, and compact briefing surfaces are isolated Client Info primitives rather than application-wide tile replacements.
|
|
|
|
## 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.
|
|
|
|
## 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.
|