// APM mock data — Earlens portfolio (a fictional hearing-tech company). // Single source of truth, mutated by useReducer in app.jsx. // ── Roles ──────────────────────────────────────────────────────────── const APM_ROLES = { admin: { label: 'Admin', desc: 'Manages users, roles, taxonomies, sensitivity tags.' }, owner: { label: 'Project Owner', desc: 'Drives projects through phase gates.' }, approver: { label: 'Stage Approver', desc: 'Signs off on phase-gate reviews.' }, manager: { label: 'Portfolio Manager', desc: 'Plans initiatives, allocates, manages capacity.' }, raqa: { label: 'RA/QA', desc: 'Reviews regulated workflows, signs HIPAA/RA gates.' }, helpdesk: { label: 'Helpdesk', desc: 'Triages tickets, runs Help board.' }, devops: { label: 'DevOps', desc: 'Manages components catalog, change control, releases.' }, exec: { label: 'Executive', desc: 'Reviews briefings, approves big-bet initiatives.' }, member: { label: 'Team Member', desc: 'Works tickets, submits ideas, contributes to projects.' }, }; // ── 9 personas ─────────────────────────────────────────────────────── const APM_PEOPLE = [ { id: 'p_alex', name: 'Alex Chen', role: 'admin', title: 'Platform Admin', team: 'IT Platform', initials: 'AC' }, { id: 'p_priya', name: 'Priya Natarajan', role: 'owner', title: 'Sr. Project Owner', team: 'Clinical Apps', initials: 'PN' }, { id: 'p_sam', name: 'Sam Okafor', role: 'approver', title: 'Director, IT Security', team: 'Security', initials: 'SO' }, { id: 'p_marisa', name: 'Marisa Vidal', role: 'manager', title: 'Portfolio Manager', team: 'PMO', initials: 'MV' }, { id: 'p_jenna', name: 'Jenna Rowe', role: 'raqa', title: 'RA/QA Lead', team: 'Regulatory', initials: 'JR' }, { id: 'p_diego', name: 'Diego Salas', role: 'helpdesk', title: 'Helpdesk Lead', team: 'IT Support', initials: 'DS' }, { id: 'p_kira', name: 'Kira Lindgren', role: 'devops', title: 'Sr. DevOps Engineer', team: 'Platform', initials: 'KL' }, { id: 'p_dr_ito', name: 'Dr. Naoko Ito', role: 'exec', title: 'Chief Medical Officer', team: 'Executive', initials: 'NI' }, { id: 'p_tomas', name: 'Tomás Beltrán', role: 'member', title: 'Audiology Lead', team: 'Clinical Ops', initials: 'TB' }, ]; const PERSON_BY_ID = Object.fromEntries(APM_PEOPLE.map(p => [p.id, p])); // ── 4 initiatives ──────────────────────────────────────────────────── const APM_INITIATIVES = [ { id: 'i_hearwell', code: 'INI-001', name: 'HearWell Cloud Migration', summary: 'Move clinical fitting platform to a HIPAA-eligible AWS environment with SOC 2 controls.', owner: 'p_marisa', sponsor: 'p_dr_ito', target: 'FY26 Q3', status: 'on-track', health: 84, budget: 4_200_000, spent: 1_780_000, projects: ['proj_fit_cloud', 'proj_id_sso', 'proj_audit_pipe', 'proj_telem_v2'], okrs: [ { id: 'o1', text: 'Decommission on-prem fitting servers', target: 'Q3', progress: 35 }, { id: 'o2', text: 'Achieve SOC 2 Type II readiness', target: 'Q4', progress: 62 }, { id: 'o3', text: 'Cut clinic-side latency by 40%', target: 'Q3', progress: 48 }, ], }, { id: 'i_pearl', code: 'INI-002', name: 'PEARL — AI Fit Coach', summary: 'Embed an AI assistant in the fitting flow that recommends adjustments from clinic-anonymized telemetry.', owner: 'p_priya', sponsor: 'p_dr_ito', target: 'FY26 Q4', status: 'at-risk', health: 58, budget: 2_800_000, spent: 1_410_000, projects: ['proj_fitcoach_mvp', 'proj_telem_v2', 'proj_consent'], okrs: [ { id: 'o1', text: 'Ship MVP fit-coach to 5 pilot clinics', target: 'Q3', progress: 70 }, { id: 'o2', text: 'Reach +15pp first-fit acceptance', target: 'Q4', progress: 22 }, { id: 'o3', text: 'Pass IRB & HIPAA review', target: 'Q3', progress: 90 }, ], }, { id: 'i_clinic', code: 'INI-003', name: 'Clinic Workbench Refresh', summary: 'Rebuild the day-of-clinic experience for audiologists: scheduling, in-visit notes, follow-up.', owner: 'p_marisa', sponsor: 'p_tomas', target: 'FY27 Q1', status: 'on-track', health: 76, budget: 1_900_000, spent: 460_000, projects: ['proj_sched_v2', 'proj_visit_notes', 'proj_followup'], okrs: [ { id: 'o1', text: 'Cut visit charting time 30%', target: 'Q4', progress: 18 }, { id: 'o2', text: 'Double follow-up adherence', target: 'Q1', progress: 12 }, ], }, { id: 'i_compliance', code: 'INI-004', name: 'Quality & RA Foundations', summary: 'Modernize document control, training records, and post-market surveillance to align with FDA QSR + EU MDR.', owner: 'p_jenna', sponsor: 'p_dr_ito', target: 'FY26 Q4', status: 'on-track', health: 81, budget: 1_350_000, spent: 720_000, projects: ['proj_doctrl', 'proj_pms', 'proj_training'], okrs: [ { id: 'o1', text: 'Replace legacy QMS', target: 'Q4', progress: 55 }, { id: 'o2', text: 'PMS dashboard live', target: 'Q3', progress: 80 }, ], }, ]; const INI_BY_ID = Object.fromEntries(APM_INITIATIVES.map(i => [i.id, i])); // ── Phases (canonical pipeline) ───────────────────────────────────── const APM_PHASES = [ 'Intake', 'Design', 'IT Review', 'Security', 'HIPAA/PII', 'Cost & Ops', 'RA/QA', 'UAT', 'Go-Live', 'Active', 'Archived' ]; // Sensitivity tags const APM_SENSITIVITY = [ { id: 'phi', label: 'PHI', desc: 'Protected Health Information' }, { id: 'pii', label: 'PII', desc: 'Personally Identifiable Info' }, { id: 'srcdata', label: 'Source data', desc: 'Clinical-trial source records' }, { id: 'finint', label: 'Fin/Internal', desc: 'Confidential financial' }, { id: 'public', label: 'Public', desc: 'No restrictions' }, ]; // ── 12 projects ────────────────────────────────────────────────────── const APM_PROJECTS = [ { id: 'proj_fitcoach_mvp', code: 'PRJ-2041', name: 'PEARL Fit-Coach MVP', initiative: 'i_pearl', owner: 'p_priya', raqa: 'p_jenna', phase: 'RA/QA', health: 'at-risk', progress: 64, sensitivity: ['phi','srcdata'], target: '2026-04-30', updated: '2 hours ago', summary: 'Recommend fitting-curve adjustments to audiologists in real time.', components: ['comp_telem','comp_audio_ml','comp_consent','comp_sso'], spent: 482_000, budget: 700_000, risks: 2, openTickets: 7, blockers: 1, }, { id: 'proj_telem_v2', code: 'PRJ-2042', name: 'Clinic Telemetry v2', initiative: 'i_pearl', owner: 'p_kira', raqa: 'p_jenna', phase: 'IT Review', health: 'on-track', progress: 38, sensitivity: ['phi'], target: '2026-06-15', updated: 'yesterday', summary: 'Streaming telemetry with consent-aware redaction.', components: ['comp_telem','comp_consent','comp_kafka'], spent: 145_000, budget: 520_000, risks: 1, openTickets: 3, blockers: 0, }, { id: 'proj_consent', code: 'PRJ-2043', name: 'Patient Consent Service', initiative: 'i_pearl', owner: 'p_priya', raqa: 'p_jenna', phase: 'HIPAA/PII', health: 'on-track', progress: 71, sensitivity: ['phi','pii'], target: '2026-03-12', updated: '4 hours ago', summary: 'Centralized consent ledger consumed by every clinic surface.', components: ['comp_consent','comp_audit'], spent: 198_000, budget: 280_000, risks: 0, openTickets: 2, blockers: 0, }, { id: 'proj_fit_cloud', code: 'PRJ-2044', name: 'Fitting Platform — Cloud', initiative: 'i_hearwell', owner: 'p_kira', raqa: 'p_jenna', phase: 'UAT', health: 'on-track', progress: 88, sensitivity: ['phi'], target: '2026-02-28', updated: '15 minutes ago', summary: 'Lift-and-reshape of legacy fitting servers onto AWS.', components: ['comp_fit_core','comp_sso','comp_audit','comp_kafka'], spent: 1_120_000, budget: 1_400_000, risks: 1, openTickets: 9, blockers: 0, }, { id: 'proj_id_sso', code: 'PRJ-2045', name: 'Workforce SSO + MFA', initiative: 'i_hearwell', owner: 'p_alex', raqa: null, phase: 'Active', health: 'on-track', progress: 100, sensitivity: ['pii'], target: '2025-11-04', updated: 'Nov 4', summary: 'OIDC-based SSO with mandatory phishing-resistant MFA.', components: ['comp_sso'], spent: 312_000, budget: 320_000, risks: 0, openTickets: 0, blockers: 0, }, { id: 'proj_audit_pipe', code: 'PRJ-2046', name: 'Audit Event Pipeline', initiative: 'i_hearwell', owner: 'p_kira', raqa: 'p_jenna', phase: 'Cost & Ops', health: 'at-risk', progress: 52, sensitivity: ['phi','finint'], target: '2026-05-20', updated: '3 days ago', summary: 'Append-only audit stream + retention policy engine.', components: ['comp_audit','comp_kafka'], spent: 248_000, budget: 410_000, risks: 3, openTickets: 5, blockers: 1, }, { id: 'proj_sched_v2', code: 'PRJ-2047', name: 'Clinic Scheduling v2', initiative: 'i_clinic', owner: 'p_priya', raqa: null, phase: 'Design', health: 'on-track', progress: 22, sensitivity: ['pii'], target: '2026-09-10', updated: 'today', summary: 'Rebuild scheduling around audiologist availability + room constraints.', components: ['comp_sched','comp_sso'], spent: 76_000, budget: 480_000, risks: 0, openTickets: 2, blockers: 0, }, { id: 'proj_visit_notes', code: 'PRJ-2048', name: 'In-Visit Charting', initiative: 'i_clinic', owner: 'p_priya', raqa: 'p_jenna', phase: 'Intake', health: 'on-track', progress: 8, sensitivity: ['phi','pii'], target: '2026-12-01', updated: 'today', summary: 'Voice + structured charting during the audiology visit.', components: [], spent: 0, budget: 360_000, risks: 0, openTickets: 0, blockers: 0, }, { id: 'proj_followup', code: 'PRJ-2049', name: 'Patient Follow-up Loop', initiative: 'i_clinic', owner: 'p_tomas', raqa: 'p_jenna', phase: 'Intake', health: 'on-track', progress: 4, sensitivity: ['phi','pii'], target: '2027-02-01', updated: 'yesterday', summary: '14- and 30-day follow-up nudges with response capture.', components: [], spent: 0, budget: 240_000, risks: 0, openTickets: 0, blockers: 0, }, { id: 'proj_doctrl', code: 'PRJ-2050', name: 'Document Control Replacement', initiative: 'i_compliance', owner: 'p_jenna', raqa: 'p_jenna', phase: 'Security', health: 'on-track', progress: 44, sensitivity: ['finint','srcdata'], target: '2026-08-30', updated: '5 hours ago', summary: 'Replace legacy QMS document control with a regulated SaaS.', components: ['comp_sso','comp_audit'], spent: 220_000, budget: 600_000, risks: 1, openTickets: 4, blockers: 0, }, { id: 'proj_pms', code: 'PRJ-2051', name: 'Post-Market Surveillance Dash', initiative: 'i_compliance', owner: 'p_jenna', raqa: 'p_jenna', phase: 'Go-Live', health: 'on-track', progress: 96, sensitivity: ['phi','srcdata'], target: '2026-01-22', updated: '1 hour ago', summary: 'Adverse-event signal detection across markets.', components: ['comp_telem','comp_audit'], spent: 392_000, budget: 410_000, risks: 0, openTickets: 1, blockers: 0, }, { id: 'proj_training', code: 'PRJ-2052', name: 'Training Records Modernization', initiative: 'i_compliance', owner: 'p_alex', raqa: 'p_jenna', phase: 'Active', health: 'on-track', progress: 100, sensitivity: ['pii'], target: '2025-09-30', updated: 'Sep 30', summary: 'Centralized training records tied to job code.', components: ['comp_sso'], spent: 108_000, budget: 110_000, risks: 0, openTickets: 0, blockers: 0, }, ]; const PROJ_BY_ID = Object.fromEntries(APM_PROJECTS.map(p => [p.id, p])); // ── Components catalog ────────────────────────────────────────────── const APM_COMPONENTS = [ { id: 'comp_sso', name: 'Workforce SSO', owner: 'p_alex', version: '2.4.1', stability: 'GA', dependents: ['proj_fit_cloud','proj_id_sso','proj_sched_v2','proj_doctrl','proj_training','proj_fitcoach_mvp'], sensitivity: ['pii'], summary: 'OIDC IdP + MFA gateway used by every employee surface.' }, { id: 'comp_consent', name: 'Consent Ledger', owner: 'p_priya', version: '1.2.0', stability: 'Beta', dependents: ['proj_fitcoach_mvp','proj_telem_v2','proj_consent'], sensitivity: ['phi','pii'], summary: 'Append-only consent records consumed by clinic + telemetry surfaces.' }, { id: 'comp_audit', name: 'Audit Event Bus', owner: 'p_kira', version: '0.9.3', stability: 'Beta', dependents: ['proj_fit_cloud','proj_audit_pipe','proj_pms','proj_doctrl','proj_consent'], sensitivity: ['phi','finint'], summary: 'Append-only audit stream feeding the long-term retention store.' }, { id: 'comp_kafka', name: 'Streaming Backbone', owner: 'p_kira', version: '3.1.0', stability: 'GA', dependents: ['proj_telem_v2','proj_audit_pipe','proj_fit_cloud'], sensitivity: [], summary: 'Internal Kafka cluster + schema registry.' }, { id: 'comp_telem', name: 'Telemetry SDK', owner: 'p_kira', version: '4.0.0-rc.2', stability: 'RC', dependents: ['proj_fitcoach_mvp','proj_telem_v2','proj_pms'], sensitivity: ['phi'], summary: 'Embedded SDK for fitting devices and clinic apps.' }, { id: 'comp_audio_ml', name: 'Audio ML Service', owner: 'p_priya', version: '0.4.0', stability: 'Alpha', dependents: ['proj_fitcoach_mvp'], sensitivity: ['phi','srcdata'], summary: 'Recommends fitting-curve adjustments from anonymized telemetry.' }, { id: 'comp_fit_core', name: 'Fitting Core Engine', owner: 'p_kira', version: '6.7.2', stability: 'GA', dependents: ['proj_fit_cloud'], sensitivity: ['phi'], summary: 'Legacy fitting algorithms wrapped as a service.' }, { id: 'comp_sched', name: 'Scheduling Service', owner: 'p_priya', version: '0.3.0', stability: 'Alpha', dependents: ['proj_sched_v2'], sensitivity: ['pii'], summary: 'Resource-constrained scheduling for clinics.' }, ]; const COMP_BY_ID = Object.fromEntries(APM_COMPONENTS.map(c => [c.id, c])); // ── Component change requests ─────────────────────────────────────── const APM_CHANGES = [ { id: 'chg_001', component: 'comp_telem', title: 'Add device-firmware version to event payload', submitter: 'p_kira', submitted: '3 days ago', breaking: false, status: 'pending', impact: ['proj_fitcoach_mvp','proj_telem_v2','proj_pms'], description: 'Append `fw_version` field to all telemetry events. Backwards compatible.', votes: 4 }, { id: 'chg_002', component: 'comp_consent', title: 'Require granular consent for ML training', submitter: 'p_jenna', submitted: '1 day ago', breaking: true, status: 'pending', impact: ['proj_fitcoach_mvp','proj_telem_v2','proj_consent'], description: 'Split consent into clinical-care and ML-training scopes. Existing consents migrate to clinical-care only.', votes: 7 }, { id: 'chg_003', component: 'comp_sso', title: 'Force MFA re-enrollment for clinical roles', submitter: 'p_alex', submitted: '6 hours ago', breaking: false, status: 'approved', impact: ['proj_fit_cloud','proj_doctrl'], description: 'Re-enroll any clinical role onto FIDO2 within 30 days.', votes: 3 }, ]; // ── Ideas backlog ──────────────────────────────────────────────────── const APM_IDEAS = [ { id: 'idea_001', title: 'Auto-summarize visit notes to the patient', submitter: 'p_tomas', submitted: '2 days ago', upvotes: 14, status: 'new', tags: ['clinic','ai','copy'], description: 'A 1-paragraph visit summary written at a 6th-grade reading level, reviewed by the audiologist before sending.' }, { id: 'idea_002', title: 'Battery-life forecast in the fitting app', submitter: 'p_diego', submitted: '5 days ago', upvotes: 22, status: 'new', tags: ['device','ux'], description: 'Predict days-until-recharge based on observed usage and surface a gentle nudge in the patient app.' }, { id: 'idea_003', title: 'Bring back the Q-shape preview in fittings', submitter: 'p_priya', submitted: '1 week ago', upvotes: 8, status: 'merged', mergedInto: 'proj_fitcoach_mvp', tags: ['clinic','ux'], description: 'Audiologists miss the legacy Q-curve preview; merge into Fit-Coach MVP scope.' }, { id: 'idea_004', title: 'Public-facing API for partner audiology chains', submitter: 'p_alex', submitted: '3 days ago', upvotes: 11, status: 'new', tags: ['platform','partners'], description: 'A read-only API for partners to retrieve aggregated, de-identified outcomes.' }, { id: 'idea_005', title: 'Replace 4-digit clinic PIN with passkeys', submitter: 'p_alex', submitted: 'today', upvotes: 5, status: 'promoted', promotedTo: 'proj_visit_notes', promotedAs: 'project', tags: ['security','clinic'], description: 'Phishing-resistant auth at the clinic terminal.' }, { id: 'idea_006', title: 'Outcomes-based pricing pilot', submitter: 'p_dr_ito', submitted: 'today', upvotes: 3, status: 'new', tags: ['business','executive'], description: 'Pilot a results-based contract with one large hearing-aid retailer.' }, ]; // ── Help board ─────────────────────────────────────────────────────── const APM_HELP = [ { id: 'help_001', title: 'Can the EU clinics share consent records?', from: 'p_priya', topic: 'compliance', age: '20 min', status: 'open', answers: 0 }, { id: 'help_002', title: 'How do I get a SOC 2 letter for a vendor?', from: 'p_alex', topic: 'security', age: '2 hr', status: 'answered', answers: 3, promoted: 'ticket' }, { id: 'help_003', title: 'Telemetry SDK 4.0 install on M1 macs', from: 'p_tomas', topic: 'devops', age: '4 hr', status: 'answered', answers: 2 }, { id: 'help_004', title: 'Where do I find the clinic PIN reset flow?', from: 'p_diego', topic: 'support', age: 'yesterday', status: 'open', answers: 0 }, ]; // ── Tickets ────────────────────────────────────────────────────────── const APM_TICKETS = [ { id: 't1001', title: 'Fitting platform 502 on EU clinic uploads', project: 'proj_fit_cloud', from: 'p_diego', age: '12 min', priority: 'P1', status: 'in-progress', assignee: 'p_kira' }, { id: 't1002', title: 'Consent ledger drops "ml-training" scope on edit', project: 'proj_consent', from: 'p_priya', age: '38 min', priority: 'P2', status: 'open', assignee: null }, { id: 't1003', title: 'SSO redirect loop for Okta + Edge users', project: 'proj_id_sso', from: 'p_diego', age: '1 hr', priority: 'P2', status: 'open', assignee: 'p_alex' }, { id: 't1004', title: 'PMS dash showing stale signal for Brazil', project: 'proj_pms', from: 'p_jenna', age: '2 hr', priority: 'P2', status: 'open', assignee: 'p_jenna' }, { id: 't1005', title: 'Audit pipeline lag spike during nightly batch', project: 'proj_audit_pipe', from: 'p_kira', age: '3 hr', priority: 'P3', status: 'in-progress', assignee: 'p_kira' }, { id: 't1006', title: 'Fit-coach mis-suggests for low-frequency loss', project: 'proj_fitcoach_mvp', from: 'p_tomas', age: '5 hr', priority: 'P2', status: 'open', assignee: 'p_priya' }, { id: 't1007', title: 'Doc-control: cannot upload 200MB CER PDF', project: 'proj_doctrl', from: 'p_jenna', age: 'yesterday', priority: 'P3', status: 'open', assignee: null }, ]; // ── Briefings (executive feed) ────────────────────────────────────── const APM_BRIEFINGS = [ { id: 'b1', kind: 'risk', when: 'Today, 9:14am', title: 'PEARL is at 58% health', body: 'First-fit acceptance OKR slipped from 31% to 22%. Owner is reviewing the model retrain schedule.' }, { id: 'b2', kind: 'milestone',when: 'Today, 7:02am', title: 'PMS Dashboard cleared Go-Live', body: 'Post-Market Surveillance dashboard cleared Go-Live with no conditions. Live in 36 hours.' }, { id: 'b3', kind: 'spend', when: 'Yesterday', title: 'HearWell at 42% of FY budget', body: 'Spend tracking on plan; cloud costs slightly under forecast.' }, { id: 'b4', kind: 'decision', when: '2 days ago', title: 'Decision needed: outcomes-based pricing pilot', body: 'Idea logged by Dr. Ito. Awaiting routing into an initiative or rejection.' }, ]; // ── Activity feed (cross-cutting) ─────────────────────────────────── const APM_ACTIVITY = [ { who: 'p_priya', verb: 'submitted', what: 'PEARL Fit-Coach MVP for RA/QA review', when: '12 min ago', kind: 'gate' }, { who: 'p_jenna', verb: 'opened a change request on', what: 'Consent Ledger', when: '38 min ago', kind: 'change' }, { who: 'p_alex', verb: 'approved', what: 'comp_sso change "Force MFA re-enrollment"', when: '1 hr ago', kind: 'approve' }, { who: 'p_kira', verb: 'released', what: 'Telemetry SDK 4.0 RC2', when: '3 hr ago', kind: 'release' }, { who: 'p_tomas', verb: 'logged an idea', what: '"Auto-summarize visit notes to the patient"', when: 'yesterday', kind: 'idea' }, { who: 'p_marisa',verb: 'updated capacity for', what: 'HearWell Cloud Migration', when: 'yesterday', kind: 'plan' }, { who: 'p_diego', verb: 'escalated ticket', what: 't1001 to P1', when: '2 days ago', kind: 'ticket' }, ]; // ── Helpers ────────────────────────────────────────────────────────── const projectsByInitiative = (iniId) => APM_PROJECTS.filter(p => p.initiative === iniId); const projectsByOwner = (pid) => APM_PROJECTS.filter(p => p.owner === pid); const ticketsByAssignee = (pid) => APM_TICKETS.filter(t => t.assignee === pid); const componentsByOwner = (pid) => APM_COMPONENTS.filter(c => c.owner === pid); const fmtMoney = (n) => '$' + Math.round(n / 1000).toLocaleString() + 'k'; const fmtMoneyFull = (n) => '$' + n.toLocaleString(); const pct = (a, b) => Math.round((a / b) * 100); Object.assign(window, { APM_ROLES, APM_PEOPLE, PERSON_BY_ID, APM_INITIATIVES, INI_BY_ID, APM_PHASES, APM_SENSITIVITY, APM_PROJECTS, PROJ_BY_ID, APM_COMPONENTS, COMP_BY_ID, APM_CHANGES, APM_IDEAS, APM_HELP, APM_TICKETS, APM_BRIEFINGS, APM_ACTIVITY, projectsByInitiative, projectsByOwner, ticketsByAssignee, componentsByOwner, fmtMoney, fmtMoneyFull, pct, });