Validierungs-API
OSCAL-1.2.2-JSON-Dokumente per HTTP validieren – zustandslos, anonym oder mit API-Schlüssel, mit derselben Engine wie der Browser-Validator.
Die Secani OSCAL Validierungs-API validiert OSCAL-1.2.2-JSON-Dokumente per HTTP. Sende das Dokument selbst als Request-Body per POST – ohne Umschlag, ohne Konto – und erhalte einen maschinenlesbaren Bericht von derselben Engine, die auch den Browser-Validator antreibt. Die API ist für Maschinen im Arbeitsfluss gebaut: CI-Jobs, Integrationsskripte und andere Werkzeuge, die OSCAL-Dokumente erzeugen oder transformieren.
Datenschutz-Zusage. Dein Dokument wird flüchtig im Arbeitsspeicher auf EU-Servern (Frankfurt) verarbeitet und mit dem Senden der Antwort verworfen. Nichts wird gespeichert, protokolliert oder für etwas anderes als die Antwort verwendet; Telemetrie ist ausschließlich aggregiert (Modelltyp, Größenklasse, Ergebnis, Dauer). Der Browser-Validator bleibt vollständig browser-lokal – dort verlässt dein Dokument den Browser nie.
Schnellstart
curl -sS -X POST https://secani.com/api/oscal/v1/validate \
-H "content-type: application/json" \
--data-binary @system-security-plan.jsonGroße Artefakte (vollständige Catalogs können das 4-MB-Limit für unkomprimierte Bodies überschreiten) lassen sich hervorragend komprimieren – sende sie gezippt:
gzip -c catalog.json | curl -sS -X POST https://secani.com/api/oscal/v1/validate \
-H "content-type: application/json" \
-H "content-encoding: gzip" \
--data-binary @-Antwort
Eine abgeschlossene Validierung liefert immer HTTP 200 – "valid": false ist die erfolgreiche Validierung eines ungültigen Dokuments. Verzweige auf dem Feld valid, nicht auf dem Statuscode.
{
"valid": false,
"model": "system-security-plan",
"oscalVersion": "1.2.2",
"level": "schema",
"complete": true,
"issues": [
{
"ruleId": "nist-schema:1.2.2:system-security-plan:required:system-security-plan/metadata/version:required",
"path": "/system-security-plan/metadata/version",
"message": "must have required property 'version'",
"keyword": "required",
"severity": "error"
}
],
"issueCount": 37,
"truncated": false,
"meta": {
"engine": "@secani/oscal",
"validator": "1.2.2",
"schemaSource": "NIST OSCAL v1.2.2 release JSON schemas",
"patches": ["profile-combine-method"],
"durationMs": 84
}
}| Feld | Bedeutung |
|---|---|
valid | Ob das Dokument ohne error-Feststellungen gültig ist. warning-Feststellungen machen es nicht false. |
model | Erkanntes OSCAL-Modell (eines der acht OSCAL-1.2.2-Modelle). |
oscalVersion | Die im Metadaten-Block deklarierte oscal-version; unknown, wenn sie fehlt. |
level | Ausgeführte Validierungsstufe: schema (Standard) oder full (siehe Validierungsstufen). |
complete | true, wenn jede angeforderte Stufe für ein erkanntes Modell vollständig durchlief. |
issues[].ruleId | Stabile ID der Regel, die die Feststellung erzeugt hat, schema-abgeleitet oder semantisch. |
issues[].path | RFC-6901-JSON-Pointer in das eingereichte Dokument. |
issues[].severity | error oder warning; warning ist beratend und macht valid nicht false. |
issueCount | Tatsächliche Gesamtzahl der Feststellungen, auch wenn issues gekürzt ist. |
truncated | true, wenn mehr als 200 Feststellungen gefunden und die Liste gekappt wurde. |
meta.validator | OSCAL-Release, auf das die vorkompilierten Validatoren zielen (aktuell 1.2.2). |
meta.patches | Dokumentierte Abweichungen von den rohen NIST-Release-Schemas. |
Fehler
Fehler verwenden RFC-9457-Problem-Details (application/problem+json) mit einem stabilen maschinenlesbaren code:
Jedes Problem enthält außerdem einen konkreten Hinweis in resolution und eine documentation-URL. Die vollständige Referenz steht unter API-Fehler beheben.
| Status | Code | Bedeutung |
|---|---|---|
| 400 | ERR_INVALID_JSON | Der Body ist kein wohlgeformtes JSON. |
| 400 | ERR_INVALID_UTF8 | Der Body ist kein gültiges UTF-8. |
| 400 | ERR_UNKNOWN_MODEL | JSON, aber kein erkennbares OSCAL-Wurzelmodell. |
| 400 | ERR_INVALID_CONTENT_ENCODING | Content-Encoding: gzip deklariert, aber der Body ist kein gültiges gzip. |
| 400 | ERR_UNSUPPORTED_PARAMETER | Ein Query-Parameter trägt einen ungültigen oder nicht unterstützten Wert (etwa eine unbekannte rules-ID). |
| 401 | ERR_INVALID_API_KEY | Der präsentierte API-Schlüssel ist unbekannt oder widerrufen. |
| 405 | ERR_METHOD_NOT_ALLOWED | Nur POST (und OPTIONS) werden akzeptiert. |
| 413 | ERR_PAYLOAD_TOO_LARGE | Unkomprimierter Body über 4 MB oder dekomprimierter Body über 24 MB. |
| 415 | ERR_UNSUPPORTED_MEDIA_TYPE | Anderer Content-Type als application/json oder ein nicht unterstütztes Encoding. |
| 429 | ERR_RATE_LIMITED | Rate-Limit überschritten; siehe Retry-After. |
| 500 | ERR_INTERNAL | Unerwarteter Fehler; es werden keine Interna offengelegt. |
| 503 | ERR_KEY_SERVICE_UNAVAILABLE | Die Schlüsselprüfung ist vorübergehend nicht erreichbar; siehe Retry-After. |
Validierungsstufen
Der Query-Parameter level steuert die Prüftiefe. Ohne Angabe läuft level=schema – reine JSON-Schema-Validierung, unverändert. level=full schaltet zusätzlich die semantische Schicht dazu: Constraint- und Referenzprüfungen, die über das hinausgehen, was das JSON-Schema allein ausdrücken kann.
curl -sS -X POST "https://secani.com/api/oscal/v1/validate?level=full" \
-H "content-type: application/json" \
--data-binary @catalog.jsonEin full-Lauf, der die semantische Schicht tatsächlich erreicht, kann Feststellungen mit severity: "warning" liefern. warning-Feststellungen sind beratend und machen ein Dokument nicht ungültig: Sie melden fragwürdige, aber nicht schema-verletzende Muster (etwa einen internen Link, der ins Leere zeigt), und valid bleibt true. Verzweige weiterhin auf valid; severity trennt dann Fehler von Hinweisen.
{
"valid": true,
"model": "catalog",
"oscalVersion": "1.2.2",
"level": "full",
"complete": true,
"issues": [
{
"ruleId": "CAT-002.a",
"path": "/catalog/controls/0/links/0/href",
"message": "local catalog link '#missing-part' does not resolve to a control, part, or resource",
"keyword": "resolved-catalog-link",
"severity": "warning"
}
],
"issueCount": 1,
"truncated": false,
"meta": {
"engine": "@secani/oscal",
"validator": "1.2.2",
"schemaSource": "NIST OSCAL v1.2.2 release JSON schemas",
"patches": ["profile-combine-method"],
"durationMs": 112,
"semanticRules": {
"count": 30,
"sha256": "d5e9ef745394fed06db58bcd5999c505cbccc83e460db024b6f3061cb710d213"
}
}
}Standardmäßig deaktivierte Regeln schaltest du einzeln über rules= zu – eine kommagetrennte Liste von Regel-IDs, nur zusammen mit level=full gültig. Eine unbekannte ID liefert 400 ERR_UNSUPPORTED_PARAMETER und nennt die betreffende ID, ohne den Regelkatalog auszuschütten:
curl -sS -X POST "https://secani.com/api/oscal/v1/validate?level=full&rules=PROF-002.a" \
-H "content-type: application/json" \
--data-binary @profile.jsonJeder full-Lauf, der die semantische Schicht erreicht, meldet meta.semanticRules: die Anzahl der aktiven semantischen Regeln (count) und einen stabilen SHA-256 über die sortierte Menge ihrer IDs (sha256). Ein full-Lauf, der bereits an der Schema-Schicht scheitert, erreicht die Semantik nicht und enthält daher kein meta.semanticRules. Der Hash identifiziert exakt, welches Regelwerk angewandt wurde; schaltest du über rules= eine Regel zu, ändert er sich. Eine gespeicherte Antwort wird damit zu einem reproduzierbaren Nachweis darüber, was tatsächlich geprüft wurde, auch wenn der Regelkatalog über künftige Releases wächst.
Limits
- Request-Body: 4 MB unkomprimiert, 24 MB dekomprimiert (
Content-Encoding: gzipwird unterstützt und für große Dokumente empfohlen). - Ein Dokument pro Request.
- Anonyme Rate-Limits: 10 Requests pro Minute und 300 pro Tag je Client, ausgewiesen über die Response-Header
RateLimit-Limit,RateLimit-RemainingundRateLimit-Reset, mitRetry-Afterbei 429-Antworten. Du brauchst mehr? Erstelle einen API-Schlüssel (siehe unten) oder schreib an hello@secani.com.
API-Schlüssel
Höhere, verlässliche Limits gibt es mit einem API-Schlüssel. Schlüssel erstellst du in den Organisationseinstellungen; jeder Schlüssel wird genau einmal angezeigt – direkt beim Erstellen. Gesendet wird er als Authorization: Bearer sk_oscal_…:
curl -sS -X POST https://secani.com/api/oscal/v1/validate \
-H "authorization: Bearer sk_oscal_..." \
-H "content-type: application/json" \
--data-binary @system-security-plan.jsonMit Schlüssel steigen die Limits auf 120 Requests pro Minute und 10.000 pro Tag je Schlüssel – zentral und unabhängig von der einzelnen Server-Instanz durchgesetzt, während die anonymen Limits Best-Effort je Instanz sind. Die anonyme Stufe bleibt bestehen: Requests ohne Authorization-Header verhalten sich unverändert. Ein unbekannter oder widerrufener Schlüssel liefert 401 ERR_INVALID_API_KEY und fällt niemals auf die anonyme Stufe zurück.
Reservierte Parameter
level und rules sind nicht mehr reserviert – sie sind live; siehe Validierungsstufen oben. Es bleibt ein Parameter mit reserviertem Wertebereich:
oscal-version– fixiert die Spezifikationsversion und akzeptiert heute nur1.2.2. Jeder andere Wert ist für künftige OSCAL-Releases reserviert und liefertERR_UNSUPPORTED_PARAMETERmit einer Erklärung.
OpenAPI
Der kanonische maschinenlesbare Vertrag wird unter /openapi.json ausgeliefert. Die versionierte URL /api/oscal/v1/openapi.json bleibt kompatibel erreichbar. CORS ist offen (*), die API lässt sich also direkt aus browserbasierten Werkzeugen aufrufen.
Siehe auch: der Browser-Validator für die interaktive Nutzung und das TypeScript-Toolkit hinter beiden.