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.sqlV1_1__seed_data.sqlV2__business_schema.sqlV27__student_privacy_settings.sqlV42__auth_token_sessions.sqlUser、UserRepository、Company、CompanyRepositoryApplication、ApplicationRepository、Job、StudentProfile
隐私与简历:
PrivacySettingsService、StudentPrivacySettings、ResumeVisibilityApplicationController、ApplicationService、CandidateDetailViewProfileController、ProfileServiceResumeStorageService、LocalResumeStorageServiceResumeFilenameSanitizer、ResumeFileValidator- 全部
profile、resume、privacy、application测试
认证与运维:
SecurityConfig、CurrentUserAccessorAuthService、AuthSessionService、JwtAuthenticationFilterapplication.yml及所有 profile 配置ErrorCode、GlobalExceptionHandlerpom.xml与 Actuator 测试
文档:
- S03 权威设计文档
privacy-settings-api.mdresume-api.mdfrontend-integration.mdbackend-development-roadmap.mdphase1-scope-and-acceptance.mdopenapi-rc.jsonverify_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。
要求:
- 不修改 V1–V42。
- 不按固定 ID 匹配。
- 每条 UPDATE 必须同时匹配 V1_1 中的原手机号、原邮箱、原 bcrypt 哈希、原角色、
is_active=1。 - ADMIN、STUDENT、COMPANY 三条分别处理。
- 仅更新
is_active=0,不删除 users/user_roles,不修改历史业务表。 - 改过手机号、邮箱、哈希或角色的同源账号不得被禁用。
- 重复执行效果稳定。
新增迁移集成测试,至少覆盖:完整指纹命中、每个单字段偏差不命中、非固定 ID 也能命中、重复执行、关联数据保留、V1–V42 校验和不变。
四、S03-A:一次性管理员初始化
新增强类型配置和条件装配,例如:
AdminBootstrapPropertiesAdminBootstrapRunner- 必要的内部 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
推荐新增:
CompanyResumeAccessPolicyCompanyResumeService- 必要的文件响应 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.mdresume-api.mdfrontend-integration.mdbackend-development-roadmap.mdphase1-scope-and-acceptance.mdverify_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。
最终报告必须列出:
- V43 精确匹配条件和各账号命中结果;
- 被修改过的种子账号不受影响证据;
- 管理员初始化配置、幂等、冲突与并发结果;
- 是否打印手机号或创建默认密码;
- 企业简历权限完整决策矩阵;
APPLIED_COMPANIES公司归属缺陷修复方式;- 拒绝路径文件读取次数;
- 完整响应与响应头脱敏结果;
- Actuator 业务端口/管理端口结果;
- 数据库副作用与 RabbitMQ 结果;
- 专项、关联、全量测试数及 Failures/Errors/Skipped;
- clean verify 与 OpenAPI 结果;
- 精确修改文件和 Git 状态;
- 是否新增 Flyway、表、索引、ErrorCode、路径;
- 明确未执行 git add -A、commit、push、Docker/MySQL 黑盒;
- 明确真实 MySQL/Docker 黑盒仍待独立验收。
最终状态只能写:
“S03 已实现并完成自动化验证与干净构建,待独立代码复验及真实 MySQL/Docker 黑盒验收。”