feat: add is_public + page_note_id FK to projects table #29

Merged
forgejo_admin merged 1 commit from schema-phase1-project-fk into main 2026-02-26 20:53:12 +00:00

Summary

  • Add is_public and page_note_id FK to projects table, making project visibility and page relationships explicit in the schema
  • Data migration auto-links existing project page notes and hides Private project from public browse
  • Frontend filtering, login redirects, and linked notes change to show private titles

Changes

  • src/pal_e_docs/models.py: Add is_public (Boolean, default True) + page_note_id (FK to notes.id, nullable, UNIQUE, ON DELETE RESTRICT) + page_note relationship (lazy="joined")
  • src/pal_e_docs/schemas.py: Add is_public and page_note_slug to ProjectCreate/ProjectUpdate, PageNoteInfo nested schema, update ProjectOut
  • src/pal_e_docs/routes/frontend.py: _apply_project_public_filter() helper, project filtering on landing + browse, login redirect for private projects, removed is_public filter on linked notes
  • src/pal_e_docs/routes/projects.py: _resolve_page_note_id() helper for slug-to-FK resolution with uniqueness check
  • src/pal_e_docs/routes/notes.py: Fixed ambiguous FK join in list_notes, 409 on RESTRICT delete
  • src/pal_e_docs/templates/landing.html: PRIVATE badge for private projects
  • src/pal_e_docs/templates/projects.html: PRIVATE badge for private projects
  • src/pal_e_docs/templates/project_notes.html: PRIVATE badge in project heading
  • alembic/versions/c3d4e5f6a7b8_*.py: Migration + data migration (auto-link project pages, set Private to is_public=false)
  • tests/test_project_schema.py: 22 new tests covering filtering, FK constraints, data migration
  • tests/test_auth.py: Updated linked notes tests (titles now visible)
  • tests/conftest.py: FK-safe teardown (disable FK checks during drop_all)

Test Plan

  • Tests pass locally (59 passing)
  • Ruff check clean
  • Ruff format clean
  • Manual verification: unauthenticated browse hides Private project
  • Manual verification: authenticated browse shows Private project with badge
  • Manual verification: direct URL to private project redirects to login
  • Manual verification: linked notes show private titles

Review Checklist

  • Passed automated review-fix loop
  • No secrets committed
  • No unnecessary file changes
  • Commit messages are descriptive
  • issue-pal-e-docs-project-is-public — the issue this PR addresses
  • plan-2026-02-26-schema-entity-links — Phase 1 of the schema entity links plan
  • plan-2026-02-25-private-notes-auth — predecessor plan (auth system)
## Summary - Add `is_public` and `page_note_id` FK to projects table, making project visibility and page relationships explicit in the schema - Data migration auto-links existing project page notes and hides Private project from public browse - Frontend filtering, login redirects, and linked notes change to show private titles ## Changes - `src/pal_e_docs/models.py`: Add `is_public` (Boolean, default True) + `page_note_id` (FK to notes.id, nullable, UNIQUE, ON DELETE RESTRICT) + `page_note` relationship (lazy="joined") - `src/pal_e_docs/schemas.py`: Add `is_public` and `page_note_slug` to ProjectCreate/ProjectUpdate, `PageNoteInfo` nested schema, update ProjectOut - `src/pal_e_docs/routes/frontend.py`: `_apply_project_public_filter()` helper, project filtering on landing + browse, login redirect for private projects, removed `is_public` filter on linked notes - `src/pal_e_docs/routes/projects.py`: `_resolve_page_note_id()` helper for slug-to-FK resolution with uniqueness check - `src/pal_e_docs/routes/notes.py`: Fixed ambiguous FK join in `list_notes`, 409 on RESTRICT delete - `src/pal_e_docs/templates/landing.html`: PRIVATE badge for private projects - `src/pal_e_docs/templates/projects.html`: PRIVATE badge for private projects - `src/pal_e_docs/templates/project_notes.html`: PRIVATE badge in project heading - `alembic/versions/c3d4e5f6a7b8_*.py`: Migration + data migration (auto-link project pages, set Private to is_public=false) - `tests/test_project_schema.py`: 22 new tests covering filtering, FK constraints, data migration - `tests/test_auth.py`: Updated linked notes tests (titles now visible) - `tests/conftest.py`: FK-safe teardown (disable FK checks during drop_all) ## Test Plan - [x] Tests pass locally (59 passing) - [x] Ruff check clean - [x] Ruff format clean - [ ] Manual verification: unauthenticated browse hides Private project - [ ] Manual verification: authenticated browse shows Private project with badge - [ ] Manual verification: direct URL to private project redirects to login - [ ] Manual verification: linked notes show private titles ## Review Checklist - [ ] Passed automated review-fix loop - [ ] No secrets committed - [ ] No unnecessary file changes - [ ] Commit messages are descriptive ## Related Notes - `issue-pal-e-docs-project-is-public` — the issue this PR addresses - `plan-2026-02-26-schema-entity-links` — Phase 1 of the schema entity links plan - `plan-2026-02-25-private-notes-auth` — predecessor plan (auth system)
feat: add is_public and page_note_id FK to projects table
All checks were successful
ci/woodpecker/pr/woodpecker Pipeline was successful
e98d087719
Schema Phase 1: Add two columns to the projects table with full API,
browse frontend, and test coverage.

is_public (Boolean, default True):
- Filter private projects from landing/browse pages for unauthenticated users
- Redirect to login when unauthenticated user accesses private project URL
- Show "PRIVATE" badge on private projects for authenticated users

page_note_id (FK to notes.id, nullable, UNIQUE, ON DELETE RESTRICT):
- Links a project to its page note via foreign key
- API accepts page_note_slug for create/update, resolves to FK
- ProjectOut schema includes nested PageNoteInfo
- Uniqueness enforced: one note per project

Additional changes:
- Alembic migration with data migration (auto-links project-{slug} notes,
  sets private project is_public=false)
- Remove is_public filter on linked notes (titles visible, click redirects)
- Handle IntegrityError on note delete (409 instead of unhandled 500)
- Fix ambiguous FK join in notes list-by-project query
- Fix circular FK teardown in test conftest

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Author
Owner

Review: PASS

Reviewer: Betty Sue (main session)

What was checked:

  • Model: is_public + page_note_id FK with UNIQUE + ON DELETE RESTRICT. Proper foreign_keys disambiguation for circular FK between projects/notes. lazy="joined" for eager loading.
  • Schemas: PageNoteInfo nested schema returns id/title/slug (not full content). page_note_slug as API input resolved to FK internally — clean API surface.
  • Frontend: _apply_project_public_filter() mirrors existing note pattern. Login redirect follows same pattern as private notes. Linked notes is_public filter removed.
  • Projects API: _resolve_page_note_id() handles slug-to-FK with uniqueness check. Update correctly distinguishes "not provided" from "explicitly null" via model_fields_set.
  • Notes API: IntegrityError caught on delete — returns 409 instead of unhandled 500.
  • Migration: Data migration auto-links project-{slug} notes and sets Private is_public=false. Proper downgrade. Revision chain verified: b2c3d4e5f6a7c3d4e5f6a7b8.
  • Tests: 22 new tests covering all acceptance criteria. Existing auth tests updated for linked notes behavior change. 59 total passing.
  • Linter: ruff check + format clean.

No issues found.

Ready for merge pending Lucas's approval.

## Review: PASS **Reviewer:** Betty Sue (main session) ### What was checked: - **Model**: `is_public` + `page_note_id` FK with UNIQUE + ON DELETE RESTRICT. Proper `foreign_keys` disambiguation for circular FK between projects/notes. `lazy="joined"` for eager loading. - **Schemas**: `PageNoteInfo` nested schema returns id/title/slug (not full content). `page_note_slug` as API input resolved to FK internally — clean API surface. - **Frontend**: `_apply_project_public_filter()` mirrors existing note pattern. Login redirect follows same pattern as private notes. Linked notes `is_public` filter removed. - **Projects API**: `_resolve_page_note_id()` handles slug-to-FK with uniqueness check. Update correctly distinguishes "not provided" from "explicitly null" via `model_fields_set`. - **Notes API**: IntegrityError caught on delete — returns 409 instead of unhandled 500. - **Migration**: Data migration auto-links `project-{slug}` notes and sets Private `is_public=false`. Proper downgrade. Revision chain verified: `b2c3d4e5f6a7` → `c3d4e5f6a7b8`. - **Tests**: 22 new tests covering all acceptance criteria. Existing auth tests updated for linked notes behavior change. 59 total passing. - **Linter**: ruff check + format clean. ### No issues found. Ready for merge pending Lucas's approval.
forgejo_admin deleted branch schema-phase1-project-fk 2026-02-26 20:53:12 +00:00
Sign in to join this conversation.
No description provided.