Visibility phase 2: privacy-engine branches on viewer auth state #43

Merged
justin merged 1 commits from visibility-phase2-privacy into main 2026-06-09 09:08:18 -04:00
Owner

Phase 2 of the public-viewing feature. can_view_tree() now branches on the viewer's auth state so the four-level model is enforceable:

  • public / unlisted → anyone incl. anonymous (unlisted not listed by the API)
  • site_members → any authenticated account (denies anonymous)
  • private → members only
    Members always view; soft-deleted trees stay hidden. person_visibility (living-person redaction) unchanged.

Tests (ran locally, all green — CI does not run pytest): full can_view_tree matrix over {anonymous, logged-in non-member, member} × {public, unlisted, site_members, private}, deleted-tree-hidden, and the site_members anon-vs-logged-in case. Adds engine/db_session fixtures (refactored from client) to unit-test the engine directly, including the anonymous path that has no endpoint until phase 3. Full suite: 65 passed.

🤖 Generated with Claude Code

Phase 2 of the public-viewing feature. `can_view_tree()` now branches on the viewer's auth state so the four-level model is enforceable: - public / unlisted → anyone incl. anonymous (unlisted not *listed* by the API) - site_members → any authenticated account (denies anonymous) - private → members only Members always view; soft-deleted trees stay hidden. `person_visibility` (living-person redaction) unchanged. **Tests (ran locally, all green — CI does not run pytest):** full `can_view_tree` matrix over {anonymous, logged-in non-member, member} × {public, unlisted, site_members, private}, deleted-tree-hidden, and the site_members anon-vs-logged-in case. Adds `engine`/`db_session` fixtures (refactored from `client`) to unit-test the engine directly, including the anonymous path that has no endpoint until phase 3. Full suite: 65 passed. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
justin added 1 commit 2026-06-09 09:08:17 -04:00
can_view_tree() now distinguishes anonymous vs authenticated non-members so the
four-level model is enforceable:
- public / unlisted → anyone, including anonymous (unlisted gated only by the
  link, so the API must never *list* it)
- site_members → any authenticated account (denies anonymous)
- private → members only
Members (any role) always view; soft-deleted trees stay hidden from everyone.
person_visibility (living-person redaction) is unchanged.

Tests: a full can_view_tree matrix across {anonymous, logged-in non-member,
member} × {public, unlisted, site_members, private}, plus deleted-tree-hidden
and the site_members anon-vs-logged-in case. Adds `engine`/`db_session` fixtures
(refactored out of `client`) so the engine can be unit-tested directly,
including the anonymous path that has no HTTP endpoint yet.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Justin Paul <justin@jpaul.me>
justin merged commit 3ff03b037b into main 2026-06-09 09:08:18 -04:00
justin deleted branch visibility-phase2-privacy 2026-06-09 09:08:18 -04:00
Sign in to join this conversation.