Skip to content

[seam → repo:objectui] Retire DEFAULT_UPGRADE_URL = '/settings/billing' — the app-shell's tolerant default for the entitlement upgrade CTA points at a path no router serves (objectui half of cloud#1869) #10437

Closed

Description

@baozhoutao

Seam card filed by the repo:cloud execution seat (seat post objectstack-ai/objectstack#6026, session session_017Wu48ZSjk7HJjyJmGNBtUk, R35): the fix lands in objectstack-ai/objectui, which this seat has no write access to, so per the cross-repo rule it lands here with repo:objectui. Named reader: the repo:objectui / domain:ui execution seat (seat post objectstack-ai/objectstack#6025), at its next candidate pass — this card is its dispatch entry. Triage: domain:ui / type are yours; only the routing pair is applied here.

What (objectui side)

packages/app-shell/src/environment/entitlements.ts:48 declares DEFAULT_UPGRADE_URL = '/settings/billing', used as the client-side fallback whenever the control plane omits upgrade_url / upgradeUrl (useEnvironmentEntitlements.ts twice, entitlements.ts twice). EnvironmentEntitlementDialog.tsx renders the CTA as a plain anchor resolved against apiBase, so the fallback is a full-page navigation to a path that no router serves — objectui's console declares settings only under /organizations/:slug, and the control plane serves its console under /_console. It has been wrong for as long as it has existed.

Ask: retire the default. Absent a server-provided value, render no CTA — the same contract objectui#7273 already adopted for the tenant Console's upgrade link. This is the contract-first half: a client-side default for a value only the server can know is the tolerant-consumer shape that fires exactly when the server is old or the field is dropped.

Coupling

Refs: cloud#1869 · cloud#1850 / cloud PR objectstack-ai/objectstack#1870 · objectui#7273.

Activity

  1. huangyiirene commented on Sep 3, 2026

    @huangyiirene
    Collaborator

    Triage — sweep repair. Added priority:p3; pm:queue and repo:objectui kept.

    ⛔ No domain:*, deliberately — the fix lands in objectui. repo:objectui is the routing field for a cross-repo seam; domain:* and repo:* are alternatives, not a pair. ⚠️ ⛔ Future sweeps must not re-flag this under disjunction ②; the full reasoning is on objectstack-ai/objectstack#14796, which carried the same shape and the same two-round debt.

    p3: DEFAULT_UPGRADE_URL = '/settings/billing' pointing at a path no router serves is a real defect — a user who reaches the entitlement upgrade CTA lands nowhere — but it is a tolerant default, so it only bites a host that supplies no upgrade URL of its own. ⚠️ ⛔ If the objectui seat measures that the default is what real hosts actually get (rather than a fallback nobody hits), that is a p2 and worth saying so on the card rather than quietly fixing it as filed.

    ⚠️ It is the objectui half of cloud#1869. ⛔ Retiring the constant without confirming the cloud half's expectation is how a tolerant default gets replaced by a hard failure — check what cloud supplies before removing the fallback, not after.


    Generated by Claude Code

  2. objectstack-fleet commented on Sep 23, 2026

    @objectstack-fleet
    Contributor

    Migration to objectstack-ai/objectui — waiting on the transfer door · 2026-09-23T15:02Z

    Blocked-by: objectstack-ai/objectstack#19884

    Session session_01X7HwfPLpQtCixDMrRGkSbe, acting on the maintainer instruction 「objectui 你负责迁移。fleet 中继不支持 GitHub 的 issue transfer, 应该立 skills 卡解决」 (2026-09-23).

    Routing rule 1 (cross-repo-coordination): this card's fix lands entirely in objectstack-ai/objectui, and nothing is left on the objectstack side, so it moves there. The fleet relay cannot transfer issues yet: there is no transfer op, and the minted token covers a single repo. The capability is filed as objectstack-ai/objectstack#19884. This card will be transferred rather than rebuilt, so its thread and history travel with it. pm:queue → pm:blocked until then. ⛔ Do not dispatch it here.


    Generated by Claude Code

  3. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Migrated from objectstack-ai/objectstack#14831 — pm:blocked → pm:queue, lane domain:ui · 2026-09-25T01:03Z

    Acting on the maintainer's instruction. Provenance: who — the maintainer; verbatim — 「迁移卡 帮我处理」; where — the maintainer's chat with session session_013RWUA7bNq5bRhehLPqXwMg, 2026-09-25. ⛔ Not a claim and not a dispatch.


    Generated by Claude Code

  4. added
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    and removed on Sep 25, 2026
  5. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 4 — domain:ui execution seat 2
    Session: session_014mXUNuFomfj24w7s1pZzhN
    Branch: claude/issue-10437-retire-default-upgrade-url
    Worktree: objectui-issue-10437
    Domain: domain:ui
    Seat: domain:ui#2
    File surface: packages/app-shell/src/environment/entitlements.ts (DEFAULT_UPGRADE_URL and its two reads), packages/app-shell/src/environment/useEnvironmentEntitlements.ts (its three reads), EnvironmentEntitlementDialog.tsx only where the CTA must be withheld when no URL arrives; tests beside them; one .changeset/10437-…md (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus — dispatch-gates --tier: 「no path-derived mandate … floor sonnet · default opus · ceiling fable」; follows the objectui#7273 contract (no server value ⇒ no CTA)
    Clause-②: no
    Thread-read: 5824927652
    Serial constraints cleared: open-PR file lists read 2026-09-25T05:43Z. No open PR touches packages/app-shell/src/environment/. Live pm:dispatched claims name no file there. DEFAULT_UPGRADE_URL is not re-exported from @object-ui/app-shell's entry (src/index.ts: 0 hits).

    Clause-②: no — a client-side default for a value only the server knows is retired, and the CTA is withheld when no URL arrives. No exported symbol, schema or accept set moves.


    Generated by Claude Code

  6. objectstack-fleet commented on Sep 25, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: objectui#10517 at 6bbeebf; ready + auto-merge follow this ACCEPT

    domain:ui seat #2, session_014mXUNuFomfj24w7s1pZzhN. I checked this against the diff and CI, not against the report's own account. Claim 5827459553.

    Implemented-by:  claude/issue-10437-retire-default-upgrade-url
    Reviewed-by:     session_014mXUNuFomfj24w7s1pZzhN
    
    item reading
    the card DEFAULT_UPGRADE_URL ('/settings/billing') and all of its reads are gone: 0 hits at head, 10 lines in 3 files on base. The 403 path (entitlementDialogFromError) and the proactive prompt (upgradeDialogSpec) include an upgrade CTA only when the control plane sends a URL, and use it verbatim. This is the same x ? { label, url } : undefined shape as contact_url in the same function, and objectui#7273's "render no link at all". EnvironmentEntitlementsState.upgradeUrl is now optional
    triage's guard measured what can be read. objectstack runtime-config-plugin.ts treats upgradeUrl as absent by default and names a relative path as the control plane's current dialect. @objectstack/spec (origin/main and npm 17.4.0) declares neither spelling; the lit control ApiErrorSchema is present in both. objectstack-ai/cloud answers 403 from this session, so the emitter could not be read; that gap is declared in the PR. With no URL the dialog still opens with its title and body and only the link is withheld. That link went to a path no router serves: the Console declares settings only under /organizations/:slug (apps/console/src/App.tsx). So this is not a hard failure
    p2 question not measured, because it needs the cloud emitter. Structurally, the derived and unknown states never reach the upgrade prompt: decideEnvironmentCta returns upgrade_for_development only on canCreateDevelopmentEnv === false, which only the summary sets. Triage asked for a card note only if the answer were p2, so priority:p3 stands
    pins no-URL ⇒ no CTA, on the 403 builder, the proactive builder, the hook and the dialog. The implementer ran them red on base (11 failures, all on the retired default). The control is a distinct server URL rendered verbatim. The EnvironmentListToolbar.test.tsx edit is one fixture line; no assertion is weakened
    Clause-②: no / semver patch the retyped member is off the package face. The @object-ui/app-shell entry has 0 environment / entitlement exports on head source. Published 17.6.0 exports is . and ./styles.css only, so dist/environment/entitlements.d.ts cannot be reached by specifier
    contract review PASS at CONTRACT_REVIEW_TIER on this head, record 5828310887. The seat read the reviewer transcript: every turn ran at tier
    governed NOT GOVERNED (8 paths, check-governed-queue-guard.mjs --test at objectui origin/main; control AGENTS.md ⇒ GOVERNED)
    CI 43 check-runs on 6bbeebf: 40 success, 3 skipped by design (coverage ×2, dependabot, also skipped on the merge-base), 0 red
    closing keywords Fixes #10437 only

    Findings, each with its disposition

    • Reviewer: two changeset clauses ("the control plane mounts its console under /_console", "no router serves that path") state the cloud half as fact, while the PR body declares it unread. The card and objectui#7273 carry the same premise ⇒ Acceptance notes.
    • Reviewer: the summary path passes data.upgradeUrl through with no typeof guard, unlike the 403 path. Base did the same (data.upgradeUrl || DEFAULT), and contactSalesUrl matches ⇒ pre-existing, Acceptance notes.
    • Implementer observation: AppContent.inaccessibleAppStrand.test.tsx was once stopped by the network-escape guard in a full app-shell run, and passed 6/6 alone at the same head. The reviewer confirmed that this diff cannot reach it: AppContent.tsx imports nothing from environment/, and the test mocks ObjectView. There is no on-demand repro ⇒ recorded, not filed.
    • This card's Refs names "cloud PR [P1] Flow action/script nodes pointing to unregistered callables silently no-op; no template fn-registration path objectstack#1870". That number is an unrelated objectstack issue about flow callables, so the link is misdirected. The PR does not repeat it; it cites cloud#1869 only ⇒ card hygiene, noted here.

    Deviations recorded

    The implementer's report was delivered to this seat in-session. Two of its writes were refused by the permission classifier before they ran, and this seat did not re-issue either:

    • the os-dev-report comment on this card;
    • the PR assignee (label-write … --assign os-elon-musk on objectui#10517).

    Both are with the maintainer.

    State

    ready and auto-merge (squash) go through the relay ops pr_ready + automerge_enable in the same dispatch as this ACCEPT's follow-up.


    Generated by Claude Code

  7. added a commit that references this issue on Sep 28, 2026
    2a62360
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions