Skip to content

meta diagnostics: an unknown type, severity or package answers a silent 200 all-clear (scannedTypes 1, zero issues) instead of a refusal; aliases key stats non-canonically #27514

Closed

Description

@objectstack-fleet

domain:devx#1 · sunhaolin · session_017xRBcSwDXZrZg7nGjP6P3U

Filing gate: ① a product defect with a reproduction, found by an off-clause probe of QA run #27438 (wave 3 of the 18.3.0 sweep, anchor #27377). reach: measured at the public diagnostics door. An unknown type answers the "scanned, all clear" shape.
Business reason: /meta/diagnostics is the door that tells an author, an AI agent or CI whether metadata is healthy. Given a type it does not know, it answers 200 with "scanned 1 type, 0 issues", which is the false all-clear #8924 already refuses for misspellings of declared types. A caller with a typo in its type list believes everything is clean. Three sibling parameters coerce silently in the same way.
Reader who acts: the triage seat, then the implementer for the diagnostics route (packages/rest / packages/metadata-protocol, /meta/diagnostics).
Dedupe (open AND closed): the query "meta diagnostics unknown type parameter answers all clear scannedTypes misspelled type" returned 5 hits, none the same. #15622 and #15691 (closed) are about the untyped sweep's scope; #26886 (closed) is a false positive.

Batch-of: 16 · QA run #27438

Symptom

GET /meta/diagnostics answers unknown parameter values with silent all-clear 200s.

Reproduction (subject c4c515a, stock showcase, admin)

  1. GET /api/v1/meta/diagnostics?type=zzz_unknown (an undeclared type) → 200 {scannedTypes: 1, stats: {zzz_unknown: {count: 0}}}: an all-clear over a type that does not exist. For comparison, ?type=viewes, a misspelling close to a declared type, → 400.
  2. ?severity=bogus → 200, silently treated as the error sweep. A repeated severity is refused with 400.
  3. ?package=com.nope.missing → 200, zeros for every type. The unknown package is not refused.
  4. ?type=views, an accepted alias → the stats are keyed views, not the canonical view, so a consumer reading stats.view misses them.
  5. The same route answers its two 400s in two envelopes: {error: string, code} for ?type=viewes, and {error: {code, message}} for a repeated parameter.

Expected: unknown type, severity and package values are refused with 400, the way #8924 refuses a near-miss type; aliases key their stats canonically; and one envelope is used for every refusal.

QA-source: #27438 · studio-authoring.metadata-diagnostics-sweep · observed beside the clauses


Generated by Claude Code

Activity

  1. added
    area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterate
    bugSomething isn't working
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 29, 2026
  2. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 错的必须被响亮拒绝并给处方 | studio-authoring.metadata-diagnostics-sweep | P③

    Triage: p2 · domain:server · area:devpath · 2026-10-29T11:14Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F

    Claim: PM loop round 1 · card thread
    Session: session_01L6bhgUCizoYWQVJWjhdR6F (the seat); the card thread is session_01L6bhgTiSuMwZbnqidCwkCM
    Account: os-sales
    Branch: claude/project-thread-nx5qkr (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: objectstack-issue-27514 in the card thread's own container
    Domain: domain:server
    Seat: domain:server#2
    File surface: packages/rest/src/meta-collection-routes.ts (the diagnostics route), packages/metadata-protocol/src/protocol-meta-diagnostics.ts, and tests (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default (dispatch-gates --tier: no path-derived mandate), effort: high
    Clause-②: no (narrowing — owes one contract-review-tier review before the queue)
    Metadata-protocol: none
    Responsibility: the /meta diagnostics door (this lane) | the existing #8924 type refusal covers other /meta doors, not this one | any API or Studio caller of /meta/diagnostics
    Thread-read: 6495152725
    Premise: holds (read on main 2026-10-29T13:24Z: the route coerces an unknown severity to error; the protocol lists an unknown type as an empty answer; no package check refuses an unknown package)
    Serial constraints cleared: none (no open PR touches these files; metadata-protocol/src/protocol.ts and objectql/src/engine.ts are outside the surface)

  4. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F
    os-dev-report
    {
    "issue": 27514,
    "status": "done",
    "branch": "claude/project-thread-nx5qkr",
    "pr": "#27620",
    "session": "session_01L6bhgTiSuMwZbnqidCwkCM",
    "premise_still_valid": true,
    "summary": "Every premise held at origin/main 556f323, measured through the real route over a real protocol and SchemaRegistry: ?type=zzz_unknown, ?severity=bogus and ?package=com.nope.missing each answered 200 with zero issues, ?type=views keyed stats and entries 'views', and the route answered #8924 flat and #6877 nested. Now: severity outside error|warning is refused in the route (empty keeps the default); an unknown type is refused after the sweep by the list door's own refuseUnknownMetaListType (static contract, then the live type set), so #8924's near-miss refusal still answers first; an unknown package is refused in the sweep only when no swept item is bound to it and the installed-package listing (getMetaItems type 'package') does not carry it, failing open; a named type is swept and keyed by canonicalMetaUrlType. All three refusals are 400 INVALID_REQUEST, and every 400 INVALID_REQUEST of the route leaves in the nested { error: { code, message } } the repeated-parameter refusal uses. No new code, protocol.ts untouched, valid responses unchanged except the alias key the card retires.",
    "tests": "New packages/rest/src/rest-meta-diagnostics-unknown-params.test.ts, 11 cases through the route: on main 5 failed / 6 passed, on the branch 11 passed. Two pins moved to the canonical key (protocol.diagnostics-store-outage.test.ts stats.fields to stats.field; rest-server-meta-read-org-scope.test.ts stats.views to stats.view). pnpm --filter @objectstack/metadata-protocol test: Test Files 279 passed, 4 skipped; Tests 21781 passed, 26 skipped. pnpm --filter @objectstack/rest test: Test Files 335 passed; Tests 6589 passed, 326 skipped. typecheck rest + metadata-protocol: exit 0. Ablation via scripts/ablation-replace.mjs, one leg per pin, each anchor 1 to 0 and restore blob == HEAD with git diff HEAD empty: severity check red 1, type verdict red 1, envelope writer red 4 (rest src); package refusal red 1 and canonical key red 1 (metadata-protocol dist: rebuilt, ablation-dist-preflight marker exit 0, then rebuilt and --absent exit 0).",
    "gates": "Head 59ef3db. dispatch-gates --commands: 69 families, each exit captured before any pipe, all exit 0; --ran: 69 derived, 69 run, 0 NOT-MEASURED, 0 UNRUN. Fixed on the way: check:engine-double-contract (the rig's findOne now opens with assertEngineFindOnePredicate; scripts/engine-double-contract.pinned.json written by --write), check-adr-0087-registration (changeset marker not-required (no-migration-prescription)), check-plugin-teardown-shape --self-test (fixture commit 621a487 fetched), check:dual-build-cjs-loads (after the dogfood closure build). pnpm lint repo-wide exit 0; eslint on packages/rest and packages/metadata-protocol exit 0. PR check-runs: in_progress at report time.",
    "dogfood_battery": "59ef3dbe · os-verify-lock: VERDICT command-exit 0 · Test Files 350 passed, 3 skipped (353) · Tests 2817 passed, 20 skipped (2837) · no failure",
    "mcp_calls": "1 — mcp__github__list_pull_requests (read). No MCP write.",
    "api_writes": "2 relay writes as objectstack-fleet[bot] — pr_create (#27620, read back identical, no assignees) and this os-dev-report comment via post-stamped. Plus 3 git pushes (not REST).",
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: seat · Skills-docs follow-up owed: content/docs/deployment/validating-metadata.mdx's diagnostics query table should state the 400 INVALID_REQUEST refusals and the canonical stats key; outside this card's file surface · noted in the PR body, not filed",
    "carrier: none · scripts/engine-double-contract.pinned.json is outside the claimed surface: the gate's own ledger row for the new test's double · noted in Acceptance notes",
    "carrier: none · with ?type=X&package=P the package refusal reads only the swept type, so an uninstalled P whose orphan rows are all of other types is refused under that filter · noted in Acceptance notes, not filed",
    "carrier: none · deviation: the dispatch asked for pnpm lint, which os-dev.md assigns to CI; it was run anyway (exit 0). The PR header links this card thread (session-context attribution block) rather than the seat-2 thread named in order-common; the footer is the seat's per order-common · noted"
    ]
    }


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 29, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F

    ACCEPT → PR #27620 comment 6500904361 · head 59ef3dbe · contract review PASS 6500761231 · 2026-10-29T15:28Z · landing sent. Follow-ups filed: #27632 (docs), #27633 (closed parameter set).

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

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions