父 Story:#7 (M1 入口级交付 · webui)。WP4b-UI。Blocked by #9 , #10 (导航骨架 + SDK 会话租户)。红线:示例数据脱敏占位。
目标
顶栏租户切换组件占位 + 调 control-plane GET /v1/me/tenants(D1:列 org membership;M1 先 1 个,结构按多租户)。
🔗 契约锚定(必须 · tolerant reader)
端点与响应 schema 钉到主仓契约 contracts/openapi/control-plane-v1.yaml v1.1.0 的 GET /v1/me/tenants(当前用户 membership 数组),契约已落地 = hashmatrix#18(CLOSED) 。msw mock 响应须按该 schema 成形(非自拟字段),与 control-plane 同缝另一端锚同一 schema,避免 I4 集成对不上。packages/sdk 落地后应优先用其生成类型。
范围(文件清单)
apps/console/src/api/(新建):control-plane 客户端 GET /v1/me/tenants,仿 apps/admin/src/api/controlPlane.ts 模式(经共享 @hashmatrix/sdk 的 axios,baseURL 由运行期 config.js 提供)。
apps/console/src/layout/AppLayout.tsx:actionsRender 加租户切换组件。
apps/console/src/mocks/*:/v1/me/tenants msw mock(按上方契约 schema 成形;1 租户,结构多租户,脱敏占位 tenant-demo)。
切换动作触发 WP4b-SDK · 会话承载租户声明 + X-Tenant-Id 派生 (D1/D2) #10 的会话租户更新(D2:重换 token 占位)。
起点(精确路径 · 真/stub/缺失)
预估 LOC
~120
测试 / DoD
story:顶栏出现切换组件;/me/tenants(mock)调通;选择走 D2 语义占位。
lint / vitest / storybook-playwright / build 绿。
依赖
验收
目标
顶栏租户切换组件占位 + 调 control-plane
GET /v1/me/tenants(D1:列 org membership;M1 先 1 个,结构按多租户)。🔗 契约锚定(必须 · tolerant reader)
端点与响应 schema 钉到主仓契约
contracts/openapi/control-plane-v1.yamlv1.1.0 的GET /v1/me/tenants(当前用户 membership 数组),契约已落地 = hashmatrix#18(CLOSED)。msw mock 响应须按该 schema 成形(非自拟字段),与 control-plane 同缝另一端锚同一 schema,避免 I4 集成对不上。packages/sdk落地后应优先用其生成类型。范围(文件清单)
apps/console/src/api/(新建):control-plane 客户端GET /v1/me/tenants,仿apps/admin/src/api/controlPlane.ts模式(经共享@hashmatrix/sdk的 axios,baseURL 由运行期config.js提供)。apps/console/src/layout/AppLayout.tsx:actionsRender加租户切换组件。apps/console/src/mocks/*:/v1/me/tenantsmsw mock(按上方契约 schema 成形;1 租户,结构多租户,脱敏占位tenant-demo)。起点(精确路径 · 真/stub/缺失)
AppLayoutactionsRender已有操作区(语言/明暗/换肤/角色)可挂入。apps/admin/src/api/controlPlane.ts提供 control-plane 客户端模板。预估 LOC
~120
测试 / DoD
/me/tenants(mock)调通;选择走 D2 语义占位。依赖
验收
GET /v1/me/tenants调通(mock 按 control-plane-v1 v1.1.0 schema,1 租户)。X-Tenant-Id唯一)。