
Whistleblower Compliance
- 46 installs
- 451 repo stars
- Updated July 21, 2026
- borghei/claude-skills
whistleblower-compliance is a Claude skill that audits whistleblower reporting systems and drafts compliant policies across EU, US, and UK frameworks.
About
Whistleblower-compliance audits existing whistleblower reporting systems and drafts compliant policies. It covers EU Directive 2019/1937, US SOX Section 806, Dodd-Frank, and the UK PIDA 1998. Mode A runs an 8-phase audit and Mode B generates jurisdiction-specific reporting policies. Compliance and legal teams use it to assess or build whistleblower programs.
- Audits whistleblower systems and drafts compliant reporting policies
- Covers EU Directive 2019/1937, US SOX 806, Dodd-Frank, and UK PIDA 1998
- Two modes: an 8-phase, 56-checkpoint audit and a policy scaffolder
Whistleblower Compliance by the numbers
- 46 all-time installs (skills.sh)
- Ranked #1,365 of 2,203 Security skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
whistleblower-compliance capabilities & compatibility
- Capabilities
- compliance audit · policy drafting · regulatory checklist
- Use cases
- security audit · documentation
- Pricing
- Free
What whistleblower-compliance says it does
Audit whistleblower systems and draft compliant reporting policies. Use when assessing or building whistleblower programs.
Mode A (Assessment) runs an 8-phase, 56-checkpoint audit of existing systems; Mode B (Drafting) generates jurisdiction-specific reporting policies.
npx skills add https://github.com/borghei/claude-skills --skill whistleblower-complianceAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 46 |
|---|---|
| repo stars | ★ 451 |
| Last updated | July 21, 2026 |
| Repository | borghei/claude-skills ↗ |
What it does
Audit a whistleblower reporting system for regulatory compliance or draft a jurisdiction-specific policy.
Who is it for?
Compliance officers and legal counsel assessing or building whistleblower reporting programs.
Skip if: Situations needing formal legal advice (marked experimental) or non-whistleblower compliance domains.
When should I use this skill?
Assessing an existing whistleblower system or drafting a reporting policy.
What you get
A compliance score with priority-classified gaps, or a jurisdiction-specific policy draft.
- compliance score
- gap remediation plan
- whistleblower policy draft
By the numbers
- 8-phase audit
- 56 checkpoints
- 4 regulatory frameworks
Files
⚠️ EXPERIMENTAL — This skill is provided for educational and informational purposes only. It does NOT constitute legal advice. All responsibility for usage rests with the user. Consult qualified legal professionals before acting on any output.
Whistleblower Compliance Skill
Overview
Production-ready whistleblower compliance toolkit for auditing existing reporting systems and drafting compliant policies. Covers EU Directive 2019/1937, US SOX Section 806, US Dodd-Frank, and UK Public Interest Disclosure Act 1998. Operates in two modes: Mode A (Assessment) runs an 8-phase, 56-checkpoint audit of existing systems; Mode B (Drafting) generates jurisdiction-specific reporting policies.
Table of Contents
- Tools
- Reference Guides
- Workflows
- Troubleshooting
- Success Criteria
- Scope & Limitations
- Anti-Patterns
- Tool Reference
Tools
1. Compliance Checker (scripts/whistleblower_compliance_checker.py)
Assess an existing whistleblower system against regulatory requirements. Takes organizational parameters and outputs a compliance score with priority-classified gaps.
python scripts/whistleblower_compliance_checker.py \
--jurisdiction EU --headcount 300 --sector financial \
--channels internal,external --has-designated-person \
--has-confidentiality --has-gdpr-measures --has-dissemination
python scripts/whistleblower_compliance_checker.py \
--jurisdiction US --headcount 5000 --sector healthcare \
--channels internal --json
python scripts/whistleblower_compliance_checker.py \
--jurisdiction UK --headcount 50 --sector technology \
--channels none2. Policy Scaffolder (scripts/whistleblower_policy_scaffolder.py)
Generate a whistleblower policy skeleton pre-populated with required sections per regulatory framework.
python scripts/whistleblower_policy_scaffolder.py \
--jurisdiction EU --org-type private --headcount 500 \
--org-name "Acme Corp"
python scripts/whistleblower_policy_scaffolder.py \
--jurisdiction US --org-type public --headcount 10000 \
--org-name "MegaCorp Inc" --json
python scripts/whistleblower_policy_scaffolder.py \
--jurisdiction UK --org-type nonprofit --headcount 100 \
--org-name "CharityOrg" --output policy-draft.mdReference Guides
| Reference | Purpose |
|---|---|
references/regulatory_framework.md | Multi-jurisdiction whistleblower regulations, comparison matrix |
references/assessment_checklist.md | 8-phase, 56-checkpoint assessment with priority classifications |
Workflows
Mode A: Assessment Workflow
1. Gather Parameters -- Collect jurisdiction, headcount, sector, and system description 2. Run Compliance Checker -- Execute whistleblower_compliance_checker.py with parameters 3. Review Gaps -- Prioritize CRITICAL gaps first, then IMPORTANT, then IMPROVEMENT 4. Cross-Reference Checklist -- Walk through assessment_checklist.md for manual verification 5. Generate Remediation Plan -- Address gaps by priority, set deadlines per regulatory timelines
Mode B: Drafting Workflow
1. Determine Jurisdiction -- Identify applicable regulations based on headquarters and operations 2. Generate Scaffold -- Run whistleblower_policy_scaffolder.py with organization details 3. Customize Sections -- Replace placeholders with organization-specific information 4. Legal Review -- Route draft through legal counsel for jurisdiction-specific validation 5. Approval & Publication -- Obtain board/management approval and disseminate to all personnel
8-Phase Assessment Framework
| Phase | Focus | Checkpoints |
|---|---|---|
| 1. Applicability | Regulatory scope determination | 3 |
| 2. Reception Channel | Reporting channel adequacy | 5 |
| 3. Designated Persons | Personnel and independence | 7 |
| 4. Verification/Processing | Investigation procedures | 8 |
| 5. Confidentiality | Identity and data protection | 9 |
| 6. Dissemination/Information | Awareness and accessibility | 10 |
| 7. Data Protection/GDPR | Privacy compliance | 12 |
| 8. Sector-Specific | Industry requirements | 6 |
| Total | 60 |
Three Reporting Channels
| Channel | When Used | Key Requirements |
|---|---|---|
| Internal | First preference; report to organization | Acknowledge within 7 days; feedback within 3 months |
| External (Regulatory) | When internal fails or is inappropriate | Report to competent authority; same protections apply |
| Public Disclosure | Last resort; imminent danger or retaliation | Protected only if internal/external channels exhausted |
Whistleblower Protections
| Protection | Description |
|---|---|
| Civil immunity | No liability for breach of confidentiality obligations |
| Criminal immunity | No criminal liability for acquiring reported information |
| Prohibited retaliation | Dismissal, demotion, harassment, blacklisting, discrimination |
| Burden of proof reversal | Employer must prove action was not retaliatory |
| Interim relief | Provisional protection during investigation |
| Legal aid access | Access to legal counsel and support |
Priority Classification
| Priority | Definition | Example |
|---|---|---|
| CRITICAL | Legal non-compliance; immediate regulatory risk | No reporting channel exists; no confidentiality measures |
| IMPORTANT | Significant gap reducing system effectiveness | Acknowledgment timeline exceeds 7 days; no designated person |
| IMPROVEMENT | Enhancement opportunity; not currently non-compliant | Training frequency below best practice; limited channel types |
Troubleshooting
| Problem | Cause | Solution |
|---|---|---|
| Checker reports all CRITICAL | No system parameters provided | Provide accurate --channels, --has-designated-person, and other flags |
| Wrong jurisdiction requirements | Multi-jurisdiction entity using single jurisdiction | Run checker separately per jurisdiction; use strictest requirements |
| Policy scaffold missing sections | Jurisdiction flag incorrect | Verify --jurisdiction matches EU, US, or UK |
| Headcount threshold confusion | EU directive has different thresholds by entity type | Private sector: 50+ employees; public sector: all municipalities |
| Sector-specific gaps not flagged | Generic sector value used | Use specific sector: financial, healthcare, defense, nuclear |
| GDPR checks fail for US entity | US entities may still need GDPR compliance | If processing EU citizen data, add --has-gdpr-measures |
| Timeline requirements unclear | Different jurisdictions have different timelines | EU: 7-day ack, 3-month feedback; SOX: 180-day filing deadline |
| Policy output too generic | Minimal parameters provided | Add --org-name, --org-type, and --headcount for specificity |
Success Criteria
- Compliance Coverage: Assessment covers 100% of applicable regulatory requirements for specified jurisdiction
- Gap Identification: All CRITICAL and IMPORTANT gaps identified with clear remediation guidance
- Policy Completeness: Generated policies include all mandatory sections per applicable regulation
- Timeline Compliance: Policies reflect correct acknowledgment (7 days) and feedback (3 months) timelines
- Audit Readiness: Assessment output sufficient for regulatory audit preparation and evidence gathering
Scope & Limitations
This skill covers:
- Compliance assessment against EU Directive 2019/1937, US SOX/Dodd-Frank, UK PIDA
- Policy scaffolding with jurisdiction-specific mandatory sections
- Gap analysis with priority classification and remediation guidance
- Multi-sector considerations (financial, healthcare, defense, nuclear, transport)
This skill does NOT cover:
- Actual whistleblower case management or investigation procedures
- Legal advice or attorney-client privileged analysis
- Real-time regulatory monitoring or automatic updates when laws change
- Whistleblower hotline software implementation or vendor selection
- Cross-border reporting coordination between multiple regulators
Anti-Patterns
| Anti-Pattern | Why It Fails | Better Approach |
|---|---|---|
| Copy-pasting policy from another jurisdiction | Regulations differ materially; EU requires 7-day ack, SOX has 180-day filing | Run scaffolder with correct jurisdiction; customize per local requirements |
| Treating all gaps as equal priority | Wastes resources on improvements while CRITICAL gaps remain | Address CRITICAL first, IMPORTANT second, IMPROVEMENT last |
| Single assessment for multi-jurisdiction org | Each jurisdiction has unique requirements and thresholds | Run separate assessments per jurisdiction; merge into unified policy |
| Skipping sector-specific phase | Regulated sectors (financial, healthcare) have additional requirements | Always complete Phase 8 for regulated industries |
| No periodic reassessment | Regulations evolve; transposition deadlines pass | Schedule annual reassessment; monitor legislative changes |
Tool Reference
scripts/whistleblower_compliance_checker.py
Assess whistleblower system compliance against regulatory requirements.
usage: whistleblower_compliance_checker.py [-h] [--json]
--jurisdiction {EU,US,UK}
--headcount HEADCOUNT
--sector SECTOR
[--channels CHANNELS]
[--has-designated-person]
[--has-confidentiality]
[--has-gdpr-measures]
[--has-dissemination]
[--has-acknowledgment-timeline]
[--has-feedback-timeline]
options:
-h, --help Show help message and exit
--json Output in JSON format
--jurisdiction Regulatory jurisdiction: EU, US, or UK
--headcount Number of employees in the organization
--sector Industry sector (financial, healthcare, technology, etc.)
--channels Comma-separated channel types: internal, external, none
--has-designated-person Designated person(s) appointed for handling reports
--has-confidentiality Confidentiality measures in place
--has-gdpr-measures GDPR/data protection measures implemented
--has-dissemination Policy disseminated to all personnel
--has-acknowledgment-timeline 7-day acknowledgment timeline met
--has-feedback-timeline 3-month feedback timeline metscripts/whistleblower_policy_scaffolder.py
Generate jurisdiction-specific whistleblower policy skeleton.
usage: whistleblower_policy_scaffolder.py [-h] [--json]
--jurisdiction {EU,US,UK}
--org-type {public,private,nonprofit}
--headcount HEADCOUNT
[--org-name ORG_NAME]
[--output OUTPUT]
options:
-h, --help Show help message and exit
--json Output in JSON format
--jurisdiction Regulatory jurisdiction: EU, US, or UK
--org-type Organization type
--headcount Number of employees
--org-name Organization name (used in policy template)
--output Write policy to file instead of stdoutWhistleblower Compliance Assessment Checklist
8-phase, 60-checkpoint assessment framework for evaluating whistleblower system compliance.
Table of Contents
- Priority Classification System
- Phase 1: Applicability
- Phase 2: Reception Channel
- Phase 3: Designated Persons
- Phase 4: Verification and Processing
- Phase 5: Confidentiality
- Phase 6: Dissemination and Information
- Phase 7: Data Protection and GDPR
- Phase 8: Sector-Specific Requirements
- Common Errors
- Assessment Scoring Guide
Priority Classification System
| Priority | Definition | Action Required | Example |
|---|---|---|---|
| CRITICAL | Legal non-compliance creating immediate regulatory risk. Failure to address exposes organization to enforcement action, fines, or liability. | Immediate remediation required within 30 days. Escalate to board/management. | No reporting channel exists; reporter identity disclosed without consent |
| IMPORTANT | Significant gap that reduces system effectiveness or creates material risk. System exists but does not meet key requirements. | Remediation within 90 days. Include in next compliance review cycle. | Acknowledgment exceeds 7-day timeline; no designated person backup |
| IMPROVEMENT | Enhancement opportunity. Current state is not non-compliant but falls below best practice. Addressing improves system effectiveness. | Plan for next annual review. Track as improvement item. | Single channel type only; training frequency below annual |
Phase 1: Applicability
Determine whether the organization falls within the scope of whistleblower protection regulations.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 1.1 | Jurisdiction identified | CRITICAL | Primary jurisdiction(s) documented with applicable regulations listed |
| 1.2 | Headcount threshold met | CRITICAL | EU: 50+ employees (private sector) or any public sector entity; US/UK: all covered entities |
| 1.3 | Sector-specific obligations identified | IMPORTANT | Regulated sectors (financial, healthcare, defense, nuclear) have additional requirements documented |
Phase 2: Reception Channel
Evaluate the existence and adequacy of reporting channels.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 2.1 | Internal reporting channel exists | CRITICAL | At least one operational internal reporting channel available |
| 2.2 | Channel supports required modes | IMPORTANT | Written and oral reporting supported; in-person available on request (EU) |
| 2.3 | Channel is accessible to all reporters | IMPORTANT | Available to employees, contractors, and other protected persons; no access barriers |
| 2.4 | Anonymous reporting option available | IMPROVEMENT | Anonymous submissions accepted where legally permitted; system preserves anonymity |
| 2.5 | External reporting channel information provided | IMPORTANT | Information about external reporting to competent authorities is documented and accessible |
Phase 3: Designated Persons
Assess the appointment and qualification of persons handling reports.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 3.1 | Designated person(s) appointed | CRITICAL | Named individual(s) or department formally designated for receiving and following up reports |
| 3.2 | Independence verified | CRITICAL | Designated person has no conflicts of interest; reports independently of management chain |
| 3.3 | Competence confirmed | IMPORTANT | Designated person has training in investigation procedures, confidentiality, and applicable law |
| 3.4 | Contact information published | IMPORTANT | Contact details accessible to all potential reporters via multiple channels |
| 3.5 | Backup person designated | IMPORTANT | Alternate designated person appointed for absence, conflict, or recusal scenarios |
| 3.6 | Mandate documented | IMPROVEMENT | Written mandate defining responsibilities, authority, and reporting line |
| 3.7 | Annual training completed | IMPROVEMENT | Designated person(s) complete annual refresher training with documented attendance |
Phase 4: Verification and Processing
Evaluate investigation and follow-up procedures.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 4.1 | Acknowledgment within timeline | CRITICAL | EU: written acknowledgment within 7 calendar days; US/UK: prompt acknowledgment |
| 4.2 | Feedback within timeline | CRITICAL | EU: feedback within 3 months of acknowledgment; US/UK: reasonable timeframe |
| 4.3 | Triage process defined | IMPORTANT | Documented process for initial assessment, categorization, and routing of reports |
| 4.4 | Investigation procedure documented | IMPORTANT | Written procedure covering evidence gathering, interviews, analysis, and conclusion |
| 4.5 | Impartiality safeguards | IMPORTANT | Investigator has no connection to reported persons; conflict of interest checks in place |
| 4.6 | Case tracking system | IMPORTANT | Unique case identifiers, status tracking, audit trail for all actions taken |
| 4.7 | Outcome communication | IMPORTANT | Process for communicating investigation outcome to reporter without compromising confidentiality |
| 4.8 | Corrective action tracking | IMPROVEMENT | System for tracking implementation of corrective actions arising from investigations |
Phase 5: Confidentiality
Assess measures protecting reporter identity and report contents.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 5.1 | Identity protection policy | CRITICAL | Written policy prohibiting disclosure of reporter identity without consent |
| 5.2 | Access restricted to designated persons | CRITICAL | Only designated person(s) and authorized investigators can access reporter identity |
| 5.3 | Secure communication channel | IMPORTANT | Reporting channel uses encrypted or secure communication; no unprotected email |
| 5.4 | Physical security of records | IMPORTANT | Paper records locked; digital records access-controlled and encrypted |
| 5.5 | Anonymization procedures | IMPORTANT | Process for anonymizing information shared beyond designated persons during investigation |
| 5.6 | Consent process for disclosure | IMPORTANT | Documented process for obtaining reporter consent before any identity disclosure |
| 5.7 | Breach notification procedure | IMPORTANT | Process for notifying reporter if confidentiality is compromised |
| 5.8 | Penalty for unauthorized disclosure | IMPORTANT | Disciplinary consequences defined for staff who breach confidentiality |
| 5.9 | Third-party confidentiality | IMPROVEMENT | Confidentiality obligations extend to external investigators, counsel, and auditors |
Phase 6: Dissemination and Information
Evaluate awareness, training, and accessibility of whistleblower information.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 6.1 | Policy published and accessible | CRITICAL | Whistleblower policy available on intranet, website, or equivalent accessible location |
| 6.2 | All employees informed | CRITICAL | All current employees have received the policy and confirmation of receipt is documented |
| 6.3 | New employee onboarding | IMPORTANT | Whistleblower policy included in onboarding process; new hires briefed within first week |
| 6.4 | Contractor/vendor coverage | IMPORTANT | Policy and channel information communicated to contractors, suppliers, and partners |
| 6.5 | Regular awareness reminders | IMPORTANT | Periodic reminders (minimum annual) about reporting channels and protections |
| 6.6 | Training program | IMPORTANT | Formal training program covering policy, channels, protections, and procedures |
| 6.7 | Management training | IMPORTANT | Managers and supervisors receive specific training on handling disclosures and preventing retaliation |
| 6.8 | Multilingual availability | IMPROVEMENT | Policy available in all languages used by the workforce |
| 6.9 | Accessibility compliance | IMPROVEMENT | Policy and channels accessible to persons with disabilities |
| 6.10 | Reporting channel prominently displayed | IMPROVEMENT | Channel contact information displayed in common areas (physical and digital) |
Phase 7: Data Protection and GDPR
Assess compliance with data protection requirements for whistleblower data.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 7.1 | Legal basis for processing documented | CRITICAL | Art. 6 GDPR legal basis identified and documented (typically legal obligation or public interest) |
| 7.2 | Data Protection Impact Assessment | CRITICAL | DPIA completed for whistleblower reporting and investigation processing activities |
| 7.3 | Privacy notice for reporters | IMPORTANT | Reporters informed of how their data will be processed, stored, and protected |
| 7.4 | Privacy notice for reported persons | IMPORTANT | Reported persons informed of data processing (without compromising investigation) |
| 7.5 | Data minimization | IMPORTANT | Only data necessary for assessment and investigation is collected and processed |
| 7.6 | Retention policy defined | IMPORTANT | Specific retention periods defined for reports, investigation files, and supporting documents |
| 7.7 | Deletion procedures | IMPORTANT | Process for secure deletion of data when retention period expires |
| 7.8 | Data subject rights procedures | IMPORTANT | Procedures for handling access, rectification, and erasure requests in whistleblower context |
| 7.9 | Cross-border transfer safeguards | IMPORTANT | Appropriate safeguards for transferring whistleblower data across borders (SCCs, adequacy decisions) |
| 7.10 | Processor agreements | IMPROVEMENT | Data processing agreements in place with external service providers handling whistleblower data |
| 7.11 | Data breach response | IMPROVEMENT | Specific procedures for responding to breaches of whistleblower data security |
| 7.12 | Records of processing activities | IMPROVEMENT | Whistleblower data processing included in Art. 30 GDPR records |
Phase 8: Sector-Specific Requirements
Evaluate compliance with additional requirements for regulated sectors.
| # | Checkpoint | Priority | Pass Criteria |
|---|---|---|---|
| 8.1 | Sector-specific regulations identified | IMPORTANT | All applicable sector-specific whistleblower/reporting requirements documented |
| 8.2 | Regulatory authority notification | IMPORTANT | Process for notifying sector regulator when required (e.g., FCA, nuclear safety authority) |
| 8.3 | Integration with existing reporting | IMPORTANT | Whistleblower channel integrated with (but separate from) existing mandatory reporting (AML, safety) |
| 8.4 | Sector-specific training | IMPROVEMENT | Training addresses sector-specific reporting obligations and distinctions |
| 8.5 | Regulatory examination readiness | IMPROVEMENT | Documentation and procedures ready for regulatory examination or audit |
| 8.6 | Industry benchmarking | IMPROVEMENT | Whistleblower system benchmarked against sector peers and regulatory expectations |
Common Errors
| # | Error | Risk Level | Typical Consequence | Correction |
|---|---|---|---|---|
| 1 | No reporting channel established | CRITICAL | Regulatory non-compliance; fines; inability to detect wrongdoing early | Implement internal reporting channel immediately; consult legal counsel |
| 2 | Designated person has conflict of interest | CRITICAL | Investigation compromised; reporter retaliation risk; legal challenge | Appoint independent designated person; implement conflict checks |
| 3 | Acknowledgment timeline exceeded | CRITICAL | Non-compliance with EU Directive (7-day requirement); regulatory scrutiny | Automate acknowledgment; set calendar alerts; designate backup |
| 4 | Reporter identity disclosed without consent | CRITICAL | Breach of confidentiality obligation; retaliation risk; legal liability | Implement strict access controls; train all personnel; disciplinary consequences |
| 5 | No GDPR compliance measures | CRITICAL | Data protection violation; regulatory fine up to 4% annual turnover | Complete DPIA; document legal basis; implement privacy notices |
| 6 | Policy not disseminated to all staff | IMPORTANT | Employees unaware of reporting options; reduced effectiveness | Include in onboarding; annual reminders; publish on intranet |
| 7 | No feedback provided to reporter | IMPORTANT | Reporter loses confidence; may escalate to external/public channels | Implement feedback tracking; set 3-month calendar reminders |
| 8 | Single jurisdiction approach for multinational | IMPORTANT | Non-compliance in other jurisdictions; inconsistent protections | Assess each jurisdiction separately; implement strictest-standard approach |
| 9 | Anonymous reports not accepted | IMPROVEMENT | Reduced reporting rates; reporters fear identification | Enable anonymous channel; consider third-party hotline provider |
| 10 | No periodic reassessment | IMPROVEMENT | System degrades over time; regulatory changes missed | Schedule annual reassessment; assign compliance owner |
Assessment Scoring Guide
Score Calculation
Phase Score = (Checkpoints Passed / Total Checkpoints in Phase) x 100
Overall Score = (Total Checkpoints Passed / Total Checkpoints) x 100Score Interpretation
| Overall Score | Rating | Interpretation |
|---|---|---|
| 90-100% | Excellent | System meets or exceeds all requirements; minor improvements only |
| 75-89% | Good | System substantially compliant; some IMPORTANT gaps to address |
| 60-74% | Fair | System operational but significant gaps exist; prioritize CRITICAL items |
| 40-59% | Poor | Major compliance gaps; immediate remediation required |
| 0-39% | Non-Compliant | System inadequate or non-existent; urgent action needed |
Remediation Priority Matrix
| Gap Priority | Score Impact | Remediation Timeline | Escalation Level |
|---|---|---|---|
| CRITICAL | High (blocks compliance) | Within 30 days | Board/executive management |
| IMPORTANT | Medium (reduces effectiveness) | Within 90 days | Compliance committee |
| IMPROVEMENT | Low (enhancement) | Next annual review | Compliance officer |
Reassessment Schedule
| Trigger | Action |
|---|---|
| Initial assessment complete | Schedule 6-month follow-up assessment |
| CRITICAL gaps identified | Reassess specific phases within 30 days of remediation |
| Annual cycle | Full 8-phase reassessment annually |
| Regulatory change | Targeted reassessment of affected phases within 60 days |
| Organizational change (merger, restructure) | Full reassessment within 90 days |
| Whistleblower incident | Post-incident review of relevant phases within 30 days |
Whistleblower Regulatory Framework
Multi-jurisdiction reference covering EU Directive 2019/1937, US SOX/Dodd-Frank, and UK Public Interest Disclosure Act 1998.
Table of Contents
- EU Directive 2019/1937
- US SOX Section 806
- US Dodd-Frank Act
- UK Public Interest Disclosure Act 1998
- Jurisdiction Comparison Matrix
- Protected Persons by Jurisdiction
- Reporting Channel Requirements
- Penalties for Non-Compliance
EU Directive 2019/1937
Scope
Material Scope -- Breaches of EU law in the following areas:
| Area | Examples |
|---|---|
| Public procurement | Bid rigging, conflict of interest, fraud |
| Financial services | Market manipulation, insider dealing, AML violations |
| Product safety | Non-compliant products, safety defects |
| Transport safety | Aviation, maritime, rail safety violations |
| Environmental protection | Pollution, waste disposal, emissions |
| Radiation protection / nuclear safety | Safety standard violations |
| Food and feed safety | Contamination, labeling fraud |
| Animal health and welfare | Cruelty, welfare standard breaches |
| Public health | Pharmaceutical fraud, medical device safety |
| Consumer protection | Unfair practices, product misrepresentation |
| Privacy and data protection | GDPR breaches, unauthorized processing |
| Network and information security | Cybersecurity incident concealment |
| Competition and state aid | Cartel activity, illegal state aid |
| Corporate tax | Tax fraud, aggressive tax planning |
Personal Scope -- Who is protected:
- Workers (employees, civil servants, self-employed)
- Shareholders and members of administrative/management/supervisory bodies
- Volunteers and paid/unpaid trainees
- Persons working under supervision of contractors, subcontractors, suppliers
- Former workers and job applicants
- Facilitators (persons assisting the reporter)
- Third persons connected with the reporter (colleagues, relatives)
- Legal entities owned/controlled by the reporter
Three Reporting Channels
1. Internal Reporting
| Requirement | Detail |
|---|---|
| Applicability | Mandatory for entities with 50+ employees; all public sector entities |
| Channel types | Must support written and/or oral reporting; in-person meetings on request |
| Acknowledgment | Within 7 calendar days of receipt |
| Feedback | Within 3 months from acknowledgment date |
| Designated person | Impartial person or department designated for follow-up |
| Record keeping | Maintain records in compliance with confidentiality requirements |
| Shared resources | Entities with 50-249 employees may share resources for receiving and investigating |
2. External Reporting (Competent Authority)
| Requirement | Detail |
|---|---|
| When available | Reporters may go directly to external channel without internal first |
| Authority | Each Member State designates competent authorities |
| Acknowledgment | Within 7 days unless reporter requests otherwise |
| Feedback | Within 3 months (extendable to 6 months in duly justified cases) |
| Follow-up | Authority must investigate and communicate outcome |
3. Public Disclosure
| Requirement | Detail |
|---|---|
| Condition 1 | Reporter first reported externally but no appropriate action within timeframe |
| Condition 2 | Imminent or manifest danger to public interest |
| Condition 3 | External reporting would risk retaliation or evidence destruction |
| Protection | Full protection if conditions met |
Protections
| Protection | Description |
|---|---|
| Prohibition of retaliation | Comprehensive list of prohibited retaliatory measures |
| Burden of proof reversal | If reporter suffers detriment, employer must prove it was not retaliation |
| Interim relief | Access to interim remedies pending legal proceedings |
| Waiver of liability | No liability for breach of confidentiality if report made in compliance |
| No criminal/civil liability | For acquiring or accessing information reported (unless criminal act) |
| Legal aid | Access to legal advice and representation |
| Support measures | Information, advice, and practical assistance from competent authorities |
Penalties
Member States must provide effective, proportionate, and dissuasive penalties for:
- Hindering or attempting to hinder reporting
- Retaliatory measures against reporters
- Vexatious proceedings against reporters
- Breaching confidentiality duty
- Knowingly making false reports (proportionate penalties)
US SOX Section 806
Scope
| Element | Detail |
|---|---|
| Applicability | Public companies (SEC registrants), subsidiaries, contractors, subcontractors, agents |
| Protected persons | Employees of covered companies |
| Protected disclosures | Fraud against shareholders, securities fraud, bank fraud, wire fraud, mail fraud, violations of SEC rules |
Protections
| Protection | Detail |
|---|---|
| Anti-retaliation | Cannot discharge, demote, suspend, threaten, harass, or discriminate |
| Filing deadline | Complaint with OSHA within 180 days of adverse action |
| OSHA investigation | OSHA investigates; preliminary reinstatement if reasonable cause found |
| Federal court | If OSHA does not issue final decision within 180 days, reporter may file in federal court |
| Remedies | Reinstatement, back pay with interest, compensatory damages, attorney fees |
Procedural Requirements
| Step | Timeline | Action |
|---|---|---|
| 1. Filing | Within 180 days | File complaint with OSHA |
| 2. OSHA investigation | 30-60 days typical | OSHA investigates, interviews, gathers evidence |
| 3. Preliminary order | If reasonable cause | Preliminary reinstatement, back pay |
| 4. ALJ hearing | If objected | Administrative Law Judge hearing |
| 5. ARB review | Appeal | Administrative Review Board |
| 6. Federal court | If no final decision in 180 days | File in appropriate federal district court |
US Dodd-Frank Act
Scope
| Element | Detail |
|---|---|
| Applicability | Broader than SOX; covers violations of securities laws reported to SEC |
| Protected persons | Any individual who provides information to SEC |
| Key distinction | Original information leading to successful enforcement action >$1M |
SEC Bounty Program
| Element | Detail |
|---|---|
| Eligibility | Original information leading to enforcement action with sanctions >$1M |
| Award range | 10-30% of monetary sanctions collected |
| Minimum sanction | $1,000,000 |
| Filing | Submit via SEC Tip, Complaint, or Referral (TCR) system |
| Anonymity | May report anonymously through attorney |
Anti-Retaliation
| Protection | Detail |
|---|---|
| Scope | Broader than SOX; covers reporting to SEC, assisting SEC, making required Dodd-Frank disclosures |
| Statute of limitations | 6 years from violation or 3 years from when facts became known (max 10 years) |
| Remedies | Reinstatement, double back pay with interest, litigation costs, attorney fees |
| Jury trial | Right to jury trial in federal court |
UK Public Interest Disclosure Act 1998
Scope
| Element | Detail |
|---|---|
| Legislation | Employment Rights Act 1996, Part IVA (inserted by PIDA 1998) |
| Protected persons | Workers (broader than employees: includes agency workers, contractors, trainees, NHS practitioners) |
| Not covered | Self-employed (other than workers), volunteers, intelligence services |
Qualifying Disclosures
A qualifying disclosure is one where the worker reasonably believes it shows one or more of:
| Category | Examples |
|---|---|
| Criminal offence | Fraud, theft, bribery, tax evasion |
| Breach of legal obligation | Contract, statutory duty, regulatory requirement |
| Miscarriage of justice | Wrongful conviction, procedural failures |
| Danger to health or safety | Workplace hazards, public health risks |
| Damage to environment | Pollution, contamination, waste |
| Deliberate concealment | Covering up any of the above |
Prescribed Persons
| Prescribed Person | Jurisdiction |
|---|---|
| Financial Conduct Authority (FCA) | Financial services regulation |
| Prudential Regulation Authority (PRA) | Prudential financial regulation |
| Health and Safety Executive (HSE) | Workplace safety |
| Environment Agency | Environmental protection |
| Information Commissioner's Office (ICO) | Data protection |
| Serious Fraud Office (SFO) | Serious/complex fraud |
| Care Quality Commission (CQC) | Health and social care |
| Ofsted | Education and children's services |
Protections
| Protection | Detail |
|---|---|
| Automatic unfair dismissal | Dismissal for making qualifying disclosure is automatically unfair |
| Detrimental treatment | Cannot subject worker to detriment for making disclosure |
| No qualifying period | No minimum service period required (unlike standard unfair dismissal) |
| No compensation cap | Compensation is uncapped (unlike standard unfair dismissal) |
| Interim relief | Can apply for interim relief within 7 days of dismissal |
| Employment tribunal | Claims heard by employment tribunal |
Reasonable Belief Standard
The worker must have a reasonable belief that: 1. The information disclosed tends to show one or more of the qualifying matters 2. The disclosure is made in the public interest (not purely personal grievance)
The belief does not need to be correct, only reasonable at the time of disclosure.
Jurisdiction Comparison Matrix
| Feature | EU Directive 2019/1937 | US SOX Section 806 | US Dodd-Frank | UK PIDA 1998 |
|---|---|---|---|---|
| Scope | EU law breaches (broad) | Securities/financial fraud | SEC violations | Qualifying disclosures (6 types) |
| Protected persons | Very broad (workers, shareholders, facilitators) | Employees of public companies | Anyone reporting to SEC | Workers (broad definition) |
| Internal channel required | Yes (50+ employees) | Yes (audit committee) | No | No (but recommended) |
| External channel | Competent authority | OSHA | SEC | Prescribed persons |
| Acknowledgment timeline | 7 days | None specified | None specified | None specified |
| Feedback timeline | 3 months | OSHA investigation timeline | SEC investigation | None specified |
| Burden of proof | Reversed (employer must prove no retaliation) | Employee bears initial burden | Employee bears initial burden | Employee proves disclosure; employer proves reason for treatment |
| Financial reward | Not required | Reinstatement + back pay | 10-30% bounty | Compensation (uncapped) |
| Filing deadline | Per national transposition | 180 days (OSHA) | 6 years / 3 years knowledge | 3 months (employment tribunal) |
| Anonymity | Encouraged | Permitted | Permitted (via attorney) | Not required |
| Public disclosure protection | Yes (conditions apply) | Limited | Limited | Yes (last resort) |
Protected Persons by Jurisdiction
| Person Type | EU | US (SOX) | US (Dodd-Frank) | UK |
|---|---|---|---|---|
| Employees | Yes | Yes | Yes | Yes |
| Former employees | Yes | No | Yes | Yes |
| Job applicants | Yes | No | No | No |
| Contractors/subcontractors | Yes | Yes | Yes | Yes |
| Self-employed | Yes | No | Yes | No |
| Shareholders | Yes | No | Yes | No |
| Board members | Yes | No | Yes | No |
| Volunteers | Yes | No | No | No |
| Trainees | Yes | No | No | Yes |
| Facilitators | Yes | No | No | No |
| Connected third parties | Yes | No | No | No |
Reporting Channel Requirements
| Requirement | EU | US (SOX) | US (Dodd-Frank) | UK |
|---|---|---|---|---|
| Internal channel mandatory | Yes (50+ employees) | Yes (audit committee) | No | No |
| Written reporting | Required | Recommended | SEC form/portal | Any form |
| Oral reporting | Required | Not specified | Permitted | Any form |
| In-person meeting | On request | Not specified | Not specified | Not specified |
| Anonymous reporting | Permitted (encouraged) | Permitted | Permitted (via attorney) | Not required |
| External authority | Competent authority | OSHA | SEC | Prescribed persons |
| Public disclosure | Protected (conditions) | Limited | Limited | Protected (conditions) |
Penalties for Non-Compliance
| Jurisdiction | Penalty Type | Detail |
|---|---|---|
| EU | Member State defined | Must be effective, proportionate, dissuasive |
| EU | Retaliation | Civil/criminal penalties per national law |
| EU | Hindering reporting | Penalties specified by Member States |
| EU | False reports | Proportionate penalties for knowingly false disclosures |
| US (SOX) | Criminal | Up to 10 years imprisonment for retaliation |
| US (SOX) | Civil | Reinstatement, double back pay, attorney fees |
| US (Dodd-Frank) | Civil | Double back pay with interest, litigation costs |
| UK | Employment tribunal | Uncapped compensation for unfair dismissal |
| UK | Interim relief | Continuation of employment pending hearing |
| UK | Costs | Employer may bear costs if claim succeeds |
#!/usr/bin/env python3
"""
Whistleblower Compliance Checker
Assesses an existing whistleblower system against regulatory requirements
for EU Directive 2019/1937, US SOX/Dodd-Frank, and UK PIDA.
Usage:
python whistleblower_compliance_checker.py --jurisdiction EU --headcount 300 --sector financial
python whistleblower_compliance_checker.py --jurisdiction US --headcount 5000 --sector healthcare --json
python whistleblower_compliance_checker.py --jurisdiction UK --headcount 50 --sector technology --channels internal,external
"""
import argparse
import json
import sys
from datetime import datetime
from typing import Any, Dict, List, Optional, Tuple
# Priority levels
CRITICAL = "CRITICAL"
IMPORTANT = "IMPORTANT"
IMPROVEMENT = "IMPROVEMENT"
# Jurisdiction-specific requirements
REQUIREMENTS: Dict[str, Dict[str, Any]] = {
"EU": {
"name": "EU Directive 2019/1937",
"headcount_threshold": 50,
"public_sector_all": True,
"acknowledgment_days": 7,
"feedback_months": 3,
"requires_internal_channel": True,
"requires_confidentiality": True,
"requires_gdpr": True,
"requires_designated_person": True,
"requires_dissemination": True,
"regulated_sectors": ["financial", "transport", "nuclear", "defense", "healthcare",
"environment", "food_safety", "public_procurement"],
},
"US": {
"name": "SOX Section 806 / Dodd-Frank",
"headcount_threshold": 0,
"public_sector_all": False,
"acknowledgment_days": None,
"feedback_months": None,
"requires_internal_channel": True,
"requires_confidentiality": True,
"requires_gdpr": False,
"requires_designated_person": True,
"requires_dissemination": True,
"filing_deadline_days": 180,
"regulated_sectors": ["financial", "healthcare", "defense", "energy"],
},
"UK": {
"name": "Public Interest Disclosure Act 1998",
"headcount_threshold": 0,
"public_sector_all": True,
"acknowledgment_days": None,
"feedback_months": None,
"requires_internal_channel": True,
"requires_confidentiality": True,
"requires_gdpr": True,
"requires_designated_person": True,
"requires_dissemination": True,
"regulated_sectors": ["financial", "healthcare", "nuclear", "defense"],
},
}
# Sector-specific additional checks
SECTOR_CHECKS: Dict[str, List[str]] = {
"financial": [
"Anti-money laundering reporting integration",
"Financial regulator notification procedures",
"Market abuse reporting channel separation",
],
"healthcare": [
"Patient safety reporting integration",
"Clinical governance alignment",
"Professional body notification procedures",
],
"defense": [
"Security clearance considerations for designated persons",
"Classified information handling procedures",
],
"nuclear": [
"Nuclear safety authority notification procedures",
"Radiation safety incident integration",
],
}
def build_gap(phase: str, checkpoint: str, priority: str, detail: str) -> Dict[str, str]:
"""Build a structured gap finding."""
return {
"phase": phase,
"checkpoint": checkpoint,
"priority": priority,
"detail": detail,
}
def assess_applicability(
jurisdiction: str, headcount: int, sector: str, reqs: Dict[str, Any]
) -> Tuple[List[Dict], int, int]:
"""Phase 1: Assess applicability (3 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 3
# Check 1: Headcount threshold
if headcount >= reqs["headcount_threshold"] or reqs["public_sector_all"]:
passed += 1
else:
gaps.append(build_gap(
"1. Applicability", "Headcount threshold", IMPROVEMENT,
f"Organization has {headcount} employees; threshold is {reqs['headcount_threshold']}. "
"Voluntary adoption still recommended."
))
# Check 2: Jurisdiction applicability
passed += 1 # Always applicable if user specified jurisdiction
# Check 3: Sector determination
if sector in reqs.get("regulated_sectors", []):
passed += 1
else:
passed += 1 # Non-regulated sectors still pass, just no extra requirements
return gaps, passed, total
def assess_reception_channel(
channels: List[str], reqs: Dict[str, Any]
) -> Tuple[List[Dict], int, int]:
"""Phase 2: Assess reception channels (5 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 5
has_internal = "internal" in channels
has_external = "external" in channels
has_any = has_internal or has_external
# Check 1: System exists
if has_any:
passed += 1
else:
gaps.append(build_gap(
"2. Reception Channel", "System existence", CRITICAL,
"No whistleblower reporting channel exists. Mandatory under applicable regulation."
))
# Check 2: Internal channel
if has_internal:
passed += 1
else:
gaps.append(build_gap(
"2. Reception Channel", "Internal channel", CRITICAL if reqs["requires_internal_channel"] else IMPORTANT,
"No internal reporting channel. Internal channels are the preferred first point of contact."
))
# Check 3: External channel awareness
if has_external:
passed += 1
else:
gaps.append(build_gap(
"2. Reception Channel", "External channel", IMPORTANT,
"No external reporting channel or awareness of regulatory authority reporting options."
))
# Check 4: Written/oral/in-person options
if has_internal:
passed += 1 # Assume basic channel supports at least one mode
else:
gaps.append(build_gap(
"2. Reception Channel", "Multiple report modes", IMPROVEMENT,
"Best practice: offer written, oral, and in-person reporting options."
))
# Check 5: Anonymous reporting option
if has_any:
passed += 1 # Score as pass but flag improvement
gaps.append(build_gap(
"2. Reception Channel", "Anonymous reporting", IMPROVEMENT,
"Consider enabling anonymous reporting to increase reporter confidence."
))
else:
total -= 1 # Skip if no channels at all
return gaps, passed, total
def assess_designated_persons(has_designated: bool, reqs: Dict[str, Any]) -> Tuple[List[Dict], int, int]:
"""Phase 3: Assess designated persons (7 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 7
if has_designated:
passed += 4 # Existence, appointment, training baseline, contact info
# Flag remaining items as improvements
gaps.append(build_gap(
"3. Designated Persons", "Independence verification", IMPORTANT,
"Verify designated person(s) have no conflicts of interest and report independently."
))
gaps.append(build_gap(
"3. Designated Persons", "Backup designation", IMPROVEMENT,
"Ensure backup designated person is appointed for absence/conflict scenarios."
))
gaps.append(build_gap(
"3. Designated Persons", "Specialized training", IMPROVEMENT,
"Confirm designated persons receive annual training on investigation procedures."
))
else:
gaps.append(build_gap(
"3. Designated Persons", "Person appointed", CRITICAL,
"No designated person appointed for receiving and processing whistleblower reports."
))
passed += 0
return gaps, passed, total
def assess_verification_processing(
has_ack_timeline: bool, has_feedback_timeline: bool, reqs: Dict[str, Any]
) -> Tuple[List[Dict], int, int]:
"""Phase 4: Assess verification and processing (8 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 8
# Acknowledgment timeline
if reqs.get("acknowledgment_days"):
if has_ack_timeline:
passed += 1
else:
gaps.append(build_gap(
"4. Verification/Processing", "Acknowledgment timeline",
CRITICAL,
f"Reports must be acknowledged within {reqs['acknowledgment_days']} days."
))
else:
passed += 1 # Not required in this jurisdiction
# Feedback timeline
if reqs.get("feedback_months"):
if has_feedback_timeline:
passed += 1
else:
gaps.append(build_gap(
"4. Verification/Processing", "Feedback timeline",
CRITICAL,
f"Feedback must be provided within {reqs['feedback_months']} months."
))
else:
passed += 1
# Standard process checks (scored generously with improvement flags)
passed += 3 # Triage process, investigation procedure, documentation
gaps.append(build_gap(
"4. Verification/Processing", "Written investigation procedure", IMPORTANT,
"Ensure formal written investigation procedure exists with defined steps."
))
gaps.append(build_gap(
"4. Verification/Processing", "Case tracking system", IMPROVEMENT,
"Implement case tracking with unique identifiers and audit trail."
))
gaps.append(build_gap(
"4. Verification/Processing", "Outcome communication", IMPORTANT,
"Document and communicate investigation outcomes to the reporter."
))
return gaps, passed, total
def assess_confidentiality(has_confidentiality: bool) -> Tuple[List[Dict], int, int]:
"""Phase 5: Assess confidentiality measures (9 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 9
if has_confidentiality:
passed += 5
gaps.append(build_gap(
"5. Confidentiality", "Access controls", IMPORTANT,
"Verify only designated persons can access reporter identity information."
))
gaps.append(build_gap(
"5. Confidentiality", "Secure communication channel", IMPORTANT,
"Ensure reporting channel uses encrypted/secure communication."
))
gaps.append(build_gap(
"5. Confidentiality", "Consent for identity disclosure", IMPROVEMENT,
"Document process for obtaining reporter consent before identity disclosure."
))
gaps.append(build_gap(
"5. Confidentiality", "Penalty for breach", IMPROVEMENT,
"Define disciplinary consequences for unauthorized identity disclosure."
))
else:
gaps.append(build_gap(
"5. Confidentiality", "Confidentiality measures", CRITICAL,
"No confidentiality measures in place. Reporter identity protection is mandatory."
))
return gaps, passed, total
def assess_dissemination(has_dissemination: bool) -> Tuple[List[Dict], int, int]:
"""Phase 6: Assess dissemination and information (10 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 10
if has_dissemination:
passed += 5
gaps.append(build_gap(
"6. Dissemination", "Employee training", IMPORTANT,
"All employees should receive training on whistleblower procedures."
))
gaps.append(build_gap(
"6. Dissemination", "Contractor/vendor coverage", IMPORTANT,
"Extend whistleblower information to contractors and business partners."
))
gaps.append(build_gap(
"6. Dissemination", "Regular reminders", IMPROVEMENT,
"Schedule periodic reminders about reporting channels and protections."
))
gaps.append(build_gap(
"6. Dissemination", "Multilingual availability", IMPROVEMENT,
"Provide policy in all languages used by the workforce."
))
gaps.append(build_gap(
"6. Dissemination", "Website/intranet publication", IMPROVEMENT,
"Publish policy on company intranet and/or public website."
))
else:
gaps.append(build_gap(
"6. Dissemination", "Policy dissemination", CRITICAL,
"Whistleblower policy not disseminated to personnel. Awareness is mandatory."
))
return gaps, passed, total
def assess_data_protection(has_gdpr: bool, reqs: Dict[str, Any]) -> Tuple[List[Dict], int, int]:
"""Phase 7: Assess data protection/GDPR (12 checkpoints)."""
gaps: List[Dict] = []
passed = 0
total = 12
if not reqs["requires_gdpr"]:
# GDPR not applicable but basic data protection still relevant
total = 6
if has_gdpr:
passed += 4
else:
passed += 2
gaps.append(build_gap(
"7. Data Protection", "Data protection measures", IMPORTANT,
"Implement basic data protection for whistleblower report data."
))
gaps.append(build_gap(
"7. Data Protection", "Retention policy", IMPORTANT,
"Define data retention period for whistleblower reports and investigation files."
))
gaps.append(build_gap(
"7. Data Protection", "Secure storage", IMPROVEMENT,
"Ensure whistleblower data is stored securely with access controls."
))
else:
if has_gdpr:
passed += 7
gaps.append(build_gap(
"7. Data Protection", "DPIA completion", IMPORTANT,
"Complete Data Protection Impact Assessment for whistleblower processing."
))
gaps.append(build_gap(
"7. Data Protection", "Legal basis documentation", IMPORTANT,
"Document legal basis for processing under Art. 6 GDPR."
))
gaps.append(build_gap(
"7. Data Protection", "Data subject rights", IMPROVEMENT,
"Define procedures for handling data subject rights in whistleblower context."
))
gaps.append(build_gap(
"7. Data Protection", "Cross-border transfer", IMPROVEMENT,
"Address cross-border data transfer requirements if applicable."
))
gaps.append(build_gap(
"7. Data Protection", "Retention schedule", IMPROVEMENT,
"Implement automated retention and deletion schedule."
))
else:
gaps.append(build_gap(
"7. Data Protection", "GDPR compliance", CRITICAL,
"No GDPR measures for whistleblower data processing. Mandatory under EU/UK regulation."
))
return gaps, passed, total
def assess_sector_specific(sector: str, reqs: Dict[str, Any]) -> Tuple[List[Dict], int, int]:
"""Phase 8: Assess sector-specific requirements (6 checkpoints)."""
gaps: List[Dict] = []
passed = 0
checks = SECTOR_CHECKS.get(sector, [])
total = max(len(checks), 2)
if not checks:
# Non-regulated sector: basic checks only
passed += 2
return gaps, passed, total
for check in checks:
gaps.append(build_gap(
"8. Sector-Specific", check, IMPORTANT,
f"Verify sector-specific requirement: {check}"
))
passed += max(0, total - len(checks))
return gaps, passed, total
def run_assessment(args: argparse.Namespace) -> Dict[str, Any]:
"""Run the full compliance assessment."""
jurisdiction = args.jurisdiction
headcount = args.headcount
sector = args.sector
channels = [c.strip() for c in args.channels.split(",")] if args.channels else []
reqs = REQUIREMENTS[jurisdiction]
all_gaps: List[Dict] = []
total_passed = 0
total_checks = 0
# Run all 8 phases
phases = [
("1. Applicability", assess_applicability(jurisdiction, headcount, sector, reqs)),
("2. Reception Channel", assess_reception_channel(channels, reqs)),
("3. Designated Persons", assess_designated_persons(args.has_designated_person, reqs)),
("4. Verification/Processing", assess_verification_processing(
args.has_acknowledgment_timeline, args.has_feedback_timeline, reqs)),
("5. Confidentiality", assess_confidentiality(args.has_confidentiality)),
("6. Dissemination", assess_dissemination(args.has_dissemination)),
("7. Data Protection", assess_data_protection(args.has_gdpr_measures, reqs)),
("8. Sector-Specific", assess_sector_specific(sector, reqs)),
]
phase_results = []
for phase_name, (gaps, passed, total) in phases:
all_gaps.extend(gaps)
total_passed += passed
total_checks += total
pct = round((passed / total) * 100, 1) if total > 0 else 100.0
phase_results.append({
"phase": phase_name,
"passed": passed,
"total": total,
"score_pct": pct,
})
overall_score = round((total_passed / total_checks) * 100, 1) if total_checks > 0 else 0.0
critical_count = sum(1 for g in all_gaps if g["priority"] == CRITICAL)
important_count = sum(1 for g in all_gaps if g["priority"] == IMPORTANT)
improvement_count = sum(1 for g in all_gaps if g["priority"] == IMPROVEMENT)
return {
"assessment_date": datetime.now().strftime("%Y-%m-%d"),
"jurisdiction": jurisdiction,
"regulation": reqs["name"],
"headcount": headcount,
"sector": sector,
"channels": channels,
"overall_score_pct": overall_score,
"total_passed": total_passed,
"total_checks": total_checks,
"gap_summary": {
"critical": critical_count,
"important": important_count,
"improvement": improvement_count,
"total": len(all_gaps),
},
"phase_results": phase_results,
"gaps": all_gaps,
}
def format_text(result: Dict[str, Any]) -> str:
"""Format assessment result as human-readable text."""
lines = []
lines.append("=" * 70)
lines.append("WHISTLEBLOWER COMPLIANCE ASSESSMENT REPORT")
lines.append("=" * 70)
lines.append(f"Date: {result['assessment_date']}")
lines.append(f"Jurisdiction: {result['jurisdiction']} ({result['regulation']})")
lines.append(f"Headcount: {result['headcount']}")
lines.append(f"Sector: {result['sector']}")
lines.append(f"Channels: {', '.join(result['channels']) or 'None'}")
lines.append("")
lines.append(f"OVERALL SCORE: {result['overall_score_pct']}% "
f"({result['total_passed']}/{result['total_checks']} checks passed)")
lines.append("")
# Phase breakdown
lines.append("-" * 70)
lines.append("PHASE BREAKDOWN")
lines.append("-" * 70)
lines.append(f"{'Phase':<35} {'Score':>10} {'Passed':>10}")
lines.append("-" * 70)
for p in result["phase_results"]:
lines.append(f"{p['phase']:<35} {p['score_pct']:>9.1f}% {p['passed']:>4}/{p['total']:<4}")
# Gap summary
lines.append("")
lines.append("-" * 70)
lines.append("GAP SUMMARY")
lines.append("-" * 70)
gs = result["gap_summary"]
lines.append(f" CRITICAL: {gs['critical']}")
lines.append(f" IMPORTANT: {gs['important']}")
lines.append(f" IMPROVEMENT: {gs['improvement']}")
lines.append(f" TOTAL: {gs['total']}")
# Detailed gaps by priority
for priority in [CRITICAL, IMPORTANT, IMPROVEMENT]:
priority_gaps = [g for g in result["gaps"] if g["priority"] == priority]
if priority_gaps:
lines.append("")
lines.append(f"--- {priority} GAPS ---")
for g in priority_gaps:
lines.append(f" [{g['phase']}] {g['checkpoint']}")
lines.append(f" {g['detail']}")
lines.append("")
lines.append("=" * 70)
return "\n".join(lines)
def main() -> None:
parser = argparse.ArgumentParser(
description="Assess whistleblower system compliance against regulatory requirements."
)
parser.add_argument("--json", action="store_true", help="Output in JSON format")
parser.add_argument("--jurisdiction", required=True, choices=["EU", "US", "UK"],
help="Regulatory jurisdiction")
parser.add_argument("--headcount", required=True, type=int,
help="Number of employees")
parser.add_argument("--sector", required=True,
help="Industry sector (financial, healthcare, technology, etc.)")
parser.add_argument("--channels", default="none",
help="Comma-separated channel types: internal, external, none")
parser.add_argument("--has-designated-person", action="store_true",
help="Designated person appointed")
parser.add_argument("--has-confidentiality", action="store_true",
help="Confidentiality measures in place")
parser.add_argument("--has-gdpr-measures", action="store_true",
help="GDPR/data protection measures implemented")
parser.add_argument("--has-dissemination", action="store_true",
help="Policy disseminated to personnel")
parser.add_argument("--has-acknowledgment-timeline", action="store_true",
help="7-day acknowledgment timeline met")
parser.add_argument("--has-feedback-timeline", action="store_true",
help="3-month feedback timeline met")
args = parser.parse_args()
try:
result = run_assessment(args)
if args.json:
print(json.dumps(result, indent=2))
else:
print(format_text(result))
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
#!/usr/bin/env python3
"""
Whistleblower Policy Scaffolder
Generates a whistleblower policy skeleton pre-populated with required sections
per regulatory framework (EU Directive 2019/1937, US SOX/Dodd-Frank, UK PIDA).
Usage:
python whistleblower_policy_scaffolder.py --jurisdiction EU --org-type private --headcount 500 --org-name "Acme Corp"
python whistleblower_policy_scaffolder.py --jurisdiction US --org-type public --headcount 10000 --json
python whistleblower_policy_scaffolder.py --jurisdiction UK --org-type nonprofit --headcount 100 --output policy.md
"""
import argparse
import json
import sys
from datetime import datetime
from typing import Any, Dict, List, Optional
# Section definitions per jurisdiction
COMMON_SECTIONS = [
"Purpose and Scope",
"Definitions",
"Who Can Report",
"What Can Be Reported",
"Reporting Channels",
"How to Make a Report",
"Handling of Reports",
"Confidentiality",
"Protections Against Retaliation",
"Record Keeping and Data Protection",
"Review and Updates",
]
JURISDICTION_SECTIONS: Dict[str, List[str]] = {
"EU": [
"Internal Reporting Channel",
"External Reporting to Competent Authority",
"Public Disclosure Conditions",
"Acknowledgment and Feedback Timelines",
"Designated Person(s)",
"GDPR and Data Protection Compliance",
"Cross-Border Reporting",
"National Transposition Specifics",
],
"US": [
"SOX Section 806 Compliance",
"Dodd-Frank Whistleblower Provisions",
"SEC Reporting and Bounty Program",
"OSHA Complaint Process",
"Filing Deadlines",
"Audit Committee Oversight",
"Anti-Retaliation Provisions",
],
"UK": [
"Qualifying Disclosures",
"Prescribed Persons",
"Employment Tribunal Rights",
"Public Interest Test",
"Reasonable Belief Standard",
"GDPR UK and Data Protection Act 2018",
"Disclosure to Legal Advisors",
],
}
SECTOR_SECTIONS: Dict[str, List[str]] = {
"financial": ["Financial Regulatory Reporting", "Anti-Money Laundering Integration"],
"healthcare": ["Patient Safety Reporting", "Clinical Governance Alignment"],
"defense": ["Classified Information Handling", "Security Clearance Considerations"],
"nuclear": ["Nuclear Safety Authority Notification", "Radiation Safety Integration"],
"technology": ["Cybersecurity Incident Reporting Integration"],
}
def build_section_content(section: str, org_name: str, jurisdiction: str,
org_type: str, headcount: int) -> str:
"""Generate placeholder content for a policy section."""
placeholders: Dict[str, str] = {
"Purpose and Scope": (
f"This policy establishes the framework for reporting suspected wrongdoing "
f"at {org_name}. It applies to all employees, contractors, consultants, "
f"temporary workers, and business partners.\n\n"
f"[CUSTOMIZE: Define specific scope based on organizational structure and "
f"geographic operations.]"
),
"Definitions": (
"For the purposes of this policy:\n\n"
"- **Whistleblower/Reporter**: Any person who reports information about "
"breaches acquired in a work-related context.\n"
"- **Report**: A disclosure of information about suspected wrongdoing.\n"
"- **Retaliation**: Any direct or indirect act or omission that causes or "
"may cause unjustified detriment to the reporter.\n"
"- **Designated Person**: The individual(s) responsible for receiving and "
"following up on reports.\n"
"- **Breach**: Acts or omissions that are unlawful or defeat the object "
"or purpose of applicable rules.\n\n"
"[CUSTOMIZE: Add organization-specific definitions as needed.]"
),
"Who Can Report": (
"The following persons are entitled to protection under this policy:\n\n"
"- Current and former employees\n"
"- Job applicants and candidates\n"
"- Contractors, subcontractors, and suppliers\n"
"- Shareholders and members of management bodies\n"
"- Volunteers and unpaid trainees\n"
"- Persons assisting the reporter (facilitators)\n"
"- Third parties connected with the reporter\n\n"
"[CUSTOMIZE: Adjust based on applicable jurisdiction and organizational structure.]"
),
"What Can Be Reported": (
"This policy covers reports of suspected breaches including:\n\n"
"- Fraud, corruption, and bribery\n"
"- Financial irregularities and accounting manipulation\n"
"- Health and safety violations\n"
"- Environmental offenses\n"
"- Data protection and privacy breaches\n"
"- Discrimination and harassment\n"
"- Competition law violations\n"
"- Tax evasion and avoidance\n"
"- Product safety and compliance failures\n"
"- Obstruction of justice or regulatory proceedings\n\n"
"[CUSTOMIZE: Add sector-specific reportable matters.]"
),
"Reporting Channels": (
f"## Internal Reporting Channel\n\n"
f"{org_name} provides the following internal reporting channels:\n\n"
f"- **Online portal**: [INSERT URL]\n"
f"- **Email**: [INSERT DEDICATED EMAIL]\n"
f"- **Phone/Hotline**: [INSERT NUMBER]\n"
f"- **In person**: By appointment with [INSERT DESIGNATED PERSON]\n"
f"- **Written submission**: Marked 'Confidential' to [INSERT ADDRESS]\n\n"
f"Reports may be submitted anonymously where permitted by law.\n\n"
f"[CUSTOMIZE: Specify available channels and contact details.]"
),
"How to Make a Report": (
"When making a report, include as much of the following as possible:\n\n"
"1. Description of the suspected breach or wrongdoing\n"
"2. Names of persons involved (if known)\n"
"3. Dates and locations of the events\n"
"4. Any evidence or documentation supporting the report\n"
"5. Whether the matter has been reported elsewhere\n\n"
"Reports do not need to be proven. A reasonable belief that the "
"information is true at the time of reporting is sufficient."
),
"Handling of Reports": (
"Upon receipt of a report, the following process applies:\n\n"
"1. **Acknowledgment**: The reporter receives written acknowledgment "
f"{'within 7 calendar days' if jurisdiction == 'EU' else 'promptly'}.\n"
"2. **Initial Assessment**: The designated person assesses whether the "
"report falls within scope and determines next steps.\n"
"3. **Investigation**: An impartial investigation is conducted by "
"qualified personnel with no conflict of interest.\n"
"4. **Feedback**: The reporter is informed of the outcome "
f"{'within 3 months of acknowledgment' if jurisdiction == 'EU' else 'as soon as practicable'}.\n"
"5. **Closure**: The investigation is closed with documented findings "
"and any corrective actions.\n\n"
"[CUSTOMIZE: Define specific investigation procedures and escalation paths.]"
),
"Confidentiality": (
"The identity of the reporter shall not be disclosed to anyone beyond "
"authorized staff without the explicit consent of the reporter, unless "
"required by law in the context of judicial proceedings.\n\n"
"Confidentiality measures include:\n\n"
"- Access restricted to designated person(s) only\n"
"- Secure storage of all report documentation\n"
"- Anonymization of information shared for investigation purposes\n"
"- Disciplinary action for unauthorized disclosure\n\n"
"[CUSTOMIZE: Specify technical and organizational confidentiality measures.]"
),
"Protections Against Retaliation": (
"Retaliation against a reporter is strictly prohibited. Prohibited forms "
"of retaliation include, but are not limited to:\n\n"
"- Dismissal, suspension, or demotion\n"
"- Reduction in duties, salary, or benefits\n"
"- Harassment, intimidation, or bullying\n"
"- Negative performance references or evaluations\n"
"- Blacklisting within the industry\n"
"- Early termination of contract or license\n"
"- Psychiatric or medical referrals\n\n"
f"{'The burden of proof in retaliation claims rests with the employer. ' if jurisdiction == 'EU' else ''}"
f"{'Reporters may seek compensatory damages through employment tribunal proceedings. ' if jurisdiction == 'UK' else ''}"
f"{'Reporters may file complaints with OSHA within 180 days and may be eligible for SEC bounty awards. ' if jurisdiction == 'US' else ''}\n\n"
"[CUSTOMIZE: Specify organizational anti-retaliation procedures and remedies.]"
),
"Record Keeping and Data Protection": (
"All reports and related documentation shall be retained in accordance "
"with applicable data protection laws and organizational retention policies.\n\n"
"- Reports retained for the duration of the investigation plus [INSERT PERIOD]\n"
"- Personal data processed only for investigation purposes\n"
"- Data subjects informed of processing (except where it would compromise the investigation)\n"
f"{'- Data Protection Impact Assessment completed for whistleblower processing' if jurisdiction in ['EU', 'UK'] else ''}\n"
f"{'- Processing based on Art. 6(1)(c) GDPR (legal obligation) or Art. 6(1)(e) (public interest)' if jurisdiction in ['EU', 'UK'] else ''}\n\n"
"[CUSTOMIZE: Specify retention periods, legal basis, and technical measures.]"
),
"Review and Updates": (
f"This policy shall be reviewed [annually/biannually] by {org_name}'s "
"legal department and updated to reflect changes in applicable law, "
"regulatory guidance, and organizational structure.\n\n"
"- Last reviewed: [INSERT DATE]\n"
"- Next review due: [INSERT DATE]\n"
"- Policy owner: [INSERT NAME/TITLE]\n"
"- Approved by: [INSERT NAME/TITLE/BOARD]\n\n"
"[CUSTOMIZE: Specify review frequency and approval workflow.]"
),
"Internal Reporting Channel": (
"In accordance with EU Directive 2019/1937, this organization maintains "
"internal reporting channels that are secure, ensure confidentiality, and "
"allow written, oral, and in-person reporting.\n\n"
"[CUSTOMIZE: Describe channel implementation details.]"
),
"External Reporting to Competent Authority": (
"Reporters may report directly to the competent national authority if:\n\n"
"- Internal reporting would be ineffective\n"
"- There is risk of retaliation\n"
"- There is an imminent or manifest danger to the public interest\n\n"
"Competent authority: [INSERT NATIONAL AUTHORITY]\n\n"
"[CUSTOMIZE: Identify the relevant national competent authority.]"
),
"Public Disclosure Conditions": (
"Public disclosure is protected only when:\n\n"
"1. The reporter first reported internally and/or externally but no "
"appropriate action was taken within prescribed timelines; or\n"
"2. There is an imminent or manifest danger to the public interest; or\n"
"3. External reporting would risk retaliation or destruction of evidence.\n\n"
"[CUSTOMIZE: Clarify organizational position on public disclosure.]"
),
"Acknowledgment and Feedback Timelines": (
"- **Acknowledgment**: Within 7 calendar days of receipt\n"
"- **Feedback**: Within 3 months from date of acknowledgment\n"
"- Feedback includes: confirmation of receipt, status of follow-up, "
"and planned or taken actions (without compromising the investigation)\n\n"
"[CUSTOMIZE: Specify internal workflow to meet these mandatory timelines.]"
),
"Designated Person(s)": (
"The following person(s) are designated to receive and follow up on reports:\n\n"
"- Primary: [INSERT NAME, TITLE, CONTACT]\n"
"- Alternate: [INSERT NAME, TITLE, CONTACT]\n\n"
"Designated persons are selected for their independence, competence, "
"and absence of conflicts of interest.\n\n"
"[CUSTOMIZE: Appoint designated persons and define their mandate.]"
),
}
return placeholders.get(section, f"[CUSTOMIZE: Complete this section for {org_name}.]\n")
def generate_policy(args: argparse.Namespace) -> Dict[str, Any]:
"""Generate the full policy scaffold."""
jurisdiction = args.jurisdiction
org_type = args.org_type
headcount = args.headcount
org_name = args.org_name or "[ORGANIZATION NAME]"
sector = getattr(args, "sector", "general")
# Build section list
all_sections = list(COMMON_SECTIONS)
all_sections.extend(JURISDICTION_SECTIONS.get(jurisdiction, []))
sector_extras = SECTOR_SECTIONS.get(sector, [])
if sector_extras:
all_sections.extend(sector_extras)
# Generate policy document
policy_lines = []
policy_lines.append(f"# {org_name} Whistleblower Policy")
policy_lines.append("")
policy_lines.append(f"**Effective Date:** [INSERT DATE]")
policy_lines.append(f"**Version:** 1.0")
policy_lines.append(f"**Jurisdiction:** {jurisdiction}")
policy_lines.append(f"**Organization Type:** {org_type.title()}")
policy_lines.append(f"**Applicable Regulation:** "
f"{'EU Directive 2019/1937' if jurisdiction == 'EU' else ''}"
f"{'SOX Section 806 / Dodd-Frank' if jurisdiction == 'US' else ''}"
f"{'Public Interest Disclosure Act 1998' if jurisdiction == 'UK' else ''}")
policy_lines.append(f"**Approved By:** [INSERT NAME/TITLE]")
policy_lines.append("")
policy_lines.append("---")
policy_lines.append("")
# Table of contents
policy_lines.append("## Table of Contents")
policy_lines.append("")
for i, section in enumerate(all_sections, 1):
anchor = section.lower().replace(" ", "-").replace("/", "").replace("(", "").replace(")", "")
policy_lines.append(f"{i}. [{section}](#{anchor})")
policy_lines.append("")
policy_lines.append("---")
policy_lines.append("")
# Sections
sections_data = []
for i, section in enumerate(all_sections, 1):
content = build_section_content(section, org_name, jurisdiction, org_type, headcount)
policy_lines.append(f"## {i}. {section}")
policy_lines.append("")
policy_lines.append(content)
policy_lines.append("")
sections_data.append({"number": i, "title": section, "has_content": True})
policy_lines.append("---")
policy_lines.append("")
policy_lines.append(f"*Policy generated on {datetime.now().strftime('%Y-%m-%d')} "
f"for {org_name}. This is a template requiring legal review "
f"and customization before adoption.*")
policy_text = "\n".join(policy_lines)
return {
"generated_date": datetime.now().strftime("%Y-%m-%d"),
"jurisdiction": jurisdiction,
"org_name": org_name,
"org_type": org_type,
"headcount": headcount,
"total_sections": len(all_sections),
"sections": sections_data,
"policy_text": policy_text,
}
def main() -> None:
parser = argparse.ArgumentParser(
description="Generate a whistleblower policy skeleton based on jurisdiction and org type."
)
parser.add_argument("--json", action="store_true", help="Output in JSON format")
parser.add_argument("--jurisdiction", required=True, choices=["EU", "US", "UK"],
help="Regulatory jurisdiction")
parser.add_argument("--org-type", required=True, choices=["public", "private", "nonprofit"],
help="Organization type")
parser.add_argument("--headcount", required=True, type=int,
help="Number of employees")
parser.add_argument("--org-name", default=None,
help="Organization name for policy template")
parser.add_argument("--sector", default="general",
help="Industry sector for additional sections")
parser.add_argument("--output", default=None,
help="Write policy to file instead of stdout")
args = parser.parse_args()
try:
result = generate_policy(args)
if args.output:
with open(args.output, "w") as f:
f.write(result["policy_text"])
print(f"Policy written to {args.output} ({result['total_sections']} sections)")
elif args.json:
print(json.dumps(result, indent=2))
else:
print(result["policy_text"])
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
Related skills
FAQ
What are its two modes?
Mode A (Assessment) runs an 8-phase, 56-checkpoint audit of an existing system; Mode B (Drafting) generates a jurisdiction-specific reporting policy.
Which regulations does it cover?
EU Directive 2019/1937, US SOX Section 806, US Dodd-Frank, and the UK Public Interest Disclosure Act 1998.