Skip to content

fix(app-shell): Studio API tab example body leaves out owner_id and optional references - #27613

Merged
objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-1o2iww
Oct 29, 2026
Merged

objectstack-fleet[bot] merged 2 commits into
mainfrom
claude/project-thread-1o2iww

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Bill · project thread

维护者速读

  • 改了什么:Studio 对象「API」标签页的示例请求体不再放 owner_id 和可选的引用字段;必填引用字段改成一眼就能认出的占位符(尖括号包住的 id of a showcase_project record)。
  • 为什么改:原来每个引用字段都填 "related_record_id",这个 id 不对应任何记录,复制出来的新建/更新 cURL 在几乎所有对象上都被 400 reference_not_found 拒掉。
  • 风险与回滚:只改示例体的生成,不碰任何写入路径;可选字段仍在体下方的提示里列名。回滚即还原 ObjectApiPanel.tsx 一个文件。
  • 先看:ObjectApiPanel.tsx 的 buildExampleBody(哪些字段进体)→ 同文件 referencePlaceholderFor(必填引用的占位符)→ 钉住测试新增的 objectstack#27490 一节。
  • 两分钟验证:pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/ObjectApiPanel.exampleBody-11803.test.tsx,预期 13 个测试全绿。
  • 需要你做的:无,席位落地。

Fixes #27490

Clause-②: no
Metadata-protocol: none

What changes

ui/packages/app-shell/src/views/studio-design/ObjectApiPanel.tsx, buildExampleBody and the reference branch of exampleElementFor:

  • Optional fields that never join the body: a field the platform adds (system: true, such as owner_id, which the platform fills in when it is left out), and a reference field (REFERENCE_VALUE_TYPES: lookup, master_detail, user, tree). Both come from the field metadata the draft already carries; there is no list of field names. They are still named in the panel's "Optional fields not shown" note, so every writable field is either in the body or named.
  • A required reference stays in the body, since a create without it is refused. Its value is now the text id of a TARGET record wrapped in angle brackets, the target read through the spec's referenceTargetOf (so a user field names sys_user), the same angle-bracket form as the cURL's token placeholder. Before, it was "related_record_id", which reads like a working value.
  • Unchanged: the other sample values, required-first order, the cap of eight, and one body for both Create and Update (no second generator).

The previous "own fields before platform fields" ordering is now a stronger rule: platform fields are never shown when optional.

Tests

ObjectApiPanel.exampleBody-11803.test.tsx (the existing pin) is extended with a objectstack#27490 describe block of 5 tests. Its oracle is the write path's own reference check: assertReferencesResolve in @objectstack/objectql resolves a supplied value only on a field that referenceTargetOf answers a target for. So for every key of the shown body the test asserts referenceTargetOf(def) is undefined (nothing for that check to refuse) and the value still parses under valueSchemaFor(def, 'stored').

  • owner_id is left out even when the body has room, and is named in the note.
  • When no writable field is shown, the body block still renders (an empty body) with the note naming the fields left out. Before, the block and its note were hidden for an empty body; with owner_id now never shown, an object whose writable fields are all optional references would otherwise lose the note.
  • Every optional reference is left out, on the showcase Account and on the field zoo without its one required reference.
  • A required reference shows the placeholder naming its target (showcase_project; sys_user for a user field).
  • The copied Create (POST) and Update (PATCH) cURL carry the shown body and no owner_id.

Two existing tests are adjusted, not weakened: the per-type zoo test reads a reference type's value shape with the field marked required (an optional one is no longer in the body), and the multi-value test marks f_lookups required for the same reason.

Test and ablation readings (head 8e49824)
  • pnpm --dir ui exec vitest run packages/app-shell/src/views/studio-design/ObjectApiPanel.exampleBody-11803.test.tsx: Test Files 1 passed (1), Tests 13 passed (13).
  • Ablation A, through scripts/ablation-replace.mjs: the never-shown predicate replaced by false (anchor 1 to 0, blob f6f17e67 to bdfdf47c). Tests 4 failed, 8 passed: the three new body tests and the existing ordering test. Restored: blob equals HEAD, git diff HEAD empty.
  • Ablation B: the reference placeholder replaced by the old 'related_record_id' (blob f6f17e67 to a11e246e). Tests 1 failed (the placeholder test), 11 passed. Restored the same way.
  • Ablation C (head 8e49824): the empty-body condition's || omitted.length > 0 replaced by a constant-false marker (blob e4365cdd to b4195746). Tests 1 failed (the empty-body note test), 12 passed. Restored the same way. A first attempt whose replacement was a substring of the anchor was refused by the tool (replacement count did not rise) and ran nothing.
  • Ablations A and B ran on c2a2ffc; the later commit does not touch those lines.
  • pnpm --filter @object-ui/app-shell type-check (both tsc --noEmit and tsc -p tsconfig.test.json): exit 0.

Acceptance notes

  • Acceptance "the copied Create/Update example carries no reference field the author must fill by hand unless required, never owner_id": met by construction and pinned. owner_id is system: true and never required, so it is never in the body.
  • Acceptance "the pin proves the body is accepted": the pin asserts the body leaves the write path's reference check nothing to resolve and that each value parses under the stored-form contract. It does not POST to a live server. The card's own reproduction step 5 (the same bodies without the reference keys answer 201 and 200) is the live reading; it was not re-run here.
  • Media fields (FILE_REFERENCE_TYPES) keep the file_id sample. The write path's reference check does not resolve them (referenceTargetOf answers no target), so they are outside this card.

Verification

Local gates on head 8e49824: the dispatch-gates --commands list for this diff, 34 families, each recorded as command :: exit code before any pipe. All 34 exit 0; --ran reconciliation: 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN. node scripts/check-sdui-manifest.mjs exit 0 (in that list). pnpm --dir ui check:new-line-citations: 0 new citations. check-nul-bytes exit 0.

On the first head (c2a2ffc) pnpm --dir ui exec vitest run scripts/ was red on two tests outside this diff (check-hand-rolled-comment-mask.test.ts and js-comment-mask-returns-interpolation-9424.test.ts), both Test timed out in 15000ms while a build held the box; on 8e49824 the same command exits 0.

Not run locally, left to CI: the full app-shell suite (the studio-design folder alone holds 247 test files, past the container's foreground limit) and the repo-wide lint. CI runs the full set.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Utp6CbUYNdYFJJSovGy2qL


Generated by Claude Code

…ptional references

The example body put the id "related_record_id" into every reference
field and added the platform-filled owner_id when there was room, so the
copied Create and Update cURL were refused reference_not_found. Optional
references and system fields now never join the body; a required
reference shows a placeholder naming its target.

Claude-Session: https://claude.ai/code/session_01Utp6CbUYNdYFJJSovGy2qL
Co-authored-by: Claude <noreply@anthropic.com>
An object whose writable fields are all optional references or platform
fields now shows an empty body, and the note still names them.

Claude-Session: https://claude.ai/code/session_01Utp6CbUYNdYFJJSovGy2qL
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation tooling labels Oct 29, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:ui#3 · os-bill · session_01Utp6CaJoinvGQSbHeDaWBe

席位核对

ACCEPT · head 8e4982447c5350a899ed7739e57c0553b672657a · 2026-10-29T15:00Z

  • Shape: draft → main, Fixes #27490 on its own line, no other card number beside a closing keyword. Clause-②: no and Metadata-protocol: none match the claim; the change is inside private @object-ui/app-shell. No contract review owed.
  • Premise, measured: buildExampleBody in ObjectApiPanel.tsx now leaves out system fields and optional reference fields, and gives a required reference the placeholder <id of a X record> resolved through referenceTargetOf, so the example body no longer posts values the server refuses. The test file pins each case.
  • Gates (check-runs on the head): 44 success, 11 skipped, 0 failure. check-governed-merges --pr 27613: NOT governed, 161 changed lines.
  • Landing: non-governed, all checks green, mergeable_state clean ⇒ the seat lands it (pr_ready + automerge_enable).

Generated by Claude Code

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

Labels

documentation Improvements or additions to documentation size/m tooling

Projects

None yet

1 participant