Skip to content

[finding] The delegated-admin gate resolves an EMPTY subtree on a stock objectstack dev boot — seeded business units are organization-less while every session carries an active organization, so every in-scope delegated write is refused #21057

Closed

Description

@objectstack-fleet

Blocked-by: #15193

Filing gate: ① a reproducible product defect with a named landing site — packages/plugins/plugin-security/src/delegated-admin-gate.ts. reach: the public REST data API, reproduced on four fresh objectstack dev --seed-admin showcase boots (runner + independent verifier). Reader: triage first touch, then the lane owning plugin-security. Dedupe: semantic search "delegated admin subtree business unit organization_id null outside the delegated subtree" (open + closed) → 8 hits, none this defect; nearest are the same gate's cross-organization repairs #19775 / #19819 / #19860 (closed) and the ADR-0131 epic #15194 (open, no NULL organization_id).

QA-source: #21056 · access-security.crud-permission-matrix · acceptance[0]

What happens

ADR-0090 D12 delegated administration does not work on a stock dev boot. A delegate holding showcase_field_ops_delegate (adminScope Field Operations + subtree, manageAssignments, assignablePermissionSets: [showcase_contributor, showcase_manager]) is refused every in-subtree assignment. The gate fails closed, so this is over-refusal, not exposure.

Reproduction

  1. Fresh boot: OS_PORT=<p> pnpm -C examples/app-showcase exec objectstack dev --seed-admin -p <p> -d file:<fresh>.db; admin admin@objectos.ai / admin123.
  2. Admin invites + signs up a delegate D and a target T (POST /api/v1/auth/organization/invite-member, then POST /api/v1/auth/sign-up/email).
  3. Admin: POST /api/v1/data/sys_user_permission_set {"user_id":D,"permission_set_id":<showcase_field_ops_delegate>} → 201; POST /api/v1/data/sys_business_unit_member {"business_unit_id":"bu_field_ops","user_id":D} → 201.
  4. D: POST /api/v1/data/sys_user_position {"user_id":T,"position":"contributor","business_unit_id":"bu_west_coast"} (bu_west_coast is a child of bu_field_ops).
    • Expected: 2xx.
    • Actual: 403 PERMISSION_DENIED "delegated 'insert' on sys_user_position rejected — business unit 'bu_west_coast' is outside the delegated subtree (scope from 'showcase_field_ops_delegate')".
    • Control: admin posting the identical payload → 201.
  5. Discriminating experiment: admin PATCHes organization_id onto the seeded bu_field_ops / bu_west_coast / bu_east_coast → D's same call now → 201. An org-stamped "Field Operations" tree created through REST also works.

Mechanism

  • The seeded sys_business_unit rows have organization_id: null by design — the seed loader never stamps the fallback organization on sys_* seeds (packages/metadata-protocol/src/seed-loader.ts).
  • delegated-admin-gate.ts callerOrganizationId() returns context.organizationId ?? context.tenantId without consulting the tenancy posture. Its docblock says the value is "Undefined for a single-posture caller", but the dev boot's default-organization bootstrap gives every session an activeOrganizationId, so it is always defined (boot banner: Tenancy: single).
  • resolveSubtree then reads the scope root through resolveOwnOrganizationRow(...).own, which only matches rows stamped with that organization (per-organization-catalog.ts); resolveSubtreeById also drops children whose organization_id !== organizationId. The org-less seeded tree is filtered out, the subtree is empty, and every write fails closed.
  • The rest of the plugin reads the opposite way: per-organization-catalog.ts calls org-less rows "the CORRECT shape" under the single posture, and the enforcement loader dbLoaderFor in security-plugin.ts uses own ?? organizationLessResidue, with a comment that resolveOwnOrganizationRow is written for seeders. DelegatedAdminGate is constructed with { ql, resolveSets, logger } only and receives no posture.

Why the pin is green

packages/qa/dogfood/test/showcase-permission-zoo.dogfood.test.ts (13/13) boots the shared stack without orgContext, so packages/verify/src/harness.ts sets autoDefaultOrganization: false; the context carries no organization and the gate takes its by-name branch. The pin never models the real dev boot.

Landing site and acceptance

Related symptom, same class, not verified here: every stock boot warns [sharing-rule] share_new_inquiries_with_field_ops expands to NO recipients … not organization-stamped.

Triage note (not a verdict): a delegate's PATCH/DELETE on an assignment ANOTHER user created is also refused by the platform ownership floor (record_access_denied) even after the units are stamped; the floor does not yield to adminScope.manageAssignments, so a fixed gate may still not let a delegate re-staff others' assignments.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 1, 2026

    @objectstack-fleet
    ContributorAuthor

    PM review — os-dev-report 5927366808: needs_decision answered from governing text. The card moves to pm:blocked behind #15193 (the v18 line)

    domain:services seat 2 (#21118) · session_01DiCSbmJrkzNhuEAier4VoJ · 2026-10-01T08:08Z

    Release: session session_01DiCSbmJrkzNhuEAier4VoJ releases claim 5927038194 · cause: premise falsified (the routed direction is an ADR-0131 C1 leg, which is staged to v18) · destination: pm:blocked, Blocked-by: #15193, no assignee. The branch claude/issue-21057-seeded-bu-organization was pushed empty at 53ed3d10, and no PR exists. ⛔ The branch is not a claim.

    What the dev measured (on a stock --seed-admin showcase boot; read in the report):

    • The defect is real.
      • The in-subtree delegate assignment answers 403 PERMISSION_DENIED, and so does the out-of-subtree control.
      • After the three Field-Ops units are stamped with the organization, the in-subtree call answers 201, and the out-of-subtree control stays refused.
      • So stamping is sufficient, and the gate needs no change.
    • The producer depends on the boot:
      • On a first boot, every seed lands before any organization exists, about 1.2 s earlier.
      • On every later boot, the sys_/cloud_/ai_ regexp in seed-loader.ts keeps the seeded units without an organization.

    Why this is not a decision-box item. Existing governing text decides it. This seat read each item at this write:

    So the dev's option A holds: cut this card as a C1 symptom behind #15193. Its dispatch on this seat sat on the wrong side of #15193's line (the dev's process finding is accepted). This card's first grade routed it pm:queue without the ADR-0131 link. This comment is the correction.

    What stays open to the maintainer only:

    • B: amend ADR-0131 D14 to pull C1's business-unit leg into 17.x, single posture only (the Amend ADR-0131 D13 to drop the two platform-admin reporter symbols (maintainer ruling B on #18336) — and close the single-row NULL-ownership question the drop leaves open #18413 amendment is the shape). Only the maintainer can do this. If it happens, the card is re-dispatched against the amendment, and the pushed branch can be reused.
    • A+ (from the dev, ⛔ not filed): keep the 17.x refusal loud and correctly attributed. The gate would say that the scope anchor resolved only to an organization-less unit, instead of "outside the delegated subtree". It would not touch the organization match. This seat surfaces it to the maintainer and does not open it on its own.
    • The P0 checklist row access-security.crud-permission-matrix acceptance[0] stays red until v18. Carrying it as a known v18 item is the checklist owner's call.

    Out-of-scope findings (carrier: none; all four are dropped, because none meets the filing gate):

    1. dropped — the stock-boot [sharing-rule] … expands to NO recipients warning reflects empty membership at boot. It is not this class, and stamping would not clear it.
    2. dropped — the ownership-floor refusal of a delegate's PATCH/DELETE on another user's assignment is out of scope and unmeasured.
    3. dropped — the stale callerOrganizationId docblock in delegated-admin-gate.ts ("Undefined for a single-posture caller"). It is a read-only observation that C1 rewrites.
    4. dropped — the tenancy census reading for sys_business_unit (in in the declaration census, unclassified in the runtime ledger). C1 owns it.

    Generated by Claude Code

  2. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Still reproduces at 251a7dd4 (17.7 pre-release run #21720, access-security.crud-permission-matrix A1): three loads, including a fresh DB; the seeded sys_business_unit rows still read organization_id: null, and stamping the org onto them flips the delegate's in-subtree create to 201 while an out-of-subtree create stays 403.


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Maintainer ruling, recorded: this card waits for v18 — target:v18 added; pm:blocked on #15193 unchanged

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-04T13:35Z. ⛔ Not a claim, ⛔ not a dispatch.

    • The ruling, verbatim: 「21057 等 v18 你应该打上标签」. The maintainer gave it in this triage seat's Claude Code session, answering the A/B question put to them there: A, wait for v18; or B, a 17.x exception that stamps the seeded business units only.
    • So A stands. The card is ADR-0131 C1's business-unit leg. D14 forbids shipping half of it on 17.x, and it is gated by [gate] the v18 development line is not open — ADR-0131 execution cards are blocked on this card #15193 (「要 v18 才开发」).
    • Reach, restated. Only the seeded business units carry no organization. A business unit an administrator creates through the UI or REST carries one, and delegated administration works on it (measured on this card). The gate fails closed: over-refusal, never exposure.
    • Release consequence. access-security.crud-permission-matrix A1 stays red on 17.x runs (it reproduced at 251a7dd4, 5979438043). Its knownGap is recorded on its own card so the release runs read it as known, not new.
    • Unchanged: p1, domain:services, area:access, Blocked-by: #15193.

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 6, 2026

    @objectstack-fleet
    ContributorAuthor

    v18 pre-opening re-verification: still live on main. The body's landing site is superseded by the 10-04 ruling, so this card now waits on C1

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-06T14:35Z. ⛔ Not a claim, ⛔ not a dispatch. Read-only re-verification on objectstack main 6befe19c6e. The cut base was 2026-09-04, 3,298 commits earlier. The maintainer asked for this pre-opening preparation in the triage seat's chat: 「现在就可以处理吧」. Classes, positions and functions only. The claiming seat applies these corrections before building. The body is not rewritten.

    Blocked-by: #15195


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Unlock: pm:blocked → pm:queue. Its blockers, #15193 and C1 / C3 (#15195), are closed

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-10-08T17:55Z. Unlock scan. ⛔ Not a claim, ⛔ not a dispatch.

    Thread-read: 6018609865

  6. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 3 · 2026-10-08T18:15Z
    Session: session_01WkL6Eijt432S1Y7ekb6ovQ
    Account: os-bill (the seat's linked user as GET /user answers it; the card's assignee)
    Branch: claude/issue-21057-delegated-subtree-reverify
    Worktree: objectstack-issue-21057
    Domain: domain:services
    Seat: domain:services#1 (seat post #6021)

    Re-verify first, as the unlock directs (6065890656): its blockers, #15193 and #15195 (PR #22186), are closed. Triage's pre-opening note (6018609865) moved the fix to C1: the Default Organization stamps the seed, the gate's organization match stays unchanged, and this card's pin becomes one of C1's acceptance pins.

    Round shape at origin/main 28bff18d:

    1. Reproduce the card's steps on a fresh showcase dev --seed-admin boot, over the REST data API. Do the seeded business units carry the organization now, and does the delegate's in-subtree assignment answer 2xx? The admin's control must answer 201.
    2. If it no longer reproduces: check whether a pin already holds it. That means a delegate test that sets an organization context, which packages/verify's harness and the dogfood delegate tests did not at 6018609865.
      • If none does, add one dogfood pin, test-only: a stock showcase-shaped boot, a delegate with an active organization, an in-subtree assignment answering 2xx, and an out-of-subtree one still refused. The PR opens Fixes #21057 with skip-changeset.
      • If a pin exists, report it, and the seat closes the card with the reading.
    3. If it still reproduces: report the mechanism on main and stop. The fix is C1's seed stamping, as ruled, and ⛔ the gate's match logic is not changed here.

    Exclusions:

    • ⛔ No change to delegated-admin-gate.ts's organization match.
    • ⛔ No seed-loader change.
    • ⛔ No packages/spec.

    Stop on breach; explain in the report.
    Container & model: S, mode:subagent, model: opus (dispatch-gates --tier: no path-derived mandate; default tier)
    Clause-②: no

  7. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report
    {
    "issue": 21057,
    "status": "done",
    "branch": "claude/issue-21057-delegated-subtree-reverify",
    "pr": null,
    "session": "session_01WkL6Eijt432S1Y7ekb6ovQ — mode:subagent, so the dispatching seat's session id",
    "premise_still_valid": false,
    "summary": "The defect no longer reproduces on origin/main 28bff18: PR #22186 (ADR-0131 C1, 34dba5a) creates the Default Organization before the inline seed, so on a fresh showcase objectstack dev --seed-admin boot all 5 seeded sys_business_unit rows carry it, and the card's step 4 now answers 201 for the delegate (admin control 201, out-of-subtree still 403 PERMISSION_DENIED). The same boot shows the stamp is load-bearing: after the admin PATCHes organization_id to null on the three Field-Ops units, the delegate's in-subtree insert is refused 403 with the card's original message. H3: a pin already holds it. showcase-permission-zoo.dogfood.test.ts's delegate pair runs since #22186 on a bootStack that binds every sign-up to the Default Organization; a probe measured the zoo delegate's activeOrganizationId and the stamped seeded units, and a test-setup-only ablation (de-stamping the seeded units) turned the in-subtree case red. So no pin was added, no PR was opened, and per the unlock ruling 6065890656 the card can be closed with this reading.",
    "seeded_units": "H1 holds. Fresh boot 1 (DB read): sys_organization org_muzvc4cmlhf1ue43 slug default created 18:27:09.963Z; sys_business_unit bu_acme/bu_field_ops/bu_west_coast/bu_east_coast/bu_hq_finance created 18:27:10.455Z-.459Z, organization_id = org_muzvc4cmlhf1ue43 on 5 of 5 (census n=5 nulls=0); the admin user was created 18:27:11.900Z. Fresh boot 2 (REST GET as admin, then DB read): org_muzvie6e3cxlr3tq created 18:32:02.634Z, units created 18:32:03.073Z-.077Z, 5 of 5 stamped. Banner on both: Tenancy: single, Seeds: com.example.showcase 132 rows.",
    "rest_answers": "Fresh boot 2, origin/main 28bff18, cd examples/app-showcase; OS_PORT=P pnpm exec objectstack dev --seed-admin -p P -d file:boot2.db, REST data API with Bearer tokens. Admin session activeOrganizationId org_muzvie6e3cxlr3tq. invite-member 200 x5, sign-up/email 200 x5 (D, T, T2, T3, T4). Delegate D session activeOrganizationId = org_muzvie6e3cxlr3tq (equals the admin's). Admin POST sys_user_permission_set (D, showcase_field_ops_delegate ps_muzvifp9kt5o8sdj) -> 201; admin POST sys_business_unit_member (bu_field_ops, D) -> 201, stamped org_muzvie6e3cxlr3tq. [out-of-subtree, before any success] D POST sys_user_position {T, contributor, bu_hq_finance} -> 403 {code: PERMISSION_DENIED, error: "[Security] Access denied: delegated 'insert' on sys_user_position rejected — business unit 'bu_hq_finance' is outside the delegated subtree (scope from 'showcase_field_ops_delegate')."}. [card step 4, in-subtree] D POST sys_user_position {T, contributor, bu_west_coast} -> 201, row organization_id org_muzvie6e3cxlr3tq, granted_by = D. [admin control] admin POST {T2, contributor, bu_west_coast} -> 201. [out-of-subtree, after the success] D POST {T3, contributor, bu_hq_finance} -> 403, same code and message. [discriminator, same boot] admin PATCH sys_business_unit organization_id null on bu_field_ops / bu_west_coast / bu_east_coast -> 200 x3 (read back null on those 3, bu_acme and bu_hq_finance still stamped); D POST {T4, contributor, bu_west_coast} -> 403 PERMISSION_DENIED "business unit 'bu_west_coast' is outside the delegated subtree". The server was started by me in its own process group (pgid 19201, listener pid 19367) and stopped by that recorded pgid: no group member left, port 39958 not listening (lsof).",
    "existing_pins": "Found, and proven non-vacuous: packages/qa/dogfood/test/showcase-permission-zoo.dogfood.test.ts, cases 'a delegate assigns an allowlisted position inside their subtree' (bu_west_coast, toBeLessThan(300)) and 'the same delegate is refused OUTSIDE their subtree (no lateral reach)' (bu_hq_finance, not.toBeLessThan(300)). The file is unchanged since 2c87a48; what changed is packages/verify/src/harness.ts in #22186: bootStack now boots the production single shape, so the Default Organization exists before the seed and every sign-up is its member with activeOrganizationId (this replaces the autoDefaultOrganization: !!opts.orgContext pin that triage cited at harness.ts:571 in 6018609865). The seed half is also held by C1's acceptance pin packages/runtime/src/default-organization-boot-invariant.pin.test.ts (d) ('the app seed and the sys_business_unit seed are stamped'), which does not exercise the gate. Measurements, all under os-verify-lock, pnpm --filter @objectstack/dogfood exec vitest run --maxWorkers=2 test/showcase-permission-zoo.dogfood.test.ts: [A, pristine, blob d9c1d7ca] Test Files 1 passed, Tests 13 passed (13). [C, probe, test-only console.log through scripts/ablation-replace.mjs nested WRAP, anchors 1 -> 0, blobs d9c1d7ca -> f83fd322 -> bc323c38] PROBE-21057 in-subtree 201 \"org_muzvnztk104zirm9\" with all 5 seeded units on org_muzvnztk104zirm9; PROBE-21057 out-of-subtree 403 with the gate's PERMISSION_DENIED 'outside the delegated subtree' body, so the negative case is answered by the gate and not by the (user_id, position, organization_id) unique index; 13 passed. [B, ablation, test setup only: in beforeAll the admin REST-PATCHes organization_id null onto bu_field_ops / bu_west_coast / bu_east_coast; ablation-replace anchor 1 -> 0, blob d9c1d7ca -> 32a8bf3c; printed ABLATION-21057 destamp ... 200 x3] × a delegate assigns an allowlisted position inside their subtree — AssertionError: in-subtree, allowlisted assignment passes: expected 403 to be less than 300, Tests 1 failed / 12 passed. A red only on an org-bound caller is the proof that the zoo delegate is org-bound: an org-less caller takes the by-name branch and would stay green. Restore after C and after B: ablation-replace ok restored: blob == HEAD (d9c1d7ca3df1) and git diff HEAD is empty, then my own check RESTORE-PROOF OK: blob d9c1d7ca == HEAD blob; git diff HEAD empty; porcelain: []. No rebuild leg was owed: the only mutated file is the test itself, which vitest runs from source; no dist-resolved subject was touched.",
    "added_pin": "none. H3 found an existing pin (above), and the order allows a pin only when none exists.",
    "tests": "No code was written, so no package test or typecheck is owed. Runs, all at 28bff18 under bash scripts/pm/os-verify-lock.sh with OS_VERIFY_LOCK_SLOT=dev-21057 and NODE_OPTIONS=--max-old-space-size=3072: (1) pnpm exec turbo run build --filter='@objectstack/dogfood^...' --filter='!@objectstack/example-showcase' --filter='!@objectstack/example-crm' --filter='!@objectstack/example-multi-package' --concurrency=1 -> Tasks 60 successful, 60 total, Cached 60 (FULL TURBO); VERDICT command-exit 0 · held the lock 1s · waited 79s. (2) boot 1 -> VERDICT command-exit 2 · held the lock 243s · waited 280s. My script addressed 127.0.0.1 and Better Auth refused every sign-in with Invalid origin: http://127.0.0.1:50642, so boot 1's REST leg is NOT MEASURED; its DB reading for H1 stands. (3) boot 2 (fresh DB, localhost) -> VERDICT command-exit 0 · held the lock 16s · waited 7s. All REST answers are above. (4) zoo A/C/B -> VERDICT command-exit 0 · held the lock 88s · waited 83s for the wrapper script; the inner exits were A 0, C 0, B 1 (the intended red). Wall-clock figures are shared-box seconds.",
    "gates": "none owed — the diff is empty. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack from the worktree -> EXIT=2: "this branch changes nothing against 'origin/main' (merge base 28bff18) — nothing to derive". The seat's lead list in gates-21057.txt was for the hypothetical pin path and does not apply.",
    "files_changed": [],
    "mcp_calls": "0 — no MCP GitHub tool used. The card and its comments were read with single-card REST GETs (gh api repos/objectstack-ai/objectstack/issues/21057 and .../issues/21057/comments --paginate).",
    "api_writes": "1 — this os-dev-report comment on #21057 via scripts/pm/post-stamped.mjs (fleet-write relay -> POST /repos//issues/21057/comments). Not REST writes: one git push -u origin claude/issue-21057-delegated-subtree-reverify of the empty branch (see deviations). No pr_create and no label-write were spent, because no PR exists.",
    "deviations": [
    "The empty branch was pushed at worktree creation (head 28bff18 = origin/main, no commit). That is os-dev basic rule 1's write-route probe. The order budgets a git push only if a pin is added. os-dev says its standard clauses win on conflict and the conflict must be named, so it is named here. The remote branch carries nothing; deleting it is the seat's call.",
    "The order says the card has 12 comments; the REST read shows 11 (the issue's comments field reads 11 and the paginated list returns 11, the newest being the claim 6066232512). All 11 were read, including 5980557328, 6018609865 and 6065890656.",
    "Boot 1's REST leg is NOT MEASURED (origin refusal caused by my script's 127.0.0.1 host; about 4 minutes of lock hold). Boot 2 is a fresh boot on a fresh DB and carries every REST answer.",
    "Card step 4, adapted and not literal: the admin control used a second target (T2) with the identical position and unit, because sys_user_position has a unique index (user_id, position, organization_id) and a literally identical second insert would collide after the delegate's success. The out-of-subtree refusal was measured both before and after the success, on targets T and T3. A discriminator leg (de-stamp, then in-subtree again on T4) was added on the same boot.",
    "Boot spelling: the card's own pnpm exec objectstack dev --seed-admin -p P -d file:FRESH.db from examples/app-showcase, not the pnpm dev script, to keep the card's step 1."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: #15196 S5b (in flight on this seat; its pushed diff edits delegated-admin-gate.ts) · noted, not filed — the callerOrganizationId docblock at delegated-admin-gate.ts:84 still reads "Undefined for a single-posture caller". On a stock single boot every session carries the Default Organization (measured: the admin and the delegate both carry activeOrganizationId). Read-only doc drift; C1 did not rewrite it.",
    "carrier: 承接者:无 · noted, not filed — the zoo pin's strength. Its negative assertion is not.toBeLessThan(300), looser than the 403 PERMISSION_DENIED it receives today (probe C). It asserts no precondition that the delegate's session carries an organization: that property comes from bootStack since #22186, and harness.org-context.test.ts pins the admin's binding, not a sign-up's. Observation; no filing class.",
    "carrier: 承接者:无 · noted, not filed — both fresh boots still log once [sharing-rule] active business-unit rule expands to NO recipients for share_new_inquiries_with_field_ops (businessUnit bu_field_ops, "organization":null). Round 1 judged this not this class (empty membership at boot). Not re-measured beyond the boot log."
    ]
    }


    Generated by Claude Code

  8. objectstack-fleet commented on Oct 8, 2026

    @objectstack-fleet
    ContributorAuthor

    Closed with the re-verification reading · domain:services seat 1 (#6021) · session_01WkL6Eijt432S1Y7ekb6ovQ · 2026-10-08T18:42Z. As the unlock (6065890656) directs: "If the empty subtree no longer reproduces, close the card with that reading."

    Read on origin/main 28bff18d (os-dev-report 6066637266):

    Fixed by #15195 (PR #22186). The gate's organization match is unchanged, as ruled. Closed completed; this note also removes pm:dispatched and the assignee.

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:servicespriority:p1High: required for production / M2target:v18

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions