This guide covers the compliance framework plugin system in VerifyWise.
- Overview
- Framework Types
- Available Frameworks
- Framework Plugin Architecture
- Adding a New Framework
- Region System
- UI Integration
- Custom Framework Import Package
Framework plugins provide compliance frameworks that can be added to projects. They appear in:
- Plugins Page > Frameworks Tab: Grouped by geographic region
- Project Setup: Framework selection when creating projects
- Controls Tab: Framework-specific controls and requirements
- Dashboard: Compliance progress tracking
Frameworks are classified into two types based on their scope and applicability:
Definition: Frameworks that apply to the entire organization. These are managed at the org level with a single org-level project containing all organizational compliance controls.
Use Cases:
- Legal/regulatory requirements (GDPR, CCPA, PDPL laws)
- Organization-wide certifications (SOC 2, ISO 27001)
- Company-wide security standards (NIST CSF, CIS Controls)
- Enterprise governance (Data Governance)
Behavior:
- One org-level project per organization
- All organizational frameworks are enabled in this single project
- Compliance tracked at organization level
Definition: Frameworks that apply only to specific projects based on their characteristics. Different projects may need different frameworks.
Use Cases:
- PCI-DSS: Only projects handling payment card data
- HIPAA: Only projects handling protected health information (PHI)
- AI Ethics: Only projects using AI/ML systems
Behavior:
- Can be enabled per individual project
- Projects can have different combinations of frameworks
- Compliance tracked at project level
The framework type is configured in two places:
- template.json (
is_organizationalfield):
{
"framework": {
"is_organizational": true // or false for project-level
}
}- plugins.json (
frameworkTypefield):
{
"key": "soc2",
"frameworkType": "organizational" // or "project"
}Important: Both values should match. The
is_organizationalin template.json controls database behavior, whileframeworkTypein plugins.json controls UI display.
| Framework | Key | Type | Description |
|---|---|---|---|
| ISO 27001 | iso27001 |
๐ข Org | Information security management systems |
| PCI-DSS | pci-dss |
๐ Project | Payment card data security |
| CIS Controls v8 | cis-controls |
๐ข Org | Critical security controls |
| AI Ethics | ai-ethics |
๐ Project | Responsible AI governance |
| OECD AI Principles | oecd-ai-principles |
๐ Project | G20-endorsed international AI standard |
| Data Governance | data-governance |
๐ข Org | Enterprise data management |
| Framework | Key | Type | Description |
|---|---|---|---|
| SOC 2 Type II | soc2 |
๐ข Org | Trust Service Criteria |
| HIPAA | hipaa |
๐ Project | Healthcare data protection |
| CCPA | ccpa |
๐ข Org | California consumer privacy |
| NIST CSF | nist-csf |
๐ข Org | Cybersecurity framework |
| Texas AI Act | texas-ai-act |
๐ Project | Texas Responsible AI Governance Act (TRAIGA) |
| Colorado AI Act | colorado-ai-act |
๐ Project | Colorado AI Act for algorithmic discrimination prevention |
| FTC AI Guidelines | ftc-ai-guidelines |
๐ Project | Federal Trade Commission AI guidance for consumer protection |
| NYC Local Law 144 | nyc-local-law-144 |
๐ Project | Automated employment decision tools (AEDT) bias audits |
| Framework | Key | Type | Description |
|---|---|---|---|
| Quebec Law 25 | quebec-law25 |
๐ข Org | Quebec Bill 64 privacy protection |
| Framework | Key | Type | Description |
|---|---|---|---|
| GDPR | gdpr |
๐ข Org | General Data Protection Regulation |
| DORA | dora |
๐ข Org | Digital Operational Resilience Act |
| ALTAI | altai |
๐ Project | Assessment List for Trustworthy AI (EU Commission) |
| Framework | Key | Type | Description |
|---|---|---|---|
| UAE PDPL | uae-pdpl |
๐ข Org | Personal Data Protection Law 45/2021, DIFC Regulation 10, AI Ethics Charter |
| Framework | Key | Type | Description |
|---|---|---|---|
| Saudi PDPL | saudi-pdpl |
๐ข Org | Personal Data Protection Law, SDAIA Ethics Principles, Generative AI Guidelines |
| Framework | Key | Type | Description |
|---|---|---|---|
| Qatar PDPL | qatar-pdpl |
๐ข Org | Personal Data Privacy Law 13/2016, National AI Policy |
| Framework | Key | Type | Description |
|---|---|---|---|
| Bahrain PDPL | bahrain-pdpl |
๐ข Org | Personal Data Protection Law 30/2018, CBB AI Notice, EDB AI Ethics Pledge |
plugins/
โโโ {framework-key}/
โโโ template.json # REQUIRED: Framework structure (controls, requirements)
โโโ icon.svg # Framework icon
โโโ index.ts # Auto-generated from template.json
โโโ dist/
โ โโโ index.js # Built backend (auto-generated)
โโโ ui/
โโโ dist/ # Copied from packages/custom-framework-ui/dist/
โโโ index.esm.js # Shared UI bundle (~1.1MB)
CRITICAL: The
template.jsonfile is REQUIRED for framework plugins. Without it:
- The plugin will install successfully
- But NO framework will appear in Settings > Custom Frameworks
- Users will see the plugin as "installed" but it won't do anything
The
template.jsoncontains the actual framework structure (chapters, controls, articles, evidence examples, etc.) that gets imported into the database when the plugin is installed.
{
"key": "soc2",
"name": "SOC 2 Type II",
"displayName": "SOC 2 Type II",
"description": "SOC 2 Type II compliance framework based on Trust Service Criteria.",
"region": "United States",
"frameworkType": "organizational",
"longDescription": "SOC 2 Type II framework plugin provides comprehensive Trust Service Criteria (TSC) compliance management...",
"version": "1.0.0",
"author": "VerifyWise",
"category": "compliance",
"iconUrl": "plugins/soc2/icon.svg",
"isOfficial": true,
"isPublished": true,
"requiresConfiguration": false,
"installationType": "tenant_scoped",
"features": [
{
"name": "Trust Service Criteria",
"description": "Complete TSC coverage: Security, Availability, Processing Integrity, Confidentiality, Privacy",
"displayOrder": 1
},
{
"name": "Auto-Import",
"description": "Framework automatically imported on plugin installation",
"displayOrder": 2
}
],
"tags": ["soc2", "audit", "trust-services", "compliance", "security"],
"pluginPath": "plugins/soc2",
"entryPoint": "dist/index.js",
"dependencies": {},
"ui": {
"bundleUrl": "/api/plugins/soc2/ui/dist/index.esm.js",
"globalName": "PluginCustomFrameworkImport",
"slots": [
{
"slotId": "modal.framework.selection",
"componentName": "CustomFrameworkCards",
"renderType": "raw",
"props": { "pluginKey": "soc2" }
},
{
"slotId": "page.controls.custom-framework",
"componentName": "CustomFrameworkControls",
"renderType": "raw",
"props": { "pluginKey": "soc2" }
},
{
"slotId": "page.framework-dashboard.custom",
"componentName": "CustomFrameworkDashboard",
"renderType": "raw",
"props": { "pluginKey": "soc2" }
},
{
"slotId": "page.project-overview.custom-framework",
"componentName": "CustomFrameworkOverview",
"renderType": "raw",
"props": { "pluginKey": "soc2" }
}
]
}
}mkdir -p plugins/my-framework/{dist,ui/dist}This is the most important file. It defines the actual framework structure that gets imported into the database.
Create plugins/my-framework/template.json:
{
"id": "my-framework",
"name": "My Framework Name",
"description": "Brief description of the framework.",
"category": "Compliance",
"tags": ["compliance", "framework"],
"framework": {
"name": "My Framework Name",
"description": "Detailed description for the framework",
"version": "1.0.0",
"is_organizational": true,
"hierarchy": {
"type": "two_level",
"level1_name": "Category",
"level2_name": "Control"
},
"structure": [
{
"title": "Category 1: Example Category",
"description": "Description of this category",
"order_no": 1,
"items": [
{
"title": "Control 1.1 - Example Control",
"description": "What this control requires",
"order_no": 1,
"summary": "Brief summary of the control",
"questions": [
"Is requirement X met?",
"Is requirement Y documented?"
],
"evidence_examples": [
"Policy document",
"Audit logs",
"Training records"
]
}
]
}
]
}
}Template Structure:
hierarchy.type: Use"two_level"for Category โ Control, or"three_level"for Category โ Subcategory โ Controlhierarchy.level1_name,level2_name,level3_name: Labels shown in the UI (e.g., "Chapter", "Article", "Requirement")is_organizational:truefor org-level frameworks,falsefor project-specificstructure: Array of level 1 items, each containingitemsarray for level 2
{
"key": "my-framework",
"name": "My Framework",
"displayName": "My Framework",
"description": "Brief description of the framework.",
"region": "International",
"frameworkType": "organizational",
"version": "1.0.0",
"author": "VerifyWise",
"category": "compliance",
"iconUrl": "plugins/my-framework/icon.svg",
"isOfficial": true,
"isPublished": true,
"requiresConfiguration": false,
"installationType": "tenant_scoped",
"features": [
{
"name": "Key Feature",
"description": "What this framework provides",
"displayOrder": 1
}
],
"tags": ["compliance", "framework", "my-framework"],
"pluginPath": "plugins/my-framework",
"entryPoint": "dist/index.js",
"dependencies": {},
"ui": {
"bundleUrl": "/api/plugins/my-framework/ui/dist/index.esm.js",
"globalName": "PluginCustomFrameworkImport",
"slots": [
{
"slotId": "modal.framework.selection",
"componentName": "CustomFrameworkCards",
"renderType": "raw",
"props": { "pluginKey": "my-framework" }
},
{
"slotId": "page.controls.custom-framework",
"componentName": "CustomFrameworkControls",
"renderType": "raw",
"props": { "pluginKey": "my-framework" }
},
{
"slotId": "page.framework-dashboard.custom",
"componentName": "CustomFrameworkDashboard",
"renderType": "raw",
"props": { "pluginKey": "my-framework" }
},
{
"slotId": "page.project-overview.custom-framework",
"componentName": "CustomFrameworkOverview",
"renderType": "raw",
"props": { "pluginKey": "my-framework" }
}
]
}
}Create plugins/my-framework/icon.svg:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" fill="none">
<rect width="48" height="48" rx="10" fill="#F0FDF4"/>
<path d="M24 8L38 15V24C38 32.28 32.11 39.95 24 42C15.89 39.95 10 32.28 10 24V15L24 8Z"
fill="#DCFCE7" stroke="#16A34A" stroke-width="2.5" stroke-linejoin="round"/>
<path d="M17 25L22 30L31 21" stroke="#16A34A" stroke-width="3"
stroke-linecap="round" stroke-linejoin="round"/>
</svg>The build script automatically:
- Reads your
template.json - Generates
index.tsfrom it - Compiles to
dist/index.js - Copies shared UI bundle from
packages/custom-framework-ui/dist/toui/dist/
# Build a specific framework plugin
npm run build:framework-plugins -- my-framework
# Or build all framework plugins
npm run build:framework-plugins
# If shared UI code changed, rebuild it first
npm run build:custom-framework-ui
npm run build:framework-pluginsWithout this step, the plugin will not work. The dist/index.js contains the logic that imports the framework template into the database on installation.
Copy the built plugin to the VerifyWise server cache:
cp -r plugins/my-framework /path/to/verifywise/Servers/temp/plugins/- Go to Plugins > Frameworks tab
- Find your framework and click Install
- The framework template will auto-import to the database
- Verify in Settings > Custom Frameworks that the framework appears
Before considering a framework plugin complete, verify:
-
template.jsonexists with valid framework structure -
template.jsonhas correctis_organizationalvalue (true/false) -
icon.svgexists - Plugin entry added to
plugins.jsonwithcategory: "compliance" -
frameworkTypeset in plugins.json ("organizational" or "project") -
frameworkTypematchesis_organizationalin template.json - Plugin built with
npm run build:framework-plugins -
dist/index.jsexists (created by build) - Plugin copied to server cache
- Plugin installed successfully
- Framework appears in Settings > Custom Frameworks (this is the real test!)
- Framework type badge displays correctly in Plugins > Frameworks
All framework plugins share the same UI bundle from packages/custom-framework-ui/. This avoids duplicating ~1.1MB of React code for each plugin.
npm run build:custom-framework-uiThis builds to packages/custom-framework-ui/dist/index.esm.js.
The build:framework-plugins script automatically copies the shared UI to each plugin's ui/dist/ folder. You don't need to manually copy files.
# Rebuilds all framework plugins AND copies the shared UI
npm run build:framework-plugins- Each framework plugin has a
regionfield in plugins.json - The frontend reads this field and groups frameworks
- Flags are mapped in the frontend code
const regionFlags: Record<string, string> = {
"International": "๐",
"United States": "๐บ๐ธ",
"European Union": "๐ช๐บ",
"Canada": "๐จ๐ฆ",
"United Kingdom": "๐ฌ๐ง",
"Australia": "๐ฆ๐บ",
"Singapore": "๐ธ๐ฌ",
"India": "๐ฎ๐ณ",
"Japan": "๐ฏ๐ต",
"Brazil": "๐ง๐ท",
"Mexico": "๐ฒ๐ฝ",
"United Arab Emirates": "๐ฆ๐ช",
"Saudi Arabia": "๐ธ๐ฆ",
"Qatar": "๐ถ๐ฆ",
"Bahrain": "๐ง๐ญ",
"Kuwait": "๐ฐ๐ผ",
"Oman": "๐ด๐ฒ",
"Other": "๐",
};- In plugins.json: Set the
regionfield to your new region name
{
"key": "lgpd",
"region": "Brazil",
...
}- In the frontend (optional): Add flag mapping if not already present
File: Clients/src/presentation/pages/Plugins/index.tsx
const regionFlags: Record<string, string> = {
// ... existing regions
"Brazil": "๐ง๐ท",
};Regions are sorted alphabetically with these exceptions:
- "International" always appears first
- "Other" always appears last
| Slot ID | Location | Purpose |
|---|---|---|
modal.framework.selection |
Project setup modal | Framework selection cards |
page.controls.custom-framework |
Org Controls page | Framework toggle + content |
page.project-controls.custom-framework |
Project Controls page | Framework toggle + content |
page.framework-dashboard.custom |
Framework Dashboard | Statistics cards |
page.project-overview.custom-framework |
Project Overview | Completion progress |
page.org-framework.management |
Framework Settings | Add/remove frameworks |
page.settings.tabs |
Settings page | Configuration tab |
The custom-framework-ui package provides:
| Component | Purpose |
|---|---|
CustomFrameworkCards |
Framework selection cards |
CustomFrameworkControls |
Controls tab with framework toggle |
CustomFrameworkDashboard |
Dashboard statistics |
CustomFrameworkOverview |
Overview progress cards |
CustomFrameworkViewer |
Control details viewer |
CustomFrameworkConfig |
Settings configuration |
All components receive:
interface CustomFrameworkProps {
project?: Project; // Current project context
apiServices?: ApiServices; // API service methods
pluginKey: string; // Plugin identifier
}packages/custom-framework-ui/
cd packages/custom-framework-ui
npm install
npm run builddist/index.esm.js- ES module bundledist/index.d.ts- TypeScript definitions
Framework plugins reference the shared UI:
"ui": {
"bundleUrl": "/api/plugins/{plugin-key}/ui/dist/index.esm.js",
"globalName": "PluginCustomFrameworkImport",
"slots": [...]
}All framework plugins use the same globalName because they share the UI components.
Framework components communicate via DOM events:
// When a framework is added/removed
window.dispatchEvent(new CustomEvent("customFrameworkChanged", {
detail: { projectId: number }
}));
// When framework count changes (for system framework button logic)
window.dispatchEvent(new CustomEvent("customFrameworkCountChanged", {
detail: { projectId: number, count: number }
}));useEffect(() => {
const handleChange = (event: CustomEvent) => {
if (event.detail?.projectId === currentProjectId) {
refetchData();
}
};
window.addEventListener("customFrameworkChanged", handleChange);
return () => window.removeEventListener("customFrameworkChanged", handleChange);
}, [currentProjectId]);Framework plugins use these tables:
| Table | Purpose |
|---|---|
custom_frameworks |
Framework definitions |
custom_framework_controls |
Controls/requirements |
custom_framework_control_status |
Completion tracking |
custom_framework_evidence |
Evidence attachments |
See the main VerifyWise documentation for full schema details.
- Check
isPublished: truein plugins.json - Verify
category: "compliance"or has compliance/framework tags - Ensure plugin is installed for the tenant
- Check the region name exactly matches a key in
regionFlags - Region names are case-sensitive
- Add new region to
regionFlagsif needed
- Verify
bundleUrlpoints to correct file - Check browser console for loading errors
- Ensure UI bundle is built and deployed
- Check DOM events are being dispatched
- Verify event listeners are attached
- Check project ID matches in event detail