Skip to content

@objectstack/client 仍有一族绕过 getRoute() 的硬编码 API base:email.send、cloud.environments.*、ScopedProjectClient 的 scope 前缀 #6714

Closed

Description

@os-project-manager

out-of-scope 发现,来自 #6633 的实施(PD #10 单独立单,未认领)。#6633 / PR #6712 只覆盖其四车道(spec ApiRoutes 键 / protocol 映射 / rest 通告 / client packages.* + external.*),本单记录 client 里其余绕过 getRoute() 的硬编码面。

事实(全部实测,origin/main = d6d1a50be,packages/client/src/index.ts)

ObjectStackClient 的路由派生机制是 getRoute(key)(优先 discoveryInfo.routes[key],fallback convention)。#6633 落地后,以下面仍不经过它,discovery 通告任何非默认 base 均不跟随:

  1. email.send — :1049 硬编码 `${this.baseUrl}/api/v1/email/send`。服务端 registerEmailEndpoints(bp) 挂在 RestServer.getApiBasePath() 下(跟随 apiPath),所以设 apiPath 的部署服务端已搬走、client 打旧前缀 → 404。ApiRoutes 无 email 键(spec 变更,需单独裁定 —— 同 @objectstack/client 的 packages.* 与 datasources.external.* 无法跟随非默认 API base:external 面硬编码 /api/v1,rest 面 discovery 也从不通告 routes.packages #6633 的 datasources 键先例)。
  2. cloud.environments.* 全族 — :1383-1657 约 20 处 `${this.baseUrl}/api/v1/cloud/...` 模板串。无 cloud 路由键。(该面由哪个宿主挂载、是否随 apiPath 移动,未在本单测量;分诊时请勿臆断归属。)
  3. ScopedProjectClient.scope() — :4827 硬编码 `/api/v1/environments/${id}` 前缀,scoped 面的全部 meta / data / batch / packages URL 由它拼出。服务端 scoped 挂载点 = getScopedBasePath(getApiBasePath())(跟随 apiPath)。
  4. 非缺陷,勿「修」:connect() 的 bootstrap 探针(:522 /api/v1/discovery、.well-known/objectstack fallback)是发现机制自身的鸡生蛋条目,convention 正是其存在意义。

后果

与 #6633 同类:非默认 base 部署(apiPath,或程序化 basePath / version)上这些面打错前缀。其中面 1、3 的服务端挂载已经跟随 apiPath,即 #6306 落地前它们就是现活的 404(不是「碰巧能用」)。

方向(留给分诊,不预设)

查重

open issues 已搜 email send hardcode / email/send / ScopedProjectClient / client hardcode route discovery,除 #6633(本单来源)外无同题。相关:#6306(9 条直挂路由移 base,server 侧)、#6633 / PR #6712(同模式的 packages / datasources 面,已实施)。

Activity

  1. os-zhuang commented on Aug 8, 2026

    @os-zhuang
    Contributor

    Triage: pm:queue + domain:cli + target:v17 — following the #6633 precedent exactly (same defect family, same labels).

    本评论来自分诊座位 Routine(#5474 试点),不构成认领。


    Generated by Claude Code

  2. os-project-manager commented on Aug 8, 2026

    @os-project-manager
    CollaboratorAuthor

    维护者裁定(2026-08-08,cli 席存档):面 1 按 #6633 先例加 email 路由键,完整复刻四车道模式。

    email.send 是现活 404(服务端 registerEmailEndpoints 已随 apiPath 移动,client 仍打 /api/v1),不是潜伏项 —— 这是本卡优先于其他两面的理由。

    落地形状与今日已合并的 #6633 / PR #6712 完全同构:spec ApiRoutes 增 email 键 → rest 从已录制挂载投影出通告(不得二次计算)→ client 走 getRoute('email')。#6712 落地的 mounted ⇒ advertised 奇偶钉可直接扩用。

    面 3(ScopedProjectClient.scope() 前缀)不需要新 spec 键,可从 discovery 的 scoping 块或 routes.data 的 base 推导,与面 1 同批做。
    面 2(cloud.environments.* 约 20 处)按本卡正文要求 —— 先测量挂载归属再定方向,不得臆断。

    维护者同时否掉了「不再逐个加键、改用通用推导」的路子:那会把「同一个 base 下」从可观测事实变成隐含假设,与 #6633 刚建立的 mounted ⇒ advertised 原则相反。


    Generated by Claude Code

  3. os-project-manager commented on Aug 8, 2026

    @os-project-manager
    CollaboratorAuthor

    CLAIM — session session_017uFVNMmTxLpmfQYiuKM1Yx, branch claude/issue-6714-client-follows-advertised-base.

    按维护者裁定(comment 5226487193)实施:面 1 复刻 #6633 四车道模式(spec ApiRoutes 增 email 键 → rest 从已录制挂载投影通告 → client 走 getRoute('email'),并扩用 #6712 的 mounted ⇒ advertised 奇偶钉);面 3 从 discovery 推导 scoped 前缀,不加新 spec 键;面 2 先测量挂载归属再决定,不臆断。

    spec 面已在 #6298 席位贴 pre-dispatch 通告(comment 5226487859),开工前会复读该席位评论。


    Generated by Claude Code

  4. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    CONTINUATION — same session session_017uFVNMmTxLpmfQYiuKM1Yx, same branch claude/issue-6714-client-follows-advertised-base. 前一段在配额墙上中断,盘面留在磁盘上(1 个本地提交 + 未提交的重生成产物)。

    接手动作:

    1. 复核认领 —— 本卡 assignee + claim 评论(5226494821)确为本会话,无第三方 claim;
    2. 复读 [PM seat] domain:spec-surface — 🔀 merged into #6017 #6298 spec-surface 席位的 pre-dispatch 通告(comment 5226487859),否决窗口开放 ~11 小时,该席位其后仍有多轮活动(最新 5229061239),无异议 ⇒ spec 半边按声明面继续;
    3. origin/main 已大幅前进(分叉 38 个提交,含 PR feat(spec,metadata-protocol,rest,client): 直挂面 packages / datasources 可发现,SDK 跟随通告的 base(#6633 · 路线 B) #6712 / fix(rest): the direct-mount routes read the ONE API base, so apiPath moves all 92 (#6306) #6822)——先合并 main,前一段的一切测量按作废处理,所有前提、四车道形状、逆向验证在合并后的树上重测重跑;
    4. 生成产物(authorable-surface/api.json、references/api/discovery.mdx)按 AGENTS.md §11 从合并后的源重生成,不做文本合并(feat(spec,metadata-protocol,rest,client): 直挂面 packages / datasources 可发现,SDK 跟随通告的 base(#6633 · 路线 B) #6712 在这里踩过坑)。

    Generated by Claude Code

  5. removed their assignment
    on Aug 9, 2026
  6. os-project-manager commented on Aug 9, 2026

    @os-project-manager
    CollaboratorAuthor

    PR opened (draft): #6887 — session session_017uFVNMmTxLpmfQYiuKM1Yx, branch claude/issue-6714-client-follows-advertised-base。

    三面结算:

    • 面 1(现活 404):已实测证实,非断言。apiPath: '/backend/api/v9' 启动录制挂载表 —— email 面只有 POST /backend/api/v9/email/send 一条,旧 client 打的 POST /api/v1/email/send 在表中不存在。已按裁定完整复刻 @objectstack/client 的 packages.* 与 datasources.external.* 无法跟随非默认 API base:external 面硬编码 /api/v1,rest 面 discovery 也从不通告 routes.packages #6633 四车道(spec email 键 → rest 从已录制挂载投影通告 → client 走 getRoute('email') → 奇偶钉扩展覆盖)。
    • 面 3:同批做,未加新 spec 键。实测 discovery 的 scoping 块只有 enabled/resolution/scoped/environmentId 四键、全是姿态无路径,不可推导 ⇒ 选 routes.data 的 base(rest 通告为 {realBase}{dataPrefix})。评审中发现并修掉一个真边界:scoping.environmentId 来自 req.params?.environmentId,宿主未填 param 时会 scoped: true 但无 id,初版会返回仍带 scope 的 base,scope() 拼出双层 /environments/…/environments/… —— 比原硬编码更糟。现改为三分支(按通告 id 摘 → 按 scoped 摘一段 → 放弃回退惯例),两个分支各有钉子。
    • 面 2:测量后不动。@objectstack/rest 挂载 /cloud/* 零条 —— 依据不是 grep,而是双向 conformance 门禁保证穷尽的 rest-route-ledger.ts,cloud 行数为 0;runtime dispatcher 无 cloud domain(无 handleCloud、无 domains/cloud.ts),并显式把 /cloud 列为他宿主控制面。而 apiPath 是 @objectstack/rest 独有配置。⇒ 该面不随 apiPath 移动,按裁定「不随则不收敛」,原样保留。(objectstack-ai/cloud 本会话无访问权限,其自身挂载 base 未测,已在 PR 中如实标注。)

    逐字节回退验证:两半 client 改动全部退回旧硬编码后,恰好 3 个测试变红,全是 case C,161 个(含全部 case A/B)保持绿。

    逆向验证中两条诚实记录已写进 PR:① 我预测的「client typecheck 会红」未兑现(client 对的是 spec 的 dist 而非 source),已从另一方向重测证明该类型总覆盖是真守卫;② 奇偶钉无法区分「投影」与「从 realBase 重算」—— 它钉的是挂载/通告的分裂,不是投影手法(改成按惯例重算则确实变红)。

    期间 origin/main 前进三次,每次都重新合并、并从合并后的源重生成产物(api.json / discovery.mdx 各恰好 1 行 delta),未做文本合并。CI 未等待。


    Generated by Claude Code

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

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