Skip to content

Add is_final to the attestation object: producer-declared end of an append-only chain #1755

Open

Description

@Levaj2000

Problem

The attestation object (record_integrity profile, 1.9) gives a consumer
everything needed to verify a chain's past — chain_uid names the stream,
prev_event links each record to its predecessor, fingerprint +
signatures bind content — but nothing to recognize its end. A consumer
watching a chain today cannot distinguish three states:

  1. The producer closed the chain gracefully (clean shutdown, key rotation,
    log rollover).
  2. Records stopped arriving (outage, misconfiguration).
  3. Records were suppressed (tampering, selective omission).

State 1 is legitimate and routine — every key rotation ends one chain and
begins another — but it is indistinguishable on the wire from states 2 and 3.
The verifier's only recourse is a timeout heuristic, which is exactly the kind
of ambient assumption tamper-evident logging is supposed to eliminate.

I hit this concretely while writing the OTel↔OCSF audit crosswalk
(AI-Identity docs/otel-ocsf-audit-crosswalk, §2.9): the OpenTelemetry audit
data model has audit.sequence.end for this; OCSF has no counterpart, so the
crosswalk has to park the signal in unmapped — a one-way door that loses the
information for any OCSF-native consumer.

Proposed change

Attribute Type Description
is_final boolean When true, the producer declares this attestation's record is the last it will emit on this chain_uid. Absent means unknown — a missing is_final is not a violation and must not be treated as one.

Rules (mirroring OTel's audit.sequence.end semantics):

  • is_final: true MUST NOT appear on any record that is not the final record
    of its chain.
  • Producers MUST NOT set it speculatively; once set, the producer MUST NOT
    emit further records under that chain_uid.
  • Consumers MUST treat absence as "unknown" — never as "chain continues" and
    never as "chain ended".

Use cases

  • Key rotation: the rotation event closes the old chain with
    is_final: true and opens the new one. A verifier can confirm the old chain
    is complete rather than truncated.
  • Forensics / incident replay: an investigator can state "this chain is
    complete through record N" instead of "no records arrived after time T".
  • Log rollover / retention boundaries: clean, attestable stream boundaries
    without out-of-band coordination.
  • OTel interop: gives the OCSF side of the audit.sequence.end mapping a
    native home, closing the crosswalk's §2.9 gap.

Non-goals

Rotation handover pointers ("chain B continues chain A"), superseded-by
references, or multi-producer merge semantics. Those are separate asks; this is
only the terminal marker.

Related

Activity

  1. Levaj2000 commented on Sep 11, 2026

    @Levaj2000
    ContributorAuthor

    A convergence data point since filing: praxis-proxy/policy#84 has since added sequence numbers for stream completeness and ordering on the audit-emit side. Sequence numbers let a consumer detect gaps in what arrived; they can't answer whether the chain ended — rotation, rollover, and clean shutdown all look identical to an outage or suppression on the wire. is_final is the other half: the producer's explicit declaration that no more records will come under this chain_uid, which is what lets a verifier state "complete through record N" instead of "nothing arrived after time T."

    Absent means unknown, so this is purely additive — no existing producer or consumer changes behavior. Would appreciate review from folks on the attestation / record_integrity side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions