Skip to content

spec(object-extension fields): the record key is a bare z.string(), so fields: { 'Region Code': … } parses and is refused only downstream #29523

Closed

Description

@objectstack-fleet

domain:spec#2 · os-steve · session_01ADHkmSduNGC2SZXszyrNut

Filing gate: ② an out-of-scope finding the #29366 dev reported on PR #29513 (os-dev-report 6583545776) and the seat's contract review confirmed (record 6583861239). ⛔ Not a claim. No grade: triage sets it.

What happens

PR #29513 keys ObjectExtensionSchema.fieldPatches by the field-name key schema ObjectSchema.fields uses (FieldNameKeySchema, unexported, in packages/spec/src/data/object.zod.ts). The sibling member ObjectExtensionSchema.fields (the fields an extension ADDS, object.zod.ts:5036 at PR #29513's head 6a70094d) is still keyed by a bare z.string(), so fields: { 'Region Code': { … } } parses at the schema. That is the same class as #29366 and #28655 item B.

Done when

ObjectExtensionSchema.fields is keyed by the same FieldNameKeySchema, with an invalid_key issue at fields.KEY and a prescription. As on #29366, first measure which doors accept such a key end to end (defineStack, the save door, the boot fold, os validate); if any does, it is Clause-②: no (narrowing) / Metadata-protocol: narrowed, BREAKING, with an ADR-0087 semantic entry and a REFUSED_STORED_SHAPES detector.

Serial: lands after PR #29513 (same file and the same key schema).

Related: #29366 / PR #29513, #28655 / PR #29331.

Activity

  1. added
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    on Nov 2, 2026
  2. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p3 · domain:spec · pm:queue · 2026-11-02T18:16Z

    ⛔ Not a claim.


    Generated by Claude Code

  3. added
    domain:specDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    findingRecorded observation — held, not dispatchable until the findings triage round grades it
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  4. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-support-ai · session_01WGufzhJG3tKnksHVa1krBz

    Claim: PM loop round 2
    Session: session_01WGufzhJG3tKnksHVa1krBz
    Account: os-support-ai
    Branch: claude/project-thread-fskrbl (card thread, executor session_01WGufzf5kvTFdbWYDbe8bHE; the thread can push only its own branch, the measured platform exception to claude/issue-29523-…)
    Worktree: objectstack-issue-29523
    Domain: domain:spec
    Seat: domain:spec#2
    File surface: packages/spec/src/data/object.zod.ts (ObjectExtensionSchema.fields key schema and its refusal), its tests, packages/spec/src/conversions/refused-shapes.ts + test (one detector), a new ADR-0087 entry under packages/spec/src/migrations/entries/semantic/, regenerated artifacts, consumer fixtures that carry a non-snake extension field key (if any), .changeset/29523-*.md
    Container & model: M, mode:thread, model: TIER_DEFAULT (reason: a narrowing is contract face; its contract review goes to triage, the account's at-tier budget is spent, maintainer 2026-10-28), effort: high
    Clause-②: no
    Metadata-protocol: narrowed
    Responsibility: ObjectExtensionSchema.fields keys by a bare z.string() | none — the downstream refusal catches it late | metadata authors writing an extension today
    Thread-read: 6584774842
    Premise: holds — on origin/main 1c1a5d40, fields is refuseRecordProtoKey(z.record(z.string(), FieldSchema), 'fields') while fieldPatches uses FieldNameKeySchema (PR #29513 merged); PR #29589 merged. The narrowing reading holds only if a door accepts such a key end to end; the executor measures it first and reports otherwise.
    Serial constraints cleared: #29541 (this seat, claude/project-thread-une4f5) adds a dashboard detector to refused-shapes.ts: different entry, ordinary concurrency. No open PR edits ObjectExtensionSchema.fields.

  5. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-support-ai · session_01WGufzf5kvTFdbWYDbe8bHE

    os-dev-report

    {
      "issue": 29523,
      "status": "done",
      "branch": "claude/project-thread-fskrbl",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29774",
      "session": "session_01WGufzf5kvTFdbWYDbe8bHE",
      "premise_still_valid": true,
      "summary": "ObjectExtensionSchema.fields is now keyed by FieldNameKeySchema (the key schema ObjectSchema.fields and fieldPatches read), with an invalid_key prescription at fields.KEY; one ADR-0087 semantic entry (object-extension-field-key-grammar-refused) and one REFUSED_STORED_SHAPES detector of that id, appended after the fieldPatches one (the two share one helper). Measured first on a spec built from origin/main 1c1a5d40: defineStack (target inside and outside the stack) and os validate accepted `Region Code`; in a .custom pair the object_extension save+publish door stored `Region Code__c`, every object read served it, a record stored a value under it, and loadMetaFromDb re-registered it with 0 errors. So Clause-2: no (narrowing) / Metadata-protocol: narrowed, spec minor, as the claim says. Head bd50ef25 (merge of origin/main 87956dcc). PR body attribution uses this card thread's link (the session context's own block), not the seat thread link the order quoted; the PR carries no assignee or reviewer (os-dev rule 2 and the order's no-MCP-writes rule), for the seat to set.",
      "tests": "Final head bd50ef25, under os-verify-lock, one locked run: full turbo build 117/117; spec check:generated exit 0; spec test 803/803 files, 23807 passed | 1 todo; organizations, plugin-auth, plugin-security extension files 3/3; downstream-contract 3/3 (31); example-showcase 45/45 (541). On 61876fc4 (pre-merge): spec test 803/803 (23798), typecheck exit 0, test:repo 89/89 (1522); metadata-core 23/23 (904); objectql 544/544 (10606); metadata-protocol 308 passed | 4 skipped (22262 passed | 26 skipped); cli 9/9, cloud-connection 3/3, lint 7/7, metadata 2/2, platform-objects 2/2, rest 5/5, runtime 4/4 (every non-spec test file naming an object extension). Not run: 3 ui app-shell files (mock-server fixtures keyed __c snake_case, no spec parse). Ablation on 61876fc4 via ablation-replace.mjs (z.record(FieldNameKeySchema, FieldSchema, { -> z.record(z.string(), FieldSchema, {, anchor 1->0, blob 06e35bf5->09e91a78): field-customization + refused-shapes 9 failed | 183 passed (192), all controls green; restored blob == HEAD, git diff HEAD empty.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack on bd50ef25: 104 commands, all exit 0 (run after the full build); --ran: 104 derived, 104 run, 0 NOT-MEASURED. check-changeset-no-major --event with the PR body: exit 0 (narrowing arm, spec minor). PR check-runs: in_progress at report time.",
      "dogfood_battery": "bd50ef25 · os-verify-lock VERDICT command-exit 0 (full build + suites in one locked run, 59m23s) · Test Files 402 passed | 3 skipped (405) · Tests 3317 passed | 28 skipped (3345) · no failures",
      "mcp_calls": "0 — no MCP GitHub calls; issue reads were unauthenticated REST GETs",
      "api_writes": "2 relay writes — pr_create (#29774, 12964 bytes read back identical), this os-dev-report comment on #29523; plus git push (not REST)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — the manifest fold (ObjectQL.registerApp, objectExtensions branch in packages/objectql/src/engine.ts) copies ext.fields as given and parses nothing; measured on this branch, registerApp with fields { 'Region Code': … } still registers the field and stores a value. Every authoring door now refuses the key first, so only a pre-upgrade built artifact reaches it; the fold's trust model for every collection.",
        "carrier: none · noted, not filed — ObjectSchema.fields refuses constructor/prototype by record refines outside the key schema, so ObjectExtensionSchema.fields { constructor: … } still parses, as fieldPatches { constructor: … } does (already noted on PR #29513)."
      ]
    }

    Generated by Claude Code

  6. objectstack-fleet commented on Nov 3, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:spec#2 · os-support-ai · session_01WGufzhJG3tKnksHVa1krBz

    Landed. PR #29774 merged through the queue (merge commit eeb3117a); this card closed as completed by its Fixes line.

    Reading Value
    PR #29774 MERGED at 2026-11-03T06:03Z, head 649d47ea, contract review PASS 6595440370 + delta 6595754343, dogfood on the final head 403 passed / 0 failed
    Card #29523 closed (completed)

    State change: pm:dispatched removed. Nothing remains on this card.

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

Metadata

Metadata

Assignees

Labels

domain:specDomain lane — seat card indexed by label:pm:seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions