ActivityFox Dev

Child Management

Child data model, AES-256-GCM credential encryption, ownership verification, and multi-parent sharing.

Child Management

Children are real Sharetribe users with encrypted credentials, owned by one or more parent users.

Child Lifecycle

%%{init: {'theme': 'neutral'}}%%
stateDiagram-v2
    [*] --> Created: POST /api/children/create
    Created --> HasCalendar: CalDAV calendar auto-provisioned
    Created --> InviteSent: POST /api/children/share
    HasCalendar --> InviteSent: Share with co-parent
    InviteSent --> Shared: Accept invitation
    InviteSent --> HasCalendar: Decline invitation
    HasCalendar --> [*]: DELETE /api/children/delete
    Created --> [*]: DELETE /api/children/delete

Data Model

Parent's privateData:

{
  "childIds": ["child-uuid-1", "child-uuid-2"],
  "childCredentials": {
    "child-uuid-1": { "ci": "child-xxx@child.placeholder.local", "ck": "<encrypted>" }
  },
  "davisUsername": "parent@example.com",
  "davisPassword": "...",
  "davisUserId": "davis-internal-id"
}

Child's privateData:

{
  "parentIds": ["parent-uuid"],
  "childName": "Alice",
  "birthYear": 2018,
  "isChildProfile": true,
  "calendarUrl": "http://localhost:9000/dav/<davisUserId>/calendars/<uuid>/"
}

Credential Encryption

Child passwords are encrypted with AES-256-GCM before storage in the parent's privateData. The key is CHILD_CREDENTIAL_ENCRYPTION_KEY (32-byte hex string). See server/api-util/crypto.js.

Generate a key:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"

Ownership Verification

Every child endpoint uses bidirectional ownership checks (server/api-util/childOwnership.js):

  1. Parent's childIds must contain the child ID
  2. Child's parentIds must contain the parent ID

Both checks must pass or the request returns 403.

CRUD Operations

EndpointMethodDescription
/api/children/createPOSTCreate child user, encrypt creds, optionally create CalDAV calendar
/api/childrenGETList all children for the authenticated parent
/api/children/updatePOSTUpdate child profile fields
/api/children/deletePOSTDelete child user and remove from parent's childIds
/api/children/upload-avatarPOSTUpload child avatar (multipart/form-data)
/api/children/remove-avatarPOSTRemove child avatar

Multi-Parent Sharing

Parents can share children with other parents via invitations:

EndpointMethodDescription
/api/children/sharePOSTSend invitation to share a child
/api/children/invitationsGETList pending invitations
/api/children/invitations/acceptPOSTAccept and add child to your profile
/api/children/invitations/declinePOSTDecline invitation

Child Preferences (Supabase)

Preferences are stored in Supabase, not Sharetribe privateData:

TablePurpose
child_interestsCategory interests per child (10 canonical categories)
child_likesActivity favourites per child
child_connectionsRelationships between children (twin, sibling, friend, etc.)

On this page