Skip to content

publishPackageDrafts' pre-flight refusal writes no audit row — a package publish rejected before the transaction leaves no trail #8595

Description

@os-zhuang

What

publishPackageDrafts has a pre-flight gate that refuses the whole batch before anything
is promoted — currently the ADR-0028 namespace-prefix rule on object drafts:

if (preflightViolations.length > 0) {
return {
success: false,
publishedCount: 0,
failedCount: preflightViolations.length,
published: [],
failed: preflightViolations,
};
}

That return is above the engine.transaction(), so it is reached by neither the
allowed-outcome rows nor the rollback handler's denied row. A publish refused here writes
nothing to sys_metadata_audit at all: in the trail, an author whose package was rejected
for a bad object name is indistinguishable from an author who never pressed Publish.

Why #8400 did not cover it

#8400's ruling placed the batch's audit rows in Phase 2, after the transaction commits,
driven off promoted[], and its denied row in the rollback handler. Both live below this
early return. The card named the rollback refusal specifically, so the pre-flight branch was
left alone rather than folded in silently — it is a separate refusal class with its own
shape (N violations, no causal item, nothing ever attempted).

Shape question for whoever takes this

The pre-flight refusal is not "one causal item aborted the batch" — it is a list of
violations, each naming a different item. So it is genuinely a different row shape from
batch_aborted:

  1. one denied row per violation, keyed on its own (type, name), or
  2. one row for the batch, which then has no honest (type, name) to key on.

Option 1 matches what the audit table is for (per-item decisions, and the per-item history
tab reads (type, name, occurred_at)); option 2 needs a synthetic identity in a compliance
ledger, which #8400 deliberately avoided for the unattributable case.

Backlink: #8400, #7748.

Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions