server: port: 8080 servlet: context-path: /api/v1 error: include-message: always include-binding-errors: always spring: application: name: mydreamjob-server profiles: active: ${SPRING_PROFILES_ACTIVE:} jpa: hibernate: ddl-auto: validate show-sql: false properties: hibernate: dialect: org.hibernate.dialect.MySQLDialect format_sql: true flyway: enabled: true locations: classpath:db/migration baseline-on-migrate: true baseline-version: 0 datasource: url: ${DB_URL:jdbc:mysql://127.0.0.1:3307/mydreamjob?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true} username: ${DB_USERNAME:mydreamjob} password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver hikari: maximum-pool-size: 10 minimum-idle: 2 idle-timeout: 30000 max-lifetime: 1800000 connection-timeout: 30000 data: redis: host: ${REDIS_HOST:127.0.0.1} port: ${REDIS_PORT:6379} password: ${REDIS_PASSWORD:} timeout: 5000ms lettuce: pool: max-active: 10 max-idle: 5 min-idle: 1 rabbitmq: host: ${RABBITMQ_HOST:127.0.0.1} port: ${RABBITMQ_PORT:5672} username: ${RABBITMQ_USERNAME} password: ${RABBITMQ_PASSWORD} virtual-host: ${RABBITMQ_VHOST:/} listener: simple: acknowledge-mode: auto prefetch: 10 concurrency: 3 max-concurrency: 10 default-requeue-rejected: false jackson: default-property-inclusion: non_null serialization: write-dates-as-timestamps: false deserialization: fail-on-unknown-properties: false # JWT # S02:Access 与 Refresh 使用独立签名密钥,另设独立的 Token 摘要密钥。 # 三项密钥均无默认值,缺失即启动失败(见 AppJwtProperties 校验)。 app: jwt: # 旧配置迁移项:S02 签发/校验的 Token **不使用**该密钥,不得回退到它。 # 仍保留是因为 talentdiscovery.CandidateKeyGenerator 用它派生候选人展示键; # 该组件在密钥为空时自行失败关闭。这里改为**非强制解析**,使未配置 JWT_SECRET # 的环境也能启动(Token 安全性完全由下面三项独立密钥承担)。 secret: ${JWT_SECRET:} access-secret: ${JWT_ACCESS_SECRET} refresh-secret: ${JWT_REFRESH_SECRET} token-hash-secret: ${JWT_TOKEN_HASH_SECRET} expiration-ms: ${JWT_EXPIRATION_MS:86400000} refresh-expiration-ms: ${JWT_REFRESH_EXPIRATION_MS:604800000} issuer: mydreamjob access-audience: mydreamjob-api refresh-audience: mydreamjob-auth # S03-A:一次性管理员初始化。默认关闭;手机号无默认值,必须由部署方显式提供。 # 初始化成功后部署方必须移除该开关,普通启动不得隐式创建管理员。 bootstrap: admin: enabled: ${ADMIN_BOOTSTRAP_ENABLED:false} phone: ${ADMIN_BOOTSTRAP_PHONE:} nickname: ${ADMIN_BOOTSTRAP_NICKNAME:平台管理员} resume: storage-type: ${RESUME_STORAGE_TYPE:local} storage-dir: ${RESUME_STORAGE_DIR:./resumes} export-dir: ${RESUME_EXPORT_DIR:./resume-exports} async: resume-export: core-pool-size: ${RESUME_EXPORT_CORE_POOL:2} max-pool-size: ${RESUME_EXPORT_MAX_POOL:4} queue-capacity: ${RESUME_EXPORT_QUEUE_CAPACITY:100} data-export: core-pool-size: ${DATA_EXPORT_CORE_POOL:2} max-pool-size: ${DATA_EXPORT_MAX_POOL:4} queue-capacity: ${DATA_EXPORT_QUEUE_CAPACITY:100} data-export: dir: ${DATA_EXPORT_DIR:./data-exports} file-ttl-hours: ${DATA_EXPORT_TTL_HOURS:24} sms: mock: enabled: ${SMS_MOCK_ENABLED:false} code-length: 6 expire-seconds: ${SMS_CODE_EXPIRE_SECONDS:300} max-attempts: 5 lockout-seconds: ${SMS_LOCKOUT_SECONDS:300} offer: scheduler: enabled: ${OFFER_SCHEDULER_ENABLED:true} expiry-interval-ms: ${OFFER_EXPIRY_INTERVAL_MS:60000} reminder-interval-ms: ${OFFER_REMINDER_INTERVAL_MS:60000} match: notification: enabled: ${MATCH_NOTIFICATION_SCHEDULER_ENABLED:true} retry-ms: ${MATCH_NOTIFICATION_RETRY_MS:60000} review-moderation: sensitive-words: ${REVIEW_SENSITIVE_WORDS:刷单,代刷,有偿删评,夸大宣传} rapid-submission-window-seconds: ${REVIEW_RAPID_WINDOW_SECONDS:60} rapid-submission-limit: ${REVIEW_RAPID_LIMIT:3} duplicate-content-window-seconds: ${REVIEW_DUPLICATE_WINDOW_SECONDS:300} batch-window-seconds: ${REVIEW_BATCH_WINDOW_SECONDS:300} batch-limit: ${REVIEW_BATCH_LIMIT:5} request-id: header-name: X-Request-Id generate-on-missing: true # R01-D4-2:GET 评分接口只读,快照由写侧登记任务、后台物化和补偿扫描维护。 # 生产默认启用;测试环境可在 profile 中显式关闭,避免后台线程干扰确定性测试。 scoring: refresh: enabled: ${SCORING_REFRESH_ENABLED:true} worker-interval-ms: ${SCORING_REFRESH_WORKER_INTERVAL_MS:60000} compensation-enabled: ${SCORING_REFRESH_COMPENSATION_ENABLED:true} compensation-interval-ms: ${SCORING_REFRESH_COMPENSATION_INTERVAL_MS:3600000} compensation-limit: ${SCORING_REFRESH_COMPENSATION_LIMIT:100} batch-size: ${SCORING_REFRESH_BATCH_SIZE:20} max-attempts: ${SCORING_REFRESH_MAX_ATTEMPTS:3} retry-backoff-ms: ${SCORING_REFRESH_RETRY_BACKOFF_MS:300000} processing-timeout-ms: ${SCORING_REFRESH_PROCESSING_TIMEOUT_MS:600000} deletion: cooling-days: ${DELETION_COOLING_DAYS:30} phone-hash-secret: ${DELETION_PHONE_HASH_SECRET:mydreamjob-deletion-dev-secret-not-for-prod} scoring: ability-assessment: enabled: ${SCORING_ABILITY_ASSESSMENT_ENABLED:false} recommendation: assessment: enabled: ${RECOMMENDATION_ASSESSMENT_ENABLED:false} management: # S03-C:Actuator 隔离到独立管理端口,默认只绑定回环地址。 # 业务端口不再提供 /actuator/metrics 与 /actuator/prometheus; # 需要采集指标时由部署层通过受控网络或反向代理访问管理端口。 server: port: ${MANAGEMENT_SERVER_PORT:8081} address: ${MANAGEMENT_SERVER_ADDRESS:127.0.0.1} endpoints: web: exposure: include: health,info,metrics,prometheus # S03-C:显式开启 Prometheus 指标导出。仅暴露端点 ID 而不开启导出时, # /actuator/prometheus 不会注册(暴露清单会指向一个不存在的端点)。 prometheus: metrics: export: enabled: true endpoint: health: # 健康探针只返回最小 UP/DOWN,不暴露数据库、Redis、RabbitMQ、磁盘或连接池细节。 show-details: never show-components: never health: db: enabled: true redis: enabled: true rabbitmq: enabled: true diskSpace: enabled: true logging: level: root: WARN com.mydreamjob: INFO org.springframework.security: WARN org.hibernate.SQL: WARN org.hibernate.type.descriptor.sql.BasicBinder: WARN pattern: console: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{requestId:-N/A}] %-5level %logger{36} - %msg%n" file: "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] [%X{requestId:-N/A}] %-5level %logger{36} - %msg%n" file: name: logs/mydreamjob.log size: 10MB max-history: 7 total-size-cap: 100MB