Skip to content

Quick Reference

Quick reference illustration

A quick reference guide for common tasks and features in the SCF Controls Platform.


ShortcutAction
RRefresh data (same as the refresh button)
Previous / next record on a detail page — controls, scoping, evidence, tasks, systems, vendors
EscClose a modal, or go back from a detail page to its list
Enter / SpaceActivate the focused list row
Ctrl+Shift+R / Cmd+Shift+RBrowser hard refresh (clears the cache)

Section GroupSectionPurpose
OverviewDashboardCompliance posture overview
OverviewAnalyticsCapability Posture by KSI theme
Controls & FrameworksControl LibraryBrowse all 1,451 SCF controls
Controls & FrameworksFramework MappingsFramework-to-control mapping matrix
Controls & FrameworksControl ScopingScope controls and identify gaps
Risk & Third PartyRisk RegisterRisk assessment and 5x5 matrix
Risk & Third PartyVendor InventoryThird-party vendor management
EvidenceEvidenceUnified evidence workspace
OperationsTask ManagementTrack evidence collection tasks
OperationsSystems RegistryManage evidence source systems
OperationsUser ManagementManage organisation members, roles and teams
AdminEngagementsClient engagement management
AdminWebhooksWebhook integrations
AdminAudit LogField-level change audit trail
AdminConsultant PortalMulti-client management
AdminOrg SettingsOrganisation configuration

  • Polls the server for a change notice every 20 seconds — it does not refetch your data
  • The poll stops while the tab is hidden and runs immediately when you return
  • Returning to the tab also refetches the queries currently on screen
  • Click the refresh button in the header, or press R
  • Browser hard refresh: Ctrl+Shift+R (Windows) or Cmd+Shift+R (Mac)
IndicatorMeaning
Updated just nowRefreshed in the last 10 seconds
Updated 40s ago / 5m ago / 2h agoTime since your last refresh
Updates available (with a dot)The poll found a change — refresh to pull it in

StatusWhen to Use
Not StartedControl scoped but no work begun
In ProgressImplementation underway
ImplementedFully operational
At RiskBehind schedule or has issues
Not ApplicableDoesn’t apply to your environment
DeferredIntentionally postponed
LevelDescription
InitialAd-hoc, inconsistent processes
DevelopingRepeatable but undocumented
DefinedDocumented and standardised
ManagedMonitored and measured
OptimisedContinuously improving
PriorityMeaning
CriticalMust address immediately
HighComplete soon
MediumNormal priority
LowAddress when resources allow

StatusMeaning
Not StartedNo evidence collected yet
In ProgressCollection underway
CollectedEvidence gathered but not verified
VerifiedReviewed and confirmed valid
ExpiredPast validity period
Not ApplicableDoesn’t apply to your environment
FrequencyDescription
One-timeCollect once during initial assessment
MonthlyRecurring monthly collection
QuarterlyRecurring quarterly collection
AnnuallyRecurring annual collection
On-demandCollect only when specifically requested
IconLevelDescription
HighFully automated via API
MediumPartial automation available
LowPrimarily manual collection

TypePurpose
FeasibilityAssess if evidence can be collected as planned
SetupConfigure systems for evidence collection
CollectionPerform evidence collection activity
ReviewReview collected evidence for completeness
DocumentationDocument collection procedures
IssueAddress problems with evidence collection
StatusColourMeaning
Not StartedBlueWork not yet begun
In ProgressOrangeCurrently being worked on
CompletedGreenFinished
RuleValue
Owning teams per taskAt most one
Task with no owning teamInherits the accountable team of its evidence item
Task with an owning teamOverrides the evidence item, for that task only
Deleting a teamIts tasks return to inheriting; tasks are never deleted with the team
Team from another organisationRejected by the database

A task is atomic — one title, one due date, one doer — so it takes a single owning team rather than the many-to-many assignment that controls and evidence items take. The override exists because Setup, Collection and Review on one evidence item are routinely three different functions.

Every reminder and escalation resolves recipients down the same chain, stopping at the first tier that produces anybody:

TierRecipients
1The item’s assignee
2The accountable team’s primary and delegate, both, in parallel
3Organisation admins

For a task the chain has one extra step: its own assignee, then its own owning team, then its evidence item’s accountable team, then organisation admins.

RuleValue
RecipientsA set — assignee who is also team primary gets one notification, not two
Consulted (non-accountable) teamsNot on the routine path; reached only on escalation
Overdue escalationOn becoming overdue, then +7 days, then +30 days — never once per scheduler run
Escalation eventsItem overdue; a control’s evidence assessed insufficient; evidence rejected
Escalation recipientsThe resolved set, plus the primary and delegate of the accountable team and of every consulted team
Organisation with no teamsNo wider audience than today; tier 2 never resolves
Overdue cadenceChanges for every org, teams or not — thresholds replace the daily alert

See Who Gets Notified for the reasoning behind each of these.


Likelihood Scale (1-5):

  • 1 = Rare
  • 2 = Unlikely
  • 3 = Possible
  • 4 = Likely
  • 5 = Almost Certain

Impact Scale (1-5):

  • 1 = Insignificant
  • 2 = Minor
  • 3 = Moderate
  • 4 = Major
  • 5 = Severe
Score RangeLevelColour
1-4LowGreen
5-9MediumYellow
10-15HighOrange
16-25CriticalRed

Two assessment layers, one review queue. The window layer is primary; the per-file layer is diagnostic. Full guide: AI evidence assessment.

LevelValues
Objective designation (advisory)appears_satisfied, gap_identified, not_applicable, cannot_assess
Window or file statussufficient, partial, insufficient, unassessable; windows also insufficient_sample
Reviewer decisionconfirmed, overridden (reason and at least one re-designation required)
POST /api/organizations/{org_id}/evidence/{evidence_id}/assess-window editor; queue a window assessment
GET /api/organizations/{org_id}/evidence/{evidence_id}/window-assessments viewer; list windows for an evidence item
GET /api/organizations/{org_id}/evidence/window-assessments/{assessment_id} viewer; one window with ao_findings and file_membership
POST /api/organizations/{org_id}/evidence/window-assessments/{assessment_id}/verdict/review editor; confirm or override the AI verdict
GET /api/organizations/{org_id}/evidence/window-assessments/{assessment_id}/versions viewer; immutable verdict history, newest first
PUT /api/organizations/{org_id}/window-assessments/{ewa_id}/review editor; acceptance review: approved, rejected, needs_revision
GET /api/organizations/{org_id}/evidence/window-assessments/summary viewer; counts by status
POST /api/organizations/{org_id}/evidence/assess-windows-bulk editor; queue every tracked item
GET /api/organizations/{org_id}/evidence/assessment/review-queue?tier=window|file viewer; verdicts awaiting confirmation (default tier=file)
POST /api/organizations/{org_id}/evidence/{evidence_id}/files/{file_id}/assess editor; per-file (diagnostic) assessment
POST /api/organizations/{org_id}/evidence/{evidence_id}/files/{file_id}/assessment/review editor; confirm or override a per-file verdict
GET /api/organizations/{org_id}/evidence/{evidence_id}/files/{file_id}/assessment/versions viewer; per-file verdict history
GET /api/features unauthenticated; the flags the backend is running with

PUT …/files/{file_id}/review (per-file document approval) answers 410 Gone for evidence that has a window assessment while ENABLE_PER_WINDOW_REVIEW is on; the response body points at the window review endpoint.

RoleAccess Level
AdminFull access: manage users, configure frameworks, view all data
EditorEdit content: manage controls, evidence, tasks, assignments
ViewerRead-only: view controls and reports without editing

Every organisation membership is recorded as internal or an external contractor. It is a reporting label on the membership — not on the person — and it grants nothing; access stays governed by the organisation role above.

RuleValue
Valuesinternal, external_contractor
Defaultinternal, for new members and for every membership that existed before the feature
ScopePer membership — the same person can be internal in one organisation and a contractor in another, and neither organisation sees the other’s record
Set byAdmin, from the Type column on the user list row, or Employment Type in the Invite User dialog
At invite timeCarried on the invitation alongside the role, and applied to the membership when the invitee accepts
Invitation that says nothinginternal — the same way an invitation silent on role means Viewer
Changing it laterAny admin, any time, from the member’s row — nothing about it is permanent
Visible toAny organisation member. Non-admins see the value as plain text rather than a dropdown
BadgeReads Contractor. Internal members get no badge; in dropdowns the name is suffixed (Contractor)
List filterAll Owner Types / Contractor-owned / Internally owned, on the controls and evidence lists
Effect on permissionsNone
Relationship to roleIndependent — changing one never alters the other
Inferred from email domain or any existing fieldNever — organisations state their own contractors
Audit logEvery change made from the member row, one entry per field. Invitations are not audited
PATCH /api/organizations/{org_id}/members/{user_id} admin; ?role, ?member_type
POST /api/organizations/{org_id}/invite admin; body: email, role, member_type, message
GET /api/organizations/{org_id}/invites admin; shows what a pending invite will apply

