Sheet MER-05 — Audit & Compliance Manual
Controls
Control creation, ownership, mapping, exceptions, testing, and the workflow that makes a control library usable.
Scope
Controls are where policy intent becomes operational reality. This page keeps the public-safe guidance for creating, mapping, testing, and managing controls while removing private product navigation and API detail.
Creating Controls
Controls are organizational practices that address compliance requirements. Each control belongs to a compliance program.
Steps
-
Go to Controls in the sidebar and pick the target program from the program selector at the top of the page.
-
Click New Control.
- Fill in the required fields: - Control Ref: A unique identifier within the program (e.g., “CTRL-001”, “AC-01”). - Title: A descriptive name for the control.
- Optionally fill in: - Description: What the control does. - Implementation Notes: How the control is implemented. - Owner: Search and select an active user from this Meridian account, and/or record the responsible team. Cross-account and deactivated users cannot be assigned.
- Fulfiller: Who operates the control (Internal, MSP, or Vendor).
- Frequency: How often the control operates (Continuous, Daily, Weekly, Monthly, Quarterly, Annual, Ad Hoc).
- Effective Date: When the control became or becomes active. 5. Optionally map the control to framework requirements inline on the same form — add one or more requirements with full or partial coverage and the mappings are created in a single follow-up API call after the control is persisted. Mappings can also be added later from the control detail page.
Meridian verifies the selected program’s current lifecycle state before it offers New Control or Create the first control. While that verification is loading, or if it fails, creation remains unavailable. A persistent message shows the lookup failure and provides Retry; controls that loaded successfully remain visible while the independent program lookup is retried. Changing programs invalidates outstanding responses, so a slower response from the previous selection cannot authorize creation or replace the newly selected program’s controls.
If you assign a governing policy, Meridian only accepts policies from the same account that are either shared defaults, bound to the same program, or scoped to one of the program’s organizations. If the selected policy is from another tenant or does not apply to the program, the save is rejected.
Controls are always created in “Not Implemented” status.
Editing Controls
Open a control and choose Edit to change its identity, description, implementation notes, accountable owner or team, fulfiller, cadence, effective date, control type, and SOX risk-and-control-matrix dimensions. The editor checks the parent program before presenting the form. An archived program is read-only; if Meridian cannot verify the program lifecycle state, the editor fails closed and provides a retry instead of allowing an unsafe mutation.
The owner picker uses the active account directory. A directory failure is shown next to the picker with its own retry control and does not discard the existing owner. Classification fields use the controlled values accepted by the API. If an older or malformed record contains an unknown value, Meridian displays that value explicitly and blocks saving until an operator selects a supported value.
When a not-yet-classified control title matches Meridian’s classification heuristics, the editor may offer an advisory control-type suggestion after the title loses focus. The suggestion never overwrites an operator’s explicit selection and must be accepted before it changes the form.
If saving fails, the editor keeps every entered value and displays the specific failure for correction and retry. Navigation and editable fields are disabled while the update is in flight so the operator cannot accidentally abandon a request whose outcome is still pending.
When a detail page, mapping picker, execution-evidence list, or parent program cannot be read, Meridian keeps independently loaded control data visible but shows the failed dependency and an in-place retry. It never substitutes a successful-looking empty list for an unavailable catalog or evidence set. A create-control requirement picker similarly warns when one or more bound framework requirement directories fail, so operators can retry before relying on an incomplete mapping choice.
Naming Conventions
Use a consistent naming scheme for control references. Common patterns:
- Sequential:
CTRL-001,CTRL-002, etc. - Category-based:
AC-01(access control),CM-01(change management), etc. - Framework-aligned:
CC1.1-01(matching the requirement it addresses).
The control_ref must be unique within each program but can be reused across different programs.
Managing Control Status
Automatic Status Derivation
Control status is automatically derived from test results. When a test execution is recorded (manually or by a connector), Meridian immediately updates the control’s status according to the policy:
| Latest Test Result | Derived Status |
|---|---|
fail |
Failing |
error |
Failing |
pass |
Implemented |
partial |
Partially Implemented |
| No test has run | Status unchanged |
This means:
-
An “Implemented” control that starts failing its tests will automatically be demoted to “Failing” — auditors will see the current state, not a stale “Implemented” badge.
-
A “Not Implemented” control that passes a test is automatically promoted to “Implemented”.
-
Every derivation is auditable: a
control.status_derivedevent is written to the audit log with the before/after status and the test run that triggered it.
Manual Status Transitions
You can also transition a control’s status manually. Available statuses for manual transitions:
- Not Implemented: The control exists as a plan but is not yet active.
- Partially Implemented: The control is in progress or only partially operational.
- Implemented: The control is fully operational.
- Not Applicable: The control has been scoped out.
- Failing: System-managed only — set by the derivation engine when tests fail.
To change a control’s status manually:
- Open the control detail view.
- Use the status transition action.
- Select the target status from the available transitions.
Not all transitions are allowed. For example, you cannot jump directly from
“Implemented” to “Not Implemented” — you must go through “Partially Implemented”
first. “Failing” cannot be set manually; it is set by the test result engine only.
“Merged” is also not a manual target: Meridian only sets merged through the
dedicated merge-controls workflow so the duplicate control’s tests, mappings,
evidence bindings, and related graph links are migrated before the duplicate is
retired.
Pinning a Status (Manual Override)
If you need to hold a control at a specific status regardless of test results — for example, while investigating a false positive — use the status override:
- Open the control detail view.
- Select the status you want to pin: Not Implemented, Partially Implemented, Implemented, or Not Applicable.
While a status is pinned, new test results will not change the status. The control’s status badge in the UI shows a pin icon to indicate the override is active.
To restore automatic derivation, click Clear Override (or send
{ "override": null } to the API). Meridian immediately re-derives the status
from the latest test result.
Use override sparingly. Overrides suppress the core value of automated status derivation — auditors reviewing your controls can see when a status is operator-pinned versus test-derived.
Marking a control Not Applicable
Scoping a control out is an auditable decision, so Meridian requires a written rationale when you mark a control Not Applicable:
-
On the control detail view, click Mark Not Applicable in the status toolbar.
-
A dialog opens. Enter the reason the control does not apply (for example, “We run no on-premise datacenter, so physical access controls do not apply.”). The Mark Not Applicable button stays disabled until you enter a non-empty reason.
-
Click Mark Not Applicable to confirm, or Cancel to abort.
The rationale is stored with the control and recorded in the control’s transition audit log, so an auditor can later see both that the control was scoped out and why. If you try to mark a control Not Applicable without a reason (for example via the API directly), the request is rejected.
When you later move the control back into scope (Not Applicable → Not Implemented), Meridian clears the stored rationale automatically so it is not mistakenly attributed to the new status.
Archived Programs
When a program is archived, its controls become read-only. You cannot create, edit, delete, or transition controls in that program, and the audit cycle / finding workflows tied to that archived program are frozen as well. Archived programs also freeze control reviews, reviewer reassignment, review conclusions, evidence requests, findings, and audit-cycle mutations so the closed audit record remains stable.
Mapping Controls to Requirements
Controls address framework requirements. Mapping a control to a requirement records that relationship and contributes to gap analysis coverage.
Mapping a Control
- Open a control’s detail view.
- Go to the “Mappings” tab.
- Use the requirement picker to search within the frameworks already bound to the parent program.
- Select a requirement. Each result shows the requirement reference/title and the framework name so you can tell SOC 2 from ISO 27001 without decoding numeric IDs.
- Set the coverage level: - Full: The control fully satisfies the requirement by itself. - Partial: The control only partially addresses the requirement.
- Optionally add notes about how the control addresses the requirement.
You can map a single control to requirements across multiple frameworks. This is common when one control satisfies criteria in both SOC 2 and ISO 27001, for example.
If the parent program has no frameworks attached, Meridian blocks the mapping form and tells you to bind a framework first from the program setup flow.
Removing a Mapping
- Open the control’s Requirements tab.
- Click the remove icon next to the mapping you want to delete.
Tips
- Map controls to requirements early to track gap analysis progress.
- Use “partial” coverage when a requirement needs multiple controls working together.
- Bulk mapping (selecting multiple requirements at once) is supported and saves time during initial setup.
Reading Gap Analysis
Gap analysis shows how well your compliance program covers framework requirements.
Accessing Gap Analysis
- Navigate to a compliance program.
- Click “Gap Analysis” in the program navigation.
Understanding the View
The gap analysis presents a per-framework breakdown with color-coded status for each requirement:
- Covered (green): At least one control with full coverage is mapped.
- Partially Covered (yellow): Controls are mapped but only with partial coverage.
- Not Covered (red): No controls are mapped — this is a gap.
- Excepted (gray): An approved exception exists for this requirement.
Summary Metrics
At the top of the gap analysis view, you see aggregate metrics:
- Total Requirements: Total applicable requirements across all frameworks.
- Covered: Requirements with at least one full-coverage control.
- Partially Covered: Requirements with only partial-coverage controls.
- Gaps: Requirements with no controls mapped.
- Excepted: Requirements with approved exceptions.
- Coverage %: Percentage of requirements with full coverage.
Filtering
Use the filters to focus on specific areas:
- Framework: Show only one framework’s requirements.
- Category: Show only requirements in a specific category (e.g., “CC1” for SOC 2 Common Criteria 1).
- Coverage Status: Show only requirements matching a specific status (covered, partially_covered, not_covered, excepted).
Using Gap Analysis for Audit Readiness
Gap analysis answers “are we ready for audit?”:
- Target zero red (not_covered) items for the frameworks in scope.
- Review yellow (partially_covered) items and decide if additional controls are needed.
- Document gray (excepted) items with clear justifications and compensating controls.
- Track coverage_pct over time to measure progress toward audit readiness.
Managing Exceptions
Exceptions document when a control cannot be implemented or a requirement does not apply.
Creating an Exception
- Open a control’s detail view.
- Go to the “Exceptions” tab.
- Click “Add Exception”.
- Fill in: - Reason: Why the exception is needed (required). - Requirement: Optionally target a specific requirement. - Compensating Control: Optionally reference another control that mitigates the gap. - Expires At: Optionally set an expiration date for time-boxed exceptions.
Before showing the form, Meridian verifies the selected control and its parent program. If either response is unavailable, malformed, or mismatched, the form remains blocked and offers Retry. Archived programs cannot receive new exceptions. Requirement and compensating-control picker failures are shown as dependency errors, not successful empty lists.
The Exceptions tab uses server-side pagination. Use the footer to move between pages or change page size; Meridian remembers your selected page size in the browser for that control’s exception list.
Exceptions are created in “Draft” status.
Approving an Exception
- Open the exception (from the control’s Exceptions tab or the exception list).
- Click “Approve”.
- The system records who approved it and when.
Only approved exceptions affect gap analysis. Draft exceptions do not change requirement coverage status.
Exception Expiry
- Manual expiry: An approved exception can be manually transitioned to “Expired”.
- Auto-expiry: Exceptions with an expiration date are automatically expired when the date passes. This happens when the exception list is viewed — no background job needed.
- Revocation: An approved exception can be “Revoked” if it should no longer apply regardless of expiration date.
Both expired and revoked are terminal states — they cannot be changed further. To reinstate coverage, create a new exception.
Best Practices
- Always document a clear reason for each exception.
- Set expiration dates for temporary exceptions (e.g., “we’ll implement this control by Q3”).
- Reference compensating controls when possible — auditors want to see risk mitigation.
- Review exceptions before each audit to ensure they are still valid.
Adding Test Definitions
Tests define how controls are verified for effectiveness.
Creating a Test
- Open a control’s detail view.
- Go to the “Tests” tab.
- Click “Add Test”.
- Fill in: - Name: Descriptive test name (e.g., “Verify quarterly access review completed”). - Description: What the test checks. - Test Type: Manual, Automated, or Hybrid. - Frequency: How often the test should be run. - Expected Result: What a passing result looks like.
Test Types
- Manual: Requires human execution and judgment (e.g., reviewing access logs).
- Automated: Runs automatically via a connector (WS-04/WS-05 will enable this).
- Hybrid: Has both manual and automated components.
Recording a test execution (CW-23)
Every time you actually run one of your control tests — a quarterly access review, a monthly firewall rule check, a daily log sampling — record it so your audit package has the proof.
How:
- Open
ControlDetail(e.g. CC6.1) → Tests tab. - Click Record on the row for the test you just ran (or open
TestDetailand click Record execution in the top right). - Fill in the modal: - Executed at — when you actually ran it (default is now). - Result — pick one: pass, fail, partial, error, not_run. - Sample size / description — how many items you looked at and how you picked them (e.g. “10 admins pulled from Okta, all checked for MFA enrollment”). - Notes — anything an auditor will want to know. - Evidence — attach existing files via the picker (scoped to your program) OR click Upload new to upload fresh ones inline. Mark one as primary if there’s a main artifact; the rest are supporting.
- Click Record execution.
The execution becomes part of the test’s history and shows up in the Test executions during this cycle section of every future audit cycle that covers its date range. It is immutable — corrections are recorded as a new execution, and the old one can be marked superseded.
That immutability has an operational consequence: once a test has any recorded executions, you can no longer delete the test definition. Meridian returns a conflict instead of erasing history. If you need to change the test going forward, leave the historical test in place and create a new replacement test definition for future runs.
If your control test carries a plain-English hint (every SOC 2 test does), it shows above the execution history on TestDetail. It’s “Example guidance — confirm with your auditor” copy, not audit gospel, but it’s usually enough to know what to put in the notes and what to attach.
Installing Meridian-Owned Automated Tests
Some recurring proof can be tested directly from Meridian data without an external connector. From a control’s Tests tab, install a first-party test when the control is meant to prove one of these internal workflows:
| Test | Use When |
|---|---|
| Access reviews completed on time | The control depends on access reviews being completed before due dates. |
| Policies published and acknowledged | The control depends on policy publication and user acknowledgment. |
| Evidence freshness threshold | The control depends on evidence staying fresh above a threshold. |
| Control ownership and monitoring summaries | The control depends on every control having an owner and monitoring summary. |
| Failed or stale test execution SLA | The control tracks stale or failed tests being remediated quickly. |
| Risk, exception, and remediation thresholds | The control depends on open risk/remediation counts staying under thresholds. |
| Trust Center request SLA | The control tracks response time for Trust Center document requests. |
| Auditor evidence request overdue status | The control tracks overdue auditor evidence requests. |
Installed first-party tests appear in the same test table as manual and connector-backed tests, with a Meridian-owned source badge. Clicking Run records a normal test execution. Scheduled runs happen through the same scheduler tick as connector tests, so due/overdue badges and alerts behave the same way.
How to tell if a test is overdue
Every test row on the ControlDetail Tests tab carries a cadence badge. Read it like this:
- Green (Current) — you’re inside the first 80% of the frequency window since the last run. Nothing to do yet.
- Yellow (Due soon) — you’re in the last 20% of the window. Put it on this week’s list.
- Red (Overdue) — the window closed. Record an execution now, and (if it’s been a while) think about whether the underlying control was actually operating during the gap.
- Gray (Never run) — you’ve defined the test but never executed it. Either run it or delete it — a test definition with no runs is audit-bait.
Hover the badge for the next expected date. Continuous tests are special: >1h without a run is due_soon, >24h is overdue. Ad-hoc tests never go overdue — they stay Current after the first run.
To see every overdue test across the whole program at once, open Program → Tests Due (the widget on the program overview or the full page at the relevant workflow). Sort and filter are applied server-side across all tests before pagination, so page 1 always shows the most urgent tests globally — not just within the current page:
- Status tab — filter to Overdue, Due Soon, Never Run, or Current.
- Control ref starts with — prefix filter on control reference (case-insensitive, e.g.
CC6). - Frequency — restrict to tests with a specific cadence.
- Sort columns — click any column header to sort ascending; click again to reverse. Available sort keys: Control, Test, Frequency, Last run, Status, Due in. Sorting by Due in ascending (the default) puts the most-overdue tests on page 1 across the entire dataset.
Click Record on any row to open the execution modal without navigating away.
How to give an auditor your evidence package
When you’re ready to hand the fieldwork to an auditor, generate an evidence package:
- Open the audit cycle on
AuditDetail. - Click Preview manifest to expand the tree view and verify exactly what the auditor will see before sharing. Everything in the preview is everything they’ll get.
- Click Issue share link. The modal defaults to a 7-day expiration, hard-capped at 30 days. Long expirations (>14 days) get a yellow warning because long-lived share tokens widen the breach window.
- Copy the endpoint and raw token immediately. The raw token is shown exactly once and is never stored server-side — only its SHA-256 hash is. If you close the modal without copying, the only fix is to revoke and issue a new token.
- Send the endpoint and token to the auditor. They call the endpoint with
Authorization: Bearer <raw_token>, no login required; the backend streams the ZIP and logsaudit.package.token.usewith the auditor’s IP, user agent, and download count.
Back on AuditDetail you’ll see the issued tokens in a table with status badges:
- Not yet used — issued but the auditor hasn’t opened it yet.
- Downloaded recently — opened in the last 24 hours.
- Last used {date} — older downloads.
Revoke any token before its expiration if you need to cut off access. Revokes are idempotent; you can’t unrevoke — just issue a fresh link if you still need to share.
If you change data in the cycle (new evidence, new executions, new findings) between generations, re-generating the package produces a new row with a different manifest_hash. Re-generating with no changes returns the existing package unchanged — this is the “here’s the exact package I showed the auditor last Tuesday” guarantee, backed by SHA-256 over the canonical manifest bytes. Auditors can reference the hash in their workpaper.
Gate: cycle closure with missing test executions
When you try to mark an audit cycle complete, the backend checks that every test on every control has at least one execution during the fieldwork window. If any don’t, you get a modal listing the missing tests with a free-text override reason box:
- Minimum 20 characters after trim. Empty, short, and whitespace-only reasons are rejected.
- The counter shows
{count}/20 minimum; the Submit button is disabled until you’re over. - On submit, the cycle closes and an
audit_cycle.closure_overrideaudit log entry captures the reason plus a full snapshot of the missing tests at that moment. Auditors (and future you) can see exactly what was skipped.
Use the override when the coverage gap is genuine (connector was down, test was being rewritten) and either reaffirm the control with compensating evidence or flag it as a finding. Don’t use the override to hide gaps — the audit log is forever.