You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

10 KiB

S03 生产配置、简历隐私与 Actuator 隔离实施指令

项目根目录:C:\Users\15642\Desktop\zhilai

候选基线:S02 已完成独立代码复验、真实 MySQL/Docker 黑盒、精确提交并推送;功能分支提交为 f399060edb2ff778322a4f021c93213f39a6f6bf。

本轮必须先完整阅读 docs/s03-production-security-and-resume-privacy-design.md。该文档是 S03 权威口径;发生冲突时停止并报告,不得自行扩大语义。

一、开始前核查

执行:

cd C:\Users\15642\Desktop\zhilai
git branch --show-current
git status --short
git diff --cached --name-only
git log -5 --oneline
git diff --check

要求:

  • 从 S02 已提交基线创建独立分支 feat/s03-production-privacy;
  • 切分支前确认暂存区和已跟踪工作区为空;
  • 保留全部历史未跟踪脚本、日志、JSON、SQL、xlsx、.env 和验收目录;
  • 不执行 git reset/restore/checkout -- <path>/clean;创建新分支仅允许 git switch -c feat/s03-production-privacy;
  • 不执行 git add -A、commit、push;
  • 实施阶段不操作 Docker,不执行真实 MySQL 黑盒;
  • 搜索并完整阅读适用的 AGENTS.md,不存在则记录。

如已有修改与 S03 目标文件重叠,停止并报告。

二、必须完整阅读

迁移与模型:

  • V1__base_schema.sql
  • V1_1__seed_data.sql
  • V2__business_schema.sql
  • V27__student_privacy_settings.sql
  • V42__auth_token_sessions.sql
  • User、UserRepository、Company、CompanyRepository
  • Application、ApplicationRepository、Job、StudentProfile

隐私与简历:

  • PrivacySettingsService、StudentPrivacySettings、ResumeVisibility
  • ApplicationController、ApplicationService、CandidateDetailView
  • ProfileController、ProfileService
  • ResumeStorageService、LocalResumeStorageService
  • ResumeFilenameSanitizer、ResumeFileValidator
  • 全部 profile、resume、privacy、application 测试

认证与运维:

  • SecurityConfig、CurrentUserAccessor
  • AuthService、AuthSessionService、JwtAuthenticationFilter
  • application.yml 及所有 profile 配置
  • ErrorCode、GlobalExceptionHandler
  • pom.xml 与 Actuator 测试

文档:

  • S03 权威设计文档
  • privacy-settings-api.md
  • resume-api.md
  • frontend-integration.md
  • backend-development-roadmap.md
  • phase1-scope-and-acceptance.md
  • openapi-rc.json
  • verify_openapi.py

先执行搜索并记录所有企业侧简历暴露点:

rg -n -i "resumeUrl|resume_url|download.*resume|resume.*download|ResumeStorageService\.read|canCompanyViewResume|studentUserId" mydreamjob-server/src/main/java

三、S03-A:禁用历史种子账号

新增且仅新增 V43__disable_legacy_seed_accounts.sql。

要求:

  1. 不修改 V1–V42。
  2. 不按固定 ID 匹配。
  3. 每条 UPDATE 必须同时匹配 V1_1 中的原手机号、原邮箱、原 bcrypt 哈希、原角色、is_active=1。
  4. ADMIN、STUDENT、COMPANY 三条分别处理。
  5. 仅更新 is_active=0,不删除 users/user_roles,不修改历史业务表。
  6. 改过手机号、邮箱、哈希或角色的同源账号不得被禁用。
  7. 重复执行效果稳定。

新增迁移集成测试,至少覆盖:完整指纹命中、每个单字段偏差不命中、非固定 ID 也能命中、重复执行、关联数据保留、V1–V42 校验和不变。

四、S03-A:一次性管理员初始化

新增强类型配置和条件装配,例如:

  • AdminBootstrapProperties
  • AdminBootstrapRunner
  • 必要的内部 Service

严格按设计文档执行:默认关闭;只有严格 true 才装配;手机号来自环境变量;无默认手机号;不打印手机号;不提供公网接口。

核心行为:

  • 已有活动 ADMIN:无副作用跳过;
  • 无活动 ADMIN + 手机号不存在:创建活动且已验证 ADMIN,users.role 与 user_roles 一致;
  • 手机号已属于任何用户或角色状态异常:启动失败,禁止提权、复活或覆盖;
  • 重复启动幂等;
  • 多实例冲突安全失败;
  • 不签发 Token、不发送短信、不写默认密码。

错误信息必须固定且不包含手机号、用户对象、SQL 或环境变量值。日志只能使用固定事件文本。

必须先写失败测试,覆盖:disabled、missing phone、invalid phone、existing active admin、new admin、duplicate run、existing student/company/inactive user、users/user_roles 一致性、日志脱敏、并发冲突。

五、S03-B:企业简历下载与隐私

新增唯一公网接口:

GET /company/candidates/{applicationId}/resume

推荐新增:

  • CompanyResumeAccessPolicy
  • CompanyResumeService
  • 必要的文件响应 record/DTO

不得将文件访问逻辑塞入现有候选人 DTO,不得返回 resumeUrl。

授权必须在 Service/Policy 中完成,不可信任 Controller 传入的归属信息。按以下顺序:当前 COMPANY 用户 → 当前 Company → Application+Job → Job.companyId → Student → privacy setting → profile/file。

必须修复现有 canCompanyViewResume 的公司归属缺失:APPLIED_COMPANIES 不能只校验学生和状态;必须证明 application 对应 Job 属于当前 company。允许替换该方法或让它委托给新 Policy,但不得保留一个可被误用的宽松生产方法。

语义严格使用设计文档决策表:

  • 默认/null 与 PRIVATE:全部企业 403;
  • APPLIED_COMPANIES:仅本企业有效投递,WITHDRAWN/REJECTED 拒绝;
  • VERIFIED_COMPANIES:企业 verified=true 且拥有 application 的岗位,状态不额外限制;
  • 跨企业、未认证、错误角色均拒绝;
  • 人才发现本轮不能借 candidateKey 下载简历。

响应要求:

  • 使用安全 Content-Disposition;
  • content type 只能来自已验证的白名单;
  • 不返回内部路径、studentUserId、手机号、邮箱;
  • 拒绝路径不得调用 storage read;
  • 文件不存在安全失败,不回显路径;
  • 不缓存私有文件,至少返回 Cache-Control: no-store;
  • 不把简历正文写入日志、审计或异常。

权限测试必须使用真实 SecurityFilterChain/MockMvc,并覆盖 COMPANY、其他企业、未认证企业、STUDENT、ADMIN、匿名。集成测试必须使用真实 H2 Repository 和真实本地临时存储,不得 Mock 掉被验证的授权链。

对所有状态 SUBMITTED/VIEWED/INTERVIEW/HIRED/REJECTED/WITHDRAWN 分别验证三种 visibility。验证企业候选人列表/详情仍不含 resumeUrl。

六、S03-C:Actuator 隔离

按设计新增:

management:
  server:
    port: ${MANAGEMENT_SERVER_PORT:8081}
    address: ${MANAGEMENT_SERVER_ADDRESS:127.0.0.1}

并将 health details/components 设为 never。不要使用业务 JWT 角色代替运维网络隔离,不新增运维公网接口。

必须验证:

  • 业务端口无法访问 metrics/prometheus;
  • 管理端口只绑定配置地址;
  • health 仅返回最小状态,不含 DB/Redis/RabbitMQ/磁盘/连接池详情;
  • metrics/prometheus 只在管理端口存在;
  • STUDENT/COMPANY/ADMIN Token 不会使业务端口指标可见;
  • dev/test/integration-test 不发生随机端口冲突。

若 Spring Boot 独立 management context 与当前 SecurityFilterChain 行为不一致,先新增真实上下文失败测试,再做最小配置;不得通过重新公开指标绕过。

七、数据与副作用测试

前后保存完整摘要,至少覆盖:

  • users、user_roles;
  • student_profiles、resume_versions;
  • applications、jobs、companies;
  • auth_tokens、audit_logs;
  • candidate_dimension_scores;
  • notifications、messages;
  • scoring_risk_events/actions;
  • talent_invitations。

企业下载只允许读取;不得修改上述业务表,不发送 RabbitMQ、短信、邮件或通知。若记录下载审计,字段必须为固定白名单且不得包含路径、文件名、学生 ID 或内容。

八、OpenAPI 与文档

从运行时契约更新 docs/openapi-rc.json,不得手工伪造。

更新:

  • privacy-settings-api.md
  • resume-api.md
  • frontend-integration.md
  • backend-development-roadmap.md
  • phase1-scope-and-acceptance.md
  • verify_openapi.py

校验器必须递归断言:

  • 只有一个新增路径/operation;
  • 下载接口无 requestBody;
  • 企业候选人 DTO 不含 resumeUrl/studentUserId/phone/email/storagePath;
  • 不存在按 studentUserId/candidateKey 的简历下载路径;
  • Actuator 不进入业务 OpenAPI;
  • 预期基线为 176 paths / 214 operations,最终以运行时生成结果为准。

九、验证顺序

先运行 S03 新增定向测试,再运行:

cd C:\Users\15642\Desktop\zhilai\mydreamjob-server
mvn -Dtest="*AdminBootstrap*Test,*LegacySeed*Test,*Privacy*Test,*Resume*Test,*CompanyCandidate*Test,*Actuator*Test" test
mvn -Dtest="*Auth*Test,*Security*Test,*Application*Test,*Company*Test,*Privacy*Test,*Resume*Test" test
mvn test
mvn clean verify
python ..\docs\verify_openapi.py

最后执行:

cd C:\Users\15642\Desktop\zhilai
git diff --check
git status --short
git diff --cached --name-only
git diff --name-only -- mydreamjob-server/src/main/resources/db/migration

必须满足 Failures=0、Errors=0、Skipped=0、clean verify 成功、静态 OpenAPI 校验通过、暂存区为空、V43 为唯一迁移、未新增 ErrorCode。

十、实施结束状态

实施结束立即停止,不操作 Docker,不执行真实 MySQL 黑盒,不暂存、不提交、不推送,不进入 Q01。

最终报告必须列出:

  1. V43 精确匹配条件和各账号命中结果;
  2. 被修改过的种子账号不受影响证据;
  3. 管理员初始化配置、幂等、冲突与并发结果;
  4. 是否打印手机号或创建默认密码;
  5. 企业简历权限完整决策矩阵;
  6. APPLIED_COMPANIES 公司归属缺陷修复方式;
  7. 拒绝路径文件读取次数;
  8. 完整响应与响应头脱敏结果;
  9. Actuator 业务端口/管理端口结果;
  10. 数据库副作用与 RabbitMQ 结果;
  11. 专项、关联、全量测试数及 Failures/Errors/Skipped;
  12. clean verify 与 OpenAPI 结果;
  13. 精确修改文件和 Git 状态;
  14. 是否新增 Flyway、表、索引、ErrorCode、路径;
  15. 明确未执行 git add -A、commit、push、Docker/MySQL 黑盒;
  16. 明确真实 MySQL/Docker 黑盒仍待独立验收。

最终状态只能写:

“S03 已实现并完成自动化验证与干净构建,待独立代码复验及真实 MySQL/Docker 黑盒验收。”