一个带版本、与框架无关的软件包家族,Webanion 的每个前端和后端都以它为起点,服务端有一层 NestJS,客户端有 React、Vue 和 Expo 绑定:支持通行密钥和单点登录的身份认证、功能开关、审计日志、多租户数据、加密、文件、文档、消息、实时与离线、webhook、worker 和一套 UI 组件库。每个包都有自己的私有仓库和独立发布,从工作室的私有 npm registry 安装,工作室的控制台会显示哪个消费方在哪个版本上落后。
完整故事
为什么把鉴权、审计和功能开关一次做好、纳入版本管理并在各处复用,会让一家工作室的客户受益更多。
每个后端都曾从零开始
客户付费开发的每个后端,在做任何客户真正关心的事情之前,都需要同样的基础:登录、会话、权限、配置、文件存储、邮件、PDF、后台任务和审计日志。如果每个项目都重新编写,这些部分要耗费数周时间,每个项目各不相同,还各自带着自己的 bug。
gm-libs 就是答案:把这些底层基础设施从早已验证过它们的项目中提取出来,加固成带有版本、文档和变更日志的包,并在工作室构建的各个前端和后端中复用。
登录与权限,一次解决
鉴权包提供 Argon2id 密码哈希、短时效的访问令牌配合轮换的刷新会话,以及基于 OpenFGA 的关系型权限,因此像“分支机构员工只能看到自己所在的分支机构”这样的规则,是一个声明式的模型,而不是散落在代码各处的检查。它还支持带账号关联的社交登录和 OIDC 登录、无密码登录、多因素认证、通行密钥和单点登录。新后端只需导入一个模块,就能获得全部这些能力。
对客户而言,这意味着安全机制已经在一个金融平台上经过加固和测试,而不是在截止日期的压力下重新发明。



安全地开启功能
功能开关包决定为每个租户、分支机构、角色或个人展示什么、运行什么,而且从不阻塞请求:开关从内存中读取,如果无法连接开关服务器,每个开关都会回退到安全的默认值,除非团队另有选择,否则默认关闭。它与授权配合使用,而不是取代授权,因此只有开关和权限都同意时,功能才会出现。
客户可以先把一个功能发布给一个分支机构或一个人,观察效果,再无需重新部署就扩大范围,Al-Insaf 团队就是这样管理自己的功能的。



从不拖慢任何人的审计日志
审计包会在每一次写操作时记录谁在何时、何地做了什么,按类别和严重程度分类,并把每条记录移出请求路径,再分批写入。审计存储变慢或出错时会被记录到日志中,但绝不会阻塞正在使用系统的人,正因如此,才能放心地审计一切重要操作。


每个包,只做一件事
除了 auth、flags 和 audit,这个家族还覆盖了前端和后端所需的其余部分,每个包只做一件事,接入方式也完全一致:底层是与框架无关的代码,服务端有一层 NestJS,包延伸到客户端的地方则提供 React、Vue 和 Expo 绑定。
- 基础与数据:core(错误、请求上下文、会隐去凭据的日志器、缺少密钥时立即报错的类型化配置、金额、分页、限流、幂等、健康检查)和 db(多租户 Postgres,每个租户独立一个数据库,附带迁移和模型)。
- 身份与访问:auth、flags、audit,以及用于字段和密钥信封加密、密钥可轮换的 crypto。
- 文件、文档与消息:用于存储和签名上传的 media、pdf,用于流式 CSV 和 XLSX 导出及带校验导入的 tabular,用于邮件、短信、推送和团队聊天的 notifications,以及用于实时对话的 chat。
- 实时与离线:用于经过认证的按频道事件的 realtime,带有适用于 React、Vue 和 Expo 的自动重连客户端;以及 offline,为每个用户提供缓存和只发送一次的写入队列,可用于浏览器和 Expo 应用。
- 集成与运行时:按 Standard Webhooks 规范签名的 webhooks,用于 Temporal 的 worker,提供加固的无头浏览器和拒绝内部地址的出站请求的 web,用于流式加密数据库备份的 datavault,以及用于构建 MCP 服务器的 mcp。
- 界面:ui,从设计令牌到 React、Vue、Next.js 和 Expo 组件。
此外,devkit 是每个库在发布前都要运行的检查。每个包都有自己的私有仓库和独立的发布版本,因此只有当客户的团队采用新版本时,客户的系统才会改变。



一次修复,惠及所有系统
由于工作室的前端和后端共享同样的基础,一次安全修复或改进只需提升版本号,就能到达每一个前端和后端,并附有说明改了什么、为什么改的变更日志。各次发布都严格遵守语义化版本,因此不会因为另一个客户需要新功能,就让某个客户的系统出问题,而控制台当天就能显示哪个消费方还没有采用新版本。
对客户来说,结果是更快的交付、更少的意外,以及一个由已在别处经过生产环境检验的组件构建的产品,其中包括Al-Insaf 的故事中那个达到账本级严谨度的金融平台。
每个包,已发布且受到监看
每个包都从工作室的私有 npm registry 安装,工作室的控制台也像消费方一样读取这个 registry。它会 ping registry,读取每个包的每个版本及其发布时间、打包大小和完整性,并读取各消费方默认分支上的清单文件,判断每个依赖是否解析到最新发布。一个库家族的价值,取决于能否证明使用它的每个系统都是最新的,而这份证明就在这里。
在截图当天,也就是 2026 年 9 月 30 日,视图显示 registry 运行正常、每个包都已发布、registry 本身有一份最近的备份,并且除工作室自己的工具之外,每个消费方都在使用最新发布,那些工具仍停留在 core 和 pdf 的较早版本上。



从 GitHub Release 到 npm install,经由工作室的 registry
给某个库打上标签,就会在 GitHub 上运行它的发布流程,并在 Release 中附上一个打包文件。集群内的同步任务每五分钟发布一次这个完全相同的文件,因此 Release 和 registry 中保存的是相同的字节,每晚还会再核对一次。读取需要登录,公开域名拒绝一切写入。之所以没有采用 GitHub Packages,是因为这些库和它们的消费方位于不同的组织中。


你可能也喜欢

博客是来自生产一线的笔记:架构决策、经受住真实用户考验的 AI 系统、能自己挣回成本的基础设施。写于工作之中,而不是隔岸观火。



