BETA
Skip to content

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:

SeverityDescription
criticalImmediate threat. Exploitable vulnerabilities that could lead to data breaches, unauthorized access, or service compromise. Address these first.
highSerious risk. Issues that could be exploited with effort or that significantly weaken your posture. Fix promptly.
mediumModerate risk. Issues that violate best practice but are not immediately exploitable. Plan a fix.
lowMinor 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
StatusMeaning
newThe finding has been detected and not yet reviewed. All new findings start here.
triagedA human has reviewed the finding and accepted it as actionable.
in_progressRemediation work is underway (typically tracked by a linked task).
ready_verifyThe fix has been shipped; a verification should run before closing.
resolvedThe fix has been verified. Set automatically when a verification is approved.
dismissedThe 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:

DomainCovers
securityVulnerabilities, misconfigurations, missing headers, injection risks, authentication weaknesses
performanceSlow load times, unoptimized assets, render-blocking resources, excessive payloads
accessibilityWCAG violations, missing alt text, color contrast issues, keyboard navigation gaps
seoIndexing problems, missing meta tags, broken canonical URLs, sitemap issues

Priority and confidence

Each finding ships with two scoring objects you can use to triage:

  • confidence is a 0.0..1.0 float reflecting how confident the scanner is that the finding is real. Treat values below 0.5 as unverified.
  • priority contains four integer scores (impact, effort, risk, score) each in the 0..100 range. score is the composite priority used to order findings — the Findings list is sorted by priority.score descending.

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:

ParameterValuesDescription
severitycritical, high, medium, lowFilter by severity
statusnew, triaged, in_progress, ready_verify, resolved, dismissedFilter by finding status
domainsecurity, performance, accessibility, seoFilter by audit domain
limitinteger (default 25, max 100)Page size
offsetintegerNumber 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/0 when 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 no first_seen / last_seen fields.
  • owner_id — UUID of the assignee, or null if 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:

FieldDescription
statusopen while the regression is active, closed once resolved again.
triggerWhy the regression was opened — e.g. verification_reopened when the source was a failed verification.
severitySeverity at the time of regression.
opened_at / closed_atWhen the regression opened and (eventually) closed.
impacted_assetsSame 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

Built by Krafter Studio