Retention & Export
Purpose: control how long CMDash keeps different kinds of data, and get your data out.
Both are top-level pages, not under Settings, and not a "Danger Zone."
Data Retention — /data-retention
Retention periods are admin-configurable, not fixed. The earlier version of this guide said periods "cannot be shortened from the settings UI" — that's no longer true (if it ever matched this page). You set a period, independently, for each of:
| Data type |
|---|
| Audit Logs |
| Automation Logs (automated alert/sync events) |
| Integration Sync Logs |
| Posture Snapshots |
| Notifications |
| Export Jobs |
using presets of 30 days, 90 days, 1 year, 2 years, or 7 years. The page also previews what a change would purge before you commit it.
Some compliance frameworks require a minimum retention window — check your framework's requirements before shortening a period.
Roles. Owners and Admins can view the page. Only the Owner can save the organization's first retention policy — saving one turns on the nightly deletion of data older than its windows — and only the Owner can shorten a period. Once a policy is saved, an Admin may lengthen a period. Every period is a whole number of days from 1 to 36,500 (100 years).
Run Purge Now (Owner only) first shows exactly what it will delete — the
records past their period, the linked records deleted with them, and the
stored files — and asks you to type DELETE. It then deletes as of that
preview: if more has become due since (an import, say), nothing is deleted and
you are shown the new preview. With nothing due, the button is disabled.
Data Export — /data-export
Exports all organization data (risks, controls, evidence, configuration) into a downloadable archive — CMDash's own description for this frames it explicitly as satisfying GDPR Article 20 (Data Portability).
Every export job produces three things, together, in one job:
| Artifact | What it is |
|---|---|
| JSON archive | The authoritative snapshot. This is the only file /data-import accepts. |
CSV bundle (.zip) | One <table>.csv per table, plus organization.csv, members.csv, a README.txt, and config-bundle.json. |
| Configuration bundle | A redacted record of this workspace's settings — see below. |
Roles. Viewing the page and downloading either format is Owner or Admin. Requesting a new export is Owner only — a full export is every row of every table in one file, so starting one is held to the same bar as restoring a workspace. An Admin sees the Request Export button disabled with that reason stated on the page, rather than a request that fails.
Download links are generated per click. Both the JSON and the CSV download
buttons ask the API for a freshly signed URL each time you press them
(GET /data-export/:id/json, GET /data-export/:id/csv). Earlier versions
made the JSON link a static URL signed once when the job was created; clicking
it after that signature lapsed landed on the object store's own "access
denied" page, which looked like a CMDash permissions bug. Downloads still
expire 24 hours after the export completes — from then on the download answers
410 Gone and says so, the archive is deleted an hour later, and you request
a new export. Requesting a new export also replaces the previous one: its
download links stop working as soon as the new one is complete. A download link
is signed for at most an hour and never past the export's expiry, and the files
themselves are deleted one hour after expiry, so a download that has already
started always finishes.
The export is never refused for storage. It counts toward your storage quota while its files exist (see below), but a workspace at or over its quota — for example a trial that ended with more stored than the Free plan holds — can always export its data.
Storage quota — what counts, what you can delete, what expires
Each workspace has one storage quota across every file it keeps in file storage: Free 250 MB, Starter 5 GB, Essentials 25 GB, Command 100 GB, Enterprise by contract. Self-hosted (on-prem and customer-AWS) deployments have no quota. Settings → Plan & billing → Storage shows what is used.
- Counts: evidence files and attachments, and the files CMDash generates for you (report and board PDFs, board decks, evidence packages, CMMC packages, audit ZIPs, scheduled-report PDFs, data exports), your branding logo and uploaded policy documents. Records kept in the database — such as imported SBOMs and questionnaire answers — do not count.
- You can delete: evidence items and their attachments (Compliance → Evidence). Deleting evidence also removes it from any evidence package ZIP that contained it (the package keeps its JSON manifest). Replacing or clearing your logo deletes the old one.
- Expires on its own: generated reports, packages and archives are deleted 7 days after they are created, and a data export after 24 hours; their space is freed then. A generated file you have added to your Document Room is kept while it is there. The original of a policy document uploaded for gap analysis is kept for 7 days too — the analysis keeps the text extracted from it.
- Per file: on the Free plan each uploaded evidence file can be up to 10 MB (paid plans are limited only by the per-kind caps: screenshots 10 MB, documents 50 MB, recordings 250 MB).
- When full: new uploads and generated files are refused with
STORAGE_QUOTA_EXCEEDED(413) until usage drops; an evidence package that does not fit is still produced with its JSON manifest, and the job says why there is no ZIP.
Configuration bundle
Six tables are deliberately withheld from the raw export because they hold
credential material (session tokens, the LDAP bind password, webhook signing
secrets, SAML/SCIM tokens, API-key digests). Four of them also hold your
configuration, which is why the archive carries a configuration bundle —
configBundle in the JSON archive, config-bundle.json in the CSV zip.
Included (secrets removed)
| Section | What it records |
|---|---|
sso.saml | IdP entity id, SSO/SLO URLs, default role, group mapping, JIT and SCIM enablement, active state |
sso.scimGroups | SCIM group display names, IdP external ids, role mapping |
directory.ldap | Server URL, bind DN, base DN, user/group filters, attribute mapping, group mapping, sync interval, default role, last sync result |
integrations.connections | Provider, status, sync interval, last sync, and the provider config JSON (redacted) |
integrations.inboundWebhookSecrets | One entry per provider that has a webhook secret installed — presence only |
notifications.channels | Slack/Teams/Email/webhook channels, type, enabled state, config (redacted) |
notifications.alertRules | Metric, operator, threshold, target channels, status, cooldown |
outboundWebhooks | URL, subscribed events, active state, rotation timestamps — presence of a secret |
apiKeys | Name, key prefix, permissions, last used, expiry, revocation |
frameworkScope | Which frameworks this workspace marked in or out of scope |
customFields | Every custom field definition: target object, key, label, type, options, required, validation, help text, order |
Not included, ever
These columns are never read from the database while the bundle is built — not read and then stripped:
saml_configs.certificate— the IdP X.509 signing certificate. Re-obtain it from your IdP.saml_configs.scim_token— the SCIM bearer token hash.ldap_configs.bind_credential— the encrypted directory bind password.integration_webhook_secrets.encrypted_secret— inbound webhook HMAC secret.webhook_registrations.secret/previous_secret— outbound webhook HMAC secrets.api_keys.key_hash— the digest of a live API key.refresh_tokens.*andidempotency_records.*— session credentials and an internal request cache; neither is configuration at all.
In addition, any value inside a free-form JSON config column whose key names
a secret (token, password, credential, webhookUrl, …) is replaced with
the literal [redacted]. The key is kept, so you can see that a value existed.
Read the whole archive as sensitive. The per-table CSVs are the raw rows:
notification_channels.csvandintegration_connections.csvcarry the same config JSON without the key-name redaction above. One exception: an integration's secret settings (for example an AWS secret access key, a scanner password or a Splunk HEC token) are encrypted at rest and are removed fromintegration_connections.csv. They never leave the deployment, in any form. Enter them again when you reconnect the integration, which you must do after a restore anyway, because connection credentials are never exported.config-bundle.jsonis the readable, redacted view — not a filter applied to the rest of the archive.
The configuration bundle is a record, not a restore artifact. /data-import
reads only the archive's models section and ignores it. See
Organization restore for what
automatic config restore would require.
Organization restore — /data-import
Restoring an archive has its own page and its own guide — Organization restore.
Workspace deletion
No self-service "Danger Zone → Delete Workspace" UI was found anywhere in the current settings pages, and no matching route exists. If your workspace needs to be closed, contact CMDash support — do not assume the self-service flow described in older versions of this guide still exists; it could not be confirmed against the current source.
Free workspaces nobody uses
On the hosted service, a Free workspace that nobody signs in to for 60 days is closed and then deleted:
- its owners and admins are e-mailed 30 days before the closure date and again 7 days before it, and each e-mail names the date;
- on the closure date (the 61st day after the last sign-in, UTC) the workspace is closed through the same account-closure flow as an owner's own closure, and a deletion certificate is issued;
- its data is purged 14 days after the closure;
- any member signing in before the purge keeps the workspace and restarts the 60-day count.
Paid, trial and contracted workspaces, design partners, workspaces with an active relying-party grant, and managed client workspaces are never closed this way. See Free tier.
GDPR erasure requests
No self-service erasure UI was found either (only the export path above, which is for portability, not erasure). Route a right-to-erasure request to privacy@cmdash.com as before, until a self-service flow is confirmed to exist.