PATCH takes query parameters, not a request body?member_type=external_contractor alongside the existing ?role=. Both are optional and at least one must be supplied; sending one leaves the other untouched.

member_type on the invite body is optional and defaults to internal. It is applied to the membership at acceptance. The invitee’s public preview of an invitation shows the role only.

GET /api/organizations/{org_id}/scoped-controls-paginated ?accountable_owner_type=internal|external_contractor
GET /api/organizations/{org_id}/evidence-tracking ?accountable_owner_type=internal|external_contractor

The same two list endpoints that take ?team_id and ?function_id, resolved through one shared helper so they cannot answer differently.

The chain is: the assignment marked accountable → that team’s primary member → that person’s type. All three hops are required, so an item with no team assignment, no accountable team, or an accountable team with no primary is absent from the results — it is not “no contractor”, it is the ownership record having no answer. Read an empty result as nothing to report yet.

See User Management for the full guide.


Teams are managed from the Team Management card in User Management. They record ownership; they grant no permissions — access stays governed by the organisation role above.

Fourteen platform-seeded functions, read-only to organisations:

KeyName
governance_risk_complianceGovernance, Risk & Compliance
security_operationsSecurity Operations
security_engineeringSecurity Engineering
it_operationsIT Operations
software_engineeringSoftware Engineering / DevSecOps
identity_access_managementIdentity & Access Management
data_privacyData Protection & Privacy
human_resourcesHuman Resources
legalLegal
financeFinance
procurement_vendor_managementProcurement & Vendor Management
facilities_physical_securityFacilities & Physical Security
business_continuityBusiness Continuity & Resilience
executive_leadershipExecutive Leadership
RoleLimit per team
PrimaryAt most one
DelegateAt most one
MemberNo limit

A team with no members, or no primary, is allowed and shows a warning badge.

Controls and evidence items are assigned owning teams from their detail view. Controls can also be assigned in bulk from the Control Scoping list.

RuleValue
Owning teams per control or evidence itemNo limit
Assigning teams in bulkControls only — tick rows in Control Scoping and use Assign owner on the selection bar, which claims the accountable team. Evidence items are assigned per item from the detail view
Accountable teams per itemAt most one
Same team assigned twice to one itemRejected
Team from another organisationRejected by the database
Teams assigned, none accountableAllowed; shows a No accountable team badge
No teams at allAllowed; no badge
Changing assignmentsAdmin; reading is open to any member
Archiving a teamDoes not release its assignments
Removing a userDoes not change any assignment — assignments name teams, not people

The free-text Owner Team Label on a control (renamed from Owner Team; values untouched) is a separate legacy field, and nothing converts it into a team assignment. Evidence items have no equivalent label.

GET /api/functions
GET /api/organizations/{org_id}/teams ?function_id, ?include_inactive
POST /api/organizations/{org_id}/teams admin
GET /api/organizations/{org_id}/teams/{team_id} includes members + health
PATCH /api/organizations/{org_id}/teams/{team_id} admin
DELETE /api/organizations/{org_id}/teams/{team_id} admin; archives, never destroys
GET /api/organizations/{org_id}/teams/{team_id}/members
POST /api/organizations/{org_id}/teams/{team_id}/members admin
PATCH /api/organizations/{org_id}/teams/{team_id}/members/{user_id} admin
DELETE /api/organizations/{org_id}/teams/{team_id}/members/{user_id} admin

Deleting a team archives it — DELETE sets the team inactive. Use include_inactive on the list endpoint to see archived teams.

Team assignment of controls and evidence uses one resource for both, selected by type:

GET /api/organizations/{org_id}/team-assignments ?type=control|evidence, ?item_ids, ?team_id
POST /api/organizations/{org_id}/team-assignments admin; {type, item_id, team_id, is_accountable}
DELETE /api/organizations/{org_id}/team-assignments/{id} admin

The GET returns one map keyed by item id, with each team and its primary and delegate embedded, so a list view renders ownership without a request per row. item_ids is repeated, not comma-joined, and is capped per request; team_id narrows to one team.

POST is an upsert. Assigning a team that is already assigned updates its is_accountable flag and returns 200; a genuinely new assignment returns 201. Posting is_accountable: true demotes the current accountable team in the same transaction, so promotion is a single request — never delete and re-create to move accountability.

item_id is the UUIDscoped_controls.id or evidence_tracking.id — not a control’s scf_id and not a catalogue evidence_id. An unrecognised type is a 422 naming the supported values; a mutation attempted by a non-admin is a 403.

Both list endpoints also take team and function filters:

GET /api/organizations/{org_id}/scoped-controls-paginated ?team_id, ?function_id
GET /api/organizations/{org_id}/evidence-tracking ?team_id, ?function_id

Both are optional and compose with every other filter on those endpoints (scope_status, domain, csf_function, framework, search, and system_id on evidence). Supplying both intersects them — an item must match the team and the function.

They match any assigned team, not only the accountable one, so filtering by a team returns everything that team is on. Both endpoints resolve that through one shared helper (services/team_assignments.py::team_assignment_filter()), so the two lists cannot drift on what “assigned to this team” means — a team’s controls and a team’s evidence are selected by the same rule.

Note the two endpoints paginate differently. The controls list is paginated — limit defaults to 50 and caps at 200 — and the filter is applied before the row count, so total reflects the filtered set rather than the unfiltered one. The evidence list is not paginated and returns every row for the organisation. It takes the same filters anyway: partly so the two lists agree, and partly because an unpaginated list is the one you least want to send to a browser whole only to discard most of it.

A team filter on the controls list returns only controls that have been scoped. The list is catalogue-driven, and a control the organisation has never scoped has no row for an assignment to attach to.

The application’s own list views use these parameters, so the controls list filters across the whole catalogue rather than only the rows it has loaded.

Assignment changes are written to the audit log with entity_type of control_team_assignment or evidence_team_assignment and an action of create, update or delete, tracking scoped_control_id (or evidence_tracking_id), team_id and is_accountable. A promotion writes two entries — the promotion and the demotion it caused. A re-post that changes nothing writes none, so an idempotent client does not fill the trail with noise.

See User Management for the full guide.


In the web interface, under Settings, Backups (Tenant Export / Import):

  1. Download Tenant Export — one organisation’s working data as a JSON file. A partial tenant export, not a disaster-recovery backup
  2. Import Tenant Data — upload a previous export, review the preview, then Confirm Restore

For a real backup use scripts/backup.sh — see Backup & Restore


Where an organisation’s evidence files are written. Each organisation may configure its own object store; one that has not falls back to the platform store, and then to whatever the process environment names, so an existing installation keeps working untouched. Organisation administrators drive this from Settings, then Evidence storage — see Evidence Storage Settings.

A configuration is created as a draft, which nothing resolves and nothing writes to. Activating it runs a real write, read-back and delete against the store first and refuses on any failure, so no configuration can go live without having been proved reachable.

The connection test. POST .../evidence-storage/test runs that same round trip on demand, against a draft, an active row, or — with no config_id in the body — whatever is in force for the organisation. It answers 200 with success: false when the store cannot be reached, rather than an error status: an unreachable customer bucket is a result the administrator asked for, not a fault in this API. Four steps are reported in order, each ok true or false:

StepWhat it did
addressResolved the configuration and built a client. Fails on an undecryptable secret, before any network call
putWrote one throwaway object
getRead it back
deleteRemoved it

A step that was never reached is reported with error_class: "NotAttempted" rather than omitted, so the list always has four entries and the first ok: false is the failure. A step carries the store’s status_code where there was one and an exception class name where there was not. Neither the object’s content nor anything the store sent back is returned, and no credential appears in any field.

StateWhat it means
draftEditable, inert. Nothing resolves it
activeWhere this organisation’s evidence is written. One per organisation
retiredOut of service, kept so evidence written under it is still readable
ProviderEndpointNotes
Amazon S3Derived from the regionThe only provider that can use an ambient instance role instead of a key pair
Google Cloud StorageFixed, not editableReached over the S3-compatible XML API with an HMAC key pair
MinIOYoursPath-style addressing; no server-side encryption. Your own MinIO deployment — the bundled one is end-of-life, see the troubleshooting guide
S3-compatibleYoursAny other S3 API

Every endpoint typed into this screen is https only, whatever the provider — MinIO included — and no endpoint resolving to a loopback, private, carrier-grade NAT or link-local address is accepted. The http scheme and an internal address are permitted only for the bundled store the installer provisions, which no request can create.

