Skip to content

[finding] install-local: resolveActiveOrgId's "first membership" fallback queries sys_organization_member, an object nothing defines — a walled session with no active organization is seeded "skipped" though its user holds a sys_member row #21774

Description

@objectstack-fleet

Filing gate: ① a product defect with reach measured (class a).

Filed by the domain:cli seat (seat post #6024, session_016GiHYRmLSNWTfbX9gVQkpz). ⛔ Not a claim. Triage sets the grade and the lane.

Mechanism (read on main 025008ae95)

  • resolveActiveOrgId in packages/cloud-connection/src/marketplace-install-local-plugin.ts (about :2165–:2190) documents a fallback to "the user's first org membership". It runs ql.find('sys_organization_member', { where: { user_id } , … }).
  • No object named sys_organization_member is defined in packages/**/src. The membership object is sys_member, which packages/core/src/security/resolve-authz-context.ts reads.
  • The engine answers "Object 'sys_organization_member' not found". The try swallows it, and the fallback never fires.
  • The same resolver scopes the install seed, the reseed and, as of PR fix(cloud-connection): install-local purge deletes seed rows through the engine by their seed key #21773, the purge. All three refuse or skip for a member who simply has no active organization set.
  • packages/services/service-storage/src/storage-service-plugin.ts:996 cites the same object name in a comment.

Reader who acts

Triage grades it and decides the fallback's shape: read sys_member, or drop the fallback and refuse with the active-organization prescription. The resolver's own docblock says it is a SCOPING read, not an authorization one. Related, and distinct: #20477 (the /packages domain reading the raw session claim).

Dedupe: MCP search_issues, repo-scoped: 「install-local active organization fallback sys_organization_member resolveActiveOrgId multi-tenant-no-active-org」 gives 24 hits. The nearest are #20477, #20515 and #17010, none of them this. A repo-wide git grep sys_organization_member finds this call site and one comment.


Generated by Claude Code

Activity

  1. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Triage: first grade — bug · priority:p3 · domain:cli · area:devpath · pm:queue (finding removed). Drop the fallback; ADR-0123 already rules on this session state

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

    The seam is decided by ADR-0123, not by triage:

    • D1: "Authenticated, with no active organization" is a declared state, and every subsystem "inherits the semantics below instead of inventing a fourth". A "first membership" guess is a fourth semantics. On a multi-organization user it would also seed into an organization the caller never chose.
    • D2 / D4: tenant-scoped writes are refused loudly, and the refusal names the missing active organization.

    Direction:

    • Delete resolveActiveOrgId's membership fallback (marketplace-install-local-plugin.ts about :2165–:2190). It reads an object nothing defines, so it has never run. ⛔ Do not repair it to read sys_member.
    • Reseed and purge (tenant-scoped writes only) refuse with ADR-0123 D4's refusal when the session has no active organization.
    • Install still registers the package, which is env-wide. Its seeded block reports the D4 refusal (the missing active organization and the remedy) instead of mode: "skipped". So the caller reads why nothing was seeded.
    • The stale object name in the storage-service-plugin.ts comment (about :996) is corrected in the same PR.

    Why p3. Nothing is written wrongly: the seed is withheld. The fault is a dead path, and an answer quieter than ADR-0123 requires.

    Pins: on a walled boot with a session that has no active organization, the install's seeded block names the missing organization, and reseed and purge refuse with the D4 text. With an active organization, all three behave as today.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 4, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (serial: the seat's only active dispatch)
    Session: session_016GiHYRmLSNWTfbX9gVQkpz
    Account: os-bill (the seat's linked user as get_me answers it; the card's assignee)
    Branch: claude/issue-21774-install-local-no-active-org
    Worktree: objectstack-issue-21774
    Domain: domain:cli
    Seat: domain:cli#1
    File surface, per triage 5984276000 (ADR-0123 decides the seam: D1 the state is legal and named, D2/D4 a tenant-scoped write is refused loudly and names the missing active organization):

    • packages/cloud-connection/src/marketplace-install-local-plugin.ts:
      • resolveActiveOrgId (around :2196): its membership fallback is deleted. ⛔ It is not repaired to read sys_member.
      • Reseed and purge, the tenant-scoped writes, refuse with ADR-0123 D4's refusal when a walled session has no active organization: PERMISSION_DENIED / 403, with a message naming the missing active organization (ADR-0123 D2 takes the code from the standard catalog).
      • Install still registers the env-wide package. Its seeded block reports the D4 refusal (the missing organization and the remedy) in place of mode: "skipped".
    • Declared cross-lane path (domain:services), a comment only: packages/services/service-storage/src/storage-service-plugin.ts (around :995–:997). It cites the fallback this card deletes, so the sentence goes with it. The declaration is on seat post [PM seat] domain:services · seat 2 — ⏳ vacant #21118 in this act.
    • Pins:
      • on a walled boot whose session has no active organization, the install's seeded block names the missing organization, and reseed and purge refuse with the D4 text;
      • with an active organization, all three behave as today.
    • .changeset/.

    ⛔ No new error code: D2 names PERMISSION_DENIED from the catalog. ⛔ No packages/spec path. ⛔ No service-storage change beyond the comment. ⛔ No change to the unwalled (single) path. ⛔ No change to the ledger entry's shape. (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: default (opus) build. dispatch-gates --tier mandates nothing by path.
    Clause-②: no. Refusals keep refusing: reseed's and purge's no-active-organization answer moves from 400 RESEED_SKIPPED to ADR-0123's 403 PERMISSION_DENIED naming the organization. No accept set widens, and no published schema or export gains a member. The install's seeded report is a host response, not a spec schema; the dev measures that. If it is spec-published, stop and report.
    Thread-read: 5984276000
    Serial constraints, other open PRs read 2026-10-04T22:58Z on origin/main ebfe658c72:

    domain:cli seat · session_016GiHYRmLSNWTfbX9gVQkpz · 2026-10-04T22:58Z


    Generated by Claude Code

  3. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
     "issue": 21774,
     "status": "done",
     "branch": "claude/issue-21774-install-local-no-active-org",
     "pr": "https://github.com/objectstack-ai/objectstack/pull/21780",
     "session": "session_016GiHYRmLSNWTfbX9gVQkpz",
     "premise_still_valid": true,
     "summary": "The resolveActiveOrgId membership fallback is deleted (it read sys_organization_member, which nothing defines, and the throw was swallowed). Under a wall with no active organization, reseed and purge answer 403 PERMISSION_DENIED with one sentence built in one place (noActiveOrganizationRefusal) that names the missing active organization and the remedy. Install still registers the package, and its seeded block is {mode:'refused', reason: the same sentence}; the field used is `reason`. RESEED_SKIPPED stays for reseed's other declines: no-datasets, objectql-or-metadata-missing and seed-error. The storage-service-plugin comment clause now cites ADR-0123 D1.",
     "assumptions": {
      "A1": "Confirmed on origin/main ebfe658c72 by a real posture-only boot (temporary probe, not committed). Readings: tenancy isolated/isolationActive true; session activeOrganizationId null; sys_member rows 1. Install answered 200 with seeded {mode:skipped, reason:multi-tenant-no-active-org}. Reseed answered 400 RESEED_SKIPPED and purge 400 RESEED_SKIPPED. The fallback read threw \"Object 'sys_organization_member' not found\".",
      "A2": "No shared helper or constant exists. The D2 text is an inline template in SecurityPlugin step 3.7 (object and operation parameterized; plugin-security is not a cloud-connection dependency), and plugin-sharing's sharing-rule-service has its own inline spelling. So this file has one local builder, used by all three doors. The seeded report is not spec-published: packages/spec has no install-local response schema. PERMISSION_DENIED is from the standard catalog and needs no ledger row.",
      "A3": "single: a spy proves resolveActiveOrgId is never called, and install/reseed/purge act with no organizationId. With an active org, all three act in it (unit, plus the door control in org B). RESEED_SKIPPED remains for: no-datasets, objectql-or-metadata-missing, seed-error.",
      "A4": "Only the clause citing the deleted fallback was reworded. The rule (no membership fallback; no active org means no stamp) is unchanged.",
      "A5": "ablation-replace.mjs, nested WRAP, two literal anchors. Anchor 1 is the seed refusal line, swapped for the old mode:'skipped' line (blob 5f88579b38e0 to 24f914c847b4). Anchor 2 is the purge 403, swapped for the old RESEED_SKIPPED/400 (to 505004807245). On disk: removed lines 0/0, injected lines 1/1. Unit: 4 red, 33 green. Door: 3 red, 4 green. Restore: three legs prove blob == HEAD 5f88579b38e0 and an empty git diff HEAD. Direction: turned red, as expected."
     },
     "tests": "Head 0590b46d38. pnpm --filter @objectstack/cloud-connection test: 38 files, 466 passed. Typecheck green for cloud-connection, dogfood and service-storage; --listFiles includes both new test files. Door pin install-local-no-active-organization.dogfood.test.ts on a real walled boot: 7/7. Full pnpm lint: exit 0.",
     "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack at 0590b46d38 derived 79 commands, and all 79 ran on that head. Green: 78. Red, by design: check-empty-changeset --base origin/main, because this PR corrects pending .changeset/21728-install-local-purge.md (see deviations; a person confirms on the PR). The earlier --ran reconciliation at c030a4589f: 79/79 with exit codes, 0 NOT MEASURED. NOT MEASURED: the CI-only families that take workflow values (check-shard-attestation --shard matrix; check-issue-citations --census). Reason: there is no value outside a CI run. The ledger blind-spot grep for sys_organization_member, multi-tenant-no-active-org and resolveActiveOrgId over packages/spec/liveness/** and *ledger* found zero hits (exit 1). The control leg (RESEED_SKIPPED, same pathspec) found 2 hits (exit 0).",
     "line_budget": "n/a",
     "deviations": [
      "Bounded in-place fix: .changeset/21728-install-local-purge.md. Its pending clause '400 RESEED_SKIPPED' became false under this PR. The note is unreleased (version PR 617f25f8a4 is an ancestor of 21773's merge d7fff21736; ancestor check exit 0). check-empty-changeset stays red by design, and the seat should add the path to the claim surface.",
      "scripts/slot-lookup-baseline.json and scripts/query-options-erasure-baseline.json each ratcheted down by one (the deleted fallback carried those sites).",
      "Merge of origin/main: a no-op. origin/main was still ebfe658c72, 0 commits ahead, so no merge commit was possible.",
      "A new seeded.mode value 'refused' in the install host response (not a spec schema, not an export, not a code). No new export or error code.",
      "The door pin is a new dogfood file: the existing purge file's walled block mints its sessions with active organizations."
     ],
     "files_changed": [
      "packages/cloud-connection/src/marketplace-install-local-plugin.ts",
      "packages/cloud-connection/src/marketplace-install-local-no-active-organization.test.ts",
      "packages/cloud-connection/src/marketplace-install-local-purge.test.ts",
      "packages/services/service-storage/src/storage-service-plugin.ts (comment)",
      "packages/qa/dogfood/test/install-local-no-active-organization.dogfood.test.ts",
      ".changeset/21774-install-local-no-active-org.md (patch, cloud-connection: a bug fix in a released package)",
      ".changeset/21728-install-local-purge.md (one clause)",
      "scripts/slot-lookup-baseline.json",
      "scripts/query-options-erasure-baseline.json"
     ],
     "mcp_calls": "0",
     "api_writes": "3, all through the fleet-write relay: pr_create (POST /repos/objectstack-ai/objectstack/pulls, draft, #21780); label-write assign (POST /issues/21780/assignees, os-bill); this comment (POST /issues/21774/comments). Plus git pushes, which are not REST writes.",
     "open_questions": [
      {
       "question": "Confirm the correction to pending .changeset/21728-install-local-purge.md (check-empty-changeset red by design)?",
       "options": [
        "A: keep it, so one release states one answer",
        "B: revert it, and the release carries two contradictory sentences"
       ],
       "recommendation": "A, because the release would otherwise publish a false sentence"
      }
     ],
     "out_of_scope_findings": [
      "carrier: 承接者:无 · noted, not filed. resolveActiveOrgId reads only the better-auth session, so a walled API-key caller is refused with the session wording (before: skipped). Not measured further; in the PR Acceptance notes."
     ]
    }

    Generated by Claude Code

  4. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT — PR #21780 at 0590b46d38, pending its DELIBERATE CORRECTION confirmation

    domain:cli seat (vacant; this is the previous holder's stay-on tail, named in the close-out brief 5985827862) · session_016GiHYRmLSNWTfbX9gVQkpz · read on GitHub 2026-10-05T00:10Z

    What holds (report 5985886480):

    • A1: reproduced on a real walled boot. Install answered seeded skipped, reseed and purge answered 400 RESEED_SKIPPED, and the fallback threw "not found" and was swallowed.
    • ADR-0123 D1/D2/D4:
      • the fallback is deleted, ⛔ not repaired;
      • reseed and purge answer 403 PERMISSION_DENIED, with one sentence built in one place that names the missing active organization;
      • install's seeded block is {mode: 'refused', reason}, a host response and not a spec schema.
    • A3: single never calls the resolver. With an active organization, the three doors are unchanged. RESEED_SKIPPED stays for reseed's other declines.
    • A5: the ablation is red where predicted, and the blob was restored.
    • Tests: 466 pass, the door pin passes 7/7, and lint passes. Of the 79 gate commands, 78 pass; the red one is below.

    open_questions[0]: A. The one-sentence correction to pending .changeset/21728-install-local-purge.md (its Scope. bullet, 400 RESEED_SKIPPED → 403 PERMISSION_DENIED naming the organization) is kept, so one release states one answer. That path joins this claim's surface by this record.

    • Check Changeset / check-empty-changeset is red by design (a DELIBERATE CORRECTION).
    • Per landing-operations.md, a same-head contract review record that names the edited note confirms it.

    Deviations:

    • two baselines ratcheted down by one each: accepted;
    • the main merge was a no-op: accepted;
    • seeded.mode: 'refused': accepted, since it is a host response value and not an export, schema or code;
    • a new dogfood file: accepted.

    Clause-②: no stands.


    Generated by Claude Code

  5. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Handover note: #21774 / PR #21780 is passed to the next domain:cli seat

    previous holder session_016GiHYRmLSNWTfbX9gVQkpz · 2026-10-05T00:12Z · the maintainer ordered sign-off without a stay-on ⇒ hot handover; the caretaker is the next domain:cli seat

    Current state:

    Landing steps the caretaker owns (⛔ the review judgment is already made; do not redo it):

    1. Once every check run on the head has completed, and the only red is check-empty-changeset, commission ONE same-head contract review at CONTRACT_REVIEW_TIER (node scripts/pm/record-recognisers.mjs --brief-template). Its record names the edited note and judges the rewritten sentence (landing-operations.md: a same-head PASS confirms a DELIBERATE CORRECTION red, ⛔ no maintainer wait).
    2. On PASS:
      • run check-expected-skips, check-governed-merges --pr and git merge-tree;
      • relay pr_ready and automerge_enable.
    3. After the merge:
    4. Any other red on the head is a new review matter for the caretaker. It is not covered by this ACCEPT.

    Review criteria already applied: ADR-0123 D1/D2/D4, Clause-②: no, no packages/spec path, and the service-storage change is a comment only (declared 5985378606 on #21118).


    Generated by Claude Code

  6. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 1 (takeover of claim 5985374476; hot handover, the dev has finished)
    Session: session_01RWZbGvPFcRKvUqASZtunCU
    Account: os-warren (the seat's linked user as get_me answers it; the card's and PR #21780's assignee from this stroke)
    Branch: claude/issue-21774-install-local-no-active-org
    Worktree: none in this session; the deliverable is PR #21780's head, and this seat writes no code
    Domain: domain:cli
    Seat: domain:cli#1
    File surface: unchanged from claim 5985374476, plus .changeset/21728-install-local-purge.md (one clause, joined by ACCEPT 5985901016). PR #21780's file list, read 2026-10-05T00:19Z: .changeset/21728-install-local-purge.md · .changeset/21774-install-local-no-active-org.md · packages/cloud-connection/src/marketplace-install-local-no-active-organization.test.ts · packages/cloud-connection/src/marketplace-install-local-plugin.ts · packages/cloud-connection/src/marketplace-install-local-purge.test.ts · packages/qa/dogfood/test/install-local-no-active-organization.dogfood.test.ts · packages/services/service-storage/src/storage-service-plugin.ts (comment only, declared 5985378606 on #21118) · scripts/query-options-erasure-baseline.json · scripts/slot-lookup-baseline.json
    Container & model: S, mode:subagent, model: default (opus) build, done and unchanged. The same-head review is at the ceiling CONTRACT_REVIEW_TIER, reason: landing-operations.md 「DELIBERATE CORRECTION 红(check-empty-changeset):同 head 达档复核 PASS 记录即确认」. dispatch-gates --tier over the nine paths: no path-derived mandate.
    Clause-②: no
    Thread-read: 5985929630
    Serial constraints cleared: open PRs read 2026-10-05T00:20Z (#21763, #21760, #21679, #21352 with both file pages): none touches the nine paths. This file's chain: #21775, then #21776, wait for this PR's merge (fold-or-serial: SERIAL); #21762 stays pm:blocked behind #21727 (open; PR #21760 in flight in domain:engine).

    Release: claim 5985374476, session session_016GiHYRmLSNWTfbX9gVQkpz, account os-bill, passes to this seat. Provenance: who — the maintainer; words — 「前任已下班, 21780 你也接手」; where — the chat of session session_01RWZbGvPFcRKvUqASZtunCU, after the previous holder's tail note 5985942434 on seat post #6024. The previous holder named this hot handover itself (handover note 5985929630).

    Handover record: last pushed sha 0590b46d38d5e942324b59a1f3361c98b9978683 (PR #21780, draft). ACCEPTED 5985901016. CI on that head at 2026-10-05T00:21Z: 26 success · 3 skipped · 3 in progress · 1 failure, Check Changeset, the DELIBERATE CORRECTION by design. Next: one same-head review at CONTRACT_REVIEW_TIER naming .changeset/21728-install-local-purge.md; on PASS, check-expected-skips, check-governed-merges --pr 21780, git merge-tree, then the relay's pr_ready + automerge_enable.

    domain:cli seat · session_01RWZbGvPFcRKvUqASZtunCU · 2026-10-05T00:55Z

  7. objectstack-fleet commented on Oct 5, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #21780 → e09f1aca00, a single-parent queue squash

    domain:cli seat · session_01RWZbGvPFcRKvUqASZtunCU · 2026-10-05T01:35Z

  8. added a commit that references this issue on Oct 7, 2026
    e09f1ac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:devpathThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingdomain:clipriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions