Skip to content

Add contributor roles and field-level privacy controls - #1481

Open
drusepth wants to merge 2 commits into
tailwind-redesignfrom
claude/universe-contributor-roles-mqa9se
Open

Add contributor roles and field-level privacy controls#1481
drusepth wants to merge 2 commits into
tailwind-redesignfrom
claude/universe-contributor-roles-mqa9se

Conversation

@drusepth

Copy link
Copy Markdown
Member

Fixes #

User-facing changes

  • Contributors to universes can now have different roles (Full Contributor, Editor, Read-Only) with varying permissions for creating and editing content
  • Attribute fields can now be marked as public, contributors-only, or private, controlling who can see field values on pages
  • Universe owners can change contributor roles from the contributors panel
  • Contributors panel now shows each contributor's role and what they can do
  • Field visibility badges appear on fields that aren't visible to everyone

Implementation notes

Contributor Roles

Added a three-tier role system to the Contributor model:

  • Full Contributor: Can view, edit, and create content in the universe
  • Editor: Can view and edit existing content, but cannot create new pages
  • Read-Only: Can view all content but cannot edit anything

The User model now tracks editable_universe_ids and creatable_universe_ids separately from contributable_universe_ids, enabling role-based permission checks throughout the app.

Field-Level Privacy

Added privacy controls to AttributeField with three levels:

  • Public: Visible to anyone who can view the page
  • Contributors: Visible only to the page owner, universe owner, and universe contributors
  • Private: Visible only to the page owner

The effective_privacy method handles legacy private notes fields (which were always private) while allowing them to be opened up to contributors.

Permission Service Enhancements

Extended PermissionService with new methods:

  • user_can_edit_universe_content?: Checks if user is Full Contributor or Editor
  • user_can_create_universe_content?: Checks if user is Full Contributor
  • attribute_field_visible_to?: Determines if a field is visible to a given viewer

Serializer Updates

Both ContentSerializer and ApiContentSerializer now filter out fields the viewer cannot see based on privacy settings and contributor role.

Authorization Changes

Updated ContentAuthorizer and related authorizers to use the new role-based permission checks instead of binary contributor/non-contributor logic.

Testing

  • Added comprehensive test suite in test/models/attribute_field_visibility_test.rb covering all privacy levels and viewer types
  • Added test/models/contributor_role_test.rb testing role capabilities and permission checks
  • Added test/controllers/contributor_roles_controller_test.rb testing role assignment and enforcement
  • Added test/controllers/field_visibility_controller_test.rb testing field-level access control
  • All new tests pass; existing tests updated to work with new role system

Database Migrations

  • 20260820000001_add_role_to_contributors.rb: Adds role column to contributors table, defaults existing contributors to 'full'
  • 20260820000002_backfill_attribute_field_privacy.rb: Normalizes privacy column values and marks legacy private notes as private

https://claude.ai/code/session_01RfS7K1qjfi2LZHCorFn7d4

claude added 2 commits August 20, 2026 05:15
Universe contributors now have a role that controls what they can do:
- Full Contributor: read, edit, and create content (existing behavior)
- Editor: read and edit existing content, but not create new pages
- Read-Only: read all content in the universe, but not edit anything

All existing contributors are backfilled as Full Contributors, matching
the access level they already had.

Details:
- Add contributors.role column (default 'full') with backfill migration
- Contributor model: role validation, labels, and capability helpers
- User: role-aware editable_universe_ids / creatable_universe_ids
  alongside the existing read-level contributable_universe_ids
- PermissionService: edit- and create-level universe permission checks
- Authorizers (content, content page, universe, book, timeline) now
  distinguish read vs edit access for contributors
- ContentController: block page creation in universes where the user
  lacks create rights, and guard the per-field update endpoints with
  updatable_by? checks
- Gallery image sort and image pinning now require edit-level access
- Contributors UI: role picker on invite, role labels/badges, and
  owner-only role changes (new PATCH contributor/:id/role route)

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RfS7K1qjfi2LZHCorFn7d4
…elds

Fields on a page template can now be configured with three visibility
levels via the previously-unused attribute_fields.privacy column:
- public: visible to everyone who can view the page (default)
- contributors: visible to the page owner, universe owner, and universe
  contributors of any role, but hidden from the public
- private: visible only to the page owner

Previously the only enforced privacy was a hardcoded check hiding
old_column_source='private_notes' fields from non-owners.

Details:
- Backfill migration normalizes stray privacy values and stamps legacy
  Private Notes fields as 'private'
- AttributeField: VISIBILITIES constant, validation, effective_privacy
  (legacy Private Notes fields can open up to contributors but never
  become fully public, preserving their historical guarantee)
- PermissionService.attribute_field_visible_to? is the single source of
  truth for field visibility
- ContentSerializer and ApiContentSerializer strip fields the viewer
  can't see (covers show, edit, and API responses); the API serializer
  now threads through the authenticated API user as the viewer
- References page hides references originating from fields the viewer
  can't see on the referencing page
- Changelog replaces its label-based 'Private' heuristic with the real
  visibility check
- Per-field update endpoints reject writes to fields the viewer can't
  see, even with edit access to the page
- Field customization UI: the dead 'Private' checkbox is replaced with
  a working three-option visibility control (permitting :privacy), and
  show pages badge contributors-only/private fields

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RfS7K1qjfi2LZHCorFn7d4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants