Appearance
Findings
Findings are the core output of Krafter Audit. Each finding represents a detected issue across one of four domains: security, performance, accessibility, or SEO. This guide covers severity, the status lifecycle, the priority object, filtering, bulk operations, and regression tracking.
Severity levels
Every finding is assigned a severity based on its potential impact:
| Severity | Description |
|---|---|
| critical | Immediate threat. Exploitable vulnerabilities that could lead to data breaches, unauthorized access, or service compromise. Address these first. |
| high | Serious risk. Issues that could be exploited with effort or that significantly weaken your posture. Fix promptly. |
| medium | Moderate risk. Issues that violate best practice but are not immediately exploitable. Plan a fix. |
| low | Minor concern. Informational findings or minor best-practice deviations. Address when convenient. |
You can override the severity if your assessment differs from the automated classification:
bash
curl -X PATCH "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings/d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a" \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"severity": "high"
}'The response is the full finding shape with the new severity reflected.
Status lifecycle
Findings move through six statuses. The expected flow is left-to-right; dismissed is the terminal "won't fix" path:
new → triaged → in_progress → ready_verify → resolved
↘ dismissed| Status | Meaning |
|---|---|
| new | The finding has been detected and not yet reviewed. All new findings start here. |
| triaged | A human has reviewed the finding and accepted it as actionable. |
| in_progress | Remediation work is underway (typically tracked by a linked task). |
| ready_verify | The fix has been shipped; a verification should run before closing. |
| resolved | The fix has been verified. Set automatically when a verification is approved. |
| dismissed | The finding was evaluated and intentionally not addressed (false positive, accepted risk, etc.). |
Don't set resolved by hand
Approving a verification automatically transitions the linked finding to resolved and the linked task to done, and closes any open regression for the finding. Reopening the verification reverses all three. The recommended path is to run verifications rather than PATCH'ing status to resolved directly.
You can transition manually with PATCH for any other status:
bash
curl -X PATCH "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings/d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a" \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"status": "triaged",
"owner_id": "22222222-2222-2222-2222-222222222222"
}'Domain categories
Findings are grouped into four domains:
| Domain | Covers |
|---|---|
| security | Vulnerabilities, misconfigurations, missing headers, injection risks, authentication weaknesses |
| performance | Slow load times, unoptimized assets, render-blocking resources, excessive payloads |
| accessibility | WCAG violations, missing alt text, color contrast issues, keyboard navigation gaps |
| seo | Indexing problems, missing meta tags, broken canonical URLs, sitemap issues |
Priority and confidence
Each finding ships with two scoring objects you can use to triage:
confidenceis a0.0..1.0float reflecting how confident the scanner is that the finding is real. Treat values below0.5as unverified.prioritycontains four integer scores (impact,effort,risk,score) each in the0..100range.scoreis the composite priority used to order findings — the Findings list is sorted bypriority.scoredescending.
Both fields are produced by the AI analysis stage and may change between scans.
Filtering findings
Use query parameters to narrow down the list. Filters can be combined:
bash
# Critical security findings that have not yet been triaged
curl "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings?severity=critical&status=new&domain=security&limit=25" \
-H "Authorization: Bearer kr_live_abc123def456"json
{
"data": [
{
"id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
"org_id": "11111111-1111-1111-1111-111111111111",
"project_id": "production-website",
"domain": "security",
"title": "Missing Content-Security-Policy header",
"severity": "critical",
"status": "new",
"confidence": 0.95,
"priority": { "impact": 80, "effort": 20, "risk": 90, "score": 88 },
"owner_id": null,
"affected_assets": [{ "type": "url", "value": "https://example.com" }],
"evidence": [],
"recommended_fix": {
"summary": "Add a Content-Security-Policy header to all responses.",
"steps": ["Configure CSP at the reverse proxy", "Start with a restrictive policy", "Relax as needed"],
"estimated_minutes": 60
},
"created_at": "2025-06-15T10:05:00Z",
"updated_at": "2025-06-15T10:05:00Z"
}
],
"meta": {
"request_id": "F-mxbAQk6m9lXeQAAATj",
"total": 1,
"next_cursor": null
},
"error": null
}Available query parameters:
| Parameter | Values | Description |
|---|---|---|
severity | critical, high, medium, low | Filter by severity |
status | new, triaged, in_progress, ready_verify, resolved, dismissed | Filter by finding status |
domain | security, performance, accessibility, seo | Filter by audit domain |
limit | integer (default 25, max 100) | Page size |
offset | integer | Number of records to skip |
Findings list does not return a cursor
The findings list endpoint always returns meta.next_cursor: null. Use limit + offset to page; read meta.total to size your queries.
Getting a single finding
Fetch a finding by ID for the full detail, including evidence artefacts and the recommended fix:
bash
curl "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings/d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a" \
-H "Authorization: Bearer kr_live_abc123def456"Key fields on the response:
evidence— array of evidence records{id, type, artifact_url, checksum, captured_at}. Empty when the scanner did not attach evidence artefacts.recommended_fix—{summary, steps[], estimated_minutes}. Always present; values default to empty strings/lists/0when the scanner did not produce a recommendation.affected_assets— array of{type, value}items.type: "url"is the most common.created_at/updated_at— when the finding was first inserted and last modified. There are nofirst_seen/last_seenfields.owner_id— UUID of the assignee, ornullif unassigned.
Bulk operations
Update multiple findings at once using the bulk endpoint. Useful for triaging a batch after a scan:
bash
curl -X POST "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/findings/bulk" \
-H "Authorization: Bearer kr_live_abc123def456" \
-H "Content-Type: application/json" \
-d '{
"finding_ids": [
"d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
"e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
"f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c"
],
"patch": {
"status": "dismissed"
}
}'json
{
"data": {
"updated_count": 3,
"requested_count": 3,
"ids": [
"d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
"e5f6a7b8-9c0d-1e2f-3a4b-5c6d7e8f9a0b",
"f6a7b8c9-0d1e-2f3a-4b5c-6d7e8f9a0b1c"
]
},
"meta": {
"request_id": "G-nyc8sPL2vXfRBBBEUk"
},
"error": null
}The patch object accepts the same fields as the single-finding update: status, severity, owner_id. Compare requested_count to updated_count to detect IDs that were silently dropped (e.g. belonging to a different project).
Regression tracking
A regression is recorded when a finding that was resolved or dismissed reappears, or when a verification is reopened. Each regression carries its own lifecycle:
| Field | Description |
|---|---|
status | open while the regression is active, closed once resolved again. |
trigger | Why the regression was opened — e.g. verification_reopened when the source was a failed verification. |
severity | Severity at the time of regression. |
opened_at / closed_at | When the regression opened and (eventually) closed. |
impacted_assets | Same shape as a finding's affected_assets. |
List regressions:
bash
curl "https://app.krafter.dev/api/v1/orgs/:org_id/projects/:project_id/audit/regressions?limit=10" \
-H "Authorization: Bearer kr_live_abc123def456"json
{
"data": [
{
"id": "d4e5f6a7-8b9c-0d1e-2f3a-4b5c6d7e8f9a",
"finding_id": "a1b2c3d4-5e6f-7a8b-9c0d-1e2f3a4b5c6d",
"severity": "critical",
"trigger": "verification_reopened",
"status": "open",
"impacted_assets": [{ "type": "url", "value": "https://example.com" }],
"opened_at": "2025-06-20T14:30:00Z",
"closed_at": null,
"created_at": "2025-06-20T14:30:00Z",
"updated_at": "2025-06-20T14:30:00Z"
}
],
"meta": {
"request_id": "H-pzd9tQM3wYgSCCCFVl",
"total": 1,
"next_cursor": null
},
"error": null
}Approved verifications close regressions
When a verification is approved, the open regressions for the linked finding are closed automatically (status: "closed", closed_at set). Reopening a verification opens a new regression with trigger: "verification_reopened".
Next steps
- Quickstart — Run your first scan and triage a finding
- Remediation Guide — Create tasks, run verifications, configure policies, and generate reports