Skip to content

2026.10.46

Pre-release
Pre-release

Choose a tag to compare

@github-actions github-actions released this 13 Oct 14:46
· 45 commits to main since this release
97c0dc2

Added

  • Say how many events an export will hold (38a51082)

    The Export menu names the number of matching events before a format is chosen.

  • Alert when an audit receiver is behind or lost records (623de17a)

    A new installation alert condition, AUDIT_DELIVERY, is active for each audit
    receiver that has a gap it has not been told about, or whose oldest
    unacknowledged record is older than audit.delivery.alert-after. The subject is
    the receiver's plugin id and the value is the age of that record. A default
    Audit delivery rule is created, enabled and bound to no channel, like the
    storage rules, and the condition is offered when editing an installation rule.

  • Retention waits for receivers and leaves held records alone (1bb820e2)

    The audit purge no longer deletes a record a receiver has not acknowledged until
    it is older than audit.delivery.max-unacknowledged-age. When it does delete such
    records, the receiver is told with an AuditGap, an AUDIT_GAP audit event records
    it, and AuditFeed.retainedFrom reports the time the trail is complete from.

    A plugin that declares audit.retentionHold provides one AuditRetentionHold
    naming time ranges, optionally narrowed by cluster, user, action and target. The
    purge leaves every record a hold covers, whatever the retention. It asks before
    every batch; a hold that throws, takes longer than audit.delivery.timeout, names
    more than 200 entries or belongs to a plugin that is not running on the purging
    replica makes the run purge nothing, and the purge status says why. A plugin that
    provides an AuditRetentionHold without declaring audit.retentionHold is not
    activated.

  • Deliver the audit trail to receiver plugins in commit order (4434d00d)

    A plugin that declares audit.receive in its manifest provides one AuditReceiver.
    Studio calls it with batches of up to 500 records after its cursor, in commit
    order, from a job that runs once per installation every two seconds. Returning
    from the call acknowledges the batch; throwing or taking longer than
    audit.delivery.timeout delivers the same batch again later, after a delay that
    doubles from 2 seconds to 5 minutes. Delivery is at least once, so a receiver
    identifies a record by its id and position. A receiver never holds up the
    audited operation.

    A new receiver starts at the beginning of the retained trail. Its cursor is
    removed when the plugin is uninstalled, not when it is disabled. A plugin that
    provides an AuditReceiver without declaring audit.receive is not activated.
    When retention removes records a receiver has not acknowledged, the receiver is
    told with an AuditGap and an AUDIT_GAP audit event records it.

    New settings: audit.delivery.max-unacknowledged-age (30d),
    audit.delivery.timeout (30s) and audit.delivery.alert-after (1h).

  • Add an Export menu to the audit log (8c5bfdb9)

    CSV, JSON and NDJSON are plain download links carrying the current filters,
    so the browser streams the file to disk and the download can be cancelled.
    The button is disabled with its reason without audit:export.

  • Export the audit trail as CSV, JSON or NDJSON (a58b48ed)

    GET /clusters/{clusterId}/audit/export streams the trail under the same
    filters as the list, oldest first, as a file. It needs the new cluster
    permission audit:export and holds only what the caller could read in the
    list, redacted the same way. CSV cells a spreadsheet would run as a formula
    get a leading quote. Each export is itself audited as EXPORT_AUDIT with its
    format and filters, and records how far it got if the client cancels.

  • Plugins declare audit access in their manifest (de54fa7d)

    A plugin.json may carry an audit block with receive and retentionHold flags,
    both false by default. The install review lists each flag, the diff shows
    flags an update adds or removes, and a plugin that newly declares one is
    activated only after the audit-access-added acknowledgement.

  • Give every audit record a commit-order position and a feed API (7e46bcb3)

    Each audit record now carries a position, the writing transaction's id and a
    sequence value stamped by the database. AuditFeed.after returns records in that
    order and only once every earlier transaction has ended, so a reader following
    the trail never skips a record that commits late. A record whose outcome is
    filled in takes a later position, so a reader that already passed it sees the
    final state. AuditFeed, AuditRecord and AuditPosition are part of the plugin API.

    A database guard now keeps the trail honest: only a record's outcome, error,
    count and outcome detail can change, only while it is pending (a refusal's count
    may keep rising), and nothing else is ever rewritten.

Fixed

  • Delete settled gap rows and fix the tests the audit delivery broke (30474c29)

    A gap row is deleted once it is audited and delivered, so the table holds only
    open gaps. Tests: the module slices that pull in the data lifecycle mock the
    retention guard, the schema baseline and store coverage lists name the new
    tables, the audit-access plugin fixture provides the beans it declares, and the
    alert rules test no longer depends on the seeded rule order.

  • Record a completed second-factor sign-in as a new event (b9f30d2e)

    A sign-in finished by its second factor is now a new successful login event
    whose parent is the attempt, instead of changing the attempt's outcome. The
    attempt's own record stays as it was written.

  • Keep gap counts, in-flight calls and export outcomes honest (24e0468a)

    A purge writes a new gap row each time instead of adding to one a delivery may
    have read, so an acknowledgement cannot mark an unseen count delivered. The
    AUDIT_GAP claim reads the row in the same statement, and the claim is given
    back only when the event could not be started. A receiver or hold that ignores
    its timeout is not called again until it has returned. An export records its
    outcome after the sink is flushed and closed.

  • Record an audit outcome once and ignore a second one (71dfb2d0)

    A row that already has its outcome is no longer overwritten by a later success or
    failure for the same operation. The first outcome stands and the second is logged
    as a warning, now that the database refuses rewriting a finished audit record.