learnlog: A Verifiable Event Log Format for Learning Software
draft-srivastava-learnlog-01
This document is an Internet-Draft (I-D).
Anyone may submit an I-D to the IETF.
This I-D is not endorsed by the IETF and has no formal standing in the
IETF standards process.
| Document | Type | Active Internet-Draft (individual) | |
|---|---|---|---|
| Author | Kumar Srivastava | ||
| Last updated | 2026-10-12 | ||
| RFC stream | (None) | ||
| Intended RFC status | (None) | ||
| Formats | |||
| Stream | Stream state | (No stream defined) | |
| Consensus boilerplate | Unknown | ||
| RFC Editor Note | (None) | ||
| IESG | IESG state | I-D Exists | |
| Telechat date | (None) | ||
| Responsible AD | (None) | ||
| Send notices to | (None) |
draft-srivastava-learnlog-01
Network Working Group K. Srivastava
Internet-Draft Quantum Learning Machines
Intended status: Standards Track 11 October 2026
Expires: 14 April 2027
learnlog: A Verifiable Event Log Format for Learning Software
draft-srivastava-learnlog-01
Abstract
This document defines learnlog, a log format for learning software.
A record holds typed events that describe what a learner did and what
other parties, human or software, did in response. As AI
participates in learning and assessment, these records can preserve
the assistance and producing instruments needed to interpret a
performance. The format does not establish independent learning or
the effectiveness of an intervention. Entries are chained by hash,
and a producer can sign the chain. A reader who trusts the signing
key can then detect changes to the entries under a signed head that
were made without that key. Some changes remain undetectable, and
the security considerations list them. An event can be redacted, and
the rest of the record still verifies. The format defines files,
records, entries, events, and registries for event schemas. Subject-
area event schemas and judgments about the applicability of research
are out of scope.
Note to Readers
This note is to be removed before publishing as an RFC.
This individual Internet-Draft is a proposal for discussion. This
revision adds motivation and non-normative guidance for recording
assistance in education with AI. It makes no changes to the wire
format, integrity rules, or test vectors of revision -00. Appendix C
lists the changes. Appendix D lists open questions, and Appendix B
describes implementation limits.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at https://datatracker.ietf.org/drafts/current/.
Srivastava Expires 14 April 2027 [Page 1]
Internet-Draft learnlog October 2026
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on 14 April 2027.
Copyright Notice
Copyright (c) 2026 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents (https://trustee.ietf.org/
license-info) in effect on the date of publication of this document.
Please review these documents carefully, as they describe your rights
and restrictions with respect to this document. Code Components
extracted from this document must include Revised BSD License text as
described in Section 4.e of the Trust Legal Provisions and are
provided without warranty as described in the Revised BSD License.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
1.1. Scope . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2. Conventions and Terminology . . . . . . . . . . . . . . . 6
2. Design Overview . . . . . . . . . . . . . . . . . . . . . . . 6
3. Log Files . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.1. Contained Files . . . . . . . . . . . . . . . . . . . . . 8
3.2. Sequential Files . . . . . . . . . . . . . . . . . . . . 8
3.3. File Schema URIs . . . . . . . . . . . . . . . . . . . . 9
4. Records . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4.1. Record Header . . . . . . . . . . . . . . . . . . . . . . 10
4.2. Entries . . . . . . . . . . . . . . . . . . . . . . . . . 12
4.3. Truncation . . . . . . . . . . . . . . . . . . . . . . . 13
5. Events . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.1. Parties . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2. Activities . . . . . . . . . . . . . . . . . . . . . . . 16
5.3. Instruments . . . . . . . . . . . . . . . . . . . . . . . 16
5.4. Event Names and Event Schemas . . . . . . . . . . . . . . 18
5.5. Defining and Extending Event Types . . . . . . . . . . . 18
5.6. Guidance for Schema Designers . . . . . . . . . . . . . . 18
5.7. Companion Profiles for AI Use . . . . . . . . . . . . . . 19
6. Generic Event Schemas . . . . . . . . . . . . . . . . . . . . 20
6.1. The consent Namespace . . . . . . . . . . . . . . . . . . 20
6.2. The assist Namespace . . . . . . . . . . . . . . . . . . 21
6.2.1. Hypothetical AI Assistance Example . . . . . . . . . 23
6.3. The dialog Namespace . . . . . . . . . . . . . . . . . . 24
Srivastava Expires 14 April 2027 [Page 2]
Internet-Draft learnlog October 2026
7. Integrity . . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.1. Canonical Form . . . . . . . . . . . . . . . . . . . . . 25
7.2. Hashes . . . . . . . . . . . . . . . . . . . . . . . . . 25
7.3. Redaction . . . . . . . . . . . . . . . . . . . . . . . . 26
7.4. Signed Heads . . . . . . . . . . . . . . . . . . . . . . 27
7.5. Verification . . . . . . . . . . . . . . . . . . . . . . 28
8. Serialization . . . . . . . . . . . . . . . . . . . . . . . . 31
8.1. JSON . . . . . . . . . . . . . . . . . . . . . . . . . . 31
8.2. JSON Text Sequences . . . . . . . . . . . . . . . . . . . 32
8.3. Other Serializations . . . . . . . . . . . . . . . . . . 32
9. Relationship to Existing Work . . . . . . . . . . . . . . . . 32
10. Security Considerations . . . . . . . . . . . . . . . . . . . 33
10.1. What Verification Shows . . . . . . . . . . . . . . . . 33
10.2. Removal of Recent Entries . . . . . . . . . . . . . . . 34
10.3. Redaction and Truncation by a Holder . . . . . . . . . . 34
10.4. Rewriting by the Producer . . . . . . . . . . . . . . . 34
10.5. Trusted Keys . . . . . . . . . . . . . . . . . . . . . . 34
10.6. Where the Producer Runs . . . . . . . . . . . . . . . . 34
10.7. Guessing Redacted Events . . . . . . . . . . . . . . . . 35
10.8. Meaning of Event Names . . . . . . . . . . . . . . . . . 35
10.9. Hash Algorithms . . . . . . . . . . . . . . . . . . . . 35
10.10. Canonical Form . . . . . . . . . . . . . . . . . . . . . 35
10.11. Untrusted Input . . . . . . . . . . . . . . . . . . . . 36
11. Privacy Considerations . . . . . . . . . . . . . . . . . . . 36
11.1. Identifiers . . . . . . . . . . . . . . . . . . . . . . 36
11.2. People Other Than the Subject . . . . . . . . . . . . . 36
11.3. Data Minimization . . . . . . . . . . . . . . . . . . . 36
11.4. Limits of Redaction . . . . . . . . . . . . . . . . . . 36
11.5. Correlation and Identification . . . . . . . . . . . . . 37
11.6. Signing Keys . . . . . . . . . . . . . . . . . . . . . . 37
11.7. Storage and Transfer . . . . . . . . . . . . . . . . . . 37
11.8. Children . . . . . . . . . . . . . . . . . . . . . . . . 37
12. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 37
12.1. URN Sub-namespace . . . . . . . . . . . . . . . . . . . 37
12.2. File Schema URIs . . . . . . . . . . . . . . . . . . . . 38
12.3. Event Schema URIs . . . . . . . . . . . . . . . . . . . 38
12.4. Media Types . . . . . . . . . . . . . . . . . . . . . . 39
12.4.1. application/learnlog+json . . . . . . . . . . . . . 39
12.4.2. application/learnlog+json-seq . . . . . . . . . . . 39
13. References . . . . . . . . . . . . . . . . . . . . . . . . . 40
13.1. Normative References . . . . . . . . . . . . . . . . . . 40
13.2. Informative References . . . . . . . . . . . . . . . . . 42
Appendix A. Example . . . . . . . . . . . . . . . . . . . . . . 43
A.1. An Example Event Schema . . . . . . . . . . . . . . . . . 43
A.2. A Complete File . . . . . . . . . . . . . . . . . . . . . 44
A.3. Intermediate Values . . . . . . . . . . . . . . . . . . . 50
A.4. The Signed Head . . . . . . . . . . . . . . . . . . . . . 51
A.5. Redaction and Truncation . . . . . . . . . . . . . . . . 52
Srivastava Expires 14 April 2027 [Page 3]
Internet-Draft learnlog October 2026
A.6. Canonical Form Check . . . . . . . . . . . . . . . . . . 53
Appendix B. Implementation Status . . . . . . . . . . . . . . . 54
Appendix C. Changes in Revision -01 . . . . . . . . . . . . . . 55
Appendix D. Open Issues . . . . . . . . . . . . . . . . . . . . 55
Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 57
1. Introduction
This document defines learnlog, a log format for learning software.
The format has two aims. The first is to record actions that have
meaning in the subject being learned, as distinct from interface
activity such as clicks and page views. The second is to let a
reader check a record for changes, within the limits that Section 10
states. Both aims cover the help that a learner receives, whether
from a teacher, a tutoring system, or an AI assistant.
Education software that includes AI needs records that distinguish
the learner's observable actions from assistance supplied by another
party. A submitted explanation alone does not state whether the
learner composed it, responded to a prompt about an approach, or
received an explanation from software. These different histories
matter when researchers, educators, or assessment designers interpret
a performance. Recording them at the time of use makes later
inspection possible; a log cannot reconstruct assistance that its
producer did not observe.
The prospective purpose is to support interpretable evidence from
future learning activities and studies. The existing event members
can identify the actor, task, session, and producing instrument,
while the assistance events preserve the help the producer observed.
A deployment may also need a companion profile that describes the
activity stage, applicable permission, and observation boundaries
(Section 5.7). Neither an intact chain nor such a profile
establishes a learning effect, independent performance, or the
validity of applying a study to a different context.
The format has the following properties:
* Events are typed. An event schema defines the event types of one
area, such as a prediction committed in a simulation
(Section 5.4).
* Every event can state who acted and toward whom. A request for
help and a scaffold given in reply are events of their own,
whether the helper is a person or a program (Section 5.1,
Section 6.2).
Srivastava Expires 14 April 2027 [Page 4]
Internet-Draft learnlog October 2026
* Entries are chained by hash, and a producer can sign the latest
hash. A reader who trusts the signing key can then detect a
change to the signed entries that was made without that key
(Section 7). Section 10 states the limits.
* An event can be redacted without breaking the chain (Section 7.3).
* Records are kept in files. A record can be written, and its
hashes checked, without a server.
The structure of files, records, and event schemas follows qlog
[QLOG], which defines structured logging for network protocols. This
document adds integrity rules and the members that a record of
learning needs.
1.1. Scope
This document defines:
* the structure of files, records, entries, and events (Section 3
through Section 5);
* event schemas for consent, assistance, and dialog, which are not
tied to one subject area (Section 6);
* the canonical form, the hashes, redaction, signed heads, and
verification (Section 7);
* two JSON serializations (Section 8);
* registries for file schemas and event schemas (Section 12).
The following are out of scope:
* Event schemas for subject areas. Other documents can define them.
* Transport and storage interfaces.
* Estimates of what a learner knows, such as scores or mastery
values. A record states what the producer recorded. This
document leaves conclusions drawn from a record to other formats.
* Distribution of the keys that verify signed heads.
* The legal basis for collecting data about learners.
Srivastava Expires 14 April 2027 [Page 5]
Internet-Draft learnlog October 2026
* Decisions about whether an intervention or research finding
applies in a new setting. Such decisions can cite records but are
not event facts or core verification results.
1.2. Conventions and Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this document are to be interpreted as described in BCP
14 [RFC2119] [RFC8174] when, and only when, they appear in all
capitals, as shown here.
Data structures are defined in the Concise Data Definition Language
(CDDL) [RFC8610]. Examples are in JSON [RFC8259]. Some figures wrap
long lines as described in [RFC8792].
This document uses the following terms:
Learner: A person whose learning activity is recorded.
Subject: The learner that a record is about.
Producer: The software that writes a record.
Holder: A party that stores a record or passes it on. The producer
is the first holder.
Verifier: Software that checks a record against this document.
Record: A header and the entries about one subject, written by one
producer. A record forms one hash chain.
Entry: One element of a record. An entry carries one event and the
hashes that bind it into the chain.
Event: A typed description of one action.
Event schema: A definition of a namespace of event types.
Head: A statement that names the latest entry of a record at some
moment (Section 7.4).
2. Design Overview
A log file holds one or more records. A record holds a header and a
sequence of entries. Each entry holds one event.
Srivastava Expires 14 April 2027 [Page 6]
Internet-Draft learnlog October 2026
log file
+-- record
+-- header what the record is about
+-- entry 1 one event and its hashes
+-- entry 2
+-- ...
+-- signed heads signed statements of the latest entry
Figure 1: Structure of a log file
Each entry holds the hash of its event and the hash of the entry
before it. The first entry holds the hash of the header, and every
entry hash covers that hash as well. A change to the header or to an
earlier entry therefore changes every later entry hash. A producer
can sign a statement of the latest entry hash, which gives a verifier
a fixed point to check against.
+--------+ +---------+ +---------+ +---------+
| header |<------| entry 1 |<------| entry 2 |<------| entry 3 |
+--------+ prev +---------+ prev +---------+ prev +---------+
hash | hash | hash |
event hash event hash event hash
| | |
event 1 event 2 (redacted)
Figure 2: The hash chain of a record
An entry commits to the hash of its event. The event itself can be
removed later, and the chain still verifies (Section 7.3).
Event types live in namespaces that event schemas define. This
document defines schemas for three namespaces that are not tied to
one subject area. Other schemas are identified by URI.
3. Log Files
A log file takes one of two forms. A contained file holds one or
more records (Section 3.1). A sequential file holds one record and
grows by appending (Section 3.2). Both forms hold the members of the
log-file group, as in Section 3 of [QLOG].
Srivastava Expires 14 April 2027 [Page 7]
Internet-Draft learnlog October 2026
LearnlogFile = {
log-file,
records: [+ Record]
}
log-file = (
file_schema: text,
serialization_format: text,
? title: text,
? description: text
)
Figure 3: LearnlogFile and the members common to all log files
file_schema: A URI [RFC3986] that identifies the file schema
(Section 3.3).
serialization_format: The media type of the serialization
(Section 8).
title, description: Free text about the file. These members SHOULD
NOT hold information about a learner.
No hash covers these members. A producer SHOULD write file_schema
and serialization_format within the first 256 octets of a file, as
Section 3 of [QLOG] also asks, so that a tool can identify the file
from its start.
The CDDL in this document has two root rules, LearnlogFile and
LearnlogFileSeq. A third rule, SeqItem, describes each later element
of a sequential file.
3.1. Contained Files
A LearnlogFile is one JSON text that holds one or more records. It
suits export and exchange. Its file schema URI is
urn:ietf:params:learnlog:file:contained.
The records in a file are verified one at a time. They can come from
different producers and describe different subjects.
3.2. Sequential Files
A LearnlogFileSeq holds one record and grows by appending. It suits
a log that is written while the learner works. Its file schema URI
is urn:ietf:params:learnlog:file:sequential.
Srivastava Expires 14 April 2027 [Page 8]
Internet-Draft learnlog October 2026
LearnlogFileSeq = {
log-file,
record: RecordStart
}
; every element after the first
SeqItem = Entry / SignedHead
Figure 4: LearnlogFileSeq definition
The first element of a sequential file is the LearnlogFileSeq object.
Every later element is a SeqItem. An element with a seq member is an
Entry. Any other element with a head member is a SignedHead.
Entries appear in order of seq. A producer writes a SignedHead after
the entry that it names, and a reader accepts one at any position.
The Entry elements, in file order, are the entries of the record, and
the SignedHead elements are its signed heads. In a sequential file,
event_schemas lists the schemas known when the file is started.
3.3. File Schema URIs
A registered file schema uses a URN of the form
urn:ietf:params:learnlog:file:<identifier> (Section 12.2). Any other
file schema uses a URI that its definer controls and MUST NOT use
that URN form. Such a URI is not registered.
4. Records
A record holds a header and the entries about one subject, written by
one producer.
record-start = (
header: RecordHeader,
event_schemas: [+ text],
? truncated: Truncation
)
RecordStart = { record-start }
Record = {
record-start,
entries: [* Entry],
? signed_heads: [+ SignedHead]
}
Figure 5: Record definition
Srivastava Expires 14 April 2027 [Page 9]
Internet-Draft learnlog October 2026
header: The record header (Section 4.1).
event_schemas: The URIs of the event schemas used in the record
(Section 5.4). As in Section 8 of [QLOG], the list is a hint to
tools about the event namespaces in the record. No hash covers it
(Section 10.8), and it can grow with the record. A record MAY
hold events from schemas that are not listed.
truncated: Present when the oldest entries were removed
(Section 4.3).
entries: The entries, in order of seq (Section 4.2).
signed_heads: Signatures by the producer over heads of this record
(Section 7.4).
The CDDL in this document defines what a producer writes. A reader
MUST ignore a member that it does not recognize, wherever the member
appears. A hash or a signature covers such a member only in a
header, an event, or a head. A producer SHOULD NOT add members
anywhere else.
4.1. Record Header
The header states what a record is about and is fixed when the record
is created.
Srivastava Expires 14 April 2027 [Page 10]
Internet-Draft learnlog October 2026
RecordHeader = {
record_id: text,
subject: text,
hash_alg: HashAlg,
created: Timestamp,
? producer: Producer,
* text => any
}
Producer = {
name: text,
? version: text,
* text => any
}
HashAlg = "sha-256" / text
; lowercase hexadecimal
HashValue = text .regexp "([0-9a-f][0-9a-f])+"
; RFC 3339, UTC only
Timestamp = text .regexp
"[0-9]{4}(-[0-9]{2}){2}T[0-9]{2}(:[0-9]{2}){2}([.][0-9]{1,9})?Z"
Figure 6: RecordHeader definition
record_id: An identifier for the record, unique among the records of
the producer. A version 4 UUID [RFC9562] is RECOMMENDED.
subject: A pseudonymous identifier for the learner. Section 11.1
gives the requirements.
hash_alg: The hash algorithm used throughout the record. The value
is a name from the IANA "Named Information Hash Algorithm
Registry" [RFC6920]. That registry gives the output length of
each algorithm, and the length MUST be at least 256 bits.
Implementations MUST support sha-256 [FIPS180].
created: The time the record was created.
producer: The name and version of the software that writes the
record.
A header MAY hold other members. The record hash (Section 7.2)
covers every member, so a change to the header changes the record
hash and every entry hash.
Srivastava Expires 14 April 2027 [Page 11]
Internet-Draft learnlog October 2026
A Timestamp is a date and time in the format of [RFC3339], in UTC,
with an uppercase T and the suffix Z. The pattern in Figure 6 admits
some impossible values, such as month 13. A Timestamp MUST also be a
valid date and time. The second 60 is valid only in the time
23:59:60. A HashValue is the whole output of the hash named by
hash_alg, written as two lowercase hexadecimal digits for each octet.
4.2. Entries
Entry = {
seq: Seq,
time: Timestamp,
event_hash: HashValue,
prev_hash: HashValue,
entry_hash: HashValue,
( event: Event // redacted: true )
}
; a position in a record, from 1 to (2^53)-1
Seq = 1..9007199254740991
Figure 7: Entry definition
seq: The position of the entry in the record. The first entry of a
record has seq 1. Each later entry has the seq of its predecessor
plus 1. A Seq is an integer of at least 1 and below 2^53.
time: The time the event occurred, as observed by the producer.
Order within a record is given by seq. Values of time SHOULD NOT
decrease from one entry to the next.
event_hash: The hash of the event (Section 7.2).
prev_hash: The hash that links the entry to what precedes it
(Section 7.2).
entry_hash: The hash of the entry (Section 7.2).
event: The event (Section 5).
redacted: Present with the value true, in place of event, when the
event was removed (Section 7.3).
An entry holds exactly one of event and redacted.
Srivastava Expires 14 April 2027 [Page 12]
Internet-Draft learnlog October 2026
A producer appends an entry when the event occurs, or as soon after
as it can. A written entry keeps its position and its hashes. This
document permits two changes to the entries of a record. Redaction
removes an event, and a party that kept the event can put it back
(Section 7.3). Truncation removes the oldest entries (Section 4.3).
4.3. Truncation
A holder can remove the oldest entries of a record, for example to
meet a retention limit. The truncated member then holds the seq and
entry_hash of the last entry that was removed.
Truncation = {
seq: Seq,
entry_hash: HashValue
}
Figure 8: Truncation definition
The first remaining entry has a seq of truncated.seq plus 1 and a
prev_hash equal to truncated.entry_hash.
A record can be truncated more than once. The truncated member then
names the last entry removed overall. A holder can remove every
entry, which leaves entries empty.
A signed head that names an entry before truncated.seq can no longer
be compared with an entry, and a holder MAY remove it. A holder
SHOULD keep every other signed head.
A verifier cannot check the entries that were removed. A change to
the header still shows in the remaining entries, because every entry
hash covers the record hash (Section 7.2). Section 10.1 states what
such a check establishes.
5. Events
An event describes one action: something the learner did, or
something another party did that bears on the learner's work.
Srivastava Expires 14 April 2027 [Page 13]
Internet-Draft learnlog October 2026
Event = $Event
event-type<Name, Data> = {
name: Name,
salt: Salt,
data: Data,
? actor: Party,
? to: Party,
? session: text,
? activity: Activity,
? instrument: Instrument,
* text => any
}
; 22 or more characters of the base64url alphabet
Salt = text .regexp "[A-Za-z0-9_-]{22,}"
Figure 9: Event definition
The event-type rule is a CDDL generic. An event type is an instance
of the rule that fixes the name and the type of data. The $Event
socket collects the instances (Section 5.5).
name: The event type, written as a namespace, a colon, and a type
identifier (Section 5.4).
salt: A random value that keeps a removed event from being guessed
from its hash (Section 7.3). For each event, a producer MUST
generate at least 16 octets from a cryptographically secure source
and encode them in base64url without padding [RFC4648].
data: An object with the members that the event type defines.
actor: The party that performed the action (Section 5.1). When
absent, the actor is the subject.
to: The party the action was directed at (Section 5.1). When
absent, an action by another party was directed at the subject.
An action by the subject then has no stated addressee.
session: An identifier that groups the events of one continuous
period of use.
activity: The task in which the action took place (Section 5.2).
instrument: How the data of the event was produced (Section 5.3).
Srivastava Expires 14 April 2027 [Page 14]
Internet-Draft learnlog October 2026
An event MAY hold other members. The event hash covers every member
of the event.
5.1. Parties
A Party describes who acted or who was addressed.
Party = {
role: Role,
? kind: "human" / "software",
? id: text,
* text => any
}
Role = "learner" / "instructor" / "assistant" / "peer" /
"guardian" / "system" / text
Figure 10: Party definition
The role member has one of these values:
learner: A person who is learning. A learner without an id is the
subject of the record.
instructor: A party responsible for teaching the subject in this
activity.
assistant: A party that responds to requests and has no teaching
responsibility.
peer: Another learner.
guardian: A person who acts for the subject, such as a parent.
system: The producer acting in none of the roles above, for example
a simulation that reveals an outcome.
Other values MAY be used.
The kind member states whether the party is a person (human) or a
program (software). When the member is absent, a learner, peer, or
guardian is a person, and a system is a program. The member is
REQUIRED with any other role. The CDDL in Figure 10 does not express
this rule.
The id member identifies a party other than the subject. For a
person, the value is pseudonymous and follows Section 11.1. For a
program, the value names the program.
Srivastava Expires 14 April 2027 [Page 15]
Internet-Draft learnlog October 2026
Table 1 shows how some common parties are described.
+====================================+============+==========+
| Party | role | kind |
+====================================+============+==========+
| A teacher working with the learner | instructor | human |
+------------------------------------+------------+----------+
| An intelligent tutoring system | instructor | software |
+------------------------------------+------------+----------+
| A general AI chat assistant | assistant | software |
+------------------------------------+------------+----------+
| A classmate | peer | human |
+------------------------------------+------------+----------+
Table 1: Examples of parties
When the actor is a program, the instrument member (Section 5.3)
describes the model or the version that produced the data.
5.2. Activities
The meaning of an event can depend on the task it belongs to. A
producer SHOULD include activity in every event that belongs to a
task.
Activity = {
id: text,
? version: text,
? variant: text,
* text => any
}
Figure 11: Activity definition
id: An identifier for the task, such as a URI.
version: The version of the task content.
variant: The form of the task that this learner received, when forms
differ. A random seed is one example.
5.3. Instruments
The instrument member states how the data of an event came to be. A
reader needs it to weigh an event that a model wrote or judged.
Srivastava Expires 14 April 2027 [Page 16]
Internet-Draft learnlog October 2026
Instrument = {
source: "deterministic" / "model" / "human" / text,
? model: text,
? config_hash: HashValue,
? parameters: { * text => any },
? validated: bool,
* text => any
}
Figure 12: Instrument definition
The source member has one of these values:
deterministic: Fixed program logic produced the data.
model: A statistical or generative model produced the data. A hint
written by a language model and a transcript of speech are
examples.
human: A person entered or judged the data.
Other values MAY be used. The remaining members are:
model: The identifier and version of the model or program.
config_hash: The hash of the configuration that governed the output,
such as a prompt (Section 7.2). The producer chooses the octets
that are hashed and needs to keep them for the hash to be of use.
parameters: Settings that affect the output, such as a sampling
temperature.
validated: True when a deterministic check accepted the output of a
model before it was used.
An event without an instrument member makes no statement about how
its data was produced.
The producer.version member identifies recording software;
instrument.model identifies the model or program that produced the
event data. Keeping these identifiers distinct lets a reader inspect
changes in either. A configuration hash identifies retained octets;
it does not make those octets available, show that the named
configuration was executed, or make a probabilistic output
reproducible. The validated member reports a deterministic
acceptance check, not empirical validation of educational
effectiveness or a learner's knowledge.
Srivastava Expires 14 April 2027 [Page 17]
Internet-Draft learnlog October 2026
5.4. Event Names and Event Schemas
Event types are grouped in namespaces, as in Section 8 of [QLOG]. An
event schema is a document that defines a namespace or extends one.
The name of an event is the namespace identifier, a colon, and the
type identifier. Each identifier starts with a letter from a to z
and continues with such letters, digits, or underscores.
Each event schema has a URI. A registered schema uses the form
urn:ietf:params:learnlog:events:<namespace> (Section 12.3). A schema
that extends a namespace adds a fragment identifier to the URI of
that namespace. Any other schema uses a URI that its definer
controls and MUST NOT use that URN form. A URI that contains a
domain name SHOULD include a month and year in the form mmyyyy.
Section 8.1 of [QLOG] gives the same rule, to avoid problems when a
domain name changes ownership.
A record can hold an event whose schema a tool does not know. Such
an event does not match the CDDL that the tool has. Verification
(Section 7.5) checks its hashes like any others and does not depend
on its schema.
5.5. Defining and Extending Event Types
An event schema adds each of its event types to the $Event socket.
The lines below, taken from the example schema in Appendix A.1,
define the event type sim:prediction_committed.
$Event /= event-type<"sim:prediction_committed",
SimPredictionCommitted>
Each data type in this document ends with a group socket named after
the type, such as $$dialog-message-extension. A later schema can add
members to the data type through that socket.
5.6. Guidance for Schema Designers
The points below apply to any event schema.
* Define events for actions that have meaning in the subject area,
such as a prediction committed before an experiment or a claim
filed with its evidence. Interface activity, such as clicks and
page views, does not belong in a record unless a schema gives it
that kind of meaning.
* Record what happened and leave conclusions out. A detected
misconception is a judgment about the learner. An event that
holds one SHOULD carry an instrument member.
Srivastava Expires 14 April 2027 [Page 18]
Internet-Draft learnlog October 2026
* Refer to an earlier entry of the same record by its seq.
* Allow text written by a learner to be left out. Free text can
hold personal data. A hash can stand in for the text, within the
limits that Section 10.7 describes.
* State which members can identify a person.
* Prefer integers and strings to fractional numbers where exact
values matter (Section 7.1).
5.7. Companion Profiles for AI Use
This subsection gives non-normative guidance. It adds no core fields
or event types. A companion profile can use the extension points of
the header and events to state context needed by a particular
deployment. The profile needs its own identifier, version, and
public specification. Event-schema URIs follow Section 5.4. A
profile identifier is not a registration in the registries requested
by this document.
A profile can distinguish practice, assessment, and other activity
stages; identify the policy that permitted or prohibited specified
assistance; and bind that policy to the relevant actor, task, stage,
and period. Permission to use assistance in an activity is separate
from consent to collect, use, or disclose data (Section 6.1).
Neither can be inferred from the other. A policy assertion also does
not establish compliance.
A profile can state which channels, sessions, activities, and periods
the producer planned to observe, which it asserts it captured, and
which it excluded. Planned capture and achieved capture are
different assertions. A missing assistance event does not
demonstrate that no assistance occurred. Outside applications, other
devices, between-session use, a capture interruption, and unavailable
content can leave relevant exposure unknown. Describing a gap does
not establish that AI was used in that gap.
The header is fixed when a record is created (Section 4.1). A plan
stated there is not a later completion report. A change in stage,
applicable policy, model, configuration, or observation coverage can
be represented by starting another record with the new context, or by
an explicitly defined extension carried in a hashed event. A profile
using such an extension needs to define its effective scope and how
events refer to the context. This document defines no runtime
context-update or capture-completion event, and modifying an existing
header changes the hash commitments.
Srivastava Expires 14 April 2027 [Page 19]
Internet-Draft learnlog October 2026
A profile can require the existing actor, activity, session, and
instrument members in particular events. It can also identify where
retained content or configuration is available to an authorized
reviewer. A hash or content reference alone does not give that
reviewer the semantic content needed to classify a scaffold, and
access can be limited by Section 11. Profiles need to distinguish
missing information from information that has not been reviewed.
Conditions such as whether AI changed practice, comparison-group
exposure, or grading usually require evidence beyond one record.
Condition assessments and judgments about the applicability of
educational research belong in separately specified analytical
records. Those records can refer to the relevant learnlog record and
entries, state the reviewed scope and comparators, and preserve
unresolved questions. The core verifier does not endorse those
judgments or decide whether a study needs to be repeated.
6. Generic Event Schemas
This section defines event schemas for three namespaces that are not
tied to one subject area: consent, assist, and dialog.
6.1. The consent Namespace
The schema URI is urn:ietf:params:learnlog:events:consent. The
namespace has two event types, consent:granted and consent:withdrawn.
Both carry the same data.
ConsentChange = {
scopes: [+ ConsentScope],
? ref: text,
* $$consent-change-extension
}
ConsentScope = "instruction" / "research" / "export" / text
$Event /= event-type<"consent:granted", ConsentChange>
$Event /= event-type<"consent:withdrawn", ConsentChange>
Figure 13: Events of the consent namespace
scopes: The uses that the consent covers.
ref: A reference to the consent that the producer holds, such as the
identifier of a signed form.
This document defines three scopes. Other values MAY be used.
Srivastava Expires 14 April 2027 [Page 20]
Internet-Draft learnlog October 2026
instruction: Use of the record to support the instruction of the
subject.
research: Use of the record in research.
export: Disclosure of the record outside the organization that
operates the producer.
The actor of a consent event is the party that gave or withdrew
consent, for example a guardian.
A consent event records that consent was given or withdrawn, as the
producer observed it. This document does not define how consent is
obtained or how a producer acts on it.
A scope is in effect from a consent:granted event that names it until
a later consent:withdrawn event that names it. A reader cannot tell
which scopes are in effect when a consent event may be among the
entries that were redacted or removed. For that reason, a holder
SHOULD NOT redact a consent event.
6.2. The assist Namespace
The schema URI is urn:ietf:params:learnlog:events:assist. The
namespace records the help that the producer observed. A reader can
treat an action by the learner that follows a scaffold in the same
activity as possibly assisted.
assist:help_requested: The actor asked for help. The to member of
the event names the party that was asked.
assist:scaffold_provided: The actor gave the learner a scaffold,
which is support meant to help the learner make progress. The
actor can be an instructor, an assistant, a peer, or the system.
The event MUST hold the actor member, because an absent actor
would mean the subject.
Srivastava Expires 14 April 2027 [Page 21]
Internet-Draft learnlog October 2026
AssistHelpRequested = {
? type: ScaffoldType,
* $$assist-help-requested-extension
}
AssistScaffoldProvided = {
type: ScaffoldType,
? request: Seq,
? level: uint .ge 1,
? reveals_answer: bool,
? modality: "text" / "speech" / text,
? content: text,
? content_ref: text,
? content_hash: HashValue,
* $$assist-scaffold-provided-extension
}
ScaffoldType = "socratic" / "probing" / "metacognitive" /
"scaffolding" / "explain" / "hint" /
"demonstrate" / text
$Event /= event-type<"assist:help_requested", AssistHelpRequested>
$Event /= event-type<"assist:scaffold_provided",
AssistScaffoldProvided>
Figure 14: Events of the assist namespace
In AssistHelpRequested, type is the kind of help that was asked for,
when the interface distinguishes kinds. The members of
AssistScaffoldProvided are:
type: The kind of scaffold (Table 2).
request: The seq of the entry that this scaffold answers, such as an
assist:help_requested entry or a dialog:message entry. Absent
when the scaffold was not requested.
level: The position of the scaffold among those given for the
current activity, starting at 1.
reveals_answer: True when the scaffold discloses the answer that the
activity asks for.
modality: How the scaffold was expressed. The default is text.
content: The words of the scaffold.
content_ref: An identifier for authored scaffold content.
Srivastava Expires 14 April 2027 [Page 22]
Internet-Draft learnlog October 2026
content_hash: The hash of the scaffold as shown to the learner
(Section 7.2), for use when content is left out. An event MUST
NOT hold both content and content_hash.
+===============+=============================+
| Value | Meaning |
+===============+=============================+
| socratic | An open question that leads |
| | the learner toward an idea |
+---------------+-----------------------------+
| probing | A question about an |
| | assumption the learner made |
+---------------+-----------------------------+
| metacognitive | A prompt about the |
| | learner's own approach |
+---------------+-----------------------------+
| scaffolding | The problem broken into |
| | parts |
+---------------+-----------------------------+
| explain | A direct explanation |
+---------------+-----------------------------+
| hint | A hint |
+---------------+-----------------------------+
| demonstrate | A worked example |
+---------------+-----------------------------+
Table 2: Values of ScaffoldType
Other values MAY be used.
A producer SHOULD record every scaffold given to the learner,
requested or not. The actor member identifies the provider.
Help can arrive as a turn in a conversation. A producer that knows a
turn to be help records it as assist:scaffold_provided, with the
words in content or their hash in content_hash, and writes no
dialog:message for that turn. When a producer cannot tell whether a
turn is help, it records the turn as dialog:message (Section 6.3).
The replies of a general chat assistant are an example.
6.2.1. Hypothetical AI Assistance Example
Consider a task that asks a learner to solve 2x + 3 = 11 and explain
the approach. An AI assistant might say, "Before calculating,
describe your plan and how you will check whether it worked." An
assist:scaffold_provided event could describe this as type equal to
metacognitive, with reveals_answer equal to false and the words in
content. The actor identifies a software assistant, and the
Srivastava Expires 14 April 2027 [Page 23]
Internet-Draft learnlog October 2026
activity, session, and instrument identify the task and producing
model.
In a different hypothetical history, the assistant says, "Subtract 3
from both sides to get 2x = 8, then divide both sides by 2, so x =
4." The event could instead use type equal to explain and
reveals_answer equal to true. These examples illustrate existing
members; they are not measurements of learning and introduce no new
event type.
If a subject-area schema records a learner response after either
scaffold, the sequence can distinguish the two recorded assistance
histories. It cannot establish the learner's internal reasoning,
when internal retrieval took place, whether another source was used,
or which assistance caused a later outcome. A declaration of type or
reveals_answer remains a producer assertion. A reviewer needs the
relevant content and task to inspect it. An applicability assessment
comparing this activity with a classroom intervention needs
additional evidence and separately stated assumptions.
6.3. The dialog Namespace
The schema URI is urn:ietf:params:learnlog:events:dialog. The
namespace has one event type, dialog:message, which is one turn in an
exchange between the subject and another party. The actor is the
party that produced the turn, and to names the party addressed.
DialogMessage = {
? modality: "text" / "speech" / text,
? content: text,
? content_hash: HashValue,
? reply_to: Seq,
* $$dialog-message-extension
}
$Event /= event-type<"dialog:message", DialogMessage>
Figure 15: Events of the dialog namespace
modality: How the turn was expressed. The default is text.
content: The words of the turn.
content_hash: The hash of the words (Section 7.2), for use when
content is left out. An event MUST NOT hold both content and
content_hash.
reply_to: The seq of the entry that this turn answers.
Srivastava Expires 14 April 2027 [Page 24]
Internet-Draft learnlog October 2026
A producer SHOULD include activity when the exchange takes place
during a task. A reader can then treat a turn by another party as
possible help.
The words of a turn can hold personal data, and Section 11 applies.
When software transcribes speech, the event SHOULD carry an
instrument member that identifies the transcriber.
7. Integrity
7.1. Canonical Form
Hashes are computed over a canonical form, so that two
implementations produce the same octets for the same value. The
canonical form of a JSON value is its serialization under the JSON
Canonicalization Scheme (JCS) [RFC8785], encoded in UTF-8.
The following rules apply to a whole log file, including the parts
that no hash covers:
* A log file MUST conform to I-JSON [RFC7493]. In particular, no
object holds two members with the same name, and no string holds a
noncharacter or a surrogate without its pair.
* A number is hashed as the IEEE 754 double nearest to its value, in
the form that [RFC8785] gives that double. A file MUST NOT hold a
number too large for a double. A number written without a
fraction or an exponent MUST have an absolute value below 2^53. A
larger integer is carried as a string.
* A string is hashed as the characters it denotes. An escape
sequence and the character it stands for give the same hash. A
holder MUST NOT apply Unicode normalization.
* A holder MUST preserve every member of a header, an event, and a
head, including members it does not recognize.
A serialization other than JSON (Section 8.3) is mapped to the JSON
data model first. Hashes are always computed over the canonical JSON
form.
7.2. Hashes
In this section, H(x) is the hash named by hash_alg, applied to the
octets x and written in lowercase hexadecimal. C(v) is the canonical
form of the JSON value v.
Srivastava Expires 14 April 2027 [Page 25]
Internet-Draft learnlog October 2026
record hash = H(C(header))
event_hash = H(C(event))
prev_hash = record hash in the entry with seq 1
= entry_hash of the preceding entry, otherwise
entry_hash = H(C({ "record_hash": record hash,
"seq": seq, "time": time,
"event_hash": event_hash,
"prev_hash": prev_hash }))
Figure 16: Hash computation
* The record hash is the hash of the header object.
* event_hash is the hash of the event object with all its members.
* prev_hash of the entry with seq 1 is the record hash. In every
other entry, it is the entry_hash of the entry before it.
* entry_hash is the hash of an object with exactly five members.
The member record_hash holds the record hash. The other four are
the seq, time, event_hash, and prev_hash of the entry.
* A member named content_hash or config_hash holds the hash of a
string of octets. For text, the octets are its UTF-8 encoding.
For other content, the producer chooses the octets.
Every entry hash covers the record hash. An entry that is moved to a
record with another header therefore fails step 4e of Section 7.5,
even after the entries before it are removed (Section 4.3).
A header and an event each require members that the object hashed for
an entry lacks. The canonical form of that object therefore differs
from the canonical form of any header or event.
7.3. Redaction
A holder redacts an entry by removing its event member and adding the
member redacted with the value true. No other member changes.
The entry hash is computed from event_hash, without the event itself.
Every hash in the record therefore still verifies, and so does every
signed head.
Srivastava Expires 14 April 2027 [Page 26]
Internet-Draft learnlog October 2026
The salt is removed with the event. A party that does not have the
salt cannot confirm a guess at the event from event_hash
(Section 10.7).
Redaction leaves seq, time, and the hashes of the entry in place. A
holder that needs to remove those as well truncates the record
(Section 4.3) or deletes it.
A verifier reports which entries are redacted. Redaction does not
cause a check to fail.
Only a party that kept the event can restore it. A restored event is
checked against event_hash like any other.
7.4. Signed Heads
A head names the latest entry of a record at some moment. A producer
signs a head so that a verifier can authenticate the record up to
that entry.
SignedHead = {
head: Head,
signature: text
}
Head = {
record_hash: HashValue,
seq: Seq,
entry_hash: HashValue,
time: Timestamp,
* text => any
}
Figure 17: SignedHead definition
record_hash: The record hash (Section 7.2).
seq, entry_hash: The seq and entry_hash of the entry that the head
names.
time: The time of signing, as observed by the producer.
The signature member is a JSON Web Signature (JWS) [RFC7515] in the
compact serialization with detached content (Appendix F of
[RFC7515]). The JWS payload is the canonical form of the head
object. The value of signature is therefore the encoded protected
header, two periods, and the encoded signature.
Srivastava Expires 14 April 2027 [Page 27]
Internet-Draft learnlog October 2026
* The protected header MUST contain alg and kid and MUST NOT contain
crit.
* The value of alg MUST name a digital signature algorithm that uses
a public key. The value none and MAC algorithms such as HS256
MUST NOT be used. Implementations MUST support ES256 [RFC7518].
* The value of kid MUST be the JWK Thumbprint [RFC7638] of the
public key, computed with SHA-256 and encoded in base64url without
padding.
To check a signature, a verifier computes the canonical form of head,
encodes it in base64url, places it between the two periods, and
verifies the result as a JWS. A verifier uses each key it trusts
with exactly one algorithm (Section 3.1 of [RFC8725]).
A producer SHOULD sign a head at the end of each session and whenever
a record leaves its control.
This document does not define how a verifier obtains the public key
or decides to trust it. A key that travels in the file itself shows
nothing about who signed.
7.5. Verification
A verifier is configured with the public keys it trusts and, for each
key, the one signature algorithm it accepts. A verifier MUST report
the result that the steps below define. Any procedure that gives the
same result is acceptable.
1. Read the file.
a. Read a file that begins with the octet 0x1E as a JSON text
sequence (Section 8.2). Read any other file as one JSON text
(Section 8.1).
b. Check that each JSON text conforms to I-JSON and to the rules
for numbers in Section 7.1.
c. Check that file_schema names a file schema that the verifier
knows and that fits the serialization. Check that a
contained file holds a records array with at least one
element, and that the first element of a sequential file
holds a record object.
Srivastava Expires 14 April 2027 [Page 28]
Internet-Draft learnlog October 2026
A verifier MUST reject a file when its JSON text fails this step,
or when the first element of a sequential file does. None of its
records is verified. A later element of a sequential file that
fails step 1b is discarded (Section 8.2). Steps 2 to 5 apply to
each record of a file that passes.
2. Check the header.
a. Check that header is an object, that record_id, subject, and
hash_alg are strings, and that created is a Timestamp.
b. If step 2a passed and the verifier does not support hash_alg,
the outcome for the record is "unsupported" and no further
step applies. A verifier MUST NOT support an algorithm whose
output is shorter than 256 bits.
c. Compute the record hash.
3. Set the expected seq to 1 and the expected link to the record
hash. If truncated is present, check that truncated.seq is a Seq
and that truncated.entry_hash is a HashValue. The expected seq
is then truncated.seq plus 1, and the expected link is
truncated.entry_hash.
4. Check that entries is an array. For each entry, in order:
a. Check that seq is a Seq, that time is a Timestamp, and that
event_hash, prev_hash, and entry_hash are HashValues. Check
that the entry holds exactly one of event and redacted.
b. Check that seq equals the expected seq.
c. Check that prev_hash equals the expected link.
d. If event is present, check that it is an object, that its
name has the form given in Section 5.4, that its salt matches
the Salt pattern of Figure 9, and that its data is an object.
Then check that the hash of the event equals event_hash. If
redacted is present, check that its value is true.
e. Compute the entry hash and check that it equals entry_hash.
f. Set the expected link to entry_hash and add 1 to the expected
seq.
5. If signed_heads is present, check that it is an array. For each
signed head:
Srivastava Expires 14 April 2027 [Page 29]
Internet-Draft learnlog October 2026
a. Check that head is an object in which record_hash and
entry_hash are HashValues, seq is a Seq, and time is a
Timestamp. Check that signature consists of two base64url
strings, neither of them empty, joined by two periods. Check
that the first string decodes to a JSON object that conforms
to I-JSON. Check that this object holds the strings alg and
kid, that alg is not none, and that crit is absent.
b. Check that head.record_hash equals the record hash.
c. Check that head.seq is no greater than the seq of the last
entry. A greater value shows that entries are missing from
the end of the record. For a record without entries, the
comparison uses truncated.seq, or 0 when the record is not
truncated.
d. If an entry has the seq that the head names, check that
head.entry_hash equals its entry_hash. If head.seq equals
truncated.seq, check that head.entry_hash equals
truncated.entry_hash. A head with a lower seq names an entry
that was removed, and this check does not apply to it.
e. If the verifier trusts a key whose JWK Thumbprint equals kid,
check that alg is the algorithm it accepts for that key, and
verify the signature with that key as Section 7.4 describes.
If the verifier trusts no such key, the signature is not
checked.
Section 4.1 and Section 4.2 define the terms Timestamp, HashValue,
and Seq. A member that this document does not define is ignored in
every step, apart from its part in a hash or a signature.
Once a check in steps 2 to 5 fails, the outcome is settled, and a
verifier MAY stop.
The result for a record has these parts:
Outcome: "consistent" when every check in steps 2 to 5 passed,
"inconsistent" when a check failed, or "unsupported" as step 2
describes.
Authenticated through: For a consistent record, the highest seq
among the heads that had an entry hash to compare in step 5d and a
signature that verified in step 5e, together with the kid of a
head that names it. This part is absent when no head qualifies.
Entries up to that seq were in the record when the holder of that
key signed. Later entries are consistent and unauthenticated.
Srivastava Expires 14 April 2027 [Page 30]
Internet-Draft learnlog October 2026
Redacted: The seq of each redacted entry.
Truncated: The value of truncated.seq, when the record is truncated.
The entries up to that seq were not checked.
A verifier reports the following conditions, and they leave the
outcome unchanged:
* a time that is earlier than the one before it, with the two
compared as instants;
* a signed head whose signature was not checked;
* an element of a sequential file that was discarded (Section 8.2).
Verification does not use title, description, serialization_format,
or event_schemas. The data of an event is not checked against an
event schema, and an event of an unknown type is handled like any
other. A tool MAY validate events against the schemas it knows and
report the result separately.
A consistent record agrees with itself. A verified head ties the
entries up to its seq to a key. Section 10.1 states what these
results establish and what they leave open.
8. Serialization
The structures in this document are defined in CDDL. Section 11 of
[QLOG] takes the same approach and maps its structures to JSON and to
JSON text sequences. This document defines the same two
serializations. Hashes always use the canonical JSON form
(Section 7.1).
Where this document defines a member as an integer, a producer writes
the number without a fraction or an exponent. A reader compares
numbers by value.
8.1. JSON
A LearnlogFile is serialized as a JSON text [RFC8259] in UTF-8. The
media type is application/learnlog+json, which is also the value of
serialization_format. The file extension is .learnlog.
Srivastava Expires 14 April 2027 [Page 31]
Internet-Draft learnlog October 2026
8.2. JSON Text Sequences
A LearnlogFileSeq is serialized as a JSON text sequence [RFC7464].
Each element is preceded by a record separator (0x1E) and followed by
a line feed (0x0A). The media type is application/learnlog+json-seq,
which is also the value of serialization_format. The file extension
is .slearnlog.
A producer can add an entry or a signed head to a sequential file
without rewriting what came before. Redaction and truncation rewrite
the file. In Figure 18, <RS> stands for the record separator and
most values are left out.
<RS>{"file_schema":"urn:ietf:params:learnlog:file:sequential",
"serialization_format":"application/learnlog+json-seq",
"record":{"header":{...},"event_schemas":[...]}}
<RS>{"seq":1,"time":"2026-10-07T14:00:05Z","event":{...},
"event_hash":"...","prev_hash":"...","entry_hash":"..."}
<RS>{"seq":2,"time":"2026-10-07T14:01:10Z","event":{...},
"event_hash":"...","prev_hash":"...","entry_hash":"..."}
<RS>{"head":{...},"signature":"..."}
Figure 18: Outline of a sequential file
A crash can leave the last element of a file cut off. A reader MUST
discard an element that is cut off (Section 2.3 of [RFC7464]) or that
fails step 1b of Section 7.5. The same applies to an element that is
neither an Entry nor a SignedHead. When the first element is
unusable, the file is rejected. When an entry is discarded, the
entries after it fail verification.
8.3. Other Serializations
Other serializations MAY be defined, for example one in CBOR. A
serialization MUST map every structure to the JSON data model without
loss, because hashes are computed over the canonical JSON form
(Section 7.1).
9. Relationship to Existing Work
The file structure and the event schema model come from qlog [QLOG].
A learnlog record corresponds to a qlog trace (Section 4.2 of
[QLOG]). This document adds hashes, redaction, and signed heads.
The Experience API (xAPI) [XAPI] defines a JSON data model and a web
service for communication between activities and a Learning Record
Store. This document defines a file format and no web service. A
mapping between the two is not defined here.
Srivastava Expires 14 April 2027 [Page 32]
Internet-Draft learnlog October 2026
Caliper Analytics [CALIPER] defines events and entities, and an
envelope that carries them to an endpoint. This document defines no
transport.
Deployments that use xAPI or Caliper need explicit mappings for
assistance, actors, task context, and instrument provenance before
exchanging such information with learnlog. A mapping needs to state
which distinctions it preserves, what information it loses, and
whether learnlog integrity commitments can be retained. This
document provides no such mapping or interoperability result.
Redaction relies on salted hashes, an approach that Selective
Disclosure for JSON Web Tokens also uses (Section 1 of [RFC9901]). A
signed head is similar to the Signed Tree Head of Certificate
Transparency (Section 4.10 of [RFC9162]), applied to a chain in place
of a tree.
10. Security Considerations
10.1. What Verification Shows
A record that verifies as consistent has entries that agree with one
another and with the header. Consistency alone does not show who
wrote the record or that nothing was replaced. Anyone who holds a
record without a signed head can change an event and recompute every
later hash.
A signed head limits this. Take a party without the signing key that
changes the seq, time, or event of an entry at or before the head.
The head stays valid only when the change is a redaction, the
restoring of a redacted event, or a truncation (Section 10.3). After
any other such change, a verifier that trusts the key reports the
record as inconsistent, or as unauthenticated when the head was
removed as well.
Neither property shows that events took place as recorded. A
producer can write an event that is false. Verification establishes
at most that the signed entries were not changed by a party without
the key.
No hash covers title, description, or event_schemas. The same holds
for a member that this document does not define, unless it sits in a
header, an event, or a head. A reader cannot rely on those values.
Srivastava Expires 14 April 2027 [Page 33]
Internet-Draft learnlog October 2026
10.2. Removal of Recent Entries
A holder can remove the latest entries of a record together with any
signed head that covers them. What remains verifies. A verifier
detects the removal only if it knows a later head from another
source. This document defines no way to exchange heads.
10.3. Redaction and Truncation by a Holder
Any holder can redact an event or truncate a record, and the result
still verifies. A verifier reports which entries are redacted and
whether the record is truncated. What the missing events said, and
who removed them, stays unknown to the verifier.
A reader that draws a conclusion from the absence of an event SHOULD
treat each redacted or removed entry as a possible instance of that
event. A redacted entry inside an activity may have been a scaffold.
A redacted or removed entry may have been a withdrawal of consent.
10.4. Rewriting by the Producer
The producer holds the signing key, so it can rewrite a record and
sign a new head. Detection requires that another party received a
head before the rewrite. A time stamping authority [RFC3161] can
provide evidence that a head existed before a given time. This
document does not define how to use one. The time of a head is a
statement by the signer and proves nothing about when the head was
signed.
10.5. Trusted Keys
A signature that verifies shows that the holder of a trusted key
signed a head. Any trusted key authenticates any record. A verifier
that trusts the keys of several producers needs to know which
producer each key belongs to. The result of verification names the
key for that purpose.
10.6. Where the Producer Runs
A signature shows that the holder of a key signed a head. When the
producer runs on a device that the learner controls, the learner may
control the key. A verifier needs to know where signing took place
before it treats a record as evidence about that learner.
Srivastava Expires 14 April 2027 [Page 34]
Internet-Draft learnlog October 2026
10.7. Guessing Redacted Events
An event can have few possible values. Without a salt, a party could
hash each candidate and compare the result with event_hash. The salt
prevents this only if it is unpredictable and is deleted with the
event. A producer MUST NOT reuse a salt and MUST NOT derive one from
the content of the event.
The position and time of a redacted entry stay visible, as do the
entries around it. Together they can suggest what was removed.
Members named content_hash and config_hash carry no salt. A party
can test a guess at a short or predictable text against such a hash.
Redaction of the event removes these members with it.
10.8. Meaning of Event Names
A hash covers the name of an event. No hash covers event_schemas,
the list that ties a namespace to a schema URI. For a registered
namespace (Section 12.3), the name alone identifies the schema. For
any other namespace, a holder can replace the URI in the list, and
with it the apparent meaning of the events. A reader that depends on
such events needs to know the schemas of the producer from another
source.
10.9. Hash Algorithms
The integrity of a record rests on the collision resistance of the
hash algorithm. A checksum or any other function that is not a
cryptographic hash MUST NOT be used.
All hashes in a record use one algorithm, so a record cannot move to
another. A producer that needs a new algorithm starts a new record.
10.10. Canonical Form
Two parsers that read the same text differently can disagree about a
hash, or agree about a hash while they hold different values.
Sections 4, 6, and 8.2 of [RFC8259] describe three such cases: member
names that are not unique, numbers beyond the range or precision of a
double, and strings with unpaired surrogates. The rules in
Section 7.1 address these cases, and step 1 of Section 7.5 applies
them before any hash is computed.
Srivastava Expires 14 April 2027 [Page 35]
Internet-Draft learnlog October 2026
10.11. Untrusted Input
A log file can come from a source that is not trusted.
Implementations need limits on file size, nesting depth, and string
length.
11. Privacy Considerations
A record describes the behavior of a person in detail, and that
person can be a child. The considerations of [RFC6973] apply. This
section covers points that are specific to this format.
11.1. Identifiers
The subject member, and the id member of a party that is a person,
MUST NOT hold a name, an email address, or an identifier taken from
another system, such as a student number.
A RECOMMENDED construction is HMAC [RFC2104] with SHA-256 over the
internal identifier, under a secret key that the producer keeps, with
at least 128 bits of the output retained. A hash without a key is
not sufficient, because identifiers can be guessed and hashed.
The subject identifier is part of the header and stays fixed for the
life of a record. Every party that receives the record sees the same
identifier and can link the record to other copies.
11.2. People Other Than the Subject
A record can describe instructors, peers, and guardians, and a dialog
event can hold their words. The data is then about them as well.
Their identifiers follow Section 11.1.
11.3. Data Minimization
* A producer SHOULD record an event only if the event has a use.
* A producer SHOULD use no more precision in time than its purpose
needs. Precision cannot be reduced later, because time is hashed.
* Text written by a learner SHOULD be left out unless it is needed.
11.4. Limits of Redaction
Redaction removes the content of an event. The entry remains and
shows that something happened at that time. Copies of the content in
other events, or outside the record, are not affected.
Srivastava Expires 14 April 2027 [Page 36]
Internet-Draft learnlog October 2026
The event_hash of a redacted entry remains as well. A party that
kept a copy of the event can still show that the event belonged to
the record. Truncation or deletion of the record removes that hash.
Redaction may not be enough after consent is withdrawn. Truncation
or deletion of the record removes more. Unless it is redacted or
removed, the consent:withdrawn event remains in the record as the
trace of the withdrawal.
11.5. Correlation and Identification
The actions and times in a record can be combined with other data
about a person. Sections 5.2.1 and 5.2.2 of [RFC6973] describe how
such correlation can lead to identification. A record SHOULD be
treated as personal data whatever identifiers it carries.
11.6. Signing Keys
The kid of a signed head is the same in every record signed with one
key. A key that serves one learner or one device links the records
of that learner, whatever their subject identifiers. A key that
serves a whole deployment does not.
11.7. Storage and Transfer
Records SHOULD be encrypted in transit and at rest. Access to them
SHOULD be controlled and logged. A holder SHOULD set a retention
period.
11.8. Children
A learner can be a child. This document does not address compliance
with any law.
12. IANA Considerations
12.1. URN Sub-namespace
IANA is requested to register the following in the "IETF URN Sub-
namespace for Registered Protocol Parameter Identifiers" registry
[RFC3553]:
Registry name: learnlog
Specification: This document
Repository: https://www.iana.org/assignments/learnlog
Index value: The part of a URN that follows
urn:ietf:params:learnlog:, which has the form file:<identifier> or
events:<namespace>. No transformation is needed.
Srivastava Expires 14 April 2027 [Page 37]
Internet-Draft learnlog October 2026
12.2. File Schema URIs
IANA is requested to create the "learnlog File Schema URIs" registry
at https://www.iana.org/assignments/learnlog. The registration
policy is Expert Review [RFC8126]. The expert checks that the URI
has the form given in Section 3.3 and that a public specification
defines the file schema. An entry holds a file schema URI, a
description, and a reference. The initial entries are:
File Schema URI: urn:ietf:params:learnlog:file:contained
Description: A file that holds one or more records
Reference: Section 3.1
File Schema URI: urn:ietf:params:learnlog:file:sequential
Description: A file that holds one record and grows by appending
Reference: Section 3.2
12.3. Event Schema URIs
IANA is requested to create the "learnlog Event Schema URIs" registry
at the same location. The registration policy is Expert Review
[RFC8126]. The expert checks the following:
* The URI has the form given in Section 5.4.
* A public specification defines the event types, with CDDL for the
data of each.
* A schema for a new namespace uses a namespace identifier that is
not yet registered.
* A schema that extends a registered namespace uses the URI of that
namespace with a fragment identifier, and leaves the registered
event types unchanged.
An entry holds an event schema URI, a namespace, the event types, a
description, and a reference. The initial entries are:
Event Schema URI: urn:ietf:params:learnlog:events:consent
Namespace: consent
Event Types: granted, withdrawn
Description: Consent given or withdrawn
Reference: Section 6.1
Event Schema URI: urn:ietf:params:learnlog:events:assist
Namespace: assist
Event Types: help_requested, scaffold_provided
Description: Help requested and scaffolds provided
Srivastava Expires 14 April 2027 [Page 38]
Internet-Draft learnlog October 2026
Reference: Section 6.2
Event Schema URI: urn:ietf:params:learnlog:events:dialog
Namespace: dialog
Event Types: message
Description: Turns in an exchange with another party
Reference: Section 6.3
12.4. Media Types
IANA is requested to register the following media types [RFC6838].
12.4.1. application/learnlog+json
Type name: application
Subtype name: learnlog+json
Required parameters: N/A
Optional parameters: N/A
Encoding considerations: binary; see Section 8.1
Security considerations: See Section 10 and Section 11
Interoperability considerations: See Section 7.1
Published specification: This document
Applications that use this media type: Software that writes,
verifies, or analyzes learnlog records
Fragment identifier considerations: As for application/json
[RFC6839]
Additional information: Deprecated alias names for this type: N/A
Magic number(s): N/A
File extension(s): .learnlog
Macintosh file type code(s): N/A
Person & email address to contact for further information: See the
Author's Address section
Intended usage: COMMON
Restrictions on usage: N/A
Author: See the Author's Address section
Change controller: IETF
Provisional registration? (standards tree only): No
12.4.2. application/learnlog+json-seq
Type name: application
Subtype name: learnlog+json-seq
Required parameters: N/A
Optional parameters: N/A
Encoding considerations: binary; see Section 8.2
Security considerations: See Section 10 and Section 11
Interoperability considerations: See Section 7.1
Published specification: This document
Srivastava Expires 14 April 2027 [Page 39]
Internet-Draft learnlog October 2026
Applications that use this media type: Software that writes,
verifies, or analyzes learnlog records
Fragment identifier considerations: As for application/json-seq
[RFC8091]
Additional information: Deprecated alias names for this type: N/A
Magic number(s): N/A
File extension(s): .slearnlog
Macintosh file type code(s): N/A
Person & email address to contact for further information: See the
Author's Address section
Intended usage: COMMON
Restrictions on usage: N/A
Author: See the Author's Address section
Change controller: IETF
Provisional registration? (standards tree only): No
13. References
13.1. Normative References
[FIPS180] National Institute of Standards and Technology, "Secure
Hash Standard (SHS)", FIPS PUB 180-4,
DOI 10.6028/NIST.FIPS.180-4, August 2015,
<https://doi.org/10.6028/NIST.FIPS.180-4>.
[RFC2104] Krawczyk, H., Bellare, M., and R. Canetti, "HMAC: Keyed-
Hashing for Message Authentication", RFC 2104,
DOI 10.17487/RFC2104, February 1997,
<https://www.rfc-editor.org/info/rfc2104>.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119,
DOI 10.17487/RFC2119, March 1997,
<https://www.rfc-editor.org/info/rfc2119>.
[RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
<https://www.rfc-editor.org/info/rfc3339>.
[RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform
Resource Identifier (URI): Generic Syntax", STD 66,
RFC 3986, DOI 10.17487/RFC3986, January 2005,
<https://www.rfc-editor.org/info/rfc3986>.
[RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
<https://www.rfc-editor.org/info/rfc4648>.
Srivastava Expires 14 April 2027 [Page 40]
Internet-Draft learnlog October 2026
[RFC6920] Farrell, S., Kutscher, D., Dannewitz, C., Ohlman, B.,
Keranen, A., and P. Hallam-Baker, "Naming Things with
Hashes", RFC 6920, DOI 10.17487/RFC6920, April 2013,
<https://www.rfc-editor.org/info/rfc6920>.
[RFC7464] Williams, N., "JavaScript Object Notation (JSON) Text
Sequences", RFC 7464, DOI 10.17487/RFC7464, February 2015,
<https://www.rfc-editor.org/info/rfc7464>.
[RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493,
DOI 10.17487/RFC7493, March 2015,
<https://www.rfc-editor.org/info/rfc7493>.
[RFC7515] Jones, M., Bradley, J., and N. Sakimura, "JSON Web
Signature (JWS)", RFC 7515, DOI 10.17487/RFC7515, May
2015, <https://www.rfc-editor.org/info/rfc7515>.
[RFC7518] Jones, M., "JSON Web Algorithms (JWA)", RFC 7518,
DOI 10.17487/RFC7518, May 2015,
<https://www.rfc-editor.org/info/rfc7518>.
[RFC7638] Jones, M. and N. Sakimura, "JSON Web Key (JWK)
Thumbprint", RFC 7638, DOI 10.17487/RFC7638, September
2015, <https://www.rfc-editor.org/info/rfc7638>.
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
Writing an IANA Considerations Section in RFCs", BCP 26,
RFC 8126, DOI 10.17487/RFC8126, June 2017,
<https://www.rfc-editor.org/info/rfc8126>.
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
[RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
Interchange Format", STD 90, RFC 8259,
DOI 10.17487/RFC8259, December 2017,
<https://www.rfc-editor.org/info/rfc8259>.
[RFC8610] Birkholz, H., Vigano, C., and C. Bormann, "Concise Data
Definition Language (CDDL): A Notational Convention to
Express Concise Binary Object Representation (CBOR) and
JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610,
June 2019, <https://www.rfc-editor.org/info/rfc8610>.
Srivastava Expires 14 April 2027 [Page 41]
Internet-Draft learnlog October 2026
[RFC8785] Rundgren, A., Jordan, B., and S. Erdtman, "JSON
Canonicalization Scheme (JCS)", RFC 8785,
DOI 10.17487/RFC8785, June 2020,
<https://www.rfc-editor.org/info/rfc8785>.
[RFC9562] Davis, K., Peabody, B., and P. Leach, "Universally Unique
IDentifiers (UUIDs)", RFC 9562, DOI 10.17487/RFC9562, May
2024, <https://www.rfc-editor.org/info/rfc9562>.
13.2. Informative References
[CALIPER] 1EdTech Consortium, "Caliper Analytics Specification,
Version 1.2", 27 March 2020,
<https://www.imsglobal.org/spec/caliper/v1p2>.
[QLOG] Marx, R., Ed., Niccolini, L., Ed., Seemann, M., Ed., and
L. Pardue, Ed., "qlog: Structured Logging for Network
Protocols", Work in Progress, Internet-Draft, draft-ietf-
quic-qlog-main-schema-14, 6 July 2026,
<https://datatracker.ietf.org/doc/html/draft-ietf-quic-
qlog-main-schema-14>.
[RFC3161] Adams, C., Cain, P., Pinkas, D., and R. Zuccherato,
"Internet X.509 Public Key Infrastructure Time-Stamp
Protocol (TSP)", RFC 3161, DOI 10.17487/RFC3161, August
2001, <https://www.rfc-editor.org/info/rfc3161>.
[RFC3553] Mealling, M., Masinter, L., Hardie, T., and G. Klyne, "An
IETF URN Sub-namespace for Registered Protocol
Parameters", BCP 73, RFC 3553, DOI 10.17487/RFC3553, June
2003, <https://www.rfc-editor.org/info/rfc3553>.
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
Specifications and Registration Procedures", BCP 13,
RFC 6838, DOI 10.17487/RFC6838, January 2013,
<https://www.rfc-editor.org/info/rfc6838>.
[RFC6839] Hansen, T. and A. Melnikov, "Additional Media Type
Structured Syntax Suffixes", RFC 6839,
DOI 10.17487/RFC6839, January 2013,
<https://www.rfc-editor.org/info/rfc6839>.
[RFC6973] Cooper, A., Tschofenig, H., Aboba, B., Peterson, J.,
Morris, J., Hansen, M., and R. Smith, "Privacy
Considerations for Internet Protocols", RFC 6973,
DOI 10.17487/RFC6973, July 2013,
<https://www.rfc-editor.org/info/rfc6973>.
Srivastava Expires 14 April 2027 [Page 42]
Internet-Draft learnlog October 2026
[RFC7942] Sheffer, Y. and A. Farrel, "Improving Awareness of Running
Code: The Implementation Status Section", BCP 205,
RFC 7942, DOI 10.17487/RFC7942, July 2016,
<https://www.rfc-editor.org/info/rfc7942>.
[RFC8091] Wilde, E., "A Media Type Structured Syntax Suffix for JSON
Text Sequences", RFC 8091, DOI 10.17487/RFC8091, February
2017, <https://www.rfc-editor.org/info/rfc8091>.
[RFC8725] Sheffer, Y., Hardt, D., and M. Jones, "JSON Web Token Best
Current Practices", BCP 225, RFC 8725,
DOI 10.17487/RFC8725, February 2020,
<https://www.rfc-editor.org/info/rfc8725>.
[RFC8792] Watsen, K., Auerswald, E., Farrel, A., and Q. Wu,
"Handling Long Lines in Content of Internet-Drafts and
RFCs", RFC 8792, DOI 10.17487/RFC8792, June 2020,
<https://www.rfc-editor.org/info/rfc8792>.
[RFC9162] Laurie, B., Messeri, E., and R. Stradling, "Certificate
Transparency Version 2.0", RFC 9162, DOI 10.17487/RFC9162,
December 2021, <https://www.rfc-editor.org/info/rfc9162>.
[RFC9901] Fett, D., Yasuda, K., and B. Campbell, "Selective
Disclosure for JSON Web Tokens", RFC 9901,
DOI 10.17487/RFC9901, November 2025,
<https://www.rfc-editor.org/info/rfc9901>.
[XAPI] IEEE, "IEEE Standard for Learning Technology--JavaScript
Object Notation (JSON) Data Model Format and
Representational State Transfer (RESTful) Web Service for
Learner Experience Data Tracking and Access", IEEE
Std 9274.1.1-2023, October 2023.
Appendix A. Example
This appendix shows one record in full. Every hash in it can be
recomputed from the text of this document.
A.1. An Example Event Schema
The example uses a private event schema with the namespace sim and
the URI https://example.org/102026/sim. It defines two event types
for a simulation.
Srivastava Expires 14 April 2027 [Page 43]
Internet-Draft learnlog October 2026
SimPredictionCommitted = {
prediction: text,
? confidence: "guess" / "fairly_sure" / "certain",
* $$sim-prediction-committed-extension
}
SimExplanationFiled = {
explanation: text,
* $$sim-explanation-filed-extension
}
$Event /= event-type<"sim:prediction_committed",
SimPredictionCommitted>
$Event /= event-type<"sim:explanation_filed", SimExplanationFiled>
Figure 19: Event schema of the example
A.2. A Complete File
The file in Figure 20 holds one record with eight entries and one
signed head. Entry 4 is a hint from a tutoring system. Entries 5
and 6 are an exchange with an AI chat assistant. Entry 7 is a spoken
hint from a teacher, transcribed by software.
The content_hash and config_hash values are hashes of the texts in
Table 3. Each text is one line, with single spaces between words and
no line ending.
+=======+==============+====================================+
| Entry | Member | Text |
+=======+==============+====================================+
| 4 | content_hash | Look for a number that divides |
| | | both 12 and 16. |
+-------+--------------+------------------------------------+
| 4 | config_hash | example tutor configuration 7 |
+-------+--------------+------------------------------------+
| 6 | content_hash | Simplifying a ratio means dividing |
| | | both parts by the same number. |
+-------+--------------+------------------------------------+
| 6 | config_hash | example chat configuration 3 |
+-------+--------------+------------------------------------+
Table 3: Texts behind the content and configuration hashes
The explanation in entry 8 holds the character U+00BE, written in the
figure as an escape. In the canonical form, that character is the
two octets C2 BE.
Srivastava Expires 14 April 2027 [Page 44]
Internet-Draft learnlog October 2026
=============== NOTE: '\' line wrapping per RFC 8792 ================
{
"file_schema": "urn:ietf:params:learnlog:file:contained",
"serialization_format": "application/learnlog+json",
"title": "Example record",
"records": [
{
"header": {
"record_id": "66a921d7-55be-4589-afcc-84ea4d2c26ef",
"subject": "L-fdda6e0e3413590a303a3737d4176389",
"hash_alg": "sha-256",
"created": "2026-10-07T14:00:00Z",
"producer": {"name": "example-sim", "version": "1.4.0"}
},
"event_schemas": [
"urn:ietf:params:learnlog:events:consent",
"urn:ietf:params:learnlog:events:assist",
"urn:ietf:params:learnlog:events:dialog",
"https://example.org/102026/sim"
],
"entries": [
{
"seq": 1,
"time": "2026-10-07T14:00:05Z",
"event": {
"name": "consent:granted",
"salt": "SUe3daeuE7ZsSfKRHA9RkQ",
"actor": {"role": "guardian", "kind": "human"},
"data": {"scopes": ["instruction", "research"]}
},
"event_hash": "0e144a6edfb39ded22fab2dba4f60a69dc9fc72cdfe\
7006ab78001e5ac11deef",
"prev_hash": "dcfc869849b6088bb8cba0761987f4fa90a181335e20\
a95b120bb0e8dfcd5556",
"entry_hash": "ff3f6b48ed7a77379e68a08f6a0c2bfa71bdc757671\
ceb88d905e5d307638433"
},
{
"seq": 2,
"time": "2026-10-07T14:01:10Z",
"event": {
"name": "sim:prediction_committed",
"salt": "yqUo0sZAN2gYAhADsPJjKw",
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
Srivastava Expires 14 April 2027 [Page 45]
Internet-Draft learnlog October 2026
"variant": "seed-8675309"
},
"data": {
"prediction": "3:4",
"confidence": "fairly_sure"
}
},
"event_hash": "1b878146c3e51d20d0411979dc7fbac81da5fd08846\
9a725b9afcf8395c2a518",
"prev_hash": "ff3f6b48ed7a77379e68a08f6a0c2bfa71bdc757671c\
eb88d905e5d307638433",
"entry_hash": "ac64c6867336279286d1837e60312b56b106978d648\
db62360f211306d65b6e5"
},
{
"seq": 3,
"time": "2026-10-07T14:01:42Z",
"event": {
"name": "assist:help_requested",
"salt": "eKmBaP2uRROEiC4HVbWZfA",
"to": {
"role": "instructor",
"kind": "software",
"id": "example-tutor"
},
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
"variant": "seed-8675309"
},
"data": {"type": "hint"}
},
"event_hash": "5485100233e98c7bca12183cf9f9da23ee91f8bb029\
d82e46ddab320661cc51b",
"prev_hash": "ac64c6867336279286d1837e60312b56b106978d648d\
b62360f211306d65b6e5",
"entry_hash": "afa914e1952ca0d6878b901e32279a09f1462f252df\
b3f289ea846c63b048e06"
},
{
"seq": 4,
"time": "2026-10-07T14:01:43.200Z",
"event": {
"name": "assist:scaffold_provided",
"salt": "DgQiQwSuZLoHwnBLIox60g",
"actor": {
"role": "instructor",
Srivastava Expires 14 April 2027 [Page 46]
Internet-Draft learnlog October 2026
"kind": "software",
"id": "example-tutor"
},
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
"variant": "seed-8675309"
},
"instrument": {
"source": "model",
"model": "example-tutor-2026-09",
"config_hash": "c9f3b7ca43165de9e1df7bc7ec6cff14e7498d\
a4250a6df8e8f1885a9b4aeea8",
"parameters": {"temperature": 0.2}
},
"data": {
"type": "hint",
"request": 3,
"level": 1,
"reveals_answer": false,
"content_hash": "86c2216ed616d2d0097475056db432d1f9f76\
e1ac5e712742157a3fe64ded70d"
}
},
"event_hash": "b4bd1e82ee9019fb8ece8ab96192a64fdc953fc9ab2\
7b2d046664ac8525cc789",
"prev_hash": "afa914e1952ca0d6878b901e32279a09f1462f252dfb\
3f289ea846c63b048e06",
"entry_hash": "3b8fb5a69bc9701329888b081538f1cc243a2fadb14\
8f6fc2f619de4f7671f61"
},
{
"seq": 5,
"time": "2026-10-07T14:02:30Z",
"event": {
"name": "dialog:message",
"salt": "HySIGmOXiD_e0G3jppGMVg",
"to": {
"role": "assistant",
"kind": "software",
"id": "example-chat"
},
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
"variant": "seed-8675309"
Srivastava Expires 14 April 2027 [Page 47]
Internet-Draft learnlog October 2026
},
"data": {
"modality": "text",
"content": "What does simplifying a ratio mean?"
}
},
"event_hash": "a83a6d085d8ae61dfe3b3783ecaea3c51d52588d7a4\
c2182245236b2b0b7d2dd",
"prev_hash": "3b8fb5a69bc9701329888b081538f1cc243a2fadb148\
f6fc2f619de4f7671f61",
"entry_hash": "4cf6025ac1e0aa85ed8a9f1e3c678f544a73319d1e0\
8eecb3fbe6ae695b65a2d"
},
{
"seq": 6,
"time": "2026-10-07T14:02:33.500Z",
"event": {
"name": "dialog:message",
"salt": "wf_VFXE_2WNouptIJguFuQ",
"actor": {
"role": "assistant",
"kind": "software",
"id": "example-chat"
},
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
"variant": "seed-8675309"
},
"instrument": {
"source": "model",
"model": "example-chat-2026-08",
"config_hash": "fcfd5153bc5c0d1f52417f66ab078c749eb21f\
4cebb5504cf274821a79a17aa5"
},
"data": {
"modality": "text",
"reply_to": 5,
"content_hash": "fb4ede48d160a985aeca77af68fcc7abdc3af\
cdbff6781574146ecd02c2b45ed"
}
},
"event_hash": "0d8d14d15cb3a606a857e86fc4fbe838a9ec11dfa3e\
bdb73a5eef53bbb96d4c9",
"prev_hash": "4cf6025ac1e0aa85ed8a9f1e3c678f544a73319d1e08\
eecb3fbe6ae695b65a2d",
"entry_hash": "43f068599a10f02217bc7287ca082d99818aa1fd92f\
Srivastava Expires 14 April 2027 [Page 48]
Internet-Draft learnlog October 2026
a3e12115cf1a7d5bfc23b"
},
{
"seq": 7,
"time": "2026-10-07T14:03:05Z",
"event": {
"name": "assist:scaffold_provided",
"salt": "lMgpY68f-AMZ-mEMbfR3cg",
"actor": {
"role": "instructor",
"kind": "human",
"id": "T-c1a8a3a416c9098d21b2baf451464304"
},
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
"variant": "seed-8675309"
},
"instrument": {
"source": "model",
"model": "example-transcriber-1"
},
"data": {
"type": "hint",
"level": 2,
"reveals_answer": false,
"modality": "speech",
"content": "Try it with the smaller numbers first."
}
},
"event_hash": "3e305baf5a3fad47f1e9c3d412d799fdd18926ff159\
169a26034af74e6214f91",
"prev_hash": "43f068599a10f02217bc7287ca082d99818aa1fd92fa\
3e12115cf1a7d5bfc23b",
"entry_hash": "4a0646f97bb877a347b7ba98eb6d1a7d9e0e3e0978e\
d5706b0e07b7ef6ec4668"
},
{
"seq": 8,
"time": "2026-10-07T14:04:20Z",
"event": {
"name": "sim:explanation_filed",
"salt": "y0_vEXCW8JNMCBA0MnLr2w",
"session": "s-01",
"activity": {
"id": "https://example.org/activities/ratio-mixing",
"version": "2.0",
Srivastava Expires 14 April 2027 [Page 49]
Internet-Draft learnlog October 2026
"variant": "seed-8675309"
},
"data": {
"explanation": "12 out of 16 is \u00be. Both divide b\
y 4."
}
},
"event_hash": "3689aa3e1f8fdea9494f10a9607ffd84db805ad0475\
f57077129a34cd8ebb5d0",
"prev_hash": "4a0646f97bb877a347b7ba98eb6d1a7d9e0e3e0978ed\
5706b0e07b7ef6ec4668",
"entry_hash": "d2b47063f53bcce905ef687c5f7f1c3f008078d0a3e\
ece78d2bc54bf8c1ca5b5"
}
],
"signed_heads": [
{
"head": {
"record_hash": "dcfc869849b6088bb8cba0761987f4fa90a18133\
5e20a95b120bb0e8dfcd5556",
"seq": 8,
"entry_hash": "d2b47063f53bcce905ef687c5f7f1c3f008078d0a\
3eece78d2bc54bf8c1ca5b5",
"time": "2026-10-07T14:04:21Z"
},
"signature": "eyJhbGciOiJFUzI1NiIsImtpZCI6IkNPSWFUYTctOFoz\
VElOYmhBOFJjczZmcjAyWlRERzExMzM3MVQzR01aUlUifQ..9SbLqNvt-_gfXkz4sYqC\
znBecvxy1YojXXOujGN2pdy5jJ7IZOOw37pxBsrdjr7K4p52Rqlo4va5MGFbP5vVWg"
}
]
}
]
}
Figure 20: A complete contained file
A.3. Intermediate Values
The canonical form of the header is:
=============== NOTE: '\' line wrapping per RFC 8792 ================
{"created":"2026-10-07T14:00:00Z","hash_alg":"sha-256","producer":{"\
name":"example-sim","version":"1.4.0"},"record_id":"66a921d7-55be-45\
89-afcc-84ea4d2c26ef","subject":"L-fdda6e0e3413590a303a3737d4176389"}
Its SHA-256 hash is the record hash, which is also the prev_hash of
entry 1:
Srivastava Expires 14 April 2027 [Page 50]
Internet-Draft learnlog October 2026
dcfc869849b6088bb8cba0761987f4fa90a181335e20a95b120bb0e8dfcd5556
The canonical form of the event in entry 2 is:
=============== NOTE: '\' line wrapping per RFC 8792 ================
{"activity":{"id":"https://example.org/activities/ratio-mixing","var\
iant":"seed-8675309","version":"2.0"},"data":{"confidence":"fairly_s\
ure","prediction":"3:4"},"name":"sim:prediction_committed","salt":"y\
qUo0sZAN2gYAhADsPJjKw","session":"s-01"}
Its hash is the event_hash of entry 2:
1b878146c3e51d20d0411979dc7fbac81da5fd088469a725b9afcf8395c2a518
The canonical form of the object that is hashed for entry 2 is:
=============== NOTE: '\' line wrapping per RFC 8792 ================
{"event_hash":"1b878146c3e51d20d0411979dc7fbac81da5fd088469a725b9afc\
f8395c2a518","prev_hash":"ff3f6b48ed7a77379e68a08f6a0c2bfa71bdc75767\
1ceb88d905e5d307638433","record_hash":"dcfc869849b6088bb8cba0761987f\
4fa90a181335e20a95b120bb0e8dfcd5556","seq":2,"time":"2026-10-07T14:0\
1:10Z"}
Its hash is the entry_hash of entry 2:
ac64c6867336279286d1837e60312b56b106978d648db62360f211306d65b6e5
A.4. The Signed Head
The head was signed with the private key that matches this public
key:
{
"kty": "EC",
"crv": "P-256",
"x": "hLOF5epJKOENr_YLdw3iuvlSeuuUdVewL1BqcNtOKYw",
"y": "PwQdWqmdT3_EOKIQvttI8kFeZLUePMifTFD5CpM-1WY"
}
The JWK Thumbprint of the key, used as kid, is:
COIaTa7-8Z3TINbhA8Rcs6fr02ZTDG113371T3GMZRU
The protected header is:
{"alg":"ES256","kid":"COIaTa7-8Z3TINbhA8Rcs6fr02ZTDG113371T3GMZRU"}
Srivastava Expires 14 April 2027 [Page 51]
Internet-Draft learnlog October 2026
The JWS payload is the canonical form of the head:
=============== NOTE: '\' line wrapping per RFC 8792 ================
{"entry_hash":"d2b47063f53bcce905ef687c5f7f1c3f008078d0a3eece78d2bc5\
4bf8c1ca5b5","record_hash":"dcfc869849b6088bb8cba0761987f4fa90a18133\
5e20a95b120bb0e8dfcd5556","seq":8,"time":"2026-10-07T14:04:21Z"}
The value of signature in the file is:
=============== NOTE: '\' line wrapping per RFC 8792 ================
eyJhbGciOiJFUzI1NiIsImtpZCI6IkNPSWFUYTctOFozVElOYmhBOFJjczZmcjAyWlRE\
RzExMzM3MVQzR01aUlUifQ..9SbLqNvt-_gfXkz4sYqCznBecvxy1YojXXOujGN2pdy5\
jJ7IZOOw37pxBsrdjr7K4p52Rqlo4va5MGFbP5vVWg
The private key is not given here, so an implementation cannot
reproduce this value. The value can be verified with the public key
above.
A.5. Redaction and Truncation
After entry 8 is redacted, it reads as shown below. Every hash in
the record and the signed head verify as before.
=============== NOTE: '\' line wrapping per RFC 8792 ================
{
"seq": 8,
"time": "2026-10-07T14:04:20Z",
"redacted": true,
"event_hash": "3689aa3e1f8fdea9494f10a9607ffd84db805ad0475f5707712\
9a34cd8ebb5d0",
"prev_hash": "4a0646f97bb877a347b7ba98eb6d1a7d9e0e3e0978ed5706b0e0\
7b7ef6ec4668",
"entry_hash": "d2b47063f53bcce905ef687c5f7f1c3f008078d0a3eece78d2b\
c54bf8c1ca5b5"
}
If entries 1 to 5 are removed from the original record instead, the
record gains the member shown below and its first remaining entry is
entry 6. The signed head still verifies.
Srivastava Expires 14 April 2027 [Page 52]
Internet-Draft learnlog October 2026
=============== NOTE: '\' line wrapping per RFC 8792 ================
{
"truncated": {
"seq": 5,
"entry_hash": "4cf6025ac1e0aa85ed8a9f1e3c678f544a73319d1e08eecb3\
fbe6ae695b65a2d"
}
}
A.6. Canonical Form Check
The record above has few values that separate the canonical form of
[RFC8785] from other compact JSON output with sorted member names.
The JSON text in Figure 21 has more of them. It holds numbers in
several spellings, a control character, and two member names whose
order by UTF-16 code unit differs from their order by code point.
{
"numbers": [1e21, 1.0, 0.000001, 1e-7, -0, 0.2, 4.50, 2E-3,
333333333.33333329],
"string": "\u000f\u00be/\"\\\n",
"\ud83d\ude00": 1,
"\ufb33": 2,
"a": null,
"A": true
}
Figure 21: A JSON text for checking the canonical form
In the canonical form, the member names appear in the order A, a,
numbers, string, U+1F600, U+FB33. The numbers appear as 1e+21, 1,
0.000001, 1e-7, 0, 0.2, 4.5, 0.002, and 333333333.3333333. The
canonical form has 131 octets, shown here in hexadecimal:
7b 22 41 22 3a 74 72 75 65 2c 22 61 22 3a 6e 75
6c 6c 2c 22 6e 75 6d 62 65 72 73 22 3a 5b 31 65
2b 32 31 2c 31 2c 30 2e 30 30 30 30 30 31 2c 31
65 2d 37 2c 30 2c 30 2e 32 2c 34 2e 35 2c 30 2e
30 30 32 2c 33 33 33 33 33 33 33 33 33 2e 33 33
33 33 33 33 33 5d 2c 22 73 74 72 69 6e 67 22 3a
22 5c 75 30 30 30 66 c2 be 2f 5c 22 5c 5c 5c 6e
22 2c 22 f0 9f 98 80 22 3a 31 2c 22 ef ac b3 22
3a 32 7d
The SHA-256 hash of those octets is:
afbc268398163c4f856a4d881d1eb85ba85b85e609c8473a11ebaf56cf28a0d1
Srivastava Expires 14 April 2027 [Page 53]
Internet-Draft learnlog October 2026
Appendix B. Implementation Status
This section is to be removed before publishing as an RFC.
This section records the status of known implementations at the time
of writing, as described in [RFC7942].
The following description of qlm-measure version 0.7.0 is retained
from revision -00. It is an earlier implementation and does not
establish conformance to this revision. qlm-measure version 0.7.0
(Quantum Learning Machines; TypeScript and Python; Apache 2.0
license; https://github.com/QuantumLearningMachines/qlm-measure)
writes and verifies records that it labels schema 0.3. This document
was derived from that format. Both chain entries by hash and allow
an event to be redacted. Both place consent events in the chain.
The differences are:
* The recorder of qlm-measure serializes hashed values with sorted
member names. Its documentation lists [RFC8785] for schema 0.3 as
planned.
* A record has no header. The first entry links to an empty string.
No hash covers the studentScopeId member, which names the learner
of the record.
* Events carry no salt.
* A record can hold attestations that refer to an entry by version
or by hash. The verifier checks that reference and a payload
hash. No signature is verified.
* Member names differ. For example, qlm-measure uses version and
prevHash where this document uses seq and prev_hash.
* The kind of scaffold is a member of an observation event. No
event type exists for a request for help or for a scaffold.
Quantum Learning Machines plans to extend qlm-measure so that it
writes records in the format of this document.
A local Learnlog AI Use Profile v0.1.0 prototype adds proposed
context fields, condition-assessment sidecars, two entirely synthetic
examples, and a Python reference checker. It checks a subset
consisting of contained, unsigned SHA-256 records without redaction
or truncation and the example-profile constraints. It does not
verify signatures, establish full CDDL conformance, or implement
runtime context-update and capture-completion events. The examples
contain no participant observations or learning-effect measurements.
Srivastava Expires 14 April 2027 [Page 54]
Internet-Draft learnlog October 2026
The prototype is not an independent implementation or an
interoperability result. No public publication location is specified
in this revision.
Appendix C. Changes in Revision -01
This section is to be removed before publishing as an RFC.
* Add prospective motivation for interpretable learning and
assessment records when AI supplies assistance.
* Clarify that judgments about research applicability are outside
the core format.
* Add non-normative companion-profile guidance for activity stage,
scoped pedagogical permission, planned and asserted observation
coverage, capture gaps, context changes, and review status.
* Add a hypothetical metacognitive prompt versus supplied-
explanation example using the existing assist members.
* Clarify the distinction between recorder and producing-model
provenance and the limits of configuration hashes and
deterministic validation.
* Identify the need for explicit xAPI and Caliper mappings and
describe the limited local synthetic profile prototype.
* Leave all existing CDDL, sourcecode examples, integrity rules,
registries, and test vectors unchanged.
Appendix D. Open Issues
This section is to be removed before publishing as an RFC.
* The name of the format is open.
* [RFC8785] is an Informational RFC from the Independent Submission
stream. A normative reference to it from a Standards Track
document is a downward reference. The alternative is to define
the canonical form in this document. [RFC2104] is Informational
as well.
* JSON text sequences follow Section 11.2 of [QLOG]. JSON objects
separated by line feeds are an alternative.
Srivastava Expires 14 April 2027 [Page 55]
Internet-Draft learnlog October 2026
* Signed heads use JWS with ES256. Open points are explicit typing
of the JWS, a second algorithm, key discovery, and whether COSE
would serve better.
* A defined way to lodge heads with a third party would address
Section 10.2 and Section 10.4.
* A sequential file holds one record. A server that writes for many
learners may want to mix records in one file.
* Every event repeats its session and activity. Section 7.5 of
[QLOG] lets a trace state such values once, as common fields. An
equivalent here would have to fit the rule that each event is
hashed by itself.
* The assist and dialog namespaces are small. Feedback on a
response and questions put to the learner are candidates for
generic event types. The values of ScaffoldType may belong in a
registry.
* The roles instructor and assistant separate parties by teaching
responsibility. Deployments may need finer roles.
* The consent scopes are a starting point.
* A reader ignores members that this document does not define, and
outside a header, an event, or a head no hash covers them. A
stricter rule may be safer.
* The content_hash and config_hash members carry no salt
(Section 10.7).
* A producer cannot yet state in the chain which entries it
redacted. Such a statement would let a reader tell a redaction by
the producer from one by a later holder (Section 10.3).
* No hash covers the list of event schemas (Section 10.8). The
header or an event could carry the list.
* A subject identifier cannot differ by recipient (Section 11.1).
* A record cannot change its hash algorithm. A way to continue a
record in a new one may be needed.
* Mappings between learnlog events and xAPI statements or Caliper
events, including assistance semantics, provenance, and
information loss.
Srivastava Expires 14 April 2027 [Page 56]
Internet-Draft learnlog October 2026
* Independent review and implementation of companion-profile
requirements for scoped assistance permission and observation
coverage, including explicit context changes and completion
claims.
* A companion format for estimates that refer to entries.
Author's Address
Kumar Srivastava
Quantum Learning Machines
Email: kumar@quantumlearningmachines.com
Srivastava Expires 14 April 2027 [Page 57]