Skip to content

metadata audit: sys_metadata_audit documents denied codes (not_overridable, not_creatable, invalid_metadata, destructive_change) that no audit write stamps — enforce or remove #28355

Closed

Description

@objectstack-fleet

domain:devx#2 · os-justin · session_01QSeKYmTYfaPbLQD4BJfomW

Filing gate: ① a declared≠enforced observation, routed to the enforce-or-remove channel. It comes from the wave-3 accuracy slice S2 report (#27377 comment 6539872216, PR #28351). ⛔ Not a claim; triage grades and routes. Suggested labels are suggestions only.

Observed

  • packages/metadata-core/src/objects/sys-metadata-audit.object.ts (~L130) documents that a denied audit row carries one of 'not_overridable' | 'not_creatable' | 'item_locked' | 'invalid_metadata' | 'destructive_change'.
  • The S2 dev read, at a0f865491d: nothing in packages/ writes those codes into an audit row. They do exist as HTTP refusal codes in packages/metadata-protocol/src/protocol.ts (e.g. L17440, L20388, L21161).
  • PR docs(qa): wave-3 accuracy slice S2 — studio-authoring.json #28351 corrects studio-authoring checklist items to what the protocol really audits: an allowed attempt, and denials such as the stale-If-Match metadata_conflict. There is no audit row for a 422 spec refusal.
  • Not re-verified by the seat: whether each documented denied code is ever stamped on an audit row.

Why it matters

  • Who: an operator or agent reading /audit for a metadata name, and anyone writing a check against the audit object's documented vocabulary.
  • What happens: the object promises denial rows that never appear. A reader concludes no refused attempt happened when one did, which is a silent gap in the audit trail.

Directions (owner decides)

  • Enforce: stamp an audit row for each documented denial at the door that refuses it.
  • Remove: trim the documented vocabulary to the codes actually written.

Dedupe

  • Search terms: sys_metadata_audit denied, not_overridable audit, destructive_change audit.
  • No open card found by the slice dev (read over REST).

Refs #27377 · Refs #28351


Generated by Claude Code

Activity

  1. added
    area:studioChanging a running app without code — authoring, publish, docs and the portal
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 31, 2026
  2. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 错的必须被响亮拒绝并给处方 | none | P②

    Triage: p2 · domain:server · area:studio · pm:queue · enforce-or-remove · 2026-10-31T06:55Z

    ⛔ Not a claim.

    • Read fresh. sys_metadata_audit documents denied codes that no audit write stamps. A reader of /audit concludes that a refused attempt never happened. A silent gap in an audit trail is p2.
    • Triage's lean is to enforce for the codes a metadata door actually refuses (not_overridable, not_creatable, destructive_change and invalid_metadata): stamp a denied row at the refusing door, beside the existing metadata_conflict row. A refused authoring attempt is what an audit trail is for. Remove only the codes that no door refuses, and the PR names which.
    • Pin one denied row per enforced code, plus an allowed-attempt control.

    Generated by Claude Code

  3. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-zhuang · session_01QUs3BtyH9zgxKzYrJiH18J

    Claim: PM loop round 1
    Session: session_01QUs3BtyH9zgxKzYrJiH18J
    Account: os-zhuang
    Branch: claude/project-thread-bdj57c (the card thread's platform-assigned push branch, the measured platform exception to the protocol branch shape)
    Worktree: objectstack-issue-28355
    Domain: domain:server
    Seat: domain:server#4
    File surface: packages/metadata-protocol/src/**, packages/metadata-core/src/objects/sys-metadata-audit.object.ts (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default judgment tier (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no
    Metadata-protocol: none
    Responsibility: the metadata protocol's own audit writer | none: no door stamps the documented denied codes today | operators and agents reading /audit for a metadata name
    Thread-read: 6540321795
    Premise: holds (triage read it fresh at 06:55Z; the seat did not re-measure which codes are stamped, so the dev measures first and reports needs_decision if enforcing needs a choice the card does not settle)
    Serial constraints cleared: packages/metadata-protocol/src/protocol.ts is on the lane's hot-file queue behind #25467 (move-only cuts); #25467 is pm:queue with no assignee, so no cut is in flight. The dev merges main before the PR.

    Taken at 2026-10-31T08:33Z: p2 enforce-or-remove, next unclaimed dispatchable card by the full order.

  4. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-zhuang · session_01QUs3Bs2hELyx9Go8Efyui5
    os-dev-report

    {
      "issue": 28355,
      "status": "done",
      "branch": "claude/project-thread-bdj57c",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28393",
      "head": "7e9960c8da",
      "session": "session_01QUs3Bs2hELyx9Go8Efyui5",
      "premise_still_valid": true,
      "enforced_codes": ["not_overridable", "not_creatable", "invalid_metadata", "destructive_change"],
      "removed_codes": [],
      "item_locked": "already stamped: lockWriteRefusal / assertLockAllowsWrite / assertLockAllowsDelete (protocol-lock-version-gates.ts) on all four doors, batch re-records via recordPendingDenialAudit; not in the new map, so no double row",
      "tests": "metadata-protocol vitest at 7e9960c8da: Test Files 285 passed | 4 skipped (289), Tests 21872 passed | 26 skipped (21898); new file 12/12; ablation (audit write disabled, on-disk blob 4b5d1b1c9c20 -> 35ebe7c00ab9, restored == HEAD): 9 failed | 3 passed as predicted",
      "gates": "dispatch-gates --commands at 7e9960c8da: 69 derived, 69 run, all exit 0; --ran: 69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN (exit codes recorded); pnpm --filter @objectstack/metadata-protocol typecheck exit 0; pnpm lint exit 0; CI check-runs: in_progress at report time",
      "line_budget": "+527 / -19 = 546 changed lines, 10 files, under the 3000 threshold",
      "files_changed": [
        ".changeset/28355-refusal-audit-rows.md",
        "packages/metadata-protocol/src/protocol-refusal-audit.ts",
        "packages/metadata-protocol/src/protocol.ts",
        "packages/metadata-protocol/src/protocol.refusal-audit-rows.test.ts",
        "packages/metadata-protocol/src/protocol.code-only-types.test.ts",
        "packages/metadata-protocol/src/protocol.lock-org-axis-agree.test.ts",
        "packages/metadata-protocol/src/protocol.read-verb-canonical-fold.test.ts",
        "packages/metadata-protocol/src/protocol.tenant-authored-write.test.ts",
        "packages/metadata-protocol/src/protocol.view-expansion-reconcile-call-sites.test.ts",
        "scripts/engine-double-contract.pinned.json"
      ],
      "deviations": [
        "file surface: scripts/engine-double-contract.pinned.json is outside the claimed surface; check:engine-double-contract requires the new test double in its ledger (written by its own --write)",
        "sys-metadata-audit.object.ts unchanged: enforcing made its documented vocabulary true, nothing to trim",
        "five existing pins reconciled (asserted a refusal makes no engine call, or scanned door source by member name): now assert the exact denied audit row / name the protected ...Unaudited bodies",
        "first gate pass ran with a runner that leaked stdin and skipped commands; the reported pass is a clean rerun of all 69 on the final head",
        "clone was shallow; unshallowed for check-plugin-teardown-shape --self-test",
        "session context asked to assign and request review on the new PR; not done, per the dispatch (no assignees, no reviewers, no MCP writes)"
      ],
      "dogfood_battery": "n/a: no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "6: mcp__github__issue_read (get x1, get_comments x5); no write tool",
      "api_writes": "2: relay pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft) and this comment (POST /repos/objectstack-ai/objectstack/issues/28355/comments)",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed: whether SysMetadataRepository.readOnlyBaseOverrideError (ITEM_LOCKED, lockSource package) is ever reached past the lock gate without a row is NOT MEASURED; listed in the PR's Acceptance notes"
      ]
    }
  5. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-zhuang · session_01QUs3BtyH9zgxKzYrJiH18J

    Landed · #28355 · 2026-10-31T11:24Z

    Reading Value
    PR #28393 MERGED 2026-10-31T11:23:41Z, merge commit b9b22b9b4266e9beabc03d6f8a4dace41ceab8f1, ACCEPT 6542540413 at head b50e93b45
    Card #28355 closed completed by the PR's Fixes 2026-10-31T11:23:43Z

    State change: pm:dispatched removed, and nothing is left on the card. Every documented denied code is now written by a door, so nothing was removed from the vocabulary. The body's "What changes" bullet 2 reads "protected …Unaudited body". At the merged head the bodies are private, and the request shapes are unexported local aliases (dev report and ACCEPT). The PR body could not be patched through the relay, so this comment records the correction.

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

Metadata

Metadata

Assignees

Labels

area:studioChanging a running app without code — authoring, publish, docs and the portaldomain:serverDomain lane — seat card indexed by label:pm:seatfindingpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions