Simplify project upsert creation without changing persisted fields
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 35/100
Research direction
Read the native AGENTS.md, _docs/PROCESS.md, and the frozen ownership notes first, then inspect api/views/project_upsert_persistence.py and its create_project_from_upsert entrypoint. Run the unchanged-source characterization in api/tests/test_json_body_shapes.py, reusing the existing project update and authentication fixtures. Done means the direct construction preserves the stated endpoint, persistence, validation, defaults, and identity behavior while the DTO and builder are removed and all native verification gates pass.
Written by the indexing model from the issue text.
Description
Goal
Delete the unnecessary project upsert dataclass/dictionary round trip. Preserve the existing HTTP contract, persisted project identity and values, permissions, validation, save ordering, defaults, visible UI and features. This is one behavior-preserving constructor simplification, not a project/model adoption.
Authority
- Native
AGENTS.md,_docs/PROCESS.md,.claude/agents/product-manager.mdand_docs/ci/change-selective-ci.md. _docs/specs/04-courses-and-cohorts.md,_docs/specs/06-studio-and-admin-api.md(existing compatibility endpoints retain their contracts),_docs/specs/07-security-privacy-operations.md,_docs/specs/10-verification-strategy.mdand_docs/architecture/app-boundaries.md.- User-required protected
/home/alexey/git/dtc-website/coding-standard.md, SHAc043aedb9c48076e7c24374d21075d8d823bf134f7ddfbba9194c5178c112b48, read-only authority absent from the committed source baseline. Follow all required practices; native executable verification commands govern actual gates. - Other-author audit
.tmp/dtc-next-code-simplification/REPORT.md, SHA6f95db95bfe244872de409944b73528f158b317e5809c9c6469ff4e18f3b2ee4, at committed maind8c6ff6ade741608cee6b318774358fe5aad82bb.
The raw audit incorrectly counted nine constructor fields. Actual source has eight supplied fields: course, slug, title, description, instructions_url, submission_due_date, peer_review_due_date, state. Generated database id is an additional persisted identity assertion, not a ninth constructor argument. Project.course currently references the site's Cohort, not a package Course model.
Status and ownership prerequisite
Groomed. The initial ownership prerequisite is resolved for isolated implementation by the root disposition in comment5970014430, following the owner reply. Authorized source worktree: agent-455-project-create-simplification, branch worktree-agent-455, committed remote/main d8c6ff6ade741608cee6b318774358fe5aad82bb; owned paths are only api/views/project_upsert_persistence.py and api/tests/test_json_body_shapes.py. No permission to alter or publish the foreign coding wave is granted.
The proposed source path api/views/project_upsert_persistence.py also differs in protected unpushed coding commit 257273d4abf92e53c751416e446a7a06c04f4849 (Advisory lint remediation in api). Its direct-return edits intersect the exact DTO builder and constructor; its save_project_upsert response/default cleanup is outside the deletion and must survive unchanged. Clean worktrees, absent/idle native sessions and an unavailable historical owner do not release that work. The orchestrator has frozen the isolated base and preservation agreement: style-only direct returns in the removed DTO/builder become redundant; later composition must retain the unrelated save cleanup unchanged; do not modify shared main, copy mixed WIP, discard or publish the foreign wave.
The second proposed path, api/tests/test_json_body_shapes.py, is byte-identical on committed d8c6ff6a, 257273d4 and protected local main. A bounded read-only inventory found 43 worktrees, zero exact dirty-path overlaps and zero unavailable statuses for both paths. This observation does not release the constructor overlap or any archived ownership.
No artificial dependency on package402, C5.3, homework validators, #439/#55 or book #410. Existing operational CI/Dev gates remain required, not waived by this small scope.
Scope after allocation
- In
api/views/project_upsert_persistence.py, retain the existingcreate_project_from_upsert(course, project_slug, data)entrypoint and replace only its DTO→vars→dictionary-copy→ORM construction with the same directProject.objects.createkeyword values. RemoveProjectUpsertCreateData, the unusedproject_upsert_create_databuilder and the dataclass import after independently confirming no other caller/dynamic patch/public export contract. No forwarding facade, new DTO or replacement construction framework. - Preserve
project_by_slug,apply_project_instructions_url,apply_project_data,save_project_upsertand their behavior; preserve the foreign approved advisory forms when composing onto its owner-approved base. Do not substitute the bulk-create service: it has different slug/title/error policies. - Use existing opted-in
api/tests/test_json_body_shapes.pyfor a cohesiveProjectUpsertBodyContractcharacterization of accepted JSON body→persisted project/response. It already owns actual project create/detail body contracts and importsProjectAPITestBase; baseline size is 163 lines. Keep the complete final module<=300 and every added/materially changed function<=30, with no arbitrary split or waiver. Retain existing body-shape/security tests. If a meaningful full contract cannot fit this owner, STOP and obtain a narrow reviewed test/gate allocation before adding tests; do not add excluded tests or silently expand configuration/seals.
Only the named persistence source slice and named existing test-module addition are proposed. Exact source/test ownership is now frozen by the orchestrator for isolated uncommitted implementation; independent Tester and final PM remain required. No model fields, migrations, serializers, URLs, decorators, validation rules, pins/lock/seals, templates, UI, deployment or infrastructure changes.
Existing public contract
PUT /api/courses/<course_slug>/projects/by-slug/<project_slug>/ retains token authentication, allowed-method wrapper and the current require_staff_token authority boundary. Ordinary learner/nonstaff credentials must not gain write authority. Preserve current error/status/body behavior, including missing Cohort404 and malformed/nonobject body rejection.
- Create: missing
titlefalls back toname; an explicitly present title wins. Explicit null/empty title is not replaced with name and fails the existing required-create validation.descriptiondefaults to empty only when absent.instructions_urldefaults toNonewhen absent; admitted explicitNoneversus empty string keeps the current value. Do not normalize invalid or unsupported explicit values into a new success. - Both required dates use unchanged
api.utils.parse_date: replaceZwith+00:00, thendatetime.fromisoformat; preserve clock/offset semantics, current database timezone behavior and serialized ISO values. No new date parser or chronology rule. - Constructor state is explicitly
ProjectState.CLOSED.value(CL), even though the model default is collecting submissions (CS). The existing apply/save phase still applies an admitted requested state afterward. Missing state leavesCL. - Preserve all eight arguments, existing other model defaults, one actual create insert followed by the current apply/save path, and existing transaction/autocommit boundaries. Do not introduce/relocate validation, atomic blocks, catches or side effects.
- Successful create returns201 through unchanged
project_to_dict; subsequent PUT to the same Cohort/slug updates that same row and returns200 with the same PK. Another Cohort's same slug remains independent. Omitted update fields retain existing values as they do today. - Preserve validation order: missing create requirements, instructions URL, dates, then state. Invalid state/date/instructions must not create a project; invalid update preserves existing row values through the current boundary. No new behavior promise for previously unsupported explicit values.
Acceptance criteria
- Explicit foreign-owner/base disposition is recorded before source edits; protected257273d4 changes and all foreign WIP remain preserved.
- Meaningful admitted-body characterization passes on unchanged authorized source before simplification and on the final candidate afterward. It asserts all eight supplied fields and generated PK through the real endpoint and refreshed local Project instance, not DTO/dictionary structure.
- Create201/update200, same-row identity, other-Cohort isolation, title/name precedence, absent defaults/admitted explicit null-or-empty instructions, both timezone-bearing dates and missing-state
CLare preserved. Response fields and database values agree. - Existing malformed/nonobject request, missing required fields, permission denial and invalid date/instructions/state tests retain their exact status/code and zero-create/unchanged-update assertions. No permission, serializer, URL or validation changes.
- A narrowly reversible intentional field-loss or wrong-date/state mutant reaches the owning persistence assertion and fails; a legitimate positive create/update control prevents a disabled-writes false positive. Mutation restoration is hash-proven before final gates; no production/test mutation remains in the frozen candidate.
- The unused DTO/builder/import and round-trip operations are deleted without a facade, schema/package adoption or new abstraction. Final actual diff reports net production line deletion rather than relocation; initial audit estimated about23 lines, not a guaranteed budget.
- Final test file<=300/functions<=30; persistence file shrinks; all user coding rules and native blocking/advisory checks hold. The existing opted-in test receives strict checking, not an ignored test claim.
- SWE freezes the exact diff-derived native verification plan/evidence/four-bucket report; distinct Tester independently recomputes and validates it; distinct PM accepts. No required skip or pending screenshot can satisfy acceptance.
- Ordinary local approved merge/push and sole OnCall exact-head CI+Dev succeed before operational completion. No existing non-green Dev result is relabelled as unrelated green.
Verification and browser disposition
No tests were run during PM grooming. The future engineer first adds the missing contract in the named admitted test owner and demonstrates the unchanged-source baseline, preserving any actual failed attempts under native process. Reuse existing api.tests.test_project_updates, project authentication/staff-authority and JSON-body fixtures rather than adding a second synthetic renderer or fake persistence owner.
Generate and execute the actual versioned plan through native commands:
uv run --frozen python scripts/ci.py verification-plan
uv run --frozen python scripts/ci.py verification-run
uv run --frozen python scripts/ci.py verification-evidence-check
uv run --frozen python scripts/ci.py verification-report-check
The api owner closure is api; actual final graph selection determines fresh components, quality/container/full backstops and reuse eligibility. Tester independently uses the documented VERIFY_CONSUMER=tester/role/phase commands. Do not hand-select fewer gates or borrow prior #453/package/site greens. Record exact base/head/tree, graph/policy/plan/environment digests, executed counts, commands, artifacts and all four dispositions. Existing registry/pin/seals remain unchanged.
No rendered product page is intentionally changed. Do not invent new browser pages or screenshots merely for this refactor. Native backend-only selection uses smoke; if the actual graph classifies the changed view slice as render impact, satisfy its derived core/screenshots gate or report a concrete mapping disposition through normal review, never force a backend override. Browser/API negatives preserve current authentication and state behavior, and no template changes enter this issue.
Deferred and excluded
Homework upsert validation deletion, rubric validators, scoring, #439/#55, #454 STOP, book #410 STOP, projection/history/template425/coding-wave integration, package release/adoption, data import/reset and cloud/provider operations remain separate and protected. This issue does not authorize reopening them.
- Dominant language
- Python
- Stars
- 0
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Getting set up
- Ships a Dockerfile or Docker Compose file
- No pull request template
- No contributing guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from DataTalksClub/website
-
bug infra operations P1 testing
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
DataTalksClub/website#329 ·
-
bug content data-migration documentation events operations P1
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
DataTalksClub/website#327 ·
-
bug frontend P0 testing
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
DataTalksClub/website#300 · 7 comments ·
-
bug data-migration events P0 testing
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
DataTalksClub/website#295 · 6 comments ·
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
DataTalksClub/website#454 · 2 comments ·
All issues in DataTalksClub/website
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
NousResearch/hermes-agent#133181 ·
Maintainers usually reply within 1 day
-
[oblt-aw][security] SEC-022 — findings (2026-10-05)Possibly taken @elastic-vault-github-plugin-prod claimed this today. Openoblt-aw/ai/fix-ready oblt-aw/detector/security oblt-aw/triage/security-secrets
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
elastic/oblt-aw#2304 · 2 comments · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 Under an hour Newbie friendliness 90/100
huggingface/huggingface_hub#5083 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 64/100
deepset-ai/haystack#13107 ·
Maintainers usually reply within 1 day
-
[Bug]: index worker dies on LOG_LEVEL=info / empty / numeric before it can report a missing bootstrapPossibly taken @sxh313 claimed this today. Opentriage/confirmed
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
agentscope-ai/agentscope#3130 ·
Maintainers usually reply within 1 day