1. ⚙️ Tech Stack
Decisions dgn rationale. Reuse existing ALESA foundation maxima — bukan re-invent.
Foundation (LIVE · reuse from existing ALESA infra)
Laravel 11
Filament 3
MariaDB 10.6+
LiteSpeed Ent
Tailwind 3
Alpine.js
PHP 8.2
Rationale: medix.alesa.my + medic.alesa.my dah running on stack ni. 86 jadual + 76 model + 6 AI service LIVE. Build atop, jangan rebuild.
Agent Runtime (NEW for MediEco)
Python 3.12
FastAPI
LangGraph
MCP SDK (Python)
Pydantic v2
Celery + Redis
httpx async
Rationale: Python ecosystem matang untuk LLM/agent. LangGraph = state-machine paradigm cocok dgn workflow eco. MCP standard untuk tool registry.
LLM & Embedding
OpenAI gpt-4o-mini
Llama 3.1 70B Q5 (on-prem Hi-End)
Llama 3.1 8B FP16 (on-prem any tier)
Qwen 2.5-Med (clinical fine-tune option)
BGE-M3 (multilingual embed)
Whisper-Large v3 (BM/EN ASR)
vLLM (serving)
llama.cpp (edge/dev)
Rationale: Tier routing — small to 8B (fast/cheap), big to 70B atau OpenAI (cloud burst). vLLM untuk on-prem batching.
Memory & State
Redis 7 (working memory · cache · sessions)
PostgreSQL 16 (state · audit log)
pgvector (long-term memory)
MariaDB (clinical ops · existing)
S3-compat object storage (audio · DICOM cache · attachments)
Dual-DB rationale: MariaDB untuk clinical ops (Filament + Laravel reuse). PostgreSQL untuk state machine + audit + vector. Sync via event stream.
Comms & Integration
FHIR R4 (Patient · Encounter · MedicationRequest)
HL7 v2 (legacy lab/radiology bridge)
DICOMweb (QIDO/WADO)
WAHA (WhatsApp Business)
e-Invoice LHDN
REST + Webhook
WebSocket (live updates)
Twilio (SMS fallback)
DevOps & Observability
Git + GitHub
GitHub Actions CI
Docker
Docker Compose (dev)
Ansible (prod deploy)
OpenTelemetry
Loki + Grafana
Sentry
Vault (secrets)
Cloudflare (CDN + WAF)
Frontend
Tailwind 3
Alpine.js
Livewire 3
Filament 3 (admin)
Vite 5
PWA (manifest + service worker)
face-api.js (biometric — leverage Skool2U)
whisper.cpp (offline ASR option)
FullCalendar 6
ApexCharts
2. 📁 Repository Structure
Monorepo dgn folder modular. Setiap modul ada own folder + own owner.
medieco/ ├── README.md ├── docs/ │ ├── decisions/ # ADR (Architecture Decision Records) │ ├── runbooks/ # Ops runbooks per scenario │ ├── api/ # OpenAPI specs · MCP schemas │ └── modules/ # Per-module spec docs ├── apps/ │ ├── ops/ # Laravel 11 + Filament 3 (Doctor/Pharmacy/Admin UI) │ │ ├── app/ │ │ │ ├── Filament/ │ │ │ │ ├── Doctor/ # M4 Doctor PA panels │ │ │ │ ├── Pharmacy/ # M5 Pharmacy PA panels │ │ │ │ └── Admin/ # M7 Admin PA panels │ │ │ ├── Models/ │ │ │ ├── Services/ │ │ │ └── Http/ │ │ ├── database/migrations/ # Doc Zam 11-section Patient + ENC + RX schemas │ │ ├── resources/views/ │ │ └── routes/ │ ├── patient-pwa/ # Patient mobile PWA (separate Laravel + Livewire) │ │ ├── app/ │ │ ├── public/manifest.json │ │ └── public/sw.js │ └── agents/ # Python agent runtime │ ├── pyproject.toml │ ├── medieco/ │ │ ├── orchestrator/ # LangGraph state machines │ │ ├── agents/ │ │ │ ├── patient_pa.py # M1 │ │ │ ├── doctor_pa.py # M4 │ │ │ ├── pharmacy_pa.py # M5 │ │ │ ├── admin_pa.py # M7 │ │ │ └── triage_engine.py │ │ ├── memory/ # Redis · pgvector wrappers │ │ ├── guardrails/ # M9 PDPA · HITL · Hallucination │ │ └── tools/ # MCP tool implementations │ └── tests/ ├── mcp-medix/ # MCP server (FastAPI) │ ├── pyproject.toml │ ├── server.py # MCP protocol implementation │ ├── tools/ │ │ ├── clinical/ # cdss · ddi · symptom-dx · cpg-lookup │ │ ├── medication/ # npra-stock · dose-calc · halal-filter │ │ ├── patient/ # fhir-read · vital-stream · history-fetch │ │ ├── billing/ # icd10-code · einvoice-lhdn · claim-file │ │ ├── comms/ # waha-send · pager-api · sms-gw │ │ └── admin/ # audit-write · perm-check · feature-flag │ └── tests/ ├── infra/ │ ├── docker/ # Dockerfile per service │ ├── docker-compose.yml # Dev environment │ ├── docker-compose.prod.yml # Prod environment │ ├── ansible/ # Server provisioning │ │ ├── playbooks/ │ │ └── roles/ │ ├── terraform/ # Cloud burst infra (optional) │ └── k8s/ # Future: kubernetes manifests ├── shared/ │ ├── proto/ # Cross-app type definitions │ ├── constants/ # Shared enums (triage levels · ICD groups) │ └── fixtures/ # Test data · seed data ├── scripts/ │ ├── deploy.sh │ ├── backup.sh │ ├── rollback.sh │ └── db-migrate.sh ├── .github/ │ ├── workflows/ │ │ ├── ci.yml # Lint · test · build │ │ ├── cd-staging.yml │ │ └── cd-prod.yml │ ├── CODEOWNERS │ └── PULL_REQUEST_TEMPLATE.md ├── .env.example ├── .gitignore └── compose.override.yml.example
3. 🌿 Branch Strategy
Gitflow-lite. Trunk-based dgn release branches.
main # production-ready · auto-deploy ke prod ├── develop # integration · auto-deploy ke staging │ ├── feat/M1-patient-intake # feature branches per modul/sprint task │ ├── feat/M4-soap-scribe │ ├── feat/M9-audit-log │ ├── fix/issue-NNN │ └── chore/dep-bump ├── release/v0.1.0 # cut from develop · final QA · merge ke main + tag └── hotfix/critical-NNN # from main · merge to main + develop
| Branch | Purpose | Auto-deploy | Merge requirement |
|---|---|---|---|
main | Production source of truth | Prod (manual approval) | From release/* or hotfix/* · 2 reviews · all checks green |
develop | Integration · next release | Staging (auto) | From feat/* · 1 review · CI green |
feat/MX-name | Feature dev | Ephemeral preview env | PR → develop · 1 review |
release/vX.Y.Z | Release stabilisation | Staging final | QA sign-off · Doc Zam clinical review for clinical changes |
hotfix/critical-NNN | Production critical fix | Prod (after fix verify) | From main · expedited review · post-mortem required |
Conventional commits:
feat(M1):, fix(M5):, docs:, test:, chore:, refactor:. Per-module prefix WAJIB for traceability.
4. 🔌 API & MCP Contracts
4a. REST API (Laravel apps)
Versioned · OpenAPI documented · Bearer token auth · rate-limited.
POST /api/v1/auth/login # Sanctum token
POST /api/v1/auth/logout
GET /api/v1/me # current user
# Patient PA (M1)
POST /api/v1/patient/symptom/start # start intake session
POST /api/v1/patient/symptom/turn # add user message · receive AI reply
GET /api/v1/patient/symptom/{sessionId} # current state
POST /api/v1/patient/symptom/{sessionId}/escalate # human override
GET /api/v1/patient/clinics/nearby # M3 locator (lat/lng query)
POST /api/v1/patient/appointments # book appointment
# Doctor PA (M4)
GET /api/v1/doctor/encounters # today's queue
GET /api/v1/doctor/encounters/{id} # encounter detail
POST /api/v1/doctor/encounters # create new encounter
PATCH /api/v1/doctor/encounters/{id} # update SOAP fields
POST /api/v1/doctor/encounters/{id}/scribe # upload audio for SOAP
POST /api/v1/doctor/encounters/{id}/orders # create order set
POST /api/v1/doctor/encounters/{id}/prescription # create RX
POST /api/v1/doctor/encounters/{id}/sign-off # complete encounter
# Pharmacy PA (M5)
GET /api/v1/pharmacy/queue # ready/verifying/pending
POST /api/v1/pharmacy/{rxId}/verify # DDI + allergy check
POST /api/v1/pharmacy/{rxId}/dispense # mark dispensed
POST /api/v1/pharmacy/{rxId}/print-label # generate label PDF
# Admin PA (M7)
GET /api/v1/admin/queue # registration queue
POST /api/v1/admin/checkin/{patientId}
POST /api/v1/admin/billing/{encId}/submit-claim # MySalam/Socso/private
POST /api/v1/admin/billing/{encId}/einvoice # LHDN
# Audit (M9)
GET /api/v1/audit/logs # query audit trail
GET /api/v1/audit/logs/{id} # specific entry detail
4b. MCP Server (mcp-medix)
Standardised tool registry untuk agents. Setiap tool ada permission gate · audit · PII strip.
Tool Namespace Tool Name Description
─────────────────────────────────────────────────────────────────
clinical/ cdss Clinical Decision Support
ddx Differential diagnosis
symptom_classifier Triage colour
cpg_lookup MOH CPG retrieve
medication/ ddi_check Drug-Drug Interaction
dose_calc Dose-by-weight/eGFR
npra_stock Drug DB lookup
halal_filter Halal status check
generic_suggest Generic substitution
patient/ fhir_read Patient FHIR resource
history_search Vector similarity
vital_stream Real-time vital
face_match Biometric ID verify
imaging/ dicom_query Imaging worklist
report_template Auto-draft report
billing/ icd10_code Auto-code from SOAP
einvoice_lhdn LHDN submit
claim_filer MySalam/Socso/private
panel_rate Insurance rate sync
comms/ waha_send WhatsApp message
pager_api On-call pager
sms_gw SMS via Twilio
scheduling/ slot_find Available slots
noshow_predict No-show probability
resource_conflict Room/staff conflict
admin/ audit_write Append audit log
perm_check RBAC verify
feature_flag Toggle check
consent_check Patient consent verify
4c. MCP Tool Schema Example
{
"name": "ddi_check",
"description": "Check drug-drug interactions between proposed prescription and patient's current medication list.",
"inputSchema": {
"type": "object",
"properties": {
"patient_id": { "type": "string", "format": "uuid" },
"proposed_rx": {
"type": "array",
"items": {
"type": "object",
"properties": {
"drug_code": { "type": "string", "description": "NPRA code or RxNorm" },
"dose_mg": { "type": "number" },
"route": { "type": "string", "enum": ["po","iv","im","sc","topical"] }
}
}
}
},
"required": ["patient_id", "proposed_rx"]
},
"outputSchema": {
"type": "object",
"properties": {
"interactions": {
"type": "array",
"items": {
"type": "object",
"properties": {
"severity": { "enum": ["MINOR","MODERATE","MAJOR","CONTRAINDICATED"] },
"description": { "type": "string" },
"citation": { "type": "string", "description": "NPRA/Lexicomp/MOH CPG ref" },
"suggested_alternative": { "type": "string" }
}
}
},
"passed": { "type": "boolean" }
}
},
"permissions": ["patient:read", "medication:read"],
"audit": true,
"pii_strip": false
}
4d. Webhook Events (event bus)
patient.symptom.started { patient_id, session_id, ts }
patient.symptom.completed { patient_id, session_id, triage_color, summary }
patient.escalated { patient_id, session_id, reason, severity }
appointment.booked { appointment_id, patient_id, clinic_id, doctor_id, start_at }
encounter.created { encounter_id, patient_id, doctor_id, clinic_id }
encounter.briefing_ready { encounter_id, briefing_packet_url }
encounter.scribe_uploaded { encounter_id, audio_url, duration_sec }
encounter.soap_drafted { encounter_id, soap_id, draft_text }
encounter.signed_off { encounter_id, doctor_id, completed_at }
prescription.created { rx_id, encounter_id, drugs: [...] }
prescription.verified { rx_id, pharmacist_id, ddi_passed }
prescription.dispensed { rx_id, dispensed_at, label_url }
adverse.reaction.reported { patient_id, rx_id, symptom, severity }
billing.claim.submitted { encounter_id, claim_id, payer }
billing.einvoice.submitted { encounter_id, einvoice_id }
audit.alert { rule, severity, details, ts }
guardrail.blocked { agent, action, reason, escalated_to }
5. 🗄️ Database Schema
Doc Zam 11-section Patient Profile = canonical. Tables di MariaDB (clinical) + PostgreSQL (state · audit · vector).
5a. Patient (canonical 11-section · MariaDB)
Column
Description (Doc Zam mock alignment)
Type
id
Primary key (UUID)
UUID
mrn
Medical Record Number — format
{YYYY}-{6digit}VARCHAR(20)
tenant_id
Klinik tenancy
UUID FK
name_full
1) Master Profile · Patient Master
VARCHAR(120)
national_id
1) IC/Passport (encrypted)
VARCHAR(30)
dob
1) Date of Birth
DATE
gender
1) Gender enum (M/F/O)
ENUM
preferred_language
1) BM/EN
VARCHAR(10)
photo_id_url
1) Photo/Biometric ID storage path
VARCHAR(255)
face_embedding
1) face-api.js 128-dim vector (Skool2U pattern)
BLOB
contact_phone
2) Contact & Address Info
VARCHAR(30)
contact_email
2) Email
VARCHAR(120)
address_full
2) Full address (encrypted)
TEXT
emergency_name
3) Emergency Contact name
VARCHAR(120)
emergency_phone
3) Emergency Contact phone
VARCHAR(30)
emergency_relation
3) Relationship
VARCHAR(50)
pcp_name
4) Primary Care Provider name
VARCHAR(120)
pcp_clinic_id
4) Primary clinic FK
UUID FK
pcp_phone
4) PCP phone
VARCHAR(30)
insurance_carrier
5) AIA/MySalam/Socso/private
VARCHAR(60)
insurance_policy_no
5) Policy number
VARCHAR(60)
insurance_group_no
5) Group number
VARCHAR(60)
insurance_coverage_type
5) Outpatient/Inpatient/Both
ENUM
consent_treatment
5) Treatment consent boolean + ts
BOOLEAN, TS
consent_data_share
5) Cross-clinic share consent
BOOLEAN, TS
consent_notifications
5) WAHA/SMS consent
BOOLEAN, TS
chronic_conditions
6) JSON array of chronic dx codes
JSON
current_diagnoses
6) JSON array of active dx
JSON
created_at · updated_at
Timestamps
TIMESTAMP
5b. Related Tables (separate normalised)
| Table | Purpose | Doc Zam section | Key fields |
|---|---|---|---|
patient_allergies | Allergies & alerts | 7 | patient_id, type (med/food/other), substance, severity, reported_at, source |
patient_medications | Current med list | 8 | patient_id, drug_code, dosage, frequency, start_date, end_date, status |
patient_vitals | Vital signs over time | 9 | patient_id, encounter_id?, bp_sys, bp_dia, hr, rr, temp, weight, spo2, recorded_at |
encounters | Visit/Encounter History | 10 | id (ENC-YYYY-MMDD-NNN), patient_id, doctor_id, clinic_id, start_at, end_at, reason, status, soap_id |
soap_notes | SOAP for each encounter | 10 | encounter_id, subjective, objective, assessment, plan, scribe_audio_url, draft_by, signed_by |
care_plans | Care Plan / Management | 11 | patient_id, active_goals, key_actions, treatment_plan, owner_id, started_at |
prescriptions | RX records | — | id, encounter_id, prescriber_id, status, items[], pharmacist_id, dispensed_at |
prescription_items | RX line items | — | rx_id, drug_code, dosage, route, frequency, duration, halal_status |
appointments | Appointments | — | id, patient_id, clinic_id, doctor_id?, start_at, end_at, status, source (PA/walk-in/web) |
audit_log | M9 mandatory audit (PostgreSQL) | Governance | id, ts, user_id, agent_id?, action, resource, before_state, after_state, ip, ua, request_id |
memory_vector | Per-patient pgvector store | — | patient_id, content_chunk, embedding (vector(1024)), source, created_at |
cpg_library | MOH CPG citation library | — | cpg_id, title, version, published_at, pdf_url, embedding |
drugs_npra | NPRA drug DB mirror | — | npra_code, generic_name, brand_name, halal_status, schedule_class |
clinics | Clinic directory (M3) | — | id, tenant_id, name, address, lat, lng, phone, hours_json, services_json |
consent_log | Per-action consent record | — | patient_id, action_type, consented_at, scope, expires_at, withdrawn_at |
feature_flags | M9 feature toggle | — | flag_key, tenant_id, enabled, set_by, set_at, reason |
adverse_events | M6 adverse reaction log | — | patient_id, rx_id, symptom, severity, reported_at, broadcast_to[] |
5c. Indexing Strategy
- B-tree:
patient.mrn,encounter.start_at,audit_log.ts - Composite:
(tenant_id, mrn),(patient_id, start_at) - Vector:
memory_vector.embedding(HNSW pgvector) - Geo:
clinics(lat, lng)via PostGIS or KD-tree - Encryption: PII columns dgn AES-256 at rest · key dlm Vault
6. 🤖 Agent Specifications
Setiap PA = LangGraph state machine + tool set + memory tier + guardrail layer.
M1 · Patient Symptom PA
Mobile PWA frontend · BM/EN intake · 3-warna triage
State machine: intake → clarify → triage → recommend → (escalate | book | self-care)
Tools:
symptom_classifier, cpg_lookup, slot_find, waha_sendMemory: Working (Redis · 24h TTL) + Patient long-term (pgvector)
Guardrails: red-flag auto-escalate · citation mandatory · NEVER prescribe
Model: Llama 8B (default) · gpt-4o-mini (cloud burst)
M4 · Doctor PA
Filament desktop UI · 6-tab Quick Access · ambient SOAP
State machine: briefing_ready → review → scribe → soap_draft → orders → sign_off
Tools:
ambient_scribe, cdss, ddx, history_search, order_builder, cpg_lookupMemory: Working + Patient + Episodic (similar cases) + Procedural (CPG)
Guardrails: HITL on all orders · citation card per suggestion · DDx alternatives shown
Model: Llama 70B (clinical reasoning) · Whisper-Large (audio)
M5 · Pharmacy PA
Pharmacy POS UI · DDI · halal · dispense
State machine: verify_request → ddi_check → allergy_check → dose_check → halal_check → dispense → counsel
Tools:
ddi_check, dose_calc, halal_filter, npra_stock, generic_suggestMemory: Working + Patient (allergy/med history)
Guardrails: closed-loop verify · barcode at dispense · pharmacist final approve · adverse loop M6 trigger
Model: Llama 8B (rule-based heavy)
M7 · Admin PA
Admin desktop UI · queue · billing · WAHA
State machine: register → queue → triage_priority → check_in → encounter → billing → claim_submit
Tools:
slot_find, noshow_predict, waha_send, icd10_code, einvoice_lhdn, claim_filerMemory: Working + Patient (visit history)
Guardrails: claim accuracy verify · LHDN format check · staff override always permitted
Model: Llama 8B (mostly rule-based + classification)
6a. Prompt Strategy (per agent)
System Prompt structure:
1. ROLE · "You are a [PA name] in MediEco hospital agentic eco-system."
2. SCOPE · "You ONLY handle [domain]. You DO NOT [excluded actions]."
3. CONSTRAINTS · "All medical suggestions MUST cite source from {NPRA, MOH CPG, hospital SOP}.
NEVER make a final clinical decision. Always defer to human clinician via HITL."
4. CONTEXT · {{patient_summary}} {{cpg_excerpts}} {{patient_history_top_5}}
5. TOOLS AVAILABLE · {{mcp_tool_list}}
6. OUTPUT FORMAT · Strict JSON dgn schema:
{ "action": "...", "rationale": "...", "citations": ["..."], "confidence": 0.85, "human_approval_needed": true }
7. SAFETY · "If anything looks like emergency (chest pain + dyspnea, stroke signs, etc.),
output action='ESCALATE_999' immediately."
User Prompt:
{{user_message}}
{{conversation_history}}
7. 🎨 Frontend Architecture
Browser-first PWA · 4 role-based shells · zero-install.
📱 Patient PWA
• Standalone Laravel + Livewire app
• Manifest + Service Worker (offline cache)
• Push notifications (web push API)
• Camera/mic permission (selfie + voice symptom)
• face-api.js for biometric login (optional)
• WhatsApp deep-link fallback
🩺 Doctor (Filament)
• Filament 3 panel · 6-tab Quick Access
• Encounter detail view (Doc Zam mock)
• Audio capture (WebRTC) · streaming ke server
• SOAP draft live preview · edit-and-approve
• Order set composer (CDSS-suggested)
• Dashboard widgets (today's queue · vitals chart)
💊 Pharmacy (Filament)
• Filament 3 pharmacist panel
• Prescription queue · DDI alert cards
• Barcode scanner integration
• Label printer (Zebra · BPL emit)
• Dispense workflow · counsel checklist
🏢 Admin (Filament)
• Filament 3 admin panel
• Registration counter (Doc Zam mock layout)
• Queue board · drag-to-reorder
• WAHA reminder cascade · no-show predictor
• Billing · panel claim submit · e-Invoice
• Reports · daily KPIs · revenue breakdown
7a. Design System
- Colour palette: based on Doc Zam mock (blue/teal primary · emerald/violet accents)
- Typography: SF Pro Text / Inter (UI) · JetBrains Mono (code/IDs)
- Component library: Tailwind UI patterns + Filament 3 components
- Icons: Heroicons + healthcare-specific custom set
- Accessibility: WCAG 2.1 AA · keyboard navigation · screen reader labels
- Mobile responsive: tested 320-768-1024-1440-1920px breakpoints
8. 🔄 DevOps Pipeline
8a. Environments
| Env | Purpose | Branch | URL | Deploy trigger |
|---|---|---|---|---|
| Dev | Per-engineer local | feat/* | localhost:8000 | docker-compose up |
| Preview | Per-PR ephemeral | feat/* | pr-NNN.medieco.dev | GitHub Actions on PR open |
| Staging | Integration · QA · Doc Zam review | develop | staging.medieco.alesa.my | Auto on develop push |
| Prod | Pilot klinik live | main | medieco.alesa.my (private) · client subdomains | Manual approval after main merge |
8b. CI Pipeline (.github/workflows/ci.yml)
on: [push, pull_request]
jobs:
lint:
- php-cs-fixer (PSR-12)
- phpstan (level 8)
- eslint + prettier
- ruff (Python)
- mypy (Python strict)
test:
- phpunit (Laravel · >75% coverage)
- pytest (agents · >80% coverage)
- playwright (E2E 3 patient scenarios)
- schema migrations check (no breaking change)
security:
- composer audit
- npm audit
- pip-audit
- trivy scan (Docker images)
- secrets scan (gitleaks)
build:
- docker build (cached layers)
- tag with sha + branch
- push to ALESA registry
8c. CD Pipeline
Staging (auto · on develop merge): 1. ansible-playbook deploy-staging.yml 2. db:migrate (no-op if no new migrations) 3. cache:clear 4. opcache:reset (web request trigger per ALESA OLS pattern) 5. smoke test (health endpoints · login · 1 patient flow) 6. notify Slack/WhatsApp Prod (manual · post-Q-gate): 1. backup db (mariadb-dump + postgres pg_dump) 2. backup current code (rsync to /home/alesa/backups/medieco-VYYYY.tgz) 3. ansible-playbook deploy-prod.yml --check (dry run) 4. operator approval prompt 5. ansible-playbook deploy-prod.yml --apply 6. db:migrate --force 7. cache:clear · opcache:reset 8. smoke test 9. canary: 10% traffic to new build · monitor 15 min 10. gradual cutover · or rollback if SLO breach
9. 👁️ Observability
Logs (Loki)
Structured JSON · per-request trace_id · PII-stripped · 7-yr retention untuk audit_log channel
Traces (OpenTelemetry)
Distributed across Laravel + Python agent + MCP server · spans for LLM calls + tool calls + DB queries
Metrics (Prometheus)
RED metrics (Rate · Errors · Duration) per endpoint + per agent · LLM token usage · GPU utilisation
Errors (Sentry)
Exception capture · auto-grouping · alert via Slack · breach SLO triggers Pagerduty
Dashboards (Grafana)
SLO board · per-modul KPI · pilot health · GPU thermal · queue depth
Alerts
p99 latency >5s · error rate >1% · audit log write fail · feature flag drift · GPU temp >80°C
10. 🔒 Security Model
🔴 Auth & AuthZ
- Patient: SMS OTP login + face-api biometric optional
- Staff (Doctor/Pharmacy/Admin): email + password + TOTP 2FA mandatory
- Sanctum tokens (Laravel) · 24h expiry · refresh rotation
- RBAC: 6 roles (super_admin · clinic_admin · doctor · pharmacist · receptionist · patient)
- Per-tenant scope · cross-tenant access audit-flagged
- Session timeout 30min idle · concurrent session limit 2 per user
🟠 PII Handling
- 12 PII fields encrypted at rest (AES-256) — IC, name, address, phone, email, etc.
- PII strip middleware before LLM call (regex + NER hybrid)
- De-identification untuk analytics/training data
- Data subject access (DSAR) · 30-day SLA · machine-readable export
- Right to erasure · cascade soft-delete + audit trail · MOH-required retention exception
- Cross-clinic share (M8) · explicit per-action consent · audit each access
🟢 Network & Infra
- TLS 1.3 only · HSTS preloaded
- Cloudflare WAF · rate limiting · bot mitigation
- VPN access untuk admin panel · IP allowlist
- Secrets di Vault · rotation policy 90-day
- Container scanning per build (Trivy)
- Quarterly penetration test (3rd party · Phase 3+)
11. 🧪 Testing Strategy
| Tier | Coverage Target | Tools | Cadence |
|---|---|---|---|
| Unit | ≥75% (PHP) · ≥80% (Python) | PHPUnit · Pytest | Per commit |
| Integration | All API endpoints · all MCP tools | PHPUnit · Pytest + httpx | Per PR |
| E2E | 3 patient scenarios + 4 PA workflows | Playwright | Per PR + nightly |
| Clinical Safety | Red-flag escalation · DDI · allergy · dose paeds | Custom test harness · Doc Zam clinical scenarios bank | Per release |
| Load/Stress | 200 concurrent · 1500 tok/s sustained | k6 · locust | Pre-pilot · pre-prod |
| Security | OWASP Top 10 · SAST · DAST | Trivy · Snyk · ZAP | Weekly + per release |
| Accessibility | WCAG 2.1 AA | axe-core · pa11y | Per major UI change |
| UAT | Klinik staff + sample patient cohort | Manual + survey | Pre-pilot · per release |
| Chaos | Failure injection (DB down · LLM timeout · GPU OOM) | Chaos Mesh / manual | Quarterly |
12. 📐 Coding Standards
- PHP: PSR-12 · php-cs-fixer auto-fix on commit · phpstan level 8
- Python: PEP 8 + ruff · type hints mandatory · mypy strict
- JS/TS: eslint + prettier · TypeScript strict
- SQL: Migrations only via Laravel/Alembic · NEVER manual ALTER on prod
- Naming: snake_case (DB · Python) · camelCase (PHP method) · PascalCase (Class)
- Comments: WHY not WHAT · only when non-obvious · no commented-out code in main
- Test naming:
test_should_X_when_Y - Commit messages: Conventional Commits (feat/fix/docs/test/chore/refactor)
- PR template: context · changes · test plan · screenshots · breaking changes
- Code review: 1 approval required (2 untuk security/clinical changes)
- No direct push to main/develop · feature branches mandatory
- No skip hooks (--no-verify) tanpa explicit approval
13. 🏃 Sprint Cadence
Sprint Length
2 minggu · Ahad → Sabtu (Malaysia week pattern)
Sprint Ceremonies
- • Day 0 (Sun PM): Sprint Planning · 90 min · backlog grooming
- • Daily: Async standup dlm Slack/WhatsApp (text · 3 lines per person)
- • Day 7 (mid-sprint): Optional sync · 30 min
- • Day 13 (Fri AM): Sprint Review/Demo · 60 min · Doc Zam attend
- • Day 13 (Fri PM): Retrospective · 45 min · process improvement
Velocity Tracking
Story points (Fibonacci 1-13) · target velocity to be calibrated after Sprint 1.1
Backlog Tooling
GitHub Issues + Projects (kanban) · labels per modul (M1-M9) · milestones per sprint