📚 离职知识库

08 · 可复用资产清单(别从零造轮子)

本机 ~/personal 下已有 40+ 个项目。本节列出「接棒 Baton」可以直接拷贝的现成资产。 重要原则:能 cp 源文件就不要从文档里复制代码。 文档里的代码可能被转义损坏,源文件不会。


#1. 统一密码门(四个文件,直接 cp)

范式来源:~/personal/english-daily。这是当前最新的 Next 16 proxy.ts 写法。 ⛔ 不要抄 media-studio / media-studio-ossmiddleware.ts,那是过时范式。

# 在 baton 项目根目录执行(假设用非 src 结构,与 english-daily 一致)
cp ~/personal/english-daily/lib/hub-auth.ts        ./lib/hub-auth.ts
cp ~/personal/english-daily/proxy.ts               ./proxy.ts
cp ~/personal/english-daily/app/login/page.tsx     ./app/login/page.tsx
cp ~/personal/english-daily/app/api/login/route.ts ./app/api/login/route.ts

四个文件各自的作用

文件 作用
lib/hub-auth.ts HMAC-SHA256 签发/校验会话令牌,纯 Web Crypto,Edge 和 Node 都能跑。导出 AUTH_COOKIE / COOKIE_DOMAIN / signToken / verifyToken / checkPassword
proxy.ts 放在项目根目录(与 app/ 同级)。导出 export async function proxy(req) + config.matcher。未配置 env 时全部拦下(绝不裸奔)
app/login/page.tsx 登录页,纯内联样式零依赖,可原样用。但今晚要按浅色干净风重做样式,逻辑照抄
app/api/login/route.ts POST 校验密码签发 Cookie,DELETE 登出。密码错误时 sleep 600ms 拖慢暴力破解

必须改的一处proxy.tsmatcher 排除列表。Baton 会新增 API 路由,凡是不需要登录也要能访问的路径必须加进排除列表。今晚至少要加:

/((?!login|api/login|api/health|_next/static|_next/image|favicon.ico).*)

其余 /api/* 全部要走门(因为里面是员工资料)。

环境变量(值从 (密码门凭据文件,路径从略) 取,⛔ 不要写进代码或 git)

  • HUB_SITE_PASSWORD
  • HUB_AUTH_SECRET
  • HUB_COOKIE_DOMAIN(可省,默认 .saveme505.help

⚠️ 本地开发的坑(实测):english-daily 的本地 .env.local没有这三个变量——它们只配在 Vercel。结果是本地 npm run dev 时 proxy 判定"未配置"→ 全站拦截且 /api/login 返 503。 今晚的做法:在 .env.local 里补齐这两个值(本地文件已 gitignore,安全),这样本地 dev 和 Playwright E2E 都能跑通登录流程。E2E 必须能跑通登录,否则所有页面测试都进不去。


#2. 技术栈版本基线(照抄,别用更新的)

理由:这套组合是本机多个项目验证过能正常 build 并部署到 Vercel 的唯一组合。用更新版本 = 今晚重新踩雷 = 没时间。

"next": "16.2.10",
"react": "19.2.4",
"react-dom": "19.2.4",
"tailwindcss": "^4",
"@tailwindcss/postcss": "^4",
"shadcn": "^4.13.1",
"@supabase/supabase-js": "^2.110.7"
  • shadcn CLI 是新版 shadcn(⛔ 不是老的 shadcn-ui
  • components.json 直接 cp ~/personal/english-daily/components.json ./components.json,其中: "style": "base-nova""baseColor": "neutral""iconLibrary": "lucide""cssVariables": true
  • 如果 npx shadcn@latest init 出来的配置和上面不一致,以上面为准

#3. 视觉基线:浅色干净风

⚠️ zhixingyuan 项目本机磁盘上已经不存在(find 全盘无命中,只剩 Claude Code 会话索引)。不要浪费时间找它。

用这两个做视觉底子:

#3.1 shadcn 中性浅色主题(主选)

cp ~/personal/english-daily/app/globals.css ./app/globals.css   # 然后按 Baton 需要改 accent

:root 是纯灰阶 oklch(chroma≈0):--background: oklch(1 0 0)--foreground: oklch(0.145 0 0)--border: oklch(0.922 0 0)--radius: 0.625rem。这是"最不会出错"的浅色起点,但没有品牌色

#3.2 Baton 的品牌色(在上面基础上叠一层)

接棒 = 交接 = 传递。用靛蓝 indigo 作单一强调色,其余全灰阶。克制,不要第二个强调色。

:root {
  --bg-page: #f6f7f9;      /* 页面底色,浅灰,不要纯白 */
  --card: #ffffff;          /* 卡片纯白,靠阴影和 1px 边框分层 */
  --accent: #6366f1;        /* indigo-500,只用在主按钮、选中态、进度条 */
  --line: #e5e7eb;
}

(这套取自 ~/personal/daily-digest/app/globals.css,全文 31 行,是本机视觉最干净的一份,可以直接读来参考。)

#3.3 视觉硬规则(明早人类会用这几条挑毛病)

  • 页面底 #f6f7f9,卡片纯白,不要纯白底 + 纯白卡片(会糊成一片)
  • 圆角统一 --radius: 0.625rem(10px),不要有的 4px 有的 16px
  • 只有一个强调色。状态色只用 shadcn 默认的 destructive
  • 中文字体栈必须有 "PingFang SC",否则 Mac 上中文会难看
  • 表格行高不小于 44px,留白宁多勿少
  • ⛔ 不要深色科技风、霓虹、玻璃拟态、渐变大背景

#4. Supabase 接入(Leo-hub)

项目 id<ID>(Leo-hub)

#4.1 client 范式(直接抄 english-daily)

cp ~/personal/english-daily/lib/supabase.ts ./lib/supabase-base.ts   # 作为 db.ts 的底层

它是单例 client + publishable key + auth: { persistSession: false }

#4.2 ⭐ 关键安全事实:Leo-hub 现有的 RLS 是全开的

实测 pg_policiesen_* 系列表的策略全是 for all to public using (true) with check (true)也就是说:Leo-hub 上的 RLS 不提供任何隔离能力,它只是"开了 RLS 但放行一切"。

对 Baton 的直接影响(这是今晚最重要的架构结论之一):

员工之间的数据隔离,必须 100% 在应用层做,RLS 一点都指望不上。

所以:

  1. 所有 DB 访问必须走 src/lib/db.tsscopedQuery(employeeId) 单一入口,它强制往每个查询注入 employee_id 过滤
  2. 禁止在任何客户端组件里 import { getSupabase },禁止把 supabase client 暴露到浏览器做业务查询
  3. 所有业务查询走 Route Handler / Server Action
  4. 这条要有专门的自动化守卫测试(见 02-TDD规程 的 AC-SEC 系列)

#4.3 建表 SQL 范式

alter table bt_xxx enable row level security;
create policy bt_xxx_all on bt_xxx for all to public using (true) with check (true);

和现有表保持一致(否则用 publishable key 会连读都读不到)。真正的隔离在应用层。 这个取舍要写进 README 的安全边界章节,不要藏着。

#4.4 环境变量命名(统一用这两个,别引入第三种)

  • NEXT_PUBLIC_SUPABASE_URL
  • NEXT_PUBLIC_SUPABASE_KEY

(注:gifmoji 用的是 ..._ANON_KEY,是历史不一致,不要跟。)

不要抄 media-studio 的 DATABASE_URL 直连 + ms_app 角色模式,那是它的特例,且它的 DATABASE_URL 现在还是坏的(占位值)。


#5. 导航站收录(P5 必做)

文件~/personal/projects-hub/src/lib/projects-meta.tsx

改两处

  1. 文件顶部 import { ... } from "lucide-react" 块里,按字母序加一个图标名(建议用 Repeat2ArrowLeftRightHandshake
  2. PROJECT_META 对象里加一条,键名必须等于 Vercel 项目名(不是域名):
baton: {
  icon: Handshake,
  description: "给小公司每人配一个 Agent 管住自己的资料,离职换岗一键把该给的交出去",
  tint: "text-violet-500 bg-violet-500/10 dark:text-violet-400 dark:bg-violet-400/10",
  group: "backend",
},

改完 projects-hub 要单独 commit + push(它自己会自动部署)。 不补的话会显示灰色地球 + "还没配图标和简介"。


#6. LLM / Embedding(云雾中转)

配置来源:~/Desktop/配置信息/云雾API-中转/README.md

YUNWU_API_BASE=https://yunwu.ai/v1     # OpenAI 兼容
YUNWU_API_KEY=<从现有项目的 Vercel env 或本地 .env.local 取,⛔ 不写进 git>
LLM_MODEL=deepseek-v4-flash            # 对话/抽取用,便宜快、结构化稳定
EMBEDDING_MODEL=text-embedding-3-small # 1536 维

Node 侧两种调法都验证过:

  • openai SDK:new OpenAI({ apiKey, baseURL: "https://yunwu.ai/v1" })
  • Vercel AI SDK:createOpenAICompatible({ name:"yunwu", apiKey, baseURL, supportsStructuredOutputs: true }) ⚠️ supportsStructuredOutputs: true 必开,否则 generateObject 不下发 response_format,记忆条目抽取会拿到非结构化文本。

⚠️ 云雾现在是一个项目一把 key。今晚不要去后台建新 key(需要人工登录)。做法:

  1. 从某个现有项目的本地 .env.local 里取一把能用的(只在本地 .env.local 用,不进 git
  2. blockers.md 写一条:「待人类在云雾后台建 baton 专属 key,并在 Vercel 环境变量里替换」

#7. 测试基线:

实测:~/personal 下所有项目的 package.json,vitest / playwright / @testing-library 命中数 = 0

结论:今晚的测试体系是从零搭的,没有现成配置可抄。 完整配置见 02-TDD规程与反作弊.md,那里给了可直接落地的 vitest.config.tsplaywright.config.ts

这也意味着:Baton 会是本机第一个有测试的项目。这本身就是明早一个漂亮的交付点,值得在一页纸总结里单独说。


#8. 部署流水线(⛔ 铁律,不许变通)

来自用户全局 CLAUDE.md 的最高准则:

改本地代码 → git commit(身份 Leo / 中文注释)→ git push origin main
   → Vercel GitHub 集成检测到 push → 自动部署 → 部署成功后发邮件汇报
  • ⛔ 禁止 vercel deploy / vercel --prod / 任何 CLI 直接部署
  • ✅ 唯一保留的 CLI 用途:域名绑定 vercel domains add / vercel alias
  • 新项目起步就要 vercel link + vercel git connect,确保 GitHub 仓库和 Vercel 项目连上、生产分支自动部署已开
  • ⚠️ 跑任何 vercel 写类命令前先 cp .env.local .env.local.bak
  • ⚠️ Vercel 上标为 sensitive 的变量写进去后三条路都读不回明文 → 凡是自己生成的密钥,先在本地留一份再写上去

#9. 关键路径速查表

要什么 去哪
密码门四文件 ~/personal/english-daily/{lib/hub-auth.ts,proxy.ts,app/login/page.tsx,app/api/login/route.ts}
shadcn 配置 ~/personal/english-daily/components.json
浅色主题 token ~/personal/english-daily/app/globals.css~/personal/daily-digest/app/globals.css
Supabase client ~/personal/english-daily/lib/supabase.ts
导航站元数据 ~/personal/projects-hub/src/lib/projects-meta.tsx
密码门密码/密钥 (密码门凭据文件,路径从略)
云雾 API 配置 ~/Desktop/配置信息/云雾API-中转/README.md
Resend key ~/Desktop/配置信息/resend-api-key.txt
上一版方案(含 VPS 现状调研) ~/Desktop/OpenFDE-Demo-接棒方案-20260730.md
本次方案原文 ~/Desktop/接棒-Agent交接方案-20260730.md

来源:沉淀/03-项目方案与交接/接棒-通宵施工包-20260731/08-可复用资产清单.md(整理于 2026-08-18)