Closed
Labels
domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:queueReady for the PM dispatch loopReady for the PM dispatch looptarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Description
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 均不跟随:
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键先例)。cloud.environments.*全族 — :1383-1657 约 20 处`${this.baseUrl}/api/v1/cloud/...`模板串。无cloud路由键。(该面由哪个宿主挂载、是否随apiPath移动,未在本单测量;分诊时请勿臆断归属。)ScopedProjectClient.scope()— :4827 硬编码`/api/v1/environments/${id}`前缀,scoped 面的全部meta/data/batch/packagesURL 由它拼出。服务端 scoped 挂载点 =getScopedBasePath(getApiBasePath())(跟随apiPath)。- 非缺陷,勿「修」:
connect()的 bootstrap 探针(:522/api/v1/discovery、.well-known/objectstackfallback)是发现机制自身的鸡生蛋条目,convention 正是其存在意义。
后果
与 #6633 同类:非默认 base 部署(apiPath,或程序化 basePath / version)上这些面打错前缀。其中面 1、3 的服务端挂载已经跟随 apiPath,即 #6306 落地前它们就是现活的 404(不是「碰巧能用」)。
方向(留给分诊,不预设)
- 面 1:
ApiRoutes增email键(spec 裁定)+ rest 通告 + client 走getRoute('email')—— 完整复刻@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633 的四车道模式。 - 面 3:scoped 前缀可从 discovery 的
scoping块或routes.data的 base 推导;改动需 both-copy 纪律(其packages命名空间同改)。 - 面 2:先测量挂载归属再定方向。
查重
open issues 已搜 email send hardcode / email/send / ScopedProjectClient / client hardcode route discovery,除 #6633(本单来源)外无同题。相关:#6306(9 条直挂路由移 base,server 侧)、#6633 / PR #6712(同模式的 packages / datasources 面,已实施)。
Metadata
Metadata
Assignees
Labels
domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:queueReady for the PM dispatch loopReady for the PM dispatch looptarget:v17Release blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GARelease blocker for v17 — on the board until fixed, dropped as no longer valid, or accepted for GA
Activity
os-zhuang commentedon Aug 8, 2026
Triage:
pm:queue+domain:cli+target:v17— following the #6633 precedent exactly (same defect family, same labels).origin/main@cfeb9a0:packages/client/src/index.ts:1049still builds the email URL from a hardcoded/api/v1/email/sendtemplate;:4827still hardcodes the scoped prefix inScopedProjectClient.scope(); 29 hardcoded/api/v1/cloud/...occurrences confirmed in the same file. All three faces bypassgetRoute()as described.getApiBasePath()server-side, so anyapiPathdeployment already gets live 404s from the stock client. Not a design question; the direction for face 1 replicates the four-lane pattern@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633 just landed (PR feat(spec,metadata-protocol,rest,client): 直挂面packages/datasources可发现,SDK 跟随通告的 base(#6633 · 路线 B) #6712).target:v17per the@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633 precedent — same "client cannot follow a non-default API base" family, ground ① (shipped-surface defect a deployer hits today). If the board judges the family covered by@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633 alone, pull this tag with one comment.getRouteopen issues returns only@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633 (the source card) — clean. Face 2's mount ownership is explicitly unmeasured; the dev should measure before touching it, per the body.ApiRoutesemailkey half is contract surface — if the dev finds it needs more than the mechanical key-add@objectstack/client的packages.*与datasources.external.*无法跟随非默认 API base:external 面硬编码/api/v1,rest 面 discovery 也从不通告routes.packages#6633'sdatasourcesprecedent established, transfer that slice to thedomain:specseat rather than deciding it in-lane.本评论来自分诊座位 Routine(#5474 试点),不构成认领。
Generated by Claude Code
os-project-manager commentedon Aug 8, 2026
维护者裁定(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
os-project-manager commentedon Aug 8, 2026
CLAIM — session
session_017uFVNMmTxLpmfQYiuKM1Yx, branchclaude/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
os-project-manager commentedon Aug 9, 2026
CONTINUATION — same session
session_017uFVNMmTxLpmfQYiuKM1Yx, same branchclaude/issue-6714-client-follows-advertised-base. 前一段在配额墙上中断,盘面留在磁盘上(1 个本地提交 + 未提交的重生成产物)。接手动作:
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, soapiPathmoves all 92 (#6306) #6822)——先合并 main,前一段的一切测量按作废处理,所有前提、四车道形状、逆向验证在合并后的树上重测重跑;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
os-project-manager commentedon Aug 9, 2026
PR opened (draft): #6887 — session
session_017uFVNMmTxLpmfQYiuKM1Yx, branchclaude/issue-6714-client-follows-advertised-base。三面结算:
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 四车道(specemail键 → rest 从已录制挂载投影通告 → client 走getRoute('email')→ 奇偶钉扩展覆盖)。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摘一段 → 放弃回退惯例),两个分支各有钉子。@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
test(client): re-pin #6714 case B — a custom dataPrefix no longer mak…
fix(client): read the CRUD data prefix from discovery instead of rest…