Repository navigation
Closed
Labels
bugSomething isn't workingSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3Medium: important, M3
Description
domain:server#2 · os-bill · session_01Utp6CaP1iy4RSEQbW6177G
立卡门 ① · 已落地工作欠的后续:PR #32523(#32435)契约审查 6813417317 的 N1/N2/N3/N5。reach: 公开入口 /api/v1/mcp tools/call describe_object(stdio 同理)与 objectstack://objects/{name} 资源。Blocked-by #32523.
What
After #32523, describe_object serves per field readonly, but only the declared flag:
- Computed / runtime-owned fields. The engine drops a caller's write to a runtime-owned type (
isRuntimeOwnedField,RUNTIME_OWNED_FIELD_TYPESin@objectstack/spec/data, todayautonumber) and never stores aformulafrom the payload. A hand-authored{ type: 'autonumber' }literal (the builder injects the flag, a literal does not) and every formula field are servedreadonly: false, so an agent still thinks they are writable — the card's own complaint for that residue. - The caller's edit permission. A field the caller may read but not edit (FLS) is served
readonly: false; the write is then refused. The card asked for "what a write needs, under the caller's FLS"; fix(mcp, runtime): describe_object serves a select's options, defaults, readonly/system and the validation rule messages, under the caller's view #32523 delivers the read half. - Prose.
packages/mcp/src/mcp-http-tools.ts, theoptionFieldsOfjsdoc still ends "sodescribe_objectserves what it served before" — false since fix(mcp, runtime): describe_object serves a select's options, defaults, readonly/system and the validation rule messages, under the caller's view #32523. And the tool description should saydefaultValuemay be a token (NOW(),current_user) or a CEL envelope: omit the field rather than copy the value.
Acceptance
readonly: truefor a runtime-owned type and for a formula field on both twins (packages/mcp/src/mcp-server-runtime.tsdescribeServedObject,packages/runtime/src/domains/mcp.ts), pinned on both.- Item 2: either serve an edit verdict per field under the caller's view (e.g.
readonly: truewhen FLS denies edit) or state in the description thatreadonlyis the schema's, not the caller's; measure which the served view can answer and say which was done. - The jsdoc and description sentences fixed.
Clause-②: yeslikely (an answer widens); not BREAKING.
业务理由
谁受益:通过 MCP 写记录的 AI 代理。场景:代理读到公式、自动编号或无编辑权限的字段显示可写,照写后被丢弃或拒收,再重试。不做:#32435 想消除的「猜—被拒—重试」在这三类字段上仍在。
读者
domain:server 席位(拥有 packages/mcp 的席位),#32523 合并后。
查重
repo:objectstack-ai/objectstack is:issue describe_object readonly formula autonumber edit permission → 3 hits (#25815, #27377 closed QA runs; #6015 open umbrella). is:issue mcp describe_object readonly → 12 hits; open: #32435 (parent) and #6015 only. No duplicate.
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingdomain:serverDomain lane — seat card indexed by label:pm:seatDomain lane — seat card indexed by label:pm:seatpriority:p2Medium: important, M3Medium: important, M3
Activity
objectstack-fleet commentedon Nov 13, 2026
triage#1 · hotlong · session_01Q4EjjMnyLqJdzuktEmRPXH
Path: none
Triage: first-touch audit (pre-labeled card) ·
p3→p2· 2026-11-13T08:48Z⛔ Not a claim; the claim (if any) is unchanged.
Generated by Claude Code
objectstack-fleet commentedon Nov 13, 2026
domain:server#7 · os-tesla · session_01L9qibzuZJBQY4wUQFJbkfx
Claim: PM loop round 7, card thread · 2026-11-13T19:23Z · MCP p2 under the maintainer's 「mcp 相关 p2 任务也可以派发处理」 (2026-11-13T15:50:52Z)
Session:
session_01L9qibzwtSQM5u87bBFCujFAccount:
os-teslaBranch:
claude/project-thread-6xoa43Worktree:
objectstack-issue-32530Domain:
domain:serverSeat:
domain:server#7File surface:
packages/mcp/src/mcp-server-runtime.ts(describeServedObject),packages/runtime/src/domains/mcp.ts(thedescribeServedObjecttwin, plus its FLS read only under item 2a),packages/mcp/src/mcp-http-tools.ts(theoptionFieldsOfJSDoc and thedescribe_objectdescription),packages/mcp/src/skill-md.ts+ui/apps/console/src/pages/developer/objectstack-skill.tsonly if they restate it, their tests, one root changeset. Stop on breach.Container & model:
M,mode:thread,model: default (dispatch-gates --tier: no path-derived mandate; PM default),effort: highClause-②: yes (widening) —
describe_objectanswersreadonly: truewhere a write is dropped or refused; no input is newly refusedMetadata-protocol: none
Responsibility: the declared-only
readonlycomes fromdescribeServedObjectinpackages/mcpandpackages/runtime(objectstack) | the engine already drops runtime-owned and formula writes and FLS already refuses edit-denied ones | every MCP agent writing records fromdescribe_objectreaches it todayThread-read: 6848345288
Premise: re-measure — filed after PR #32523 merged; the dev measures both twins at
origin/mainfirstSerial constraints cleared:
mcp-http-tools.tsandruntime/src/domains/mcp.tsare shared with this seat's #32872 (PR #33134) and #31699: edits stay ondescribeServedObject, theoptionFieldsOfJSDoc and thedescribe_objectdescription; land serially, merge main after a sibling landsobjectstack-fleet commentedon Nov 13, 2026
domain:server#7 · os-tesla · session_01L9qibzwtSQM5u87bBFCujF
os-dev-report
{ "issue": 32530, "status": "done", "branch": "claude/project-thread-6xoa43", "pr": "https://github.com/objectstack-ai/objectstack/pull/33150", "session": "session_01L9qibzwtSQM5u87bBFCujF", "premise_still_valid": true, "summary": "Both describeServedObject twins (runtime HTTP bridge; mcp stdio bridge and the objects resource) now serve readonly from writeNeverSetsField: the declared flag, RUNTIME_OWNED_FIELD_TYPES (autonumber), a formula (isVirtualSearchField) or a stored field declaring an expression (bounded same-class fix, measured). Item 2 took option (b): the served view carries only the caller's read projection (getMetadataReadableFields/canReadObject), so the describe_object description now says readonly is the schema's, not the caller's edit permission; what (a) would need is in the PR's acceptance notes. Item 3: the optionFieldsOf JSDoc is corrected and the description gains the defaultValue token/expression sentence. skill-md.ts restates neither point, so no Skills-docs edit.", "tests": "At 819ea267: pnpm --filter @objectstack/mcp test 63/63 files, 1106/1106; pnpm --filter @objectstack/runtime test 596/596 files, 10581 passed 19 skipped, VERDICT command-exit 0; mcp + runtime typecheck VERDICT command-exit 0 (tsc + check:test-typecheck over tsconfig.test.json). Measured first: the runtime pins over the unfixed twin answered 1 failed / 3 passed (doubled, ticket_no, total served readonly false; engine drops or replaces each sent value; locked_note served false and the write refused PERMISSION_DENIED 403). 12 ablations via scripts/ablation-replace.mjs, all red and all restored to the HEAD blob: runtime twin whole/runtime-owned/formula/expression/declared arms 1 failed each, CONTROL 2 failed; mcp twin whole 4, runtime-owned 2, formula 2, expression 2, declared 3, CONTROL 5 failed. Source-imported suites, no dist leg.", "gates": "dispatch-gates --commands at 819ea267: 66 families, stdin closed, exits recorded before any pipe; --ran reconciles 66 accounted, 65 run, 1 NOT MEASURED: pnpm check:dual-build-cjs-loads exit 3 PREREQUISITE NOT MET (dist of packages outside the closure). check-plugin-teardown-shape --self-test exit 3 then exit 0 (48 cases) after fetching its pinned control 621a4876. pnpm lint exit 0. CI check-runs on #33150: in_progress at report time.", "dogfood_battery": "n/a — no ! in the PR title and Clause-② is yes (widening)", "mcp_calls": "4 — reads only: issue_read get + get_comments x2 (#32530), pull_request_read get (#33141 for the body shape); 0 writes", "api_writes": "2 — relay pr_create (#33150, with assignee os-tesla), and this os-dev-report comment via post-stamped", "open_questions": [], "security_findings": "none", "out_of_scope_findings": [ "carrier: none · noted, not filed: a summary field stays readonly false because the engine persists a caller-sent summary value (stripComputedWriteFields JSDoc), though COMPUTED_VALUE_TYPES calls it server-computed", "carrier: none · noted, not filed: the spec's only formula/virtual predicate is search-named (isVirtualSearchField); a write-named spec predicate would be its own spec change", "carrier: none · noted, not filed: an FLS edit verdict on describe_object (option a) needs getWritableFields per describe on the HTTP bridge, a widened ObjectSchemaMaskSecuritySurface in stdio-data-bridge.ts, a principal seam for the objects resource, and the contract's narrowed-by-read-projection statement" ] }