130 lines
7.1 KiB
SQL
130 lines
7.1 KiB
SQL
-- Closed-loop repository findings, Gitea issue synchronization and investigations.
|
|
CREATE TYPE "FindingSeverity" AS ENUM ('info', 'warning', 'critical');
|
|
CREATE TYPE "FindingStatus" AS ENUM ('new', 'triaged', 'issue_open', 'investigating', 'planned', 'fixing', 'verifying', 'resolved', 'regressed', 'suppressed');
|
|
CREATE TYPE "InvestigationStatus" AS ENUM ('collecting', 'ready', 'concluded', 'planned', 'fixing', 'verifying', 'resolved', 'failed', 'cancelled');
|
|
CREATE TYPE "IssueSyncMode" AS ENUM ('manual', 'review', 'automatic');
|
|
|
|
ALTER TYPE "EntityType" ADD VALUE IF NOT EXISTS 'repository_finding';
|
|
ALTER TYPE "EntityType" ADD VALUE IF NOT EXISTS 'finding_investigation';
|
|
ALTER TYPE "EntityType" ADD VALUE IF NOT EXISTS 'gitea_issue';
|
|
|
|
CREATE TABLE "RepositoryFinding" (
|
|
"id" TEXT NOT NULL,
|
|
"fingerprint" TEXT NOT NULL,
|
|
"projectId" TEXT,
|
|
"repositoryLinkId" TEXT,
|
|
"owner" TEXT NOT NULL,
|
|
"repository" TEXT NOT NULL,
|
|
"ruleCode" TEXT NOT NULL,
|
|
"subject" TEXT NOT NULL,
|
|
"title" TEXT NOT NULL,
|
|
"message" TEXT NOT NULL,
|
|
"severity" "FindingSeverity" NOT NULL,
|
|
"confidence" INTEGER NOT NULL DEFAULT 90,
|
|
"riskScore" INTEGER NOT NULL DEFAULT 0,
|
|
"status" "FindingStatus" NOT NULL DEFAULT 'new',
|
|
"occurrenceCount" INTEGER NOT NULL DEFAULT 1,
|
|
"clearCount" INTEGER NOT NULL DEFAULT 0,
|
|
"firstSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"lastSeenAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"resolvedAt" TIMESTAMP(3),
|
|
"suppressedAt" TIMESTAMP(3),
|
|
"suppressedUntil" TIMESTAMP(3),
|
|
"suppressionReason" TEXT,
|
|
"lastAnalysisJobId" TEXT,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "RepositoryFinding_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "FindingOccurrence" (
|
|
"id" TEXT NOT NULL,
|
|
"findingId" TEXT NOT NULL,
|
|
"analysisJobItemId" TEXT NOT NULL,
|
|
"observed" BOOLEAN NOT NULL DEFAULT true,
|
|
"detailJson" JSONB,
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
CONSTRAINT "FindingOccurrence_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "GiteaIssueLink" (
|
|
"id" TEXT NOT NULL,
|
|
"findingId" TEXT NOT NULL,
|
|
"owner" TEXT NOT NULL,
|
|
"repository" TEXT NOT NULL,
|
|
"issueNumber" INTEGER NOT NULL,
|
|
"issueUrl" TEXT NOT NULL,
|
|
"state" TEXT NOT NULL DEFAULT 'open',
|
|
"title" TEXT NOT NULL,
|
|
"bodyFingerprint" TEXT NOT NULL,
|
|
"lastSyncedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"closedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "GiteaIssueLink_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "FindingInvestigation" (
|
|
"id" TEXT NOT NULL,
|
|
"findingId" TEXT NOT NULL,
|
|
"projectId" TEXT,
|
|
"deliveryPlanId" TEXT,
|
|
"status" "InvestigationStatus" NOT NULL DEFAULT 'collecting',
|
|
"actor" TEXT NOT NULL,
|
|
"contextJson" JSONB NOT NULL,
|
|
"diagnosis" TEXT,
|
|
"rootCause" TEXT,
|
|
"proposedChangesJson" JSONB NOT NULL DEFAULT '[]',
|
|
"confidence" INTEGER,
|
|
"conclusion" TEXT,
|
|
"startedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"concludedAt" TIMESTAMP(3),
|
|
"completedAt" TIMESTAMP(3),
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "FindingInvestigation_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE TABLE "FindingAutomationPolicy" (
|
|
"id" TEXT NOT NULL,
|
|
"projectId" TEXT NOT NULL,
|
|
"enabled" BOOLEAN NOT NULL DEFAULT true,
|
|
"issueSyncMode" "IssueSyncMode" NOT NULL DEFAULT 'review',
|
|
"minimumSeverity" "FindingSeverity" NOT NULL DEFAULT 'warning',
|
|
"minimumOccurrences" INTEGER NOT NULL DEFAULT 2,
|
|
"maxIssuesPerRun" INTEGER NOT NULL DEFAULT 5,
|
|
"autoCloseResolved" BOOLEAN NOT NULL DEFAULT true,
|
|
"autoReopenRegressed" BOOLEAN NOT NULL DEFAULT true,
|
|
"scheduledAnalysis" BOOLEAN NOT NULL DEFAULT true,
|
|
"scheduleMinutes" INTEGER NOT NULL DEFAULT 1440,
|
|
"updatedBy" TEXT NOT NULL DEFAULT 'system',
|
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
"updatedAt" TIMESTAMP(3) NOT NULL,
|
|
CONSTRAINT "FindingAutomationPolicy_pkey" PRIMARY KEY ("id")
|
|
);
|
|
|
|
CREATE UNIQUE INDEX "RepositoryFinding_fingerprint_key" ON "RepositoryFinding"("fingerprint");
|
|
CREATE INDEX "RepositoryFinding_projectId_status_severity_idx" ON "RepositoryFinding"("projectId", "status", "severity");
|
|
CREATE INDEX "RepositoryFinding_repositoryLinkId_status_idx" ON "RepositoryFinding"("repositoryLinkId", "status");
|
|
CREATE INDEX "RepositoryFinding_owner_repository_status_idx" ON "RepositoryFinding"("owner", "repository", "status");
|
|
CREATE INDEX "RepositoryFinding_lastSeenAt_idx" ON "RepositoryFinding"("lastSeenAt");
|
|
CREATE UNIQUE INDEX "FindingOccurrence_findingId_analysisJobItemId_key" ON "FindingOccurrence"("findingId", "analysisJobItemId");
|
|
CREATE INDEX "FindingOccurrence_analysisJobItemId_idx" ON "FindingOccurrence"("analysisJobItemId");
|
|
CREATE UNIQUE INDEX "GiteaIssueLink_findingId_key" ON "GiteaIssueLink"("findingId");
|
|
CREATE UNIQUE INDEX "GiteaIssueLink_owner_repository_issueNumber_key" ON "GiteaIssueLink"("owner", "repository", "issueNumber");
|
|
CREATE INDEX "GiteaIssueLink_state_updatedAt_idx" ON "GiteaIssueLink"("state", "updatedAt");
|
|
CREATE UNIQUE INDEX "FindingInvestigation_deliveryPlanId_key" ON "FindingInvestigation"("deliveryPlanId");
|
|
CREATE INDEX "FindingInvestigation_findingId_createdAt_idx" ON "FindingInvestigation"("findingId", "createdAt");
|
|
CREATE INDEX "FindingInvestigation_projectId_status_idx" ON "FindingInvestigation"("projectId", "status");
|
|
CREATE UNIQUE INDEX "FindingAutomationPolicy_projectId_key" ON "FindingAutomationPolicy"("projectId");
|
|
|
|
ALTER TABLE "RepositoryFinding" ADD CONSTRAINT "RepositoryFinding_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "RepositoryFinding" ADD CONSTRAINT "RepositoryFinding_repositoryLinkId_fkey" FOREIGN KEY ("repositoryLinkId") REFERENCES "GiteaRepositoryLink"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "FindingOccurrence" ADD CONSTRAINT "FindingOccurrence_findingId_fkey" FOREIGN KEY ("findingId") REFERENCES "RepositoryFinding"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "FindingOccurrence" ADD CONSTRAINT "FindingOccurrence_analysisJobItemId_fkey" FOREIGN KEY ("analysisJobItemId") REFERENCES "AnalysisJobItem"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "GiteaIssueLink" ADD CONSTRAINT "GiteaIssueLink_findingId_fkey" FOREIGN KEY ("findingId") REFERENCES "RepositoryFinding"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "FindingInvestigation" ADD CONSTRAINT "FindingInvestigation_findingId_fkey" FOREIGN KEY ("findingId") REFERENCES "RepositoryFinding"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|
|
ALTER TABLE "FindingInvestigation" ADD CONSTRAINT "FindingInvestigation_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "FindingInvestigation" ADD CONSTRAINT "FindingInvestigation_deliveryPlanId_fkey" FOREIGN KEY ("deliveryPlanId") REFERENCES "DeliveryPlan"("id") ON DELETE SET NULL ON UPDATE CASCADE;
|
|
ALTER TABLE "FindingAutomationPolicy" ADD CONSTRAINT "FindingAutomationPolicy_projectId_fkey" FOREIGN KEY ("projectId") REFERENCES "Project"("id") ON DELETE CASCADE ON UPDATE CASCADE;
|