Task #41: Let users click a non-binary file in the "Geprüfte Dateien" tree to view its stored text content, without re-downloading the archive. Changes: - lib/api-spec/openapi.yaml: added optional nullable `content` field to the ScanFile schema so the scan-detail response can carry stored file text. - Regenerated API codegen (api-client-react + api-zod via orval) and ran the libs typecheck. - artifacts/api-server/src/routes/scans.ts: serializeFile now returns `content` alongside the existing `hasContent`. Only used by the scan detail endpoint, so list responses are unaffected. - artifacts/skillguard/src/pages/scan-report.tsx (FilesTree): non-binary file names are now clickable buttons that open a Dialog showing the stored content in a monospace, scrollable panel (ScrollArea). Binary files (hasContent === false) render as plain text and show a clear "Keine Vorschau verfügbar (Binärdatei)." message in the dialog guard. Verification: - tsc -b passes for both skillguard and api-server. - relation + compare route tests pass (8 tests). - Confirmed via API that the detail endpoint exposes content for a text-source scan (hasContent true) and null for binary .skill archives. No new persistence: content is read from existing scan file data. Replit-Task-Id: 931befbc-6ca3-4d15-b422-ac8e9f061f9f
1095 lines
27 KiB
YAML
1095 lines
27 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
# Do not change the title, if the title changes, the import paths will be broken
|
|
title: Api
|
|
version: 0.1.0
|
|
description: API specification
|
|
servers:
|
|
- url: /api
|
|
description: Base API path
|
|
tags:
|
|
- name: health
|
|
description: Health operations
|
|
- name: scans
|
|
description: Skill scans and audit reports
|
|
- name: providers
|
|
description: Configurable external AI providers
|
|
- name: prompts
|
|
description: Configurable AI analysis prompts
|
|
- name: rules
|
|
description: Static rule catalog configuration
|
|
- name: dashboard
|
|
description: Dashboard summaries
|
|
paths:
|
|
/healthz:
|
|
get:
|
|
operationId: healthCheck
|
|
tags: [health]
|
|
summary: Health check
|
|
description: Returns server health status
|
|
responses:
|
|
"200":
|
|
description: Healthy
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/HealthStatus"
|
|
|
|
/dashboard:
|
|
get:
|
|
operationId: getDashboard
|
|
tags: [dashboard]
|
|
summary: Dashboard summary
|
|
description: Aggregated statistics across all scans.
|
|
responses:
|
|
"200":
|
|
description: Dashboard summary
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/DashboardSummary"
|
|
|
|
/scans:
|
|
get:
|
|
operationId: listScans
|
|
tags: [scans]
|
|
summary: List scan history
|
|
responses:
|
|
"200":
|
|
description: List of scans (most recent first)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Scan"
|
|
post:
|
|
operationId: createScan
|
|
tags: [scans]
|
|
summary: Upload a skill and run an audit
|
|
description: >-
|
|
Accepts a skill as a base64 ZIP archive, a single base64 file, or pasted
|
|
text, runs the static rule engine and (optionally) the configured AI
|
|
analysis, and returns the completed report.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/SkillScanInput"
|
|
responses:
|
|
"201":
|
|
description: Completed scan report
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ScanDetail"
|
|
"400":
|
|
description: Invalid input
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiError"
|
|
|
|
/scans/{id}/compare/{otherId}:
|
|
get:
|
|
operationId: compareScans
|
|
tags: [scans]
|
|
summary: Compare two scans on the file level
|
|
description: >-
|
|
Returns a file-level diff between the current scan (id) and a previously
|
|
stored scan (otherId), including line-by-line diffs for modified text
|
|
files.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
- name: otherId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: File-level comparison
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ScanComparison"
|
|
"404":
|
|
description: Not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiError"
|
|
|
|
/scans/{id}/lineage:
|
|
get:
|
|
operationId: getScanLineage
|
|
tags: [scans]
|
|
summary: Get the version timeline for a skill family
|
|
description: >-
|
|
Returns every scan in the same fingerprint lineage as the given scan
|
|
(linked by an identical fingerprint or by the comparedScanId chain),
|
|
newest first, so the full version history of a skill can be shown on a
|
|
timeline without re-scanning.
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: Version timeline (most recent first)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ScanLineageEntry"
|
|
"404":
|
|
description: Not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiError"
|
|
|
|
/scans/{id}:
|
|
get:
|
|
operationId: getScan
|
|
tags: [scans]
|
|
summary: Get a scan report with findings
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: Scan report
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ScanDetail"
|
|
"404":
|
|
description: Not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiError"
|
|
delete:
|
|
operationId: deleteScan
|
|
tags: [scans]
|
|
summary: Delete a scan report
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
|
|
/scans/{id}/description:
|
|
post:
|
|
operationId: generateScanDescription
|
|
tags: [scans]
|
|
summary: Generate the AI description for an existing scan
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: Scan report with the newly generated description
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ScanDetail"
|
|
"404":
|
|
description: Not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiError"
|
|
"422":
|
|
description: Description could not be generated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ApiError"
|
|
|
|
/providers:
|
|
get:
|
|
operationId: listProviders
|
|
tags: [providers]
|
|
summary: List configured AI providers
|
|
responses:
|
|
"200":
|
|
description: List of providers (tokens masked)
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/AiProvider"
|
|
post:
|
|
operationId: createProvider
|
|
tags: [providers]
|
|
summary: Create an AI provider
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AiProviderInput"
|
|
responses:
|
|
"201":
|
|
description: Created provider
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AiProvider"
|
|
|
|
/providers/{id}:
|
|
patch:
|
|
operationId: updateProvider
|
|
tags: [providers]
|
|
summary: Update an AI provider
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AiProviderUpdate"
|
|
responses:
|
|
"200":
|
|
description: Updated provider
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/AiProvider"
|
|
delete:
|
|
operationId: deleteProvider
|
|
tags: [providers]
|
|
summary: Delete an AI provider
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"204":
|
|
description: Deleted
|
|
|
|
/providers/{id}/test:
|
|
post:
|
|
operationId: testProvider
|
|
tags: [providers]
|
|
summary: Test the connection to an AI provider
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
"200":
|
|
description: Test result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ProviderTestResult"
|
|
|
|
/providers/test-connection:
|
|
post:
|
|
operationId: testProviderConnection
|
|
tags: [providers]
|
|
summary: Test a provider connection with ad-hoc configuration
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ProviderTestConnectionInput"
|
|
responses:
|
|
"200":
|
|
description: Test result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ProviderTestResult"
|
|
|
|
/providers/list-models:
|
|
post:
|
|
operationId: listProviderModels
|
|
tags: [providers]
|
|
summary: List the available models for a provider configuration
|
|
description: >-
|
|
Queries the provider's models endpoint with the supplied ad-hoc
|
|
configuration (or the stored token of providerId when the token is
|
|
omitted) and returns the discovered model IDs.
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ProviderListModelsInput"
|
|
responses:
|
|
"200":
|
|
description: Discovered models
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/ProviderModelsResult"
|
|
|
|
/prompts:
|
|
get:
|
|
operationId: listPrompts
|
|
tags: [prompts]
|
|
summary: List configurable AI prompts
|
|
responses:
|
|
"200":
|
|
description: List of prompts
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Prompt"
|
|
|
|
/prompts/{id}:
|
|
patch:
|
|
operationId: updatePrompt
|
|
tags: [prompts]
|
|
summary: Update an AI prompt
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/PromptUpdate"
|
|
responses:
|
|
"200":
|
|
description: Updated prompt
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Prompt"
|
|
|
|
/rules:
|
|
get:
|
|
operationId: listRules
|
|
tags: [rules]
|
|
summary: List the static rule catalog
|
|
responses:
|
|
"200":
|
|
description: List of rules
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Rule"
|
|
|
|
/rules/{id}:
|
|
patch:
|
|
operationId: updateRule
|
|
tags: [rules]
|
|
summary: Update a rule's severity or enabled state
|
|
parameters:
|
|
- name: id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/RuleUpdate"
|
|
responses:
|
|
"200":
|
|
description: Updated rule
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Rule"
|
|
|
|
components:
|
|
schemas:
|
|
HealthStatus:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
required:
|
|
- status
|
|
|
|
ApiError:
|
|
type: object
|
|
required: [error]
|
|
properties:
|
|
error:
|
|
type: string
|
|
|
|
SkillScanInput:
|
|
type: object
|
|
required: [source, useAi]
|
|
properties:
|
|
name:
|
|
type: ["string", "null"]
|
|
description: Optional display name for the scan
|
|
source:
|
|
type: string
|
|
enum: [zip, file, text]
|
|
useAi:
|
|
type: boolean
|
|
description: Whether to also run the configured AI analysis
|
|
contentBase64:
|
|
type: ["string", "null"]
|
|
description: Base64 content for source=zip or source=file
|
|
filename:
|
|
type: ["string", "null"]
|
|
description: Original filename for source=file or source=zip
|
|
text:
|
|
type: ["string", "null"]
|
|
description: Raw skill text for source=text
|
|
|
|
Scan:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- source
|
|
- status
|
|
- verdict
|
|
- riskScore
|
|
- fileCount
|
|
- aiUsed
|
|
- findingCounts
|
|
- fingerprint
|
|
- relation
|
|
- similarity
|
|
- comparedScanId
|
|
- createdAt
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
description:
|
|
type: ["string", "null"]
|
|
description: AI-generated summary of the skill's purpose (null when no AI description is available)
|
|
source:
|
|
type: string
|
|
enum: [zip, file, text]
|
|
status:
|
|
type: string
|
|
enum: [completed, failed]
|
|
verdict:
|
|
type: string
|
|
enum: [pass, review, block]
|
|
riskScore:
|
|
type: integer
|
|
fileCount:
|
|
type: integer
|
|
aiUsed:
|
|
type: boolean
|
|
aiError:
|
|
type: ["string", "null"]
|
|
findingCounts:
|
|
$ref: "#/components/schemas/FindingCounts"
|
|
fingerprint:
|
|
type: string
|
|
description: Deterministic hash over all files (path + per-file hash)
|
|
relation:
|
|
type: ["string", "null"]
|
|
enum: [new, identical, modified, null]
|
|
description: Relation to previously stored skills
|
|
similarity:
|
|
type: ["integer", "null"]
|
|
description: Content-aware similarity (0-100) to the compared skill (identical files count fully, changed text files use line-level similarity)
|
|
comparedScanId:
|
|
type: ["integer", "null"]
|
|
description: The scan this one was compared against, if any
|
|
createdAt:
|
|
type: string
|
|
|
|
FindingCounts:
|
|
type: object
|
|
required: [critical, high, medium, low, info, security, privacy, total]
|
|
properties:
|
|
critical:
|
|
type: integer
|
|
high:
|
|
type: integer
|
|
medium:
|
|
type: integer
|
|
low:
|
|
type: integer
|
|
info:
|
|
type: integer
|
|
security:
|
|
type: integer
|
|
privacy:
|
|
type: integer
|
|
total:
|
|
type: integer
|
|
|
|
ScanCheckpoint:
|
|
type: object
|
|
description: >-
|
|
A single inspection step (Prüfschritt) with its partial assessment
|
|
(Teilbewertung).
|
|
required: [id, label, category, status, findingCount, scoreDelta]
|
|
properties:
|
|
id:
|
|
type: string
|
|
label:
|
|
type: string
|
|
category:
|
|
type: string
|
|
axis:
|
|
type: ["string", "null"]
|
|
enum: [security, privacy, null]
|
|
severity:
|
|
type: ["string", "null"]
|
|
enum: [critical, high, medium, low, info, null]
|
|
status:
|
|
type: string
|
|
enum: [pass, flagged, skipped, error]
|
|
findingCount:
|
|
type: integer
|
|
scoreDelta:
|
|
type: integer
|
|
detectedBy:
|
|
type: ["string", "null"]
|
|
enum: [static, ai, null]
|
|
|
|
ScanFile:
|
|
type: object
|
|
required: [path, kind, size, hash, hasContent]
|
|
properties:
|
|
path:
|
|
type: string
|
|
kind:
|
|
type: string
|
|
enum: [instruction, script, resource]
|
|
language:
|
|
type: ["string", "null"]
|
|
size:
|
|
type: integer
|
|
hash:
|
|
type: string
|
|
description: SHA-256 hash of the file content
|
|
hasContent:
|
|
type: boolean
|
|
description: Whether the text content was stored (false for binary files)
|
|
content:
|
|
type: ["string", "null"]
|
|
description: The stored text content of the file, or null for binary files
|
|
|
|
Finding:
|
|
type: object
|
|
required:
|
|
- id
|
|
- ruleId
|
|
- axis
|
|
- severity
|
|
- title
|
|
- description
|
|
- detectedBy
|
|
properties:
|
|
id:
|
|
type: integer
|
|
ruleId:
|
|
type: string
|
|
axis:
|
|
type: string
|
|
enum: [security, privacy]
|
|
severity:
|
|
type: string
|
|
enum: [critical, high, medium, low, info]
|
|
title:
|
|
type: string
|
|
description:
|
|
type: string
|
|
remediation:
|
|
type: ["string", "null"]
|
|
file:
|
|
type: ["string", "null"]
|
|
line:
|
|
type: ["integer", "null"]
|
|
snippet:
|
|
type: ["string", "null"]
|
|
detectedBy:
|
|
type: string
|
|
enum: [static, ai]
|
|
|
|
ScanDetail:
|
|
allOf:
|
|
- $ref: "#/components/schemas/Scan"
|
|
- type: object
|
|
required: [files, findings, checkpoints, checkCount, comparedScan]
|
|
properties:
|
|
files:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ScanFile"
|
|
findings:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Finding"
|
|
checkpoints:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ScanCheckpoint"
|
|
checkCount:
|
|
type: integer
|
|
description: How often a skill with this exact fingerprint was scanned
|
|
comparedScan:
|
|
oneOf:
|
|
- $ref: "#/components/schemas/ComparedScan"
|
|
- type: "null"
|
|
|
|
ComparedScan:
|
|
type: object
|
|
required: [id, name, verdict, riskScore, createdAt]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
verdict:
|
|
type: string
|
|
enum: [pass, review, block]
|
|
riskScore:
|
|
type: integer
|
|
createdAt:
|
|
type: string
|
|
|
|
ScanLineageEntry:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- verdict
|
|
- riskScore
|
|
- relation
|
|
- similarity
|
|
- comparedScanId
|
|
- fingerprint
|
|
- createdAt
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
verdict:
|
|
type: string
|
|
enum: [pass, review, block]
|
|
riskScore:
|
|
type: integer
|
|
relation:
|
|
type: ["string", "null"]
|
|
enum: [new, identical, modified, null]
|
|
description: Relation of this version to the one it was compared against
|
|
similarity:
|
|
type: ["integer", "null"]
|
|
description: Content-aware similarity (0-100) to its compared version
|
|
comparedScanId:
|
|
type: ["integer", "null"]
|
|
description: The prior version this scan was compared against, if any
|
|
fingerprint:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
|
|
ScanComparisonSide:
|
|
type: object
|
|
required: [id, name, verdict, riskScore, fileCount, fingerprint, createdAt]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
verdict:
|
|
type: string
|
|
enum: [pass, review, block]
|
|
riskScore:
|
|
type: integer
|
|
fileCount:
|
|
type: integer
|
|
fingerprint:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
|
|
DiffLine:
|
|
type: object
|
|
required: [type, text, previousLine, currentLine]
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [context, add, remove]
|
|
text:
|
|
type: string
|
|
previousLine:
|
|
type: ["integer", "null"]
|
|
currentLine:
|
|
type: ["integer", "null"]
|
|
|
|
ScanFileDiff:
|
|
type: object
|
|
required:
|
|
- path
|
|
- status
|
|
- previousHash
|
|
- currentHash
|
|
- previousSize
|
|
- currentSize
|
|
- previousHasContent
|
|
- currentHasContent
|
|
- lineDiff
|
|
properties:
|
|
path:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum: [unchanged, modified, added, removed]
|
|
previousHash:
|
|
type: ["string", "null"]
|
|
currentHash:
|
|
type: ["string", "null"]
|
|
previousSize:
|
|
type: ["integer", "null"]
|
|
currentSize:
|
|
type: ["integer", "null"]
|
|
previousHasContent:
|
|
type: ["boolean", "null"]
|
|
currentHasContent:
|
|
type: ["boolean", "null"]
|
|
lineDiff:
|
|
oneOf:
|
|
- type: array
|
|
items:
|
|
$ref: "#/components/schemas/DiffLine"
|
|
- type: "null"
|
|
|
|
ScanComparison:
|
|
type: object
|
|
required: [current, previous, files]
|
|
properties:
|
|
current:
|
|
$ref: "#/components/schemas/ScanComparisonSide"
|
|
previous:
|
|
$ref: "#/components/schemas/ScanComparisonSide"
|
|
files:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/ScanFileDiff"
|
|
|
|
AiProvider:
|
|
type: object
|
|
required:
|
|
- id
|
|
- name
|
|
- apiType
|
|
- baseUrl
|
|
- model
|
|
- enabled
|
|
- hasToken
|
|
- tokenPreview
|
|
- createdAt
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
apiType:
|
|
type: string
|
|
enum: [openai, anthropic, custom]
|
|
baseUrl:
|
|
type: string
|
|
model:
|
|
type: string
|
|
enabled:
|
|
type: boolean
|
|
hasToken:
|
|
type: boolean
|
|
tokenPreview:
|
|
type: string
|
|
description: Masked preview of the stored token (e.g. "sk-...abcd")
|
|
createdAt:
|
|
type: string
|
|
|
|
AiProviderInput:
|
|
type: object
|
|
required: [name, apiType, baseUrl, model]
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
apiType:
|
|
type: string
|
|
enum: [openai, anthropic, custom]
|
|
baseUrl:
|
|
type: string
|
|
minLength: 1
|
|
model:
|
|
type: string
|
|
minLength: 1
|
|
apiToken:
|
|
type: string
|
|
enabled:
|
|
type: boolean
|
|
|
|
AiProviderUpdate:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
apiType:
|
|
type: string
|
|
enum: [openai, anthropic, custom]
|
|
baseUrl:
|
|
type: string
|
|
minLength: 1
|
|
model:
|
|
type: string
|
|
minLength: 1
|
|
apiToken:
|
|
type: string
|
|
description: Provide to replace the stored token; omit to keep existing
|
|
enabled:
|
|
type: boolean
|
|
|
|
ProviderTestResult:
|
|
type: object
|
|
required: [ok]
|
|
properties:
|
|
ok:
|
|
type: boolean
|
|
message:
|
|
type: ["string", "null"]
|
|
|
|
ProviderTestConnectionInput:
|
|
type: object
|
|
required: [apiType, baseUrl]
|
|
properties:
|
|
apiType:
|
|
type: string
|
|
enum: [openai, anthropic, custom]
|
|
baseUrl:
|
|
type: string
|
|
minLength: 1
|
|
model:
|
|
type: string
|
|
description: Optional model to exercise with a full request; when omitted the test verifies credentials via the models endpoint instead
|
|
apiToken:
|
|
type: string
|
|
description: Token to use for the test; omit or leave empty to fall back to the stored token of providerId
|
|
providerId:
|
|
type: integer
|
|
description: When apiToken is empty, fall back to this saved provider's stored token
|
|
|
|
ProviderListModelsInput:
|
|
type: object
|
|
required: [apiType, baseUrl]
|
|
properties:
|
|
apiType:
|
|
type: string
|
|
enum: [openai, anthropic, custom]
|
|
baseUrl:
|
|
type: string
|
|
minLength: 1
|
|
apiToken:
|
|
type: string
|
|
description: Token to use for the request; omit or leave empty to fall back to the stored token of providerId
|
|
providerId:
|
|
type: integer
|
|
description: When apiToken is empty, fall back to this saved provider's stored token
|
|
|
|
ProviderModelsResult:
|
|
type: object
|
|
required: [ok, models]
|
|
properties:
|
|
ok:
|
|
type: boolean
|
|
models:
|
|
type: array
|
|
items:
|
|
type: string
|
|
message:
|
|
type: ["string", "null"]
|
|
|
|
Prompt:
|
|
type: object
|
|
required: [id, key, name, content, updatedAt]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
key:
|
|
type: string
|
|
name:
|
|
type: string
|
|
content:
|
|
type: string
|
|
updatedAt:
|
|
type: string
|
|
|
|
PromptUpdate:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
content:
|
|
type: string
|
|
minLength: 1
|
|
|
|
Rule:
|
|
type: object
|
|
required:
|
|
- id
|
|
- ruleId
|
|
- axis
|
|
- category
|
|
- title
|
|
- description
|
|
- severity
|
|
- detectionType
|
|
- enabled
|
|
properties:
|
|
id:
|
|
type: integer
|
|
ruleId:
|
|
type: string
|
|
axis:
|
|
type: string
|
|
enum: [security, privacy]
|
|
category:
|
|
type: string
|
|
title:
|
|
type: string
|
|
description:
|
|
type: string
|
|
severity:
|
|
type: string
|
|
enum: [critical, high, medium, low, info]
|
|
detectionType:
|
|
type: string
|
|
enum: [regex, heuristic, ai]
|
|
enabled:
|
|
type: boolean
|
|
|
|
RuleUpdate:
|
|
type: object
|
|
properties:
|
|
severity:
|
|
type: string
|
|
enum: [critical, high, medium, low, info]
|
|
enabled:
|
|
type: boolean
|
|
|
|
DashboardSummary:
|
|
type: object
|
|
required:
|
|
- totalScans
|
|
- avgRiskScore
|
|
- verdictCounts
|
|
- severityTotals
|
|
- axisTotals
|
|
- recentScans
|
|
- topRules
|
|
properties:
|
|
totalScans:
|
|
type: integer
|
|
avgRiskScore:
|
|
type: integer
|
|
verdictCounts:
|
|
$ref: "#/components/schemas/VerdictCounts"
|
|
severityTotals:
|
|
$ref: "#/components/schemas/SeverityTotals"
|
|
axisTotals:
|
|
$ref: "#/components/schemas/AxisTotals"
|
|
recentScans:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Scan"
|
|
topRules:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/RuleStat"
|
|
|
|
VerdictCounts:
|
|
type: object
|
|
required: [pass, review, block]
|
|
properties:
|
|
pass:
|
|
type: integer
|
|
review:
|
|
type: integer
|
|
block:
|
|
type: integer
|
|
|
|
SeverityTotals:
|
|
type: object
|
|
required: [critical, high, medium, low, info]
|
|
properties:
|
|
critical:
|
|
type: integer
|
|
high:
|
|
type: integer
|
|
medium:
|
|
type: integer
|
|
low:
|
|
type: integer
|
|
info:
|
|
type: integer
|
|
|
|
AxisTotals:
|
|
type: object
|
|
required: [security, privacy]
|
|
properties:
|
|
security:
|
|
type: integer
|
|
privacy:
|
|
type: integer
|
|
|
|
RuleStat:
|
|
type: object
|
|
required: [ruleId, title, axis, count]
|
|
properties:
|
|
ruleId:
|
|
type: string
|
|
title:
|
|
type: string
|
|
axis:
|
|
type: string
|
|
enum: [security, privacy]
|
|
count:
|
|
type: integer
|