Files
form-center-service/src/main/resources/application.yml
T
chenxing d7473112b0
build / build-push (push) Successful in 1m26s
t1~t3落地+10-22精修: 消费授权v3(owner/grant/订阅/目录)+答卷投递v2(可信提交上下文/快照/幂等关联)+答卷对账v1(清单/派发/租约/结果)
含10-22精修六类修复: 续租renewRunning/结果INCOMPLETE_RESULT门/终态TASK_TERMINAL/liveGrant复用ACL/hosted幂等重放绑定/错误明细整条重序列化。
合规审计与证据: 工作区docs/tasks/REFINEMENT_AUDIT.md + evidence/refinement-20261022/(patch+指纹)。SQL未执行、测试未运行(仅-skipTests编译)。
2026-10-22 10:02:57 +08:00

184 lines
11 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
server:
port: 8086
# 本地无 context-path(同 flow-center dev / Notice dev);生产经 CONTEXT_PATH=/form-center 注入,
# Caddy 只反代 /form-center/api/* 与 /form-center/oapi/*,页面走前端静态。
# 端口/context-path 一律不写生产值:projman 用 SERVER_PORT、CONTEXT_PATH 环境变量注入(env 压过本文件)。
spring:
application:
name: form-center
datasource:
# 本地开发库;生产 DB 连接由 projman 平台供给(SPRING_DATASOURCE_* env 注入,本文件值被压过)
url: jdbc:mysql://localhost:3306/bsch_formcenter?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
minimum-idle: 5
maximum-pool-size: 20
jpa:
hibernate:
# 开发期 update 自动建表;生产环境建议 none + 升级脚本(sql/ 目录,见 T2 起)
ddl-auto: update
show-sql: false
open-in-view: false
database-platform: org.hibernate.dialect.MySQL5InnoDBDialect
properties:
hibernate:
jdbc:
time_zone: Asia/Shanghai
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: Asia/Shanghai
# ===== 上传大小上限(T3 上传模块,问题单 P12 记档项)=====
# 必须显式配:Spring Boot 默认 max-file-size=1MB,会把契约 §3 的 ≤50MB 附件在校验器之前就挡掉
# (报 MultipartException,用户只看到"上传失败")。两处上限与方案 §7.7 全局兜底同口径:
# 单文件 ≤50MB;请求侧同样 50MB——前端逐文件上传(view-ui-plus 默认一次请求一个文件),
# 不给"一个请求塞多个大文件"的放大面。生产若需调整由平台 env 覆盖,不写进 jar。
servlet:
multipart:
max-file-size: 50MB
max-request-size: 50MB
# ===== MQ 事件推送(契约 v2 §6.2,T17):全部键都从 RABBITMQ_* env 现读 =====
# 本地不启 broker:host 留空 → FcEventPublisher 判定"未配置"→ 发布整体 no-op(启动一条日志说明),
# 服务照跑、提交链路照绿(V64)。**不在本文件写任何生产 host/账号**:projman 按环境注入
# RABBITMQ_HOST/PORT/USER/PASS/VHOST,哪天容器就绪哪天开,不阻塞任何批次(裁决 3「可选依赖」)。
rabbitmq:
host: ${RABBITMQ_HOST:}
port: ${RABBITMQ_PORT:5672}
username: ${RABBITMQ_USER:}
password: ${RABBITMQ_PASS:}
virtual-host: ${RABBITMQ_VHOST:}
# 关掉 Boot 的 RabbitAdmin(它在启动时就拨号声明拓扑:未配 broker 的环境会反复连接失败,
# 实测把上下文启动拖到分钟级——"可选依赖"就名存实亡)。拓扑声明由 FcEventPublisher
# 自己惰性做一次(exchangeDeclare durable topic,第一次真要发的时候),不依赖 admin。
dynamic: false
# ===== v2 快照投递的两把可靠性闸(契约 answer-delivery-v2 §3.4,TASK_2 B.4)=====
# correlated:逐条 confirm 回到 AnswerDeliveryService 的回调,只有它才写 broker_accepted_at;
# 拿不到 confirm 就不算"总线收下",行留在 PENDING/FAILED 退避。
# 这两键对 v1 广播通道同样生效:v1 的消息没有 fc-delivery-id 头,回调按头缺席直接忽略。
publisher-confirm-type: ${RABBITMQ_PUBLISHER_CONFIRM_TYPE:correlated}
publisher-returns: ${RABBITMQ_PUBLISHER_RETURNS:true}
template:
# mandatory=true + publisher-returns:路由不到目标私有队列(消费方队列没绑上=部署契约缺项)
# 时必须回来,静默丢弃是最坏结局
mandatory: ${RABBITMQ_TEMPLATE_MANDATORY:true}
# ===== 文件上传存储路径 =====
# 教训注释自 notice/service application.yml 原样抄入(2026-10 事故):
# 仅供本地 Windows 开发兜底;生产读 FILE_PATH(平台统一,共享配置 application-platform.yml 一份
# /data/upload,子应用不再各自维护)。
# 切勿在生产只依赖本键:历史教训是 Linux 容器把 D:/data/upload
# 锚定成 /app/D:/data/upload 写进容器可写层,每次更新部署附件全部丢失(2026-10)。
# 读取形态(T3 上传模块实现):${FILE_PATH:${FILE_UPLOAD_PATH:${file.upload-path:/data/upload}}}
# —— FILE_PATH 由 projman 注入且持久卷固定挂 /data/upload,本键只在不注入 env 的本地生效,不可删。
file:
upload-path: D:/data/upload
# ===== 基础平台 yh 配置(flow-center/Notice/svc-hall 同款三件套)=====
yh:
auth:
enabled: true
sso:
# 本地全链测试:指向 local-debug 的 CAS(8443 根路径,RSA+AJAX 登录页);生产由平台注入
# SSO_SERVER_URL_PREFIX / SSO_CLIENT_HOST_URL 覆盖(projman 按平台设置现算,本文件不要写生产值)
server-url-prefix: http://localhost:8443
# 本地 dev 指向后端直连(脚本化登录 service=client-host-url+请求路径)
client-host-url: http://localhost:8086
allow-headers: all
allow-origins: all
# 用户面与管理面全在 /api/* 下;本应用无匿名面。
# 业务方调用走 /oapi/*(appKey 签名,RequireAppSignFilter 强制 401)
url-pattern: /api/*
app-auth:
enabled: true
# 本应用自身身份(客户端签名用)——UserBase 注册后分配(进白名单),占位值上线前必须替换,
# 生产由 projman 注入 YH_APP_AUTH_APP_KEY / APP_SECRET,禁止明文入库仓库。
# 本地占位 appKey=100021(svc-hall=100018 → flow-center=100019 → work-leave=100020 顺延);
# 联调时需在 UserBase(及对端 trusted-apps)侧同步此占位对。
# 注意:占位 secret 必须带引号且含字母——裸 32 个 0 会被 YAML 按八进制整数解析成 "0",SignUtil 校验直接 500
app-key: 100021
app-secret: "form-center-dev-secret-100021"
# 提供方强制验签(两级模型 §4.1):/oapi/** 无签名三件套即 401(starter 版 RequireAppSignFilter)。
# T1 暂无 /oapi 端点,声明保留(T4 对外读接口落地即用,不出现「先上线后端点无门」的空窗)
server:
enforce-patterns: [/oapi/*]
# 中央密钥链(两级模型 §4.2):trusted-apps 先(本地确定性兜底),未命中走 SignKeyResolver
# (Redis sign:app:* → Caffeine → UserBase 兜底端点)——任何在 UserBase 注册过的 appKey 自动可验
trust-registry: true
# 入站验签白名单:只列本地需要直调本应用 /oapi 的对端,联调时按实际补充(号段同各应用本地占位)。
# 开 trust-registry 后此表仍保留为主兜底(Redis 停摆时白名单确定性工作)
trusted-apps:
"100018": "svc-hall-dev-secret-100018"
"100019": "flow-center-dev-secret-100019"
open:
# 身份密钥唯一来源 = yh.app-auth(本文件 app-auth 段),open.* 副本不写;
# base-host 是「服务目录三级兜底」的输入(userbase 目标 = base-host + 枚举 ctx /userbase):
# 本地指向 local-debug 的 UserBase;生产由平台注入 YH_OPEN_BASE_HOST 覆盖(base.yunhaixingtong.com)。
# ⚠️ 绝不能把 services.userbase=http://localhost:8060 之类的本地覆盖写进本文件(同 flow-center 纪律):
# yh.open.services.{key} 是目录第 2 级,平台注入的 base-host 只喂第 3 级兜底、压不过它 ——
# 写进 jar 会让部署实例去连容器内的 localhost:8060(2026-09-18 事故:Connection refused →
# 所有 /api/* 报 code=6 内部服务错误)。本地联调请运行时注入:
# YH_OPEN_SERVICES_USERBASE=http://localhost:8060 mvn -o spring-boot:run
base-host: http://localhost:8060
base-path: ""
# ===== 表单中心专属配置 =====
form-center:
# 本地开发跨端口 CORS:本应用 front dev(8089) 直调 /api/* 需带凭据的 CORS 头
# (CAS cookie 不隔离端口,免二次登录成立的前提);同主域生产置空即整体关闭
cors:
allowed-origins: http://localhost:8089
# ===== hosted 填报(可信提交上下文,answer-delivery-v2 §6,TASK_2 A.2)=====
# 键按**已验签的消费 appKey**取,浏览器传的任何 URL 都不采信:可嵌入 origin 决定被嵌页
# 只允许向哪个精确 origin 发 postMessage,回调基址是消费方确认入口(签发时锁定,作审计与
# 后续反向通知的唯一事实源)。缺键=签发直接失败(fail-closed,宁可不给入口也不给一个能被
# 任意父页面接走的入口)。生产由 env 注入,本文件的本地值仅用于本机联调。
# ⚠️ 本地 svc-hall 后端与 form-center 都写 8086(两应用不会同时本机起,联调时用 env 错开):
# 跨应用联调请显式注入 FC_HOSTED_CALLBACK_URL_SVCHALL 指向 SH 后端实际端口。
hosted-fill:
token-ttl-minutes: ${FC_HOSTED_TOKEN_TTL_MINUTES:30}
embed-origin:
"100018": ${FC_HOSTED_EMBED_ORIGIN_SVCHALL:http://localhost:8087}
callback-url:
"100018": ${FC_HOSTED_CALLBACK_URL_SVCHALL:http://localhost:8086/api/apply/intents}
# ===== v2 快照投递(answer-delivery-v2 §3,TASK_2 B.1~B.6)=====
# 持久性是 outbox 行本身(答卷事务内落库),这里只调"发送侧"的节奏与重试预算。
# source-app-key 默认取本应用签名身份(yh.app-auth.app-key),信封里的 sourceAppKey 由服务端给,
# 不接受消费方申报。未配 broker 时行留在 PENDING、不丢事件(B.4)。
fc:
answer:
delivery:
source-app-key: ${YH_APP_AUTH_APP_KEY:100021}
scan-interval-ms: ${FC_DELIVERY_SCAN_INTERVAL_MS:10000}
scan-initial-delay-ms: ${FC_DELIVERY_SCAN_INITIAL_DELAY_MS:30000}
batch-size: ${FC_DELIVERY_BATCH_SIZE:50}
# 有界重试:8 次×2 递增退避(30s→60s→…→封顶 1h),耗尽即 DEAD 留表待处置,不无限 requeue
max-retries: ${FC_DELIVERY_MAX_RETRIES:8}
backoff-base-seconds: ${FC_DELIVERY_BACKOFF_BASE_SECONDS:30}
backoff-cap-seconds: ${FC_DELIVERY_BACKOFF_CAP_SECONDS:3600}
logging:
level:
com.yunhai.formcenter: debug
management:
endpoints:
web:
exposure:
include: health
endpoint:
health:
show-details: never
health:
redis:
# 引 data-redis 仅服务于 trust-registry 密钥链;关健康指标防 Redis 停摆拉 DOWN /actuator/health
# (组合链 trusted-apps 先行兜底,Redis 不可用时验签仍确定性工作)
enabled: false
rabbit:
# 同上一条先例(契约 v2 §6.2 裁决 3/V64):amqp 依赖是可选通道,RABBITMQ_HOST 未注入时
# 本地/未接 MQ 的环境不该被健康探针拖成 DOWN——发布器自身就是"未配置即 no-op"。
enabled: false