Skip to content

security: the connector connection door refuses a delegated / agent caller by name; connecting and revoking is a human administrator's act (ruling A on #28427) #28468

Closed

Description

@objectstack-fleet

domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

Filing gate: ③ the maintainer dispatched this card directly. At 2026-10-31T20:29Z Tesla answered 「同意」 to batch #435, which takes the seat's recommendation, letter A. The ruling record is on #28427, comment 6548764795. ⛔ Not a claim.

Ruling-ref: 6548764795

Business reason. Connecting an organization's OAuth vendor, or revoking that connection, decides whose grant every later run in that organization uses. ADR-0143 D5 binds a connection to the session that began it. The maintainer ruled that only a human administrator takes that step. An agent acting for that administrator does not.

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

The rule (ruling A)

  • The connector connection door's begin leg (connect and reconnect) and its revoke leg refuse a delegated or agent caller by name. That covers an OAuth client acting for a user and an API key's agent principal. The refusal answers with a stable code and a message that names the rule. It is never a silent 403 under another name.
  • Human administrators keep exactly the reach they have today: platform administrators, the organization-administrator sets (ruling B, feat(plugin-security): organization administrators hold manage_connector_connections by default (ADR-0143 D5, ruling B) #28441), and anyone granted manage_connector_connections.
  • isSystem keeps its bypass.

Wanted

  1. First, a live measure. The finding was read from code (dev report 6545987804, out-of-scope item). On a booted stack, show today's answer on the begin and revoke legs for a delegated caller acting for a capability holder. If the door already refuses, stop and report back to the seat with the evidence.
  2. The door refuses as ruled. Follow the precedent of the runtime(mcp): an OAuth-token agent's api action forward carries a bearer the target door does not accept (acceptOAuthAccessToken matches /mcp paths only), so the target likely resolves the caller as anonymous #28178 B refusal table: refuse by caller kind, and name the kind in the message.
  3. Pins:
    • A delegated caller acting for a holder is refused on begin and on revoke.
    • The same human, calling directly, is admitted.
    • A system call is admitted.
    • An ablation shows each pin goes red without the refusal.
  4. One line in content/docs/automation/connectors.mdx: connecting and revoking is a human administrator's act, and an agent cannot do it.

Clause-②: no (narrowing) for delegated callers, so a contract review is owed. Metadata-protocol: none. Size S.

Not here:

  • The door's read leg (connection status).
  • The callback leg. The browser landing there carries the session that began the connect.
  • Any other door's agent posture.
  • An ADR edit. D5 already says "bound to the initiating session". If the dev finds the ADR needs a line, that is a separate Tier H PR.

Dedupe: I searched "connector connection agent delegated refuse" and found nothing open that covers this (#28427, #28327, #26702 are related, not this).

Links: #28427 (ruling record 6548764795), #28441, #26702, ADR-0143 D5, #28178.

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 card (filing gate ③) · card thread · 2026-10-31T20:33Z
    Session: session_01L9qibz3ZUbZ8Qcn1rDw9yc (the seat); the card thread's session is named in the thread's first report
    Account: os-tesla (the seat's linked user; the card's assignee)
    Branch: the card thread's harness-pinned claude/project-thread-* branch, named in the dev report
    Worktree: the card thread's own container checkout
    Domain: domain:server
    Seat: domain:server#1
    Ruling-ref: 6548764795 (letter A, Tesla 「同意」 2026-10-31T20:29Z, batch #435)
    File surface: the connector connection door's gate in packages/runtime/src/domains/automation.ts, its tests, one line in content/docs/automation/connectors.mdx, and a .changeset/28468-*.md. ⛔ No packages/spec, no metadata-protocol/src/protocol.ts, no docs/adr/**.
    Container & model: S, mode:thread, model: opus, effort high; contract-review tier before the queue
    Clause-②: no (narrowing)
    Metadata-protocol: none
    Thread-read: 6548764795
    Premise: a live measure on origin/main comes first. Public text stays at rule level.
    Serial constraints cleared: no in-flight PR of this seat touches automation.ts. #28441 merged.
    Resume-from: none (fresh from origin/main)
    Order: /mnt/project-files/server-seat-1/r2026-10-31/dispatch-28468.md (project file, not public)

    State: pm:queue → 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_01L9qibz3ZUbZ8Qcn1rDw9yc

    Claim amendment to 6548795089 · 2026-10-31T20:39Z · branch named

    Branch: claude/project-thread-0wkobq (the card thread's harness-pinned branch)
    Session: the card thread is session_01L9qibvkQWJban49F52ZjBc
    Everything else stands as claimed.

  4. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

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

    {
      "issue": 28468,
      "status": "done",
      "branch": "claude/project-thread-0wkobq",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28474",
      "session": "session_01L9qibvkQWJban49F52ZjBc",
      "premise_still_valid": true,
      "summary": "Live measure on origin/main 52306d40 (booted stack): the connection door did not refuse a delegated caller by name on begin or revoke; readings are in the seat's private out/28468-mechanism.md, not here. Fix: refuseUngrantedConnectorConnectionAccess (packages/runtime/src/domains/automation.ts) now refuses, on POST and DELETE only, after the isSystem bypass and before the capability read, a caller named by connectorConnectionDelegatedCaller (agent envelope: principalKind agent or onBehalfOf; oauth or api_key credential via apiForwardCredentialKind), 403 PERMISSION_DENIED with connectorConnectionDelegatedCallerRefusal(kind) naming the kind and the rule. Read leg, callback, capability holders and isSystem unchanged. connectors.mdx one sentence; changeset patch @objectstack/runtime, BREAKING, adr-0087 not-required marker.",
      "tests": "head 1788eefb: door file Tests 31/31 (9 new: fixtures, 3 kinds x begin+revoke refused, signed-in holder admitted, system admitted, 3 kinds x read+callback 200; envelopes from the real core assembleExecutionContext). runtime whole package Test Files 494/494, Tests 8048 passed 19 skipped. Ablations via ablation-replace on automation.ts (src import, no dist), each anchor 1->0 and restored blob == HEAD: drop agent branch 2/31 red; oauth unnamed 2/31 red (first attempt refused by the tool: replacement was a substring, count could not rise; re-run with distinct replacement); api_key unnamed 2/31 red; refusal never fires 3/31 red.",
      "gates": "dispatch-gates --commands on 1788eefb derived 91 families for 4 paths; each run with stdin /dev/null, exit captured by redirect: 91 exit 0 (check-plugin-teardown-shape --self-test first exit 3, fixture commit missing from the shallow clone; fetched it, re-run exit 0). --ran: 91 accounted, 0 NOT-MEASURED, exit 0 (list out/28468-gates-ran-1788eefb.list). Scoped lint (eslint --no-inline-config packages/runtime): exit 0. runtime typecheck: exit 0. CI check-runs: in_progress at report time.",
      "line_budget": "4 files, +202 / -4",
      "files_changed": [
        ".changeset/28468-connector-connection-delegated-caller.md",
        "content/docs/automation/connectors.mdx",
        "packages/runtime/src/domains/automation.ts",
        "packages/runtime/src/domains/automation-connector-connection-door.test.ts"
      ],
      "deviations": [
        "Dispatch named the docs line as one line; it is one sentence wrapped over four source lines.",
        "No PR assignee or reviewer written (frame rule; the harness default to assign os-tesla was not followed)."
      ],
      "dogfood_battery": "1788eefb · os-verify-lock VERDICT command-exit 0 · Test Files 362 passed 3 skipped (365) · Tests 2922 passed 28 skipped (2950) · no failures",
      "mcp_calls": "0",
      "api_writes": "2 — relay pr_create (run 41244268368, POST /repos/objectstack-ai/objectstack/pulls -> #28474, body read back identical); post-stamped comment on #28468 (this report)",
      "open_questions": [],
      "out_of_scope_findings": []
    }
  5. objectstack-fleet commented on Oct 31, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#1 · os-tesla · session_01L9qibz3ZUbZ8Qcn1rDw9yc

    Landing record · #28468 · PR #28474

    domain:server seat 1 · session_01L9qibz3ZUbZ8Qcn1rDw9yc · 2026-10-31T22:28Z

    Reading Probe Result
    Merged GET pulls/28474 merged, 5e706e7a
    Ancestry git merge-base --is-ancestor 5e706e7a origin/main yes
    Content git grep -c connectorConnectionDelegatedCaller in runtime/src/domains/automation.ts on origin/main present
    • Landed: under ruling A (6548764795), the connector connection door's begin and revoke legs now refuse a delegated or agent caller by name: an agent, an OAuth token, or an API key. Connecting and revoking is a human administrator's act. The read leg, the callback, human holders and isSystem are unchanged. @objectstack/runtime ships a patch changeset. The card closed via Fixes.

    Release: claim 6548795089 (session_01L9qibz3ZUbZ8Qcn1rDw9yc, branch claude/project-thread-0wkobq) · 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