Skip to content

Auditor Workbench + MSP Cockpit

Auditor Workbench (/auditor)

POST /api/v1/auditor/bundle with body {period_start, period_end}. Owner / admin / auditor only. TOTP-gated in production (purpose auditor_bundle); no TOTP in dev.

Bundle contents (ZIP):

manifest.json bundle metadata + pack list + key list
verify.py offline Ed25519 verifier (pynacl-based)
signing_keys.json public keys + rotation reasons in period
compliance_summary.md markdown audit report
evidence_packs/<id>.tar.gz each pack from the period (only from
allowlisted storage paths)

Path-traversal guard: evidence_packs.storage_uri MUST start with one of:

  • /var/lib/monsys/ai-evidence-packs/
  • /var/lib/monsys/copilot-evidence-packs/
  • /var/lib/monsys/openai-evidence-packs/

Otherwise the pack is omitted from the bundle (a row with archive_path:"" remains in manifest.json for traceability).

The download URL is one-shot, 24h expiry. The atomic claim sits in the UPDATE:

UPDATE auditor_bundle_tokens
SET downloaded_at = NOW(), downloaded_by = $3
WHERE token = $1 AND tenant_id = $2
AND downloaded_at IS NULL AND expires_at > NOW()
RETURNING file_path

Postgres MVCC + row lock guarantees that two concurrent requests do not both receive RETURNING.

Offline verify

Each recipient runs python3 verify.py (pynacl) inside the unpacked bundle. No network, no monsys credentials needed — verifies every pack’s signature against the bundled signing_keys.json. Output:

pack 1234: OK
pack 1235: BAD SIGNATURE
=== 12 OK, 1 BAD ===

Exit code 0 = all OK, 1 = at least one pack fails.

MSP Cockpit (/msp/cockpit)

GET /api/v1/msp/overview. Strictly fenced: role = msp_operator OR is_superadmin = true. A normal owner/admin user gets 403 — this endpoint walks every tenant in the platform.

Per tenant:

  • name + plan
  • current Trust Score + Δ7d
  • open critical+warning alerts

  • failing compliance evidence rows

  • last login activity

Default sort = urgency composite:

urgency = open_alerts*5 + failing_controls
+ (-Δ7d if Δ7d < 0)
+ 0.5 * (60 - score) if score < 60

Per-column sort is available from the dashboard (urgency / name / score).

New roles

Migration 064 extends the users.role CHECK with:

RoleAccess
auditorread-only + bundle generate/download (TOTP-gated in production)
msp_operatorcross-tenant via /api/v1/msp/overview

Existing roles (analyst, admin, owner) unchanged.