[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-93787":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":9,"language":10,"languages":9,"totalLinesOfCode":9,"stars":11,"forks":12,"watchers":13,"openIssues":14,"contributorsCount":14,"subscribersCount":14,"size":14,"stars1d":14,"stars7d":14,"stars30d":14,"stars90d":14,"forks30d":14,"starsTrendScore":14,"compositeScore":15,"rankGlobal":9,"rankLanguage":9,"license":16,"archived":17,"fork":17,"defaultBranch":18,"hasWiki":19,"hasPages":17,"topics":20,"createdAt":9,"pushedAt":9,"updatedAt":21,"readmeContent":22,"aiSummary":23,"trendingCount":14,"starSnapshotCount":14,"syncStatus":24,"lastSyncTime":25,"discoverSource":26},93787,"Conformiti","dboudreau00\u002FConformiti","dboudreau00","A GRC Compliance tool for SaaS products to manage the entire lifecycle of security audits.",null,"Python",151,23,1,0,44.14,"MIT License",false,"main",true,[],"2026-09-21 04:01:26","\n# Conformiti\n\n\n\u003Cimg width=\"966\" height=\"297\" alt=\"827b2be6-ec29-41a2-ad11-de0a6ab2ed75\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fe9352e41-8969-41ad-9f6a-159f0a84d360\" \u002F>\n\n\n\n\n\u003Cimg width=\"2216\" height=\"1025\" alt=\"Screenshot 2026-07-23 102705\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F51db74b2-eaf6-4189-b3f8-880c3688cff5\" \u002F>\n\n\n\n\n\u003Cdetails>\n\u003Csummary>\u003Cb>📸 Click to expand Screenshots Gallery (15 screens)\u003C\u002Fb>\u003C\u002Fsummary>\n\u003Cbr>\n\n\u003Cp align=\"center\">\n  \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F0b882dbb-945d-4d3b-aa93-0ab20401cbec\" width=\"250\" alt=\"App Icon \u002F Logo\" \u002F>\n\u003C\u002Fp>\n\n| View | View |\n| :---: | :---: |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F24189986-e29b-4cb2-9e2e-0346e7964bbb\" width=\"100%\" alt=\"Screenshot 1\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F1baa8882-5eb8-4be0-91a5-047ce9ce2709\" width=\"100%\" alt=\"Screenshot 2\"> |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F4927ea81-03f3-4ec3-b5eb-474a190392a1\" width=\"100%\" alt=\"Screenshot 3\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F449e4924-aea6-4199-a42e-9c174d8d00b2\" width=\"100%\" alt=\"Screenshot 4\"> |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fb5f48291-75ca-42c2-b216-489375e7d5a2\" width=\"100%\" alt=\"Screenshot 5\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Ff98614dd-c126-4611-b22a-0e794b1bfd8d\" width=\"100%\" alt=\"Screenshot 6\"> |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F030f6d62-b918-46f8-960b-b9614d59a0ea\" width=\"100%\" alt=\"Screenshot 7\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fefd43619-62eb-4ab1-9db1-60d3348d03e6\" width=\"100%\" alt=\"Screenshot 8\"> |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F791ba0df-fc13-4071-b7a4-78d4a4e315f8\" width=\"100%\" alt=\"Screenshot 9\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F2fd24bfa-0210-4172-bd7d-a3eb87afa92d\" width=\"100%\" alt=\"Screenshot 10\"> |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F07144dc7-a2c7-4d56-a007-0aa5197f8c58\" width=\"100%\" alt=\"Screenshot 11\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fd2601e7f-eee3-4922-84be-a37500222227\" width=\"100%\" alt=\"Screenshot 12\"> |\n| \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fb662f589-2840-4711-854c-0b4b7491cc09\" width=\"100%\" alt=\"Screenshot 13\"> | \u003Cimg src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F47c1a091-b72b-4912-867c-b2ff3da94abb\" width=\"100%\" alt=\"Screenshot 14\"> |\n\n\u003C\u002Fdetails>\n\n\n\nA Vanta-style compliance management application for **SOC 2**, **ISO\u002FIEC 27001:2022**\nand **PCI DSS v4.0.1**. It ships with the full control libraries for all three\nframeworks, an evidence folder tree segregated by control, role-based access to\nfolders, document lifecycle management with review scheduling, automated review\nreminders over a **standard IMAP\u002FPOP3 + SMTP mailbox** or **Amazon SES**, an\nanalytics dashboard, an account settings area, and a dashboard calendar.\n\n\n**For preloaded compliance data you must unzip compliance-data.zip in the root directory before building.**\n\n\n\n\n**Want a look before installing?** Open **[app-preview.html](app-preview.html)**\nin a browser — a clickable static preview of all 12 screens with the live\ntheme switcher (no install needed).\n\n**For the full manual — installation paths, configuration reference, and\nevery workflow in depth — see [USER_GUIDE.md](USER_GUIDE.md).**\n\n**New to the project? Start with [GETTING_STARTED.md](GETTING_STARTED.md)** —\none walkthrough that installs, verifies, and tests every function (including\nthe document-review email reminders). [INSTALL.md](INSTALL.md) has the\none-command installer details.\nSecurity posture, the audit findings, and the production checklist are in\n**[SECURITY.md](SECURITY.md)**. Setup requirements live in\n**[PREREQUISITES.md](PREREQUISITES.md)**, and the automated readiness report is\n**[VALIDATION.md](VALIDATION.md)** — re-run it any time with\n`python3 tools\u002Fvalidate.py`. A design spec for the planned SharePoint\nintegration (OAuth email login, session retention, email-scoped viewer\nlinks) is in **[docs\u002FSHAREPOINT_INTEGRATION.md](docs\u002FSHAREPOINT_INTEGRATION.md)**.\n\n---\n\n## What's inside\n\n| Requirement | Where it lives |\n|---|---|\n| SOC 2 \u002F ISO 27001 \u002F PCI DSS v4.0.1 control libraries | `backend\u002Fcompliance\u002Fdata\u002F*.json` (217 controls) generated by `tools\u002Fbuild_seed_data.py` |\n| Neat folder tree segregated by control | `backend\u002Fcompliance\u002Ffolder_tree.py` + `manage.py generate_folder_tree` → `compliance-data\u002F` |\n| SMTP alerts for documents coming up for review | `backend\u002Fnotifications\u002Ftasks.py` (+ `send_review_reminders` command \u002F Celery beat) |\n| Mail owners from a standard mailbox (IMAP\u002FPOP3 + SMTP) | `backend\u002Fnotifications\u002Fmailbox.py`, toggled by `EMAIL_PROVIDER=mailbox` (+ `manage.py test_mailbox`) |\n| Amazon SES for mailing | `backend\u002Fnotifications\u002Fses.py`, toggled by `EMAIL_PROVIDER=ses` |\n| Analytics dashboard (readiness, status mix, review timeline, ownership) | `backend\u002Fanalytics\u002F` (`\u002Fapi\u002Fanalytics\u002Fsummary`) + `frontend\u002Fsrc\u002Fpages\u002FAnalytics.jsx` |\n| Account settings sidebar (profile, password, role & access) | `frontend\u002Fsrc\u002Fpages\u002FAccount.jsx` + `\u002Fapi\u002Fusers\u002Fme` (PATCH) & `\u002Fapi\u002Fusers\u002Fchange_password` |\n| User access audits (grid + CSV export) | `backend\u002Fgovernance\u002F` (`\u002Fapi\u002Faccess-reviews`) + `frontend\u002Fsrc\u002Fpages\u002FUserAudit.jsx` |\n| Meeting minutes with required yearly cadence | `governance.MeetingSeries` \u002F `MeetingMinute` + `frontend\u002Fsrc\u002Fpages\u002FMeetings.jsx` |\n| Champion groups (owned, inter-departmental) | `governance.ChampionGroup` \u002F `GroupMember` + `frontend\u002Fsrc\u002Fpages\u002FGroups.jsx` |\n| Optional Jira board tracking | `backend\u002Fintegrations\u002F` (stdlib REST client) + `frontend\u002Fsrc\u002Fpages\u002FJira.jsx` |\n| Immutable audit trail with in-app viewer — every create\u002Fupdate\u002Fdelete captured server-side (actor, record, detail, IP); filterable, searchable, read-only, gated to admins\u002Fauditors\u002Fview-all | `audit.AuditLogMiddleware` + `\u002Fapi\u002Faudit-log\u002F`, `frontend\u002Fsrc\u002Fpages\u002FAuditLog.jsx` |\n| Theming — Audit Ledger + Blazor themes, each with light & dark, plus a custom accent-colour picker (Account → Appearance), persisted per browser | `frontend\u002Fsrc\u002Ftheme.js` engine + CSS token themes in `styles\u002Fapp.css` |\n| Per-account notification bell — feed derived from each user's ownership, assignments, and role (documents, risks, events, meetings, manager digests, access reviews) | `backend\u002Fnotifications\u002Fnotifications.py` engine + `NotificationReceipt`, `\u002Fapi\u002Fnotifications\u002F*`, `frontend\u002Fsrc\u002Fcomponents\u002FNotificationBell.jsx` |\n| Two-factor auth (TOTP, RFC 6238) with backup codes + admin reset | `accounts\u002Fmfa.py` (stdlib), `MfaDevice`\u002F`MfaBackupCode`, `\u002Fapi\u002Fauth\u002Fmfa\u002F*`, Security tab in `Account.jsx`, two-step `Login.jsx` |\n| User management admin panel (create users, assign roles, activate\u002Fdeactivate, reset passwords) with lockout guards | `accounts.UserViewSet` guards + `frontend\u002Fsrc\u002Fpages\u002FUsers.jsx` |\n| Risk register with remediation notes, CSV\u002FXLSX import, CSV export | `governance.Risk`\u002F`RiskNote` (`\u002Fapi\u002Frisks`), stdlib importer `governance\u002Frisk_import.py`, `frontend\u002Fsrc\u002Fpages\u002FRisks.jsx`, sample file `docs\u002Fsample-risk-import.csv` |\n| Evidence ↔ control mapping (cross-framework, with bulk attach) | `compliance.ControlEvidence` (`\u002Fapi\u002Fcontrol-evidence`) + evidence drawer in `Controls.jsx`, \"satisfies\" chips in `Documents.jsx` |\n| Calendar on the main dashboard | `frontend\u002Fsrc\u002Fcomponents\u002FCalendar.jsx` + `calendar_app` (`\u002Fapi\u002Fcalendar\u002Ffeed`) |\n| Storage of common document forms | `documents.FormTemplate` + `\u002Fapi\u002Fform-templates` |\n| Document renaming & managing | `documents.Document` + rename \u002F move \u002F new-version \u002F mark-reviewed actions |\n| Assign owners | `owner` on controls, folders and documents |\n| Role-based access to specific folders | `accounts.Role` + `documents.FolderPermission` (inherited down the tree) |\n\n---\n\n## Tech stack\n\n- **Backend:** Django 5 + Django REST Framework, JWT auth\n- **Async \u002F scheduling:** Celery + Redis (review-reminder scan runs daily)\n- **Storage:** local filesystem by default, Amazon S3 optional (`django-storages`)\n- **Email:** a standard IMAP\u002FPOP3 + SMTP mailbox, Amazon SES (boto3), plain SMTP, or console\n- **Frontend:** React 18 + Vite\n- **Database:** SQLite locally, PostgreSQL in Docker\u002Fproduction\n\n---\n\n## Quickstart — Docker (everything at once)\n\n```bash\ncp .env.example .env            # edit if you like; defaults work\n# point the DB at Postgres for the compose stack:\necho \"POSTGRES_DB=compliance\"   >> .env\necho \"POSTGRES_USER=compliance\" >> .env\necho \"POSTGRES_PASSWORD=compliance\" >> .env\n\ndocker compose up --build\n```\n\nThen open:\n\n- **App:** http:\u002F\u002Flocalhost:8080  (log in as `admin` \u002F `DemoPass123!`)\n- **API:** http:\u002F\u002Flocalhost:8000\u002Fapi\u002F\n- **Django admin:** http:\u002F\u002Flocalhost:8000\u002Fadmin\u002F\n\nThe backend container automatically migrates, seeds all three frameworks, builds\nthe folder tree, and loads demo data on first boot.\n\n## Quickstart — manual (no Docker)\n\n**Backend**\n```bash\ncd backend\npython -m venv .venv && source .venv\u002Fbin\u002Factivate     # Windows: .venv\\Scripts\\activate\npip install -r requirements.txt\ncp ..\u002F.env.example ..\u002F.env                             # console email + SQLite\n\npython manage.py makemigrations accounts compliance documents calendar_app notifications audit governance integrations\npython manage.py migrate\npython manage.py seed_frameworks --with-folders        # controls + app folders + roles\npython manage.py bootstrap_demo                        # demo users, docs, events\npython manage.py generate_folder_tree                  # physical evidence tree on disk\npython manage.py runserver\n```\n\n**Frontend** (second terminal)\n```bash\ncd frontend\nnpm install\nnpm run dev            # http:\u002F\u002Flocalhost:5173  (proxies \u002Fapi to :8000)\n```\n\nLog in as `admin` \u002F `DemoPass123!`.\n\n---\n\n## Role-based access control\n\nTwo layers work together:\n\n1. **Role capabilities** (`accounts.Role`) — platform-wide flags: manage users,\n   manage frameworks, manage documents, manage folders, view-all, auditor.\n   Five roles are seeded: **Administrator, Compliance Manager, Control Owner,\n   Auditor, Viewer**.\n2. **Folder permissions** (`documents.FolderPermission`) — grant a *role* or a\n   *specific user* `view` \u002F `edit` \u002F `manage` on a folder. Grants are inherited\n   by every subfolder, so giving \"Control Owner → edit\" on `CC6` cascades to all\n   CC6 controls. Document access is derived from its folder; owners can always\n   edit their own documents; auditors are capped at read-only.\n\nEffective access is computed in `Folder.effective_access(user)`.\n\n## Email & review reminders\n\nSet the provider in `.env`:\n\n```\nEMAIL_PROVIDER=console   # dev: prints emails to the log\nEMAIL_PROVIDER=smtp      # any SMTP server (set EMAIL_HOST etc.)\nEMAIL_PROVIDER=mailbox   # a standard inbox: IMAP\u002FPOP3 connects, SMTP sends\nEMAIL_PROVIDER=ses       # Amazon SES (set AWS_SES_REGION + credentials)\nREVIEW_ALERT_LEAD_DAYS=30,14,7,1\n```\n\nWith `EMAIL_PROVIDER=mailbox`, reminders go out through an ordinary mail account\n(`backend\u002Fnotifications\u002Fmailbox.py`). IMAP or POP3 is used to connect to the\nmailbox — verifying the credentials and, for IMAP, filing a copy of each reminder\nin the **Sent** folder — while **SMTP** performs the actual send (IMAP\u002FPOP3 cannot\nsend mail). The SMTP host\u002Fusername default to the mailbox values, so a single\nprovider often needs only the four `MAILBOX_*` lines in `.env.example`. Verify a\nmailbox and send yourself a test with `python manage.py test_mailbox --to you@x.com`.\n\nEach document has a review cadence (monthly … biennial). `next_review_date` is\ncomputed from `last_reviewed + cadence`. A daily scan\n(`notifications.tasks.run_review_scan`, wrapped by the Celery task\n`scan_document_reviews`) emails the document owner and the compliance team when\na lead threshold is first crossed, and again once when a document goes overdue —\nnever duplicating a reminder.\n\nRun the scan on a schedule two ways:\n\n- **Celery beat** (Docker `worker` service runs this automatically), or\n- **cron:** `python manage.py send_review_reminders` (add `--dry-run` to preview).\n\n## The folder tree\n\n`manage.py generate_folder_tree` writes a filesystem tree to `compliance-data\u002F`:\n\n```\ncompliance-data\u002F\n  SOC2\u002FCC6 - Logical and Physical Access Controls\u002FCC6.1 - Access security\u002F\n    _control.md   policies\u002F   procedures\u002F   evidence\u002F   forms\u002F\n  ISO27001\u002F...\n  PCI-DSS-v4.0.1\u002F...\n```\n\nPoint it anywhere with `--root`, or set `COMPLIANCE_TREE_ROOT` (e.g. an\nS3-synced directory) to keep a browsable on-disk mirror alongside the app.\n\n---\n\n## API surface (selected)\n\n```\nPOST \u002Fapi\u002Fauth\u002Ftoken\u002F                 # obtain JWT\nGET  \u002Fapi\u002Fusers\u002Fme\u002F                   # current user + capabilities\nPATCH \u002Fapi\u002Fusers\u002Fme\u002F                  # update own profile (name\u002Femail\u002Fjob title)\nPOST \u002Fapi\u002Fusers\u002Fchange_password\u002F      # change own password\nGET  \u002Fapi\u002Fanalytics\u002Fsummary\u002F          # dashboard metrics (readiness, status, reviews)\nGET  \u002Fapi\u002Fframeworks\u002F                 # frameworks with control counts\nGET  \u002Fapi\u002Fframeworks\u002F{key}\u002Fcontrols\u002F  # controls for a framework\nGET  \u002Fapi\u002Fcontrols\u002F  PATCH \u002Fapi\u002Fcontrols\u002F{id}\u002F   # status \u002F owner\nGET  \u002Fapi\u002Fcrosswalk\u002F                  # cross-framework control mappings\nGET  \u002Fapi\u002Fcontrol-evidence\u002F?control=  # evidence linked to a control (folder-scoped)\nPOST \u002Fapi\u002Fcontrol-evidence\u002Fbulk\u002F      # attach several documents to one control\nGET  \u002Fapi\u002Fcontrol-evidence\u002Fchoices\u002F   # pick-lists: visible documents + control catalog\nGET  \u002Fapi\u002Ffolders\u002Ftree\u002F               # access-filtered folder tree\nGET  \u002Fapi\u002Ffolders\u002F{id}\u002Fpermissions\u002F   # folder access grants\nPOST \u002Fapi\u002Ffolder-permissions\u002F         # grant role\u002Fuser access to a folder\nGET  \u002Fapi\u002Fdocuments\u002F                  # documents (folder-scoped by access)\nPOST \u002Fapi\u002Fdocuments\u002F{id}\u002Frename\u002F      # rename\nPOST \u002Fapi\u002Fdocuments\u002F{id}\u002Fmove\u002F        # move to another folder\nPOST \u002Fapi\u002Fdocuments\u002F{id}\u002Fnew_version\u002F # upload a new version (archives the old)\nPOST \u002Fapi\u002Fdocuments\u002F{id}\u002Fmark_reviewed\u002F\nGET  \u002Fapi\u002Fdocuments\u002Freviews\u002F?days=90  # upcoming \u002F overdue reviews\nGET  \u002Fapi\u002Fcalendar\u002Ffeed\u002F?start=&end=  # events + synthesized review deadlines\nGET  \u002Fapi\u002Fform-templates\u002F             # shared blank forms library\nPOST \u002Fapi\u002Faccess-reviews\u002F             # snapshot all users into an audit grid\nPATCH \u002Fapi\u002Faccess-review-items\u002F{id}\u002F  # record keep \u002F modify \u002F revoke decisions\nGET  \u002Fapi\u002Faccess-reviews\u002F{id}\u002Fexport\u002F # download the audit grid as CSV\nGET  \u002Fapi\u002Fmeeting-series\u002F             # meeting cadences w\u002F held-vs-required status\nPOST \u002Fapi\u002Fmeeting-minutes\u002F            # record minutes (optional file attachment)\nGET  \u002Fapi\u002Fchampion-groups\u002F            # owned inter-departmental champion groups\nGET  \u002Fapi\u002Frisks\u002F  PATCH \u002Fapi\u002Frisks\u002F{id}\u002F         # risk register (status\u002Fowner\u002Fplan)\nGET  \u002Fapi\u002Frisks\u002Fsummary\u002F              # open \u002F overdue \u002F rating counts\nPOST \u002Fapi\u002Frisks\u002Fimport\u002F               # ingest a register from .csv or .xlsx\nGET  \u002Fapi\u002Frisks\u002Fexport\u002F               # download the register as CSV\nPOST \u002Fapi\u002Frisk-notes\u002F                 # add a remediation progress note\nGET  \u002Fapi\u002Fintegrations\u002Fjira\u002Fconfig\u002F   # Jira connection (managers; token write-only)\nGET  \u002Fapi\u002Fintegrations\u002Fjira\u002Fboards\u002F{id}\u002Fissues\u002F  # issues from a tracked board\n```\n\n---\n\n## A note on control text & copyright\n\nControl IDs and short titles are functional identifiers. The `objective` fields\nare brief, original-wording paraphrases — **not** the normative text of the\nstandards. ISO\u002FIEC 27001 and PCI DSS are copyrighted; only paste official control\ntext into the app if your organisation holds a licence for the source documents.\n\n## Roadmap (what a production premium rollout adds next)\n\n- Automated evidence collection via cloud\u002FSaaS integrations (AWS, GitHub, Okta, …)\n- Auditor workspace with read-only evidence export and a Type II audit window\n- Per-control readiness scoring (evidence mapping shipped — see `\u002Fapi\u002Fcontrol-evidence`)\n- Notifications beyond email (Slack\u002FTeams), digests, and escalation\n- SSO\u002FSAML, granular field-level audit history, and data-retention policies\n- Full test suite and CI, background-job monitoring, and S3 lifecycle rules\n\nhttps:\u002F\u002Fdboudreau.dev\n","Conformiti 是一款面向 SaaS 产品的 GRC（治理、风险与合规）工具，用于统一管理安全审计的全生命周期。核心功能包括内置 SOC 2、ISO\u002FIEC 27001:2022 和 PCI DSS v4.0.1 三大框架的完整控制项库，按控制分类的证据文件树、基于角色的文件访问控制、文档版本与审阅周期管理、通过 IMAP\u002FPOP3+SMTP 或 Amazon SES 自动发送审阅提醒、合规仪表盘及日历视图。适用于中早期 SaaS 团队在无专职合规人员情况下系统化开展第三方审计准备与持续合规运营。",2,"2026-07-25 02:30:05","CREATED_QUERY"]