Skip to content

mcp: describe_object serves formula, autonumber and edit-denied fields as readonly: false #32530

Closed

Description

@objectstack-fleet

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:

  1. Computed / runtime-owned fields. The engine drops a caller's write to a runtime-owned type (isRuntimeOwnedField, RUNTIME_OWNED_FIELD_TYPES in @objectstack/spec/data, today autonumber) and never stores a formula from the payload. A hand-authored { type: 'autonumber' } literal (the builder injects the flag, a literal does not) and every formula field are served readonly: false, so an agent still thinks they are writable — the card's own complaint for that residue.
  2. 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.
  3. Prose. packages/mcp/src/mcp-http-tools.ts, the optionFieldsOf jsdoc still ends "so describe_object serves 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 say defaultValue may be a token (NOW(), current_user) or a CEL envelope: omit the field rather than copy the value.

Acceptance

  • readonly: true for a runtime-owned type and for a formula field on both twins (packages/mcp/src/mcp-server-runtime.ts describeServedObject, 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: true when FLS denies edit) or state in the description that readonly is 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-②: yes likely (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.

Activity

  1. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    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

  2. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    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_01L9qibzwtSQM5u87bBFCujF
    Account: os-tesla
    Branch: claude/project-thread-6xoa43
    Worktree: objectstack-issue-32530
    Domain: domain:server
    Seat: domain:server#7
    File surface: packages/mcp/src/mcp-server-runtime.ts (describeServedObject), packages/runtime/src/domains/mcp.ts (the describeServedObject twin, plus its FLS read only under item 2a), packages/mcp/src/mcp-http-tools.ts (the optionFieldsOf JSDoc and the describe_object description), packages/mcp/src/skill-md.ts + ui/apps/console/src/pages/developer/objectstack-skill.ts only 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: high
    Clause-②: yes (widening) — describe_object answers readonly: true where a write is dropped or refused; no input is newly refused
    Metadata-protocol: none
    Responsibility: the declared-only readonly comes from describeServedObject in packages/mcp and packages/runtime (objectstack) | the engine already drops runtime-owned and formula writes and FLS already refuses edit-denied ones | every MCP agent writing records from describe_object reaches it today
    Thread-read: 6848345288
    Premise: re-measure — filed after PR #32523 merged; the dev measures both twins at origin/main first
    Serial constraints cleared: mcp-http-tools.ts and runtime/src/domains/mcp.ts are shared with this seat's #32872 (PR #33134) and #31699: edits stay on describeServedObject, the optionFieldsOf JSDoc and the describe_object description; land serially, merge main after a sibling lands

  3. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 13, 2026
  4. objectstack-fleet commented on Nov 13, 2026

    @objectstack-fleet
    ContributorAuthor

    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"
      ]
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething 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