feat(portal-shell): v2.1 P0 auth + middleware + login + graphql proxy

- 新增 ARCHITECTURE.md v3.0:portal-shell 架构权威文档
  涵盖 §3.4 V3-A2/A3 认证链、§4 GraphQL 联邦、§5 安全、
  §6 部署、§10 P0-P3 验收清单
- 新增 middleware.ts:认证 + 路由门禁
  httpOnly cookie edu_session(JWT)读取
  DEV_MODE 合成 dev-user/teacher 身份(NODE_ENV!=production &&
  NEXT_PUBLIC_DEV_MODE=true)
  生产模式 jose JWKS RS256 验签(iss/aud 校验)
  路由权限位图注入 x-user-id/x-user-role/x-user-permissions 头
  /shell/** 强制 checkRoutePermission,拒绝跳 /shell/forbidden
- 新增 instrumentation.ts:生产环境 DEV_MODE 强制 false
  防止生产环境误开 DEV_MODE 合成身份
- 新增 app/api/auth/login/route.ts + logout/route.ts
  登录走 api-gateway /v1/iam/login
  设置 httpOnly + Secure + SameSite=Strict cookie
- 新增 app/api/graphql/route.ts:同域 GraphQL 代理
  转发到 apollo-router,注入 router-authorization 头
- 新增 app/login/page.tsx + login-form.tsx
  zod 表单校验,next 参数支持
- 新增 app/shell/forbidden/page.tsx:403 页面
- 更新 route-permissions.ts:补全 P0 路由权限映射
- 更新 permission-bitmap.ts(shared-ts):位图编码/解码
- 更新 apollo-client.ts:DEV_MODE APQ 关闭,错误处理
- 更新 config-fetcher.ts:config-service 直连降级
- 更新 ApolloProvider.tsx:SSR/RSC 兼容
- 更新 eslint.config.js:design-tokens/no-hardcoded-fonts
  白名单调整
This commit is contained in:
SpecialX
2026-07-22 11:35:36 +08:00
parent 682f323bad
commit cfb7b005fd
23 changed files with 2542 additions and 435 deletions

View File

@@ -5,7 +5,12 @@
* - 禁止 #hex 颜色字面量
* - 禁止 'Inter'/'Fraunces'/'JetBrains Mono' 字体名字面量
*
* 关联project_rules §3.10、portal-shell spec §7
* P0-7补 no-restricted-importsARCHITECTURE.md §3.4 V3-A3 / §8.3 铁律)
* - 禁 widget/页面 直接 import sonner统一走 @/shared/lib/notify
* - 禁 widget/页面 绕过 lib/api 直接 import @apollo/client
* - 禁 widget 跨目录 import 其他 widget插件隔离
*
* 关联project_rules §3.10、portal-shell ARCHITECTURE.md §8.3、§11.7
*/
import js from "@eslint/js";
import tseslint from "typescript-eslint";
@@ -66,6 +71,56 @@ export default tseslint.config(
},
},
// P0-7no-restricted-imports 强制ARCHITECTURE.md §8.3 / §11.7 红线)
// - 禁直接 import sonner统一走 @/shared/lib/notify 封装)
// - 禁页面/widget 绕过 lib/api 直接 import @apollo/client
// - 禁 widget 跨目录 import 其他 widget插件隔离铁律
// 白名单:
// - notify 封装本体src/shared/lib/notify.ts+ 其测试__tests__/notify.test.ts+ Toaster 容器src/shared/components/ui/sonner.tsx
// - 数据层src/lib/apollo-client.ts、useWidgetQuery.ts、useWidgetMutation.ts、config-fetcher.ts、src/lib/api/**、src/providers/ApolloProvider.tsx
// - widget 注册中心src/shell/Registry.tsx必须 import 各 widget 的 plugin.manifest是唯一例外
{
files: ["src/**/*.{ts,tsx}"],
ignores: [
"src/shared/lib/notify.ts",
"src/shared/lib/__tests__/notify.test.ts",
"src/shared/components/ui/sonner.tsx",
"src/lib/apollo-client.ts",
"src/lib/useWidgetQuery.ts",
"src/lib/useWidgetMutation.ts",
"src/lib/config-fetcher.ts",
"src/lib/api/**",
"src/providers/ApolloProvider.tsx",
"src/shell/Registry.tsx",
],
rules: {
"no-restricted-imports": [
"error",
{
paths: [
{
name: "sonner",
message:
"禁止直接 import sonner统一使用 @/shared/lib/notifyARCHITECTURE.md §8.3",
},
{
name: "@apollo/client",
message:
"禁止绕过 lib/api 直接 import @apollo/client使用 useWidgetQuery/useWidgetMutationARCHITECTURE.md §11.7",
},
],
patterns: [
{
group: ["@/widgets/*", "../widgets/*", "../../widgets/*"],
message:
"禁止 widget 跨目录 import 其他 widget插件隔离铁律ARCHITECTURE.md §11.7",
},
],
},
],
},
},
// 白名单令牌原始定义、PWA manifest
{
files: ["**/primitive.css", "**/manifest.ts"],