GET /health carries an evidence_storage component. It takes no authentication, and it reports the platform-wide effective store — the one an organisation with no configuration of its own falls back to. It says nothing about any individual organisation’s store.

"evidence_storage": { "status": "ok", "source": "bundled", "provider": "minio" }
FieldValues
statusok, unconfigured, error. Only error degrades the overall status; unconfigured is a working --no-minio install and does not
sourcebundled, platform, legacy_env, or none
provideraws_s3, gcs, minio, s3_compatible, or null

An error adds a fourth field carrying the exception class name only. No bucket, endpoint, credential or hostname appears in any state: the endpoint is unauthenticated and a bucket name is an asset inventory.

It never dials the store. The answer comes from the resolver’s cached snapshot, so a Docker healthcheck every 30 seconds costs the customer’s object store nothing and a network blip cannot flap container health. For a real reachability answer use the connection test above, which dials on demand and has an administrator to report the failure to. See Monitoring for the full table.

All require the admin role in the organisation named in the path. A configuration id belonging to another organisation answers 404, never 403.

POST /api/organizations/{org_id}/evidence-storage/test write, read back, delete; reports each step
POST /api/organizations/{org_id}/evidence-storage creates a draft
GET /api/organizations/{org_id}/evidence-storage this organisation's configurations
GET /api/organizations/{org_id}/evidence-storage/effective the one actually in force, and where it came from
GET /api/organizations/{org_id}/evidence-storage/{config_id}
PATCH /api/organizations/{org_id}/evidence-storage/{config_id} drafts only; 409 otherwise
POST /api/organizations/{org_id}/evidence-storage/{config_id}/activate probes first, then goes live
POST /api/organizations/{org_id}/evidence-storage/{config_id}/rotate replaces the stored secret
POST /api/organizations/{org_id}/evidence-storage/{config_id}/retire out of service, row kept
DELETE /api/organizations/{org_id}/evidence-storage/{config_id} 409 while active or referenced
POST /api/organizations/{org_id}/evidence-storage/{config_id}/copy-to/{target_config_id}
202 with the queued run; 422 same config or target
not active; 409 if one is already running
GET /api/organizations/{org_id}/evidence-storage/copy-sources stores holding this org's evidence, minus the
active one; includes the platform store when this
organisation's files are stamped to it
GET /api/organizations/{org_id}/evidence-storage/copy-runs recent copy runs, newest first
GET /api/organizations/{org_id}/evidence-storage/copy-runs/{run_id} one run's progress

The copy reads every evidence file of this organisation recorded under the source configuration, writes it to the target, verifies it by size and SHA-256 read-back, and re-points the row — one file per transaction, so a re-trigger resumes rather than repeats. It never deletes from the source.

The {config_id} in the copy path may be the platform configuration as a source, which is how a bundled installation’s evidence gets out: activating an organisation’s first own store stamps its existing files with the platform row, because that is where the bytes are. A platform id the organisation neither resolves to nor has files stamped to answers 404, like any row that is not theirs. The target is always strictly organisation-scoped, so no copy can write into the shared store.

A source of this organisation’s own is retired only when no evidence file references it, which is also the condition a DELETE checks, so a copy that left rows behind leaves the source both un-retired and undeletable. A source that is the platform store, an is_bundled row, or another organisation’s row is never retired: the run reports source_retired: false with a source_retired_reason naming why, and the screen repeats that string verbatim. Run progress is held in Redis for a day, not in the database: losing it loses the report, never the evidence.

POST .../activate also answers 409 with an unstamped_files count when the store in force is the one named in the installation’s environment (legacy_env) and the organisation still has evidence files not associated with any configuration row. There is no correct row to associate them with, and activating anyway would leave them resolving to the new store, which does not hold them. Seed the platform configuration — the installer does this — and retry.

The secret is encrypted with SCF_SECRET_KEY before it reaches the database and is never returned: a configured row renders a fixed mask, the same eight characters whatever the secret is. With no SCF_SECRET_KEY configured, the three writes that store a secret — create, edit and rotate — are refused with a 409 naming that as the cause. Activate, retire and delete store no secret and are unaffected.

Every configuration also reports where it came from and whether the operator manages it, in the same two fields the Integrations screen uses: source and managed_by_operator. A row of the organisation’s own is org and the organisation’s admins may edit it; the platform row is platform and belongs to whoever installed the platform. The effective read adds the third source, legacy_env — the process environment, which is what an installation with no configurations at all resolves to, and which no one can change from the application:

