Repository navigation
fix(connector-openapi): send each parameter by its declared style and explode - #28537
Conversation
…and explode Query, path and header parameter values were passed through String(), so an object went out as [object Object] and an array as a comma list whatever the document declared. Each value is now encoded by its Parameter Object's style / explode (or the OpenAPI 3.x default for its location); an undefined style refuses the operation at materialization, and a value the style cannot carry fails the dispatch before anything is sent. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
…e Stripe fixtures Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
…eset Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
The Limits bullet told authors to leave expand and the created range filters out because they went out as plain pairs; they are now sent by their declared deepObject style. Claude-Session: https://claude.ai/code/session_017xRBcVBKAFk1ntXSjvPt7U Co-authored-by: Claude <noreply@anthropic.com>
📓 Docs Drift CheckThis PR changes 2 package(s): 1 hand-written doc(s) NAME something this change touched and may need an implementation-accuracy re-verification:
What this run could not see
Coarse fallback — 2 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): Which tree this was computed onThis run read A worktree cut from an older # while this PR is open — GitHub drops the merge commit once it closes
git fetch origin f63a5da1c63f8fa68818014a1ce4598b201adea3 && git checkout f63a5da1c63f8fa68818014a1ce4598b201adea3
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin 37184244b82b9e4234581b653cdc7554e74e6136 73e2a2ec62142c8ad97cbec4619beb9ff9adc241 && git checkout -B drift-repro 37184244b82b9e4234581b653cdc7554e74e6136 && git merge --no-ff 73e2a2ec62142c8ad97cbec4619beb9ff9adc241
node scripts/docs-audit/affected-docs.mjs --json 37184244b82b9e4234581b653cdc7554e74e6136
|
|
epic:#27293#1 · sunhaolin · session_017xRBcVBKAFk1ntXSjvPt7U 席位核对ACCEPT at head
Noted, not filed (agreed): cookie parameters are never sent, and Landing: not governed. The seat lands it ( |
Fixes #28504
Clause-②: no
Metadata-protocol: none
维护者速读
style/explode(或 OpenAPI 3.x 默认值)编码,对象和数组不再经String()变成[object Object]或逗号串。deepObject传日期区间和expand,此前请求被静默发错、运行却答 200;作者和 AI 按 schema 填参也照样发错。packages/connectors/connector-openapi/src/parameter-serialization.ts(serializeQueryParameter与deepPairs,deepObject 数组取下标括号);openapi-connector.ts的parameterEncodings/withAuthQuery(启动期拒绝与 api-key 合并);parameter-style.test.ts。pnpm --filter @objectstack/connector-openapi exec vitest run --maxWorkers=2 src/parameter-style.test.ts,预期 17 passed,其中 Stripe 的created发成created%5Bgte%5D=1700000000。What changes
src/parameter-serialization.ts: each sent parameter is encoded by its Parameter Object'sstyle/explode, or by its location's OpenAPI 3.x default when it declares none (queryform, exploded; path and headersimple). Implemented: queryform,spaceDelimited,pipeDelimited,deepObject; pathsimple,label,matrix; headersimple. Scalars are the only values that become text.deepObjecton an array (Stripe'sexpand) brackets each index,expand[0]=a&expand[1]=b: the style's own rule (each property in brackets) applied to the array's keys, rather than a guessedexpand[]convention. Nested values recurse the same way.styleOpenAPI 3.x does not define for its location, or a non-booleanexplode, throws fromcreateOpenApiConnectornaming the operation, the parameter and the style (fatal at boot for a declarative instance;includethat leaves the operation out clears it).ParameterValueError): a value the declared style has no encoding for (an array of objects forform, an object for explodedspaceDelimited, any non-scalar for acontent-typed parameter) fails the step beforefetchis called.OpenApiParametergains optionalstyle,explode,content.content/docs/automation/connectors.mdxstates how parameters are sent and adds the two refusals to the failure table;packages/apps/connector-stripe/README.mdLimits bullet, which told authors to leaveexpand/created[gte]out, now says how they are sent (this change made it false).@objectstack/connector-openapipatch.Tests
src/parameter-style.test.ts(17): the three Stripe shapes withGetInvoices' five parameter objects copied verbatim from Stripe's document (MIT), equal to the packagedconnector-stripedocument's objects (one-off canonical-JSON compare:equal true); two scalar controls (query and path); the style table; the auth-merge case; both refusals, the dispatch refusal asserting the error class and zerofetchcalls.openapi-connector.tsswapped in, restored withgit checkout HEAD --, hash re-matched): 15 failed / 2 passed of 17. The 2 that stay green are the scalar controls, so scalar output is byte-identical to the old code. Old outputs read off the failures:created=%5Bobject+Object%5D,expand=data.customer%2Cdata.subscription,due_date=%5Bobject+Object%5D.bootStack, a flow callingGetInvoicesviaPOST /api/v1/automation/:flow/triggeranswered 200 and the fake Stripe receivedhttps://api.stripe.com/v1/invoices?created%5Bgte%5D=1700000000&due_date%5Bgte%5D=1700000000&due_date%5Blt%5D=1702592000&expand%5B0%5D=data.customer&expand%5B1%5D=data.subscription&limit=3.Acceptance notes
expand[0]=…andcreated[gte]=…is NOT MEASURED (no key); the tests run against a fake Stripe.allowReservedis not read: reserved characters stay percent-encoded, as before.,as%2C, a space as+,|as%7C), which is how a scalar was always encoded; path delimiters stay literal.Verification
All readings at head
73e2a2ec(after mergingorigin/mainateeec88d1), repositoryobjectstack-ai/objectstack.Package tests and typecheck
pnpm --filter @objectstack/connector-openapi test: Test Files 9 passed (9), Tests 109 passed (109).pnpm --filter @objectstack/connector-openapi typecheck: exit 0;check:test-typecheck: OK, 1 file / 5 errors / 1 pinned signature held (pre-existing ledger, unchanged).pnpm --filter @objectstack/connector-app-stripe test(the consumer that boots the packaged Stripe document):objectstack validatepassed, Test Files 2 passed (2), Tests 16 passed (16).os-verify-lock: VERDICT command-exit 0.Derived gate families
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 88 commands for the 6 changed paths; every one run on73e2a2ec, each exit code captured before any pipe: 88 exit 0.--ranreconciliation:88 derived, 88 run, 0 NOT-MEASURED, 0 UNRUN.node scripts/check-nul-bytes.mjs: exit 0.pnpm lintsweep.Generated by Claude Code