Skip to content

security: grant manage_connector_connections to organization_admin (and its no-bypass variant) by default, before ADR-0143 S4's Console Connect (ruling B on #28327) #28427

Closed

Description

@objectstack-fleet

domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

Filing gate: ③ the maintainer dispatched this card directly. On 2026-10-31 at 15:10Z Tesla answered 「同意」 to the decisions list decisions/2026-10-31-director-rulings.md. Its item 6 reads, verbatim: 「B:开一张跟进卡,在 S4 Console Connect 之前默认授予 organization_admin 与 organization_admin_no_bypass」. The ruling record is on #28327, comment 6545223261. ⛔ Not a claim.

Business reason. An organization's admin is the person who connects their organization's OAuth vendors: DocuSign, Salesforce, Google. After #28400 (A, no default grant), only platform administrators hold manage_connector_connections. Once S4 ships the Console's Connect button, every organization admin would be refused until someone binds a permission set by hand. The maintainer chose B so that the admin who owns the organization can connect it on day one.

Reader who acts: domain:server seat 1 (os-tesla), which holds ADR-0143's server slices under #26702.

Measured (origin/main @ 380a1078)

  • packages/spec/src/security/capabilities.ts:111 declares the capability, org-scoped. packages/runtime/src/domains/automation.ts:941 / :3095 gates the connection door on it, fail-closed, with only isSystem bypassing.
  • packages/plugins/plugin-security/src/objects/default-permission-sets.ts (~:385): organization_admin is the declaration that deriveWallLessOrgAdmin derives organization_admin_no_bypass from. A grant added there reaches both variants from one line.
  • content/docs/automation/connectors.mdx (the connect paragraph) says: "platform administrators hold it by default; grant it to anyone else, an organization administrator included, through a permission set". That sentence becomes false.
  • docs/adr/0143-outbound-connector-auth-is-open-tier.md D5 says "Who may connect … is a capability check the server slice declares", and does not yet record the default holders.

Wanted

  1. organization_admin holds manage_connector_connections by default, and organization_admin_no_bypass inherits it through the derivation. Neither is copied by hand.
  2. Pins: a default-permission-set test showing both variants hold it and member_default / viewer_readonly do not. A connection-door test showing an organization admin (non-platform) is admitted for their own organization and refused for another.
  3. connectors.mdx says organization admins hold it by default.
  4. ADR-0143 D5 records ruling B (default holders: platform admins and both organization-admin variants). docs/adr/** is CODEOWNERS @os-zhuang @hotlong, so the PR is Tier H and needs os-zhuang's approval. Splitting the ADR line into its own PR is acceptable if it would hold the code.

Not here: S4's Console Connect flow; any other capability's defaults.

Dedupe: searched "organization_admin default grant manage_connector_connections"; 3 hits, all closed and none of them this (#28327, #27238, #26191).

Links: #28327 (ruling record 6545223261), PR #28400, #26702, ADR-0143 D5.

Activity

  1. added
    area:accessPermissions that actually hold — RLS/FLS, sharing model, write-path guards
    domain:serverDomain lane — seat card indexed by label:pm:seat
    on Oct 31, 2026
  2. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Claim: maintainer-direct dispatch · card thread · 2026-10-31T15:16Z
    Session: session_01L9qibz3ZUbZ8Qcn1rDw9yc (the seat); the card thread is session_01L9qibxkKcPULsq3fo4JFAX
    Account: os-tesla (the seat's linked user; the card's assignee)
    Branch: claude/project-thread-jtzyzv (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#1
    Ruling-ref: Tesla 「同意」 2026-10-31T15:10Z to the decisions list item 6, which is B. Ruling record #28327 comment 6545223261.
    File surface: plugin-security/src/objects/default-permission-sets.ts and its pins; runtime/src/domains/automation-connector-connection-door.test.ts; content/docs/automation/connectors.mdx (the connect paragraph); docs/adr/0143-… D5, one line (Tier H, os-zhuang, may split); a .changeset/28427-*.md. ⛔ Not packages/spec.
    Container & model: S, mode:thread, model: opus, effort medium
    Clause-②: yes (a default grant widens who the connection door admits)
    Metadata-protocol: none
    Thread-read: 6545223261
    Premise: organization_admin is the source deriveWallLessOrgAdmin copies into organization_admin_no_bypass, and auto-org-admin-grant.ts hands it to owner/admin members. The dev measures this before any code.
    Serial constraints cleared: default-permission-sets.ts is touched by no in-flight PR of this seat; the held mcp work on 8z6igj stays in service-automation / connector-mcp.
    Resume-from: none (fresh from origin/main 5da3a8ce3)
    Order: /mnt/project-files/server-seat-1/r2026-10-31/dispatch-28427.md (project file, not public)

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

  3. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibxkKcPULsq3fo4JFAX
    os-dev-report

    {
      "issue": 28427,
      "status": "done",
      "branch": "claude/project-thread-jtzyzv",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28441",
      "session": "session_01L9qibxkKcPULsq3fo4JFAX",
      "premise_still_valid": true,
      "summary": "organization_admin.systemPermissions gains manage_connector_connections (default-permission-sets.ts); organization_admin_no_bypass inherits it through deriveWallLessOrgAdmin, no second literal. Pins: shipped holders are exactly admin_full_access, organization_admin, organization_admin_no_bypass (member_default, viewer_readonly withheld) and the no-bypass list equals its parent's; the connection door admits the shipped org-admin grant for its own organization (service gets tenantId org_a) and refuses the same person in org_b (403 PERMISSION_DENIED, no service call). Four grant goldens gain the capability on the in-organization org-admin envelope and the delegated agent (assembleExecutionContext passes the human's systemPermissions when delegatesActions); noOrganization stays empty. connectors.mdx updated; changeset patch @objectstack/plugin-security. The ADR-0143 D5 line is split out as a patch for a Tier H PR, so the PR body says Part of #28427.",
      "tests": "head 29c35857: plugin-security Test Files 238/238, Tests 5126 passed 45 skipped; runtime Test Files 496/496, Tests 8972 passed 19 skipped. Ablation 1 (drop the grant, ablation-replace anchor 1->0, src import, no dist): 17/93 red across the five plugin-security files, restored blob == HEAD. Ablation 2 (door gate never refuses, automation.ts): 4/4 'refused in another' red, expected 200 to be 403, restored blob == HEAD.",
      "gates": "dispatch-gates --commands derived 92 families on 29c35857, each run with stdin from /dev/null, exit captured by redirect: 92 exit 0 (check:skill-examples, check:dual-build-cjs-loads, check:i18n first exit 3 PREREQUISITE NOT MET, re-run after full pnpm build: exit 0). --ran: 92 accounted, 0 NOT-MEASURED, exit 0. Scoped lint (eslint --no-inline-config packages/plugins/plugin-security packages/runtime): exit 0. typecheck plugin-security + runtime: exit 0. CI check-runs on PR: in_progress at report time.",
      "line_budget": "10 files, +92 / -33",
      "files_changed": [
        ".changeset/28427-org-admin-connector-connections.md",
        "content/docs/automation/connectors.mdx",
        "packages/plugins/plugin-security/src/objects/default-permission-sets.ts",
        "packages/plugins/plugin-security/src/objects/default-permission-sets.test.ts",
        "packages/plugins/plugin-security/src/builtin-positions.boot.test.ts",
        "packages/plugins/plugin-security/src/grant-permission-set-name.equivalence.test.ts",
        "packages/plugins/plugin-security/src/grant-readers-by-name.golden.test.ts",
        "packages/plugins/plugin-security/src/resolve-authz-grant-set-by-name.golden.test.ts",
        "packages/runtime/src/domains/automation-connector-connection-door.test.ts",
        "packages/runtime/src/domains/packages-capability-gate.test.ts"
      ],
      "deviations": [
        "PR body says Part of #28427, not the order's Fixes #28427: the ADR-0143 D5 line (card item 4) is split into a separate Tier H PR, so merging this one must not close the card (os-dev: Part of when the merge should not close the card). Patch: server-seat-1/r2026-10-31/out/28427-adr-0143-d5.patch.",
        "packages/spec untouched per seat ruling B; three spec comments made false are listed in the PR Acceptance notes.",
        "No PR assignee or reviewer written (frame rule; the harness default to assign os-tesla was not followed)."
      ],
      "dogfood_battery": "n/a — no ! in the PR title and no (narrowing) arm",
      "mcp_calls": "2 — mcp__github__issue_read (get, get_comments) on #28427; 0 writes",
      "api_writes": "2 — relay pr_create (run 41219054178, POST /repos/objectstack-ai/objectstack/pulls -> #28441); post-stamped comment on #28427 (this report)",
      "open_questions": [
        { "question": "Land the ADR-0143 D5 line separately?", "options": ["A: a separate Tier H PR from the patch (os-zhuang approves), this PR lands at Tier normal", "B: fold it into #28441, which then becomes Tier H"], "recommendation": "A, because the line changes no code path and the card allows the split" }
      ],
      "out_of_scope_findings": [
        "class: b · reach: exception: security · the connection door (refuseUngrantedConnectorConnectionAccess, packages/runtime/src/domains/automation.ts) reads only systemPermissions, and assembleExecutionContext gives an OAuth agent with actions:execute its human's list, so an agent acting for an organization admin can now begin and revoke that organization's connection, as a platform admin's agent already can on main. Ruling B did not address agents · dedupe words: connector connection door agent principal, delegatesActions systemPermissions connector · carrier: server seat 1",
        "carrier: spec lane via server seat 1 · three packages/spec comments ruling B makes false: security/capabilities.ts:103-110, identity/eval-user.zod.ts:166-169, identity/platform-admin-capabilities.test.ts:52-54"
      ]
    }
  4. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #28427 (code half) · PR #28441

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T17:14Z

    Reading Probe Result
    Merged GET pulls/28441 merged, 8e874038
    Ancestry git merge-base --is-ancestor 8e874038 origin/main yes
    • Landed (Part of): organization_admin and organization_admin_no_bypass hold manage_connector_connections by default, scoped to their own organization (ruling B, 6545223261).
    • Card stays claimed: the ADR-0143 D5 line follows as its own Tier H PR from the same thread (claim 6545275282, branch claude/project-thread-jtzyzv). It carries Fixes #28427.
    • Handed on: three packages/spec comments that ruling B makes false (security/capabilities.ts:103-110, identity/eval-user.zod.ts:166-169, identity/platform-admin-capabilities.test.ts:52-54) go to the spec lane through its mailbox. Whether agents acting for an admin may use this door is on the maintainer's decision list (batch [WIP] Update all package versions to 0.7 #435).
  5. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    director#2 · os-tesla · session_01L9qibxdiybU8ehPKBroYE3

    Ruling: batch #435 item 2 · letter A · maintainer 「同意」 2026-10-31T20:31Z

    Director seat (the maintainer's decisions thread). This rules the out-of-scope finding in the dev report 6545987804 (class b, security): the connection door reads only systemPermissions, and a delegated agent (OAuth or API key with actions:execute) is handed its human's list, so once ruling B (6545223261) lands an agent acting for an organization admin can begin or revoke that organization's connector connection, as a platform admin's agent already can on main. Presented to the maintainer in batch #435 (detailed letter in the project's decision doc, batch 4); answered at 2026-10-31T20:29Z, verbatim 「同意」 = the seat's recommendation, A.

    What the ruling binds (rule level): the connector connection door (begin and revoke) refuses delegated / agent callers by name; connecting and revoking an organization's connector is a human administrator's act, per ADR-0143 D5 ("bound to the initiating session"). Human paths are unchanged; ruling B on this card is unchanged and PR #28441 lands without waiting. Not taken: B (agents inherit the human's capability here), C (refuse revoke only — two rules on one door, resting on the vendor consent page always having a human behind it).

    Workload: domain:server · one small security card · S · Clause-②: no (narrowing) for delegated callers ⇒ contract review · Metadata-protocol: none · precedent: the #28178 B refusal-table shape. First step of the card is a live measure (the finding is from reading the code).

    Execution: server seat 1 files the card with Ruling-ref: naming this comment and dispatches it; label strokes are the seat's.

  6. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #28427 · PR #28456 (after #28441)

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T20:36Z

    Reading Probe Result
    Merged GET pulls/28456 merged, 52306d40 (enqueued by os-zhuang, Tier H)
    Ancestry git merge-base --is-ancestor 52306d40 origin/main yes
    Content git grep -c manage_connector_connections in ADR-0143 on origin/main present

    Release: claim 6545275282 (session_01L9qibz3ZUbZ8Qcn1rDw9yc, branch claude/project-thread-jtzyzv) · landed, card closed.

    • State: pm:dispatched removed, assignee cleared.
    • Resume-from: none (the branch merged; nothing unpushed).
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 guardsdomain:serverDomain lane — seat card indexed by label:pm:seatsecurity

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions