You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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:
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:
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.
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
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 insideObjectStackProtocolImplementation.auditMetaItem(locate by text, not line number — this file moves):The comment names two benign causes. The
catchis 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.
auditMetaItemis the read behindGET /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. Aconsole.warnon the server is not an answer to the reader.Control — this is a discriminating finding, not a blanket claim about
catchThe same defect class has been filed and closed repeatedly in this package, which is what makes an unswept survivor worth naming rather than assuming:
getMetaItem's overlay read swallowed "sys_metadata unreachable" into "item does not exist" (closed)MetadataProtocol.listCommits把 commit store 读不到答成[]—— ADR-0067 时间线上「无历史」与「读不到」不可分辨(零日志,JSDoc 里写着这是设计) #5980 —MetadataProtocol.listCommitsanswered an unreadable commit store with[](closed)diffMetaItemanswered 200 with an empty diff whensys_metadata_historywas unreadable (closed)SysMetadataRepository.nextEventSeq()/nextItemVersion()read a failed read as "table not created yet" (closed)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
auditMetaItemmethod 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:
catchto the two conditions the comment already names (missing table / driver withoutfind) and let everything else propagate, so the route's existinghandleRouteErrorturns it into an honest 5xx. Keeps the documented empty-array promise exactly as documented.packages/spec, the same fence [finding] The REST references route answers a MISSINGfindReferencesToMetacapability with{references: []}— "nothing depends on this item", one layer above the defect #9190 just closed #9326 and The REST audit route answers a MISSINGauditMetaItemcapability 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 inmetadata-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 thiscatch. 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