Skip to content

feat(intake): add session answer endpoint (#5) - #112

Merged
cg8-5712 merged 2 commits into
mainfrom
issue-5-intake-answers
Jul 25, 2026
Merged

cg8-5712 merged 2 commits into
mainfrom
issue-5-intake-answers

Conversation

@cg8-5712

@cg8-5712 cg8-5712 commented Jul 24, 2026 •

Copy link
Copy Markdown
Collaborator

Implements #5. Adds the family-owned intake answer endpoint, draft candidate persistence, SQLite/PostgreSQL/MySQL migration 0013, OpenAPI contract, and API coverage for authorization, closed or unknown sessions, prompt-like text, length limits, duplicate submissions, and audit redaction. Verification: cargo fmt --check; cargo clippy --workspace --all-targets --all-features --locked -- -D warnings; cargo test --workspace --all-features --locked.

Summary by CodeRabbit

  • 新功能
    • 新增提交摄入会话单条答案接口:提交后返回候选字段、缺失字段与下一题。
    • 返回提供规则化指导模式与隐私提示;对字段候选信息进行结构化返回。
    • 新增答案记录的数据支持,用于保存原始答案与候选值。
  • 错误修复
    • 完善权限与会话状态校验:未认证 401、会话不存在(避免信息泄露)404、会话关闭或重复提交 409、超长答案 400。
  • 测试
    • 补充多场景接口测试,覆盖数据落库、审计事件并验证审计脱敏与输入安全。

Copilot AI review requested due to automatic review settings July 24, 2026 15:07

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

新增问询会话单条答案提交接口,支持创建者校验、答案规范化、会话状态更新、候选字段持久化、审计记录及下一题返回,并覆盖多数据库迁移和接口测试。

Changes

问询会话答案提交

Layer / File(s) Summary
答案存储与迁移
migration/sql/*/0013_*, migration/src/*, src/entities/...
新增 intake_session_answers 表、唯一约束、索引、级联外键、SeaORM 实体及迁移注册。
答案接口契约
src/models.rs, docs/openapi.yaml
新增答案请求、候选字段和响应模型,并声明提交接口、路径参数、认证限制及标准响应。
答案提交服务流程
src/services/intake_session_service.rs
新增事务化答案提交流程,处理权限、会话状态、字段校验、重复提交、答案更新、审计和下一题计算。
路由接入与接口验证
src/routes/intake_sessions.rs, tests/api/*
注册 POST /intake-sessions/{session_id}/answers,并测试成功提交、持久化、权限、冲突、长度限制、重复字段和审计内容。

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant 成员
  participant HTTP路由
  participant 答案提交服务
  participant 数据库
  participant 审计事件
  成员->>HTTP路由: POST session_id/answers
  HTTP路由->>答案提交服务: 传递认证信息和答案请求
  答案提交服务->>数据库: 校验会话并保存答案
  答案提交服务->>数据库: 更新会话状态和缺失字段
  答案提交服务->>审计事件: 写入字段及候选状态元数据
  答案提交服务-->>HTTP路由: 返回提交响应
  HTTP路由-->>成员: 201 Created
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.13% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确概括了新增摄入会话答案提交接口这一主要变更,且简洁明确。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-5-intake-answers

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown

Preview ready

The preview for this build is available at https://pr-112-638fb7ca7235.angui.cg8.site.

Temporary demo accounts (all use the password c6cc8259171c948822e781f86b704dae57886882b64320ca):

Role Email
Family family@demo.invalid
Commander commander@demo.invalid
Volunteer volunteer@demo.invalid
Learner learner@demo.invalid
Administrator admin@demo.invalid

These accounts and all preview data belong only to this deployment. The next preview deployment resets the SQLite database and invalidates these credentials.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/api/intake_session_answers_post.rs (1)

38-90: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

建议补充 ready_for_confirmation 状态流转的覆盖。

现有用例断言了 status == "collecting",但未覆盖“提交后必填字段全部满足 → 会话状态转为 ready_for_confirmation”这一被改动的正向路径。这是 submit_intake_answer 的关键分支,建议补一个用例把该会话的所有必填字段答完并断言最终 status。需要我生成该测试吗?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/api/intake_session_answers_post.rs` around lines 38 - 90, 补充一个覆盖
submit_intake_answer 完整正向流程的测试:创建会话后依次提交所有必填字段的答案,确保每次请求成功,并断言最后一次响应及会话记录的
status 为 ready_for_confirmation,而不是 collecting;复用现有的
answer_request、create_family_session 和 TestContext 测试工具。

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/services/intake_session_service.rs`:
- Around line 121-151: Update the insert error handling in the answer-submission
flow around set_answer and intake_session_answers::ActiveModel::insert so a
unique-constraint conflict caused by concurrent duplicate submissions is
converted to ApiError::Conflict with the existing duplicate-answer message.
Preserve propagation of all other database errors as ApiError::Database.

---

Nitpick comments:
In `@tests/api/intake_session_answers_post.rs`:
- Around line 38-90: 补充一个覆盖 submit_intake_answer
完整正向流程的测试:创建会话后依次提交所有必填字段的答案,确保每次请求成功,并断言最后一次响应及会话记录的 status 为
ready_for_confirmation,而不是 collecting;复用现有的 answer_request、create_family_session
和 TestContext 测试工具。
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2d9a2ae6-1409-4dba-9b53-112ebd3f33b3

📥 Commits

Reviewing files that changed from the base of the PR and between 91cc8cc and 638fb7c.

📒 Files selected for processing (16)
  • docs/openapi.yaml
  • migration/sql/mysql/down/0013_drop_intake_session_answers.sql
  • migration/sql/mysql/up/0013_create_intake_session_answers.sql
  • migration/sql/postgres/down/0013_drop_intake_session_answers.sql
  • migration/sql/postgres/up/0013_create_intake_session_answers.sql
  • migration/sql/sqlite/down/0013_drop_intake_session_answers.sql
  • migration/sql/sqlite/up/0013_create_intake_session_answers.sql
  • migration/src/lib.rs
  • migration/src/m0013_create_intake_session_answers.rs
  • src/entities/intake_session_answers.rs
  • src/entities/mod.rs
  • src/models.rs
  • src/routes/intake_sessions.rs
  • src/services/intake_session_service.rs
  • tests/api/intake_session_answers_post.rs
  • tests/api/mod.rs

Comment thread src/services/intake_session_service.rs Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/services/intake_session_service.rs (1)

165-170: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

避免不同字段并发提交时丢失答案。

两个请求提交不同字段时,都会从同一份旧 answers_json 构造更新;两次答案行插入都能成功,但后一次 updated_session.update 会覆盖前一次写入的 JSON,导致已存在的 intake_session_answers 记录与会话答案、缺失字段及状态不一致。请用会话行锁,或基于版本/原 updated_at 的 CAS 加重试,串行化“读取答案→更新会话”的流程。

As per path instructions, "Review Rust/Actix code for authentication, authorization, privacy, error handling, concurrency, API compatibility, and data-loss risks."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/services/intake_session_service.rs` around lines 165 - 170,
在处理会话提交的函数中,将读取答案到更新会话的整个流程串行化:使用会话行锁,或基于原始 updated_at/版本字段执行 CAS
并在冲突时重试,确保每次更新都基于最新 answers_json。重点修改构造 updated_session 并调用 update
的逻辑,同时保持答案行插入、缺失字段处理和状态更新的一致性,避免后一次提交覆盖并发请求已写入的答案。

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/services/intake_session_service.rs`:
- Around line 165-170: 在处理会话提交的函数中,将读取答案到更新会话的整个流程串行化:使用会话行锁,或基于原始
updated_at/版本字段执行 CAS 并在冲突时重试,确保每次更新都基于最新 answers_json。重点修改构造 updated_session
并调用 update 的逻辑,同时保持答案行插入、缺失字段处理和状态更新的一致性,避免后一次提交覆盖并发请求已写入的答案。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 187ed78f-737b-4ff1-a41c-56be7848e29c

📥 Commits

Reviewing files that changed from the base of the PR and between 638fb7c and 2f04874.

📒 Files selected for processing (2)
  • src/services/intake_session_service.rs
  • tests/api/intake_session_answers_post.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/api/intake_session_answers_post.rs

@github-actions

Copy link
Copy Markdown

Preview ready

The preview for this build is available at https://pr-112-2f04874a30d8.angui.cg8.site.

Temporary demo accounts (all use the password 583b3010688375113757f926d7e117648ec9e58225bded2a):

Role Email
Family family@demo.invalid
Commander commander@demo.invalid
Volunteer volunteer@demo.invalid
Learner learner@demo.invalid
Administrator admin@demo.invalid

These accounts and all preview data belong only to this deployment. The next preview deployment resets the SQLite database and invalidates these credentials.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants