PALA-1: A Tamper-Evident Audit Record Format for Constrained and Disconnected Deployments
draft-sparysh-pala-audit-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) | |
|---|---|---|---|
| Authors | Andrii Sparysh , Oleksandr Verteletskyi | ||
| Last updated | 2026-10-02 | ||
| 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-sparysh-pala-audit-01
Network Working Group A. Sparysh
Internet-Draft O. Verteletskyi
Intended status: Informational Assault Consulting
Expires: 5 April 2027 2 October 2026
PALA-1: A Tamper-Evident Audit Record Format for Constrained and
Disconnected Deployments
draft-sparysh-pala-audit-01
Abstract
This document describes PALA-1 -- version 1 of the Portable Append-
only Log for Audit -- a compact binary record format for tamper-
evident audit trails produced by AI inference runtimes and robotic
control systems. It is designed for a class of deployment defined by
three constraints that hold together: the hardware is computationally
modest and its cycles are reserved for the workload and the power
budget rather than for the audit trail; no external witness is
reachable, whether because policy forbids outbound contact or because
the platform operates beyond connectivity, so a witness is
unavailable by rule or by physics rather than by circumstance; and
the right to verify the trail is separated from the right to read
what it records.
Records form an append-only hash chain. Integrity verification
requires no key material of any kind, inspects no record bodies, and
costs one hash per record rather than one signature. The format
distinguishes three separately answerable questions -- internal
consistency, completeness against an external anchor, and existence
at a point in time against an external witness -- and states which of
the three a given trail actually supports rather than implying all
three.
The format is frozen at version 1.0 and is described here as it is.
This document presents an existing wire format; it does not revise
one. Where a deployment does permit an external witness, a chain
head may be published to a transparency service such as that of the
Supply Chain Integrity, Transparency, and Trust architecture (SCITT,
RFC 9943); that path is described but is not part of the hashing
contract.
Status of This Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 1]
Internet-Draft PALA-1 Audit Records October 2026
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/.
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 5 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.
Table of Contents
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1. The constraints . . . . . . . . . . . . . . . . . . . . . 3
1.2. What the constraints force . . . . . . . . . . . . . . . 4
1.3. On COSE . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.4. Scope . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5. A note on regulation . . . . . . . . . . . . . . . . . . 6
1.6. Terminology . . . . . . . . . . . . . . . . . . . . . . . 6
2. Record layout . . . . . . . . . . . . . . . . . . . . . . . . 7
2.1. Fixed header -- 156 bytes . . . . . . . . . . . . . . . . 7
2.2. TLV extensions . . . . . . . . . . . . . . . . . . . . . 8
2.3. body_len -- exactly what it counts . . . . . . . . . . . 10
2.4. File container . . . . . . . . . . . . . . . . . . . . . 10
3. Record types . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1. Spans are two records . . . . . . . . . . . . . . . . . . 11
3.2. AGGREGATE body schema . . . . . . . . . . . . . . . . . . 12
3.3. SHED is in the never-shed class . . . . . . . . . . . . . 13
3.4. Profiles . . . . . . . . . . . . . . . . . . . . . . . . 13
4. Recording at the dispatch boundary . . . . . . . . . . . . . 14
5. Chain rules . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.1. Linking . . . . . . . . . . . . . . . . . . . . . . . . . 15
5.2. Genesis and boots . . . . . . . . . . . . . . . . . . . . 15
5.3. Merkle aggregation . . . . . . . . . . . . . . . . . . . 16
5.4. Bodies, encryption and crypto-shredding . . . . . . . . . 17
Sparysh & Verteletskyi Expires 5 April 2027 [Page 2]
Internet-Draft PALA-1 Audit Records October 2026
6. Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
7. Assurance tiers . . . . . . . . . . . . . . . . . . . . . . . 19
8. Relationship to transparency services . . . . . . . . . . . . 19
9. Verification . . . . . . . . . . . . . . . . . . . . . . . . 22
9.1. Header-only chain verification . . . . . . . . . . . . . 22
9.2. Completeness against an anchor . . . . . . . . . . . . . 24
9.3. Existence against a witness . . . . . . . . . . . . . . . 24
9.4. Semantic checks . . . . . . . . . . . . . . . . . . . . . 25
9.5. Body verification (needs the key) . . . . . . . . . . . . 25
9.6. Forward compatibility . . . . . . . . . . . . . . . . . . 25
10. Test vectors . . . . . . . . . . . . . . . . . . . . . . . . 26
11. Related work . . . . . . . . . . . . . . . . . . . . . . . . 29
12. Relationship to the agent auditing architecture . . . . . . . 31
13. Implementation status . . . . . . . . . . . . . . . . . . . . 33
14. Security considerations . . . . . . . . . . . . . . . . . . . 36
15. IANA considerations . . . . . . . . . . . . . . . . . . . . . 37
16. References . . . . . . . . . . . . . . . . . . . . . . . . . 37
16.1. Normative References . . . . . . . . . . . . . . . . . . 37
16.2. Informative References . . . . . . . . . . . . . . . . . 38
Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . . 42
Changes from draft-sparysh-pala-audit-00 . . . . . . . . . . . . 42
Contributors . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 43
1. Introduction
An AI inference runtime executing on a workstation, an edge device,
or a robot produces a sequence of events that someone may later need
to reconstruct: what was asked, what was answered, which tools were
dispatched, what came back, and what the operator did about it.
A growing body of work addresses this by making a record transparent:
the producer signs a statement, registers it with an external service
maintaining an append-only log, and receives a receipt proving
registration [RFC9943]. Where that construction is available it
answers questions this format cannot answer alone, and this document
describes how to reach it (Section 8).
It presupposes two things: that cycles are available to sign each
record, and that a witness is reachable. This document addresses the
deployments where neither holds.
1.1. The constraints
Three constraints defined this format. They are stated first because
every subsequent decision follows from them, and a reader who rejects
them will reject the format.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 3]
Internet-Draft PALA-1 Audit Records October 2026
*C1 -- the hardware is modest, and its cycles are reserved for the
workload and the power budget.* The target is a control system or an
inference runtime on commodity or embedded hardware, frequently one
that carries its own power. A trail that writes thousands of records
in a session cannot spend an asymmetric signature on each one: that
cost is taken directly from the workload the device exists to run,
and on a self-powered platform it is taken from endurance as well.
The usual answer to a compute constraint -- provision a faster
processor -- does not resolve the second of those, since a faster
processor draws more. Integrity therefore has to come from hashing a
chain, not from signing a record.
*C2 -- no external witness is reachable.* This is not a network that
happens to be down. It is either a regime under which reaching an
external service is not permitted, or a platform operating beyond
connectivity by the nature of its task; in both cases the witness is
unavailable *by rule or by physics*, and no engineering effort
changes it. The distinction from C1 matters: C1 is a constraint that
better hardware partly relaxes over time, while C2 does not relax at
all. Any design that requires a service to be reachable before a
record is trustworthy is inapplicable here, not merely inconvenient.
*C3 -- the right to verify is separated from the right to read.* An
auditor may be entitled to establish that a trail is intact and
complete while holding no clearance for what the trail records. This
is an access regime, not a privacy preference, and it makes
"verification requires reading the records" an unsatisfiable
requirement rather than an acceptable cost.
1.2. What the constraints force
Each of the following is a consequence, not a preference.
From C1: the chain hash covers a fixed-length record header, one hash
per record, no asymmetric operation on the write path.
From C1 and C3 together: because there is no per-record signature,
there is no per-record signature to check, and integrity verification
consequently needs no key material at all. A verifier reads headers,
reports that a million records contain no break, and has read none of
the bodies. The header is fixed-length so that it can be scanned and
sought without parsing a variable structure.
From C3: bodies are bound into the chain by a digest carried inside
the header, so a body may be encrypted, or its key destroyed, while
the chain continues to verify. Key destruction is an ordinary
lifecycle operation in such a deployment rather than an exceptional
one.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 4]
Internet-Draft PALA-1 Audit Records October 2026
From C2: existence in time is never asserted by the format on its own
authority. Where a deployment does permit publication, the claim is
made after the fact by a record naming an explicit range and a
witness, and a verifier reports the witnessed range and the
unwitnessed remainder separately (Section 8). A trail that has never
been witnessed says so.
And from all three: the format is binary and has no canonicalisation
step, because a canonicalisation step is a place where two conforming
implementations can disagree about the bytes being hashed. A JSON
canonicalisation such as [RFC8785] serialises numbers through double
semantics, and a nanosecond wall-clock value exceeds the largest
integer a double represents exactly, so its canonical form is lossy.
The available workarounds -- the value as a string, truncation to
milliseconds -- each trade the property JSON was chosen for against
the one property this format cannot trade: byte-exact agreement
between independent implementations. Inspectability is recovered by
a converter, which is a tool and not part of the hashing contract.
1.3. On COSE
The question this section exists to answer is why the records are not
COSE_Sign1 [RFC9052] structures, given that CBOR encodes a nanosecond
integer exactly and is not subject to the objection above.
The objection above is to JSON canonicalisation, and it does not
apply to CBOR. A CBOR encoding could carry the same chain semantics
this document defines, and an implementer who values ecosystem
alignment over the constraints of Section 1.1 should consider that a
reasonable design.
What C1 and C3 exclude is not the encoding but the envelope.
COSE_Sign1 places a signature on each record and a verification key
in the hands of anyone checking one. Both are intrinsic to what a
single-signer signature envelope is, not parameters of it, and both
are the two properties C1 and C3 rule out. A signature per record is
the cost C1 forbids; a key required to verify is the dependency C3
forbids.
The trade-off applies in both directions and is stated here rather
than left for a reader to find. A COSE_Sign1 record is self-
sufficient: it carries its own evidence, and one such record proves
something on its own. A PALA-1 record proves nothing on its own --
the sequence is what carries the evidence, and a single record
removed from its chain is inert. For deployments that write few
records, are not compute-constrained, and need per-record self-
sufficiency, the envelope is the better choice and this format is the
wrong tool.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 5]
Internet-Draft PALA-1 Audit Records October 2026
Where the two meet is Section 8: a chain head expressed as a Signed
Statement is a COSE_Sign1 structure, so the envelope is used exactly
where its cost is paid once rather than per record.
1.4. Scope
In scope: the byte layout of a record, the rules linking records into
a chain, the aggregation of record digests, the encoding of assurance
claims, and a normative verification procedure any party can
implement from this document alone.
Out of scope: agent-to-agent protocols, authorization decisions,
policy evaluation, transport, and the internal protocol of any
witness. This document records what a runtime did. It does not
decide what a runtime may do, and it makes no claim about the honesty
of the runtime at the moment of recording (Section 14).
1.5. A note on regulation
The constraints of Section 1.1 arose in deployments that are also
subject to record-keeping, data-minimisation and erasure obligations,
and those obligations shaped what the format was required to support:
that a trail can be verified without disclosing its contents, and
that a record's content can be destroyed without falsifying the trail
it sits in.
No claim is made that this format satisfies any legal obligation.
Regulations of this kind do not prescribe formats, and a format
cannot discharge a duty that falls on an operator. The relationship
is only that a set of obligations produced a set of technical
requirements, and this document specifies a format meeting them.
1.6. Terminology
PALA stands for Portable Append-only Log for Audit. _Portable_: a
PALA-1 log verifies on any machine, offline, with no key material.
_Append-only_: records are only ever added to a hash chain. _For
audit_: that is its purpose. The expansion is descriptive and has no
normative effect.
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.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 6]
Internet-Draft PALA-1 Audit Records October 2026
2. Record layout
A record is header || body. The body may be empty.
2.1. Fixed header -- 156 bytes
+========+======+================+=======+=====================+
| Offset | Size | Field | Type | Notes |
+========+======+================+=======+=====================+
| 0 | 4 | magic | bytes | PALA (0x50 0x41 |
| | | | | 0x4C 0x41) |
+--------+------+----------------+-------+---------------------+
| 4 | 2 | format_version | u16 | 1 |
+--------+------+----------------+-------+---------------------+
| 6 | 2 | header_len | u16 | 156 + TLV bytes. |
| | | | | Total header |
| | | | | length. |
+--------+------+----------------+-------+---------------------+
| 8 | 2 | record_type | u16 | Section 3 |
+--------+------+----------------+-------+---------------------+
| 10 | 1 | assurance_tier | u8 | Section 7 |
+--------+------+----------------+-------+---------------------+
| 11 | 1 | time_trust | u8 | Section 6 |
+--------+------+----------------+-------+---------------------+
| 12 | 8 | seq | u64 | Monotonic within a |
| | | | | chain. Never |
| | | | | reused. |
+--------+------+----------------+-------+---------------------+
| 20 | 16 | boot_id | bytes | Opaque, unique per |
| | | | | boot |
+--------+------+----------------+-------+---------------------+
| 36 | 32 | prev_hash | bytes | record_hash of the |
| | | | | previous record |
+--------+------+----------------+-------+---------------------+
| 68 | 16 | span_id | bytes | Zero if not span- |
| | | | | scoped |
+--------+------+----------------+-------+---------------------+
| 84 | 16 | parent_span_id | bytes | Zero = root |
+--------+------+----------------+-------+---------------------+
| 100 | 8 | monotonic_ns | u64 | Since boot. Never |
| | | | | wall-clock. |
+--------+------+----------------+-------+---------------------+
| 108 | 8 | wall_clock_ns | i64 | Nanoseconds since |
| | | | | Unix epoch, or 0 |
+--------+------+----------------+-------+---------------------+
| 116 | 4 | key_id | u32 | 0 = no body, or a |
| | | | | cleartext body. |
| | | | | Section 5.4 |
Sparysh & Verteletskyi Expires 5 April 2027 [Page 7]
Internet-Draft PALA-1 Audit Records October 2026
+--------+------+----------------+-------+---------------------+
| 120 | 4 | body_len | u32 | Section 2.3 |
+--------+------+----------------+-------+---------------------+
| 124 | 32 | body_digest | bytes | SHA-256 [FIPS180-4] |
| | | | | of the body bytes, |
| | | | | or 32 zero bytes if |
| | | | | body_len = 0 |
+--------+------+----------------+-------+---------------------+
Table 1
All multi-byte integers little-endian. No padding. header_len MUST
be >= 156 and MUST equal the actual number of header bytes.
2.2. TLV extensions
Immediately after the fixed header, until header_len is reached:
type: u16 | length: u16 | value: <length> bytes
A TLV item MUST NOT overrun header_len. The last item MUST end
exactly at header_len.
*Unknown TLV types MUST be hashed and MUST NOT cause rejection.* They
are opaque bytes to a verifier that does not know them. This is what
makes Section 9.5 possible.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 8]
Internet-Draft PALA-1 Audit Records October 2026
+========+======================+===============================+
| Type | Name | Value |
+========+======================+===============================+
| 0x0001 | ORIGIN_ROLE | UTF-8 role of the emitting |
| | | component, e.g. planner.main; |
| | | vocabularies are profile- |
| | | defined (Section 3.4) |
+--------+----------------------+-------------------------------+
| 0x0002 | ORIGIN_MODEL_DIGEST | 32 bytes |
+--------+----------------------+-------------------------------+
| 0x0003 | ORIGIN_CONFIG_DIGEST | 32 bytes |
+--------+----------------------+-------------------------------+
| 0x0011 | MERKLE_TREE_HASH | 32 bytes |
+--------+----------------------+-------------------------------+
| 0x0012 | MERKLE_LEAF_COUNT | u32 |
+--------+----------------------+-------------------------------+
| 0x0020 | SHED_CLASS | u16 |
+--------+----------------------+-------------------------------+
| 0x0021 | SHED_COUNT | u32 |
+--------+----------------------+-------------------------------+
| 0x0022 | SHED_WINDOW_NS | u64 |
+--------+----------------------+-------------------------------+
| 0x0030 | WITNESS_KIND | u16 -- 1 = transparency log, |
| | | 2 = [RFC3161] TSA |
+--------+----------------------+-------------------------------+
| 0x0031 | WITNESS_RANGE_LO | u64 |
+--------+----------------------+-------------------------------+
| 0x0032 | WITNESS_RANGE_HI | u64 |
+--------+----------------------+-------------------------------+
| 0x0033 | WITNESS_RECEIPT | opaque |
+--------+----------------------+-------------------------------+
| 0x0040 | SHRED_KEY_ID | u32 |
+--------+----------------------+-------------------------------+
| 0x0050 | ANCHOR_HEAD | 32 bytes -- the head written |
| | | to the anchor store. |
| | | Section 9.2 |
+--------+----------------------+-------------------------------+
Table 2
*TLV type numbers and record type numbers are separate namespaces.*
TLV 0x0011 MERKLE_TREE_HASH and record type 0x0020 MERKLE both
concern Merkle aggregation and are different numbers in different
spaces. The names are kept distinct for that reason; do not read one
table with the other's numbers.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 9]
Internet-Draft PALA-1 Audit Records October 2026
*origin is three TLVs, not a name.* (ORIGIN_ROLE,
ORIGIN_MODEL_DIGEST, ORIGIN_CONFIG_DIGEST) -- because the first
question after an incident is which weights produced an output, and a
component name alone does not answer it. A model update is a
different origin and the chain shows it.
2.3. body_len -- exactly what it counts
*body_len is the total number of bytes following the header, up to
the start of the next record.* A reader that consumes body_len
bytes after header_len has consumed the whole body and nothing
else.
For an encrypted body (Section 5.4) that total covers nonce ||
ciphertext || tag -- the nonce is *inside* the count, not additional
to it. body_digest is taken over exactly those body_len bytes.
This is stated explicitly because it is the most likely implementer
error: a reader that treats the 12-byte nonce as a prefix outside
body_len truncates the GCM tag, fails to decrypt, and attributes the
failure to the cipher.
2.4. File container
A log file is records *concatenated back-to-back, with no file
header, no framing, and no trailing metadata*. The first record
starts at byte 0.
A reader finds record boundaries from the records themselves: read
the fixed header at the current offset, confirm magic, take
header_len and body_len, and the next record begins at offset +
header_len + body_len. A file whose final record ends exactly at
end-of-file is well-formed; anything else is a truncated tail and
MUST be reported as such (it is not a chain break at any earlier
record).
There is deliberately nothing else at file level. A file header
would be one more thing to version, and the records are already self-
delimiting; rotation, segmentation and naming are storage concerns
outside this format -- a segment boundary is invisible to the chain,
which continues across files exactly as it continues across boots.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 10]
Internet-Draft PALA-1 Audit Records October 2026
3. Record types
+========+============+==============+===========================+
| Value | Name | Class | Meaning |
+========+============+==============+===========================+
| 0x0001 | GENESIS | never-shed | Chain origin. |
| | | | Section 5.2 |
+--------+------------+--------------+---------------------------+
| 0x0002 | BOOT | never-shed | New boot. Its prev_hash |
| | | | *is* the cross-boot link. |
+--------+------------+--------------+---------------------------+
| 0x0010 | SPAN_START | normal | Opens a span |
+--------+------------+--------------+---------------------------+
| 0x0011 | SPAN_END | normal | Closes it. Section 3.1 |
+--------+------------+--------------+---------------------------+
| 0x0012 | EVENT | normal | Point event. Payload |
| | | | semantics are profile- |
| | | | defined (Section 3.4). |
+--------+------------+--------------+---------------------------+
| 0x0020 | MERKLE | sheddable | Digest aggregation over a |
| | | | window. Section 5.3 |
+--------+------------+--------------+---------------------------+
| 0x0021 | AGGREGATE | sheddable | Tier 0 statistics over a |
| | | | window. Section 3.2 |
+--------+------------+--------------+---------------------------+
| 0x0030 | SHED | *never-shed* | Records that records were |
| | | | dropped. Section 3.3 |
+--------+------------+--------------+---------------------------+
| 0x0040 | SAFETY | *never-shed* | Written by the safety |
| | | | path; the audit only |
| | | | observes |
+--------+------------+--------------+---------------------------+
| 0x0050 | ANCHOR | never-shed | Local anchor written. |
| | | | Section 9.2 |
+--------+------------+--------------+---------------------------+
| 0x0051 | WITNESS | never-shed | External witness receipt. |
| | | | Section 7 |
+--------+------------+--------------+---------------------------+
| 0x0060 | KEY_SHRED | never-shed | A key was destroyed. |
| | | | Section 5.4 |
+--------+------------+--------------+---------------------------+
Table 3
3.1. Spans are two records
SPAN_START and SPAN_END are separate chained records. Duration is
derived at read time.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 11]
Internet-Draft PALA-1 Audit Records October 2026
The alternative -- one record written on close -- loses exactly the
case that crashed. *A crash must leave a visibly unclosed span*,
because that is the evidence.
This also fixes the limit of the whole design: the audit *cannot*
guarantee a record precedes the action it describes -- that would
require blocking, which the architecture forbids. It guarantees only
that *absence is visible*: the property provided is detectable
absence, not write-ahead semantics.
3.2. AGGREGATE body schema
Tier 0 statistics are not personal data, so an AGGREGATE body SHOULD
be cleartext (key_id = 0). Encrypting it would only make the post-
market monitoring export useless to the party entitled to read it.
The body is a TLV sequence, encoded exactly as Section 2.2, in its
*own type namespace*. The core defines the window framing; the
measured quantities are profile-defined:
+=========+===================+===================================+
| Type | Name | Value |
+=========+===================+===================================+
| 0x0001 | AGG_WINDOW_NS | u64 -- length of the aggregation |
| | | window. *Core.* |
+---------+-------------------+-----------------------------------+
| 0x0002 | AGG_SAMPLE_COUNT | u32 -- samples folded into this |
| | | record. *Core.* |
+---------+-------------------+-----------------------------------+
| 0x0003+ | _profile-defined_ | Allocated upward from 0x0003 by |
| | | the chain's profile (Section 3.4) |
+---------+-------------------+-----------------------------------+
Table 4
A reader treats body tags it does not know as opaque -- reported,
never rejected -- the same posture Section 9.6 takes for the header.
Because one chain follows exactly one profile (Section 3.4), profile
allocations cannot collide within a chain.
*Milli-units, not floats -- a constraint on profiles.* A float in a
body reintroduces exactly the cross-implementation disagreement
Section 1.1 rejects JSON for -- and it would do so in the one record
type whose whole purpose is being comparable across versions and
vendors. A profile MUST express fractional quantities as fixed-point
integers (milli-, micro-). Fixed-point integers carry no cross-
implementation ambiguity.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 12]
Internet-Draft PALA-1 Audit Records October 2026
The framing is defined here rather than left to implementations
because AGGREGATE is the PMM instrument: a wholly undefined body
means two conformant implementations produce incomparable exports,
which defeats the record type. The core fixes the window; each
profile fixes the quantities -- so two implementations of the _same
profile_ are comparable. The robotics profile published with the
specification [PALA-SPEC] defines optical-flow statistics at
0x0003-0x0005.
3.3. SHED is in the never-shed class
The audit never blocks the execution path. Therefore records are
dropped under saturation, and *which* records is a design decision,
not an accident.
A dropped record is survivable. A *silently* dropped record is a log
that misrepresents by omission, which is worse than no log. SHED
carries class, count and window, and it is never itself shed.
3.4. Profiles
The envelope must outlive any one domain, so the split is structural:
this document defines everything a verifier needs -- layout, chain,
tiers, time, cryptography, the three questions -- and *profiles*
define what the records are _about_. A profile is a companion
document that fixes, for one domain:
* *EVENT payload semantics* -- what lives in the bodies;
* *AGGREGATE quantities* -- body tags from 0x0003 upward
(Section 3.2);
* *MERKLE leaf source* -- what the aggregated digests are digests
_of_, and at what rate (Section 5.3);
* *ORIGIN_ROLE vocabulary* -- the component names that appear in
headers.
*One chain follows exactly one profile.* Which profile is a property
of the deployment, stated by the emitting system's documentation; the
format does not carry a profile identifier in version 1 (a chain's
ORIGIN_ROLE vocabulary makes it evident in practice, and adding a
field is a v1.0 freeze decision, not a retrofit). Mixing profiles
within one chain is out of scope.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 13]
Internet-Draft PALA-1 Audit Records October 2026
*Verification is profile-independent.* Every check in Section 9 reads
the envelope only; a verifier needs no profile knowledge to answer
the three questions, and profile content it does not understand is
opaque bytes -- reported, never rejected (Section 3.2, Section 9.6).
Two profiles are published with the specification [PALA-SPEC]: a
robotics profile -- the first, and the one the committed test vectors
follow -- and an inference profile, under which the reference
implementation audits its own serving loop.
4. Recording at the dispatch boundary
This section is informative and describes an emitter obligation that
the record types of this document are shaped to support.
A hash chain constrains the relationship between records. On its own
it does not constrain _when_ a record was written relative to the
event it describes. A producer could execute an entire session and
afterwards emit a chain that is internally consistent, verifies
correctly, and records only what the producer chose to say about
itself. Such a trail is conformant and evidentially weak, and the
distinction matters wherever the question is whether a control
actually operated.
The record types here are designed so that a conforming emitter does
not have that freedom in the one place it matters most: the tool-
dispatch boundary, where an inference runtime causes an effect
outside itself.
A tool call is recorded when the call is handed to its executor,
before any result is known. The result is recorded as a separate
record bound by digest to the call it answers, so an attempt cannot
be presented as a completion. On shutdown, a call with no recorded
outcome is explicitly cancelled in the chain, so a reader never
encounters a dispatch whose fate is unstated. Span-structured events
are two records -- one at open, one at close -- for the same reason.
The consequence a verifier can rely on: for every dispatch in a
conforming trail there is a record written before the outcome
existed, and every such record has a stated fate. What no format can
supply is an assurance that the emitter obeyed this. That is a
property of the implementation, which is why the verification
procedure treats an unpaired dispatch as an advisory finding to be
surfaced rather than silently tolerated, and why independent
implementations of this document are the evidence that matters
(Section 13).
Sparysh & Verteletskyi Expires 5 April 2027 [Page 14]
Internet-Draft PALA-1 Audit Records October 2026
A second limit is stated for the same reason. An emitter can record
only the dispatches it mediates as structured data. A client that
negotiates tool use with the model in free text and executes the
result locally produces no dispatch at the emitter's boundary, and
therefore no record; the reference implementation measured this with
a widely used agent client and documents it as a visibility limit
rather than concealing it (Section 13). A trail's silence about tool
use is evidence of what the emitter observed, not of what the client
did.
5. Chain rules
5.1. Linking
record_hash(r) = SHA-256(header_bytes(r))
r.prev_hash = record_hash(previous record)
seq MUST increase by exactly 1 within a chain. *A gap in seq is a
break, whether or not the hashes link*, and a verifier MUST report it
as one (Section 9.1).
The rule is not redundant with the hash link. An actor holding the
key can rebuild a shorter, perfectly linked chain that omits a range
of seq; the hashes will chain and only the gap reveals it.
5.2. Genesis and boots
* GENESIS has prev_hash = 32 zero bytes *and* record_type = GENESIS.
A distinguished type is required so that _"no predecessor"_ and
_"predecessor removed"_ are distinguishable. prev_hash = 0 alone
is not sufficient.
* A verifier MUST report as a *violation* any chain whose first
record is not a GENESIS (the record is the wrong kind; the links
around it may be perfectly sound), and MUST report a GENESIS at
any position other than the first as a violation. Defining the
type and then not checking it adds nothing.
* *A BOOT record's prev_hash is the previous boot's head.* The chain
is continuous across power cycles; a deleted segment leaves a head
nothing references.
*What this does not fix -- stated in the format, not hidden in
prose:* an owner with the key can start a _new_ GENESIS and present
the device as new. Chain continuity cannot prove device continuity.
Only Section 7 addresses that, and only partly.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 15]
Internet-Draft PALA-1 Audit Records October 2026
5.3. Merkle aggregation
High-rate digests are aggregated per window into one MERKLE record --
the digest *source* and rate are profile-defined (Section 3.4): the
robotics profile folds a second of sensor-frame digests into one
record; an inference profile might fold a batch of token or KV-
operation digests. The tree is the same either way.
[RFC6962] tree hash, domain-separated:
leaf(d) = SHA-256(0x00 || d)
node(l, r) = SHA-256(0x01 || l || r)
empty = SHA-256("")
*An unpaired node is PROMOTED, never duplicated.* Duplicating the
last node is the CVE-2012-2459 mistake: two distinct leaf sets
collapse to the same root.
An *inclusion proof* for a leaf is the list of sibling hashes on the
path from that leaf to the root, each tagged with the side the
sibling occupies: an entry ["L", s] means the sibling is the *left*
operand of node() -- the step computes node(s, h) -- and ["R", s]
computes node(h, s). Folding the leaf's leaf() hash through the
entries in order MUST reproduce the tree hash. This is the encoding
the published vectors use for the inclusion proof [PALA-VECTORS].
Two constructions are in circulation and they agree, which is worth
stating so an implementer does not go looking for a discrepancy: RFC
6962 defines the tree recursively, splitting at the largest power of
two below n; the iterative bottom-up form that promotes an unpaired
node yields the same root. Either may be implemented.
This provides *selective disclosure*: one leaf can be proven with
about log2(n) hashes without revealing the other n-1 -- one moment,
without the rest of the window.
*The count is a commitment, verified against the leaves -- never in
the header.* MERKLE_LEAF_COUNT states how many leaves the root
covers. Because the MERKLE record does not carry the leaves, only a
party that has them -- checking a disclosure, or holding the full set
-- can confirm it, and such a verifier SHOULD check that the number
of leaves equals MERKLE_LEAF_COUNT and reject a disclosure whose
count disagrees. A mismatch is a defect of that disclosure, not a
chain violation: the header and its chain are intact; what was
revealed is inconsistent with what was committed. A header-only
verifier (Section 9.1) neither has the leaves nor checks the count.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 16]
Internet-Draft PALA-1 Audit Records October 2026
5.4. Bodies, encryption and crypto-shredding
A body is one of two shapes, and key_id says which:
+========+====================================+
| key_id | Body |
+========+====================================+
| 0 | Absent (body_len = 0), or |
| | *cleartext*: body is the raw bytes |
+--------+------------------------------------+
| != 0 | *Encrypted*: body = nonce (12) |
| | \|\| ciphertext \|\| tag (16) |
+--------+------------------------------------+
Table 5
In both cases body_digest = SHA-256(body_bytes) over exactly body_len
bytes. The digest does not know which shape it covered -- which is
why crypto-shredding does not disturb it.
Body encryption is *AES-256-GCM* [SP800-38D].
nonce = 4 zero bytes || seq (u64 LE)
aad = seq (u64 LE) || boot_id (16) || record_type (u16 LE)
ciphertext = AES-256-GCM(K[key_id], nonce, plaintext, aad)
body = nonce || ciphertext || tag
body_digest= SHA-256(body)
The AAD binds the ciphertext to its position in the chain: bodies
cannot be swapped between records.
*The nonce is derived from seq, not random.* A random 96-bit nonce is
not safe past ~2^32 records under one key -- a horizon a sustained
high-rate writer actually reaches within the ten-year lifetime this
format must survive (a 30 Hz emitter crosses it in under five years;
higher rates get there sooner). A seq-derived nonce is unique per
record by construction -- seq never repeats within a chain
(Section 5.1) -- and its only leak is the record's position, which
the cleartext header states anyway. A key MUST NOT be reused across
chains with independent seq spaces.
*Order of operations is normative* (it is otherwise circular): 1.
encrypt -> 2. compute body_digest -> 3. fill the header -> 4.
record_hash.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 17]
Internet-Draft PALA-1 Audit Records October 2026
*Crypto-shredding.* Keys live outside the log, addressed by key_id.
Erasure = destroying K[key_id]; a KEY_SHRED record notes it. The
body becomes noise, body_digest stays, the chain still verifies. A
verifier reports _"record exists, body unreadable"_ -- a reported
condition, not a gap in the chain.
*Shred granularity equals key granularity, and that is a deployment
decision, not a format one.* Per subject, per session, per day -- the
format only requires that key_id exists and that destroying a key
breaks nothing structural.
*key_id scope is one device.* 2^32 keys is ample per device and
ambiguous across a fleet: two devices may both use key_id = 7 for
unrelated keys. A fleet key-management layer MUST qualify key_id
with a device identity of its own; the format does not carry one.
6. Time
A device without a battery-backed real-time clock boots with its wall
clock at the Unix epoch, and network time synchronisation is
unavailable under C2. Therefore:
* *monotonic_ns and seq are authoritative for ordering.* Always
present.
* *wall_clock_ns is advisory* and always accompanied by time_trust:
+============+=================================================+
| time_trust | Meaning |
+============+=================================================+
| 0 | UNKNOWN -- wall_clock_ns MUST be 0 |
+------------+-------------------------------------------------+
| 1 | UNSYNCED -- free-running, no external reference |
+------------+-------------------------------------------------+
| 2 | HW_RTC -- battery-backed clock, unverified |
+------------+-------------------------------------------------+
| 3 | NTP_SYNCED -- externally synchronised |
+------------+-------------------------------------------------+
Table 6
Values above 3 are undefined in version 1. A verifier MUST report a
record whose time_trust is UNKNOWN with a non-zero wall_clock_ns as a
violation (Section 9.1): an unenforced requirement is not a
requirement, and this one separates an explicit statement that the
time is unknown from a timestamp that cannot be justified. The first
can be defended; the second cannot.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 18]
Internet-Draft PALA-1 Audit Records October 2026
7. Assurance tiers
The format states how much it can be trusted. It does not overstate.
+======+==============+========================+=================+
| Tier | Mechanism | Proves | Does not prove |
+======+==============+========================+=================+
| *A* | Chain + | A record was modified; | Everything else |
| = 0 | local anchor | with the anchor, that | |
| | | nothing was truncated | |
+------+--------------+------------------------+-----------------+
| *B* | + hardware | Device identity | *Fresh genesis* |
| = 1 | root of | | -- a TPM signs |
| | trust | | any chain |
+------+--------------+------------------------+-----------------+
| *B+* | + monotonic | Counter never returns | Platform-bound |
| = 2 | NV counter | to zero -> fresh | |
| | bound to seq | genesis visible | |
+------+--------------+------------------------+-----------------+
Table 7
*Tier C is deliberately not a header value.*
Tier C -- periodic publication of the chain head to a transparency
log or an [RFC3161] TSA -- proves *existence at time T*, which is the
guarantee that actually defeats a fresh genesis. But a header cannot
honestly claim to have been witnessed _before the witness exists_.
So tier C is asserted *after the fact*, by a WITNESS record covering
a seq range. A verifier reads:
_records 0-9: externally witnessed at 2026-07-16T10:00Z records
10-...: tier A, no existence claim_
*C is strictly stronger than B here*, because fresh genesis is a
question of existence, not identity. Its cost is one published hash,
not data: the model of Certificate Transparency applied to an audit
trail.
8. Relationship to transparency services
This section is informative. It adds no requirement and changes no
byte.
The strongest question this format cannot answer from its own bytes
is existence at a point in time. A chain proves that its records
have not been altered relative to one another. It does not prove
Sparysh & Verteletskyi Expires 5 April 2027 [Page 19]
Internet-Draft PALA-1 Audit Records October 2026
that the chain was not created wholesale after the fact, because a
producer in possession of its own keys can construct a consistent
history at any time. Defeating that requires a party other than the
producer to have observed a commitment, and the observation has to
have happened.
PALA-1 handles this by deferring the claim rather than asserting it.
A witness record covers an explicit range of sequence numbers and
states that the head of that range was published externally. The
record is itself chained, so the claim cannot be inserted
retroactively without breaking the chain, and a verifier reports the
witnessed range and the unwitnessed remainder separately. The
protocol by which the external publication is verified is the
witness's own and is out of scope here.
A SCITT transparency service [RFC9943] is one such witness, and a
natural one where a deployment permits it. A producer takes the
chain head, expresses it as a Signed Statement -- a COSE_Sign1
[RFC9052] whose payload commits to the head by digest -- registers it
with a transparency service, and attaches the returned Receipt -- a
COSE Receipt [RFC9942] -- to the statement's unprotected header,
producing what [RFC9943] calls a Transparent Statement, which is then
carried in the evidence the producer exports. What the producer
publishes is one digest, not the trail: no record body, no personal
data, no model output leaves the device. The envelope's cost is paid
once per published head rather than once per record (Section 1.3),
which is what makes it affordable under C1.
The construction published with the specification [PALA-INTEROP] is
stated here so that it can be checked rather than assumed. The
statement's protected header carries the algorithm, the payload's
content type, a key identifier, and CWT claims for issuer and subject
under the header label registered by [RFC9597].
Two of those values are digests, and they are treated differently on
purpose. The subject names the *full* chain head: a transparency
service indexes by the subject, distinct chains must not collide
under it, and a truncated digest collides at the birthday bound of
whatever length is kept. The key identifier is the COSE Key
Thumbprint of the verification key [RFC9679] *truncated to its first
20 bytes*, which is not a thumbprint and is not claimed to be one.
The asymmetry is deliberate: kid is a hint for locating a key and
[RFC9052] places no collision-resistance duty on it, since presenting
the wrong key simply fails the signature check, whereas the subject
is the identifier by which a relying party decides that two
statements concern the same thing, and nothing downstream catches a
collision there. Truncation is acceptable exactly where a collision
is self-correcting and unacceptable where it is not. The payload is
Sparysh & Verteletskyi Expires 5 April 2027 [Page 20]
Internet-Draft PALA-1 Audit Records October 2026
attached -- a CBOR map of the head, the sequence range and the format
identifier, encoded as CBOR [RFC8949] -- so that the statement is
readable offline, without the service. Section 6 of [RFC9943]
requires the kid header parameter when neither x5t nor x5chain is
present in the protected header; its initial omission was found by a
reproduction of the statement performed under a stated contamination
boundary and was corrected before any registration took place
(Section 13).
Two properties of the envelope bear on what such a statement can be
said to be. First, byte-for-byte reproduction of a statement by an
independent implementation is achievable only when the signature is
deterministic: EdDSA [RFC8032] provides that by construction, whereas
an ECDSA signature is deterministic only as a per-library choice, so
two conforming implementations may emit different signature bytes
over identical input. The published vector therefore uses EdDSA, and
a vector over ECDSA could claim that a statement verifies, not that
it reproduces. Second, a valid signature and the published bytes are
two different facts: content in the unprotected header, the presence
or absence of the outer CBOR tag, a detached payload, or a non-
canonical Ed25519 scalar each yield an artifact with different bytes
over which the signature still verifies. An auditor comparing an
artifact to a published one compares bytes; an auditor accepting a
statement checks the signature; the two checks are not substitutes
for each other. [PALA-INTEROP] enumerates these cases with
executable expectations.
Under C2 this path is closed -- by policy or by the absence of any
reachable service -- and the format is designed so that its closure
costs nothing structural: a trail that is never witnessed is still
verifiable for internal consistency and, against a local anchor, for
completeness. It simply does not claim the third question, and says
so.
Two properties of this arrangement are worth stating plainly, because
the difference between them is the difference between a claim and a
proof.
A verifier that has checked a Receipt against a log key it trusts may
report the covered range as externally witnessed. A verifier that
has not checked one MUST NOT, whatever the trail says about itself.
The overclaim rule that governs every assurance field in this
document governs this one.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 21]
Internet-Draft PALA-1 Audit Records October 2026
And the guarantee itself is bounded. A Receipt establishes that a
commitment was registered, and therefore bounds when the trail can
have been constructed and makes later substitution or omission
detectable. It does not establish that the recorded content is true.
That boundary is not peculiar to this format; it applies to every
construction of this kind, including the transparency service's own.
9. Verification
Verification answers three questions, and they MUST NOT be collapsed
into one boolean. Each needs different inputs and each fails
differently.
+=============================+==============+======================+
| Question | Needs | Answers |
+=============================+==============+======================+
| *Section 9.1 Is what I hold | Nothing | Modification, |
| internally consistent?* | | reordering, |
| | | seq gaps |
+-----------------------------+--------------+----------------------+
| *Section 9.2 Is what I hold | An anchor, | Truncation, |
| all of it?* | from outside | replacement, |
| | the log | rollback |
+-----------------------------+--------------+----------------------+
| *Section 9.3 Did this | A witness | Fresh genesis |
| history exist at time T?* | receipt | |
+-----------------------------+--------------+----------------------+
Table 8
A verifier that reports only Section 9.1 as "ok" is misleading,
because Section 9.1 cannot see a truncated tail: dropping the last N
records leaves a perfectly linked chain with a different head and no
other trace.
9.1. Header-only chain verification
Requires no key. Touches no bodies.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 22]
Internet-Draft PALA-1 Audit Records October 2026
prev := unset # no link expectation yet
expected := unset
for index, header h in file order:
MUST h.magic == "PALA" else break, stop
MUST h.header_len == actual header bytes else violation
if index == 0:
MUST h.record_type == GENESIS else violation
if h.record_type == GENESIS:
MUST h.prev_hash == 32 zero bytes else violation
else:
MUST h.record_type != GENESIS else violation
if prev is set and h.prev_hash != prev: report break at h.seq
if expected is set and h.seq != expected: report gap at h.seq
expected := h.seq + 1
if h.format_version unknown or h.record_type unknown:
report uninterpretable at h.seq # not a break; see below
else:
run semantic checks # violations, not breaks
prev := SHA-256(h.header_bytes)
report: count, breaks, gaps, violations, uninterpretable, head = prev
chain_ok is true iff breaks, gaps and violations are all empty. It
means *internally consistent*, nothing more.
A chain whose first record is not a GENESIS yields exactly *one*
violation -- the wrong _kind_ of first record. Per Section 5.2, the
links around it may be perfectly sound: the zero-prev_hash
requirement applies only when the first record _is_ a GENESIS, and
the break check compares only records that have a predecessor in the
file. (Aligned at the final pre-freeze verification run: read
literally, the earlier pseudocode produced two violations and a
spurious break on this case, contradicting this section's own prose
above and Section 5.2. The published missing-GENESIS demonstration
had not discriminated the two readings -- its input satisfied both --
until that run constructed the discriminating case; the demo input
was strengthened accordingly, with its published outputs unchanged.)
breaks and gaps are reported at the record's seq. Violations from
per-record checks are likewise keyed by seq; the chain-does-not-
start-with-GENESIS violation is reported at position 0, because it is
a property of the chain, not of any record's seq.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 23]
Internet-Draft PALA-1 Audit Records October 2026
9.2. Completeness against an anchor
The anchor is the head this chain is supposed to have, obtained from
*outside the log*: the _current_ head held in the local anchor store
(an OS keychain entry), or the head covered by the newest WITNESS
receipt. An in-chain ANCHOR record with its ANCHOR_HEAD TLV *records
a store write at the time it occurred* -- a historical note, not the
anchor itself. Because a writer may append records after a store
write, the newest ANCHOR record's head can lag the store's current
head; a completeness check therefore uses the *store's current head*,
not any in-chain ANCHOR record's TLV.
Given an anchor A and a computed head H:
+================+===========================================+
| Condition | Report |
+================+===========================================+
| A == H | Complete to the anchor |
+----------------+-------------------------------------------+
| A is the | *Unanchored tail*: anchor_lag = N records |
| record_hash of | past the anchored head. A crash between |
| some record in | write and anchoring, or an anchor-store |
| the chain | outage -- or records appended by a writer |
| | without anchor access. |
+----------------+-------------------------------------------+
| A names no | *Replaced, rolled back, or truncated.* |
| record in the | This is not the history that was |
| chain | anchored. |
+----------------+-------------------------------------------+
Table 9
Both non-matching cases are failures; the diagnosis differs, and the
diagnosis is what an auditor acts on. Without an anchor a verifier
MUST report completeness as _not checked_ -- never as passing.
9.3. Existence against a witness
A WITNESS record asserts that the head of records [RANGE_LO,
RANGE_HI] was published to an external log at some time.
Verification is out of scope for this document -- it follows the
witness's own protocol (a COSE Receipt [RFC9942], a Rekor inclusion
proof, an [RFC3161] token). What this format guarantees is only that
the claim is _in_ the chain, is itself chained, and names its range
explicitly.
A verifier SHOULD report the witnessed range and the unwitnessed
remainder separately (Section 7).
Sparysh & Verteletskyi Expires 5 April 2027 [Page 24]
Internet-Draft PALA-1 Audit Records October 2026
9.4. Semantic checks
On records whose version and type are known -- *GENESIS and BOOT
included*. The position checks Section 9.1 makes at index 0 (the
record is a GENESIS, its prev_hash is zero) are _in addition to_
these, not in place of them: a GENESIS with time_trust = UNKNOWN and
a non-zero wall_clock_ns is as much a violation as any other record.
The checks:
* time_trust == UNKNOWN => wall_clock_ns == 0 (Section 6)
* time_trust <= 3 (Section 6)
* body_len == 0 if and only if body_digest == 32 zero bytes
(Section 2.1)
* key_id != 0 and body_len > 0 => body_len >= 28 (nonce + tag,
Section 5.4)
* TLV items parse and end exactly at header_len (Section 2.2)
These are violations, not breaks: the record is defective, the chain
around it may be sound. They MUST be reported distinctly.
MERKLE_LEAF_COUNT is deliberately *not* among these checks. A MERKLE
record carries the root and the count but never the leaves (body_len
= 0, Section 5.3), so a header-only verifier does not have the leaves
to count and does not treat the field as verifiable here -- it is a
commitment, checked only when the leaves are disclosed. Section 5.3
says how.
9.5. Body verification (needs the key)
SHA-256(body) == header.body_digest, then -- if key_id != 0 -- AES-
256-GCM decrypt with the nonce and AAD of Section 5.4. Failure to
decrypt with a *matching* digest means the key is wrong or destroyed
-- not that the log is corrupt. These MUST be reported distinctly.
9.6. Forward compatibility
A verifier meeting an unknown format_version, record_type or TLV
type:
* *MUST* still chain-verify it -- the hash is over raw bytes
* *MUST* report it as uninterpretable
Sparysh & Verteletskyi Expires 5 April 2027 [Page 25]
Internet-Draft PALA-1 Audit Records October 2026
* *MUST NOT* reject the chain
* *MUST NOT* apply Section 9.4 to it -- those checks belong to a
version it claims
*These fields are frozen for all future versions:* magic,
format_version, header_len, record_type, seq, boot_id, prev_hash,
body_len, body_digest, at their stated offsets.
body_len is in the frozen set for a mechanical reason: without it a
verifier cannot find the next record, and forward compatibility ends
at the first unknown record with a body.
That freeze is what allows a tool written today to report, on a trail
written ten years later:
_"Chain intact, 1.2M records, no gaps, 400 records I cannot
interpret."_
10. Test vectors
The full set -- every record byte, the Merkle leaves and the
inclusion proof -- is published as [PALA-VECTORS]. The vectors are
deterministic: a fixed key, derived nonces and fixed identifiers --
real cryptography over deterministic inputs. Such inputs MUST NOT be
used outside a test vector.
The vector chain's record bodies and narrative follow the robotics
profile (Section 3.4). Every property demonstrated below is an
*envelope* property and holds under any profile.
The chain is a representative ten seconds: genesis, boot with no
clock, a brain span, a c' write with an encrypted body, a second of
frames, a second of Tier 0 statistics, a divergence event, a shed
notice, span close, a local anchor, an external witness, and an
erasure.
key = 000...02a (32 bytes) key_id = 7
nonce = 4 zero bytes || seq (u64 LE)
seq 3 -> 000000000300000000000000
body plaintext (seq 3) =
"clear path ahead, one pedestrian at 12m, static"
| seq | type | note | |---:|---|---| | 0 | GENESIS | tier A, time
UNKNOWN | | 1 | BOOT | wall_clock_ns = 0, time_trust = UNSYNCED | |
2 | SPAN_START | brain | | 3 | EVENT | AES-GCM body, key_id = 7,
origin = eyes.tier1 + digests | | 4 | MERKLE | 30 frame digests | |
5 | AGGREGATE | cleartext TLV body, key_id = 0 | | 6 | SAFETY |
Sparysh & Verteletskyi Expires 5 April 2027 [Page 26]
Internet-Draft PALA-1 Audit Records October 2026
divergence, origin = perception_health | | 7 | SHED | class 1, 400
records, 12 s window | | 8 | SPAN_END | | | 9 | ANCHOR | carries the
head anchored at seq 8 | | 10 | WITNESS | transparency log, covers
seq 0-9 | | 11 | KEY_SHRED | key 7 destroyed -> seq 3 body
unreadable |
*Expected results -- an implementation that disagrees with any of
these is wrong, or this specification is:*
chain_head =
3a1a3673f50498eb1d1c6f94b983d6c606cd85ed53627b4e4ffe55153c7af813
chain_ok = true record_count = 12
breaks = [] gaps = [] violations = []
complete_to_anchor = true
(the anchor is the store's current head = the tip)
anchor_head =
3a1a3673f50498eb1d1c6f94b983d6c606cd85ed53627b4e4ffe55153c7af813
(== chain_head)
merkle_tree_hash =
518f5be5173250f705e3bda029ec1c11ac5c4459115c07dde5bc1021d9f468db
merkle_leaf_count = 30 proof(index 7) verifies proof_len = 5
The ANCHOR record at seq 9 carries, in its ANCHOR_HEAD TLV, the head
as of seq 8
(14434088e5f5866cf0276ba5a9055d8ee0d115a750b2cdf9cc4006d9481b29b4) --
a historical store write that lags the tip by 3. It is *not* the
completeness anchor (which is the store's current head, anchor_head
above); the stale_anchor demonstration below checks against it
deliberately.
Seven properties the vectors demonstrate rather than assert:
Sparysh & Verteletskyi Expires 5 April 2027 [Page 27]
Internet-Draft PALA-1 Audit Records October 2026
+===============+===================================================+
| Demo | Result |
+===============+===================================================+
| Flip one bit | body_digest mismatch detected *and |
| in the seq-3 | the chain still verifies* -- body |
| body | damage and chain damage are distinct |
| | failures |
+---------------+---------------------------------------------------+
| Append a | chain_ok = true, count = 13, |
| record of | uninterpretable = [12] -- Section 9.6 |
| unknown type | works |
| 0x7fff | |
+---------------+---------------------------------------------------+
| Destroy key 7 | seq 3 body unreadable forever, chain |
| | unchanged -- Section 5.4 works |
+---------------+---------------------------------------------------+
| *Drop the | chain_ok = true *without* an anchor; |
| last record* | complete_to_anchor = false *with* one |
| | -- Section 9.1 cannot see truncation, |
| | Section 9.2 can. This is why the two |
| | questions are separate. |
+---------------+---------------------------------------------------+
| *Stale | anchor_lag = 3, reported as an |
| anchor* | unanchored tail, *not* a replacement |
| (anchor names | |
| seq 8, chain | |
| has 12) | |
+---------------+---------------------------------------------------+
| *seq gap* 11 | chain_ok = false, gaps = [99] -- |
| -> 99 with | Section 5.1 |
| valid hashes | |
+---------------+---------------------------------------------------+
| *Chain with | chain_ok = false, violation _"chain |
| no GENESIS* | does not start with a GENESIS |
| | record"_ -- Section 5.2 |
+---------------+---------------------------------------------------+
| *time_trust = | chain_ok = false, violation -- |
| UNKNOWN with | Section 6 |
| a non-zero | |
| clock* | |
+---------------+---------------------------------------------------+
Table 10
A companion vector [PALA-INTEROP] publishes a Signed Statement over
this chain head in the construction of Section 8: 331 bytes, EdDSA
under the published test key of [RFC8032] Section 7.1, with the
expected bytes, digest, key identifier and a set of tamper
Sparysh & Verteletskyi Expires 5 April 2027 [Page 28]
Internet-Draft PALA-1 Audit Records October 2026
expectations that includes the byte-stability cases stated there.
The vector was reissued once, after a reproduction performed under a
stated contamination boundary found the conformance defect described
in Section 13; both versions and their digests are on the record.
11. Related work
Evidence for the conduct of AI systems is an active area, and most of
the current work sits in a different place in the stack than this
document. The distinctions below are stated to locate this format,
not to rank the documents.
*Transparency substrate.* [RFC9943] defines an architecture in which
an issuer registers a signed statement with a transparency service
and receives a receipt, generalising the approach of certificate
transparency to arbitrary content. It is the substrate a number of
the documents below profile, and, as described in Section 8, the
natural witness for a PALA-1 chain head. This document does not
compete with it; the two operate at different points and compose.
*Statement profiles for agent conduct.* A cluster of individual
submissions profiles that substrate for AI agents.
[I-D.mih-scitt-agent-action-capsule] records verdict-level
disposition for a single agent action, with a binding that
distinguishes a dispatched effect from an observed result and a flag
that prevents a policy approval from being presented as human
oversight. [I-D.munoz-scitt-permit-profile] records pre-execution
authorization -- whether an action was permitted, rather than what
occurred. [I-D.emirdag-scitt-ai-agent-execution] defines operator-
signed interaction records with redaction receipts.
[I-D.kamimura-vap-framework] frames hash chaining, signatures and
anchoring as a conformance-tiered provenance architecture.
[I-D.dawkins-scitt-ai-article50] profiles receipts for a specific
regulatory transparency obligation. [I-D.sato-soos-gar] records
session-level governance audit records produced by an enforcing
component.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 29]
Internet-Draft PALA-1 Audit Records October 2026
These are per-action or per-session statement profiles, expressed in
JSON or CBOR, made transparent by registration with a service. This
document specifies a wire format for a continuously appended local
trail, verifiable without a service and without a key, under the
constraints of Section 1.1. The difference is not a disagreement
about design: none of the documents above targets a deployment in
which signing each record is unaffordable, an external service is
forbidden by policy, and the verifier may not read what it verifies.
A single agent action in one of those profiles may correspond to many
PALA-1 records; conversely a PALA-1 chain head may be carried into
that ecosystem as a signed statement. The layers are complementary,
and the practical relation is the anchoring path of Section 8.
*Statement construction and binding.*
[I-D.mih-sokolov-scitt-payload-binding] specifies how a Signed
Statement declares the canonicalization applied to its payload, and
leaves payload formats, serialization and structure out of scope.
Its envelope conventions -- alg, kid or x5chain, and a content type
in the protected header -- are the ones the statement of Section 8
follows. [I-D.nobuo-scitt-protected-object-binding] defines a common
model for relating Signed Statements to the objects they describe,
including device instances. [RFC9995] defines a COSE structure
carrying a digest of a payload that the verifier obtains elsewhere.
The statement of Section 8 is a narrow instance of these concerns:
its payload is a fixed-shape commitment to a chain head -- which is
not a digest of a file but the result of the chain rules -- together
with the range and format identifier a verifier needs to recompute
it. It could be expressed under either binding document, or as a
hash envelope over the head, without loss, and this document does not
preclude that.
*Architectural requirements.*
[I-D.daniel-ai-agent-internet-architecture] states requirements for
supporting AI agents on the Internet, among them that audit evidence
be tamper-evident and support selective disclosure, and that
protocols not require the collection of private reasoning traces as a
condition of accountability. This format was designed before those
requirements were written and satisfies the second by construction:
chain verification inspects headers only and never requires a body to
be disclosed.
*Time and existence.* [RFC3161] timestamp tokens and [RFC6962]-style
logs are alternative witnesses for the existence claim of Section 8.
This document is deliberately indifferent to which is used; the
witness record names a range and a witness, not a mechanism.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 30]
Internet-Draft PALA-1 Audit Records October 2026
*Deployed tamper-evident logs.* Two deployed mechanisms address the
same broad problem and are the nearest prior art. Signed syslog
[RFC5848] has an originator periodically emit Signature Blocks that
carry hashes of the messages it has sent and a signature over them,
with the signer's key conveyed in Certificate Blocks; the cost of a
signature is amortised over a group of messages, an idea this
document shares through its checkpoint and witness records. It
differs in what a verifier needs: checking a signed-syslog stream
requires the signer's public key, whereas the integrity of a PALA-1
chain is checked with no key at all; and signed syslog is a mechanism
for text messages in transit rather than a stored record format whose
bodies can be erased without falsifying the record.
The systemd journal's Forward Secure Sealing [FSS] [SSKG] appends a
message authentication tag at a fixed interval -- every fifteen
minutes by default -- under a sealing key that evolves irreversibly,
so that compromise of the current key does not permit undetected
alteration of entries sealed earlier. That forward-security property
is one a tier A PALA-1 trail does not have on its own; PALA-1 obtains
the corresponding guarantee only from an anchor or witness held
outside the device (Section 7). In the other direction, verifying a
sealed journal requires a verification key from which every sealing
key can be derived, so a party able to verify is also able to forge,
which C3 excludes; entries written since the last seal are
unprotected until the next one; and the journal provides neither
selective disclosure nor erasure that leaves the record verifiable.
Both mechanisms are reasonable choices where their assumptions hold.
Neither is a substitute where C1 to C3 hold together.
*What is not addressed here.* Selective disclosure at field
granularity, agent identity, authorization, and cross-party
attestation are all outside this document. Where a deployment needs
them, the profiles above address them directly and this format is not
a substitute.
12. Relationship to the agent auditing architecture
This section is informative.
[I-D.kuehlewind-audit-architecture] describes an architecture for
auditing agent-driven interactions in which each acting role records
its own behaviour, records are linked by a propagated audit context,
and attestation and transparency logging are composed as optional
trust mechanisms. It proposes four record types -- Interaction,
Action, Delegation and Authorization Transition Records -- and roles
including an Auditing Service, an Audit Store, a Transparency Log and
an Auditor. This section states where PALA-1 sits in that
architecture and, as importantly, where it does not.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 31]
Internet-Draft PALA-1 Audit Records October 2026
*What PALA-1 corresponds to.* A PALA-1 trail written by an inference
runtime records, at the runtime's dispatch boundary, the events that
architecture assigns to Action Records: a tool call when it is handed
to its executor, its result bound by digest to the call, and the
explicit cancellation of a call that never returned (Section 4).
Arguments and results enter the chain only as digests, which is the
treatment that architecture's privacy considerations recommend for
tool-call outputs. The container is an Audit Store substrate in that
architecture's sense -- append-only, and readable by an Auditor
without the runtime that produced it -- and the verification of
Section 9 is the Auditor's integrity check over it. The chain-head
publication of Section 8 is the composition with the Transparency
Log, in the form that architecture already allows when it lets
registration happen as soon as network conditions permit: a head
published after the fact covers every record before it.
*Where it sits differently.* That architecture's Action Records are
produced where an action takes effect and, preferably, by the Tool or
Service, reflecting a request as observed there rather than as
reported by the agent. A PALA-1 trail of the kind described here is
agent-side: it records what the runtime dispatched and what it
received back. In that architecture's terms this is the co-located
recorder of its role-aggregation discussion, with the recorder-
collusion threat that discussion names. The mitigation it offers --
non-repudiable registration with a Transparency Service -- is the one
Section 8 provides, and under C2 that mitigation is deferred rather
than absent. PALA-1 also does not sign records with an identity
bound to the recorder: its integrity is the chain's, and signed
statements exist only at a published head.
*What PALA-1 does not provide.* Interaction Records -- user prompts,
approvals and human-in-the-loop dialogue -- for which that
architecture names [I-D.birkholz-verifiable-agent-conversations] as
the principal candidate. Delegation Records and Authorization
Transition Records. Propagation of an audit context across protocol
interactions, and the actor and on-behalf-of identities that context
carries. A per-record serialisation in CBOR/COSE or JSON/JWS: PALA-1
records are binary TLV (Section 1.3) and enter a COSE-based ecosystem
only at the chain head. Each of these is a non-goal of this
document, not a gap it intends to close.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 32]
Internet-Draft PALA-1 Audit Records October 2026
*How the two compose.* A record in that architecture can reference a
PALA-1 record by its record hash, or a window of them by a Merkle
root, without carrying any PALA-1 body; and a PALA-1 chain head
registered as a Signed Statement is an artifact a SCITT Transparency
Log already accepts. The intended relation is a profile, not a
competitor: PALA-1 as the local recorder of action events in
deployments where an independent Auditing Service is not reachable at
the moment of recording.
13. Implementation status
This section records implementation experience per [RFC7942] and is
to be removed before publication as an RFC, should that occur.
The wire format described here is frozen at version 1.0. Five
implementations of it exist: the reference implementation; one
written by a co-maintainer under a stated contamination boundary; and
three by implementers who were external to the project at the time of
their runs -- one has since become a maintainer -- and who worked
from the specification text and the published test vectors alone
[PALA-VECTORS]. Each of the latter four reproduces the published
expected values of the specification's test-vector section without
access to any prior implementation.
+=+=================+========+=======+============+=================+
|#| Implementer |Language|Date | Spec | Result |
| | | | | tested | |
+=+=================+========+=======+============+=================+
|1| reference |Python |-- | -- | the format's |
| | (authors) | | | | origin, not a |
| | | | | | verification |
| | | | | | run |
+-+-----------------+--------+-------+------------+-----------------+
|2| O. |Python, |2026-08| 776aa15a, | chain + |
| | Verteletskyi |stdlib | | ce877e4 | completeness |
| | (co-maintainer, | | | | reproduced; |
| | stated | | | | Merkle first |
| | boundary) | | | | blocked |
| | | | | | (leaves |
| | | | | | unpublished); |
| | | | | | 2 spec defects |
| | | | | | filed, closed; |
| | | | | | Merkle then |
| | | | | | reproduced |
+-+-----------------+--------+-------+------------+-----------------+
|3| R. Bakaiev |Python, |2026-08| c8e8247 | 8/9 blind; 1 |
| | (external, |stdlib | | | divergence -- |
| | unaffiliated) | | | | the verifier |
Sparysh & Verteletskyi Expires 5 April 2027 [Page 33]
Internet-Draft PALA-1 Audit Records October 2026
| | | | | | was right, the |
| | | | | | vectors were |
| | | | | | inconsistent; |
| | | | | | confirmed at |
| | | | | | 1294bd0, |
| | | | | | verifier |
| | | | | | unchanged |
+-+-----------------+--------+-------+------------+-----------------+
|4| V. Kurdybailo |Python, |2026-08| ff2720a | 11/11 blind |
| | (external, |stdlib | | | first run + |
| | unaffiliated) | | | | 7/7 demos; own |
| | | | | | adversarial |
| | | | | | construction |
| | | | | | exposed a |
| | | | | | common-mode |
| | | | | | pseudocode/ |
| | | | | | prose defect; |
| | | | | | fixed, vectors |
| | | | | | byte-identical |
+-+-----------------+--------+-------+------------+-----------------+
|5| O. Turak |Perl 5, |2026-08| tag | 11/11 + 7/7 |
| | (external and |core | | pala1-v1.0 | first run; 13 |
| | unaffiliated at |only | | | own |
| | the time of the | | | | adversarial |
| | run; a | | | | cases, 140 |
| | maintainer | | | | checks, 0 |
| | since) | | | | failures; 8 |
| | | | | | ambiguities |
| | | | | | logged; span- |
| | | | | | pairing gap |
| | | | | | reported; AES- |
| | | | | | GCM built from |
| | | | | | the primitive |
| | | | | | standards, |
| | | | | | NIST-tested |
| | | | | | first |
+-+-----------------+--------+-------+------------+-----------------+
Table 11
Sparysh & Verteletskyi Expires 5 April 2027 [Page 34]
Internet-Draft PALA-1 Audit Records October 2026
Run kind, stated in the vocabulary in current use for
interoperability reporting: rows 2 through 5 are each an _independent
implementation from the text_, checked against author-supplied
vectors. None is an _independent implementation with independent
vectors_, since the vectors are this project's; rows 4 and 5
additionally constructed their own adversarial inputs beyond the
published set, and in row 4 that construction is what exposed the
defect. The distinction is recorded here rather than left to be
inferred.
The fifth run is described in more detail because it is the one that
changed the specification after the freeze. The gap concerned span
pairing: the specification states that a crash must leave a visibly
unclosed span, because that is the evidence, yet defines no pairing
check anywhere -- so two conformant verifiers would differ on whether
a user ever sees an unpaired span. The resolution deliberately did
not make span pairing a verification verdict, since a trail truncated
by a crash is incomplete without being falsified; it is surfaced as
an advisory finding instead. The finding, the reasoning and the
resolution are on the public record, as are the verifiers, run
records and ambiguity logs of every run above.
The reference implementation ships the published vectors inside its
distribution package, so an installed build can be checked against
them without network access.
The cost claim of C1 has been measured rather than argued. An in-
repository harness compares chain hashing with per-record COSE
signing, and a second run of the same comparison, performed by a co-
maintainer under a stated contamination boundary, agrees with it:
with native primitives on a workstation, which is the case least
favourable to the format, per-record signing costs between 45 and 61
times the header hash on the write path and between 116 and 168 times
on the verify path [PALA-COST]. On the embedded targets of
Section 1.1 the ratio is larger. These are measurements of two
implementations, not properties of the format, and are reported as
such.
*The transparency path.* The Signed Statement construction of
Section 8 has its own record, kept separately from the wire-format
runs above because neither is evidence for the other [PALA-INTEROP].
Two runs by a maintainer, each performed under a stated contamination
boundary from the referenced standards and the published vector
alone, and each with its own implementation of the CBOR and Ed25519
primitives, reproduced the statement byte-for-byte. The first run
found that the protected header omitted the kid header parameter that
Section 6 of [RFC9943] requires when neither x5t nor x5chain is
present, and that the subject truncated the chain head; the
Sparysh & Verteletskyi Expires 5 April 2027 [Page 35]
Internet-Draft PALA-1 Audit Records October 2026
construction was corrected, the vector reissued, and the second run
reproduced the corrected statement and independently re-derived the
key thumbprint. The second run additionally established that the
published tamper expectations had not exercised Ed25519 signature
non-uniqueness (a scalar increased by the group order verifies unless
the verifier enforces the range check of [RFC8032] Section 5.1.7);
the reference implementation's verifier was measured to enforce it,
and the case is now an executable expectation.
Registration was then exercised end to end: a statement over the head
of a chain written during a co-maintainer's session with the serving
interface described below was registered with the SCITT API emulator
published by the scitt-community project (scitt-api-emulator -- an
emulator, not a production service), and the receipt was verified
both by that emulator's own verifier and offline from the published
artifacts alone. The run is reported with its scope: the emulator
was operated by the authors on a local host for the duration of the
run, under a single-use key, and its receipt structure is the
emulator's own, predating [RFC9942]. One finding resulted: the
emulator expected the CWT-claims header under a draft-era label,
whereas [RFC9597] registered a different one; the statement was not
altered to match, the emulator received a one-line correction whose
diff is published with the run, and the matter is reported upstream.
A registration with a transparency service operated by an unrelated
party is the next class of evidence and is not claimed here.
The reference implementation also serves an interface compatible with
a widely deployed inference API, recording the tool-dispatch boundary
of Section 4 for any client of that interface. A measured limit of
that recording is stated in the same record: when a client negotiates
tool use with the model in free text and executes locally, no
structured dispatch crosses the interface and nothing is recorded;
the reference implementation reports this as a visibility limit and
does not reconstruct dispatches from prose.
14. Security considerations
Tamper-evidence applies to record bytes, not to the honesty of the
recorder. This format makes alteration of a written trail
detectable. It cannot establish that the runtime which wrote the
trail reported truthfully at the moment of writing, and no format
can: a dishonest producer with no external observer can construct an
internally valid record of a fiction. Publication of a chain head to
an external witness (Section 8) bounds when such a trail can have
been constructed and makes its later substitution or omission
detectable; it does not make its content true. Every claim elsewhere
in this document is bounded by this paragraph.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 36]
Internet-Draft PALA-1 Audit Records October 2026
The boundaries below are stated here rather than discovered later.
1. *It does not make the log true.* The chain proves _this is what
the system recorded, unmodified_. Not _this is what happened_. A
hallucinated model output is preserved faithfully.
2. *It does not defend against the owner at tier A.* Key and anchor
are both theirs. Tier A is self-diagnostics. Section 7 is the
only mitigation, and it is partial.
3. *It does not bind to hardware.* _"This is the same device"_ needs
tier B+.
4. *A digest without its frame proves nothing about content.*
Commitment defeats fabrication; it does not reconstruct.
5. *Cleartext headers are metadata, and metadata discloses.* The
span graph, origins and timing are readable without a key. That
is the cost of Section 1.1, and it is not zero.
6. *It does not guarantee an action was logged before it happened.*
Section 3.1.
7. *The chain alone does not detect truncation.* Section 9.2 is not
optional; without an anchor the last N records can be removed
silently.
15. IANA considerations
This document has no IANA actions.
16. References
16.1. Normative References
[FIPS180-4]
National Institute of Standards and Technology, "Secure
Hash Standard (SHS)", FIPS PUB 180-4, August 2015.
[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/rfc/rfc2119>.
[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/rfc/rfc8174>.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 37]
Internet-Draft PALA-1 Audit Records October 2026
[SP800-38D]
National Institute of Standards and Technology,
"Recommendation for Block Cipher Modes of Operation:
Galois/Counter Mode (GCM) and GMAC", NIST SP 800-38D,
November 2007.
16.2. Informative References
[FSS] The systemd project, "journald.conf: Seal= (Forward Secure
Sealing)",
<https://www.freedesktop.org/software/systemd/man/latest/
journald.conf.html>.
[I-D.birkholz-verifiable-agent-conversations]
Birkholz, H., Heldt, T., and O. Steele, "Verifiable Agent
Conversation Records", Work in Progress, Internet-Draft,
draft-birkholz-verifiable-agent-conversations-01, 31
August 2026, <https://datatracker.ietf.org/doc/html/draft-
birkholz-verifiable-agent-conversations-01>.
[I-D.daniel-ai-agent-internet-architecture]
Park, S. D. and I. Siddique, "Architectural Requirements
for Supporting AI Agents on the Internet", Work in
Progress, Internet-Draft, draft-daniel-ai-agent-internet-
architecture-03, 28 August 2026,
<https://datatracker.ietf.org/doc/html/draft-daniel-ai-
agent-internet-architecture-03>.
[I-D.dawkins-scitt-ai-article50]
Dawkins, V. S., "A SCITT Profile for EU AI Act Article 50
Transparency Receipts", Work in Progress, Internet-Draft,
draft-dawkins-scitt-ai-article50-00, 25 May 2026,
<https://datatracker.ietf.org/doc/html/draft-dawkins-
scitt-ai-article50-00>.
[I-D.emirdag-scitt-ai-agent-execution]
Emirdag, P., "AI Agent Execution Profile of SCITT", Work
in Progress, Internet-Draft, draft-emirdag-scitt-ai-agent-
execution-00, 11 April 2026,
<https://datatracker.ietf.org/doc/html/draft-emirdag-
scitt-ai-agent-execution-00>.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 38]
Internet-Draft PALA-1 Audit Records October 2026
[I-D.kamimura-vap-framework]
Tokachi, K., "Verifiable AI Provenance Framework (VAP): An
Architectural Framework for Evidentiary-Grade AI Decision
Trails", Work in Progress, Internet-Draft, draft-kamimura-
vap-framework-01, 21 July 2026,
<https://datatracker.ietf.org/doc/html/draft-kamimura-vap-
framework-01>.
[I-D.kuehlewind-audit-architecture]
Kühlewind, M. and H. Birkholz, "An Architecture for
Auditing Agent Delegation and Interactions", Work in
Progress, Internet-Draft, draft-kuehlewind-audit-
architecture-01, 7 September 2026,
<https://datatracker.ietf.org/doc/html/draft-kuehlewind-
audit-architecture-01>.
[I-D.mih-scitt-agent-action-capsule]
Mih, S., "An Agent Action Capsule Profile for SCITT", Work
in Progress, Internet-Draft, draft-mih-scitt-agent-action-
capsule-05, 26 September 2026,
<https://datatracker.ietf.org/doc/html/draft-mih-scitt-
agent-action-capsule-05>.
[I-D.mih-sokolov-scitt-payload-binding]
Mih, S. and A. Sokolov, "Canonicalization Declaration for
SCITT Signed Statements", Work in Progress, Internet-
Draft, draft-mih-sokolov-scitt-payload-binding-05, 12
September 2026, <https://datatracker.ietf.org/doc/html/
draft-mih-sokolov-scitt-payload-binding-05>.
[I-D.munoz-scitt-permit-profile]
Munoz, C., "A SCITT Profile for Pre-Execution AI Action
Authorization Records", Work in Progress, Internet-Draft,
draft-munoz-scitt-permit-profile-01, 19 July 2026,
<https://datatracker.ietf.org/doc/html/draft-munoz-scitt-
permit-profile-01>.
[I-D.nobuo-scitt-protected-object-binding]
Aoki, N., "SCITT Statement Relationship and Protected
Object Binding", Work in Progress, Internet-Draft, draft-
nobuo-scitt-protected-object-binding-00, 6 July 2026,
<https://datatracker.ietf.org/doc/html/draft-nobuo-scitt-
protected-object-binding-00>.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 39]
Internet-Draft PALA-1 Audit Records October 2026
[I-D.sato-soos-gar]
Sato, "The Governance Audit Record (GAR) for Agentic AI
Systems", Work in Progress, Internet-Draft, draft-sato-
soos-gar-08, 7 September 2026,
<https://datatracker.ietf.org/doc/html/draft-sato-soos-
gar-08>.
[PALA-COST]
"Serialization cost, independently measured: chain hashing
versus per-record signing", August 2026,
<https://github.com/Assault-
Consulting/Palimpsests/blob/main/docs/specs/pala-1/
independent-runs/oleksandr/serialization-cost/REPORT.md>.
[PALA-INTEROP]
"PALA-1 SCITT bridge: statement vector, bridge runs and
registration run", August 2026, <https://github.com/
Assault-Consulting/Palimpsests/tree/main/docs/interop>.
[PALA-SPEC]
"PALA-1 wire format specification, v1.0 (frozen)", August
2026, <https://github.com/Assault-
Consulting/Palimpsests/blob/main/docs/specs/pala-1/PALA-
1.md>.
[PALA-VECTORS]
"PALA-1 test vectors and independent verification record",
August 2026, <https://github.com/Assault-
Consulting/Palimpsests/tree/main/docs/specs/pala-1>.
[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/rfc/rfc3161>.
[RFC5848] Kelsey, J., Callas, J., and A. Clemm, "Signed Syslog
Messages", RFC 5848, DOI 10.17487/RFC5848, May 2010,
<https://www.rfc-editor.org/rfc/rfc5848>.
[RFC6962] Laurie, B., Langley, A., and E. Kasper, "Certificate
Transparency", RFC 6962, DOI 10.17487/RFC6962, June 2013,
<https://www.rfc-editor.org/rfc/rfc6962>.
[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/rfc/rfc7942>.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 40]
Internet-Draft PALA-1 Audit Records October 2026
[RFC8032] Josefsson, S. and I. Liusvaara, "Edwards-Curve Digital
Signature Algorithm (EdDSA)", RFC 8032,
DOI 10.17487/RFC8032, January 2017,
<https://www.rfc-editor.org/rfc/rfc8032>.
[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/rfc/rfc8785>.
[RFC8949] Bormann, C. and P. Hoffman, "Concise Binary Object
Representation (CBOR)", STD 94, RFC 8949,
DOI 10.17487/RFC8949, December 2020,
<https://www.rfc-editor.org/rfc/rfc8949>.
[RFC9052] Schaad, J., "CBOR Object Signing and Encryption (COSE):
Structures and Process", STD 96, RFC 9052,
DOI 10.17487/RFC9052, August 2022,
<https://www.rfc-editor.org/rfc/rfc9052>.
[RFC9597] Looker, T. and M.B. Jones, "CBOR Web Token (CWT) Claims in
COSE Headers", RFC 9597, DOI 10.17487/RFC9597, June 2024,
<https://www.rfc-editor.org/rfc/rfc9597>.
[RFC9679] Isobe, K., Tschofenig, H., and O. Steele, "CBOR Object
Signing and Encryption (COSE) Key Thumbprint", RFC 9679,
DOI 10.17487/RFC9679, December 2024,
<https://www.rfc-editor.org/rfc/rfc9679>.
[RFC9942] Steele, O., Birkholz, H., Delignat-Lavaud, A., and C.
Fournet, "CBOR Object Signing and Encryption (COSE)
Receipts", RFC 9942, DOI 10.17487/RFC9942, June 2026,
<https://www.rfc-editor.org/rfc/rfc9942>.
[RFC9943] Birkholz, H., Delignat-Lavaud, A., Fournet, C., Deshpande,
Y., and S. Lasker, "An Architecture for Trustworthy and
Transparent Digital Supply Chains", RFC 9943,
DOI 10.17487/RFC9943, June 2026,
<https://www.rfc-editor.org/rfc/rfc9943>.
[RFC9995] Steele, O., Lasker, S., and H. Birkholz, "CBOR Object
Signing and Encryption (COSE) Hash Envelope", RFC 9995,
DOI 10.17487/RFC9995, July 2026,
<https://www.rfc-editor.org/rfc/rfc9995>.
Sparysh & Verteletskyi Expires 5 April 2027 [Page 41]
Internet-Draft PALA-1 Audit Records October 2026
[SSKG] Marson, G. A. and B. Poettering, "Practical Secure
Logging: Seekable Sequential Key Generators",
DOI 10.1007/978-3-642-40203-6_7, 2013,
<https://doi.org/10.1007/978-3-642-40203-6_7>.
Acknowledgments
The specification was hardened by its independent verifiers, whose
findings were resolved on the public record before this document
existed, and the transparency path was hardened in the same way by
the runs recorded in Section 13. The authors thank every external
contributor to that effort, the maintainers of the scitt-community
reference implementation, and the SCITT and COSE working groups,
whose published work this document refers to and builds no claim
upon.
Changes from draft-sparysh-pala-audit-00
This section is to be removed before publication as an RFC.
* Literal blocks now use kramdown's native fence. In the -00
rendering seven blocks, including the verification procedure of
Section 9.1, had been flattened into running text. No normative
content changed.
* References: corrected an empty co-author entry and missing
publication months introduced by the -00 build.
* Related work: added signed syslog [RFC5848] and the systemd
journal's Forward Secure Sealing; the description of
[I-D.mih-sokolov-scitt-payload-binding] follows its -05 reframing
as a canonicalization declaration.
* Added Section 12, the relationship to the agent auditing
architecture.
* The expansion of the name PALA is stated.
Contributors
Oleksii Turak
Email: olexii.turak@gmail.com
Produced the fifth implementation of the frozen wire format, in Perl
5, working from the specification text and published vectors alone
under the project's stated contamination boundary, and surfaced a
specification-completeness gap in span pairing that was resolved on
Sparysh & Verteletskyi Expires 5 April 2027 [Page 42]
Internet-Draft PALA-1 Audit Records October 2026
the public record before this document existed. Later, as a
maintainer, reproduced the SCITT-bridge Signed Statement byte-for-
byte from the referenced standards in two further runs, the first of
which identified a conformance defect against RFC 9943 that was
corrected on the record.
Authors' Addresses
Andrii Sparysh
Assault Consulting
Kyiv
Ukraine
Email: as@assault.consulting
Oleksandr Verteletskyi
Assault Consulting
Kyiv
Ukraine
Email: ov@assault.consulting
Sparysh & Verteletskyi Expires 5 April 2027 [Page 43]