DIVCAAS
Diving Competency Assessment & Assurance Scheme
Complete System Documentation
1. What is DIVCAAS?
DIVCAAS is a full competency assessment and assurance platform built entirely as a static web application — no backend server required. It implements the IMCA C003 Revision 3.3 (September 2025) standard, the international competency framework for offshore diving personnel.
The system manages the complete lifecycle of a diver's competency journey — from initial onboarding through portfolio evidence building, workplace assessment, unit sign-off, certificate issuance, and public verification — all within a secure, multi-tenant environment.
Core Purpose: To provide diving companies with a digital, IMCA-aligned competency assurance system that manages all 12 diving roles, replaces paper-based portfolios, and produces verifiable digital certificates — while keeping each organisation's data completely private and isolated from all other organisations using the same platform.
Platform Architecture at a Glance
| Layer | Technology | Purpose |
| Frontend | HTML5, CSS3, Vanilla JavaScript | All UI, logic, rendering |
| Database | Supabase (PostgreSQL) | All data storage and retrieval |
| Hosting | Cloudflare Pages | Global CDN, zero-downtime deploy |
| Email | EmailJS | Client-side email notifications |
| QR Codes | qrcodejs CDN + api.qrserver.com | Certificate verification QR |
| PWA | Service Worker | Offline capability, install prompt |
| Security | Cloudflare Headers + SHA-256 | CSP, HSTS, password hashing |
2. IMCA Roles Supported (D01–D12)
All 12 IMCA C003 diving roles are fully supported. Each role has its own unique set of competency units, performance criteria, knowledge requirements, and evidence types — encoded verbatim from the IMCA C003 standard.
| Code | Role Title | Standard Reference |
| D01 | Diving Superintendent | IMCA C 003 / D01 |
| D02 | Bell Diving Supervisor | IMCA C 003 / D02 |
| D03 | Air (Surface Supplied) Diving Supervisor | IMCA C 003 / D03 |
| D04 | Bell (Saturation) Diver | IMCA C 003 / D04 |
| D05 | Air (Surface Supplied) Diver | IMCA C 003 / D05 |
| D06 | Life Support Supervisor | IMCA C 003 / D06 |
| D07 | Life Support Technician | IMCA C 003 / D07 |
| D08 | Assistant Life Support Technician (ALST) | IMCA C 003 / D08 |
| D09 | Tender | IMCA C 003 / D09 |
| D10 | Senior Dive Technician (All Systems) | IMCA C 003 / D10 |
| D11 | Senior Dive Technician (Surface Supplied Only) | IMCA C 003 / D11 |
| D12 | Dive Technician | IMCA C 003 / D12 |
Evidence Types Supported
| Code | Evidence Type | Code | Evidence Type |
| LOG | Logbook / CV | WPA | Workplace Assessment |
| WT | Witness Testimony | CERT | Certificate / Qualification |
| WR | Work Record | MED | Medical Certificate |
| DRILLS | Drill Record | PHOTO | Photograph / Video |
| EOT | End of Trip Report | OR | Observation Record |
| APP | Performance Appraisal | QR | Questioning Record |
| DEMO | Demonstration Record | CT | Candidate Testimony |
3. The Five Portals
| Portal | URL | Who Uses It | Auth Required |
| Candidate Portfolio |
portfolio.html |
Divers and technicians building their evidence portfolio |
Login |
| Admin Dashboard |
admin.html |
Diving company admin — manages candidates, issues certificates |
Login |
| Assessor Portal |
assessor.html |
IMCA qualified assessors conducting workplace assessments |
Login |
| Observer / Verifier View |
observer.html |
Read-only view for verifiers and third parties |
Login |
| Certificate Verification |
verify.html |
Anyone scanning a certificate QR code — public |
Public |
| Master Admin Panel |
master-admin.html |
DIVCAAS platform operator — manages all tenants |
Restricted |
4. Complete Feature List
4.1 Authentication System
🔐 Login & Registration
- Email or Diver ID login
- SHA-256 password hashing (Web Crypto API)
- Password strength checker (5-level score)
- Show/hide password toggle
- Dual-role accounts (candidate + assessor)
- Invite-only registration
- Auto-login from saved session
🔑 Password Recovery
- In-app OTP (6-digit code shown on screen)
- No email-based reset — security by design
- Admin can reset candidate passwords
- Password change from within portal
- Offline login using cached profile
- Session persistence via localStorage
4.2 Candidate Portfolio App
📋 Competency Management
- Role-specific unit grid (auto-built per IMCA role)
- Entry criteria tracking per unit
- Performance criteria tracking
- Progress bar per unit (% complete)
- 3-gate completion check
- Unit status indicators
📁 Evidence Management
- 14 built-in evidence types
- Custom evidence types (user-defined)
- Evidence filtering by type
- Document descriptions and dates
- File reference tracking
- Photo/video evidence capture
✍️ Signatures & Sign-Off
- Canvas-based digital signature pads
- Unit sign-off workflow
- Assessor signature per unit
- Verifier second-level sign-off
- Signature date and timestamp
🔄 Sync & Offline
- Real-time background sync (polling)
- Full offline mode (Service Worker)
- localStorage cache fallback
- PWA install prompt
- Portfolio sharing with other users
4.3 Admin Dashboard
👥 Candidate Management
- Full candidate list with search and filter
- Access approval / rejection workflow
- Invitation link generation per role
- Role change for candidates
- Account deactivation
- Password reset for candidates
🎓 Certificate Management
- Certificate issuance and approval
- Canvas-rendered A4 certificate preview
- Admin digital signature on certificate
- Certificate number generation
- 5-year expiry date calculation
- Certificate revocation
🔧 Operations
- Assessor assignment to candidates
- Bulk operations (approve, reject, assign)
- Expiry alerts management
- Audit trail viewer
- Admin account management
- Report generation per candidate
📊 Dashboard Overview
- Active candidates count
- Pending approvals count
- Certificates issued count
- Units signed off count
- In-app notification inbox
- Recent activity feed
4.4 Assessor Portal
📝 Assessment Workflow
- Assigned candidates list
- Unit-by-unit portfolio review
- Performance criterion sign-off (pass/fail)
- Oral questioning records
- Workplace Assessment (WPA) forms
- Assessor comments per unit
✅ Verification
- Evidence document review
- Digital signature per unit sign-off
- Second-level verifier workflow
- Portfolio submission for approval
- Shared inbox for notifications
- Assessment history per candidate
4.5 Certificate System
The certificate is rendered entirely on an HTML5 Canvas — no PDF library, no server-side rendering. Every element is drawn programmatically.
🏅 Certificate Content
- Candidate full name and Diver ID
- IMCA role and full role title
- Employer name
- IMCA standard reference
- Issue date and 5-year expiry date
- Certificate number (DVS-[Name]-[ID]-[MMYYYY])
🎨 Certificate Design
- A4 landscape canvas (1122×794px)
- DIVCAAS logo watermark
- Professional border and page texture
- Admin authorised-by block
- Admin digital signature image
- QR code with verify URL
📱 QR Code (3-Strategy System)
- Strategy 1: qrcodejs library (synchronous)
- Strategy 2: api.qrserver.com API (async fallback)
- Strategy 3: placeholder (offline)
- Verify URL: divcaas.com/verify.html?cert=CERTNO
- QR cache to prevent re-fetching
- Canvas taint guard for export safety
🖨️ Export & Print
- Print window with full CSS print layout
- Canvas export to PNG (toDataURL)
- A4 landscape print optimisation
- Popup-blocked detection and warning
- Browser print → PDF workflow
4.6 Certificate Designer
A fully featured drag-and-drop certificate template designer allowing admins to create custom branded certificates with full layout control.
🎨 Design Tools
- Drag-and-drop canvas elements
- Text, image, and shape elements
- Font, size, colour, alignment controls
- Background colour/image customisation
- Element layering (z-index)
- Undo / redo history
💾 Template Management
- Save templates to database
- Load saved templates
- Issue live certificates from designer
- QR code embedded automatically
- Admin login gate (shared session)
- Sign-out without clearing session
4.7 Certificate Verification
A fully public page — no login required. Accessible to anyone who scans a QR code on a printed certificate or visits the verify URL directly.
🔍 Verification Features
- Enter certificate number manually
- Scan QR code (opens URL with cert param)
- Shows candidate name, role, issue date, expiry
- Shows VALID / EXPIRED / NOT FOUND status
- Global query — works across all tenants
- No private data exposed — public info only
4.8 Competence Management System (CMS)
A full IMCA-aligned CMS with 7 structured sections covering the complete organisational competence management lifecycle.
| # | Section | Content |
| 1 | Policy & Governance | Competence policy documents, governance framework |
| 2 | Roles & Responsibilities | Role definitions, accountability matrix |
| 3 | Competency Standards | IMCA C003 standard reference, role standards |
| 4 | Assessment Process | Assessment procedures, WPA forms, oral questioning guides |
| 5 | Record Keeping | Evidence records, portfolio management, retention policy |
| 6 | Review & Improvement | Periodic review cycles, improvement tracking |
| 7 | Audit & Compliance | Internal audit tools, compliance checklists, IMCA alignment |
4.9 Notification Engine
Client-side email notifications via EmailJS — no SMTP server required. 15+ event types with fully formatted HTML email templates.
| Event | Triggered When | Recipients |
| Access Request | Candidate registers and awaits approval | Admin |
| Access Approved | Admin approves a candidate account | Candidate |
| Access Rejected | Admin rejects a candidate account | Candidate |
| Certificate Issued | Admin issues a certificate | Candidate |
| Certificate Approved | Certificate approval confirmed | Candidate + Admin |
| Unit Signed Off | Assessor signs off a unit | Candidate + Admin |
| Assessment Completed | All units assessed | Admin |
| Portfolio Shared | Candidate shares portfolio | Recipient |
| Admin User Added | New admin account created | New Admin |
| Expiry Alert (30/60/90d) | Certificate approaching expiry | Candidate + Admin |
4.10 Supporting Systems
📊 Analytics & Tracking
- Observer analytics (charts, stats, timelines)
- Usage tracking (page views, session duration)
- Activity tracker (login, logout, actions)
- Progress calculations and gate checks
🌍 Internationalisation
- i18n structure for English, Arabic, French
- Per-tenant language setting
- RTL support structure (Arabic)
- String replacement engine
🎨 Branding
- Per-tenant logo upload
- Custom colour scheme per tenant
- Company name and contact details
- Applied globally across all portals
🔒 Audit & Compliance
- Full audit trail logging
- Who did what and when
- Bulk operation logging
- Certificate issuance audit records
📱 PWA & Offline
- Service Worker for offline caching
- Install to home screen prompt
- Background sync when reconnected
- Offline login with cached profile
🔊 UI Experience
- UI sound effects (success, error, notification)
- In-app notification inbox
- Document preview modal
- Camera access for photo evidence
5. Assessment-to-Certificate Process
The following describes the complete logical flow from a candidate joining the system through to receiving their Certificate of Competence and generating their portfolio report.
- Admin creates an invitation link for a specific IMCA role (e.g. D02 Bell Diving Supervisor)
- Candidate opens the invite link — name, role and employer are pre-filled from the invitation
- Candidate sets a password — account created in
profiles table with SHA-256 hashed password
- Access request created in
user_access table with status = pending
- Admin receives notification: "New access request from [Candidate Name]"
- Admin reviews and either Approves or Rejects the request
- If approved →
user_access.status = approved → candidate can log in
- Candidate receives approval notification by email
- Candidate logs in →
portfolio.html loads their role-specific competency unit grid from js/data.js
- For each competency unit, the candidate works through three tabs:
- Entry Criteria tab: Tick each criterion as attained, add evidence reference and date → saved to
entry_criteria table
- Assessment Items tab: Mark knowledge and performance criteria → saved to
assessments table
- Evidence tab: Upload evidence documents, select type (LOG, WPA, CERT, etc.), add description and date → saved to
evidence table
- Progress bar updates per unit showing % of criteria met
- Digital signature can be added to relevant sections via canvas signature pad
- Admin assigns a qualified assessor to the candidate via the Admin Dashboard
- Assessor logs in →
assessor.html → sees their assigned candidates
- Assessor opens the candidate portfolio and reviews unit by unit:
- Reviews all evidence documents submitted by the candidate
- Conducts workplace observation and records findings in WPA form
- Conducts oral questioning and records responses
- For each unit: marks each performance criterion as PASS or FAIL
- Adds assessor comments per unit for the record
- Digitally signs the unit sign-off → saved to
assessments table with assessor_signed = true
- All units signed → portfolio is ready for the next stage
- A verifier (senior assessor or independent third party) reviews the completed portfolio
- Checks all assessor sign-offs, evidence quality, and oral questioning records
- Adds verifier signature as second-level confirmation
- Submits portfolio as ready for final admin approval
- This step follows IMCA C001 verifier guidelines and applies where required by the scheme
- Admin receives notification: "Portfolio ready for certificate issuance"
- Admin opens
admin.html → Certificates section → opens candidate record
- System checks three mandatory gates:
- Gate 1: All entry criteria attained ✅
- Gate 2: All assessment items completed ✅
- Gate 3: All units signed off by assessor ✅
- If all three gates pass → "Issue Certificate" button becomes active
- Admin enters their name, title, and draws their digital signature
- System generates certificate number:
DVS-[Name3]-[DiverID]-[MMYYYY]
- Issue date = today; Expiry date = today + 5 years (auto-calculated)
- Certificate record saved to
certificate_approvals table
- Canvas renders the full A4 certificate with QR code embedded
- Print window opens — admin or candidate can print or save as PDF
- Candidate receives notification: "Your Certificate of Competence has been issued"
- Anyone scans the QR code printed on the certificate
- Browser opens:
https://divcaas.com/verify.html?cert=DVS-XXX-XXXXX
verify.html queries the certificate_approvals table globally (no tenant filter)
- If found and valid: shows ✅ VALID — Candidate Name, Role, Issued Date, Expiry Date
- If expired: shows ⚠️ EXPIRED with expiry date
- If not found: shows ❌ NOT FOUND
- No private data is ever exposed — only public certificate information
- Available at any stage of the process — not just after certification
- Admin or candidate triggers report generation from the dashboard
- Report rendered by
js/d02-portfolio-report.js (or role-specific variant)
- Full printable report includes:
- Candidate profile header: Name, Diver ID, role, employer, photo
- Entry criteria table per unit — attained/not attained status
- Performance criteria table per unit — with assessor results
- Evidence list — all submitted evidence with type, date, description
- Assessor sign-off records — signatures and dates
- Progress summary — overall completion percentage
- Certificate status — issued/pending with certificate number if applicable
- Print window opens → browser prints to PDF
Complete Process Flow Diagram
┌─────────────────────────────────────────────────────────────────────┐
│ DIVCAAS — ASSESSMENT TO CERTIFICATE FLOW │
└─────────────────────────────────────────────────────────────────────┘
ADMIN Creates invitation link for IMCA role (e.g. D02)
│
CANDIDATE Opens invite → registers → sets password
│
↓
user_access.status = 'pending'
│
ADMIN Reviews → APPROVES → user_access.status = 'approved'
│
CANDIDATE Logs in → Portfolio loads role-specific unit grid
│
├── Entry Criteria → tick attained → save to entry_criteria
├── Assessment Items → mark criteria → save to assessments
└── Evidence → upload docs → save to evidence
│
↓ (repeat for each unit)
ADMIN Assigns assessor to candidate
│
ASSESSOR Reviews portfolio unit by unit
├── Reviews evidence documents
├── Conducts workplace observation (WPA form)
├── Conducts oral questioning
└── Signs off each unit → assessor_signed = true
│
VERIFIER (Optional) Reviews and adds second-level signature
│
ADMIN Checks 3 gates:
├── Gate 1: All entry criteria attained? ✅
├── Gate 2: All assessment items done? ✅
└── Gate 3: All units signed by assessor? ✅
│
↓ All gates pass
Issues Certificate
├── Cert No: DVS-[Name3]-[DiverID]-[MMYYYY]
├── Issue date + 5-year expiry
├── Admin signature
├── QR code → divcaas.com/verify.html?cert=CERTNO
└── Print window → PDF
│
ANYONE Scans QR → verify.html → ✅ VALID / ❌ NOT FOUND
│
ADMIN/CAND Generate full portfolio report → PDF
6. Multi-Tenant Architecture & Data Isolation
This is the most sophisticated part of the DIVCAAS architecture. A single codebase and a single Supabase database serve every organisation independently and simultaneously with complete data isolation — no organisation can see or touch another's data.
6.1 How Tenant Detection Works
The tenant identity is derived purely from the subdomain of the URL — read automatically at page load. No cookie, no server session, no manual configuration needed.
| URL Visited | TENANT_ID Detected | Data Scope |
client1.divcaas.com | client1 | Only client1 data |
client2.divcaas.com | client2 | Only client2 data |
xyzco.divcaas.com | xyzco | Only xyzco data |
divcaas.com | master | Master tenant data |
*.genspark.ai | Genspark mode | Dev/sandbox — no filter |
6.2 The Fetch Interceptor — Core Isolation Mechanism
The key to the entire multi-tenant system is that js/api.js patches the global window.fetch function. Every network call made by every other JS file goes through this interceptor invisibly — no other file needs to know about tenants.
Any JS file calls: fetch(apiUrl('tables/profiles'))
↓
api.js INTERCEPTOR (patched window.fetch)
↓
┌────────────────────────────────────┐
│ 1. Add Supabase auth headers │
│ 2. Add tenant_id filter (GET) │
│ 3. Inject tenant_id into body │
│ (POST / PATCH) │
└────────────────────────────────────┘
↓
Supabase receives filtered query
↓
Returns ONLY that tenant's data
6.3 Read Isolation (GET Requests)
Every database read automatically appends a tenant filter to the query:
-- client1.divcaas.com reading profiles:
GET /profiles?tenant_id=eq.client1
-- client2.divcaas.com reading profiles:
GET /profiles?tenant_id=eq.client2
-- Result: client1 NEVER sees client2 data — impossible at query level
6.4 Write Isolation (POST / PATCH Requests)
Every database write automatically injects the correct tenant_id into the request body:
-- client1 creating a candidate profile:
POST /profiles
body: {
full_name: "John Smith",
imca_role: "D02",
tenant_id: "client1" ← injected automatically
}
-- The developer writing app.js does NOT need to know about tenant_id
-- api.js handles it silently for every single write operation
6.5 Global Tables (Intentional Exceptions)
Two tables bypass tenant filtering by design:
| Table | Why Global | Risk Level |
tenants | Master admin must see all organisations | Admin-only access |
admins | Login must find admin accounts across tenants | Password-protected |
Everything else — profiles, assessments, evidence, entry_criteria, certificate_approvals, user_access, notifications — is strictly tenant-isolated.
6.6 What Each Organisation Gets
DIVCAAS MULTI-TENANT ARCHITECTURE
divcaas.com (single Cloudflare Pages deployment)
│
┌────────────────┼────────────────────┐
│ │ │
client1.divcaas.com client2.divcaas.com client3.divcaas.com
TENANT_ID='client1' TENANT_ID='client2' TENANT_ID='client3'
│ │ │
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ XYZ Diving │ │ ABC Marine │ │ DEF Subsea │
│ Ltd data │ │ Ltd data │ │ Ltd data │
│ │ │ │ │ │
│ profiles │ │ profiles │ │ profiles │
│ assessments │ │ assessments │ │ assessments │
│ evidence │ │ evidence │ │ evidence │
│ certs │ │ certs │ │ certs │
└─────────────┘ └─────────────┘ └─────────────┘
│ │ │
└────────────────┴────────────────────┘
│
ONE Supabase DB
All rows in same tables
Isolated by tenant_id column
Auto-filtered by api.js
6.7 Data Privacy Scenarios
| Scenario | Result | Reason |
| Client A tries to read Client B's candidate list |
Impossible |
Query filtered to tenant_id=eq.clientA — returns zero rows |
| Client A admin logs into Client B's portal URL |
No data visible |
Their admin account's tenant differs from subdomain's tenant |
| Someone guesses a candidate's name from another company |
Zero results |
Search always appends tenant filter — cross-tenant search impossible |
| QR code scanned from a certificate (any tenant) |
Public cert info only |
verify.html global query returns only cert number, name, dates — no private data |
| Master admin views all tenants |
Full access |
master-admin.html uses unfiltered queries — protected by password + Cloudflare Access |
| Supabase database direct access |
Full access |
True admin layer — Supabase dashboard credentials must be protected |
6.8 Onboarding a New Organisation
Step 1: Master admin creates tenant record:
tenants table → { tenant_id: 'xyzco', company_name: 'XYZ Diving Ltd', plan: 'professional' }
Step 2: DNS configured:
xyzco.divcaas.com → Cloudflare Pages (same static site — no new deployment)
Step 3: Admin account created:
admins table → { username: '
[email protected]', tenant_id: 'xyzco', password_hash: SHA-256 }
Step 4: Organisation visits
xyzco.divcaas.com
→ TENANT_ID auto-detected as 'xyzco'
→ All data reads/writes automatically scoped to 'xyzco'
→ Complete isolation from all other organisations
→ Custom branding applied via js/branding.js
Result: Full independent DIVCAAS instance — zero code changes required
7. Database Schema
| Table | Key Fields | Purpose | Tenant Filtered |
| tenants |
tenant_id, company_name, plan, branding |
Organisation registry |
Global |
| admins |
id, username, password_hash, role, tenant_id |
Admin accounts and authentication |
Global |
| profiles |
id, full_name, email, diver_id, imca_role, password_hash, account_type, tenant_id |
Candidate profiles |
Isolated |
| user_access |
id, profile_id, status, reviewed_by, reviewed_at, tenant_id |
Approval workflow status |
Isolated |
| entry_criteria |
id, profile_id, unit_code, criterion_key, attained, evidence_ref, date_attained |
Entry criteria records per unit |
Isolated |
| assessments |
id, profile_id, unit_code, item_key, status, assessor_signed, assessor_name, signed_at |
Assessment and sign-off records |
Isolated |
| evidence |
id, profile_id, type_code, description, date, file_ref, tenant_id |
Evidence document records |
Isolated |
| certificate_approvals |
id, cert_number, candidate_name, diver_id, imca_role, issue_date, expiry_date, admin_sig_data, tenant_id |
Issued certificates |
Isolated |
| notifications |
id, profile_id, event_type, message, read, created_at, tenant_id |
In-app notification inbox |
Isolated |
| assessor_assignments |
id, assessor_id, candidate_id, assigned_by, tenant_id |
Assessor-to-candidate links |
Isolated |
| invitations |
id, token, role, invited_by, used, tenant_id |
Invite tokens for registration |
Isolated |
| share_requests |
id, sender_id, recipient_email, status, tenant_id |
Portfolio share requests |
Isolated |
| audit_log |
id, actor, action, target, timestamp, tenant_id |
Full audit trail |
Isolated |
| cert_templates |
id, name, template_data, created_by, tenant_id |
Certificate designer templates |
Isolated |
8. Security Architecture
| Security Layer | Implementation | Status |
| Password Hashing |
SHA-256 via Web Crypto API (crypto.subtle.digest) — no plaintext stored anywhere in source or database |
✅ Active |
| HTTPS / HSTS |
Strict-Transport-Security: max-age=63072000; includeSubDomains; preload |
✅ Active |
| Content Security Policy |
Full CSP with strict source allowlists — blocks XSS, inline injection |
✅ Active |
| Clickjacking Protection |
X-Frame-Options: DENY |
✅ Active |
| MIME Sniffing |
X-Content-Type-Options: nosniff |
✅ Active |
| Referrer Policy |
strict-origin-when-cross-origin |
✅ Active |
| Permissions Policy |
camera=(self), microphone=(), geolocation=() |
✅ Active |
| Tenant Data Isolation |
Automatic tenant_id filtering on all DB reads/writes via api.js fetch interceptor |
✅ Active |
| Admin Area Protection |
Cloudflare Access (Zero Trust) — planned for /private/ folder |
⏳ Pending Deploy |
| Mozilla Observatory Score |
Expected A / A- (85–100) after Cloudflare Pages deploy — was C- (45/100) |
⏳ Pending Deploy |
9. Technology Stack
🌐 Frontend
- HTML5 — semantic, accessible markup
- CSS3 — custom properties, grid, flexbox
- Vanilla JavaScript (ES2020+)
- No frontend framework (React, Vue, etc.)
- Canvas API for certificate rendering
- Web Crypto API for password hashing
- Service Worker API for PWA/offline
🗄️ Backend / Data
- Supabase (PostgreSQL) — cloud database
- PostgREST — automatic REST API from schema
- Supabase Anon Key — client-side auth
- Row-level isolation via tenant_id column
- No custom backend server
- No serverless functions
☁️ Hosting & CDN
- Cloudflare Pages — static site hosting
- Cloudflare CDN — global edge network
- Cloudflare Zero Trust — access control
- _headers file — HTTP security headers
- Automatic HTTPS on all subdomains
📦 Third-Party Libraries
- [email protected] — QR code generation
- api.qrserver.com — QR code fallback API
- EmailJS — client-side email sending
- Font Awesome — icons (jsDelivr CDN)
- Google Fonts — Inter typeface
- Chart.js — analytics charts
10. JavaScript Codebase Summary
Total: 30 JavaScript files · ~1.6 MB · approximately 35,000 lines of code · 100% client-side · zero backend
| File | Size | ~Lines | Responsibility |
| app.js | 250 KB | 5,600 | Main candidate portfolio application |
| obs-analytics.js | 245 KB | 5,500 | Observer analytics engine and charts |
| admin.js | 191 KB | 4,500 | Full admin dashboard logic |
| data.js | 155 KB | 3,500 | All IMCA competency data (12 roles, verbatim from C003) |
| cms.js | 80 KB | 1,800 | Competence Management System (7 sections) |
| d02-portfolio-report.js | 82 KB | 1,800 | Portfolio report renderer (PDF-style) |
| notify.js | 59 KB | 1,300 | Email notification engine (EmailJS) |
| auth.js | 46 KB | 1,000 | Login, registration, password reset, OTP |
| wpa-templates.js | 46 KB | 1,000 | Workplace Assessment form templates |
| assessors-admin.js | 35 KB | 800 | Assessor management and assignment |
| certificate.js | 37 KB | 800 | Certificate canvas renderer + QR system |
| signoff.js | 34 KB | 750 | Unit sign-off workflow engine |
| tracker.js | 28 KB | 600 | Activity tracker (login, logout, actions) |
| progress.js | 21 KB | 450 | Progress tracking and gate calculations |
| sounds.js | 21 KB | 460 | UI sound effects system |
| analytics.js | 18 KB | 400 | Usage analytics and session tracking |
| email-templates.js | 17 KB | 380 | HTML email template library |
| expiry-alerts.js | 16 KB | 350 | Certificate expiry monitoring |
| doc-preview.js | 15 KB | 330 | Document preview modal |
| branding.js | 15 KB | 330 | Per-tenant branding system |
| inapp-notify.js | 15 KB | 330 | In-app notification inbox |
| camera.js | 15 KB | 330 | Camera access, signature capture |
| i18n.js | 14 KB | 300 | Internationalisation (EN / AR / FR) |
| sw-register.js | 13 KB | 290 | Service Worker / PWA management |
| portfolio-shared.js | 12 KB | 270 | Shared utilities across portals |
| comments.js | 12 KB | 260 | Assessor comment threads per unit |
| cert-templates-db.js | 11 KB | 240 | Certificate template database operations |
| bulk-ops.js | 11 KB | 240 | Bulk admin operations |
| api.js | 11 KB | 240 | API resolver + multi-tenant fetch interceptor |
| audit.js | 7 KB | 160 | Audit trail logging |