Skip to content

objectql: a plain lookup write accepts a target the writer cannot read — the reference check probes it elevated, and only master_detail asks the caller's read door #29029

Open

Description

@objectstack-fleet

director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw
Ruled: 6663849489 · letter A (re-affirmed) + delegate read · 2026-11-05T16:47Z (supersedes 6573561091)

What happens

A write that names a record in a lookup field is checked for existence, never for the writer's access to it. A caller who reads a record as 404 can still store a reference to it.

Measured on @objectstack/objectql 18.2.0, live (objectstack-ai/duly main 98c188a, pnpm demo). The caller is a member whose permission set grants readScope: 'own' on the target object duly_duty (sharingModel: 'private'):

request (as the member) answer
GET /api/v1/data/duly_duty/<id> 404 RECORD_NOT_FOUND
POST /api/v1/data/duly_task with { duty: <id> } (duty is Field.lookup('duly_duty')) 201
PATCH /api/v1/data/duly_task/<own task> with { duty: <id> } 200
MCP create_record / update_record with the same payload 200
the same POST with an id that exists nowhere 400 reference_not_found

Where

packages/objectql/src/engine.ts (objectstack main cae71fe: assertReferencesResolve → referenceExists, around line 10521). For a plain lookup the probe runs under referenceCheckContext ({ ...context, isSystem: true }, tenant kept). The docblock states the choice: existence "is a fact about the database, not about the caller's row-level visibility", and refusing an unreadable target "would make the platform's own admin flows fail".

#22519 (ruling A) made the exception for master_detail. masterDetailHeaderExists asks the caller's read door first, and an unreadable header answers reference_not_found. The docblock then says "⛔ A plain lookup keeps the elevated probe above, unchanged" and "the plain lookup probe is not this rule's". The one-hop read for validation predicates (resolveOneHopRelated, authority: 'predicate') is also elevated for a tenant-walled target, so a validations[] script rule cannot express this either. lookupFilters is picker-only.

Why it matters

Asked

A declarable opt-in on a lookup field (for example referenceAccess: 'caller', name illustrative) that runs the #22519 caller-read-door check for that field. The elevated default stays for the admin-flow case the docblock names. An unreadable target then answers exactly reference_not_found, localized like the engine's own. System writes (isSystem) stay exempt, as for master_detail.

Workaround in place

objectstack-ai/duly#174: hook duly_task_duty_readable on duly_task (runAs: 'inherit', compares against the stored value so a re-save is not re-judged). It is meant to be deleted when the platform can declare this.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: none

    Triage: p2 · domain:server · area:access · security · 2026-11-02T07:02Z

    ⛔ Not a claim.

    • Read fresh. A reference write must not let a writer bind a record they cannot read. That is a security boundary on the write path, so it is labelled security, p2, domain:server. Handling goes through the PM session under the maintainer's standing rule for security findings; ⛔ add no further mechanism here. Triage has put the card to the maintainer.

    Generated by Claude Code

  2. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    domain:serverDomain lane — seat card indexed by label:pm:seat
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Maintainer ruling on this security card · 2026-11-02T07:51Z

    The maintainer answered triage's options in the triage session, verbatim: 「A+C 同意」.

    • A, how this card is fixed: domain:server fixes it from this card, as queued. The fix PR, its changeset and its records state the rule only: what a door must check, not how it can be got around. ⛔ No reproduction, probe or payload goes into the PR, its comments or this thread. Anything more that the fix needs goes through the PM session.
    • C, how the next one is filed: to the filing lane (the duly measurement). The standing rule is 「对于测试中遇到的安全问题,不适合提交issue 的,只是使用pm-dispatch技能派发」. A security finding (an authentication or authorization gap, a cross-tenant read, a bypassable limit, a secret leak) is dispatched through pm-dispatch to a dev, with its mechanism kept in the session, and is never filed as an issue. This card stays open because it is already public; the rule applies from now on.

    Generated by Claude Code

  4. added
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    and removed
    pm:queueReady for the PM dispatch loop
    on Nov 2, 2026
  5. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1

    决策请求 · #29029 修法形状 · 2026-11-02T08:26Z

    ⛔ Not a claim. 维护者已裁「A+C 同意」(triage 记录 6571949926 之前的 6571949926):本卡由 domain:server 修,只写规则不写复现。本席在派发前读代码发现,卡面所求的修法需要一个新的 lookup 字段键,那是 spec 契约面和新公开键名,按 SKILL.md 必须由维护者定,所以先停在这里问修法形状。

    Governing text: packages/objectql/src/engine-referential-integrity.ts(origin/main a4015ab47b)引用检查:master_detail 走 masterDetailHeaderExists(调用者读门,#22519 裁决 A),普通 lookup 走 referenceExists(提权探测,只判存在);engine 的 docblock 写明「普通 lookup 保持提权探测」,理由是拒绝不可读目标会让平台自己的管理流程失败。

    选项 做法 工作量
    A 默认收紧(席位推荐) 非系统上下文的写入,所有 lookup/user 引用都问调用者读门,读不到即 reference_not_found,与 master_detail 同一规则;系统上下文(isSystem)照旧豁免。不加新键 M,仅 packages/objectql;带前提:开发先实测仓内以用户身份写入、引用其读不到的记录的合法路径,有则停下回报,不硬做
    B 字段级开关(卡面所求) spec 新增一个 lookup 键(卡里举例 referenceAccess: 'caller',名字待定),只对声明的字段走调用者读门,默认仍提权 M+,spec 席加键 + 本车道实现;新键名要你批
    C 不改 维持现状,应用用 hook 自行检查 0;与已裁的 A 冲突

    os-decision-facets
    ① 项目长远合理性:A 让引用规则只剩一种(调用者能读才可引用,系统豁免),与 master_detail 对齐,缩小特例;B 留两种语义,靠作者记得开。
    ② 实际业务拉动:duly 今天在撞(任务引用决定排班唯一性,成员可占别人的期次),现靠应用手写 hook;A、B 都满足,B 只救声明了的字段。
    ③ 防 AI 犯错:A 是结构性的,写元数据的 AI 不需要知道任何开关;B 要求每个敏感 lookup 记得声明,漏写即静默不安全。
    ④ 创业阶段不扩散:A 不加公开面;B 新增一个永久契约键。
    Prior rulings read: "reference_not_found" lookup caller read → 35 hits; #22519 ruling A (master_detail reads the caller's door); thread: 2

    推荐 A,前提:仓内不存在需要以用户身份引用不可读记录的合法流程(开发先测,命中即回报,不改走 B)。

  6. zhuangjianguo commented on Nov 2, 2026

    @zhuangjianguo
    Collaborator

    director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw

    Brief-claimed-by: session_01QsR2jV5sBSzCYNEDgpYLJw · batch #453 · 2026-11-02T08:57Z

    Director seat (第 56 场). The fix-shape question (6572536863) is presented to the maintainer as batch #453 item 2 in the 总监决裁 thread; the ruling comment follows the maintainer's answer. Per the maintainer's ruling 6571949926 (A+C), the presentation states the rule only and carries no reproduction. ⛔ Not a claim.


    Generated by Claude Code

  7. zhuangjianguo commented on Nov 2, 2026

    @zhuangjianguo
    Collaborator

    director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw

    Ruling: batch #453 item 2 · letter A · maintainer 「同意」 2026-11-02T09:22Z

    Director seat (第 56 场; brief-claimed above in 6573082000 and presented in the 总监决裁 thread as batch #453 item 2, the fix-shape question of 6572536863, recommendation A). The maintainer's word is 「同意」 for the whole batch, so the fix shape is ruled A: the default tightens, no new key. Per the maintainer's earlier ruling 6571949926 (A+C), this comment states the rule only.

    What the ruling binds (A):

    Workload of the letter: packages/objectql only, red-first tests, full dogfood; a narrowing of the write accept set, so fix(objectql)!, Clause-②: yes (narrowing), CONTRACT_REVIEW_TIER (this seat).

    Execution: domain:server seat 5 dispatches as queued (6572536863); the lane seat moves the label. The Ruled: body line is written by this act.


    Generated by Claude Code

  8. added
    pm:queueReady for the PM dispatch loop
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Nov 2, 2026
  9. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#5 · os-steve · session_01ADHkmQKwKFCp1m6Pb6Q8c1

    Claim: PM loop round 7 · card thread · 2026-11-02T12:19Z
    Session: session_01ADHkmQKwKFCp1m6Pb6Q8c1 (the seat); the card thread is named in a follow-up claim once it reports its branch
    Account: os-steve (the seat's linked user; the card's assignee)
    Branch: pending: the card thread's harness-pinned branch, written into a follow-up claim before the dev starts
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#5
    Ruling-ref: 6573561091 (batch #453 item 2 · letter A · the default tightens, no new key)
    File surface: packages/objectql/src/ (the write's reference check in engine.ts / engine-referential-integrity.ts: lookup and user join master_detail on the caller's read door when the write carries no isSystem), the localized reference_not_found text if a new site needs it, their tests, changeset. ⛔ No packages/spec/**, no new field key.
    Container & model: M, mode:thread, model: the thread's default judgement tier, effort: high (p2, security)
    Clause-②: yes (narrowing): fix(objectql)!; contract review at CONTRACT_REVIEW_TIER by this seat on the delivered head
    Metadata-protocol: none
    Responsibility: the code is objectql's write-time reference check · a non-system write can point a lookup / user field at a record its caller cannot read · reached by every app whose users write lookups
    Thread-read: 6573561091
    Premise: holds (read at origin/main 5780fa49d: the master_detail branch asks the caller's read door; lookup keeps the elevated probe)
    Serial constraints cleared: this seat's #29253 (claude/project-thread-u66mdq) edits the same two files; the dev writes now and opens its PR only after #29253's PR merges, merging origin/main then. #29245 has merged. Precondition from the ruling: full dogfood and the example apps on the tightened engine before the PR opens; a legitimate non-system flow that breaks stops the work and is reported here.
    Resume-from: none: fresh from origin/main

    State: pm:queue → pm:dispatched, assigned to os-steve, recorded by this claim.

  10. 15 remaining items

  11. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-bill · session_01Utp6CYQjMkN514R78sCrTT
    os-dev-report

    {
      "issue": 29029,
      "status": "done",
      "branch": "claude/project-thread-m0wypr",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30672",
      "session": "session_01Utp6CYQjMkN514R78sCrTT",
      "premise_still_valid": true,
      "summary": "A write that is not a system write may name, in a lookup, user or master_detail field, only a record its caller's own read door returns; an unreadable target answers the field's localized reference_not_found, before the record's validation rules, on insert, update by id, bulk update and the validate preview. System writes keep their exemption, their order and their answer, and a flow run's write keeps its existence check; a failed caller read is refused, and only a target the registry does not hold is not judged. A delegate whose admin scope covers a business-unit subtree reads the units in it and none outside, bounded to the union of the held subtrees. The records-forms checklist item takes revision 7, the dogfood case and the plugin-security parity control are rewritten, and the engine docblock states the rule. After #30546 landed on main, a lookup or user value naming a sys_user row asks the caller's read door first, then the one elevated probe that answers the user's existence and its ban: a user the caller cannot read answers reference_not_found and its ban is not read (composition agreed by the seat).",
      "tests": "On 75a7c44d96 (main 14c67d446e merged at 93fce6c797): objectql Test Files 557 passed (557), Tests 11155 passed (11155); plugin-security Test Files 245 passed (245), Tests 5412 passed | 45 skipped (5457); plugin-audit Test Files 73 passed (73), Tests 1145 passed (1145) (objectql and plugin-audit on 93fce6c797; the one later commit edits one plugin-security test); typecheck objectql / plugin-security (test program included) / plugin-audit exit 0; pnpm lint exit 0. Ablations through scripts/ablation-replace.mjs, each restored to HEAD with git diff HEAD empty (suites read src/): delegatedUnitReadScope returns {} -> 6 red; middleware admission null -> 21 red; referencesCheckedBeforeRules returns false -> 17 red; returns true -> 4 red (system-write order control); a failed caller read returns the asked ids -> 9 red; an unresolvable target returns false -> 1 red; the sys_user branch without the caller read door -> 17 red.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack over the 36 changed paths on 75a7c44d96: 97 families, each exit code captured before any pipe, all 0; --ran: 97 derived, 97 run, 0 NOT-MEASURED, 0 UNRUN. First pass (earlier head): check-tenant-audit-census + self-test 1, check:system-context-census 1, check:query-options-erasure 1 (fixed); check:skill-examples and check:dual-build-cjs-loads 3 until the workspace build, then 0. main has moved 16 commits since 14c67d446e: a trial merge is clean and both census gates hold on it. CI check-runs: to be read on the PR.",
      "dogfood_battery": "75a7c44d96 · os-verify-lock: VERDICT command-exit 0 · Test Files 420 passed | 3 skipped (423) · Tests 3504 passed | 36 skipped (3540) · no failure",
      "line_budget": "36 files, +1289 -238 against the merge base (the parked base 60e40025b plus this card). Source: objectql 5 files +209 -90 (engine-referential-integrity, engine, engine-validate, engine-references-and-master-detail, engine-master-detail-related); plugin-security 2 files +77 -2 (delegated-admin-gate, security-plugin-authz-middleware). The rest is tests, the testkit, the checklist item, the changeset and 4 docs pages; engine-unreadable-reference-target.test.ts alone is +439.",
      "deviations": [
        "#30546 (#30205) landed on main mid-card and changed the same reference check: its rig and one pin assumed a caller with no sys_user read, whose answer under ruling 6663849489 is reference_not_found. The rig now gives the caller the read of a user's id, that pin holds the ban is read elevated, and a new pin holds the ruling's answer; ablation 7: 17 red. Seat agreed the composition in thread.",
        "predicate-related-read-tenant-scope: the rule's peer user now carries an expired ban (banned stays true, ban not in force), because the ban check now answers before the record's validation rules.",
        "content/docs/permissions/system-context.mdx (row 23 + generated register) and plugin-security src/__tests__/rig-users.testkit.ts sit outside the named file surface: required by check:system-context-census and check-tenant-audit-census.",
        "scripts/ablation-replace.mjs restores a file to HEAD: one run wiped an uncommitted edit (the referencesCheckedBeforeRules helper); it was re-added and committed before ablations 4-7.",
        "Two full dogfood/gate passes were superseded when main moved (9 commits, then 13 including #30546); each time main was merged, the closure rebuilt, and gates, suites and dogfood re-run on the new head."
      ],
      "files_changed": [
        ".changeset/29029-lookup-user-caller-read.md",
        "content/docs/api/error-catalog.mdx",
        "content/docs/data-modeling/fields.mdx",
        "content/docs/permissions/delegated-administration.mdx",
        "content/docs/permissions/system-context.mdx",
        "docs/qa/platform-checklist/areas/records-forms.json",
        "packages/objectql/src/engine-banned-user-reference.test.ts",
        "packages/objectql/src/engine-formula-hop-stored-metadata-body.test.ts",
        "packages/objectql/src/engine-hydration-stored-metadata-body.test.ts",
        "packages/objectql/src/engine-master-detail-related.ts",
        "packages/objectql/src/engine-predicate-related-master-detail-header.test.ts",
        "packages/objectql/src/engine-predicate-relationship.test.ts",
        "packages/objectql/src/engine-reference-tenant-scope.test.ts",
        "packages/objectql/src/engine-references-and-master-detail.ts",
        "packages/objectql/src/engine-referential-integrity.ts",
        "packages/objectql/src/engine-unreadable-master-detail-header.test.ts",
        "packages/objectql/src/engine-unreadable-reference-target.test.ts",
        "packages/objectql/src/engine-validate.ts",
        "packages/objectql/src/engine.ts",
        "packages/plugins/plugin-audit/src/audit-lookup-summary.test.ts",
        "packages/plugins/plugin-audit/src/audit-milestone-summary.test.ts",
        "packages/plugins/plugin-audit/src/audit-option-label-summary.test.ts",
        "packages/plugins/plugin-audit/src/implicit-reference-target-summary.test.ts",
        "packages/plugins/plugin-security/src/__tests__/rig-users.testkit.ts",
        "packages/plugins/plugin-security/src/delegable-scope-no-identity-positions.posture.test.ts",
        "packages/plugins/plugin-security/src/delegated-admin-gate.ts",
        "packages/plugins/plugin-security/src/delegated-admin-own-name-set.posture.test.ts",
        "packages/plugins/plugin-security/src/grant-holder-membership-refusal.test.ts",
        "packages/plugins/plugin-security/src/grant-permission-set-name.test.ts",
        "packages/plugins/plugin-security/src/org-admin-assignment-boundary.posture.test.ts",
        "packages/plugins/plugin-security/src/position-catalog-refusal.test.ts",
        "packages/plugins/plugin-security/src/predicate-related-read-tenant-scope.test.ts",
        "packages/plugins/plugin-security/src/security-plugin-authz-middleware.ts",
        "packages/plugins/plugin-security/src/sys-user-permission-set-window-order.test.ts",
        "packages/plugins/plugin-security/src/write-preview-field-gate-parity.test.ts",
        "packages/qa/dogfood/test/predicate-relationship-traversal.dogfood.test.ts"
      ],
      "mcp_calls": "15 - reads only: issue_read x7, pull_request_read x5, get_file_contents x3; no write tool",
      "api_writes": "2 - POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, PR #30672); POST /repos/objectstack-ai/objectstack/issues/29029/comments (post-stamped, this report)",
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": []
    }

    Report taken 2026-11-05T21:55Z.


    Generated by Claude Code

  12. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL

    Release: session_01Utp6Cbvcmv8YWFhFJwzjKL (domain:server#2) · reason: seat sign-off · to: pm:queue for the next server seat.
    Maintainer: 「开发中的尽快收工」, project chat, 2026-11-05T22:01Z.
    Resume-from: claude/project-thread-m0wypr@0c2b9851b6ee0eb79ca4b66f9d90f5f9d51a019d

    State at release. The PR is #30672, a draft at that head. It adds one wording-only commit after the head its Verification names (75a7c44d96), which states the rule only. The dev readings are in os-dev-report 6670586454. The seat has decided the PR's three open points: system writes keep the old order; the Deviations entry for the rule-control fixture stands; and public text states the rule only (done in the last commit).

    Owed, in order:

    1. The contract review, on the narrowing face, through record-recognisers --face narrowing and a fresh reviewer.
    2. The seat ACCEPT.
    3. The maintainer's per-PR word, because the PR is BREAKING. Ask through a decision thread.
    4. Merge main again before queueing.

    security#1 has been asked to read it (mailbox #30424).

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

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-bill · session_01Utp6Cbvcmv8YWFhFJwzjKL

    Resume-from: claude/project-thread-m0wypr@4ba91079fb (supersedes the head in Release 6670899065; still released to pm:queue)

    Since the release, the dev thread fixed two CI reds that the new rule caused, without loosening anything:

    • Test Core 8/8: an agent-ceiling suite that landed on main writes users that have no directory record. They are now seeded the way sibling suites seed them.
    • Test Core 4/8: in @objectstack/verify's parent-write-reach, the create probe filled a required lookup with a record the writer cannot read. The verifier persona now reads the probe's off-chain required reference objects.

    The second fix is product code, so the changeset adds '@objectstack/verify': patch. Owed by the next seat: before ACCEPT, add @objectstack/verify and this deviation to the PR body (the dev cannot edit it). security#1's hold on the PR is recorded; it stays draft and is not queued until that hold clears.

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

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

    Claim: PM loop round 1 · 2026-11-05T23:19Z
    Session: session_016WV4czvZykUqhYxYXSSDt4
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/project-thread-m0wypr (continued, PR #30672); the card thread's session is named in a claim amendment once the thread reports it
    Worktree: objectstack-issue-29029
    Domain: domain:server
    Seat: domain:server#4
    File surface: PR #30672's file list as it stands at 4ba91079fb (packages/objectql/** reference check and engine docblock, packages/plugins/plugin-security/** delegate business-unit read, packages/plugins/plugin-audit/**, @objectstack/verify parent-write-reach probe persona, docs/qa/platform-checklist/areas/records-forms.json, the four content/docs/** pages, one root .changeset/ file); no new surface. ⛔ packages/spec/** (stop on breach; explain in the report)
    Container & model: M, mode:thread, model: default (dispatch-gates --tier: no path-derived mandate; floor sonnet · default opus · ceiling fable; the narrowing face owes a CONTRACT_REVIEW_TIER review, run by the seat through a fresh reviewer), effort: xhigh (security)
    Clause-②: no
    Metadata-protocol: narrowed
    Responsibility: the engine's reference check in packages/objectql (probes a lookup / user target elevated, so a write may name a record its caller cannot read) | master_detail already asks the caller's read door; nothing covers lookup / user | any non-system writer over REST, MCP or a flow's user-context write; measured on the card
    Thread-read: 6671674952
    Premise: holds per os-dev-report 6670586454 and the security read 6671171164; the PR's two CI reds since then are fixed at 4ba91079fb (6671674952)
    Serial constraints cleared: re-derived by the card thread before its next push: merge main again before queueing (Release 6670899065 item 4)
    Resume-from: claude/project-thread-m0wypr@4ba91079fb (Release 6670899065, superseded head in 6671674952)

    Narrowing note: narrowing (BREAKING): a non-system write may name, in a lookup / user / master_detail field, only a record its caller's read door returns. Owed before the queue, in order (Release 6670899065): the contract-review-tier review on the narrowing face; the seat ACCEPT, with @objectstack/verify and the verify-persona deviation recorded in it (the relay cannot edit the PR body); the maintainer's per-PR word, because the PR is BREAKING; security#1's hold cleared; main merged again.

  17. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    Claim: PM loop round 2 · 2026-11-05T23:19Z · resumes release 6670899065 + 6671674952 (domain:server#2)
    Session: session_016WV4cytLmJxfAmgPVjUbbW
    Account: os-elon-musk (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: PR #30672 at claude/project-thread-m0wypr@4ba91079fb (the released head). No dev is ordered at claim time; if the review returns a must-fix, or main must be merged again, a card thread is ordered and named in an amendment
    Worktree: objectstack-issue-29029
    Domain: domain:server
    Seat: domain:server#1
    File surface: PR #30672's existing 39 files, unchanged at claim. The seat edits only the PR body (adds @objectstack/verify and the parent-write-reach probe deviation, per 6671674952)
    Container & model: security, seat-run; contract review at CONTRACT_REVIEW_TIER (fable) by a fresh reviewer, effort: xhigh
    Clause-②: yes (narrowing)
    Metadata-protocol: narrowed
    Responsibility: the reference check on plain lookup writes in packages/objectql | the elevated reference probe, which lets a non-system write name a target the writer cannot read | any tenant user who can write a record with a lookup to an object they cannot read
    Thread-read: 6671674952
    Premise: holds per ruling 6663849489 (A re-affirmed + delegate read) and os-dev-report 6670586454
    Serial constraints cleared: owed in order, per the release: ① contract review on the narrowing face (record-recognisers --face narrowing, fresh reviewer); ② the security#1 hold recorded on the PR clears; ③ seat ACCEPT; ④ the maintainer's per-PR word (BREAKING), asked through 总监决裁; ⑤ merge main again before queueing.

  18. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-elon-musk · session_016WV4cytLmJxfAmgPVjUbbW

    Yield: already claimed. domain:server#4's Claim 6672100060 is stamped before this seat's Claim 6672101946, so seat 4 holds #29029 and Claim 6672101946 is void. Labels and assignee stay as they are (same account).

  19. objectstack-fleet commented on Nov 5, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4czvZykUqhYxYXSSDt4

    Claim amendment · claim 6672100060 · 2026-11-05T23:24Z

    Branch: claude/project-thread-2l4nno (started at claude/project-thread-m0wypr@4ba91079fb, origin/main 06cccd32 merged in)
    Dev session: session_016WV4d1ZVVUQY6crnfvCXhg (the card thread this seat opened)
    Clause-②: yes (narrowing)
    Metadata-protocol: none
    Correction: the claim's Clause-②: no / Metadata-protocol: narrowed pair was wrong. The change narrows runtime data writes, not what a metadata author can write, so the lines follow ruling 6573561091 and PR #30672's body and changeset (patch). The contract-review-tier review on the narrowing face is still owed before the queue.
    Serial: seat 1's competing claim 6672101946 yielded (6672130517).

    Everything else in claim 6672100060 stands. PR #30672 is superseded by the PR this branch opens; the seat closes #30672 with a pointer then.

  20. objectstack-fleet commented on Nov 6, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#4 · os-elon-musk · session_016WV4d1ZVVUQY6crnfvCXhg
    os-dev-report

    {
      "issue": 29029,
      "status": "done",
      "branch": "claude/project-thread-2l4nno",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/30747",
      "session": "session_016WV4d1ZVVUQY6crnfvCXhg",
      "premise_still_valid": true,
      "summary": "Continuation of the released PR #30672: the branch starts at its released head 4ba91079fb and merges origin/main 06cccd32e1 (merge commit 0e54448624, no conflict, no file of the diff touched by the nine incoming commits); the delta against main is unchanged at 39 files, +1317 / -246. No code was changed. The behaviour of record is os-dev-report 6670586454: a non-system write may name, in a lookup, user or master_detail field, only a record its caller's own read door returns, answered reference_not_found before the record's validation rules; system writes keep their exemption and order; the delegate reads the business units its admin scope covers. New draft PR #30747 carries #30672's body updated to this head, plus the verify-persona fix (Test Core 4/8) and the agent-ceiling seeding fix (Test Core 8/8) in Deviations, @objectstack/verify in the changeset list, and states it supersedes #30672.",
      "tests": "All on 0e54448624 after a whole-workspace build of the merged tree (turbo run build --concurrency=2, 118/118 tasks, lock VERDICT command-exit 0). @objectstack/objectql: Test Files 557 passed (557), Tests 11168 passed (11168). @objectstack/plugin-security: Test Files 246 passed (246), Tests 5426 passed | 45 skipped (5471). @objectstack/plugin-audit: Test Files 73 passed (73), Tests 1145 passed (1145). @objectstack/verify: Test Files 48 passed (48), Tests 408 passed (408). Merge-touched joint behaviour (the banned user's work hand-over writes owner_id as the caller): core src/security/user-assigned-work.test.ts 12 passed, rest src/user-work-routes.test.ts 7 passed. typecheck (with test programs) objectql / plugin-security / plugin-audit / verify: each lock VERDICT command-exit 0. No ablation this round: no tested behaviour changed; the seven ablations recorded at 75a7c44d96 stand, the rule's source files having changed since only by main's unrelated navigation-contribution hunk in engine.ts.",
      "gates": "node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 0e54448624: 97 derived families, each run with its exit code captured before any pipe: 96 exit 0 on the first pass, pnpm check:type-check-debt exit 3 (its closure build queued behind the dogfood battery on the verify lock, 540 s timeout), re-run under the lock after the battery: exit 0 (re-measure OK, 0 ledger entries above their number). --ran: 97 derived, 97 run, 0 NOT-MEASURED, 0 UNRUN. Record: /mnt/project-files/server-lane-seat4/29029/gates-ran-0e54448624.txt. CI check-runs on #30747: in_progress at report time (PR opened just before this report).",
      "dogfood_battery": "0e54448624 · os-verify-lock: VERDICT command-exit 0 (held 27m38s) · Test Files 421 passed | 3 skipped (424) · Tests 3513 passed | 36 skipped (3549) · no failure",
      "mcp_calls": "5 - reads only: issue_read get x1, issue_read get_comments x1, pull_request_read get x2 (#30672, #30747), pull_request_read get_comments x1; no write tool",
      "api_writes": "2 - POST /repos/objectstack-ai/objectstack/dispatches (relay pr_create, PR #30747, body read back byte-identical 14260/14260); POST /repos/objectstack-ai/objectstack/issues/29029/comments (post-stamped, this report)",
      "deviations": [
        "No assignee and no review request on #30747: os-dev rule 2 leaves both to the seat at hand-over, and the dispatch allows no GitHub MCP write.",
        "main moved 18 commits (to 82142ed65c) while the build, suites, gates and dogfood ran; none touches a file of this diff. Not merged again before opening (AGENTS.md multi-agent section 10); the merge before queueing stays owed to the seat's sequence.",
        "pnpm lint (repo-wide scan) not run locally: CI-owned per os-dev; read from the PR's Lint and Repo Gates check-run.",
        "The first push answered 'remote rejected (fatal error in commit_refs_rules)'; a plain retry seconds later succeeded. GitHub-side transient, not a 403."
      ],
      "open_questions": [],
      "security_findings": "none",
      "out_of_scope_findings": []
    }

    Report taken 2026-11-06T00:29Z.


    Generated by Claude Code

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

Metadata

Metadata

Assignees

Labels

area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsdomain:serverDomain lane — seat card indexed by label:pm:seatpm:dispatchedDispatched to a dev agent by /pm-dispatchpriority:p2Medium: important, M3security

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions