Gerege Nexus¶
Production · 第 3 层 — 平台底座 ·
仓库:open-gerege-nexus · nexus.gerege.mn
服务、运营与系统的统一平台。 一个把公共部门与私营机构的服务、运营、系统和数据 汇聚到同一底座上的模块化平台。开源,Apache 2.0 许可。
Nexus 意为连接点 —— 组织、服务、工作流、系统、用户与数据在此汇合。平台本身 不针对某一个行业:真正定义某家机构需求的,是运行在它之上的模块。
生态系统模型正在改变
Gerege Nexus 是 Template Platform 的继任底座。旧模型是 「一个模板 → 每个产品一个分叉」;新模型是「一个 upstream(Nexus)→ 每个品牌 一个分叉,通过从 upstream 合并来更新」。这一转变正在进行中 —— 既有平台仍在 production 运行。详见分层架构。
最本质的差别:应用即模块¶
在旧模型里,新产品意味着新仓库、新部署、新数据库。在 Nexus 上,新产品通常是 一个新模块 —— 编译进同一个二进制、由每个租户自行启用或停用的应用。
| Template 模型(旧) | Nexus 模型(新) | |
|---|---|---|
| 新产品 | 分叉模板 | 编写模块并加入目录 |
| 分发 | 每个仓库一套部署 | 按租户,通过应用商店 |
| 代码共享 | open-gerege-core + @gerege/ui-core 包 |
单一 upstream;下游分叉从中合并 |
| 模块间调用 | HTTP(仓库分离时) | 进程内 Go 调用 |
| 启用 / 停用 | 需要部署 | 管理员在 app_installations 中决定 |
模块化单体¶
业务模块实现 Go 的 Module 契约,并编译进同一个二进制。某个租户启用了哪些
应用,由 PostgreSQL 中的 app_installations 表动态决定。
- 没有额外的网络跳转 —— 模块之间在进程内调用,因此既不会产生微服务延迟,也不会 带来编排复杂度。
- DAG 依赖解析 —— 模块依赖在有向无环图上递归求解,带环检测与 semver 校验。
- 目录同步 ——
catalog/apps.json是唯一真实来源;apps表在每次启动时据此刷新。 新增应用无需手写 SQL。 - 应用门禁 —— 未安装应用的路由一律返回
403 Forbidden。
为什么不用微服务?
模块边界由 Go 接口保障,而不是由网络保障。边界的约束力得以保留,同时避开了 网络延迟、分布式事务,以及多套部署的运维成本。
随平台提供的模块¶
| 模块 | ID | 路径 | 用途 |
|---|---|---|---|
| Contacts | io.example.contacts |
/contacts |
往来单位名录,支持 ХУР / XYP 自动填充 |
| Products | io.example.products |
/products |
商品、定价、租户范围内的 SKU |
| Inventory | io.example.inventory |
/inventory |
仓库、库存水位、只追加的出入库流水 |
| Billing & e-Barimt | io.example.billing |
/billing |
发票、10% 增值税、e-Barimt 票据 |
| Digital Documents | io.example.documents |
/documents |
电子文档与审批流 |
| Developer Portal | io.example.developer_portal |
/developer/apps |
OAuth2 客户端应用注册 |
| PDF 电子签名 | io.example.esign |
/esign |
通过 eID Mongolia(PIN2)签署具法律效力的签名 |
| 政务服务 | io.example.gov_services |
/gov |
可配置的服务流程、层级与 SLA |
可配置的政务服务流程¶
gov_services 模块把同一套代码变成一种服务交付能力:每个租户、以及租户内的
每一项服务,都可以各自配置。在三种模式之间切换,无需改动任何代码:
| 模式 | 含义 |
|---|---|
LOCAL |
受理单位自行办结 |
DELEGATE |
转交下级单位,上级单位监督并核验 |
HYBRID |
由路由规则按每一笔请求决定采用哪一种 |
核心原则 —— 代码决定什么是可能的,配置决定什么是可选的。 规范的状态迁移表位于 代码中;已发布的版本只能收窄它,永远无法拓宽。因此配置错误的租户也无法进入一个 不可能的状态。
其他保证:
- 状态由服务端计算 —— 客户端发送的是动作,绝不是状态。
- 下级单位完成工作并不会关闭请求 —— 当某一步要求核验时,完成后进入
AWAITING_VERIFICATION。 - 逾期是推导出来的(
due_at < now()),绝不覆写业务状态。 - 租户与单位的隔离写在库表结构里 —— 每个外键都是包含
tenant_id的复合外键, 即使应用代码有缺陷,一行记录也无法指向另一个租户。 - 幂等接入 —— 外部请求以
(tenant_id, source_system, external_request_id)标识; 完全相同的重试返回"created": false,而载荷实质不同的重放会被409拒绝。 - 对外通知走 outbox —— 远端 endpoint 永远无法回滚或卡住一次流程迁移。
电子签名 —— eID Mongolia(PIN2)¶
esign 模块以依赖方身份接入 eID Mongolia 的合格远程签名:
- 先对 PDF 取哈希 → eID 把该摘要推送到公民手机上,
- 公民用 PIN2 批准,
- eID 自己的 doc-signer 将 PKCS#7 连同 OCSP 与 CRL 数据一并嵌入,组装出带 PAdES 签名的 PDF。
签名私钥从不接触平台。 证书级别默认为 QUALIFIED —— 若接受 ADVANCED,平台
产出的每一份文档都会被悄悄降级。
以机构名义签署
代表权是直接从国家登记库实时读取的,而不是从证书读取 —— 因为昨天辞职的 负责人,今天仍然持有昨天那张证书。
此外还包括:签名日志(筛选、分页、CSV 导出)、批量签署、带 A4 预览的印章定位、HSM 连接与签名策略。租户可以强制要求合格 eID 签名并彻底关闭 HSM 通道 —— 对直接调用 API 的调用方同样生效。
认证与政务集成¶
- 自带 OAuth2 / OIDC 提供方 ——
/.well-known/openid-configuration、/oauth2/token、/oauth2/introspect、/oauth2/revoke,支持authorization_code、client_credentials与refresh_token。 - eID 与 ДАН / DAN —— 四条官方通道:PKI 数字签名、Mobile OTP、 银行 SSO、人脸生物识别。
- ХУР / XYP —— 公民户籍登记(
WS100101)与法人核验(WS100201)。 - 会话令牌不透明,256 位,数据库中只保存 SHA-256 摘要。退出登录会真正吊销它们。
Mock 模式在 production 下不会运行
E-ID / ДАН / ХУР 的 mock 模式仅供开发使用。当 ENVIRONMENT=production 时会自动
关闭,因此无法用伪造的公民数据登录。
AI 与韧性¶
AI —— 基于 Gemini、扎根于租户数据库真实状态的助手(/api/v1/ai/chat、/stt、
/tts、/translate),提示词与知识库由管理员维护,另有库存需求预测。
云原生韧性(受 go-zero 启发):
| 组件 | 作用 |
|---|---|
| Adaptive circuit breaker | Google SRE 风格的滑动窗口失败率熔断 |
| Adaptive load shedding | 并发超限时返回 503 + Retry-After |
| Singleflight coalescing | 合并重复查询,防止缓存击穿 |
| Exponential backoff retry | 对瞬时故障做指数退避重试 |
语言政策¶
蒙古语加上联合国六种官方语言 = 共七种。 蒙古语是源语言。文档七种齐备,但 软件本体交付蒙古语与英语,其余五种在设置 → 外观中开启。这与本站的 i18n 政策同出一辙。
由它分叉出的品牌¶
Nexus 是 upstream;每个品牌从它分叉,并通过合并保持更新。
| 品牌 | 仓库 | 域名 | 差异所在 |
|---|---|---|---|
| Gerege Nexus | open-gerege-nexus |
nexus.gerege.mn |
Upstream,参考部署 |
| Gerege SSO | sso-gerege-nexus |
— | 聚焦登录、权限与访问层的分叉 |
| Eduge.mn | eduge-mn-nexus |
eduge.mn |
教育行业品牌;带有无法从 GHCR 拉取时在主机构建的 overlay |
两个都叫 Gerege SSO
sso-gerege-nexus 是建立在 Nexus 上的新分叉;production 上的
sso.gerege.mn 仍在运行原先的 sso-gerege-mn 代码。切勿混淆 ——
在转变完成之前,以 Gerege SSO 页面所述行为为准。
部署¶
向 main 推送会触发 GitHub Actions:构建并推送 backend 与
frontend 镜像到 GHCR → 把 docker-compose.prod.yml 复制到服务器 → 拉取镜像 →
在迁移全部完成之后才切换 API 与 frontend → 检查 /health 与 /ready。部署只在
CI 确实通过之后才开始。
服务器上除 Docker 之外什么都不需要 —— 没有源码,没有 Go,也没有 Node。
PUBLIC_ORIGIN 一次决定三件事
CORS、OIDC issuer 与 eID 回调都由同一个变量推导而来。改动它会让 DNS、TLS 证书 以及每一个依赖 issuer 的客户端一起迁移。更换域名时请使用 认证与授权页上的检查清单。
技术栈¶
| 层 | 选型 |
|---|---|
| Backend | Go 1.25 · chi 路由 · pgx(不用 ORM,手写 SQL) |
| Frontend | Next.js 15 App Router |
| 数据库 | PostgreSQL 16 —— 共享 schema,按 tenant_id 隔离 |
| 迁移 | goose(backend/db/migrations/);禁止运行期 DDL |
| 可观测性 | Prometheus(/metrics)· OpenTelemetry |
| 容器 | Docker Compose · GHCR |
生态系统层面的全貌见技术栈。
详细文档¶
实现层面的文档位于仓库内,共七种语言:
| 文档 | 内容 |
|---|---|
README.md |
平台概览(7 种语言) |
docs/ARCHITECTURE_SPECIFICATION.md |
分层与架构决策(MN/EN) |
docs/MODULE_AUTHORING_GUIDE.md |
如何编写新的应用模块 |
docs/GOV_SERVICES_WORKFLOW.md |
政务服务流程的完整模型 |
docs/DOCUMENTS_SIGNING.md |
签署仪式及其契约 |
docs/TRANSLATION_GUIDE.md |
七语翻译指南 |
CHANGELOG.md |
各版本变更 |