Skip to content

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

Description

@os-zhuang

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 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.tsinterpolateTarget 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

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:

  1. 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.
  2. params.newTab is already superseded by the declared openIn key, which the runner reads with priority. That half looks like a plain deprecation.
  3. If (1) says keep, the key needs its own name and the same treatment InlineActionSchema.params 声明为参数定义数组,但 type:'api' 的活消费者(与 showcase 页)用的是静态载荷 map —— 一个键两种形状 #5777 gave the payload — a separate key, not a third arm of params.

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).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions