Pramio System Architecture and Technical Pipelines

This document details the complete technical architecture, cloud infrastructure, and operational data pipelines of the Pramio medical application. The infrastructure is 100% serverless, running entirely on Cloudflare edge services with zero local Docker containers or background host processes.

1. High-Level System Architecture

Mobile clients (Android and iOS) connect over HTTPS to an Anycast edge API Gateway running on Cloudflare Workers. The gateway interacts with an edge-native relational SQL database (D1), distributed media storage (R2), and low-latency key-value memory (KV).

Figure 1: System Topology and Cloudflare Services
flowchart TD subgraph Clients["Mobile Client Layer"] A["Android Application (Kotlin / Jetpack Compose)"] B["iOS Application (Swift / SwiftUI)"] end subgraph Edge["Cloudflare Edge Network"] GW["API Gateway Worker: pramio-api
(Routing, Validation, Auth, Media Handler)"] subgraph Storage["Cloudflare Storage and Crypto Layer"] D1[("Cloudflare D1: pramio-db
(Relational SQL Database)")] R2[("Cloudflare R2: pramio-media
(Distributed Object Storage)")] KV[("Cloudflare KV: PRAMIO_KV
(Key-Value OTP and Session Cache)")] CRYPTO["Web Crypto Engine
(HMAC-SHA256 Token Signing)"] end end A -->|HTTPS REST| GW B -->|HTTPS REST| GW GW -->|SQL Operations| D1 GW -->|PUT / GET Binary Buffers| R2 GW -->|OTP Cache with TTL| KV GW -->|SubtleCrypto Sign / Verify| CRYPTO A -.->|Direct Binary Media Upload| R2

2. Cloud Services and Infrastructure Stack

All backend services operate under Cloudflare account cadefunn@gmail.com (Account ID: cc82a15e73e49b96877da6c12617bbdc).

Service Name Resource Identifier Technical Role Tier Limits and Cost
Cloudflare Workers pramio-api Primary API router, request validation, business logic, authentication gate, and direct R2 upload streamer. 100,000 requests/day included ($0/month)
Cloudflare D1 pramio-db
e9df2305-6144-4e4b-9441-c230fe46ef4b
Distributed relational database for profiles, clinical posts, replies, CME credits, conversations, and verifications. 5 GB storage, 5,000,000 reads/day included ($0/month)
Cloudflare R2 pramio-media Zero-egress object storage for clinical case photographs, doctor avatars, and audio dictation attachments. 10 GB storage included, 0 egress fees ($0/month)
Cloudflare KV PRAMIO_KV
757e418e5b1c4e25b068c463c9368c30
Low-latency memory store for SMS one-time passwords with automatic TTL expirations and revoked token blacklists. 1 GB storage, 100,000 reads/day included ($0/month)
Web Crypto API V8 Engine Native Hardware-accelerated HMAC-SHA256 signature generation and validation for JSON Web Tokens. Standard runtime component ($0/month)

3. Core Technical Pipelines

Pipeline 1: Authentication and Doctor Verification Pipeline

Doctor sign-in uses mobile phone numbers with SMS one-time password verification. Testing accounts use master bypass codes (831782, 000000, 150441). Access tokens expire in 15 minutes; refresh tokens expire in 30 days.

Figure 2: Authentication and Verification Sequence
sequenceDiagram autonumber participant App as Mobile App participant Worker as Cloudflare Worker participant KV as Cloudflare KV participant D1 as Cloudflare D1 App->>Worker: POST /api/v1/auth/otp/request { phone: "+919798402612" } Worker->>KV: PUT otp:+919798402612 (TTL: 600s) Worker-->>App: 204 No Content App->>Worker: POST /api/v1/auth/otp/verify { phone: "+919798402612", code: "831782" } Worker->>KV: Validate against stored OTP or Master Bypass List Worker->>Worker: Web Crypto sign HMAC-SHA256 JWT pair Worker-->>App: 200 OK { accessToken, refreshToken } App->>Worker: GET /api/v1/me (Bearer Token) Worker->>D1: SELECT * FROM profiles WHERE userId = ? Worker->>D1: SELECT status FROM verifications WHERE userId = ? Worker-->>App: 200 OK { profile, verificationStatus: "verified" }

Pipeline 2: Medical Image Privacy, Sanitization and R2 Storage Pipeline

To comply with healthcare data privacy requirements, all photographs undergo strict client-side sanitization on the device before transmission. The pipeline guarantees zero EXIF metadata, GPS data, or vendor encoder comments leave the phone.

Figure 3: Image Sanitization and Direct R2 Upload Pipeline
sequenceDiagram autonumber participant Device as Phone Camera / Picker participant Sanitizer as ImageSanitizer (Kotlin) participant Worker as Cloudflare Worker participant R2 as Cloudflare R2 Bucket Device->>Sanitizer: Raw Image Bytes (Content URI / Cache File) Sanitizer->>Sanitizer: Downscale longest edge to max 2048px Sanitizer->>Sanitizer: Apply rotation matrix to bake upright orientation Sanitizer->>Sanitizer: Re-encode raw pixel buffer to JPEG (Quality 85) Sanitizer->>Sanitizer: JpegMetadata.strip() removes APP1, APP13, and COM segments Sanitizer->>Sanitizer: JpegMetadata.find() asserts 0 metadata segments remain Sanitizer->>Worker: POST /api/v1/uploads/presign { contentType: "image/jpeg", contentLength } Worker-->>Sanitizer: 200 OK { uploadUrl, fileUrl } Sanitizer->>Worker: PUT /api/v1/uploads/raw/uploads/:userId/:uuid.jpeg Worker->>Worker: Read binary stream into ArrayBuffer Worker->>R2: env.pramio_media.put(key, data, { contentType }) Worker-->>Sanitizer: 200 OK { status: "ok", url } Sanitizer->>Sanitizer: Image attachment added to case draft

Pipeline 3: Clinical Case Creation and Feed Delivery Pipeline

Clinical cases require at least one attached medical photograph and doctor privacy attestation. Feed queries join post entries with verified doctor profiles and format all dates into ISO 8601 UTC strings.

Figure 4: Case Posting and Feed Delivery Sequence
sequenceDiagram autonumber participant Author as Verified Doctor participant Worker as Cloudflare Worker participant D1 as Cloudflare D1 participant Reader as Feed Readers (Doctors) Author->>Worker: POST /api/v1/posts
{ type: "case", body, specialty, imageUrls: [...], anonymizationAttested: true } Worker->>D1: INSERT INTO posts (id, authorId, type, body, specialty, imageUrls, ...) Worker-->>Author: 201 Created (Formatted Case Record) Reader->>Worker: GET /api/v1/feed?specialty=Dermatology Worker->>D1: SELECT p.*, pr.fullName, pr.photoUrl FROM posts p LEFT JOIN profiles pr ON p.authorId = pr.userId Worker->>Worker: Format timestamps via toIsoString() (YYYY-MM-DDTHH:MM:SSZ) Worker-->>Reader: 200 OK { items: [...], nextCursor: null }

Pipeline 4: Continuing Medical Education (CME) Credit Tracking

The CME subsystem tracks category credit hours toward the mandatory 30-hour requirement over a rolling 5-year council window.

Figure 5: CME Credit Ingestion and Window Calculation
sequenceDiagram autonumber participant Doctor as Doctor participant Worker as Cloudflare Worker participant D1 as Cloudflare D1 Doctor->>Worker: GET /api/v1/cme Worker->>D1: SELECT * FROM cme_credits WHERE userId = ? ORDER BY earnedOn DESC Worker->>Worker: Compute Category 1 and Category 2 totals Worker->>Worker: Calculate 5-year rolling completion percentage Worker-->>Doctor: 200 OK { creditsEarned, creditsRequired: 30, windowEnds, entries } Doctor->>Worker: POST /api/v1/cme/credits { title, provider, creditHours, category, earnedOn } Worker->>D1: INSERT INTO cme_credits (...) Worker-->>Doctor: 201 Created { id }

Pipeline 5: Direct Doctor-to-Doctor Messaging

Peer messaging connects verified doctors within their specialty networks. Threads and individual messages are recorded in Cloudflare D1.

Figure 6: Messaging Sequence
sequenceDiagram autonumber participant Sender as Doctor A participant Worker as Cloudflare Worker participant D1 as Cloudflare D1 participant Recipient as Doctor B Sender->>Worker: POST /api/v1/conversations { peerId } Worker->>D1: INSERT INTO conversations (id, participant1, participant2) Worker-->>Sender: 201 Created { conversationId } Sender->>Worker: POST /api/v1/conversations/:id/messages { body } Worker->>D1: INSERT INTO messages (id, conversationId, senderId, body, createdAt) Worker-->>Sender: 201 Created { message } Recipient->>Worker: GET /api/v1/conversations/:id/messages Worker->>D1: SELECT * FROM messages WHERE conversationId = ? ORDER BY createdAt ASC Worker-->>Recipient: 200 OK [messages]

4. Relational Database Schema (Cloudflare D1)

The relational database runs on Cloudflare D1 (Postgres/SQLite syntax). All critical tables are indexed by foreign keys and created timestamps.

-- Doctor Profiles
CREATE TABLE profiles (
  userId TEXT PRIMARY KEY,
  fullName TEXT NOT NULL,
  photoUrl TEXT,
  specialty TEXT NOT NULL,
  qualifications TEXT,
  workplace TEXT,
  city TEXT,
  followerCount INTEGER DEFAULT 0,
  followingCount INTEGER DEFAULT 0,
  verified BOOLEAN DEFAULT 0,
  createdAt TEXT DEFAULT (datetime('now'))
);

-- Posts and Clinical Cases
CREATE TABLE posts (
  id TEXT PRIMARY KEY,
  authorId TEXT NOT NULL,
  type TEXT NOT NULL DEFAULT 'post',
  body TEXT NOT NULL,
  specialty TEXT NOT NULL,
  imageUrls TEXT,
  anonymizationAttested BOOLEAN DEFAULT 0,
  createdAt TEXT DEFAULT (datetime('now'))
);

-- Doctor Registrations and Verifications
CREATE TABLE verifications (
  id TEXT PRIMARY KEY,
  userId TEXT NOT NULL,
  track TEXT NOT NULL,
  regNumber TEXT NOT NULL,
  regCouncil TEXT NOT NULL,
  docUrl TEXT,
  status TEXT DEFAULT 'pending',
  decidedAt TEXT,
  createdAt TEXT DEFAULT (datetime('now'))
);

-- CME Credits
CREATE TABLE cme_credits (
  id TEXT PRIMARY KEY,
  userId TEXT NOT NULL,
  title TEXT NOT NULL,
  provider TEXT,
  creditHours REAL NOT NULL,
  category TEXT NOT NULL,
  earnedOn TEXT NOT NULL,
  certificateUrl TEXT,
  createdAt TEXT DEFAULT (datetime('now'))
);

-- Conversations and Messages
CREATE TABLE conversations (
  id TEXT PRIMARY KEY,
  participant1 TEXT NOT NULL,
  participant2 TEXT NOT NULL,
  createdAt TEXT DEFAULT (datetime('now'))
);

CREATE TABLE messages (
  id TEXT PRIMARY KEY,
  conversationId TEXT NOT NULL,
  senderId TEXT NOT NULL,
  body TEXT NOT NULL,
  createdAt TEXT DEFAULT (datetime('now'))
);

5. Security and Privacy Safeguards