Skip to Content
Living documentation — last reviewed 2026-05-28
FeaturesManaged MembersManaged Members — Code Map

Managed Members — Code Map

All paths from the repo root. Mobile paths are in the taikan-mobile repo.

Schema and migration (libs/db)

FileRole
libs/db/drizzle/0168_managed_members.sqlThe single migration. Order and safety notes in data-model.md §5.
libs/db/src/lib/schema/guardianships.tsguardianships: subject, guardian, optional org scope, status (pending → active / revoked / expired), source, the 13 can* capabilities, attestation fields, objectionLodged, suppression (accessSuppressedFrom, reason, evidence ref). Three partial unique indexes (global, org-scoped, one primary per child).
libs/db/src/lib/schema/users.tsemail nullable (:36) with the partial unique index users_email_unique_idx (:97); kind 'account' | 'managed' (:67); national_id_hash; CHECK that a managed user has a birth date (:108).
libs/db/src/lib/schema/memberships.tsparticipation 'trains' | 'guardian_only' (:64).
libs/db/src/lib/schema/scheduling.tsbookings.bookedByUserId / cancelledByUserId (:264-265).
libs/db/src/lib/schema/forms.tsform_signatures.signedByUserId / signedInCapacity (:355-356), signerFullName, attestationText; form_instances.signerRequirement and health-artefact expiry.
libs/db/src/lib/schema/enums.tsuser_kind, participation_kind, guardianship_status, guardianship_source (incl. staff_enrolled), guardian_relationship, signing_capacity, actor_capacity, suppression_reason, import_reconciliation_reason.

Shared (libs/shared)

FileRole
libs/shared/src/lib/schemas/guardianship.schema.tsZod schemas and types for grants, household, capabilities, staff enrolment; MANAGED_MIN_AGE_YEARS (:30).
libs/shared/src/lib/acting-for.tsWho the member app acts for and for whom an action may be done: defaultActingFor, actingOptions, resolveActingFor. Shared by web and mobile so both start and offer the same people.
libs/shared/src/lib/constants/guardian-attestation.tsThe verbatim attestation text, rendered server-side and stored on the grant.
libs/shared/src/lib/constants/feature-flags.tsFeatureFlags.MANAGED_MEMBERS = 'managed-members'.
libs/shared/src/lib/i18n/dictionaries/{en,he,ru}.jsonmanagedMembers namespace (staff enrolment email, family hub, switcher, accept page, household section).

API — the feature (apps/api/src/guardianships)

FileRole
guardianships.controller.tsAll routes: staff enrolment (POST managed-members, resend), household, pending detail, member guardianships and dependants, child profile edit, invite, request, accept, decline, approve, reject, capabilities, revoke, make-primary, objection, suppress, unsuppress.
guardianships.service.tsGrant lifecycle. Every public method asserts the flag first. accept creates the adult’s guardian_only membership; suppress stamps accessSuppressedFrom with the database clock; sendInvitation sends the staff-enrolment or attestation email, with a Clerk sign-up invitation as the button when the adult has no login.
managed-members.service.tsStaff Add child (createByStaff), child profile edits (contact-only for a guardian: 403 staff_only_field on name or email), resend, and the import entry used by the CSV importer.
guardian-access.service.tsThe one authority resolver. actingMembership (flag, then capability, then the subject’s membership), can / check, activeGrantsFor, listAccessibleMembers (who appears in the switcher), consentQuorum, assertGuardianAge (21+).
guardian-capability.guard.ts, require-capability.decorator.tsRoute guard: a request naming another subject needs the flag and the declared capability.
managed-members-flag.service.tsenabled(orgId) / assertEnabled(orgId): tier managed_members AND PostHog managed-members; fails closed.
notification-recipients.service.tsWho receives a notification about a person: the person, or a managed member’s confirmed adults with canReceiveNotifications. Ungated.
guardian-access.module.ts, guardianships.module.tsDI wiring.
dto/*.tsRequest DTOs (staff-enrol-child, accept-guardianship, invite-guardian, request-guardianship, update-capabilities, revoke-guardianship, suppress-guardianship, objection, update-managed-member, pending-guardianship-query).

API — touchpoints in other modules

FileRole
apps/api/src/memberships/participation.tspromoteToTrainsOnOwnPlan: a guardian_only adult whose own plan goes live (active or scheduled, never pending) becomes trains. Called where a row is inserted live (SubscriptionsService.createSubscription for non-pending rows, plan change, and import for an active row only — an import of a cancelled membership promotes nothing) and wherever a row goes live later: WebhookProcessingService.handlePaymentCompleted (every provider, Cardcom return verification included, and a revived abandoned checkout), PresaleCheckoutService.handle, ManualPaymentService (cash prepayment for plans and packs, and advanceSubscription) and ExternalPaymentApplyService.advanceSubscription. The two advanceSubscription writers promote on every activation, whatever the prior status, so a checkout paid after the sweep released it still promotes.
apps/api/src/memberships/memberships.service.tsresponsibleAdults=true filter (:578); the guardian’s view of a child’s member detail; actingMembership for member reads.
apps/api/src/memberships/responsible-adults.controller.tsStaff search for an adult to name in Add child.
apps/api/src/class-sessions/class-sessions.service.ts, apps/api/src/bookings/bookings.service.tsSchedule and booking for a child via actingMembership; bookedByUserId / cancelledByUserId.
apps/api/src/bookings/booking-form-requirement.ts, apps/api/src/forms/forms.service.tsGuardian signing (resolveSigner), youth consent (parental_consent_youth, issue + booking gate when the flag is on), signing links routed to adults.
apps/api/src/payments/services/payer-resolver.service.ts, payment-method.service.tsPayer and card-owner resolution for a child’s subscription.
apps/api/src/subscriptions/subscriptions.service.ts, plan-change.service.ts, apps/api/src/plans/plans.service.tsBuying and changing a child’s plan as their adult.
apps/api/src/users/users.service.tsTeen sign-up block: SignupEmailHeldByManagedError (:57, thrown at :139, :251).
apps/api/src/webhooks/clerk-webhook.controller.tsAcknowledges the refused sign-up with 2xx and audits it with ids only.
apps/api/src/import/import.service.ts, import.controller.tsManaged CSV rows (:793), reconciliation queue (:1367), GET/POST jobs/:jobId/reconciliation (:185, :201).
apps/api/src/common/message-purpose.ts, apps/api/src/automations/channels/message-purpose.tsPromotional sends to a minor or managed subject are hard-blocked.
apps/api/src/progress-photos/progress-photos.service.tsHard block for managed members (:178).
apps/api/src/organizations/minisites.service.tsA managed member is never a public profile (:1123).
apps/api/src/analytics/analytics.service.ts, apps/api/src/insights/insights.service.tsCounts only participation = 'trains'.
apps/api/src/organization-leads/organization-leads.service.tsLead matching skips managed identities.

Web (apps/web/src)

FileRole
components/members/add-child-dialog.tsxStaff Add child (from Members, or pre-filled from an adult’s record).
app/[lang]/(protected)/dashboard/members/members-content.tsxAdd child entry and the People filter (training members / responsible adults); gated on tier and flag (:234).
components/overview/members/member-detail-page.tsxAdd child on an adult’s record (:102), Message {guardian} about {child} (:444).
components/overview/members/member-household-section.tsxHousehold section: a child’s adults or an adult’s children (:47).
components/members/pending-guardian-notice.tsx”Waiting to confirm” with resend on a child’s record.
app/[lang]/(protected)/(member)/family/accept/[grantId]/page.tsx, components/member/family/accept/accept-guardianship.tsxThe adult’s confirmation: typed name (prefilled), attestation, and the birth date when the profile has none. Signed out: inline ticket sign-up, or a redirect to sign-in and back.
app/[lang]/(protected)/(member)/family/add/page.tsx, components/member/family/add-child/*The setup steps after accepting: health, waiver, plan, first booking. Does not create a child.
app/[lang]/(protected)/(member)/profile/family/page.tsx, components/member/family/family-hub.tsx, household-tile.tsxFamily hub under Profile (/family redirects there).
app/[lang]/(protected)/(member)/profile/family/[childId]/page.tsxA child’s profile: contact-only edits.
providers/acting-context-provider.tsx, components/member/family/member-switcher.tsx, member-rail.tsx, lib/acting-paths.ts, lib/acting-scoped-query.tsView as child: the selected subject (starting at defaultActingFor), the switcher, and child-keyed queries.
components/member/acting-for-picker.tsx, app/[lang]/(protected)/(member)/shop/page.tsx, shop/payment-return/page.tsx, components/member/schedule/session-detail-drawer.tsx”Who is this for?” on the Shop and “Booking for” on a session; buying for a child (onBehalfOfUserId) and confirming it on return (?for=).
components/member/family/view-only-notice.tsx, action-notice.tsx, child-plan-summary.tsxView-only states and the child’s plan summary.

Mobile (taikan-mobile)

FileRole
src/providers/acting-provider.tsxView-as-child context.
src/components/family/member-switcher.tsx, household-tile.tsx, view-only-gate.tsx, section-not-permitted.tsxSwitcher and permission states.
app/family/accept/[grantId].tsx, src/components/family/guardian-attestation.tsxConfirmation.
app/(tabs)/profile/family/index.tsx, [childId]/profile.tsx, [childId]/setup.tsx, src/components/family/setup-steps.ts, child-forms-step.tsxFamily hub, child profile, setup steps.

Tests

AreaSpecs
Grants and accessapps/api/src/guardianships/guardianships.int.spec.ts, guardian-access.service.int.spec.ts, guardian-capability.guard.unit.spec.ts, managed-members-flag.service.unit.spec.ts, __tests__/route-capability-architecture.unit.spec.ts
Enrolment and childrenstaff-enrolment.int.spec.ts, managed-members.int.spec.ts, apps/api/src/memberships/managed-member-guards.int.spec.ts, member-detail-authz.int.spec.ts, member-erasure-guardianship.int.spec.ts
Booking, training, formsapps/api/src/bookings/guardian-booking.int.spec.ts, apps/api/src/workout-results/view-as-child-training.int.spec.ts, apps/api/src/forms/guardian-signing.int.spec.ts
Billingapps/api/src/payments/services/payer-resolver.service.int.spec.ts, payer-routing.int.spec.ts, apps/api/src/subscriptions/guardian-subscription-authority.int.spec.ts
Notificationsnotification-recipients.service.int.spec.ts, apps/api/src/notifications/managed-member-routing.int.spec.ts, apps/api/src/announcements/announcement-guardian-routing.int.spec.ts
Guardsapps/api/src/progress-photos/managed-member-block.int.spec.ts, apps/api/src/messages/managed-member-direct-message.int.spec.ts, apps/api/src/organization-leads/lead-managed-identity.int.spec.ts, apps/api/src/analytics/participation-filter.int.spec.ts, apps/api/src/automations/channels/message-purpose.unit.spec.ts
Sign-up and importapps/api/src/users/managed-email-signup.int.spec.ts, apps/api/src/import/managed-import.int.spec.ts
Webcomponents/members/add-child-dialog.int.spec.tsx, dashboard/members/members-add-child.int.spec.tsx, overview/members/member-household-section.int.spec.tsx, member/family/**/*.int.spec.tsx, providers/acting-context-provider.int.spec.tsx, profile/family/**/*.int.spec.tsx