Commit graph

16 commits

Author SHA1 Message Date
ab8cfcad97 Configuration page with change log
- new collector instance-config: collation, edition, version, services and
  accounts (sys.dm_server_services, 2008 R2 SP1+), Instant File
  Initialization and Lock Pages in Memory (where the build has the
  columns), tempdb files, default paths; plus a fingerprint of the whole
  setup (sp_configure, trace flags, services, version, tempdb files)
- changes are computed against the previous collection, which the agent
  restores from the repository after a restart; migration 0008 keeps them
  in insight.ConfigurationChanges (as long as resolved findings)
- SQLI-CFG-013 "Konfiguration ændret": information for a day when
  sp_configure, a trace flag or a service account changes (account names
  are sensitive evidence)
- page /instanser/{navn}/konfiguration: instance, CPU and memory, services,
  tempdb, trace flags, non-default sp_configure (default vs. in use vs.
  configured) and the change log; linked from the instance page
- the management report lists configuration changes in the period
- trace flag reading shared by trace-flags and instance-config

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 08:12:26 +02:00
ac13e3d826 Disk speed per drive: IOPS, MB/s and latency
- file-io records each file's drive: sys.dm_os_volume_stats from 2008 R2 SP1
  (new capability VolumeStats, mount points included), otherwise derived
  from the path (D:\..., \server\share\, / on Linux), so 2005 works too
- migration 0007: Volume and IntervalSeconds on FileIoSamples, and
  DiskHourly (rolled up by maintenance, kept HourlyDays)
- DiskActivity sums files per drive: read/write IOPS, MB/s and latency
  weighted by I/O count
- instance page: "Diskhastighed pr. drev" (table and MB/s + latency charts);
  time window analysis and its PDF: per drive against the same hours of the
  four previous weeks
- SQLI-IO-001/002 now report per drive (one finding when the storage is
  slow, the slowest files in the evidence) instead of per file

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 08:03:11 +02:00
25a67cb98b Stop SQLInsight deadlocking itself, and stop reporting its own deadlocks
At a customer whose repository sits on a monitored instance, the agent
reported 12 deadlocks that were its own: two instances' monitors save
findings in parallel, one transaction each, and while insight.Findings is
small SQL Server scans it, so the two lock each other's rows.

- SaveRuleResultsAsync takes an exclusive application lock for its
  transaction (the agent is the only writer; a save takes milliseconds)
  and retries if chosen as deadlock victim anyway
- repository connections are named "SQLInsight Pro (repository)"
- deadlocks where every participant is SQLInsight Pro are not reported
  (the read position still moves past them); any other session keeps it

The new integration test (two instances saving 25 rules x 40 rounds in
parallel) failed 2 of 2 without the fix and passed 5 of 5 with it.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-02 07:34:59 +02:00
bb3b38e77f Top SQL: collect what the heaviest statements use every 5 minutes
New collector query-stats reads sys.dm_exec_query_stats for the statements
that ran since the previous collection, grouped by query_hash (SQL Server
2008+) or sql_handle + offsets (2005, via legacy ODBC; literals only). Only
the 50 heaviest by CPU, duration, reads and executions, text cut to 4000
characters, no plan XML. The database comes from the plan's dbid attribute,
because ad hoc batches (as Dynamics AX sends) have none in sql_text.

QueryStatsDelta diffs against the previous collection: a statement seen
before with the same plan gets the difference, a plan compiled since then
counts in full, a recompiled or evicted plan or counters that went
backwards start over (never negative), a restart gives no delta. Up to 2000
statements are remembered between collections.

Repository migration 0006: insight.QueryStatSamples (deltas, top 100 per
collection) and insight.QueryTexts (text once per statement), kept for
Retention:RawDays. The text is customer data: never stored as a JSON
snapshot and never part of hub submissions. Window queries for metrics,
waits (raw and hourly), file I/O, blocking, deadlocks, findings active in a
window and top SQL by CPU/duration/reads/executions.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 15:46:45 +02:00
50bc878776 Customers file support cases in SQLInsight Web and follow their status
- Repository migration 0005: insight.SupportCases. The web UI has only
  db_datareader, so INSERT on this one table is granted to public.
- Web: /support (menu "Support") lists the customer's cases and, with
  Hub sync on and a Professional/Enterprise license, a form (title,
  description, contact; contact prefilled from the Windows user).
  /support?fund=<id> prefills from a finding: instance, rule, severity,
  explanation and non-sensitive measurements.
- "Opret supportsag" on findings: right-click a finding link or a
  finding's heading (support-menu.js, a static file within the CSP;
  Shift+F10/context key, Escape closes), and a visible button on the
  finding page that works without JavaScript. Only when support is
  available.
- Agent: sends pending requests to POST /api/v1/cases, stores the case
  number, backs off on failures and gives up on 400/401/403/422; fetches
  the customer's cases every 5 minutes (at once after sending).
- Docs: support.md (also on the community site), databehandling.md
  (contact details are sent to the hub).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-01 11:34:06 +02:00
Claude
4269f6f9e8
Fase 4: experience across customers
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
The hub records when an instance changes build and works out which
findings went away within three days of an update and which were still
there a week later (version rules excluded). Staff see every effect in
the portal; effects seen at three or more customers, resolved more
often than not, are served to licensed agents as anonymous counts
(rule, major version, build, CU, customers, instances). The agent
fetches them every six hours and the web UI shows them on matching
findings: 'at 3 customers this went away after updating to CU21'.
Data processing documentation covers the aggregation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 10:33:37 +00:00
Claude
d238580614
Fase 4: management and compliance reports as PDF
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
A PDF report for management and auditors (PDFsharp/MigraDoc, MIT, with
the Inter font embedded): key figures, a plain-language summary,
compliance controls backed by rules (met, not met, not measured),
instances and the critical and high findings. Downloadable from the
web UI (/rapporter) and mailed monthly by the agent with the PDF
attached, once per month, across daylight saving changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 10:09:10 +00:00
Claude
0e2146ef6d
Fase 4: integration with Prometheus, Grafana, SCOM and scripts
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
Read-only JSON API (/api/v1/instances, /api/v1/findings) and a
Prometheus endpoint (/metrics) in the web UI, with bearer tokens for
machines (only their SHA-256 is configured; a token only opens the API,
never the pages; sensitive evidence left out unless enabled). A
Grafana dashboard and Prometheus scrape example. A Windows Event Log
notification channel with fixed event ids for SCOM, exempt from the
hourly cap.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 09:56:01 +00:00
Claude
19fbb02045
Fase 3: data processing, hub retention and deployment
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
Hub: nightly retention of resolved findings, the submission log and
silent instances; delete-customer erases a customer's data and blocks
its licenses; persistent data protection keys and trusted reverse
proxies. Docker image and compose file with PostgreSQL. The agent
refuses to send the license to a non-https hub. Documentation for the
hub, for data processing (GDPR basis for a data processing agreement)
and the README roadmap for phase 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 09:29:20 +00:00
Claude
3121b598f9
Fase 3: signed updates of rule packs and the application
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
Rule packs (support dates and newest CU per release) are published in a
signed feed and hot-loaded without a restart; the verified pack is
reloaded at startup. New versions are announced (Notify) or downloaded
and staged by the unprivileged agent (Automatic), and installed by a
privileged apply-update task that re-verifies signature and hash in an
admin-only folder, keeps appsettings/web.config, health-checks the
services and rolls back on failure. Stable and preview channels,
manifest expiry and rollback protection, https or folder/share feeds
for offline sites. Vendor tool gains rulepack and publish; the Hub can
serve the feed; the web UI gets a System page with update, rule pack,
license and exactly what is sent to the Hub.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 09:19:41 +00:00
Claude
bfb27778d2
Fase 3: findings sync from agent to hub (queue, retry, data minimization)
Some checks are pending
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
- Evidence can be marked sensitive (query text, logins, hosts, programs,
  job error messages); rules mark it. Sensitive values and the server
  name are sent as [udeladt] unless the customer allows them.
- Full-state submission contract (all active findings and rule outcomes
  per instance), idempotent by submission id
- Local outbound queue in the repository (migration 0002): newest state
  per instance only, exponential backoff up to an hour, permanent
  rejections (bad license, bad request) are given up, sent items purged
- Hub status (license state, last sent, last error) for the web UI
- Sync runs only with a valid license (or in grace); monitoring never
  depends on it

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 08:35:22 +00:00
Claude
edb7410f76
Fase 2: Azure SQL Managed Instance, docs and rule catalog test
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
- Managed Instance reports 12.0.2000.8 but is evergreen: treated as the
  newest engine with all capabilities; new SelfManagedInfrastructure
  capability so backup, CHECKDB, files, tempdb, memory, patch level and
  lifecycle rules report 'handled by Azure' instead of false findings
- Microsoft Entra ID login (managed identity, service principal, default
  credential chain) via SqlConnection.AccessTokenCallback
- Least-privilege script recognizes Managed Instance; deadlock collector
  falls back to the ring buffer when event files cannot be read
- Web UI shows the right release for Managed Instance
- README and installation docs: notifications and Managed Instance
- Catalog test: 61 rules with unique, well-formed ids

Integration suite green on SQL Server 2017 and 2022.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 08:23:40 +00:00
Claude
eac799a1f1
Fase 2: notifications by e-mail, Teams and webhook
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
- Repository reports which findings opened and resolved per evaluation
- Agent notifies on new and resolved findings and on instance
  unreachable/recovered transitions, with links to the web UI
- Channels: e-mail (MailKit, HTML-encoded), Microsoft Teams Workflows
  webhook (Adaptive Card), generic JSON webhook signed with HMAC-SHA256
- Per-channel minimum severity (outages always sent), one message per
  batch, hourly cap per channel; a failing channel never stops monitoring
- Tested with a real SMTP server (Mailpit) and the real agent pipeline

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 08:08:06 +00:00
Claude
d84cf8c2b6
Fase 2: baselines and anomaly detection
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
Baselines per hour of the week (with neighbouring hours) from four weeks
of hourly aggregates, computed in C# (independent of DATEFIRST) and
refreshed by the agent each hour. SQLI-ANOM-001 compares current load
with what is normal at this time: CPU far above normal, batch requests
far above or collapsed (application down?), page life expectancy
collapse. Not measurable until enough history exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 08:01:11 +00:00
Claude
5bb1c37fef
Fase 1: on-prem web UI (IIS or Windows service), light design system
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
- ASP.NET Core Blazor static SSR: overview with KPI tiles, instance page
  (findings, CPU/batch/PLE trends, top waits, file latency, blocking,
  deadlocks with .xdl download, not-measurable rules, resolved), finding
  detail with explanation, evidence, fix script and references
- Light-first design (sidebar, cards, self-hosted Inter, teal accent),
  optional dark theme via toggle; strict CSP, no inline styles
- Windows authentication (Negotiate/IIS) with optional group restriction;
  refuses to run without authentication outside Development
- Hosting: IIS (in-process ASP.NET Core Module), Windows service with
  Kestrel, or systemd; web reads the repository with db_datareader only
- docs/installation.md for repository, permissions, agent and web
- Fix: CPU used by other processes is not derived on Linux (SystemIdle is
  unreliable there); deadlocks are not re-reported or stored twice after
  an agent restart; Dapper sends datetime2 so time comparisons are exact

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 06:58:51 +00:00
Claude
9372c2e927
Fase 1: local repository with finding tracking, time series and retention
Some checks are pending
CI / Integration (mcr.microsoft.com/mssql/server:2017-latest) (push) Blocked by required conditions
CI / Build og unit tests (push) Waiting to run
CI / Integration (mcr.microsoft.com/mssql/server:2019-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2022-latest) (push) Blocked by required conditions
CI / Integration (mcr.microsoft.com/mssql/server:2025-latest) (push) Blocked by required conditions
- Versioned, embedded migrations serialized with sp_getapplock so the agent
  and web UI can both migrate at startup
- Findings tracked per rule and subject: first seen, last seen, resolved;
  a rule that could not run never resolves its findings
- Time series (waits, file I/O, CPU, counters), blocking chains and
  deadlock graphs; idempotent inserts (timestamps truncated to match
  datetime2(0)), hourly aggregation and batched retention deletes
- Read API for the web UI; integration tests against SQL Server

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01E3EExwndy8Z22EK2Qpt6BK
2026-09-29 06:23:38 +00:00