SecaniDocumentation

API de validation

Validez les documents OSCAL 1.2.2 JSON via HTTP – sans état, anonyme ou avec une clé API, alimenté par le même moteur que le validateur du navigateur.

L'API de validation Secani OSCAL valide les documents JSON OSCAL 1.2.2 sur HTTP. POSTEZ le document lui-même en tant que corps de la demande – pas d'enveloppe, pas de compte – et recevez un rapport lisible par machine du même moteur qui alimente le validateur de navigateur. Il est conçu pour les machines en vol : tâches CI, scripts d'intégration et autres outils qui produisent ou transforment des documents OSCAL.

Contrat de confidentialité. Votre document est traité de manière transitoire en mémoire sur les serveurs de l'UE (Francfort) et supprimé lors de l'envoi de la réponse. Rien n'est conservé, enregistré ou utilisé pour autre chose que la production de la réponse ; la télémétrie est uniquement globale (type de modèle, taille du compartiment, résultat, durée). Le validateur de navigateur reste entièrement local au navigateur – votre document ne quitte jamais le navigateur.

Démarrage rapide

curl -sS -X POST https://secani.com/api/oscal/v1/validate \
  -H "content-type: application/json" \
  --data-binary @system-security-plan.json

Les artefacts volumineux (les catalogues complets peuvent dépasser la limite de 4 Mo de corps brut) se compressent extrêmement bien – envoyez-les au format gzippé :

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 @-

Réponse

Une validation terminée renvoie toujours HTTP 200 – "valid": false est une validation réussie d'un document invalide. Branche sur le valid champ, pas le code d’état.

{
  "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
  }
}
ChampSignification
validSi le document a été validé sans error résultats. warning les résultats ne suffisent pas false.
modelModèle OSCAL détecté (l'un des huit modèles OSCAL 1.2.2).
oscalVersionLe oscal-version déclaré dans les métadonnées du document ; unknown si absent.
levelNiveau de validation exécuté : schema (par défaut) ou full (voir Niveaux de validation).
completetrue lorsque chaque niveau demandé a été atteint pour un modèle reconnu.
issues[].ruleIdIdentifiant stable de la règle qui a produit la découverte, dérivé du schéma ou sémantique.
issues[].pathRFC 6901 JSON Pointeur dans le document soumis.
issues[].severityerror ou warning; warning est consultatif et ne fait pas valid FAUX.
issueCountNombre total réel de problèmes, même lorsque issues est tronqué.
truncatedtrue lorsque plus de 200 problèmes ont été trouvés et que la liste a été plafonnée.
meta.validatorOSCAL publie la cible des validateurs précompilés (actuellement 1.2.2).
meta.patchesÉcarts documentés par rapport aux schémas de version bruts du NIST.

Erreurs

Les erreurs utilisent les détails du problème RFC 9457 (application/problem+json) avec un format stable lisible par machine code:

Chaque problème comprend également une action resolution et un documentation URL. Voir l'intégralité référence de récupération d'erreur.

StatutCodeSignification
400ERR_INVALID_JSONLe corps n'est pas un JSON bien formé.
400ERR_INVALID_UTF8Le corps de la requête n'est pas UTF-8 valide.
400ERR_UNKNOWN_MODELJSON, mais pas de modèle racine OSCAL reconnaissable.
400ERR_INVALID_CONTENT_ENCODINGContent-Encoding: gzip déclaré mais le corps n'est pas un gzip valide.
400ERR_UNSUPPORTED_PARAMETERUn paramètre de requête comporte une valeur non valide ou non prise en charge (par exemple, une valeur inconnue). rules identifiant).
401ERR_INVALID_API_KEYLa clé API présentée est inconnue ou révoquée.
405ERR_METHOD_NOT_ALLOWEDSeuls les POST (et OPTIONS) sont acceptés.
413ERR_PAYLOAD_TOO_LARGECorps brut de plus de 4 Mo ou corps décompressé de plus de 24 Mo.
415ERR_UNSUPPORTED_MEDIA_TYPEType de contenu autre que application/json, ou un encodage non pris en charge.
429ERR_RATE_LIMITEDLimite de débit dépassée ; voir Retry-After.
500ERR_INTERNALÉchec inattendu ; aucun élément interne n’est divulgué.
503ERR_KEY_SERVICE_UNAVAILABLELa vérification des clés est temporairement indisponible ; voir Retry-After.

Niveaux de validation

Le level Le paramètre de requête contrôle la profondeur de validation. Sans aucun donné, level=schema exécutions – validation simple du schéma JSON, inchangée. level=full engage en outre la couche sémantique : des vérifications de contraintes et de références qui vont au-delà de ce que le schéma JSON seul peut exprimer.

curl -sS -X POST "https://secani.com/api/oscal/v1/validate?level=full" \
  -H "content-type: application/json" \
  --data-binary @catalog.json

UN full une exécution qui atteint réellement la couche sémantique peut renvoyer des résultats avec severity: "warning". warning les conclusions sont consultatives et ne rendent pas un document invalide : elles signalent des modèles douteux mais ne violant pas le schéma (comme un lien interne qui ne pointe vers rien), et valid reste true. Continuez à vous ramifier valid; severity puis sépare les erreurs des indices.

{
  "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"
    }
  }
}

Les règles de désactivation par défaut s'activent individuellement via rules= – une liste d'identifiants de règles séparés par des virgules, valable uniquement à côté level=full. Un identifiant inconnu revient 400 ERR_UNSUPPORTED_PARAMETER nommer l'identifiant incriminé, sans vider le catalogue de règles :

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.json

Chaque full exécution qui atteint les rapports de la couche sémantique meta.semanticRules: le nombre de règles sémantiques actives (count) et un SHA-256 stable sur l'ensemble trié de leurs identifiants (sha256). UN full l'exécution rejetée au niveau de la couche schéma n'atteint jamais la sémantique, elle ne transporte donc aucun meta.semanticRules. Le hachage identifie exactement quel ensemble de règles a été appliqué, donc l'activation d'une règle via rules= le change. Une réponse stockée devient ainsi un enregistrement reproductible de ce qui a été réellement vérifié, même si le catalogue de règles s'agrandit au fil des versions futures.

Limites

  • Corps de la requête : 4 Mo bruts, 24 Mo décompressés (Content-Encoding: gzip est pris en charge et recommandé pour les documents volumineux).
  • Un document par demande.
  • Limites de débit anonymes : 10 requêtes par minute et 300 par jour et par client, révélées via RateLimit-Limit, RateLimit-Remaining, et RateLimit-Reset en-têtes de réponse, avec Retry-After sur 429 réponses. Besoin de plus ? Créez une clé API (voir ci-dessous) ou contactez bonjour@secani.com.

Clés API

Des limites plus élevées et durables sont accompagnées d’une clé API. Vous créez des clés dans les paramètres de l'organisation ; chaque clé est affichée exactement une fois – lors de la création. Envoyez-le comme 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.json

Avec une clé, les limites s'élèvent à 120 requêtes par minute et 10 000 par jour et par clé – appliquées de manière centralisée et indépendamment de toute instance de serveur unique, tandis que les limites anonymes correspondent au meilleur effort par instance. Le niveau anonyme reste : demandes sans Authorization l'en-tête se comporte de manière inchangée. Une clé inconnue ou révoquée revient 401 ERR_INVALID_API_KEY et ne retombe jamais au niveau anonyme.

Paramètres réservés

level et rules ne sont plus réservés – ils sont en direct ; voir Niveaux de validation ci-dessus. Un paramètre conserve une plage de valeurs réservée :

  • oscal-version – épingle la version de spécification et accepte uniquement 1.2.2 aujourd'hui. Toute autre valeur est réservée aux futures versions et retours d'OSCAL ERR_UNSUPPORTED_PARAMETER avec une explication.

OpenAPI

Le contrat canonique lisible par machine est signifié à /openapi.json. Le versionné /api/oscal/v1/openapi.json L'URL reste disponible pour des raisons de compatibilité. CORS est ouvert (*), de sorte que l'API peut être appelée directement à partir d'outils basés sur un navigateur.

Voir aussi : le validateur de navigateur pour une utilisation interactive et le Boîte à outils TypeScript derrière les deux.