WP-12 API spec
Fields and read projections the Stitch screens show. Decision: ADR 0012. Contract types: contracts.md. Wire: exchange/api-enrichment.md.
Usage
Each field lands in its owner package. New projections are read-only. A patient reads /patient/home and /notifications. A clinician reads /clinician/dashboard. An admin reads /admin/dashboard. Imaging and lab read /worklists/summary?kind=.
Domain
Appointmentinpatient.appointmentgainsreason,mode(VIDEO,CABINET),priority(ROUTINE,URGENT),clinicName,specialty, andrating?.ClinicianProfileinclinician.profilegainsdisplayName,clinicName, andbio. The search card addsfeeandnextSlot.PatientProfileinpatient.profilegainsfirstName,lastName,birthDate,email,address,city,bloodGroup,allergies, andhistory.- Vitals in
patient.monitoringgainunit,measuredAt, andstatus(NORMAL,HIGH,LOW). - Invoices in
patient.billinggaincreatedAt,currency(MRU),reference, andclinicianName. DiagnosticOrderindiagnosticsgainsexamName,requestedAt,orderedBy,structureName, andscheduledAt?.- Admin users in
admingaindisplayName,status(ACTIVE,SUSPENDED), andcreatedAt.statuslives on theAccountrow. Admin does not add a user table. AccountinidentitygainslastSeenAt?.Notificationinnotificationsis a record:id,kind(VISIT,RESULT,INVOICE,ALERT),title,at,refId,unread. It is built per request.
Persistence
All new columns are in db/changelog/modules/stitch-parity.yaml. One changeset per owner table. appointment_rating is one new table keyed by appointment_id. Notifications have no table. They are read from the owner tables at request time.
HTTP DTOs
RatingRequestDtoinbound.stars1 to 5.AgendaQueryDtogainsfromandto.ScheduleRequestDtoinbound.scheduledAt.UserStatusRequestDtoinbound.status.PatientHomeResponseDtooutbound.nextVisit?,latestResults,unpaidInvoices,openAlerts,unreadCount.ClinicianDashboardResponseDtooutbound.todayCount,waitingCount,urgentCount,nextVisits,openAlerts.AdminDashboardResponseDtooutbound.userCount,activeCount,structureCount,transactionTotal,recentUsers.WorklistSummaryResponseDtooutbound.kind,pending,urgent,scheduledToday,toValidate,sent.NotificationResponseDtooutbound.Notificationfields.
Mappers
NotificationMapper.fromAppointment(Appointment, lastSeenAt) -> Notification
NotificationMapper.fromResult(DiagnosticResult, lastSeenAt) -> Notification
NotificationMapper.fromInvoice(Invoice, lastSeenAt) -> Notification
NotificationMapper.fromAlert(Alert, lastSeenAt) -> Notification
Owner mappers add the new fields to their existing response DTOs.
Services
NotificationService
list(session) -> Notification[]
markSeen(session) -> lastSeenAt
HomeProjectionService
patientHome(session) -> PatientHomeResponseDto
clinicianDashboard(session) -> ClinicianDashboardResponseDto
BookingService.rate(session, appointmentId, stars)
AgendaService.clinicianAgenda(session, from, to)
AdminService.dashboard(session)
AdminService.setUserStatus(session, accountId, status)
DiagnosticsService.summary(session, kind)
DiagnosticsService.schedule(session, orderId, scheduledAt)
Projection services call owner services. They do not call another package's controller or repository.
Controllers
NotificationControlleron/api/v1/afia/notificationsand/notifications/seen.HomeProjectionControlleron/api/v1/afia/patient/homeand/api/v1/afia/clinician/dashboard.AppointmentControlleraddsPOST /{id}/rating.AgendaControlleraddsfromandto.AdminControlleraddsGET /dashboardandPATCH /users/{id}/status. The existingPOST /users/{id}/activationcalls the same service until WP-15 moves tostatus.DiagnosticsControlleraddsGET /worklists/summaryandPATCH /orders/{id}/schedule.
Does not do
Screens. A copy of health rows in notifications. Push delivery. Charts. AI fields. Video session state. NNI is ADR 0013 / AFIA-38 on the patient profile, not this enrichment cut.