Skip to content

API Reference

rimae/scan exposes a RESTful JSON API at /api/. All endpoints use JSON request and response bodies unless otherwise noted. Auto-generated OpenAPI documentation is available at /api/docs (Swagger UI) and /api/redoc (ReDoc).

Authentication

All API endpoints require authentication unless explicitly marked as public. rimae/scan supports two authentication methods:

Bearer JWT Token

Include the access token in the Authorization header:

Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Tokens are issued by the login and OIDC callback endpoints. Access tokens expire after 30 minutes; use the refresh endpoint to obtain a new one.

API Key

Include the API key in the X-API-Key header:

X-API-Key: rvk_a1b2c3d4e5f6...

When both headers are present, Bearer JWT is checked first.


Pagination

All list endpoints return a standard paginated envelope:

{
  "data": [...],
  "total": 142,
  "page": 1,
  "page_size": 50,
  "total_pages": 3
}

Common query parameters:

Parameter Type Default Constraints Description
page int 1 >= 1 Page number (1-based)
page_size int 50 1 -- 500 Items per page
sort string varies endpoint-specific Column to sort by
sort_dir string asc asc or desc Sort direction

Rate Limiting

rimae/scan enforces per-user rate limits backed by Redis for auth endpoints (with an in-process token bucket fallback when Redis is unavailable).

Endpoint Type Limit Window Scope
Auth endpoints (POST /api/auth/login, /api/auth/setup) 10 requests 1 minute Per IP address
Write endpoints (POST, PATCH, PUT, DELETE) Configurable 1 minute Per user
Export endpoints (GET /api/export/*) Configurable 1 minute Per user
Read endpoints (GET, authenticated) Unlimited -- --

When rate limited, the API returns:

HTTP 429 Too Many Requests
Retry-After: 42

{
  "detail": "Rate limit exceeded",
  "retry_after": 42
}

Note: Rate limiting is disabled when DEBUG=true in the configuration.


Error Response Format

All errors use a consistent JSON structure:

{
  "detail": "Resource not found"
}

For validation errors (422):

{
  "detail": "Validation error",
  "errors": [
    {
      "field": "body -> email",
      "message": "value is not a valid email address",
      "type": "value_error"
    }
  ]
}

For rate limit errors (429):

{
  "detail": "Rate limit exceeded",
  "retry_after": 42
}

Standard HTTP status codes:

Code Meaning
200 Success
201 Created
202 Accepted (async task queued)
204 No Content (asset upload success)
400 Bad request
401 Authentication required
403 Insufficient permissions
404 Resource not found
409 Resource already exists
413 Request entity too large
422 Validation error
429 Rate limit exceeded
500 Internal server error
502 Bad gateway (upstream service error, e.g., OIDC provider)
503 Service unavailable (e.g., LDAP server unreachable)

Note: 5xx errors always return "detail": "Internal server error" regardless of the actual cause, to avoid leaking sensitive information.


Health

GET /health

Check service health. Public -- no authentication required.

Response:

{
  "status": "ok",
  "version": "0.1.0",
  "database": "connected",
  "redis": "connected",
  "scheduler_jobs": 8,
  "uptime_seconds": 86432.15
}

Status values: ok, degraded (Redis down), unhealthy (database down).


Auth

GET /api/auth/providers

Auth: None

Returns which authentication methods are currently enabled.

{
  "internal_enabled": true,
  "ldap_enabled": false,
  "oidc_enabled": true,
  "oidc_provider_name": "keycloak.example.com"
}

POST /api/auth/login

Auth: None

Authenticate with username and password.

Request:

{
  "username": "admin",
  "password": "secretpassword"
}

Response (200):

{
  "access_token": "eyJ...",
  "refresh_token": "eyJ...",
  "token_type": "bearer",
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "username": "admin",
    "email": "admin@example.com",
    "role": "admin"
  }
}

curl example:

curl -X POST https://rimae-scan.example.com/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username": "admin", "password": "secretpassword"}'

POST /api/auth/setup

Auth: None (only works when zero users exist)

Create the initial admin user.

Request:

{
  "username": "admin",
  "email": "admin@example.com",
  "password": "strongpassword123"
}

Response (201): Same as login response.

POST /api/auth/refresh

Auth: None (requires valid refresh token in body)

Exchange a refresh token for a new access token.

Request:

{
  "refresh_token": "eyJ..."
}

Response (200):

{
  "access_token": "eyJ...",
  "token_type": "bearer"
}

GET /api/auth/me

Auth: Bearer JWT

Returns the currently authenticated user's info.

Response (200):

{
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "username": "admin",
  "email": "admin@example.com",
  "role": "admin"
}

GET /api/auth/oidc/authorize

Auth: None

Returns the OIDC authorization URL for the frontend redirect.

Response (200):

{
  "authorization_url": "https://keycloak.example.com/realms/corp/protocol/openid-connect/auth?...",
  "state": "random-state-token",
  "nonce": "random-nonce-token"
}

POST /api/auth/oidc/callback

Auth: None

Exchange an OIDC authorization code for rimae/scan tokens.

Request:

{
  "code": "auth-code-from-provider",
  "state": "random-state-token",
  "expected_state": "random-state-token",
  "nonce": "random-nonce-token"
}

Response (200): Same as login response.


Users

All user management endpoints require the admin role.

GET /api/users

List all users (paginated).

Query parameters: page, page_size

Response (200):

{
  "data": [
    {
      "id": "550e8400-...",
      "username": "admin",
      "email": "admin@example.com",
      "role": "admin",
      "auth_provider": "internal",
      "is_active": true,
      "theme_preference": "dark",
      "created_at": "2024-01-15T10:00:00Z",
      "last_login_at": "2024-03-20T08:15:00Z"
    }
  ],
  "total": 5,
  "page": 1,
  "page_size": 50,
  "total_pages": 1
}

POST /api/users

Create a new user.

Request:

{
  "username": "analyst1",
  "email": "analyst1@example.com",
  "password": "securepassword",
  "role": "analyst"
}

Roles: admin, analyst, read_only (default).

Response (201): UserDetail object.

GET /api/users/{user_id}

Get a single user by ID.

PATCH /api/users/{user_id}

Update a user's email, role, or active status.

Request:

{
  "role": "analyst",
  "is_active": true
}

DELETE /api/users/{user_id}

Deactivate a user (soft-delete: sets is_active=false).


Summary / Dashboard

GET /api/summary/

Auth: Required

Returns all KPI counts for the dashboard.

Response (200):

{
  "total_assets": 150,
  "total_vulns": 1234,
  "critical_count": 12,
  "high_count": 89,
  "medium_count": 456,
  "low_count": 677,
  "kev_count": 8,
  "new_24h": 15,
  "new_7d": 67,
  "stale_assets": 3,
  "source_health": [
    {
      "slug": "nvd",
      "name": "NVD",
      "last_crawled_at": "2024-03-20T06:00:00Z",
      "last_crawl_status": "success",
      "enabled": true
    }
  ]
}

GET /api/summary/trend

Auth: Required

Daily vulnerability counts by severity.

Query parameters: days (1 -- 365, default 30)

Response (200):

{
  "days": 30,
  "trend": [
    {
      "date": "2024-03-15",
      "critical": 2,
      "high": 5,
      "medium": 12,
      "low": 8,
      "total": 27
    }
  ]
}

GET /api/summary/top-cves

Auth: Required

Top CVEs by composite score.

Query parameters: limit (1 -- 50, default 10)


CVEs

GET /api/cves/

Auth: Required

List CVEs with filters.

Query parameters: page, page_size, severity, cvss_min, cvss_max, epss_min, epss_max, kev, has_exploit, nvd_status, search, sort, sort_dir

Sortable columns: cve_id, published_at, last_modified_at, cvss_v31_score, cvss_v4_score, epss_score, epss_percentile

GET /api/cves/{cve_id}

Auth: Required

Get full CVE detail with affected asset count.

curl example:

curl -H "Authorization: Bearer $TOKEN" \
  https://rimae-scan.example.com/api/cves/CVE-2024-1234

GET /api/cves/{cve_id}/affected-assets

Auth: Required

List assets affected by a specific CVE (paginated).


Advisories

GET /api/advisories/

Auth: Required

List advisories with filters.

Query parameters: page, page_size, advisory_type, os_version_config_id, severity, date_from, date_to, sort, sort_dir

Sortable columns: advisory_id, published_at, severity, title, advisory_type

GET /api/advisories/{advisory_id}

Auth: Required

Get advisory detail with packages and affected asset count. Accepts either UUID or advisory ID string.


Assets

GET /api/assets

Auth: Required

List all assets with optional filters.

Query parameters: page, page_size, os_distro, os_version, stale, tag, hostname

GET /api/assets/{asset_id}

Auth: Required

Get asset detail with aggregated counts (packages, apps, infra components, Docker images, vulnerabilities).

PATCH /api/assets/{asset_id}

Auth: Required

Update user-editable fields (tags).

Request:

{
  "tags": ["production", "web-tier"]
}

GET /api/assets/{asset_id}/packages

List OS packages on an asset (paginated).

GET /api/assets/{asset_id}/apps

List application instances on an asset.

GET /api/assets/{asset_id}/infra

List infrastructure components on an asset.

GET /api/assets/{asset_id}/docker-images

List Docker images on an asset.

GET /api/assets/{asset_id}/vulns

List vulnerability matches for an asset (paginated, sorted by composite score).

PATCH /api/assets/bulk

Auth: Required

Bulk update risk zone and tags for multiple assets.

Request:

{
  "asset_ids": ["uuid1", "uuid2"],
  "risk_zone": "production",
  "add_tags": ["pci-scope"],
  "remove_tags": ["legacy"]
}

All fields except asset_ids are optional, but at least one update field (risk_zone, add_tags, or remove_tags) must be provided.

Valid risk_zone values: dev (default), staging, production, dmz, internal, restricted

Response (200):

{
  "updated_count": 2
}

Errors:

Code Condition
400 No asset_ids provided
400 Invalid risk_zone value
400 No update fields provided

Vulnerability Matches

GET /api/vuln-matches/

Auth: Required

List vulnerability matches with comprehensive filters.

Query parameters: page, page_size, asset_id, cve_id, status, severity, kev, has_exploit, patch_available, min_score, max_score, sort, sort_dir

Sortable columns: composite_score, cvss_score, epss_score, first_seen_at, last_confirmed_at, resolved_at, package_name, status

curl example:

curl -H "Authorization: Bearer $TOKEN" \
  "https://rimae-scan.example.com/api/vuln-matches/?severity=critical&kev=true&page_size=10"

GET /api/vuln-matches/{match_id}

Auth: Required

Get vulnerability match detail with asset hostname and CVE details inline.

PATCH /api/vuln-matches/{match_id}

Auth: Required

Update vulnerability match status.

Request:

{
  "status": "accepted_risk",
  "status_note": "Risk accepted per CISO approval on 2024-03-20"
}

Valid statuses: open, in_review, accepted_risk, resolved

Note: status_note is required when setting status to accepted_risk.

POST /api/vuln-matches/bulk-status

Auth: Required

Bulk update status for multiple vulnerability matches.

Request:

{
  "match_ids": ["uuid1", "uuid2", "uuid3"],
  "status": "in_review",
  "status_note": "Batch triage 2024-03-20"
}

Constraints: 1 -- 500 match IDs per request.

Response (200):

{
  "updated_count": 3,
  "match_ids": ["uuid1", "uuid2", "uuid3"]
}

Alerts

GET /api/alerts/

Auth: Required

List alerts with optional filters.

Query parameters: page, page_size, acknowledged, severity

POST /api/alerts/

Auth: Required

Create a new alert.

Request:

{
  "alert_type": "custom",
  "title": "Manual alert",
  "message": "Investigation needed",
  "severity": "high"
}

Severity values: critical, high, medium, low, informational

PATCH /api/alerts/{alert_id}/acknowledge

Auth: Required

Mark an alert as acknowledged. Records the acknowledging user and timestamp.


Scan Runs

GET /api/scan-runs/

Auth: Required

List scan run history with filters.

Query parameters: page, page_size, run_type, source_slug, status, date_from, date_to, sort, sort_dir

Sortable columns: started_at, completed_at, status, source_slug, run_type, records_processed

POST /api/scan-runs/trigger/{source_slug}

Auth: Admin

Trigger an on-demand crawl for a specific source.

Response (202):

{
  "status": "accepted",
  "message": "Crawl triggered for nvd"
}

curl example:

curl -X POST -H "Authorization: Bearer $TOKEN" \
  https://rimae-scan.example.com/api/scan-runs/trigger/nvd

GitHub Repositories

GET /api/github/repos

Auth: Required

List GitHub repositories with filters.

Query parameters: page, page_size, sort, sort_dir, ecosystem, has_critical, upstream_status, archived

Sortable columns: repo_name, last_pushed_at, last_scanned_at, language, vuln_count_critical, vuln_count_high, vuln_count_medium, vuln_count_low, dependency_count, scorecard_score

GET /api/github/repos/{repo_id}

Auth: Required

Get full repository detail including dependencies and vulnerability matches.

GET /api/github/repos/{repo_id}/vulns

Auth: Required

List vulnerability matches for a repository (paginated).

POST /api/github/repos/{repo_id}/scan

Auth: Analyst or Admin

Trigger an on-demand scan of a single repository.

POST /api/github/scan-all

Auth: Analyst or Admin

Trigger a full organization scan.


Exports

GET /api/export/{format}

Auth: Required

Export vulnerability data. See Exports for full documentation.

Path parameter: format -- one of csv, json, html, pdf

Query parameters: report_type, asset_id, cve_id, status, severity, kev, has_exploit, patch_available, min_score, max_score

curl example:

curl -H "Authorization: Bearer $TOKEN" \
  "https://rimae-scan.example.com/api/export/csv?severity=critical" \
  -o critical.csv

Configuration: Integrations

GET /api/config/integrations

Auth: Required

Returns all integration settings with secrets masked.

PATCH /api/config/integrations/wazuh

Auth: Admin

Update Wazuh integration settings.

PATCH /api/config/integrations/github

Auth: Admin

Update GitHub integration settings.

PATCH /api/config/integrations/ceph

Auth: Admin

Update Ceph integration settings.

POST /api/config/integrations/wazuh/test

Auth: Required

Test Wazuh API connectivity. Returns success status and response time.

POST /api/config/integrations/github/test

Auth: Required

Test GitHub API connectivity.

POST /api/config/integrations/ceph/test

Auth: Required

Test Ceph Manager API connectivity.


Configuration: Vulnerability Sources

GET /api/config/vuln-sources

Auth: Required

List all vulnerability source configurations (paginated).

Query parameters: page, page_size, category, enabled

GET /api/config/vuln-sources/{config_id}

Auth: Required

Get a single vulnerability source configuration.

PATCH /api/config/vuln-sources/{config_id}

Auth: Admin

Update a vulnerability source (enabled, crawl interval, API key, weight, notes).

POST /api/config/vuln-sources/{config_id}/test

Auth: Required

Test connectivity to the source's fetch URL.

POST /api/config/vuln-sources/{config_id}/crawl-now

Auth: Admin

Trigger an immediate crawl. Returns HTTP 202.


Configuration: OS Versions

GET /api/config/os-versions

Auth: Required

List all OS version configurations (paginated).

POST /api/config/os-versions

Auth: Admin

Create a new OS version configuration.

Request:

{
  "distro": "ubuntu",
  "version": "24.04",
  "codename": "noble",
  "eol_date": "2029-04-25",
  "advisory_feed_url": "https://ubuntu.com/security/notices.rss",
  "advisory_feed_type": "usn",
  "nvd_cpe_string": "cpe:2.3:o:canonical:ubuntu_linux:24.04:*:*:*:*:*:*:*",
  "enabled": true
}

GET /api/config/os-versions/{config_id}

Auth: Required

Get a single OS version configuration.

PATCH /api/config/os-versions/{config_id}

Auth: Admin

Partially update an OS version configuration.

DELETE /api/config/os-versions/{config_id}

Auth: Admin

Soft-disable an OS version (sets enabled=false).

POST /api/config/os-versions/{config_id}/test-feed

Auth: Required

Test reachability of the advisory feed URL.

GET /api/config/os-versions/staged

Auth: Required

List auto-discovered OS versions that are staged for review (disabled).

PATCH /api/config/os-versions/{config_id}/approve

Auth: Admin

Approve a staged auto-discovered OS version (sets enabled=true).

POST /api/config/os-versions/discover

Auth: Admin

Trigger the OS version discovery agent. Returns HTTP 202.

POST /api/config/os-versions/{config_id}/re-run-agent

Auth: Admin

Re-run the onboarding agent for a specific OS version. Returns HTTP 202.


Configuration: Applications

GET /api/config/apps

Auth: Required

List all application configurations (paginated).

Query parameters: page, page_size, category

POST /api/config/apps

Auth: Admin

Create a new application configuration.

GET /api/config/apps/{config_id}

Auth: Required

Get a single application configuration.

PATCH /api/config/apps/{config_id}

Auth: Admin

Partially update an application configuration.

POST /api/config/apps/{config_id}/probe-now

Auth: Admin

Trigger an immediate version probe. Returns HTTP 202.


Configuration: Scoring

GET /api/config/scoring

Auth: Required

Returns all enabled vulnerability sources with their priority weights and a formula preview.

Response (200):

{
  "weights": [
    {"source_slug": "nvd", "priority_weight": 1.0},
    {"source_slug": "epss", "priority_weight": 1.5},
    {"source_slug": "cisa-kev", "priority_weight": 2.0}
  ],
  "formula_preview": "composite = (1.0*nvd + 1.5*epss + 2.0*cisa-kev) / sum(weights)"
}

PATCH /api/config/scoring

Auth: Admin

Bulk update source priority weights.

Request:

[
  {"source_slug": "nvd", "priority_weight": 1.0},
  {"source_slug": "epss", "priority_weight": 2.0}
]

Weight range: 0.0 -- 10.0.

POST /api/config/scoring/reset

Auth: Admin

Reset all source weights to the default (1.0).


Configuration: Retention

GET /api/config/retention

Auth: Required

Returns current data retention settings.

Response (200):

{
  "retention_days": 365,
  "per_table_overrides": {}
}

PATCH /api/config/retention

Auth: Admin

Update retention period and per-table overrides.


Branding

GET /api/branding

Auth: None (public)

Returns branding configuration for the frontend.

PATCH /api/branding

Auth: Admin

Update branding settings.

POST /api/branding/assets/{asset_type}

Auth: Admin

Upload a branding asset. asset_type: logo_light, logo_dark, or favicon.

Logos must be PNG format. Maximum file size: 2 MB.

GET /api/branding/assets/{asset_type}

Auth: None (public)

Serve a stored branding asset. Cached for 1 hour.


System

GET /api/system/status

Auth: Required

Returns system health and infrastructure status.

POST /api/system/force-correlate

Auth: Admin

Trigger a full vulnerability correlation run. Returns HTTP 202.

POST /api/system/force-inventory

Auth: Admin

Trigger a full inventory pull from all integrations. Returns HTTP 202.

PATCH /api/system/maintenance

Auth: Admin

Toggle maintenance mode on/off.

GET /api/system/log-level

Auth: Admin

Returns the current application log level.

Response (200):

{
  "log_level": "info"
}

PUT /api/system/log-level

Auth: Admin

Change the application log level at runtime. No service restart required.

Request body:

{
  "log_level": "debug"
}

Valid values: debug, info, warn, error.

Response (200):

{
  "log_level": "debug",
  "previous": "info"
}

Compliance Reports

GET /api/reports/frameworks

Auth: Required

List supported compliance frameworks with control counts.

GET /api/reports/frameworks/:framework/controls

Auth: Required

List controls for a specific framework. Framework values: iso27001, soc2, pci_dss, nist_csf, cis_controls, hipaa.

GET /api/reports/report-types

Auth: Required

List available report types (full assessment, gap analysis, evidence package, etc.).

POST /api/reports/generate

Auth: Required

Generate a compliance report. Returns HTTP 202 and queues a background task.

Request body:

{
  "title": "Q1 2026 ISO 27001 Assessment",
  "framework": "iso27001",
  "report_type": "full_assessment",
  "format": "pdf"
}

GET /api/reports

Auth: Required

List generated reports. Query parameters: page, page_size, framework, status.

GET /api/reports/:report_id

Auth: Required

Get a report with its control-level sections.

DELETE /api/reports/:report_id

Auth: Admin

Delete a compliance report.


Evidence Tasks

POST /api/evidence-tasks

Auth: Required

Create an evidence task for a compliance control. Returns HTTP 409 if a task already exists for the given framework + control combination.

Request body:

{
  "framework": "iso27001",
  "control_id": "A.8.8",
  "control_name": "Management of technical vulnerabilities",
  "assignee": "security-team",
  "due_date": "2026-06-30"
}

GET /api/evidence-tasks

Auth: Required

List evidence tasks. Query parameters: page, page_size, framework, status.

GET /api/evidence-tasks/:task_id

Auth: Required

Get an evidence task with its attachments.

PATCH /api/evidence-tasks/:task_id

Auth: Required

Update task status, assignee, notes, or due date.

DELETE /api/evidence-tasks/:task_id

Auth: Admin

Delete an evidence task and all its attachments.

POST /api/evidence-tasks/:task_id/attachments

Auth: Required

Upload an evidence file (multipart form, max 50MB).

GET /api/evidence-tasks/:task_id/attachments/:attachment_id/download

Auth: Required

Download an evidence attachment.

DELETE /api/evidence-tasks/:task_id/attachments/:attachment_id

Auth: Required

Delete an evidence attachment.


Audit Log

GET /api/audit

Auth: Analyst or Admin

List audit log entries with filters.

Query parameters: page, page_size, actor, action, target_type, date_from, date_to

Response (200):

{
  "data": [
    {
      "id": "...",
      "actor": "admin",
      "action": "user.create",
      "target_type": "user",
      "target_id": "...",
      "old_value": null,
      "new_value": {"username": "analyst1", "role": "analyst"},
      "created_at": "2024-03-20T08:15:00Z"
    }
  ],
  "total": 250,
  "page": 1,
  "page_size": 50,
  "total_pages": 5
}

Compliance Policies

Upload Policy

POST /api/compliance-policies
Authorization: Bearer <admin-token>
Content-Type: application/json

{
  "framework": "iso27001",
  "policy_name": "Acme Corp Information Security Policy",
  "policy_version": "3.1",
  "effective_date": "2026-01-15",
  "controls": [
    {
      "control_id": "ACME-A.8.8",
      "maps_to": "A.8.8",
      "name": "Critical Vulnerability Remediation SLA",
      "description": "All critical vulnerabilities must be remediated within 7 days.",
      "data_query": "vuln_remediation",
      "pass_criteria": [
        { "metric": "mttr_days", "operator": "<=", "value": 7 },
        { "metric": "sla_breached_count", "operator": "==", "value": 0 }
      ]
    }
  ],
  "exclusions": [
    {
      "control_id": "A.5.26",
      "status": "not_applicable",
      "justification": "Incident response managed by external MSSP"
    }
  ]
}

Responses: - 201 Created -- Policy uploaded and activated - 400 Bad Request -- Validation failure (unknown framework, invalid pass_criteria) - 409 Conflict -- Version is not newer than current active version

List Policies

GET /api/compliance-policies?framework=iso27001&page=1&page_size=20

Returns paginated list of all policy versions (active and inactive).

Get Active Policy

GET /api/compliance-policies/active/:framework

Returns the currently active policy for a framework, including full policy data.

Get Policy Detail

GET /api/compliance-policies/:id

Returns full policy data including controls, exclusions, and pass_criteria.

Deactivate Policy

DELETE /api/compliance-policies/:id
Authorization: Bearer <admin-token>

Deactivates a policy version. Reports generated before deactivation retain their results.


Compliance Control Versions

List Loaded Versions

GET /api/compliance-controls/versions

Returns all factory and patch control versions loaded by the system:

{
  "versions": [
    {
      "id": "uuid",
      "framework": "iso27001",
      "source_type": "factory",
      "version": "1.0.0",
      "revision_date": "2026-01-15",
      "control_count": 16,
      "loaded_at": "2026-04-11T10:00:00Z",
      "loaded_by": "system"
    }
  ],
  "total": 6
}

Upload Compliance Controls

POST /api/compliance-controls/upload
Content-Type: multipart/form-data
Authorization: Bearer <admin-token>

Uploads a tar.gz archive containing signed compliance catalog files. Each .json file must have a corresponding .json.sig Ed25519 signature sidecar. The archive is verified, validated, written to the factory directory, and the framework cache is reloaded.

Request body: file field containing the tar.gz archive (max 10 MB).

Archive structure:

fedramp.json
fedramp.json.sig

Response (200):

{
  "uploaded": [
    {
      "id": "uuid",
      "framework": "fedramp",
      "source_type": "factory",
      "version": "1.0.0",
      "revision_date": "2026-04-01",
      "control_count": 24,
      "loaded_at": "2026-04-11T14:00:00Z",
      "loaded_by": "admin"
    }
  ],
  "total": 1
}

Error responses: - 400 — Missing file, invalid format, missing .sig, signature verification failure, invalid framework JSON - 409 — Uploaded version is not newer than the currently loaded version


Compliance Scopes

Create Scope

POST /api/compliance-scopes
Content-Type: application/json

{
  "name": "Production PCI CDE Q2 2026",
  "description": "All production assets in the PCI cardholder data environment",
  "framework": "pci_dss",
  "included_risk_zones": ["production", "dmz"],
  "included_tags": ["pci-cde"],
  "excluded_control_ids": ["3.4.1"],
  "excluded_control_notes": {
    "3.4.1": "No stored cardholder data - card processing outsourced to Stripe"
  },
  "assessment_period_start": "2026-01-01",
  "assessment_period_end": "2026-06-30"
}

Default included_risk_zones is ["production", "dmz"] if omitted.

List Scopes

GET /api/compliance-scopes?framework=pci_dss&page=1&page_size=20

Get Scope Detail

GET /api/compliance-scopes/:id

Returns scope definition plus live asset_count matching the scope filters.

Update Scope

PATCH /api/compliance-scopes/:id

Delete Scope

DELETE /api/compliance-scopes/:id
Authorization: Bearer <admin-token>

Scoped Report Generation

Pass scope_id and/or policy_id to POST /api/reports/generate:

{
  "title": "PCI DSS Q2 Assessment",
  "framework": "pci_dss",
  "report_type": "full_assessment",
  "scope_id": "uuid-of-scope",
  "policy_id": "uuid-of-policy"
}

When scope_id is provided: - Environment-level N/A exclusions from the scope are applied - Report sections clearly distinguish organizational vs environment exclusions

When policy_id is omitted, the active policy for the framework is auto-detected. When scope_id is omitted, default scope (production + dmz, no exclusions, last 90 days) is used.