Implement guided-interview filing handoffs - #225
Conversation
|
@mnewsted @VTskier what do you think about this as a configuration layer? Happy to explain more what I was thinking. The idea is you can import docassemble.LITEFile:litefile.yml and just override the things you need to with a block like variable name: litefile_data
data from code:
schema_version: 1
jurisdiction: '"vermont"'
filing_intent: '"relief_from_abuse"'
case_category_name_hints: '["Family"]'
case_type_name_hints: '["Relief from Abuse"]'
filing_type_name_hints: '["Complaint"]'
case:
existing_case: 'False'
court_name: showifdef("trial_court.name")
county: showifdef("user_selected_county")
filer: litefile_person("users[0]")
parties:
- source: '"users[0]"'
person: litefile_person("users[0]")
semantic_role: '"plaintiff"'
case_side_hint: '"plaintiff"'
is_self: 'True'
is_filing_party: 'True'
---
variable name: litefile_document_map
data:
complaint:
role: lead
form_name: Complaint
filing_type_name_hints:
- Complaint
document_type_name_hints: []
filing_component_name_hints:
- Lead DocumentYou can also have county/court specific code hints. Inside LITEFile, there's another configuration layer that can override the hints without forcing you to update the docassemble interview. And you can always override the hints inside LITEFile manually, too. |
There was a problem hiding this comment.
🟡 Changes recommended
Confirmed issues in correction draft field-reset consistency, metadata-edit signal performance overhead, and browser UX error handling for correct_filing should be addressed before approval.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR adds a guided-interview “handoff” receiver to LITEFile: an authenticated external API can create an unclaimed draft (with private PDFs + semantic hint suggestions), and the filer can later claim, review, correct clerk-returned filings, and replace PDFs while preserving immutable submission snapshots and provenance.
Changes:
- Adds source-authenticated handoff endpoints + claim/review/correction UI to turn interview payloads into durable, editable FilingDrafts.
- Introduces receipt/provenance/correction models and supporting services (metadata resolution, matter grouping, idempotent retries, PDF replacement).
- Updates workflow navigation and documentation to support correction flows and interview integration.
File summaries
| File | Description |
|---|---|
| efile_app/efile/views/my_drafts.py | Redirects resumed handoff/correction drafts to the handoff review hub. |
| efile_app/efile/views/my_cases.py | Exposes a local draft link for rejected filings to start correction flow. |
| efile_app/efile/views/login.py | Preserves a post-login continuation path for handoff claim links. |
| efile_app/efile/views/handoff.py | Adds the handoff API (create + replace documents) and claim/review/correction browser views. |
| efile_app/efile/views/confirmation.py | Expands confirmation-number extraction to include envelope identifiers. |
| efile_app/efile/urls.py | Registers new API and browser routes for handoff, claim, review, corrections, and returns. |
| efile_app/efile/tests/test_handoff.py | Adds comprehensive test coverage for handoff, claim, resolution, corrections, and replacements. |
| efile_app/efile/templates/efile/workflow_base.html | Adds a navigation link back to the handoff review hub during workflow steps. |
| efile_app/efile/templates/efile/handoff_review.html | New “saved interview answers & corrections” hub page for handoff drafts. |
| efile_app/efile/templates/efile/handoff_claim.html | New claim screen to explicitly attach an unclaimed handoff to an account. |
| efile_app/efile/templates/efile/filing_detail.html | Adds “Correct and resubmit” affordance when a locally-linked filing is rejected. |
| efile_app/efile/templates/efile/correct_filing.html | New correction-field selection UI for clerk-returned filings. |
| efile_app/efile/templates/efile/confirmation.html | Adds a link from confirmation to the correction checker flow. |
| efile_app/efile/static/config/states/vermont.yaml | Adds Vermont-specific handoff hint aliases. |
| efile_app/efile/signals.py | Records provenance for user edits to metadata fields on handoff/correction drafts. |
| efile_app/efile/settings_base.py | Adds env-configured handoff source registry and token TTL settings. |
| efile_app/efile/services/handoff.py | Core handoff domain logic: validation, populate, resolution, issues, corrections, replacements, grouping. |
| efile_app/efile/services/filings.py | Groups filings into “matters” using local correction chains before remote case IDs exist. |
| efile_app/efile/services/drafts.py | Renews signed URLs for imported handoff PDFs when resuming drafts. |
| efile_app/efile/services/draft_urls.py | Surfaces handoff draft context for workflow templates/navigation. |
| efile_app/efile/models.py | Adds correction/snapshot fields and new receipt/provenance/replacement models. |
| efile_app/efile/migrations/0023_interview_handoff.py | Database migration for new handoff/correction/provenance schema. |
| efile_app/efile/middleware.py | Ensures targeted edits from handoff flows return to the handoff review hub. |
| efile_app/efile/management/commands/expire_unclaimed_handoffs.py | Adds retention cleanup for unclaimed handoffs + private PDFs. |
| docs/docs/user-guide/case-management.md | Updates user guidance for clerk returns to use “Correct and resubmit”. |
| docs/docs/partners-courts/interview-integration.md | Adds full partner-facing integration guide for guided interview handoffs. |
| docs/developer-notes/issue-106-vermont-handoff-validation.md | Adds internal validation record for the Vermont handoff implementation. |
Review details
- Files reviewed: 27/27 changed files
- Comments generated: 5
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| def remember_metadata_before_edit(sender, instance, **kwargs): | ||
| if not instance.pk: | ||
| instance._metadata_before = None | ||
| return | ||
| instance._metadata_before = sender.objects.filter(pk=instance.pk).values(*_METADATA_FIELDS[sender]).first() |
There was a problem hiding this comment.
Fixed in 992e8dd. The pre_save metadata tracker now short-circuits when update_fields does not include any tracked metadata field, avoiding the extra lookup query.
| <h1>Correct and resubmit</h1> | ||
| <p>The court returned this filing. Select the details the clerk asked you to correct. Your other answers and documents will stay in the same matter.</p> | ||
| {% for comment in detail.comments %}<p>{{ comment.text }}</p>{% endfor %} | ||
| <form method="post"> | ||
| {% csrf_token %} | ||
| <fieldset> | ||
| <legend>What needs a correction?</legend> | ||
| {% for value, label in choices %}<div><label><input type="checkbox" name="fields" value="{{ value }}"> {{ label }}</label></div>{% endfor %} | ||
| </fieldset> | ||
| <button type="submit" class="btn btn-primary">Create correction draft</button> | ||
| </form> |
There was a problem hiding this comment.
Fixed in 992e8dd. The template now shows an error message when provided and hides the correction checklist form in that state.
| except HandoffError as exc: | ||
| return JsonResponse({"error": str(exc)}, status=exc.status) |
There was a problem hiding this comment.
Fixed in 992e8dd. correct_filing now returns the browser template with an error message (and proper status) for expected error conditions instead of JSON responses.
| <link rel="stylesheet" href="{% static 'css/confirmation.css' %}" /> | ||
| {% endblock extra_css %} | ||
| {% block workflow_content %} | ||
| <p><a href="{% url 'correct_filing' draft.pk %}">Check for a clerk return and correct this filing</a></p> |
There was a problem hiding this comment.
Fixed in 992e8dd. The new confirmation-page link text is now wrapped in {% translate %}.
Co-authored-by: nonprofittechy <7645641+nonprofittechy@users.noreply.github.com>
A completed guided interview can now create a durable, editable LITEFile filing draft containing its known answers and private PDFs. LITEFile resolves semantic suggestions against live court metadata, lets the filer complete or change every filing detail, and supports idempotent retries, account claiming, clerk-return corrections, and PDF replacement without losing the prior submission record.
Closes #106.
The Vermont sender is implemented in LSVermont/docassemble-RFApackage#426.
Receiver configuration
Apply the migration, configure private document storage as usual, and register each sending application with its own secret, jurisdiction allowlist, and allowed return origins:
cd efile_app uv run python manage.py migrateThe sender uses the same source name and secret in the Docassemble server configuration. This is one configuration per Docassemble server:
An interview may select another top-level server configuration, while defaulting to
litefile:Interview configuration
Include the adapter YAML after AssemblyLine and display its template on the download screen:
The adaptation declares what leaves the interview in ordinary Docassemble data blocks. The reusable Python transport contains no Vermont, RFA, variable-path, or document-classification branches:
litefile_person()defaults to normal AssemblyLineALIndividualand DocassembleIndividualname, address, email, and phone fields, read throughshowifdef. Different object shapes can passfields={...}and tests can passknown=...as keyword arguments.County and court-specific overrides handle jurisdictions where the same semantic hint maps differently by location. A court entry replaces a county entry for the same field; a county entry replaces the general hint. Omitted fields retain the less-specific value:
County names may include or omit
County. Court names match either the source court name or the official name resolved from live metadata. Scoped document keys must match declared document IDs. All values remain semantic names; only one unique live metadata match preselects a code.Behavior and safety
expire_unclaimed_handoffs.Validation
uv run pytest -q— 784 passed.uv run ruff check .— passed.uv run ty check— passed.uv run python manage.py makemigrations --check --dry-run— no model drift.npm run build— passed.BackgroundAction. The one-click success flow completed, and retrying returned HTTP 200 while retaining one receipt, one draft, four documents, and the same source identity.The detailed test record is in
docs/developer-notes/issue-106-vermont-handoff-validation.md.