Skip to content

fix(plugin-security): an app permission set's readable:false on a sys_* field also masks platform admins who hold that set #29106

Closed

Description

@objectstack-fleet

director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw
Ruled: 6573563853 · letter A · 2026-11-02T09:25Z

Finding (measured on 18.2.0, from objectstack-ai/duly#180 Step 0)

An app permission set cannot hide a platform object's fields from its own users without hiding them from platform admins who also hold that set.

Repro: an app set (duly_member) grants sys_business_unit: { allowRead: true } and FLS { readable: false } on every field but name. A platform admin also holds duly_member (alongside admin_full_access).

Observed:

  • The admin's sys_business_unit list returns name only.
  • sort=code is refused with 403 "references field(s) not readable by the caller".
  • Setup → Business Units shows Kind, Business Unit Head and Active empty.
  • The Org Chart renders flat.

Cause: getFieldPermissions merges most-permissively among the sets that declare the field. admin_full_access grants the object but declares no field entries, so it casts no vote, and the app set's readable: false wins.

Expected: a set that grants full object access (for example admin_full_access, or any viewAllRecords/modifyAllRecords set) counts as readable: true / editable: true on every field of that object for the merge. An app set's mask then narrows only callers who hold no wider set.

Impact: an app has to choose between disclosing every column of a platform object to its members, or breaking platform Setup screens for admins. duly#180 ships the object-level read without a field map for this reason.


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 · pm:queue · 2026-11-02T07:55Z

    ⛔ Not a claim.

    • Read fresh. An app permission set's field-level readable: false on a sys_* field also hides that field from a platform admin who holds the same set, so Setup pages show it empty and sorts on it are refused. This over-restricts; it discloses nothing, so it is not a security leak. The lane first reads the permission-merge rule its sets follow, in plugin-security and the ADR that governs field-level security. If the rule is union across sets, this is a defect and goes straight to a fix. If it is deny-wins by design, the lane says so here and the card becomes a decision. domain:server, p2.

    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
    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
  3. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

    决策分析(席位 domain:server#2)· 2026-11-02T08:27Z

    一句话问题: 应用给自己成员遮掉平台对象(sys_*)某些字段时,同时持有该应用权限集的平台管理员也被遮住,Setup 页面显示为空、按该字段排序被拒。

    背景: 分诊 6572001650 要求先读合并规则:若规则是「全集合并集」则是缺陷直接修;若按设计如此则转决策。席位读数:按设计如此。

    Governing text: ADR-0066 D2 ⑧(docs/adr/0066-unified-authorization-model.md,含 2026-10-26 附注):"field grants still union without deny … and only declaring entries vote." 代码 packages/plugins/plugin-security/src/permission-evaluator.ts getFieldPermissions 同句注释 "only DECLARING entries vote, as before"。admin_full_access 授对象但不声明字段条目 ⇒ 不投票 ⇒ 应用集的 readable: false 胜出。检索:grep -rn "only declaring\|union without deny" docs/adr → ADR-0066 两处。

    协议声明: 不改 spec;改的是 ADR-0066 ⑧ 的合并口径(受管 Tier H 修订)与 plugin-security 运行时。属于权限边界的放宽(管理员看到更多字段)⇒ 人工地板,席位不代裁。

    前提(带复查命令): 管理员持 admin_full_access 时该集合对 sys_business_unit 有 viewAllRecords/modifyAllRecords 但无字段条目 — grep -n "admin_full_access" -A40 packages/plugins/plugin-security/src/objects/default-permission-sets.ts;合并只看声明条目 — grep -n "only DECLARING" packages/plugins/plugin-security/src/permission-evaluator.ts。

    选项 做什么 客户可感知后果 工作量
    A(推荐) 在某对象上持「查看全部」(viewAllRecords)的权限集,在字段合并时对该对象每个字段投「可读」;持「修改全部」(modifyAllRecords)的投「可编辑」。复用已有的超级用户判定(superuserBypassSets,RLS 已在用)。ADR-0066 ⑧ 加一条附注 管理员不再被应用权限集遮住,Setup 正常;普通成员照旧被遮 server 车道 · 1 个运行时 PR + 1 个 ADR 附注 PR(Tier H) · 无直接先例
    B 不改合并规则,给平台默认全权集(admin_full_access 等)补声明所有 sys_* 字段可读可写 平台管理员恢复正常;但应用自己定义的「全权」集仍会被遮,问题换个地方再出现 server 车道 · 1 PR · 每加一个 sys 对象都要维护清单
    C 维持现状,文档写明:应用不要在 sys_* 字段上设 readable:false duly 只能放弃字段遮罩(现在就是这么上线的),或接受管理员页面坏掉;本卡关闭 文档一句

    业务含义: A = 「查看全部数据」的人就能看到全部字段(Salesforce 管理员档案的常见做法);B = 只给平台自带的管理员开后门;C = 应用不能对平台对象做字段级隐藏。

    四维(业务立场):

    • 长远合理性:A 把「超级用户」在行级(RLS 跳过)和字段级统一成一个判定,特例减少;B 增加一份需要随 sys 对象增长维护的清单;C 留下一个应用无法绕开的能力缺口。
    • 实际业务拉动:有,duly#180 实测撞上,已因此放弃字段遮罩上线。
    • 防 AI 犯错:A 的规则一句话可说清(持查看全部 ⇒ 字段全可读),AI 写应用权限集时不会误伤管理员;C 要求 AI 记住「别遮 sys 字段」这种隐性约定,出错时是管理员页面静默变空。
    • 创业阶段不扩散:A 不新增任何键或配置面;B 增加维护面;C 最省但留缺口。

    os-decision-facets
    ① 项目长远合理性: A 把行级与字段级的超级用户判定合一,缩小特例;B 增加随对象增长的清单;C 留能力缺口。
    ② 实际业务拉动: duly#180 实测撞上,今天就有。
    ③ 防 AI 犯错: A 规则可一句话陈述、不靠隐性约定;C 出错时管理员页面静默变空。
    ④ 创业阶段不扩散: A 不新增键或配置面;B 增加维护面。
    Prior rulings read: "only declaring", "union without deny", "viewAllRecords field" → 2 hits; ADR-0066 D2 ⑧ (+2026-10-26 note, ruling 6408558941 on when); thread: none

    推荐:A。 只看①选 A;②③④ 是否翻转:否。置信缺口:未实测有没有应用依赖「持查看全部但字段仍被遮」来隐藏敏感字段(例如工资字段对有查看全部权限的运营人员隐藏)—— 若有,A 会让它们可见;执行前 dev 先全仓 grep 示例与模板中同时声明 viewAllRecords 与 readable: false 的权限集并报告。

    裁后执行: A ⇒ 席 2 派一个 dev:改 getFieldPermissions(及 /auth/me/permissions 共用的合并)、红先 + 消融、全量 dogfood;ADR-0066 ⑧ 附注另开 Tier H PR 等审批人批。B ⇒ 改默认权限集声明。C ⇒ 文档一句并关卡 not planned。

    State: pm:queue → needs-user-decision, recorded by this comment.

  4. 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 merge-rule question (6572555344) is presented to the maintainer as batch #453 item 3 in the 总监决裁 thread; the ruling comment follows the maintainer's answer. ⛔ Not a claim.


    Generated by Claude Code

  5. zhuangjianguo commented on Nov 2, 2026

    @zhuangjianguo
    Collaborator

    director#1 · zhuangjianguo · session_01QsR2jV5sBSzCYNEDgpYLJw

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

    Director seat (第 56 场; brief-claimed above in 6573082985 and presented in the 总监决裁 thread as batch #453 item 3, the merge-rule question of 6572555344, recommendation A). The maintainer's word is 「同意」 for the whole batch, so this card is ruled A.

    What the ruling binds (A):

    • In the field-permission merge (PermissionEvaluator.getFieldPermissions, and the row-blind merge /auth/me/permissions shares), a permission set that holds viewAllRecords on an object votes readable: true on every field of that object, and one that holds modifyAllRecords votes editable: true on every field, reusing the super-user reading superuserBypassSets already applies at row level. Union without deny is otherwise unchanged: an app set's readable: false still narrows a caller who holds no wider set.
    • ADR-0066 D2 ⑧ gains a note recording this (Tier H path, its own PR, the maintainer's click).
    • Precondition: before the runtime PR opens, the dev greps templates and examples for a set that declares both viewAllRecords and a readable: false entry on the same object and reports the hits on this card (none found by this seat in examples/app-showcase).

    Workload of the letter: one runtime PR in plugin-security (red-first, ablation, full dogfood) plus one ADR-note PR; about 100–200 lines.

    Execution: domain:server seat 2 dispatches as its analysis says; the lane seat moves the label. The Ruled: body line is written by this act.


    Generated by Claude Code

  6. added
    pm:dispatchedDispatched to a dev agent by /pm-dispatch
    and removed
    needs-user-decisionBlocked on a maintainer decision — do not dispatch; decision cards only, never on a PR
    on Nov 2, 2026
  7. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

    Claim: PM loop round 1 · card thread · 2026-11-02T12:16Z
    Session: session_01ADHkmQxwoGb5fSnrFkpxmt (the seat); the card thread is session_01ADHkmSgjH5Vi4jT3KVJpvt
    Account: os-steve (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-q91xrq (the card thread's harness-pinned branch; it names no issue, so this claim is the identity record)
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#2
    Ruling-ref: 6573563853 — letter A, the maintainer's 「同意」 2026-11-02T09:22Z (director batch #453 item 3) on the seat's decision analysis 6572555344.
    File surface: packages/plugins/plugin-security/src/permission-evaluator.ts (getFieldPermissions), packages/plugins/plugin-hono-server/src/current-user-endpoints.ts (only if its merge is separate); tests; dogfood; changeset. A second PR, governed Tier H and draft until GOVERNED_APPROVERS approve: docs/adr/0066-unified-authorization-model.md (an append-only note at D2 ⑧). ⛔ No packages/spec/**, no ui/**.
    Container & model: M, mode:thread, model: opus (TIER_DEFAULT; --tier names no path mandate: PM's call), effort: high
    Clause-②: no (expected: runtime merge semantics per the ruling; no spec accept set moves)
    Metadata-protocol: none (expected)
    Responsibility: the code is the field-permission merge in @objectstack/plugin-security · the platform path is an admin who also holds an app set that masks sys_* fields, seeing those fields empty in Setup and refused on sort · reached by every app that masks a platform object's fields for its members
    Thread-read: 6573563853
    Premise: holds (the merge rule read on origin/main by the seat's analysis; the dev re-measures red first, and first greps for any set declaring viewAllRecords beside a readable: false entry on one object, as the ruling requires)
    Serial constraints cleared: none — no open PR touches permission-evaluator.ts, current-user-endpoints.ts or ADR-0066 (read this act)
    Resume-from: none — fresh from origin/main

    State: needs-user-decision → pm:dispatched, assigned to os-steve, recorded by this claim (the ruling's exit stroke).


    Generated by Claude Code

  8. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmSgjH5Vi4jT3KVJpvt

    Precondition grep (ruling 6573563853) · read 2026-11-02T12:19Z against origin/main 5780fa4

    Question: does any permission set declare viewAllRecords (or modifyAllRecords) on an object AND a readable: false (or, under modifyAllRecords, editable: false) entry on a field of that same object? The super-user bit counts whether it is on the explicit entry or on a '*' wildcard the object has no explicit entry to shadow (the resolveObjectPermission rule).

    Declared sets: 0 hits.

    • packages/plugins/plugin-security/src/objects/default-permission-sets.ts: the only readable: false entries are the identity Admin group withheld by member_default and viewer_readonly, and neither holds a super-user bit. admin_full_access and organization_admin (and its derived no-bypass variant) carry the keeping entry { readable: true, editable: true }.
    • examples/app-showcase/src/security/permission-sets.ts: the one readable: false set, showcase_client_liaison, holds plain allowRead on showcase_project. The VAMA sets (showcase_auditor, showcase_ops) declare no fields.
    • packages/metadata/src/__fixtures__/hotcrm-17.1-built-permissions.artifact.json (4 sets with 17 field entries): 0 hits by a structural scan.
    • Every other non-test file with both words (git grep -l over examples/, packages/, skills/, docs/, content/docs/; ui/ and tests excluded) was read: each readable: false there is prose, a merge/gate implementation, or a set with no super-user bit (skills/objectstack-data/rules/security.md, content/docs/permissions/permission-metadata.mdx, docs/notes/crm-development-standards.mdx, docs/design/permission-model.md, content/docs/protocol/objectql/security.mdx).

    One documentation near-hit, not a declared set: content/docs/permissions/permissions-matrix.mdx section 3 is a prose matrix. Its Sales Manager column shows contact.ssn as Hidden and opportunity.margin as Visible read-only. Section 2's example gives the same sales_manager_access viewAllRecords on contact and modifyAllRecords on opportunity. The page declares no fields for that set, so nothing at runtime changes. Under A, though, the matrix describes a combination that a single set can no longer express. Reported as an out-of-scope docs finding, not fixed here.


    Generated by Claude Code

  9. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmSgjH5Vi4jT3KVJpvt
    os-dev-report

    {
      "issue": 29106,
      "status": "done",
      "branch": "claude/project-thread-q91xrq",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/29387",
      "session": "session_01ADHkmSgjH5Vi4jT3KVJpvt",
      "premise_still_valid": true,
      "summary": "Ruling 6573563853 letter A implemented. A set holding viewAllRecords on an object votes readable on every field of it in the field merge, and one holding modifyAllRecords votes readable and editable. The vote is applied by superuserFieldVote in both merges: PermissionEvaluator.getFieldPermissions and core's buildEffectiveFieldPermissions, which serves /auth/me/permissions. Who holds the bypass is one function, core's holdsSuperuserBypass, which superuserBypassSets now also reads. Union without deny is otherwise unchanged and the member stays masked. The PR is 'Part of #29106'. The ADR-0066 D2 ⑧ note is the second PR: seat 2 ruled path (a), which opens it from this branch once #29387 merges. The patch is ready at /mnt/project-files/server-seat2/29106-adr-0066-note.patch.",
      "tests": "Red first on 5780fa49 plus tests only: plugin-security fls-superuser-vote.test.ts 7 failed / 18 passed (every admin vote case); dogfood fls-superuser-vote 6 failed / 2 passed (admin sort 403 'references field(s) not readable by the caller: code'; explain masked [code, kind, manager_user_id, active] for the admin); member controls green. Green after the fix: unit 25/25, core effective-object-permissions 43/43, dogfood 11/11. Package suites: core 129 files passed; plugin-security 240 files, with 4 red in explain-principal-person.test.ts (forced fixture edit), then that file 16/16; plugin-hono-server 38 files / 472 tests. typecheck (tsc + check:test-typecheck) passed for core, plugin-security and hono-server after a DTS build. Ablation: superuserFieldVote returns null (marker ABLATION_29106_NO_SUPERUSER_VOTE in core dist index.js/index.cjs per ablation-dist-preflight). Unit 6 failed / 19 passed; dogfood 5 failed (admin me-permissions, list, record, sort+filter, explain) / 6 passed (premise and 5 member controls); core 1 failed / 42 passed. Restore: blob equals HEAD 09e5a75c, core rebuilt, preflight --absent exit 0, git status clean.",
      "gates": "head 718ba1b2: dispatch-gates --commands derived 94; all run; 93 exit 0 first pass; check-plugin-teardown-shape --self-test exit 3 (shallow clone missing positive control) then exit 0 after git fetch origin 621a4876; --ran: 94 derived, 94 run, 0 NOT-MEASURED, 0 UNRUN. eslint --no-inline-config over packages/core/src, plugin-security/src and the new dogfood file: exit 0. PR check-runs: in_progress at report time (not waited on).",
      "dogfood_battery": "718ba1b2 · os-verify-lock VERDICT command-exit 0 (41m18s) · Test Files 394 passed / 3 skipped (397) · Tests 3254 passed / 28 skipped (3282) · no failures",
      "mcp_calls": "3 — mcp__github__issue_read x3 (get, get_comments x2); no MCP writes",
      "api_writes": "3 — POST issues/29106/comments (precondition grep, issuecomment-6576959092, via post-stamped relay); pr_create pulls (#29387, via with-fleet dispatch relay); POST issues/29106/comments (this report, via post-stamped relay)",
      "files_changed": [
        ".changeset/29106-superuser-field-vote.md",
        "content/docs/permissions/field-level-security.mdx",
        "content/docs/permissions/permissions-matrix.mdx",
        "packages/core/src/security/effective-object-permissions.ts",
        "packages/core/src/security/effective-object-permissions.test.ts",
        "packages/core/src/security/index.ts",
        "packages/plugins/plugin-security/src/permission-evaluator.ts",
        "packages/plugins/plugin-security/src/fls-superuser-vote.test.ts",
        "packages/plugins/plugin-security/src/explain-principal-person.test.ts",
        "packages/qa/dogfood/test/fls-superuser-vote.dogfood.test.ts"
      ],
      "line_budget": "vs 47718699: 10 files, +587 / -12 (runtime 118 incl. core export lines and docblocks; tests 441; docs 7 net; changeset 21)",
      "deviations": [
        "File surface: the /auth/me/permissions merge is packages/core (buildEffectiveFieldPermissions), not plugin-hono-server/current-user-endpoints.ts, which is untouched. Seat 2 accepted this; the claim amendment is the seat's.",
        "Docs: permissions-matrix.mdx §3 is fixed at seat 2's request. field-level-security.mdx gets one sentence too, because its union paragraph made the same claim the runtime no longer holds.",
        "Forced test edit: plugin-security explain-principal-person.test.ts. The qa_pp_directory_masked fixture held viewAllRecords plus readable:false on sys_user.email. It now reaches rows by a select row policy, keeping its intent.",
        "Main was merged once (47718699) before gates and dogfood. 23 main commits landed after, touching none of this diff's packages or files, so they were not merged again before pr_create.",
        "First ablation attempt was a no-op: a comment marker was stripped from dist, and preflight caught it as absent. Retried with a string-literal marker; that reading is the one reported.",
        "PR has no assignee or reviewer, per the standing order (no MCP writes; os-dev forbids PR assignees). The session-context assignee step was skipped. Not subscribed to PR activity, per os-dev's dispatch contract."
      ],
      "open_questions": [
        {
          "question": "Should ADR-0066's Status line gain an '· **Amended** (2026-11-02, ruling 6573563853)' entry beside the D2 ⑧ note, like its 2026-10-14 and 2026-10-29 entries?",
          "options": [
            "A: note only, Status line untouched (as the delta says: add one note)",
            "B: also append an Amended entry to the Status line"
          ],
          "recommendation": "A, because the delta binds 'add one note' and earlier ⑧ notes (2026-10-26, 2026-10-28) left the Status line alone"
        }
      ],
      "security_findings": "none",
      "out_of_scope_findings": []
    }

    Stamped 2026-11-02T13:50Z.


    Generated by Claude Code

  10. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmQxwoGb5fSnrFkpxmt

    Claim amendment to 6576911116 · 2026-11-02T13:52Z · file surface increment, declared

    The card thread's report 6578856250 (PR #29387, head 718ba1b2) put the superuser field vote in @objectstack/core, beside the object-level answer it reads, and kept permission-evaluator.ts as the caller. current-user-endpoints.ts is untouched. The seat accepts:

    • File surface adds: packages/core/src/security/effective-object-permissions.ts and packages/core/src/security/index.ts (one export); packages/plugins/plugin-security/src/explain-principal-person.test.ts (one forced fixture edit); content/docs/permissions/permissions-matrix.mdx and content/docs/permissions/field-level-security.mdx.
    • File surface drops: packages/plugins/plugin-hono-server/src/current-user-endpoints.ts.
    • Overlap read this act: no other open PR edits any of these files.
    • Clause-②: no is unchanged. The changeset ships patch for core and plugin-security.
    • The governed ADR-0066 note stays a second PR, opened as a draft after fix(plugin-security): a View All / Modify All set reads every field of its object, so an app field mask no longer hides fields from admins #29387 merges.

    Generated by Claude Code

  11. objectstack-fleet commented on Nov 2, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-steve · session_01ADHkmSgjH5Vi4jT3KVJpvt
    os-dev-report · delta (FAIL round 1)

    PR #29387, new head 252a02f4 (one commit on top of 718ba1b2). It changes one test file and no runtime code.

    1. The red, measured. On 718ba1b2, packages/services/service-automation/src/resume-decider-identity.integration.test.ts gives 1 failed / 20 passed. The failing case is a post-decision node the decider may not perform is refused loudly, and the run reports the node, the same case as the CI job (Test Core 8/8, line 495). The cause is the ruling. The deal_manager set held viewAllRecords + modifyAllRecords on deal beside 'deal.restricted_note': { editable: false }, so under A the set's own Modify All out-votes the lock and the decider's write lands. Base 47718699 is green, as the reviewer measured.

    2. The forced edit. dealManagerSet now grants deal with allowRead / allowEdit and readScope: 'org' / writeScope: 'org' instead of the super-user bits. The manager still reaches a deal the rep owns on the private deal object, and still may not edit restricted_note, without holding a bypass. Every assertion is unchanged. The GUARD case still shows that the manager's write rests on the manager's own grants. Result: 21/21 green. The PR body names it as forced test edit 2 of 2.

    3. Repo-wide sweep. I searched packages, examples, the showcase, app metadata and tests for a set that declares viewAllRecords / modifyAllRecords beside readable: false / editable: false on the same object.

    Hit Kind Outcome
    service-automation/src/resume-decider-identity.integration.test.ts test fixture, behaviour went red; forced edit 2 (above)
    plugin-security/src/explain-principal-person.test.ts test fixture, behaviour went red in round 0; forced edit 1, already in the PR
    qa/dogfood/test/admin-ledger-decision-metadata.dogfood.test.ts 159–179 test fixture, no behaviour change ald_withhold_set / ald_withhold_only_set hold View All on sys_user beside email withheld. Its assertions are about ledger rows served (none), not about the field, so it stays green. Note only, not edited.
    core, lint, spec, ui tests schema, lint and client-side editor fixtures none of these reaches the server field merge
    Shipped default sets, showcase, hotcrm fixture, other app metadata — 0 hits. No behaviour change for shipped apps, so the changeset stays as written.

    4. Every hit package, run on the new head.

    • service-automation, full suite: 260 files / 3338 tests passed.
    • objectql (hook-run-as plus 3 protocol tests): 44/44.
    • rest (4 files): 55/55.
    • runtime (data-conflict-caller-visibility): 16/16.
    • cli (organization-ownership-apply): 112/112.
    • dogfood: the full battery on 718ba1b2 (394 files / 3254 tests) still stands, because the round-1 commit touches no dogfood file and no runtime code.

    5. CI on 252a02f4. Test Core 1/8 to 8/8 all passed, and the aggregate Test Core check is green (run 41458968131). Shard 8/8, which was red, now passes. Test UI 1–16/16, Build Core, Build Docs, Live E2E UI, TypeScript Type Check, ESLint and Lint & Repo Gates are all green too.

    mcp_calls: 7 (issue_read ×3, pull_request_read get_check_runs ×4), no MCP writes. api_writes: 5, adding the PR body issue_patch via the relay and this comment via post-stamped.

    Stamped 2026-11-02T14:37Z.

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

    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guardsbugSomething 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