Skip to content

auditMetaItem's unqualified catch reports ANY failed audit read as {events: []} — the compliance trail says "no entries" when the read broke #9638

Description

@os-zhuang

Found while implementing #9426 (PR #9637), by the Zone-2 check that card asked for: confirm the missing-capability path and the unprovisioned-table path are genuinely separate. They are — and measuring that is what exposed this, one layer down. Filed rather than ridden on that PR: #9426's declared file surface is packages/rest/src/rest-server.ts, and this lands in a different package.

The measurement

packages/metadata-protocol/src/protocol.ts, closing the read inside ObjectStackProtocolImplementation.auditMetaItem (locate by text, not line number — this file moves):

} catch (err: any) {
    // Table not provisioned (legacy env) or driver doesn't
    // expose `find` — return empty rather than 500ing the tab.
    console.warn(
        `[Protocol] auditMetaItem read failed for ${request.type}/${request.name}: ${err?.message ?? err}`,
    );
    return { events: [] };
}

The comment names two benign causes. The catch is unqualified and takes every other one with them: a driver connection failure, a permission error, a malformed row, a query bug, a timeout. All of them are reported to the caller as the well-formed statement "this item has no audit entries".

ADR-0110 D3 — a miss and a fault are different facts. This is the same collapse #9426 fixed at the route, but at the layer below it, and the harm shape is worse in one respect: at the route the condition was a static capability gap, whereas here it is a transient read failure, so the same item can report a full trail one minute and a clean one the next, with nothing on the wire distinguishing them.

⚠️ Consequence, same as #9426's: this is the compliance surface. auditMetaItem is the read behind GET /api/v1/meta/:type/:name/audit, which exists so Studio's 审计日志 / Audit log tab can show "who tried what and whether a lock blocked it". An empty answer reads as nobody touched this item. A console.warn on the server is not an answer to the reader.

Control — this is a discriminating finding, not a blanket claim about catch

The same defect class has been filed and closed repeatedly in this package, which is what makes an unswept survivor worth naming rather than assuming:

So the sweep that produced this had a real chance of finding nothing here. It did not.

Scope note — what #9637 does and does not change

PR #9637 refuses at the route when the protocol has no auditMetaItem method at all. It does not touch this path and deliberately leaves the unprovisioned-table answer intact, because the two are separate frames in separate packages and only the first was #9426's card. This one is still open after that PR merges.

What would close it

Not obvious enough to assert here, and there is a real design question — which is why this is filed rather than fixed:

  1. Narrow the catch to the two conditions the comment already names (missing table / driver without find) and let everything else propagate, so the route's existing handleRouteError turns it into an honest 5xx. Keeps the documented empty-array promise exactly as documented.
  2. Distinguish on the wire — a third state beside "read, no entries" and "read failed". That is a response-shape decision and would be fenced to packages/spec, the same fence [finding] The REST references route answers a MISSING findReferencesToMeta capability with {references: []} — "nothing depends on this item", one layer above the defect #9190 just closed #9326 and The REST audit route answers a MISSING auditMetaItem capability with {events: []} — a compliance surface reporting "this item has no audit trail" #9426 both carried.

Option 1 looks like the one that needs no contract decision, but the choice belongs to triage, and #8901 (the read-seam failure-propagation vocabulary) may govern how the propagating half is expected to be spelled.

Dedup

Searched open issues for auditMetaItem, for the empty-collection-on-read-failure shape in metadata-protocol, and for the audit route generally. Nearest cards are #8747 (auditMetaItem's org scope — closed, different defect on the same method), #9426 (the route's missing-capability limb — this card's sibling, open) and the four closed same-class cards listed above. None covers this catch. No duplicate.

Related

#9426 / PR #9637 (the route limb, same class, one layer up) · #9326 / PR #9425 · #8896 (the empty-accumulator harm shape) · #8901 (read-seam failure-propagation vocabulary) · ADR-0110 D3

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions