Pet Profiles
This document describes the pet profile system, including public vs. private views and access control.
Overview
Pet profiles contain detailed information about a pet, including:
- Basic info (name, age, sex, species)
- Location (country, state, city)
- Description
- Photos
- Categories/tags
- Health records (vaccinations, medical records, weight history)
- Placement requests (for rehoming)
Access Control
Pet profiles use a flexible relationship system that supports multiple user roles per pet. Each pet can have multiple active relationships with different users, allowing for complex scenarios like co-ownership, fostering, and delegated management.
Relationship Types
The system supports four relationship types:
- Owner: Full access with ownership rights, including the ability to transfer ownership, manage relationships, and delete the pet
- Foster: Caretaking access for temporary fostering situations, with edit permissions but no ownership rights
- Editor: Edit access for pet management assistance, including updating information and managing health records
- Viewer: Read-only access for monitoring pet information without edit capabilities
Access Levels
Owner/Editor View (/pets/:id)
The full pet profile is accessible to users with an active direct relationship that grants view access. Edit controls require owner or editor (foster/sitter are view-only today).
- Owners: Full access including ownership transfer, relationship management, and pet deletion
- Editors: Edit access for pet management assistance
- Fosters / Sitters: View-only access via active relationships (no main-app edit)
- Admins: Operational access stays on Filament/admin surfaces; main-app API does not grant admin-role shortcuts
Full view includes:
- All basic pet information
- Health records (weight, vaccinations, medical records) for editors/owners
- Placement requests with management capabilities (editors/owners)
- Relationship management — invite people via QR/link, view pending invitations, change owner/editor/viewer roles, and remove sharing access while keeping at least one owner
- Leave button for editors and co-owners (hidden for the last remaining owner)
- Edit controls when
viewer_permissions.can_editis true
Viewer Access
Users with viewer relationships can access the pet profile but cannot make changes:
- Read-only access to basic information
- Can view health records and placement requests
- Cannot edit information or manage relationships
- Cannot perform ownership transfers
On the public view page, viewers see a banner with a Leave button to voluntarily end their access.
View Page (/pets/:id/view)
A limited profile view is accessible based on several conditions. The view page is accessible if:
- User is the pet owner - Owners can always view their pets
- User has a PetRelationship - Users with 'owner' or 'viewer' relationship type can view
- Pet status is "lost" - Lost pets are publicly viewable to help find them
- Pet has an active placement request - Pets up for adoption/fostering (status: 'open') are publicly viewable
- User is involved in a pending transfer - Helpers who are recipients of a pending transfer request (placement request status: 'pending_transfer') can view
View page includes (whitelisted fields only):
- Basic info: name, sex, age, species
- Location: country, state, city (no street address)
- Description
- Photos
- Categories
- Active placement requests
- Viewer permission flags (relationship awareness, no edit controls)
View page excludes:
- User/relationship information
- Exact address
- Health records (unless user has appropriate relationship)
- Edit permissions
Routing Logic
When a user visits /invite/:token:
Fetch invitation preview (public endpoint)
├── Not found → Show error
├── Not authenticated → Redirect to /login?redirect=/invite/:token
└── Authenticated → Show invitation details (target, role, inviter, countdown)
├── Accept → Apply target side effect, navigate to destination
└── Decline → Record decision, navigate homeWhen a user visits /pets/:id:
Does user have edit relationship (owner/foster/editor) with pet?
├── YES → Show full view (PetProfilePage)
└── NO → Does user have viewer relationship?
├── YES → Show viewer view (read-only full profile)
└── NO → Is pet publicly viewable (lost OR active placement)?
├── YES → Redirect to /pets/:id/view
└── NO → Show "Access Restricted" messageWhen a user visits /pets/:id/view:
Can user view the pet? (owner, viewer relationship, pending transfer recipient, or publicly viewable)
├── YES → Show view page (PetPublicProfilePage)
│ └── Does user have relationship with pet? → Show info banner
└── NO → Show "Not publicly available" errorRelationship Holders Viewing Public Profile
When a user with a relationship to a pet visits the public view:
- They see the public profile with a banner indicating their relationship: "You are viewing the public profile of [pet name]."
- The "Respond to Placement Request" button is replaced with a message: "You cannot respond to placement requests for pets you have a relationship with."
API Endpoints
GET /api/pets/
Full pet profile endpoint (existing).
- Auth: Optional (uses
optional.authmiddleware) - Access: Users with active relationships (owner/foster/sitter/editor/viewer), pending transfer recipients, or publicly viewable pets (lost / open placement). No main-app admin-role shortcut.
- Returns: Full pet data with normalized
viewer_permissionscan_edit(owner/editor, or Group member with the pet in an active Group)can_delete,can_manage_people,can_transfer_ownership(direct owner only)can_view_contact(authenticated non-owners who can view)is_owner/is_editor/is_viewer/is_foster/is_sitteraccess_sources(private responses only)
GET /api/pets/{id}/view
View pet profile endpoint.
- Auth: Optional
- Access:
- Pet owner (always)
- Users with 'owner' or 'viewer' PetRelationship
- Helpers involved in pending transfers (PlacementRequest status: 'pending_transfer')
- Anyone for publicly viewable pets (lost OR active placement request)
- Returns: Whitelisted fields only
Response includes:
{
"data": {
"id": 1,
"name": "Fluffy",
"sex": "female",
"birthday_precision": "year",
"birthday_year": 2020,
"country": "US",
"state": "California",
"city": "Los Angeles",
"description": "A friendly cat",
"status": "active",
"pet_type_id": 1,
"photo_url": "...",
"photos": [...],
"pet_type": {...},
"categories": [...],
"placement_requests": [...],
"viewer_permissions": {
"is_owner": false,
"is_viewer": true,
"has_active_relationship": true
}
"is_editor": false,
"can_edit": false,
"can_manage_people": false,
"has_active_relationship": true,
"can_view_contact": true
}
}
}Components
Frontend
PetProfilePage.tsx- Owner view with full profile and health recordsPetPublicProfilePage.tsx- Public view with limited information; includes leave banner for viewersPetRelationshipsSection.tsx- Relationship management: invite people, view pending invitations, remove/leaveResourceInvitationPage.tsx- Shared page for accepting/declining resource invitations (/invite/:token)PublicPlacementRequestSection.tsx- Placement request section for public view with respond functionality
Backend
ShowPetController.php- Full pet profile endpoint with relationship-based access controlShowPublicPetController.php- Public pet profile endpoint with whitelisted fieldsPetPolicy.php- Authorization policy with relationship-based permissions andisPubliclyViewable()methodPetRelationshipService.php- Service for managing pet-user relationshipsResourceInvitationService.php- Shared invitation lifecycle (create, preview, accept, decline, revoke)PetResourceInvitationHandler.php- Pet-specific invitation preview/accept side effectsResourceInvitation.php/PetResourceInvitation.php- Shared invitation + pet detail modelsPetRelationship.php- Model representing relationships between pets and users
Related Documentation
- Pet Relationship System - Relationship types, invitations, and leave/remove flows
- Placement Request Lifecycle - How placement requests and transfers work
- Categories System - Pet categorization