配置与环境
# 配置与环境
后端从 fago/fago-server/configs/config.<环境>.yaml 读取配置。APP_ENV 选择 development、test 或 production,默认 development。优先级是环境变量、所选环境文件、内置默认值。不同环境的文件不会叠在一起,也不支持热重载。启动时生成只读快照。
开发脚本从当前目录向上寻找 configs/ 或 fago/fago-server/configs/。部署时显式指定文件:
export APP_ENV=production
export APP_CONFIG_FILE=/etc/fago/config.production.yaml
export APP_PUBLIC_ORIGIN=https://admin.example.com
export APP_API_ENCRYPTION_KEY_ID=release-key
export APP_API_ENCRYPTION_PRIVATE_KEY_FILE=/etc/fago/api-private.pem
数据库连接串、Redis 地址和口令通过环境变量注入,不写入仓库。显式指定的文件缺失、未知字段、重复字段或非法值都会拒绝启动。${变量名} 在 YAML 解析之后展开。私钥相对路径以配置文件所在目录为基准。
| 项 | 开发 / 测试 | 生产 |
|---|---|---|
| 请求内容加密 | 默认关闭 | 强制开启,不能用环境变量关掉 |
| Cookie | development-http,仅 loopback | 推荐 HTTPS 与精确 Origin;HTTP 时启动 WARN,按 Origin 选用 __Secure- 或 dev_ 刷新 Cookie |
| 加密私钥 | 手动开启加密时按 suite 提供 RSA PEM 或 SM2 PKCS#8 | API 启动必填,按 suite 提供 RSA PEM 或 SM2 PKCS#8,权限不宽于 0600 |
内容加密套件缺省是 rsa-aes。YAML 键为 api_encryption.suite,环境变量 APP_API_ENCRYPTION_SUITE 覆盖 YAML。sm2-sm4 使用 SM2 PKCS#8 PEM。切换套件必须更换 PEM,已有密钥文件不会被改写成另一套件。SM4 密钥是 16 字节。SM2 与 SM4 的安全强度按 128 位计。TLCP、口令 SM3 和商用密码产品认证未实现;本页不表示二级等保或商密认证已通过。
私钥不放进 YAML、前端或 Git。当前按新的 key id 切换,客户端刷新页面后拿新公钥。多把旧私钥并存的无缝轮换还没有实现。
字段表见 fago/fago-server/configs/README.md。协议细节见 配置与数据安全。
# 数据库构建与运行配置
开发入口 scripts/fago.sh 会按 FAGO_DATABASE_BUILD、APP_DATABASE_DRIVER、默认 mysql 的优先级选择驱动。YAML 不参与构建脚本解析:如果数据库类型仅配置在 YAML 中,必须同时设置相同的 FAGO_DATABASE_BUILD。预编译产物的驱动固定,配置不匹配会在连接前返回依赖错误,需换用正确构建版本。
构建与发布目录见 后端启动。APP_DATABASE_DSN 始终是运行时私密配置,不进入构建标签、产物清单或日志。
API 的 http.metrics_address / APP_METRICS_ADDR 默认 127.0.0.1:9091,只接受 loopback,指标使用独立端口。多实例需使用不同本机端口,端口冲突会阻止启动。采集与告警见 发布运维。
# 对象存储
storage.driver 默认 disabled。显式设 APP_STORAGE_DRIVER=s3 后,必须同时配置 APP_STORAGE_ENDPOINT/BUCKET/ACCESS_KEY/SECRET_KEY;region 默认 us-east-1,APP_STORAGE_PATH_STYLE 控制寻址。生产 endpoint 必须 HTTPS;不接受 URL 用户信息、查询或任意路径。凭证仅在启动装配使用,不进入租户参数或日志。API/worker 启动会检查预建桶及从未版本化的前提,失败拒绝启动。
显式设 APP_STORAGE_DRIVER=local 时改为 APP_STORAGE_ROOT,必须是预建绝对目录,不能是相对路径或文件系统根,根目录本身不能是符号链接,且其他用户不能访问。同一受信服务组可以共用该目录,细节见文件手册。这种模式不加载 S3 凭证。API 与 worker 必须指向同一目录;未共享该目录的多副本不支持。完整配置与停机恢复见 文件与对象存储。
# config.development.yaml 片段;环境变量 APP_STORAGE_* 优先于 YAML。
storage:
driver: local
root: /var/fago/object-store
# 消息后端
messaging.driver 默认 event;redis 模式显式提供消息专用地址、凭证及部署前缀,worker 检查 AOF/noeviction/WAITAOF 前提。配置与登录缓存分开,不自动迁移既有消息或降级后端。完整字段、积压指标及保留边界见 可靠消息后端与积压观测。
OIDC 的部署信任档案与外部秘密文件配置见 OIDC提供方与外部绑定。默认空档案,环境覆盖整体替换,不将秘密写入管理表单。
# 正式工作流后台
本节配置cmd/worker中的命令、定时器与实例ready三个循环;显式选择外部动作模板时增加第四类循环。默认关闭,现有通知、定时任务等循环继续按原配置运行。
启用的前置条件是同一业务库已显式升级到当前schema v47(持续池从v42引入),且真实平台管理服务已登记本构建的精确清单。
内置版本fago-form-approval-v1保留原清单,fago-form-approval-v2增加强制持续池授权;
两者都只支持已实现的标量表单、十类候选和基础审批,不接受配置传入指纹或动作。外部目标使用下方独立v6模板。
平台目录与首批业务HTTP已可独立开启,操作见工作流API;审批中心及定义与运行管理页面已接入;浏览器与完整组合验收仍继续,不能仅设开关就宣称已完成工作流上线。
当前环境YAML的最小片段如下。环境变量优先,版本名单整体覆盖,不合并文件中的旧版本;修改后重启进程,不热加载。
workflow:
worker_enabled: true
pool_enabled: false
runtime_versions: [fago-form-approval-v1]
poll_millis: 1000
lease_millis: 30000
retry_millis: 1000
| 配置 | 环境覆盖 | 默认与限制 |
|---|---|---|
catalog_enabled | APP_WORKFLOW_CATALOG_ENABLED | false;独立平台目录,空目录可显式登记,不要求业务池 |
api_enabled | APP_WORKFLOW_API_ENABLED | false;实际API运行面,精确清单/池在监听前就绪,逐请求绑定截止 |
worker_enabled | APP_WORKFLOW_WORKER_ENABLED | false;开启须明确提供版本 |
pool_enabled | APP_WORKFLOW_POOL_ENABLED | false;旧清单可显式加入持续池准备滚动升级,新PoolProtected清单始终强制池;开启须提供版本 |
runtime_versions | APP_WORKFLOW_RUNTIME_VERSIONS | 空名单;环境以逗号分隔,最多32个,不允许重复、空项或构建未实现的版本 |
poll_millis | APP_WORKFLOW_POLL_MILLIS | 1000;100–60000毫秒 |
lease_millis | APP_WORKFLOW_LEASE_MILLIS | 30000;100–60000毫秒,SQL与回调使用同一绝对截止 |
retry_millis | APP_WORKFLOW_RETRY_MILLIS | 1000;100–60000毫秒,失败最多5次后保留dead |
external_runtimes | APP_WORKFLOW_EXTERNAL_RUNTIMES | 空数组;完整数组整体覆盖,最多32个版本、每版1–32个动作,必须同时列入版本名单 |
完成迁移、登记和部署前置检查后,从外层仓库根目录启动;连接、Redis和秘密由本机环境或私有配置提供,不写进命令行示例:
export APP_WORKFLOW_WORKER_ENABLED=true
export APP_WORKFLOW_RUNTIME_VERSIONS=fago-form-approval-v1
bash scripts/fago.sh worker
# 正常启动记录worker loops started;后台从数据库恢复command/timer/ready,不依赖原在线会话。
# 旧版未启用池时SIGTERM正常退出;启用池后的受控退出规则见下文。先等待全部循环退出再关闭共享数据库。
启动先核对全部enabled/draining运行时与实际内核bundle,不仅检查配置里选择的一项。 未登记、缺旧版本处理器或清单不一致,输出固定业务码409003并非零退出;未知版本或非法配置为500001。 日志只含固定诊断与业务码,不输出连接串、变量、正文或内部错误链。失败后先核对构建和管理目录,不能直接改表指纹、重开准入或清fence。 进程不自动执行迁移、注册版本、创建账号或开通套餐。
正常取消会中止当前SQL并回滚未提交工作,然后等待全部循环退出。崩溃时持久lease不被重置,新进程等其到期后按更高fence接管; 已提交收据不改写,人工等待仍由当前有效审批人处理。dead需使用明确管理恢复合同,不能靠重启复活。
# 持续池与滚动升级边界
要让旧清单参加持续协议,可在已有v1配置上明确开启池。池租期为工作租期的三倍且至少一秒, 每三分之一池租期续期一次;心跳只锁池行,不等待长业务持有的运行时版本锁。
workflow:
worker_enabled: true
pool_enabled: true
runtime_versions: [fago-form-approval-v1]
poll_millis: 1000
lease_millis: 30000
retry_millis: 1000
池绑定当前实际内核、角色和不可变清单,不从消息恢复在线会话。每次操作捕获当时绝对截止, 后续心跳只供下一次操作使用;到期后整笔业务回滚,队列须按更高fence重领,不能把另一池的领取结果直接转交。 持久心跳结果不确定时,本进程立即丢弃执行权,不猜测提交是否成功。 旧v1默认无池的进程不在持续池视图中;滚动升级前须先让所有参与进程显式加入池, 不能把未登记的旧进程算作已受控排空或受到最后池卸载保护。
v2要求兼容api/worker池共同覆盖,且所有存活工作流池都支持其精确清单,发布/启用和首次发起才放行。 因此不能在部署旧池时直接开放新版定义。当前已具备受信api池库合同及实库证明, 正式API池和首批管理/审批HTTP已实现,显式登记与调用见工作流API。 这里不把后端入口当作完整生产v2发布验收;页面、历史与完整滚动/容量仍需继续。
受控Close会拒绝最后一个非retired版本的同角色兼容池,返回409003;须先部署接管池,或关闭全部定义准入、
排空活动实例/命令/三类队列并原子退役后再关闭。普通version用于心跳CAS,fence用于业务代次,不能手工清零。
直接SIGTERM/SIGKILL和机器失联无法被此库API阻止:循环停止并撤销本地权力,未成功Close的presence保留至原截止,
进程可能以故障状态退出,不能把“进程已停”当作受控卸载成功。
完整滚动/多版本容量验收继续W12。开启工作流后,正式消息循环同步登记workflow.command.wakeup消费者,
处理workflow.command.ready原outbox提示;inbox提交成功才唤醒命令循环,所有实际执行仍重查SQL队列与池/业务租约。
工作流关闭时不订阅/派发该类型;提示过期、重复、失败或丢失不替代SQL轮询恢复。状态解释见可靠消息。
# 固定外部动作模板与进程恢复
fago-form-external-前缀的显式版本只使用代码内固定的标量表单外部动作模板:compiler v6、当前十类候选、真实审批端口和强制持续池。
配置不能提供指纹、能力开关或脚本。实际HTTP调用器生成目标摘要,动作名、动作版本及目标合同进入不可变运行清单。
模型仅引用注册动作名及输入/输出白名单,不能提供URL或凭据。
下面是受信组合根的配置形状。域名为示例,操作者须提供实际符合持久幂等/补偿协议的接收方、外部凭据文件, 并先通过独立目录管理HTTP显式登记当前构建同一工厂生成的清单。 操作见工作流API,该片段仍不代表完整生产部署/远端厂商已认证。
workflow:
worker_enabled: true
runtime_versions: [fago-form-external-orders-v1]
poll_millis: 1000
lease_millis: 30000
retry_millis: 1000
external_runtimes:
- engine_version: fago-form-external-orders-v1
actions:
- name: orders.reserve
version: orders-v1
endpoint: https://receiver.example.invalid/fago/actions
credential_file: /run/secrets/orders-external
allow_loopback_http: false
engine_version需唯一且同时存在于runtime_versions;actions的名字在该版本内唯一。
endpoint最多2048字节,规范化后固定目标,不跟随重定向、不使用环境HTTP代理。凭据文件只允许受限普通文件,
不接受初始符号链接、组/其他用户权限、换行或超过4096字节的内容;相对路径以实际加载YAML所在目录为基准,无YAML时相对当前工作目录。
APP_ENV由统一加载器选择,不是YAML字段。production始终要求HTTPS及凭据文件,禁止allow_loopback_http: true;
development/test也只有显式开关加数值回环IP的HTTP才允许无凭据,localhost和非回环HTTP拒绝。
环境覆盖接受严格数组(JSON也是合法输入),整体替换而非逐项合并;未知/重复键拒绝,最长64 KiB, 错误仅输出固定诊断与业务码,不输出配置、目标、路径或凭据。移除全部声明可用以下覆盖,但仍有旧版本引用时启动会拒绝:
export APP_WORKFLOW_EXTERNAL_RUNTIMES='[]'
# 此值只清空外部模板配置,不删除数据库中的定义、实例、job或原响应收据。
同一engine_version改目标、动作版本或动作集合会因清单不匹配而非零退出,不能修改数据库清单绕过。
要切换目标,新增版本并在两个数组中保留旧新配置;旧定义、活动实例、外部job等排空并原子退役后才移除旧处理器。
凭据轮换不改变目标摘要;配置快照不热加载,重启时重读凭据。完整多版本滚动验收仍归W12。
外部worker在持久发送意图提交后才发HTTP,所有网络操作都在SQL事务外。
远端结果未知时保持同一业务键和固定输入,达到有限预算后保留dead;已提交原响应收据的本地恢复不再发送HTTP。
正常停机先取消、join四类循环与池心跳,再关闭空闲HTTP连接;WorkerProcess.Close是本地停机,
不等同于前述RuntimePool.Close的受控卸载,也不代表远端效果已补偿。
真实双库子进程崩溃/停机证据与未认证边界见M6外部进程记录。