sqlinsight-pro/src/SQLInsight.Repository/Migrations/0005_support_cases.sql
Søren Eggert Lundsteen Olsen 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

36 lines
2.3 KiB
SQL

/* Support cases with SEOSoft (Professional/Enterprise). SQLInsight Web adds a request (Status 'Pending'); the agent
sends it to SQLInsight Hub, stores the case number it gets back, and keeps every case's status in step with the hub,
including cases SEOSoft created (ClientRequestId NULL). */
CREATE TABLE insight.SupportCases
(
CaseId bigint IDENTITY(1, 1) NOT NULL CONSTRAINT PK_SupportCases PRIMARY KEY,
ClientRequestId uniqueidentifier NULL,
Reference nvarchar(32) NULL,
Title nvarchar(200) NOT NULL,
Description nvarchar(max) NULL,
ContactName nvarchar(200) NULL,
ContactEmail nvarchar(320) NULL,
ContactPhone nvarchar(50) NULL,
FindingId bigint NULL,
InstanceName nvarchar(128) NULL,
RuleId nvarchar(50) NULL,
Subject nvarchar(400) NULL,
RequestedBy nvarchar(256) NULL,
Source varchar(16) NOT NULL CONSTRAINT DF_SupportCases_Source DEFAULT ('Customer'),
Status varchar(16) NOT NULL CONSTRAINT DF_SupportCases_Status DEFAULT ('Pending')
CONSTRAINT CK_SupportCases_Status CHECK (Status IN ('Pending', 'Open', 'Closed', 'Failed')),
LastError nvarchar(1000) NULL,
Attempts int NOT NULL CONSTRAINT DF_SupportCases_Attempts DEFAULT (0),
NextAttemptAt datetime2(0) NOT NULL CONSTRAINT DF_SupportCases_NextAttemptAt DEFAULT (SYSUTCDATETIME()),
CreatedAt datetime2(0) NOT NULL CONSTRAINT DF_SupportCases_CreatedAt DEFAULT (SYSUTCDATETIME()),
SentAt datetime2(0) NULL,
ClosedAt datetime2(0) NULL,
UpdatedAt datetime2(0) NOT NULL CONSTRAINT DF_SupportCases_UpdatedAt DEFAULT (SYSUTCDATETIME())
);
CREATE UNIQUE INDEX UQ_SupportCases_ClientRequestId ON insight.SupportCases (ClientRequestId) WHERE ClientRequestId IS NOT NULL;
CREATE UNIQUE INDEX UQ_SupportCases_Reference ON insight.SupportCases (Reference) WHERE Reference IS NOT NULL;
CREATE INDEX IX_SupportCases_Pending ON insight.SupportCases (NextAttemptAt) WHERE Status = 'Pending';
/* The web UI only has db_datareader, yet it must be able to file a request. INSERT on this one table is granted to
public: only the repository's own users (the agent, the web UI and its administrators) exist in this database. */
GRANT INSERT ON insight.SupportCases TO public;