You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Object-form params on a type:'url' inline action is a THIRD meaning of the key (interpolation scope + newTab) with no authorized spelling (observation) #6828
Found while implementing #5777 (PR #6819). Not fixed there — filing per Prime Directive #10 so the third meaning is written down before someone assumes there were only two.
#5777 measured params carrying two fact-contracts on an inline action and the maintainer ruled direction A: the type:'api'request payload moves to its own key (bodyExtra), params keeps only the ActionParam[] definition-array meaning.
While scoping that conversion I had to answer "does object-form params mean the same thing on every inline action type?" It does not. On type:'url' it is a third concept again, and objectui reads it in two places:
packages/core/src/actions/ActionRunner.ts — interpolateTarget takes a non-array params as the ${param.X} interpolation scope for the target URL. This is a live, documented mechanism: target carries ${param.X} / ${ctx.X} tokens and the runner substitutes them (URL-encoded) just before navigation.
the same file's executeUrl — reads params.newTab as the legacy new-tab escape hatch, below openIn in priority.
So the same key has meant: definition array (spec), api request payload (#5777, now bodyExtra), and url interpolation scope / newTab flag (this issue).
Why the #5777 conversion deliberately does not touch it
inline-action-api-params-to-body-extra guards on action.type === 'api' precisely because of this. Rewriting a url action's object-form params into bodyExtra would be lossy, not lossless — an api request-body key is not an interpolation scope — and ADR-0087 D2 requires losslessness. The guard is correctness, not conservatism, and it is pinned by a test.
Why this is observation-class
Nothing in the reachable corpus authors it. I grepped origin/main in all three repos for inline-action sites (objectstack examples, cloud service-tenant pages, objectui). Every type:'url' inline action is target-only; the only object-form params anywhere was the showcase's api submit button, which InlineActionSchema.params 声明为参数定义数组,但 type:'api' 的活消费者(与 showcase 页)用的是静态载荷 map —— 一个键两种形状 #5777 migrates.
The spec already refuses it, and always has: params is z.array(ActionParamSchema), so a url action authored this way fails the props parse. After InlineActionSchema.params 声明为参数定义数组,但 type:'api' 的活消费者(与 showcase 页)用的是静态载荷 map —— 一个键两种形状 #5777 the refusal message names bodyExtra, which for a url action is the wrong prescription — but only for a shape nobody writes and the schema rejects.
So no user hits this today. It is a latent inconsistency in the vocabulary, not a live defect.
What a fix would have to decide
Not obvious, which is the other reason this is a record rather than a patch:
Is the interpolation scope worth an authorable key at all?${param.X} on an inline action with no param dialog can only read a statically-authored bag — which is what target string interpolation already expresses more directly. This may be a capability with no business pull (startup-focus axis), in which case the answer is retirement in objectui, not a new spec key.
params.newTab is already superseded by the declared openIn key, which the runner reads with priority. That half looks like a plain deprecation.
Deciding this needs the same three-axis analysis #5777 got, and it needs objectui's read of whether the interpolation scope has any consumer left. Filing unlabeled for triage rather than guessing.
Related: #5777 (the payload half, ruled 2026-08-06), PR #6819 (spec half), #5068 (the props gate that made any of this visible).
Found while implementing #5777 (PR #6819). Not fixed there — filing per Prime Directive #10 so the third meaning is written down before someone assumes there were only two.
What #5777 settled, and what it did not
#5777 measured
paramscarrying two fact-contracts on an inline action and the maintainer ruled direction A: thetype:'api'request payload moves to its own key (bodyExtra),paramskeeps only theActionParam[]definition-array meaning.While scoping that conversion I had to answer "does object-form
paramsmean the same thing on every inline action type?" It does not. Ontype:'url'it is a third concept again, and objectui reads it in two places:packages/core/src/actions/ActionRunner.ts—interpolateTargettakes a non-arrayparamsas the${param.X}interpolation scope for the target URL. This is a live, documented mechanism:targetcarries${param.X}/${ctx.X}tokens and the runner substitutes them (URL-encoded) just before navigation.executeUrl— readsparams.newTabas the legacy new-tab escape hatch, belowopenInin priority.So the same key has meant: definition array (spec), api request payload (#5777, now
bodyExtra), and url interpolation scope /newTabflag (this issue).Why the #5777 conversion deliberately does not touch it
inline-action-api-params-to-body-extraguards onaction.type === 'api'precisely because of this. Rewriting aurlaction's object-formparamsintobodyExtrawould be lossy, not lossless — an api request-body key is not an interpolation scope — and ADR-0087 D2 requires losslessness. The guard is correctness, not conservatism, and it is pinned by a test.Why this is observation-class
origin/mainin all three repos for inline-action sites (objectstackexamples,cloudservice-tenant pages,objectui). Everytype:'url'inline action is target-only; the only object-formparamsanywhere was the showcase'sapisubmit button, whichInlineActionSchema.params声明为参数定义数组,但type:'api'的活消费者(与 showcase 页)用的是静态载荷 map —— 一个键两种形状 #5777 migrates.paramsisz.array(ActionParamSchema), so aurlaction authored this way fails the props parse. AfterInlineActionSchema.params声明为参数定义数组,但type:'api'的活消费者(与 showcase 页)用的是静态载荷 map —— 一个键两种形状 #5777 the refusal message namesbodyExtra, which for aurlaction is the wrong prescription — but only for a shape nobody writes and the schema rejects.So no user hits this today. It is a latent inconsistency in the vocabulary, not a live defect.
What a fix would have to decide
Not obvious, which is the other reason this is a record rather than a patch:
${param.X}on an inline action with no param dialog can only read a statically-authored bag — which is whattargetstring interpolation already expresses more directly. This may be a capability with no business pull (startup-focus axis), in which case the answer is retirement in objectui, not a new spec key.params.newTabis already superseded by the declaredopenInkey, which the runner reads with priority. That half looks like a plain deprecation.InlineActionSchema.params声明为参数定义数组,但type:'api'的活消费者(与 showcase 页)用的是静态载荷 map —— 一个键两种形状 #5777 gave the payload — a separate key, not a third arm ofparams.Deciding this needs the same three-axis analysis #5777 got, and it needs objectui's read of whether the interpolation scope has any consumer left. Filing unlabeled for triage rather than guessing.
Related: #5777 (the payload half, ruled 2026-08-06), PR #6819 (spec half), #5068 (the props gate that made any of this visible).