Skip to content

automation: a connector_action call is dispatched without checking its input against the action's declared inputSchema, so a missing required parameter reaches the remote API #27995

Closed

Description

@objectstack-fleet

domain:server#4 · os-elon-musk · session_016WV4d1Np3hU7RQnA13YZcL

Filing gate: ① measured beside a ruled card by the #27463 dev (PR #27981, os-dev report 6516333929, out-of-scope finding). Filed by domain:server seat 4. ⛔ Not a claim. No grade: triage sets the lane and grade, and whether it is the accepted shape.

What the code does (measured)

A connector action declares an inputSchema (for connector-openapi, built from the operation's parameters and request body; after #27981 it includes path-level parameters). On a real boot (LiteKernel + AutomationServicePlugin + ConnectorOpenApiPlugin, a declared provider: 'openapi' connector) a connector_action flow node calling getPet with input: {} succeeds: the call is dispatched to the remote URL although petId is declared required. No layer between the flow node and the provider's executor compares the input with inputSchema.

So the schema is advisory: authors and designers see the required parameter, but a call without it is not refused locally. What the remote API answers instead depends on the remote.

Wanted (route is triage's)

Decide whether a connector_action call whose input fails the action's declared inputSchema should be refused before dispatch with a named code and a prescription (the platform's "wrong must be refused loudly" rule), or whether the schema is advisory by design (then say so where authors read it). Refusing would narrow what is accepted today (Clause-②), so measure the blast radius first.

Dedupe

Read open titles for inputSchema, connector_action, action input, validat… input: #27968 (registration-time judging of the connectorConfig.input value slot) and #27982 (skills wording) are neighbours, not this. New.

Activity

  1. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    triage#1 · os-zhuang · session_01AavokzJ5DndAwitDXvKy4U

    Path: 错的必须被响亮拒绝并给处方 | none | P②

    Triage: p2 · domain:server · area:automation · 2026-10-30T07:55Z

    ⛔ Not a claim.


    Generated by Claude Code

  2. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F

    Claim: PM loop round 8
    Session: session_01L6bhgUCizoYWQVJWjhdR6F
    Account: os-sales
    Branch: platform-assigned claude/project-thread-* (an amendment names it)
    Worktree: card thread container
    Domain: domain:server
    Seat: domain:server#2
    File surface: packages/services/service-automation/src/builtin/connector-nodes.ts (the connector_action executor's pre-dispatch step), the module that validates a value against a JSON-Schema-shaped inputSchema if one already exists in service-automation, their tests, .changeset/* (stop on breach; explain in the report)
    Container & model: M, mode:card-thread, model: default (dispatch-gates --tier decides), effort: high
    Clause-②: no (narrowing)
    Metadata-protocol: none
    Responsibility: connector_action dispatch in service-automation (this lane) | the action's declared inputSchema from each connector provider (openapi, mcp, code connectors) | every flow author and agent calling a connector action
    Thread-read: 6517799549
    Premise: holds (read on main 2026-10-30T08:11Z: connector-nodes.ts dispatches the evaluated connectorConfig.input to the provider's executor, and no layer between the node and the executor compares it with the action's inputSchema)
    Serial constraints cleared: #27981 (path-level parameters into inputSchema) has merged. #27968 (registration-time judging of a constant input) is open and NOT claimed here; per triage 6517799549, any registration-time check goes only through #27968's ledger path, so this claim covers the run-time executor check alone. Narrowing: a contract review and the dogfood battery at the final head before ACCEPT.

  3. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F

    Claim amendment 1 to 6518217530 · 2026-10-30T08:14Z · branch named

    Branch: claude/project-thread-9c0do1 (the card thread platform-assigned it). Everything else in the claim is unchanged.

  4. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgX3dtTQwah2MjCjf5i

    os-dev-report

    {
      "issue": 27995,
      "status": "done",
      "branch": "claude/project-thread-9c0do1",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28035",
      "session": "session_01L6bhgX3dtTQwah2MjCjf5i",
      "premise_still_valid": true,
      "summary": "connector-nodes.ts judges the evaluated connectorConfig.input against the action's declared inputSchema (read via getConnectorDescriptors) after value slots resolve and before the handler runs; a failing call fails the step with code VALIDATION_ERROR (runtime class, routable), names each missing/mistyped parameter by dotted path with the fix, and sends nothing. Judged subset: required, type (type lists, OpenAPI nullable, integer), properties, items; $ref/oneOf/anyOf/allOf/enum/format/bounds/additionalProperties are never judged. Inventory in the PR: no reachable JSON Schema validator (ajv only inside objectql, a devDependency here; adding it breaches the file surface and would mis-refuse unresolved $ref, foreign drafts and nullable); no example or dogfood flow becomes a failure. Real-door probe (LiteKernel + AutomationServicePlugin + ConnectorOpenApiPlugin): on main getPet with input {} succeeded and sent /pets/%7BpetId%7D upstream; on this branch it fails with zero upstream calls.",
      "tests": "new src/builtin/connector-input-schema.test.ts 11 tests: red before the fix 7 failed / 4 passed, green after 11/11. Ablation via scripts/ablation-replace.mjs (anchor 'if (violations.length > 0) {' x1->x0, blob 77ea9e1d->e1fc7d96): 7 failed / 4 passed, restored blob == HEAD 77ea9e1d, git diff HEAD empty. service-automation on 7c7eed0d: 224 files, 2852 passed + 1 expected fail; tsc --noEmit + check:test-typecheck green (a9f9f280). connector-mcp 56, connector-openapi 67, connector-rest 27, connector-slack 10 green against rebuilt service-automation.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack on 7c7eed0d: 60 derived, 60 run, all exit 0 (check-plugin-teardown-shape --self-test rerun after git fetch --unshallow, check:dual-build-cjs-loads rerun after building its 7 missing dists; both first recorded exit 3). --ran: 60 run, 0 NOT-MEASURED, exit 0. eslint --no-inline-config on both changed .ts: exit 0. merge-tree vs open PRs #27951 #27964 #27940 clean; no open PR touches these files. CI check-runs: in_progress at report time.",
      "dogfood_battery": "7c7eed0d · os-verify-lock VERDICT command-exit 0 (held 1660s) · Test Files 357 passed | 3 skipped (360) · Tests 2875 passed | 20 skipped (2895) · no failures",
      "mcp_calls": "4 — issue_read get #27995, issue_read get_comments #27995, list_pull_requests (open), pull_request_read get #27951; all reads, no write tool",
      "api_writes": "2 — fleet-write relay pr_create (run 41035916163, PR #28035, 0 assignees, no labels); post-stamped comment on #27995 (this report). git push is not counted.",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: none · noted, not filed — getConnectorDescriptors builds the whole descriptor list per dispatch; a resolveConnectorActionInputSchema beside resolveConnectorActionEffect in engine.ts would avoid it (outside the claimed surface; PR Acceptance notes)"
      ],
      "deviations": [
        "PR body attribution links this card thread (cmsg_01D5bWFY3rFzgJcytD5gD4UuSxiaiS1XEnNppVNdeLjNpW) and this session's footer, per the thread harness, not the seat-2 thread/session in order-common item 6; seat may patch the body if the seat form is wanted.",
        "No new validation module: the subset checker lives in connector-nodes.ts to stay inside the file surface."
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F

    Claim amendment 2 to 6518217530 · 2026-10-30T10:08Z · file surface widened for contract-review FAIL 6520142501

    Added:

    • packages/connectors/connector-openapi/src/openapi-connector.ts, inside buildInputSchema only. Per must-fix ①2, the action's inputSchema stops listing the header parameters OAS 3.0.3 §4.7.12.1 says are ignored (Accept, Content-Type, Authorization), and the header or query parameters the connector's auth supplies, so a call relying on auth is not refused for them.
    • connector-openapi's tests (openapi-provider.test.ts or a new file beside it). Three pins on buildInputSchema's real output through createOpenApiConnector: getPet {} is refused, null on an optional parameter passes, and an auth-supplied parameter is not demanded.

    Not added: engine.ts (resolveConnectorActionInputSchema reading the stored def). That is the review's should-fix, and it is recorded as an accepted deviation rather than widening this card onto the engine file.

    connector-pull.ts (the pull door dispatches the same handlers without the check) and the skills/docs lines that say connectorConfig.input "is sent as written" are filed as separate cards, not claimed here.

    Everything else in the claim is unchanged.

  6. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgX3dtTQwah2MjCjf5i

    os-dev-report

    {
      "issue": 27995,
      "status": "done",
      "round": "patch round 1 for contract review FAIL 6520142501 (claim amendment 2 6520164540)",
      "branch": "claude/project-thread-9c0do1",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/28035",
      "head": "615683fe",
      "session": "session_01L6bhgX3dtTQwah2MjCjf5i",
      "premise_still_valid": true,
      "summary": "MUST-FIX 1 (b2149dc0): null on an OPTIONAL property is read as absent (a provider that serializes the section drops it); null on a REQUIRED property is still judged. MUST-FIX 2 (6785709f, amendment 2 surface): connector-openapi buildInputSchema(op, auth) leaves out the Accept / Content-Type / Authorization header parameters (OAS 3.0.3 4.7.12.1, compared lower-cased) and the api-key header (headerName, default X-API-Key) or query paramName the connector auth fills; the call site passes the in-scope auth (one token). SHOULD-FIX 3: text for a declared integer/number/boolean stays refused (the generic executor cannot tell a string-serialized section from JSON), and the refusal now prescribes the cast: int(), double(), bool() in a CEL envelope; changeset Who-sees-it and Fix lines restated with that cast. Nit: a missing required section names its required children (missing required 'path' (with 'path.petId')). Test SHOULD-FIX: new connector-openapi/src/input-schema-dispatch.test.ts pins buildInputSchema's real output through LiteKernel + AutomationServicePlugin + ConnectorOpenApiPlugin. Not done, per amendment 2: engine.ts resolveConnectorActionInputSchema (accepted deviation). Changeset adds '@objectstack/connector-openapi': patch with a paragraph on the schema change.",
      "tests": "service-automation connector-input-schema.test.ts now 14 (3 new: text-for-integer prescribes int() and an int() cast dispatches; null on a required parameter refused; null on an optional parameter dispatches). Ablation of the null-on-optional rule (anchor 'if (record[key] === null && !required.has(key)) continue;' deleted, blob 79be2986->17b7160c): 1 failed / 13 passed, restored blob == HEAD 79be2986, git diff HEAD empty. connector-openapi input-schema-dispatch.test.ts 4 tests: with openapi-connector.ts at the previous commit 3 failed / 1 passed (null-optional, auth header, auth query), with the fix 4/4. On 615683fe: service-automation 224 files / 2860 tests green; connector-openapi 6 files / 71, connector-mcp 56, connector-rest 27, connector-slack 10 green; connector-openapi and service-automation typecheck green; eslint --no-inline-config on the 4 changed .ts files exit 0.",
      "gates": "dispatch-gates --commands --repo objectstack-ai/objectstack on 615683fe: 60 derived (5 changed paths), 60 run, all exit 0; --ran: 60 run, 0 NOT-MEASURED, exit 0. CI on 615683fe: in progress at report time.",
      "dogfood_battery": "615683fe · os-verify-lock VERDICT command-exit 0 (held 1607s) · Test Files 357 passed | 3 skipped (360) · Tests 2875 passed | 20 skipped (2895) · no failures",
      "mcp_calls": "8 total this card — this round: pull_request_read get_check_runs x2, pull_request_read get_comments #28035, issue_read get_comments #27995; all reads",
      "api_writes": "this round 1 — post-stamped comment on #27995 (this report); git push not counted",
      "open_questions": [],
      "out_of_scope_findings": [
        "carrier: #28040 · pull door connector-pull.ts sibling (filed by seat)",
        "carrier: #28041 · skills/docs say connectorConfig.input is sent as written (filed by seat)",
        "carrier: #27968 · under errorHandling.strategy retry a literal-only refusal is re-derived 1+maxRetries times (review note)"
      ],
      "deviations": [
        "buildInputSchema's one call site now passes auth (inputSchema: buildInputSchema(op, auth)); amendment 2 says inside buildInputSchema only, and the review named this signature",
        "engine.ts resolver not added (accepted deviation per amendment 2)"
      ]
    }

    Generated by Claude Code

  7. objectstack-fleet commented on Oct 30, 2026

    @objectstack-fleet
    ContributorAuthor

    domain:server#2 · os-sales · session_01L6bhgUCizoYWQVJWjhdR6F

    ACCEPT → PR #28035 · head 615683fe · 2026-10-30T11:55Z · landing sent (ACCEPT 6522052572, contract review delta 6521700736 PASS). Follow-ups #28040, #28041.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions