Methodology/ xAPI Profile v1.0
Companion Document Version 1.0 — 2026-03-12

xAPI Profile v1.0

The complete specification of every xAPI statement emitted by Svelto's audit evidence engine. Defines all verbs, context fields, result fields, integrity metadata, and the export document structure delivered to customer SIEMs. Referenced in Methodology §3.1 and §4.2.

Purpose & Design Philosophy

Svelto uses the xAPI (Experience API / Tin Can) statement model as its canonical format for compliance learning evidence. Each meaningful event in the system — a scenario delivered, an answer submitted, a question asked to the chatbot, a scenario approved or rejected by an admin — is recorded as a tamper-evident, RFC 3161-timestamped xAPI statement.

Design constraints that shape this profile:

  • No LRS. Svelto does not export to a Learning Record Store. Statements are stored in Svelto's own database and exported as a signed JSON document delivered directly to the customer's SIEM.
  • Pseudonymization by default. Exported statements carry pseudonymizedActorId, not the learner's real identity. The mapping is held in an isolated audit registry accessible only during an authorized export.
  • Every statement is timestamped at write time with an RFC 3161 token from a trusted timestamp authority (TSA). This makes retroactive modification of the evidence record cryptographically detectable.
  • Control traceability is mandatory. Statements for learning events (experienced, answered) must carry primaryControlId and focusTopicIds. Statements without these fields are rejected at write time.
Auditor's note: The xAPI export document (§7 below) includes a exportIntegrityHash (SHA-256 over all statements) and a wrapping RFC 3161 token covering the entire export. This means the document is self-verifying: any deletion, insertion, or modification of a statement after export breaks the hash and invalidates the timestamp proof.

Statement Anatomy

Every Svelto xAPI statement shares the same outer envelope:

// Persisted statement (as stored in DB and included in exports) { "id": "<uuid-v4>", // statement UUID "verb": "experienced", // XAPIVerb enum value "timestamp": "2026-02-26T09:14:22.000Z", // ISO 8601 UTC, set at write time "roomId": "<uuid>", "taskId": "<uuid>", // omitted for chatbot statements "statementData": { "verb": "experienced", // mirrors outer verb "object": "microlearning:micro_simulation:<taskId>", "result": { /* verb-dependent, see §5 */ }, "context": { /* verb-dependent, see §4 */ } }, "integrityHash": "<sha256-hex>", // SHA-256 of canonical stamp payload "tstToken": "<rfc3161-base64>", // RFC 3161 timestamp token "tsaProviderId": "freetsa", // provider that issued tstToken "tsaProviderUrl": "https://freetsa.org/tsr", "pseudonymizedActorId": "<pseudonym>", // null if actor unregistered "isManuallyDispatched": false // true when the parent task came from manual dispatch }

taskId is omitted on asked statements in the exported document. tsaProviderId and tsaProviderUrl identify the exact TSA that issued tstToken, and isManuallyDispatched distinguishes super-admin manual dispatches from scheduler-driven tasks.

Object URI Patterns

Verb(s) Object pattern Notes
experienced answered microlearning:micro_simulation:{taskId} The micro-simulation task UUID
approved rejected microlearning:task:{taskId} Admin action on a generated task
asked chatbot-question Literal string; no UUID — chatbot interactions are not task-bound

Stamp Payload

The integrityHash and RFC 3161 token are computed over a deterministic canonical payload that includes both the statement envelope and the full statementData (verb, object, result, context). This ensures an auditor can independently verify not just when an event occurred, but what the employee actually saw and answered:

{ "id": "<statement-uuid>", "actorId": "<internal-actor-registry-id or null>", "verb": "experienced", "roomId": "<uuid>", "taskId": "<uuid or null>", "timestamp": "2026-02-26T09:14:22.000Z", "statementData": { /* full verb/object/result/context as stored */ } }

SHA-256 of the above (using stable JSON serialization) is submitted to the TSA. The TSA returns a token that proves this exact payload — including the employee response content — existed at this point in time.


Verb Reference

Five verbs are actively emitted across learner, chatbot, and admin interactions.

experienced Scenario delivered to employee
recordMicrolearningPresented()

Emitted once per employee per broadcast when a micro-simulation is delivered to the chat platform. Records what the employee saw before they responded, including the compliance context used to generate the scenario. Has no result block.

{ "verb": "experienced", "object": "microlearning:micro_simulation:1c6b12e5-3944-4fb7-8b9d-2599f97f07e2", "context": { "riskLevel": "high", "difficultyLevel": "basic", "questionText": "Given the potential sensitivity of customer data, what is the most appropriate action?", "optionCount": 4, "primaryControlId": "A.6.3", "focusTopicIds": ["A.5.34", "A.5.10", "A.5.36"], "mappingRationale": "This scenario teaches the responsible use of AI tools with sensitive data...", "sessionType": "regular", "microlearning": { "contentType": "problem_solving", "conceptsTested": ["AI Tool Usage Policy", "Data Sensitivity"], "deliverySequence": 1, "expectedClassification": "suspicious", "sourceCitations": [ { "citation": "acme-corp-information-security-policy.pdf (p.8-11) [Acceptable Use of AI Tools]" }, { "citation": "acme-corp-information-security-policy.pdf (p.5-6) [Data Classification Rules]" } ] } } }
answered Employee submits a response
recordMicroSimulationCompletion()

Emitted when an employee selects an answer option. Always paired with a prior experienced statement for the same taskId. The reactionTimeInSeconds is computed as the difference between the two statement timestamps. When the session is a remediation simulation, sessionType is "remediation" and remediationTrackingId links this statement to the active remediation cycle.

{ "verb": "answered", "object": "microlearning:micro_simulation:1c6b12e5-3944-4fb7-8b9d-2599f97f07e2", "result": { "success": false, "score": { "scaled": 0, "raw": 0, "min": 0, "max": 100 }, "response": "A", "feedbackGiven": { "type": "immediate", "content": "Incorrect: Disabling chat history does not negate the initial policy violation." }, "detailedScoring": { "criteriaEvaluated": [{ "criterion": "correctness", "addressed": false, "qualityScore": 0 }], "misconceptionsIdentified": ["Inputting sensitive information into unapproved AI tools is prohibited..."], "strengthsObserved": [], "gapsIdentified": ["Disabling chat history does not negate the initial policy violation."] } }, "context": { "riskLevel": "high", "difficultyLevel": "basic", "questionText": "Given the potential sensitivity of customer data, what is the most appropriate action?", "scenarioContext": "Dr. Anya Sharma (AI Research Lead): Hi team. I'm working on a critical analysis...", "allOptionsPresented": ["A", "B", "C", "D"], "reactionTimeInSeconds": 3, "primaryControlId": "A.6.3", "focusTopicIds": ["A.5.34", "A.5.10", "A.5.36"], "mappingRationale": "This scenario teaches the responsible use of AI tools...", "sessionType": "remediation", // "regular" | "remediation" "remediationTrackingId": "a4c3e2f1-...", // present only when sessionType = "remediation" "microlearning": { "contentType": "problem_solving", "conceptsTested": ["AI Tool Usage Policy", "Data Sensitivity"], "deliverySequence": 1, "expectedClassification": "suspicious", "sourceCitations": [ { "citation": "acme-corp-information-security-policy.pdf (p.8-11) [Acceptable Use of AI Tools]" }, { "citation": "acme-corp-information-security-policy.pdf (p.5-6) [Data Classification Rules]" } ] } } }
asked Employee queries the chatbot
recordChatbotQuestion()

Emitted each time an employee sends a message to the compliance chatbot. The question and response are truncated to 500 characters before storage. These statements are not task-bound, so taskId, primaryControlId, and focusTopicIds are omitted.

{ "verb": "asked", "object": "chatbot-question", "result": { "success": true, "response": "<chatbot-response truncated to 500 chars>" // omitted if success=false }, "context": { "questionText": "<employee question truncated to 500 chars>", "sessionType": "regular", "chatbot": { "questionCategory": "policy_clarification", "questionTopic": "Data Retention", "responseProvided": true } } }
approved Admin approves a generated scenario
recordContentApproval()

Emitted when an admin explicitly approves a generated scenario task for delivery. This statement is the Admin Attestation Gate event described in Methodology §4.1 — no scenario reaches learners without a preceding approved statement. The full scenario content is embedded in the statement so that the attestation record is self-contained: an auditor can verify exactly what was approved without platform access.

{ "verb": "approved", "object": "microlearning:task:72987576-fd68-4546-a6cb-410288bffc03", "result": { "success": true }, "context": { "primaryControlId": "A.6.3", "focusTopicIds": ["A.5.34", "A.5.10", "A.5.36"], "mappingRationale": "This scenario teaches the responsible use of AI tools with sensitive data under A.6.3.", "riskLevel": "high", "difficultyLevel": "intermediate", "questionText": "What should you do about Dr. Sharma's request to use a new, unapproved AI tool with sensitive customer data?", "scenarioContext": "Dr. Sharma asks you to input confidential patient records into an external AI summarisation tool that has not been approved by IT Security...", "sessionType": "regular", "microlearning": { "contentType": "scenario_based", "conceptsTested": ["AI Acceptable Use", "PII Handling"], "deliverySequence": 0, "expectedClassification": "suspicious", "sourceCitations": [{ "citation": "Section 3.1 — Acceptable Use of Information Systems" }] } } }
rejected Admin rejects a generated scenario
recordContentRejection()

Emitted when an admin rejects a generated scenario task. The result.response field carries a structured rejection reason (see table below). An optional free-text feedbackGiven.content note may be included. A task with a rejected statement is never delivered to learners.

{ "verb": "rejected", "object": "microlearning:task:72987576-fd68-4546-a6cb-410288bffc03", "result": { "success": false, "response": "control_mapping_wrong", // RejectionReason — see table below "feedbackGiven": { // optional "type": "rejection_note", "content": "Scenario maps to A.8.24 but content is about physical access control." } }, "context": { "primaryControlId": "A.6.3", "focusTopicIds": ["A.8.24"], "mappingRationale": "This scenario teaches cryptography and key management practices under A.8.24.", "riskLevel": "medium", "difficultyLevel": "basic", "questionText": "A colleague asks you to share the encryption key for the backup drive over Slack. What do you do?", "scenarioContext": "Your colleague needs urgent access to an encrypted backup and is asking for the key via chat...", "sessionType": "regular", "microlearning": { "contentType": "scenario_based", "conceptsTested": ["Cryptographic Key Management"], "deliverySequence": 0, "expectedClassification": "suspicious" } } }

Rejection Reason Values (result.response)

ValueMeaning
content_inaccurateScenario contains factually wrong or misleading information
content_off_topicScenario subject matter does not relate to the room's compliance focus
content_too_easyDifficulty level is too low for the target audience
content_too_difficultDifficulty level is too high for the target audience
control_mapping_wrongThe AI assigned the wrong compliance control to the scenario
otherAny other reason — should always be accompanied by a feedbackGiven note

Context Field Reference

The context object fields and their presence per verb:

Field Type Verbs Description
primaryControlId string exp ans appr rej required The primary compliance control this scenario trains (e.g. A.6.3, CC6.1).
focusTopicIds string[] exp ans appr rej required Secondary controls reinforced by the scenario.
mappingRationale string exp ans appr rej required Human-readable explanation of why this scenario maps to the assigned controls. AI-generated at scenario creation time. Embedded in admin statements so the attestation record is self-contained.
difficultyLevel string exp ans appr rej required Scenario difficulty: basic, intermediate, or advanced. Embedded in admin statements so auditors can verify the difficulty of what was attested.
riskLevel string exp ans appr rej required Compliance risk level of the scenario context: low, medium, high, or critical. Embedded in admin statements.
questionText string exp ans ask appr rej required The question posed to the learner. Truncated to 500 chars for chatbot statements. Embedded in admin statements to make the attested scenario fully legible from the audit record alone.
scenarioContext string ans appr rej required The full narrative/scenario text shown to the learner. Embedded in admin statements — the complete scenario text is preserved in the attestation record for auditor review.
correctAnswerText string ans optional Full text of the correct answer option shown for audit readability.
selectedOptionText string ans optional Full text of the option actually selected by the learner.
optionCount number exp optional Number of answer options presented.
allOptionsPresented string[] ans optional IDs of all options shown (e.g. ["A","B","C","D"]).
reactionTimeInSeconds number ans optional Seconds elapsed between the experienced and answered timestamps for the same task.
sessionType string exp ans ask appr rej required "regular" for standard assessments; "remediation" for remediation simulations. Allows auditors to distinguish remediation evidence from the baseline record.
remediationTrackingId string exp ans optional UUID of the active remediation cycle. Present only when sessionType = "remediation". Links this statement to the remediation tracking record, providing a direct audit trail from the triggering failure event to the corrective simulation delivered.
policyReference string ans optional The specific policy clause or section that grounded the scenario generation when organization training materials were used (e.g. "Section 3.1 — Acceptable Use of Information Systems").
microlearning object exp ans appr rej required Nested object — see table below. Embedded in admin statements to preserve the full scenario metadata in the attestation record.
chatbot object ask optional Nested object — see table below.

context.microlearning fields

FieldTypeDescription
contentTypestringrequired problem_solving or scenario_based
conceptsTestedstring[]required Human-readable concepts the scenario exercises
deliverySequencenumberrequired Sequence marker within the room's microlearning lifecycle. Admin curation statements use 0; learner delivery and answer statements use the positive session ordinal (1, 2, ...).
expectedClassificationstringrequired "suspicious" or "legitimate" — the intended correct answer classification
sourceCitationsArray<{citation: string}>Exact citations extracted from the customer's policy documents that grounded this scenario. Present on learner statements and preserved on admin attestation statements when available.

context.chatbot fields

FieldTypeDescription
questionCategorystringoptional AI-extracted category of the question (e.g. policy_clarification)
questionTopicstringoptional AI-extracted topic
responseProvidedbooleanrequired Whether the chatbot successfully returned a response

Result Field Reference

FieldTypeVerbsDescription
success boolean ans ask appr rej Whether the event represents a positive outcome. true for correct answers and approvals; false for incorrect answers, chatbot failures, and rejections.
score.scaled number ans 0.0 (incorrect) or 1.0 (correct)
score.raw number ans 0 or 100
score.min / score.max number ans Always 0 / 100
response string ans ask rej For answered: the selected option ID (e.g. "B"). For asked: chatbot response (500 char max). For rejected: the RejectionReason enum value.
feedbackGiven.type string ans rej "immediate" for answered; "rejection_note" for rejected.
feedbackGiven.content string ans rej For answered: the feedback text shown to the learner. For rejected: admin's free-text note (optional).
detailedScoring object ans Breakdown of evaluation criteria. Contains: criteriaEvaluated[], misconceptionsIdentified[], strengthsObserved[], gapsIdentified[].

Integrity & Timestamping

Each statement is individually stamped at write time. The process is:

  1. A canonical stamp payload is assembled from 7 fields: id, actorId, verb, roomId, taskId, timestamp, and the full statementData object (verb, object, result, context).
  2. The payload is serialized using stable JSON (key-sorted) to guarantee deterministic output.
  3. A SHA-256 hash is computed — stored as integrityHash.
  4. The hash is submitted to a trusted RFC 3161 TSA (DigiCert, Sectigo, or Freetsa.org per Methodology §6).
  5. The TSA returns a signed timestamp token — stored as tstToken.
  6. Both integrityHash and tstToken are stored alongside the statement and included verbatim in every export.
Verification: An auditor can verify any individual statement by: re-assembling the canonical stamp payload (envelope fields + statementData), re-computing SHA-256 and confirming it matches integrityHash, then validating the RFC 3161 token against that hash using any standard TSA verification library. A mismatch on either check indicates the statement — including its response content — was modified after issuance.

Export Document Structure

When an auditor requests an evidence export via the admin API, the system produces a single signed JSON document. The document ID follows the pattern XAPI-EXPORT-{date}-{hash-prefix}.

{ "documentId": "XAPI-EXPORT-2026-02-26-A3F9C2E1", "exportIntegrityHash": "<sha256 over all statements using stable JSON>", "rfc3161Token": "<rfc3161 token covering exportIntegrityHash>", "exportMetadata": { "documentId": "XAPI-EXPORT-2026-02-26-A3F9C2E1", "exportedAt": "2026-02-26T14:00:00.000Z", "framework": "ISO_27001_2022", // or "all" "periodStart": "2026-01-01T00:00:00.000Z", "periodEnd": "2026-01-31T23:59:59.000Z", "statementCount": 1842, "catalogVersionTags": ["1.0.0"], "exportTsaProviderId": "freetsa", "exportTsaProviderUrl": "https://freetsa.org/tsr" }, "statements": [ // array of IXAPIExportStatement — one per recorded audit event in period { "id": "<uuid>", "verb": "answered", "timestamp": "2026-01-15T10:23:44.000Z", "roomId": "<uuid>", "taskId": "<uuid>", // omitted for asked "statementData": { /* full statement data as described above */ }, "integrityHash": "<sha256-hex>", "tstToken": "<rfc3161-base64>", "tsaProviderId": "freetsa", "tsaProviderUrl": "https://freetsa.org/tsr", "pseudonymizedActorId": "USR-7F3A2B", "isManuallyDispatched": false } ] }

The export itself is also RFC 3161-timestamped at generation time — the exportIntegrityHash (SHA-256 over all statements using stable JSON) is submitted to the TSA and the resulting rfc3161Token covers the entire document. Every export generation is recorded in the audit report registry with the generating user's ID, IP address, and timestamp.


Versioning Record

Field Value
Profile Version1.0
Publication Date2026-03-12
Canonical URLdocs.svelto.io/methodology/xapi-profile/v1
Active Verbsexperienced, answered, asked, approved, rejected
LRS ExportNot supported — SIEM delivery only
Actor RepresentationPseudonymized ID in exports; real ID in internal DB only
Integrity MethodSHA-256 + RFC 3161 (per-statement and per-export)
Governing MethodologyMethodology Framework v1.0
StatusPublic — Approved for External Audit Review