sourcemanaged_by_operatorWhat it is
orgfalseThis organisation’s own active configuration
platformtrueThe platform default, set by the installer or an operator
legacy_envtrueNo active configuration applies to this organisation, so the process environment is in force. config_id is null

The effective read also carries is_bundled, which is true only for the object store this installer provisioned into the stack. It is a column on the row, written once at seeding and by nothing else — no request can set it. Read it rather than inferring “bundled” from source == "platform" and a MinIO provider: an operator who configured a platform-wide MinIO of their own matches that pattern and is not running the bundled store.

The effective read returns no credential — not the stored secret, not a mask of it, and not the access key id. It also reports configured, which is false when nothing — no organisation row, no platform row, and no usable environment setting — resolves for this organisation, and true once something does. Read configured rather than the source to decide whether an object store is in force: legacy_env is returned in both cases, and only configured separates an installation running on its environment settings from one with no evidence storage at all.

Rotating an active configuration probes the store with the new credential before anything is written, so a bad credential leaves the old one in place instead of taking evidence storage down. A successful rotation bumps the configuration’s key version, which every process uses as part of its storage client cache key, so background workers pick the new credential up within a couple of seconds without a restart.


Self-hosted only. The installer generates every credential; you type none on the bundled path. See Credentials and secrets.

Terminal window
scripts/install.sh --up # first run: wizard on 127.0.0.1:8765, then start the stack
scripts/install.sh --unattended ./install.json # scripted / CI install: same validation, no browser
scripts/install.sh --import-env # move an existing .env's credentials into 0600 files
scripts/install.sh --port 9765 # wizard on another loopback port
scripts/install.sh --no-minio # recommended for real evidence: bundle NO object store, configure your own in the app
ssh -L 8765:127.0.0.1:8765 <user>@<host> # remote host: tunnel first, then open http://127.0.0.1:8765/
ItemWhere
Credential files$SCF_SECRETS_DIR (recorded in .env as an absolute path): a 0700 directory, one 0600 file per credential
SCF_SECRET_KEY$SCF_SECRETS_DIR/SCF_SECRET_KEY on an installer-provisioned install; an SCF_SECRET_KEY= line in .env on a legacy install. scripts/upgrade.sh generates it if absent and never overwrites it
Non-secret settings.env in the checkout, including SCF_SECRETS_DIR and COMPOSE_FILE=docker-compose.yml:docker-compose.secrets.yml
Provisioning sentinel$SCF_SECRETS_DIR/.provisioned — makes provisioning once-only; do not delete it
Provisioning token$SCF_SECRETS_DIR/.provision-token — deleted when the wizard finishes; never in a URL, never in a backup
Terminal window
docker compose exec backend python -m cli.admin secrets-status # integration credential health; never prints a value
docker compose exec backend python -m cli.admin backfill-encrypt # encrypt legacy plaintext rows in place (idempotent)
docker compose exec backend python -m cli.admin rotate-secret-key # re-encrypt every stored credential under the primary SCF_SECRET_KEY
Terminal window
scripts/backup.sh # one backup set into ./backups, then prune
scripts/upgrade.sh --rollback <TS> # restore a set, credential tarball included
scripts/upgrade.sh --resume-post-checkout <TS> # re-run only the second half of an upgrade (rebuild, migrate, start, verify, env fixups) against the code already checked out, with <TS> as its rollback point
FileContents
<TS>_v<version>.dumpPostgres custom-format dump (whole database)
<TS>_v<version>_minio.tgzMinIO evidence volume tarball
secrets-<TS>.tar.gzCredential files from SCF_SECRETS_DIR, mode 0600, excluding .provision-token. Not written on a legacy .env install — back up .env separately
<TS>_ref.txtGit ref at backup time
<TS>_checksums.sha256Checksums of the data files

  1. Go to Control Scoping
  2. Click Scope by Framework
  3. Select your target framework(s)
  4. Click Add to Scope
  5. Review and configure controls
  1. Check Dashboard for overall status
  2. Review the Evidence Dashboard tab for gaps
  3. Filter by framework being audited
  4. Create tasks for missing evidence
  5. Verify all controls show green status
  1. Check Dashboard for at-risk items
  2. Review Tasks for due/overdue items
  3. Check notification bell for mentions
  4. Update task status as needed