Complete Projects API lifecycle and field validation #80
- AtlantisPleb opened this issue 23h ago
-
A Author 6h ago Shipped in
b315cb2onmain.Endpoints now complete
Method Path PATCH/repos/{owner}/{repo}/projectsV2/{project_number}— now also acceptsarchivedDELETE/repos/{owner}/{repo}/projectsV2/{project_number}PATCH/repos/{owner}/{repo}/projectsV2/{project_number}/fields/{field_id}DELETE/repos/{owner}/{repo}/projectsV2/{project_number}/fields/{field_id}GET /repos/{owner}/{repo}/projectsV2gains anarchived=trueparameter, and a project object now reportsarchivedandarchived_at.Lifecycle
A project moves along two independent axes.
statestaysopenorclosed, so close and reopen arePATCHonstate. Archive and restore arePATCHonarchived, backed by anarchived_attimestamp. Closing says the work the board tracked reached an end; archiving says the board left the working set, whatever became of the work. Keeping the archive offstateleaves every existing reader ofopenandclosed— the API, the board, the workspace tabs — reading the two values it always read. Project lists omit archived boards until asked.DELETEon a project needs two keys: a writable membership in the repository, and a project already archived. The board pairs its delete control with a confirmation prompt and an API caller has none, so archiving is the deliberate step that stands in for one. Deleting removes the project's fields and items, never the referenced issues, and never the append-only item event history.Validation
stateis checked byvalidate_inclusion/3and by a newprojects_state_checkdatabase constraint.- A field's
data_typeistext,number,date,single_select, orpromise_state, checked in the changeset and by aproject_fields_data_type_checkdatabase constraint. - Field names are unique within a project, compared without case, enforced by a unique index on
(project_id, lower(name)). The name is the key an item stores its value under, so a duplicate would make a stored value ambiguous. - A select carries a non-empty
options.valueslist. Entries are names, where the name identifies the option, or objects with a stableidandname, where the identifier survives a relabel. Duplicate identifiers, blank entries, and options on a data type that carries none are all refused. - Item values are checked against the fields a project declares: a select value must name one of the field's options, a number must be a number, a date must be ISO 8601. A value under a key no field declares passes through untouched, so a board keeps a value written before its field existed and existing clients stay compatible.
How a field change affects existing item values
- Rename rewrites the stored key on every item of the project in the same transaction, so a rename never empties the column.
- Data type never changes. Values already stored were written against the old type, and reinterpreting them is a destructive change wearing an edit's clothes.
- Dropping an option items still carry returns
422naming the identifiers in use, and preserves the options and the values. - Deleting a field items still carry returns
422and preserves both the field and the values.
Activity and authority
Every project lifecycle and field change appends an actor-attributed
activityentry, readable at.../notes?kind=activity. The new routes resolve the repository from the path and require a writable membership, so a non-member receives404and a private repository's projects and fields stay indistinguishable from missing ones.Verification
Controller and context tests were written before the routes, controller, context, and migrations, per the repository's test-first workflow.
MIX_TEST_PARTITION=lane80 mix precommitpasses: 3072 tests, 15 excluded.Documented in
docs/github-api-issues-projects-assessment.mdandpriv/docs/projects.md.Left to #81
Item operations and stored-field board rendering stay out of scope. Two shapes established here are what that lane builds on:
ProjectField.option_ids/1andProjectField.option_id/1are the public readers for what a select offers, and an item stores the option identifier rather than the label. - closed this as completed 6h ago
Outcome
Complete the project and project-field lifecycle so project views can serve as durable planning surfaces.
Current behavior
The API can create and read projects and create fields. It cannot update, close, reopen, archive, or delete projects, and stored field names, option identifiers, data types, and values do not yet provide a complete validated contract.
Source:
docs/2026-08-21-issues-projects-work-system-assessment.md, tracks C3 and C4.Contract
Acceptance criteria
Verification
Write controller and context tests first, then migration, authorization, event, rollback, and exact-candidate API tests. Run
mix precommit.Dependencies
Build on #9 and #60. Coordinate the item and stored-board issue in project 8.