Compliance Soc2 Readiness
blocklegalVanta/Drata-style SOC 2 Type II, ISO 27001, and HIPAA compliance readiness dashboard with framework selector tabs, audit readiness scorecards, 4 control pillar health bars, continuous automated evidence test tables with verified artifact badges, and auditor trust center portal controls.
Installation
$pnpm dlx uipkge-ng@latest add compliance-soc2-readiness$npx uipkge-ng@latest add compliance-soc2-readiness$yarn dlx uipkge-ng@latest add compliance-soc2-readiness$bunx uipkge-ng@latest add compliance-soc2-readinessManifest:
https://uipkge.dev/r/angular/compliance-soc2-readiness.jsonInstalls to:src/app/components/blocks/compliance-soc2-readiness/Variants
Loading interactive previews…
Loading interactive previews…
Schema
Type aliases exported from this item's source. Use these to shape the data you pass in.
PillarDatainterface PillarData {
code: string
title: string
description: string
score: number
passed: number
total: number
status: string
statusVariant: 'success' | 'warning' | 'secondary'
highlights: string[]
iconType: 'key' | 'shield' | 'activity' | 'users' | 'lock' | 'server' | 'file'
}EvidenceTestIteminterface EvidenceTestItem {
id: string
code: string
name: string
description: string
category: 'Identity & Auth' | 'Cloud Infrastructure' | 'Security Operations' | 'DevOps & CI/CD' | 'People & HR'
frequency: 'Continuous (1h)' | 'Daily' | 'Monthly' | 'Quarterly'
status: 'Passing' | 'Needs Attention'
statusVariant: 'success' | 'warning'
artifact: string
verified: boolean
lastTested: string
auditorNotes: string
}FrameworkConfiginterface FrameworkConfig {
id: string
tabLabel: string
name: string
badge: string
standard: string
score: number
readinessLabel: string
period: string
auditor: string
totalPassing: number
totalTests: number
pillars: PillarData[]
tests: EvidenceTestItem[]
trustCenterUrl: string
}Files installed (2)
src/app/components/blocks/compliance-soc2-readiness/compliance-soc2-readiness.component.ts54.1 kB
// Vanta/Drata-style SOC 2 Type II, ISO 27001, and HIPAA compliance readiness dashboard // with framework selector tabs, audit readiness scorecards, 4 control pillar health bars, // continuous automated evidence test tables with verified artifact badges, and auditor // trust center portal controls. Port of the React block 1:1. import { ChangeDetectionStrategy, Component, Input, computed, signal } from '@angular/core' import { AlertCircle, AlertTriangle, ArrowUpRight, BadgeCheck, Calendar, Check, CheckCircle2, Clock, Download, Eye, FileDown, FileText, Filter, KeyRound, Lock, LucideAngularModule, RefreshCw, Search, Server, Shield, ShieldCheck, Users, X, Zap, } from 'lucide-angular' import { cn } from '@/lib/utils' import { UiBadgeComponent } from '@/ui/badge/badge.component' import { UiButtonComponent } from '@/ui/button/button.component' import { UiCardComponent, UiCardContentComponent, UiCardDescriptionComponent, UiCardHeaderComponent, UiCardTitleComponent, } from '@/ui/card/card.component' import { UiProgressComponent } from '@/ui/progress/progress.component' import { UiSeparatorComponent } from '@/ui/separator/separator.component' import { UiTableBodyComponent, UiTableCellComponent, UiTableComponent, UiTableHeadComponent, UiTableHeaderComponent, UiTableRowComponent, } from '@/ui/table/table.component' import { UiTabsComponent, UiTabsListComponent, UiTabsTriggerComponent } from '@/ui/tabs/tabs.component' export interface PillarData { code: string title: string description: string score: number passed: number total: number status: string statusVariant: 'success' | 'warning' | 'secondary' highlights: string[] iconType: 'key' | 'shield' | 'activity' | 'users' | 'lock' | 'server' | 'file' } export interface EvidenceTestItem { id: string code: string name: string description: string category: 'Identity & Auth' | 'Cloud Infrastructure' | 'Security Operations' | 'DevOps & CI/CD' | 'People & HR' frequency: 'Continuous (1h)' | 'Daily' | 'Monthly' | 'Quarterly' status: 'Passing' | 'Needs Attention' statusVariant: 'success' | 'warning' artifact: string verified: boolean lastTested: string auditorNotes: string } export interface FrameworkConfig { id: string tabLabel: string name: string badge: string standard: string score: number readinessLabel: string period: string auditor: string totalPassing: number totalTests: number pillars: PillarData[] tests: EvidenceTestItem[] trustCenterUrl: string } const frameworksData: Record<string, FrameworkConfig> = { soc2: { id: 'soc2', tabLabel: 'SOC 2 Type II', name: 'SOC 2 Type II Readiness', badge: 'Security & Confidentiality', standard: 'AICPA Trust Services Criteria (CC1–CC9)', score: 96, readinessLabel: '96% Audit Ready', period: 'Jan 1, 2026 – Dec 31, 2026', auditor: 'KPMG LLP · Sarah Jenkins, CPA/CISA', totalPassing: 69, totalTests: 71, pillars: [ { code: 'CC1', title: 'Access Control & IAM', description: 'Identity federation, MFA enforcement, and least-privilege role provisioning.', score: 100, passed: 24, total: 24, status: '100% Passed · 24/24 tests', statusVariant: 'success', highlights: ['FIDO2/WebAuthn Hardware MFA', 'Just-In-Time Role Elevation'], iconType: 'key', }, { code: 'CC2', title: 'Encryption & Key Management', description: 'Data encryption in-transit & at rest with automated CMK key rotation.', score: 98, passed: 18, total: 18, status: '98% Passed · 18/18 tests', statusVariant: 'success', highlights: ['AWS KMS Envelope CMKs', 'TLS 1.3 Strict Cipher Suites'], iconType: 'shield', }, { code: 'CC3', title: 'Incident Response & Logging', description: 'Immutable audit trail ingesters, P1 runbooks, and real-time SIEM alerts.', score: 94, passed: 15, total: 16, status: '94% Passed · 15/16 tests', statusVariant: 'warning', highlights: ['Immutable WORM S3 Bucket', 'Quarterly Drill Executed'], iconType: 'activity', }, { code: 'CC4', title: 'Employee Security & Vendor Risk', description: 'Background checks, awareness training, and third-party vendor DPA reviews.', score: 92, passed: 12, total: 13, status: '92% Passed · 12/13 tests', statusVariant: 'secondary', highlights: ['100% Staff Security Training', 'Tier 1 Vendor DPA Signed'], iconType: 'users', }, ], tests: [ { id: 'test-soc2-1', code: 'CC6.1', name: 'MFA Enforced for All Staff', description: 'Continuous sync with Okta IAM confirming hardware/TOTP MFA active on all active seats.', category: 'Identity & Auth', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'okta-mfa-sync-v2.json', verified: true, lastTested: '4m ago', auditorNotes: '100% of 248 accounts verified with WebAuthn/FIDO2 hardware key enforcement.', }, { id: 'test-soc2-2', code: 'CC6.6', name: 'DB Storage Encrypted with KMS', description: 'All production RDS PostgreSQL and Redis storage volumes encrypted at rest with AWS KMS.', category: 'Cloud Infrastructure', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'aws-kms-rds-audit-prod.json', verified: true, lastTested: '12m ago', auditorNotes: 'AES-256 GCM encryption validated across primary cluster and 4 replica volumes.', }, { id: 'test-soc2-3', code: 'CC7.2', name: 'Quarterly Penetration Test Completed', description: 'Independent gray-box network and web application penetration test with zero open criticals.', category: 'Security Operations', frequency: 'Quarterly', status: 'Passing', statusVariant: 'success', artifact: 'BishopFox-Pentest-Q2-2026.pdf', verified: true, lastTested: 'Aug 12, 2026', auditorNotes: 'Full remediation verified within 14-day SLA. Attestation signed by Bishop Fox.', }, { id: 'test-soc2-4', code: 'CC6.7', name: 'Automated Backup Verification Daily', description: 'Daily point-in-time cross-region database snapshot validation and SHA-256 checksum test.', category: 'Cloud Infrastructure', frequency: 'Daily', status: 'Passing', statusVariant: 'success', artifact: 's3-replica-checksum-20260821.log', verified: true, lastTested: '2h ago', auditorNotes: 'Automated restore drill executed with RPO < 5m and RTO < 15m.', }, { id: 'test-soc2-5', code: 'CC8.1', name: 'Branch Protection & PR Reviews Enforced', description: 'GitHub repository rulesets require min 2 peer reviews, signed commits, and passing CI.', category: 'DevOps & CI/CD', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'github-branch-policy-main.json', verified: true, lastTested: '18m ago', auditorNotes: 'Zero bypass permissions granted. Administrator force-push strictly disabled.', }, { id: 'test-soc2-6', code: 'CC9.2', name: 'Third-Party Vendor Risk Assessment', description: 'Annual SOC 2 Type II report collection and DPA compliance review for active SaaS vendors.', category: 'People & HR', frequency: 'Monthly', status: 'Needs Attention', statusVariant: 'warning', artifact: 'vendor-risk-matrix-2026.csv', verified: false, lastTested: 'Yesterday', auditorNotes: '1 vendor report renewal pending (Datadog EU renewal contract awaiting counter-signature).', }, ], trustCenterUrl: 'https://trust.uipkge.dev', }, iso27001: { id: 'iso27001', tabLabel: 'ISO 27001', name: 'ISO/IEC 27001:2022 ISMS', badge: 'Information Security Management', standard: 'Annex A Controls (A.5 – A.8) · Stage 2 Ready', score: 94, readinessLabel: '94% Stage 2 Ready', period: 'Audit Cycle 2026–2027', auditor: 'BSI Group · Henrik Lindqvist, Lead Auditor', totalPassing: 88, totalTests: 93, pillars: [ { code: 'A.5', title: 'Organizational Controls', description: 'Information security policies, supplier governance, and asset inventories.', score: 96, passed: 35, total: 37, status: '96% Passed · 35/37 controls', statusVariant: 'success', highlights: ['Approved Security Policies', 'Supplier Risk Classification'], iconType: 'shield', }, { code: 'A.6', title: 'People Controls', description: 'Screening, remote work guidelines, and continuous infosec education.', score: 92, passed: 8, total: 8, status: '92% Passed · 8/8 controls', statusVariant: 'success', highlights: ['Annual Training Certification', 'Formal Disciplinary Rules'], iconType: 'users', }, { code: 'A.7', title: 'Physical Controls', description: 'Physical security perimeters, clear desk, and device screen lock policies.', score: 100, passed: 14, total: 14, status: '100% Passed · 14/14 controls', statusVariant: 'success', highlights: ['Zero Trust Cloud Infrastructure', 'Automated Screen Locking'], iconType: 'lock', }, { code: 'A.8', title: 'Technological Controls', description: 'Endpoint protection, access rights, network security, and vulnerability management.', score: 93, passed: 31, total: 34, status: '93% Passed · 31/34 controls', statusVariant: 'warning', highlights: ['EDR on 100% Managed Laptops', 'Zero Trust Network Architecture'], iconType: 'server', }, ], tests: [ { id: 'test-iso-1', code: 'A.8.2', name: 'Privileged Access Rights Review', description: 'Quarterly review and revocation of administrative privileges on AWS and cloud IdPs.', category: 'Identity & Auth', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'iam-privileged-access-matrix.json', verified: true, lastTested: '8m ago', auditorNotes: 'All root credentials locked behind hardware token in safe storage.', }, { id: 'test-iso-2', code: 'A.8.24', name: 'Use of Cryptography & Key Management', description: 'Enforcement of cryptographic standard policies for data in transit and at rest.', category: 'Cloud Infrastructure', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'crypto-policy-attestation.json', verified: true, lastTested: '15m ago', auditorNotes: 'TLS 1.3 enforced globally. Insecure TLS 1.0/1.1 disabled.', }, { id: 'test-iso-3', code: 'A.5.24', name: 'Infosec Incident Management Plan', description: 'Annual test of incident response playbooks and SIEM real-time alerting integration.', category: 'Security Operations', frequency: 'Quarterly', status: 'Passing', statusVariant: 'success', artifact: 'incident-drill-simulation-2026.pdf', verified: true, lastTested: 'Aug 04, 2026', auditorNotes: 'Mean time to acknowledge (MTTA) under 3 minutes recorded during drill.', }, { id: 'test-iso-4', code: 'A.8.9', name: 'Configuration Management Validation', description: 'Infrastructure-as-Code Terraform state tracking and drift detection alerts.', category: 'DevOps & CI/CD', frequency: 'Daily', status: 'Passing', statusVariant: 'success', artifact: 'terraform-drift-scan-log.json', verified: true, lastTested: '1h ago', auditorNotes: '100% cloud resources provisioned strictly via verified CI pipelines.', }, { id: 'test-iso-5', code: 'A.6.3', name: 'Security Awareness & Training', description: 'Tracking employee onboarding training completion and phishing simulation resilience.', category: 'People & HR', frequency: 'Monthly', status: 'Passing', statusVariant: 'success', artifact: 'knowbe4-training-summary-q2.csv', verified: true, lastTested: 'Aug 18, 2026', auditorNotes: '98.4% staff passed quarterly spear-phishing test simulation.', }, { id: 'test-iso-6', code: 'A.5.19', name: 'Supplier Security Governance', description: 'Formal security evaluation and risk scoring for external vendors processing company data.', category: 'People & HR', frequency: 'Monthly', status: 'Needs Attention', statusVariant: 'warning', artifact: 'iso-vendor-evaluation-register.csv', verified: false, lastTested: '2 days ago', auditorNotes: 'Annual security questionnaire overdue for 2 low-risk sub-contractors.', }, ], trustCenterUrl: 'https://trust.uipkge.dev', }, hipaa: { id: 'hipaa', tabLabel: 'HIPAA Security Rule', name: 'HIPAA Security & Privacy Rule', badge: 'Healthcare & ePHI Protection', standard: '45 CFR Part 160 & Part 164 Subparts A, C, E', score: 98, readinessLabel: '98% Compliant', period: 'Active Assessment · 2026', auditor: 'Coalfire Systems · HIPAA Assessor', totalPassing: 42, totalTests: 43, pillars: [ { code: '164.308', title: 'Administrative Safeguards', description: 'Security management process, workforce clearance, and contingency operations.', score: 97, passed: 18, total: 18, status: '97% Passed · 18/18 tests', statusVariant: 'success', highlights: ['Emergency Mode Operations', 'Violation Sanction Policy'], iconType: 'shield', }, { code: '164.310', title: 'Physical Safeguards', description: 'Facility access controls, workstation security, and device media control.', score: 100, passed: 10, total: 10, status: '100% Passed · 10/10 tests', statusVariant: 'success', highlights: ['Encrypted SSD Storage Media', 'Biometric Facility Access'], iconType: 'lock', }, { code: '164.312', title: 'Technical Safeguards', description: 'ePHI encryption, unique user identification, and automated session timeout.', score: 96, passed: 12, total: 13, status: '96% Passed · 12/13 tests', statusVariant: 'warning', highlights: ['15-Minute Auto-Lock Policy', 'SHA-256 Audit Trail Integrity'], iconType: 'server', }, { code: '164.314', title: 'Organizational Requirements', description: 'Business Associate Agreements (BAAs) with all vendors handling ePHI.', score: 100, passed: 2, total: 2, status: '100% Passed · 2/2 BAAs', statusVariant: 'success', highlights: ['AWS HIPAA BAA Signed', 'Cloudflare HIPAA BAA Signed'], iconType: 'users', }, ], tests: [ { id: 'test-hipaa-1', code: '164.312(a)(1)', name: 'Unique User ePHI Access Identification', description: 'Every healthcare provider and system operator assigned a unique non-shared login.', category: 'Identity & Auth', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'hipaa-identity-access-log.json', verified: true, lastTested: '10m ago', auditorNotes: 'Zero generic or shared accounts found across electronic health records.', }, { id: 'test-hipaa-2', code: '164.312(a)(2)(iii)', name: 'Automatic Logoff Configuration', description: 'System automatically terminates an electronic session after 15 minutes of inactivity.', category: 'Cloud Infrastructure', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'session-timeout-policy-test.json', verified: true, lastTested: '22m ago', auditorNotes: 'Verified on web, desktop app, and clinician mobile portals.', }, { id: 'test-hipaa-3', code: '164.312(b)', name: 'Audit Controls & 6-Year Retention', description: 'Immutable audit logs recording access, modification, and export of electronic patient data.', category: 'Security Operations', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'audit-worm-retention-spec.json', verified: true, lastTested: '5m ago', auditorNotes: 'AWS S3 Object Lock in Compliance Mode active with 6-year retention policy.', }, { id: 'test-hipaa-4', code: '164.312(e)(1)', name: 'Transmission Security TLS 1.3', description: 'ePHI in transit encrypted across public networks using TLS 1.3 with HSTS enabled.', category: 'Cloud Infrastructure', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'tls-cipher-scan-report.json', verified: true, lastTested: '30m ago', auditorNotes: 'A+ SSL Labs score verified on all public API endpoints.', }, { id: 'test-hipaa-5', code: '164.314(a)(1)', name: 'Active BAAs for All Cloud Vendors', description: 'Executed Business Associate Agreements signed with all subprocessors with access to ePHI.', category: 'People & HR', frequency: 'Monthly', status: 'Passing', statusVariant: 'success', artifact: 'signed-baa-register-2026.pdf', verified: true, lastTested: 'Aug 15, 2026', auditorNotes: 'BAA signed with AWS, Twilio, SendGrid, and Datadog.', }, { id: 'test-hipaa-6', code: '164.308(a)(7)', name: 'Contingency & Disaster Recovery Plan', description: 'Documented emergency mode operations and annual disaster recovery failover drill.', category: 'Security Operations', frequency: 'Quarterly', status: 'Needs Attention', statusVariant: 'warning', artifact: 'dr-failover-drill-q2.pdf', verified: false, lastTested: '3 days ago', auditorNotes: 'Q3 secondary region failover drill scheduled for next Tuesday.', }, ], trustCenterUrl: 'https://trust.uipkge.dev', }, gdpr: { id: 'gdpr', tabLabel: 'GDPR', name: 'General Data Protection Regulation', badge: 'Data Privacy & Subject Rights', standard: 'Regulation (EU) 2016/679 · DPO Supervised', score: 95, readinessLabel: '95% Compliant', period: 'Annual Privacy Review · 2026', auditor: 'Internal DPO & Lead Data Authority', totalPassing: 32, totalTests: 34, pillars: [ { code: 'Art 25', title: 'Data Protection by Design', description: 'Pseudonymization, data minimization, and automated retention limits.', score: 94, passed: 9, total: 10, status: '94% Passed · 9/10 tests', statusVariant: 'success', highlights: ['Automated 90-Day PII Purge', 'Data Minimization Schemas'], iconType: 'shield', }, { code: 'Art 30', title: 'Records of Processing (RoPA)', description: 'Complete registry of personal data processing categories and legal purposes.', score: 100, passed: 8, total: 8, status: '100% Passed · 8/8 records', statusVariant: 'success', highlights: ['Dynamic RoPA Data Flow', 'Lawful Basis Cataloged'], iconType: 'file', }, { code: 'Art 32', title: 'Security of Processing', description: 'Technical safeguards, encryption, and regular vulnerability assessments.', score: 96, passed: 11, total: 11, status: '100% Passed · 11/11 tests', statusVariant: 'success', highlights: ['Field-Level PII Encryption', 'Zero-Trust Bastion Access'], iconType: 'lock', }, { code: 'Art 33/34', title: 'Breach Notification Protocol', description: '72-hour supervisory authority notification process and risk assessments.', score: 90, passed: 4, total: 5, status: '90% Passed · 4/5 tests', statusVariant: 'warning', highlights: ['72-Hour DPA Escalation SLA', 'Subject Notification Workflow'], iconType: 'activity', }, ], tests: [ { id: 'test-gdpr-1', code: 'Art 17', name: 'Right to Erasure / DSR Pipeline', description: 'Automated user data deletion across database tables and 3rd party integrations in < 30 days.', category: 'DevOps & CI/CD', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'dsr-erasure-orchestrator.json', verified: true, lastTested: '14m ago', auditorNotes: 'Mean time to complete erasure request: 4.2 hours.', }, { id: 'test-gdpr-2', code: 'Art 30', name: 'RoPA Inventory Live Synchronization', description: 'Data classification tags synced with schema catalog to ensure full records of processing coverage.', category: 'Identity & Auth', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'ropa-schema-mapping-v3.json', verified: true, lastTested: '6m ago', auditorNotes: '100% of PII data fields mapped to lawful basis.', }, { id: 'test-gdpr-3', code: 'Art 28', name: 'Data Processing Agreements (DPAs)', description: 'Standard Contractual Clauses (SCCs) and DPAs executed with all EU data processors.', category: 'People & HR', frequency: 'Monthly', status: 'Passing', statusVariant: 'success', artifact: 'dpa-register-eu-2026.pdf', verified: true, lastTested: 'Aug 10, 2026', auditorNotes: 'All sub-processors compliant with EU-US Data Privacy Framework.', }, { id: 'test-gdpr-4', code: 'Art 7', name: 'Cookie Consent & Preference CMP', description: 'Explicit opt-in banner blocking non-essential tracking prior to affirmative user consent.', category: 'Cloud Infrastructure', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'cmp-consent-telemetry.json', verified: true, lastTested: '1h ago', auditorNotes: 'Zero tracking cookies loaded prior to consent confirmation.', }, { id: 'test-gdpr-5', code: 'Art 32(1)(a)', name: 'PII Field-Level Encryption at Rest', description: 'Names, emails, and financial identifiers hashed or encrypted with AES-256 before storage.', category: 'Cloud Infrastructure', frequency: 'Continuous (1h)', status: 'Passing', statusVariant: 'success', artifact: 'field-encryption-audit.json', verified: true, lastTested: '25m ago', auditorNotes: 'KMS envelope encryption active on all customer records.', }, { id: 'test-gdpr-6', code: 'Art 33', name: '72-Hour Breach Notification Drill', description: 'Tabletop simulation testing supervisory authority DPA notification within statutory 72h window.', category: 'Security Operations', frequency: 'Quarterly', status: 'Needs Attention', statusVariant: 'warning', artifact: 'gdpr-breach-playbook-2026.pdf', verified: false, lastTested: '4 days ago', auditorNotes: 'DPO escalation contact list updated; tabletop review due in Q3.', }, ], trustCenterUrl: 'https://trust.uipkge.dev', }, } @Component({ changeDetection: ChangeDetectionStrategy.Eager, selector: 'ui-compliance-soc2-readiness, [ui-compliance-soc2-readiness]', standalone: true, // React renders the root <div> itself: the host stays out of layout and `class` goes to the root. host: { '[attr.class]': '"contents"' }, imports: [ LucideAngularModule, UiBadgeComponent, UiButtonComponent, UiCardComponent, UiCardContentComponent, UiCardDescriptionComponent, UiCardHeaderComponent, UiCardTitleComponent, UiProgressComponent, UiSeparatorComponent, UiTableBodyComponent, UiTableCellComponent, UiTableComponent, UiTableHeadComponent, UiTableHeaderComponent, UiTableRowComponent, UiTabsComponent, UiTabsListComponent, UiTabsTriggerComponent, ], template: ` <div data-slot="compliance-soc2-readiness" [class]="rootClass"> <!-- Framework Selector Tabs --> <ui-tabs [value]="activeFrameworkId()" (valueChange)="activeFrameworkId.set($event)" class="w-full"> <div class="flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between"> <ui-tabs-list class="grid w-full grid-cols-2 md:w-auto md:grid-cols-4"> <button ui-tabs-trigger value="soc2" class="text-xs font-medium">SOC 2 Type II</button> <button ui-tabs-trigger value="iso27001" class="text-xs font-medium">ISO 27001</button> <button ui-tabs-trigger value="hipaa" class="text-xs font-medium">HIPAA Security Rule</button> <button ui-tabs-trigger value="gdpr" class="text-xs font-medium">GDPR</button> </ui-tabs-list> <div class="text-muted-foreground flex items-center gap-2 text-xs"> <span class="bg-success inline-flex size-2 rounded-full"></span> <span>Real-time Telemetry Ingestion Active</span> </div> </div> <!-- Executive Overview Card --> <div ui-card class="border-border bg-card mt-4 shadow-xs"> <div ui-card-content class="p-6"> <div class="flex flex-col gap-6 lg:flex-row lg:items-center lg:justify-between"> <!-- Left: Framework info --> <div class="space-y-2"> <div class="flex flex-wrap items-center gap-2.5"> <h1 class="text-foreground text-xl font-bold tracking-tight sm:text-2xl"> {{ currentFramework().name }} </h1> <span ui-badge variant="secondary" class="font-medium"> {{ currentFramework().badge }} </span> </div> <p class="text-muted-foreground text-xs sm:text-sm"> {{ currentFramework().standard }} </p> <div class="text-muted-foreground flex flex-wrap items-center gap-3 pt-1 text-xs"> <span ui-badge variant="outline" class="gap-1.5 font-normal"> <lucide-icon [img]="Calendar" class="size-3.5" /> {{ currentFramework().period }} </span> <div ui-separator orientation="vertical" class="hidden h-3.5 sm:block"></div> <span> Lead Assessor: <strong class="text-foreground font-medium">{{ currentFramework().auditor }}</strong> </span> </div> </div> <!-- Right: Big Score Card & Action Buttons --> <div class="flex flex-col gap-4 sm:flex-row sm:items-center"> <!-- Score Badge --> <div class="border-success/30 bg-success/10 flex items-center gap-3.5 rounded-xl border p-3.5 shadow-xs" > <div class="bg-success/20 text-success flex size-11 shrink-0 items-center justify-center rounded-lg"> <lucide-icon [img]="ShieldCheck" class="size-6" /> </div> <div class="space-y-0.5"> <div class="flex items-baseline gap-2"> <span class="text-success text-2xl font-bold tracking-tight tabular-nums sm:text-3xl"> {{ currentFramework().score }}% </span> <span ui-badge variant="success" class="gap-1 px-2 text-xs font-semibold"> <lucide-icon [img]="CheckCircle2" class="size-3" /> {{ readinessShort() }} </span> </div> <p class="text-muted-foreground text-xs"> {{ currentFramework().totalPassing }}/{{ currentFramework().totalTests }} Continuous Controls Passing </p> </div> </div> <!-- Action Buttons --> <div class="flex flex-wrap gap-2.5 sm:flex-col"> <button ui-button variant="default" size="sm" class="gap-2 shadow-xs" (click)="handleScheduleReview()" > @if (scheduleRequested()) { <lucide-icon [img]="Check" class="text-success size-4" /> } @else { <lucide-icon [img]="Calendar" class="size-4" /> } <span>{{ scheduleRequested() ? 'Review Requested!' : 'Schedule Auditor Review' }}</span> </button> <button ui-button variant="outline" size="sm" class="gap-2 shadow-xs" (click)="handleExportPackage()"> @if (exportSuccess()) { <lucide-icon [img]="Check" class="text-success size-4" /> } @else { <lucide-icon [img]="FileDown" class="size-4" /> } <span>{{ exportSuccess() ? 'Package Exported!' : 'Export Compliance Package' }}</span> </button> </div> </div> </div> </div> </div> <!-- 4 Compliance Control Pillar Cards --> <div class="mt-6 grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4"> @for (pillar of currentFramework().pillars; track pillar.code) { <div ui-card class="border-border bg-card hover:border-border shadow-xs transition-colors"> <div ui-card-header class="p-4 pb-2"> <div class="flex items-start justify-between gap-2"> <div class="flex items-center gap-2"> <div class="bg-muted text-foreground border-border flex size-8 shrink-0 items-center justify-center rounded-lg border" > <lucide-icon [img]="pillarIcon(pillar.iconType)" class="size-4" /> </div> <span ui-badge variant="outline" class="font-mono text-xs font-semibold"> {{ pillar.code }} </span> </div> <span ui-badge [variant]="pillar.statusVariant" class="text-xs font-medium"> {{ pillarChip(pillar) }} </span> </div> <h3 ui-card-title class="mt-2 text-sm leading-snug font-semibold"> {{ pillar.title }} </h3> <p ui-card-description class="line-clamp-2 text-xs"> {{ pillar.description }} </p> </div> <div ui-card-content class="space-y-3 p-4 pt-1"> <div class="space-y-1.5"> <div class="flex flex-wrap items-baseline justify-between gap-x-2 gap-y-0.5 text-xs"> <span class="text-foreground text-2xl font-bold tracking-tight tabular-nums"> {{ pillar.score }}% </span> <span class="text-muted-foreground font-medium tabular-nums"> {{ pillar.passed }}/{{ pillar.total }} tests </span> </div> <div ui-progress [value]="pillar.score" class="h-1.5 w-full"></div> </div> <!-- Bullet highlights --> <div class="bg-muted/40 border-border/60 space-y-1 rounded-md border p-2 text-xs"> @for (highlight of pillar.highlights; track highlight) { <div class="text-muted-foreground flex items-center gap-1.5"> <lucide-icon [img]="CheckCircle2" class="text-success size-3 shrink-0" /> <span class="truncate">{{ highlight }}</span> </div> } </div> </div> </div> } </div> <!-- Automated Evidence Tests Table Card --> <div ui-card class="border-border bg-card mt-6 shadow-xs"> <div ui-card-header class="flex flex-col gap-4 pb-4 sm:flex-row sm:items-center sm:justify-between"> <div> <div class="flex items-center gap-2"> <h3 ui-card-title class="text-base font-semibold">Automated Evidence Tests</h3> <span ui-badge variant="secondary" class="font-mono text-xs"> {{ filteredTests().length }} Active </span> </div> <p ui-card-description class="text-xs"> Continuous synthetic and policy compliance evaluation across infrastructure and IAM. </p> </div> <div class="flex flex-wrap items-center gap-2"> <button ui-button variant="outline" size="sm" class="gap-1.5 text-xs shadow-xs" [disabled]="isTestingAll()" (click)="handleRunAllTests()" > <lucide-icon [img]="RefreshCw" [class]="runAllIconClass" /> <span>{{ isTestingAll() ? 'Evaluating Tests...' : 'Run All Automated Tests' }}</span> </button> </div> </div> <!-- Filter & Search Toolbar --> <div class="border-border/60 border-t p-4 pt-3 pb-3"> <div class="flex flex-col gap-3 lg:flex-row lg:items-center lg:justify-between"> <div class="relative flex-1"> <lucide-icon [img]="Search" class="text-muted-foreground pointer-events-none absolute top-1/2 left-3 size-3.5 -translate-y-1/2" /> <input [value]="searchQuery()" (input)="searchQuery.set($any($event.target).value)" type="text" placeholder="Filter by control code, name, category, or evidence artifact..." class="border-border bg-background placeholder:text-muted-foreground focus-visible:ring-ring h-8 w-full rounded-md border px-3 pl-8 text-xs focus-visible:ring-2 focus-visible:outline-none" /> </div> <div class="flex flex-wrap items-center gap-1.5"> <span class="text-muted-foreground mr-1 flex items-center gap-1 text-xs font-medium"> <lucide-icon [img]="Filter" class="size-3" /> Category: </span> @for (cat of availableCategories(); track cat) { <button type="button" [class]="categoryPillClass(cat)" (click)="selectedCategory.set(cat)"> {{ cat === 'all' ? 'All Categories' : cat }} </button> } </div> </div> </div> <!-- Table Container --> <div ui-card-content class="p-0"> <div class="border-border/60 overflow-x-auto border-t"> <table ui-table> <thead ui-table-header class="bg-muted/50"> <tr ui-table-row> <th ui-table-head class="min-w-[220px] text-xs">Control & Rule Name</th> <th ui-table-head class="text-xs">Domain Category</th> <th ui-table-head class="text-xs">Frequency</th> <th ui-table-head class="text-xs">Status</th> <th ui-table-head class="text-xs">Evidence Artifact</th> <th ui-table-head class="text-right text-xs">Actions</th> </tr> </thead> <tbody ui-table-body> @for (test of filteredTests(); track test.id) { <tr ui-table-row class="hover:bg-muted/20"> <!-- Control Code & Name --> <td ui-table-cell class="py-3"> <div class="space-y-0.5"> <div class="flex items-center gap-2"> <span class="text-foreground font-mono text-xs font-bold">{{ test.code }}</span> <span class="text-foreground text-xs font-semibold">{{ test.name }}</span> </div> <p class="text-muted-foreground max-w-sm text-xs leading-relaxed sm:max-w-md"> {{ test.description }} </p> </div> </td> <!-- Category --> <td ui-table-cell class="py-3"> <span ui-badge variant="outline" class="text-xs font-normal"> {{ test.category }} </span> </td> <!-- Frequency --> <td ui-table-cell class="text-muted-foreground py-3 text-xs"> <div class="flex items-center gap-1.5 font-medium"> <lucide-icon [img]="Clock" class="size-3.5" /> <span>{{ test.frequency }}</span> </div> <span class="text-muted-foreground/70 block text-xs"> Tested: {{ lastTestedFor(test) }} </span> </td> <!-- Status --> <td ui-table-cell class="py-3"> <span ui-badge [variant]="test.statusVariant" class="gap-1 text-xs font-medium"> @if (test.status === 'Passing') { <lucide-icon [img]="CheckCircle2" class="size-3" /> } @else { <lucide-icon [img]="AlertTriangle" class="size-3" /> } {{ test.status }} </span> </td> <!-- Evidence Artifact Link --> <td ui-table-cell class="py-3"> <button type="button" class="hover:border-primary/40 hover:bg-muted/60 focus-visible:ring-ring group border-border/80 bg-muted/30 flex items-center gap-1.5 rounded-md border px-2 py-1 text-left transition-colors focus-visible:ring-2 focus-visible:outline-none" (click)="viewEvidence(test)" > <lucide-icon [img]="FileText" class="text-muted-foreground group-hover:text-foreground size-3.5 shrink-0" /> <span class="text-foreground max-w-[150px] truncate font-mono text-xs sm:max-w-[200px]"> {{ test.artifact }} </span> @if (test.verified) { <lucide-icon [img]="CheckCircle2" class="text-success size-3 shrink-0" /> } </button> </td> <!-- Action Buttons --> <td ui-table-cell class="py-3 text-right"> <div class="flex items-center justify-end gap-1.5"> <button ui-button variant="ghost" size="xs" class="h-7 gap-1 text-xs" [disabled]="isRunning(test.id)" (click)="handleRunTest(test.id)" > <lucide-icon [img]="RefreshCw" [class]="runIconClass(test.id)" /> <span class="hidden sm:inline">Test Now</span> </button> <button ui-button variant="outline" size="xs" class="h-7 gap-1 text-xs" (click)="viewEvidence(test)" > <lucide-icon [img]="Eye" class="size-3" /> <span>Evidence</span> </button> </div> </td> </tr> } @if (filteredTests().length === 0) { <tr ui-table-row> <td ui-table-cell colspan="6" class="py-8 text-center"> <p class="text-muted-foreground text-xs">No automated compliance tests match your query.</p> </td> </tr> } </tbody> </table> </div> </div> </div> <!-- Auditor Access & Trust Center Preview Strip --> <div ui-card class="border-border bg-card mt-6 overflow-hidden shadow-xs"> <div ui-card-content class="p-6"> <div class="flex flex-col gap-6 lg:flex-row lg:items-center lg:justify-between"> <div class="flex items-start gap-4"> <div class="bg-primary/10 text-primary border-primary/20 flex size-11 shrink-0 items-center justify-center rounded-xl border" > <lucide-icon [img]="BadgeCheck" class="size-6" /> </div> <div class="space-y-1"> <div class="flex flex-wrap items-center gap-2"> <h3 class="text-foreground text-base font-semibold">Auditor Access & Public Trust Center</h3> <span ui-badge variant="outline" class="gap-1 font-mono text-xs"> <span class="bg-success size-1.5 rounded-full"></span> Vault Online </span> </div> <p class="text-muted-foreground text-xs leading-relaxed sm:text-sm"> Cryptographically verifiable evidence room configured for continuous compliance review by <strong class="text-foreground font-medium">{{ currentFramework().auditor }}</strong >. </p> <div class="text-muted-foreground flex flex-wrap items-center gap-3 pt-1 text-xs"> <span>Access Grant: <strong class="text-foreground font-medium">Valid for 14 days</strong></span> <div ui-separator orientation="vertical" class="hidden h-3 sm:block"></div> <span >Trust Portal: <span class="text-foreground font-mono">{{ currentFramework().trustCenterUrl }}</span></span > </div> </div> </div> <div class="flex flex-wrap items-center gap-2.5 sm:self-start lg:self-center"> <a [href]="currentFramework().trustCenterUrl" target="_blank" rel="noreferrer" class="inline-flex"> <button ui-button variant="outline" size="sm" class="gap-1.5 shadow-xs"> <lucide-icon [img]="ArrowUpRight" class="size-4" /> <span>Preview Live Trust Center</span> </button> </a> <button ui-button variant="secondary" size="sm" class="gap-1.5 shadow-xs"> <lucide-icon [img]="KeyRound" class="size-4" /> <span>Manage Auditor Access</span> </button> </div> </div> </div> <!-- Bottom Audit Ingestion Watermark --> <div class="bg-muted/40 border-border flex flex-col gap-2 border-t px-6 py-2.5 text-xs sm:flex-row sm:items-center sm:justify-between" > <div class="text-muted-foreground flex items-center gap-2 font-mono"> <span class="bg-success size-1.5 rounded-full"></span> <span>Ledger Stamp: 0x9b4a8e217f0a4421b8c1992019a · SHA-256 Verified</span> </div> <span class="text-muted-foreground font-mono text-xs"> Framework: {{ currentFramework().tabLabel }} · Last Evaluation: Just now </span> </div> </div> </ui-tabs> <!-- Modal / Sheet Preview for Evidence Artifact --> @if (activeEvidenceModal(); as modal) { <div role="dialog" aria-modal="true" class="bg-background/80 fixed inset-0 z-50 flex items-center justify-center p-4 backdrop-blur-sm" (click)="closeEvidenceModal()" > <div ui-card class="border-border bg-card w-full max-w-lg shadow-lg" (click)="$event.stopPropagation()"> <div ui-card-header class="flex flex-row items-center justify-between pb-3"> <div class="space-y-1"> <div class="flex items-center gap-2"> <span ui-badge variant="outline" class="font-mono text-xs">{{ modal.code }}</span> <h3 ui-card-title class="text-base font-semibold">Evidence Verification Details</h3> </div> <p ui-card-description class="text-xs">{{ modal.name }}</p> </div> <button ui-button variant="ghost" size="icon-sm" class="size-7" aria-label="Close evidence modal" (click)="closeEvidenceModal()" > <lucide-icon [img]="X" class="size-4" /> </button> </div> <div ui-card-content class="space-y-4 text-xs"> <div class="bg-muted/40 border-border/80 space-y-2 rounded-lg border p-3"> <div class="flex items-center justify-between"> <span class="text-muted-foreground font-medium">Artifact File:</span> <span class="text-foreground font-mono font-semibold">{{ modal.artifact }}</span> </div> <div class="flex items-center justify-between"> <span class="text-muted-foreground font-medium">Verification Status:</span> <span ui-badge [variant]="modal.statusVariant" class="gap-1 text-xs"> @if (modal.verified) { <lucide-icon [img]="CheckCircle2" class="size-3" /> } @else { <lucide-icon [img]="AlertCircle" class="size-3" /> } {{ modal.verified ? 'Cryptographically Verified' : 'Action Required' }} </span> </div> <div class="flex items-center justify-between"> <span class="text-muted-foreground font-medium">Test Frequency:</span> <span class="text-foreground font-mono">{{ modal.frequency }}</span> </div> </div> <div class="space-y-1.5"> <span class="text-muted-foreground font-medium">Auditor Evaluation Notes:</span> <p class="bg-muted/20 border-border text-foreground rounded-md border p-2.5 leading-relaxed"> {{ modal.auditorNotes }} </p> </div> <div class="flex items-center justify-end gap-2 pt-2"> <button aria-label="Close evidence modal" ui-button variant="outline" size="sm" class="text-xs" (click)="closeEvidenceModal()" > Close </button> <button aria-label="Close evidence modal" ui-button variant="default" size="sm" class="gap-1.5 text-xs" (click)="closeEvidenceModal()" > <lucide-icon [img]="Download" class="size-3.5" /> Download Artifact </button> </div> </div> </div> </div> } </div> `, }) export class UiComplianceSoc2ReadinessComponent { protected readonly AlertCircle = AlertCircle protected readonly AlertTriangle = AlertTriangle protected readonly ArrowUpRight = ArrowUpRight protected readonly BadgeCheck = BadgeCheck protected readonly Calendar = Calendar protected readonly Check = Check protected readonly CheckCircle2 = CheckCircle2 protected readonly Clock = Clock protected readonly Download = Download protected readonly Eye = Eye protected readonly FileDown = FileDown protected readonly FileText = FileText protected readonly Filter = Filter protected readonly KeyRound = KeyRound protected readonly Lock = Lock protected readonly RefreshCw = RefreshCw protected readonly Search = Search protected readonly Server = Server protected readonly Shield = Shield protected readonly ShieldCheck = ShieldCheck protected readonly Users = Users protected readonly X = X protected readonly Zap = Zap @Input() set defaultFramework(v: string | undefined) { if (v) this.activeFrameworkId.set(v) } @Input('class') className?: string readonly activeFrameworkId = signal('soc2') readonly searchQuery = signal('') readonly selectedCategory = signal<string>('all') readonly runningTestIds = signal<Record<string, boolean>>({}) readonly lastTestedMap = signal<Record<string, string>>({}) readonly activeEvidenceModal = signal<EvidenceTestItem | null>(null) readonly isTestingAll = signal(false) readonly scheduleRequested = signal(false) readonly exportSuccess = signal(false) readonly currentFramework = computed(() => frameworksData[this.activeFrameworkId()] ?? frameworksData['soc2']!) readonly readinessShort = computed(() => { const fw = this.currentFramework() return fw.readinessLabel.replace(`${fw.score}% `, '') }) readonly availableCategories = computed(() => { const cats = new Set<string>() this.currentFramework().tests.forEach((t) => cats.add(t.category)) return ['all', ...Array.from(cats)] }) readonly filteredTests = computed(() => { const q = this.searchQuery().trim().toLowerCase() const cat = this.selectedCategory() return this.currentFramework().tests.filter((test) => { const matchesCat = cat === 'all' || test.category === cat const matchesQuery = !q || test.code.toLowerCase().includes(q) || test.name.toLowerCase().includes(q) || test.description.toLowerCase().includes(q) || test.artifact.toLowerCase().includes(q) || test.category.toLowerCase().includes(q) return matchesCat && matchesQuery }) }) get rootClass(): string { return cn('w-full space-y-6', this.className) } get runAllIconClass(): string { return cn('size-3.5', this.isTestingAll() && 'animate-spin') } runIconClass(id: string): string { return cn('size-3', this.isRunning(id) && 'animate-spin') } categoryPillClass(cat: string): string { return cn( 'focus-visible:ring-ring inline-flex items-center rounded-full border px-2.5 py-1 text-xs font-medium transition-colors focus-visible:ring-2 focus-visible:outline-none', this.selectedCategory() === cat ? 'border-primary bg-primary text-primary-foreground shadow-xs' : 'border-border bg-card text-muted-foreground hover:bg-accent hover:text-foreground', ) } pillarIcon(iconType: string): unknown { switch (iconType) { case 'key': return KeyRound case 'shield': return ShieldCheck case 'activity': return Zap case 'users': return Users case 'lock': return Lock case 'server': return Server case 'file': return FileText default: return Shield } } pillarChip(pillar: PillarData): string { if (pillar.score === 100) return 'Zero Gaps' if (pillar.statusVariant === 'warning') return '1 Warning' return 'Passing' } isRunning(id: string): boolean { return !!this.runningTestIds()[id] } lastTestedFor(test: EvidenceTestItem): string { return this.lastTestedMap()[test.id] ?? test.lastTested } handleRunTest(testId: string): void { this.runningTestIds.update((prev) => ({ ...prev, [testId]: true })) setTimeout(() => { this.runningTestIds.update((prev) => ({ ...prev, [testId]: false })) this.lastTestedMap.update((prev) => ({ ...prev, [testId]: 'Just now' })) }, 500) } handleRunAllTests(): void { this.isTestingAll.set(true) setTimeout(() => { this.isTestingAll.set(false) const next: Record<string, string> = {} this.currentFramework().tests.forEach((t) => { next[t.id] = 'Just now' }) this.lastTestedMap.update((prev) => ({ ...prev, ...next })) }, 700) } handleScheduleReview(): void { this.scheduleRequested.set(true) setTimeout(() => this.scheduleRequested.set(false), 3000) } handleExportPackage(): void { this.exportSuccess.set(true) setTimeout(() => this.exportSuccess.set(false), 3000) } viewEvidence(test: EvidenceTestItem): void { this.activeEvidenceModal.set(test) } closeEvidenceModal(): void { this.activeEvidenceModal.set(null) } }src/app/components/blocks/compliance-soc2-readiness/index.ts0.2 kB
export { UiComplianceSoc2ReadinessComponent, type PillarData, type EvidenceTestItem, type FrameworkConfig, } from './compliance-soc2-readiness.component'
Raw manifest:https://uipkge.dev/r/angular/compliance-soc2-readiness.json