Skip to content

finding(plugin-form): the line-items parent id asserts RecordContextValue.recordId down to string, so a numeric primary key reaches buildMasterDetailEditBatch typed as something it is not #9333

Description

@os-tesla

Found while landing objectui#9304 (the two whole-context assertions on useRecordContext()), in packages/plugin-form/src/LineItemsPanel.tsx. ⛔ Not claimed.

What was measured

objectui#9304's acceptance asked what the inner assertion on the parent id turns out to be once the whole-context assertion above it is gone — pure redundancy, or a real mismatch. Measured on that branch, with the outer assertion removed and the inner one deleted, pnpm --filter @object-ui/plugin-form run type-check:

src/LineItemsPanel.tsx(262,64): error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string'.
  Type 'number' is not assignable to type 'string'.

⇒ a real mismatch, not a redundancy. The assertion is now the only thing that makes the two declarations meet. objectui#9304 kept it deliberately and documented it at the site instead of repairing it, because every repair moves bytes on the wire and that card is type-side with no runtime effect.

The two declarations

  • RecordContextValue.recordId (packages/react, src/context/RecordContext.tsx) is declared string | number | null | undefined.
  • buildMasterDetailEditBatch (packages/plugin-form, src/masterDetailTx.ts) takes parentObject: string, parentId: string.

The panel computes its parent id as schema.parentId || schema.recordId || record?.recordId and asserts the third arm down to string | undefined. A host that mounts a record with a NUMERIC primary key — which RecordContextValue explicitly permits, and which DataSource.update accepts as string | number — therefore hands the helper a number where its own declaration says string. The value flows on into the batch op's id and into the child filter keyed by relationshipField.

Why it was not repaired there

Both candidate repairs change runtime bytes:

  • CoerceString(record.recordId). Changes the id this panel sends and the child filter value; on a numeric-id backend an equality filter against a stringified id is a different query.
  • WidenbuildMasterDetailEditBatch(parentId: string | number). Zero runtime change and it removes the assertion entirely, but it is masterDetailTx's contract, shared with MasterDetailForm, and BatchOp (an alias of BatchTransactionOperation) has to be read first to confirm its id already admits both.

⇒ this wants a decision on which, not a drive-by inside another card's scope.

Dedup

Declared with its boundary. MCP search_issues answered with a rate-limit error for this session's identity, so the check ran over the repo-scoped REST open issues list, fully paginated — 449 open issues over five pages, page six empty — with objectui#9304 itself carried as a known-hit control, which came back lit. Keyword sweep over those titles: recordId, line items, master detail, parentId, string | number, plugin-form. Nearest neighbours are objectui#7209 (the SchemaRendererContext cast family) and objectui#6904 (ObjectForm visibleWhen assertions); neither is this. ⛔ No text query over CLOSED cards was possible this session, so a closed duplicate would not have been seen.

Related

objectui#9304 (where it was measured) · objectui#9197 (the retype that opened this family) · objectui#7483 (same defect class)

Filed by an os-dev seat while working objectui#9304, generated with Claude Code; session https://claude.ai/code/session_01UzHd6hDYatoDn17BuwKxnZ.


Generated by Claude Code

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

    Labels

    bugSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions