Week 1 Day 04 Healthcare Domain Generated by Gemini Code Assist

3-Tier Serverless Stack Specs

Detailed RESTful API definitions and backend handlers specification.

Critical Architectural Pivot

Moving from a "thick client" (BaaS - Backend as a Service) model to a traditional 3-Tier Architecture (Client → API Gateway → Compute → Database) significantly changes our flow design and enhances security and decoupling.

This is a very common enterprise requirement. Here is the Revised Day 4 specification, focusing on RESTful API definitions and the backend handlers.

Revised Architecture: The 3-Tier Serverless Stack

We are abandoning direct client access to Firestore.

Client (Mobile App)

Authenticates via Firebase Auth to get a temporary ID Token (Bearer Token). It makes HTTP requests to the API Gateway, putting that token in the Authorization header.

Security Boundary (API Gateway)

Sits in front of our Cloud Functions. It is configured with a security definition to validate the Firebase ID Token. If valid, it passes the request to the function; if not, it rejects with 401 Unauthorized.

Compute (Cloud Functions)

Now act as RESTful API handlers. They trust the user ID passed down from the Gateway, perform business logic, and are the only things allowed to talk to Firestore.

A. API Gateway Security Configuration

Before defining the endpoints, we define the security scheme that applies to all of them.

Type: OAuth2 (using Firebase Auth ID Tokens)
Mechanism: The Client sends header: Authorization: Bearer <firebase_id_token_here>
Gateway Verification: The API Gateway config will point to the Firebase project's issuer URI (https://securetoken.google.com/YOUR_PROJECT_ID) to validate the token signature without needing a separate function.
Context Injection: Upon successful validation, API Gateway injects the user's claims (specifically their sub (UID) and custom claims like role) into a base64 encoded header (X-Apigateway-Api-UserInfo) that the backend Cloud Function can decode and trust.

B. API Endpoint Definitions & Function Specs

We need to build 5 specific Cloud Functions to act as handlers for our API routes.

1. The "Get Upload URL" Handler (Replacing direct upload)

Since the client cannot write to storage directly, it must ask the backend for a temporary, pre-authorized "Signed URL" to perform the upload.

POST /v1/reports/upload-url
Handler Name: api-getSignedUrl
Trigger: HTTP Request
Input (Request Body):
{
  "fileName": "bloodwork_oct26.pdf",
  "contentType": "application/pdf"
}
Logic Specifications:
  • Auth Check: Decode gateway header. Ensure requestor has role: 'patient'. Get their UID.
  • Validation: Ensure contentType is 'application/pdf' or 'image/jpeg'.
  • Path Construction: Determine the target storage path: uploads/{patient'sAssignedDoctorId}/{patientUid}/{timestamp}_{fileName}. (Need to read patient profile first to get the doctor ID).
  • GCS Operation: Use Cloud Storage Admin SDK to generate a V4 Signed PUT URL, valid for 15 minutes, restricted to that specific path and content type.
Success Output (HTTP 200):
{
  "uploadUrl": "https://storage.googleapis.com/...", // The pre-signed long URL
  "expiresIn": 900
}
(The mobile app then performs a PUT directly to this uploadUrl with the file binary).

2. Patient: Get My Reports

GET /v1/patient/reports
Handler Name: api-getPatientReports
Input: ?limit=5 (Optional)
Logic Specifications:
  • Auth Check: Decode header. Get Patient UID. Ensure role: 'patient'.
  • DB Operation: Query Firestore: collection('users').doc(patientUid).collection('lab_reports').orderBy('uploadTimestamp', 'desc').limit(X).
  • Success Output (HTTP 200): A JSON array of the report documents.
  • Error Output: 403 Forbidden if role is wrong.

3. Doctor: Get My Patient List

GET /v1/doctor/patients
Handler Name: api-getDoctorPatients
Logic Specifications:
  • Auth Check: Decode header. Get Doctor UID. Ensure role: 'doctor'.
  • DB Operation: Query Firestore: collection('users').where('assignedDoctorId', '==', doctorUid).
  • Success Output (HTTP 200): JSON array of patient profile documents (excluding sensitive internal fields).

4. Doctor: Get Specific Patient Report Details

GET /v1/doctor/patients/{patientId}/reports/{reportId}
Handler Name: api-getReportDetails
Logic Specifications:
  • Auth Check: Decode header. Get Doctor UID. Ensure role: 'doctor'.
  • Security Verification (Crucial):
    Read the target patient's profile: db.doc('users/' + patientId).
    Verify that fetchedPatient.assignedDoctorId === requestingDoctorUid.
    If not match: return 403 Forbidden (You are not assigned to this patient).
  • DB Operation: If verified, read db.doc('users/' + patientId + '/lab_reports/' + reportId).
  • Success Output (HTTP 200): JSON object of the specific lab report.

5. Doctor: Schedule Appointment

POST /v1/appointments
Handler Name: api-scheduleAppointment
Input (Request Body):
{
  "patientId": "uid_of_patient",
  "startTime": "2023-10-28T10:00:00Z", // ISO 8601 string
  "endTime": "2023-10-28T10:30:00Z",
  "notes": "Initial consult"
}
Logic Specifications:
  • Auth Check: Doctor UID from token.
  • Validation: Ensure startTime is in the future. Ensure patientId belongs to this doctor (similar check to #4 above).
  • Data Prep: Read Doctor Name and Patient Name to prepare for denormalization.
  • DB Operation: db.collection('appointments').add({ doctorId: requestingUid, patientId: req.body.patientId, ... }).
  • Success Output (HTTP 201 Created): { "appointmentId": "new_auto_id" }
  • Error Output: 400 Bad Request (invalid dates), 403 Forbidden (wrong patient).

C. The Background Event Functions

These components automate business logic, invisible to the user but driving application state.

Function 1: User Profile Seeder

Trigger: auth-onCreateUser (Firebase Authentication User Created Event)

Logic: Check if doc exists at /users/{uid}. If not, create with default data (Role: 'patient', AssignedDoctor: null).

{
  "email": event.email,
  "displayName": event.displayName || "New User",
  "createdAt": admin.firestore.FieldValue.serverTimestamp(),
  "role": "patient",
  "assignedDoctorId": null
}

Function 2: The Intelligent PDF Processor

Trigger: storage-onFinalize (Cloud Storage Object Finalized)

Filter: Path must match uploads/{doctorId}/{patientId}/{filename}.

Step Action On Failure
Pre-validation Check content type & path. Log error "Invalid File".
Placeholder Write { "status": "processing" } to Firestore. Log error.
AI Processing Send to Document AI Form Parser. Update status to "failed".
Parsing Extract key-value pairs & test date. Update status to "failed".
Finalize Update Firestore with { "status": "processed", "parsedData": {...} }. Log write error.

D. Architecture Diagrams

Visual representations of the system flow for Client, Doctor, and Background operations.

Figure 1: Client Side & API Security Flow

Client Side to Data Layer Architecture Diagram

Flow: Mobile App -> API Gateway -> Cloud Functions -> Firestore/GCS

Workflow Narrative
  1. Auth: App authenticates user, receives Firebase ID Token.
  2. View Request: App requests reports via Gateway, attaching token to header.
  3. Gateway Security: API Gateway validates signature of the token with Firebase.
  4. Backend Query: The authorized Cloud Function queries Firestore for this specific user's data.
  5. Upload Request: Patient wants to upload. App asks API for permission.
  6. Path Logic: Backend function reads patient profile to determine correct folder path (e.g., uploads/dr_smith_id/patient_jones_id/).
  7. Signed URL: Function asks Cloud Storage for a temporary (e.g., 15-min) URL that allows a single PUT operation to that specific path.
  8. Direct Upload: The mobile app uses that temporary URL to upload the heavy PDF file directly to Google Cloud Storage, bypassing the API Gateway and Functions to save bandwidth/cost.
GCP Resource Inventory (View 1)
Resource Name Type Purpose in this Flow
Firebase Authentication Identity Issues and validates the secure JWT (ID Tokens) used for API calls.
API Gateway Networking/Security The single entry point. Handles TLS termination, DDoS protection, and token validation before reaching compute.
Cloud Functions (2nd Gen) Compute (HTTP) Hosts the Node.js/Python API handlers (api-getPatientReports, api-getSignedUrl).
Cloud Firestore Database (NoSQL) Stores user profiles and metadata pointers to the lab reports.
Cloud Storage Object Storage Stores the actual raw PDF files. Generates temporary Signed URLs for secure direct access.

Figure 2: Doctor View & Routing Logic

Doctor View Architecture Diagram

Flow: Doctor Actions -> Gateway Validation -> Role Check -> Compute Logic

Workflow Narrative
  1. API Request: Doctor app makes REST calls (e.g., to view patient list or schedule).
  2. List Query: The getDoctorPatients function performs a filtered query on Firestore to find users assigned to the requesting doctor's UID.
  3. Security Check (Crucial): When accessing specific patient data (viewing a report or making an appointment), the Cloud Function first reads the target patient's user document to verify the assignedDoctorId matches the requestor. If not, it throws a 403 Forbidden error.
  4. Write Operation: Once verified, the appointment is written to Firestore.
GCP Resource Inventory (View 2)
Resource Name Type Purpose in this Flow
Firebase Authentication Identity Issues tokens asserting the user has the 'doctor' role.
API Gateway Networking/Security Protects doctor API routes.
Cloud Functions (2nd Gen) Compute (HTTP) Hosts API handlers and enforces business logic security checks.
Cloud Firestore Database (NoSQL) Stores patient relationships, lab report data, and appointment schedules.

Figure 3: Event-Driven Background Compute

Background Compute Architecture Diagram

Flow: Upload Event -> Eventarc -> Processor Function -> DocAI -> Firestore Update

Workflow Narrative
  1. Event Emission: A file successfully finishes uploading to Cloud Storage (from Patient View, step 8). Storage emits an google.storage.object.finalize event.
  2. Trigger: Eventarc routes this event to the specific Cloud Function designed to handle it.
  3. Initial Status: The function immediately writes to Firestore to let the UI know processing has begun.
  4. AI Processing: The function streams the file from Storage to the Document AI API.
  5. Data Extraction: Document AI analyzes the PDF and returns a JSON object of key/value pairs.
  6. Finalize: The function sanitizes the JSON and updates the Firestore document, changing status from "processing" to "processed". The mobile app listens to this document and updates the UI automatically.
GCP Resource Inventory (View 3)
Resource Name Type Purpose in this Flow
Cloud Storage Object Storage The trigger source. Holds the raw file.
Eventarc Eventing Captures the storage event and reliably delivers it to the Cloud Function.
Cloud Functions (2nd Gen) Compute (Event) The background worker that coordinates the AI and Database process.
Document AI AI/ML API The intelligence engine that converts unstructured PDF pixels into structured JSON data.
Cloud Firestore Database (NoSQL) Stores the final processed results for the frontend to consume.

Summary of Revised Day 4

We have successfully redefined the application flow to adhere to a strict 3-Tier API Gateway architecture.

Next Step: We are ready for Day 5: Code generation. We will write the OpenAPI (Swagger) definition for the Gateway and the Node.js/Python code for these 5 handler functions.