---
title: 'Mapping Compliance Requirements to the Cloud'
source: 'https://academia.sh/en/courses/cloud-governance/mapping-compliance-requirements-to-the-cloud'
course: 'Cloud Governance, Security and Cost'
language: en
updated: '2026-09-13T05:07:36+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - 'Takes compliance requirements by type, breaks each one into evidence items, and counts who the evidence comes from'
    - 'Redraws the shared-responsibility boundary on the evidence side: names the items where layer and evidence producer do not line up, and the requirements whose evidence stays in the gap'
    - 'Derives the ongoing cost of producing evidence in two line items: record retention and report generation'
---

# Mapping Compliance Requirements to the Cloud

Turning compliance requirements into evidence in the rented layer: across 12 requirement types and 26 evidence items, 7 items come from the provider's document and 16 from the tenant's own record, 3 requirements' evidence stays in the gap, 7 of the 14 items sitting outside the tenant's layer have evidence that does not come from the provider, and producing evidence costs 139 fictional units and 160 person-hours a year.

The previous lesson ran detection rules and produced three numbers: caught, missed, false alarm.
All three were the team's own measure — the same side set the threshold and made the decision to
close a rule. When someone outside says "show that access is restricted and unusual activity is
monitored," what is being asked for is not these numbers. What is being asked for is **evidence**:
a record or document that shows, in a form presentable to someone who did not set that obligation,
that the obligation is met.

Turning external constraints into runnable checks was measured in M20/K04; there, evidence took
the place of loosening, and all of the evidence was the architecture's own output. In the rented
layer, this splits. Part of the requirements are met on the provider's machine, facility, or
personnel; the tenant has no record it can produce there, and the **provider's document** stands
in as evidence. This lesson's measure is that split. Requirements here are referred to **by
type** — data residency constraint, retention obligation, right to deletion, access-logging
obligation, privileged-access evidence — and no regulation, standard, certification, or framework
name is written.

## Requirements and Evidence Items

The example course is the fictional **regional measurement network**. **CS43 — requirement
catalog:** twelve requirement types. **CS44 — evidence-item table:** twenty-six items; each item
carries which layer it sits in (provider, shared, tenant), who produces its evidence (the
provider's document, the tenant's own record, none), its freshness in days, its daily line count,
and its retention period. **CS45 — requirement-item mapping:** thirty-two links; one item can
serve more than one requirement. **CS46 — record units:** 200 bytes per line, 1.5 fictional units
a month per GB. **CS47 — report generation:** every requirement is compiled once a quarter, 2
person-hours fixed per requirement plus 0.5 person-hours per item. **CS48 — evidence store cap:**
12 GB (fictional unit).

The file below builds the tables and separates evidence by its producer. It is a process-internal
model; no real document, record, or charge exists.

```js
// compliance/evidence.mjs — turning compliance requirements into evidence in the rented layer.
// Process-internal model: the regional measurement network (fictional); no real document, record, or charge exists.

const parseRows = (s) => s.trim().split("\n").map((l) => l.trim().split("|"));
const row = (g, ...s) => console.log(s.map((v, i) =>
  (g[i] < 0 ? String(v).padEnd(-g[i]) : String(v).padStart(g[i]))).join(""));

// Evidence item: name|layer|producer (provider|own|none)|freshness (days)|daily lines|retention (days)
const ITEM = Object.fromEntries(parseRows(`
  resource-inventory|tenant|own|1|400|1095
  region-tag|tenant|own|1|400|1095
  data-flow-map|tenant|none|0|0|0
  facility-region-attestation|provider|provider|365|0|0
  retention-policy-record|tenant|own|1|150|1095
  lifecycle-run-record|tenant|own|1|900|1095
  backup-copy-inventory|shared|own|7|60|1095
  deletion-request-record|tenant|own|1|30|2555
  deletion-propagation-record|tenant|own|1|120|2555
  backup-deletion-confirmation|shared|none|0|0|0
  audit-log|shared|own|1|9000|2555
  data-plane-access-record|provider|own|1|4000|2555
  provider-personnel-access-attestation|provider|provider|365|0|0
  privileged-session-record|tenant|own|1|200|2555
  role-assumption-record|tenant|own|1|600|2555
  encryption-configuration-scan|shared|own|1|300|1095
  key-ownership-attestation|provider|provider|365|0|0
  transit-endpoint-scan|tenant|own|1|250|1095
  client-verification-record|tenant|none|0|0|0
  key-rotation-record|shared|own|1|20|2555
  key-material-destruction-attestation|provider|provider|365|0|0
  facility-access-control-attestation|provider|provider|365|0|0
  hardware-destruction-attestation|provider|provider|365|0|0
  restore-drill-record|tenant|own|90|10|1095
  incident-timeline|shared|own|1|80|2555
  provider-incident-notification|provider|provider|30|0|0`)
  .map(([name, layer, producer, fresh, lines, retention]) => [name,
    { layer, producer, fresh: +fresh, lines: +lines, retention: +retention }]));

// Requirement type -> evidence items. No regulation, standard, or framework name.
const REQUIREMENT = parseRows(`
  G01 data residency constraint|resource-inventory region-tag data-flow-map facility-region-attestation
  G02 retention lower bound|retention-policy-record lifecycle-run-record backup-copy-inventory
  G03 retention upper bound|retention-policy-record lifecycle-run-record
  G04 right to deletion|deletion-request-record deletion-propagation-record backup-deletion-confirmation
  G05 access-logging obligation|audit-log data-plane-access-record
  G06 privileged-access evidence|privileged-session-record role-assumption-record provider-personnel-access-attestation audit-log
  G07 encryption-at-rest evidence|encryption-configuration-scan key-ownership-attestation
  G08 encryption-in-transit evidence|transit-endpoint-scan client-verification-record
  G09 key-rotation evidence|key-rotation-record key-ownership-attestation key-material-destruction-attestation
  G10 physical-access-and-destruction evidence|facility-access-control-attestation hardware-destruction-attestation
  G11 recoverability evidence|restore-drill-record backup-copy-inventory
  G12 incident-notification evidence|incident-timeline provider-incident-notification audit-log`)
  .map(([name, k]) => ({ name, item: k.split(" ") }));

const LAYER = ["provider", "shared", "tenant"];
const PRODUCER = ["provider", "own", "none"];

console.log(`${REQUIREMENT.length} requirement types, ${Object.keys(ITEM).length} evidence items, ` +
  `${REQUIREMENT.reduce((t, g) => t + g.item.length, 0)} requirement-item links`);

// Per requirement: who the evidence comes from, whether a gap exists, how old the oldest evidence is
const G = [-47, 8, 16, 8, 8, 15];
console.log();
row(G, "requirement type", "items", "from provider", "own", "gap", "oldest (days)");
const status = {};
for (const g of REQUIREMENT) {
  const count = (u) => g.item.filter((k) => ITEM[k].producer === u).length;
  const produced = g.item.filter((k) => ITEM[k].producer !== "none");
  const fresh = Math.max(...produced.map((k) => ITEM[k].fresh));
  status[g.name] = { gap: count("none"), fresh };
  row(G, g.name, g.item.length, count("provider"), count("own"), count("none"), fresh);
}
const gapped = REQUIREMENT.filter((g) => status[g.name].gap > 0);
console.log(`\nrequirements whose evidence stays in the gap: ${gapped.length}/${REQUIREMENT.length} -> ` +
  gapped.map((g) => `${g.name.split(" ")[0]} (${g.item.filter((k) =>
    ITEM[k].producer === "none").join(", ")})`).join("; "));

// The shared-responsibility boundary redrawn on the evidence side: layer x producer
const C = [-18, 12, 10, 8, 9];
console.log();
row(C, "layer \\ producer", "provider", "own", "none", "total");
for (const lt of LAYER) {
  const set = Object.values(ITEM).filter((k) => k.layer === lt);
  row(C, lt, ...PRODUCER.map((u) => set.filter((k) => k.producer === u).length), set.length);
}
row(C, "total", ...PRODUCER.map((u) =>
  Object.values(ITEM).filter((k) => k.producer === u).length), Object.keys(ITEM).length);
const outsideTenant = Object.entries(ITEM).filter(([, k]) => k.layer !== "tenant");
const outsideNotProvider = outsideTenant.filter(([, k]) => k.producer !== "provider");
console.log(`of the ${outsideTenant.length} items that sit outside the tenant's layer, ` +
  `${outsideNotProvider.length} have evidence that does not come from the provider: ` +
  `${outsideNotProvider.map(([a]) => a).join(", ")}`);

// The ongoing cost of producing evidence (fictional unit)
const BYTES_PER_LINE = 200, GB = 1e9, UNIT_PER_GB = 1.5;
const own = Object.entries(ITEM).filter(([, k]) => k.producer === "own");
const volume = own.reduce((t, [, k]) => t + (k.lines * k.retention * BYTES_PER_LINE) / GB, 0);
const dailyLines = own.reduce((t, [, k]) => t + k.lines, 0);
console.log(`\n${own.length} items coming from the tenant's own record: ` +
  `${dailyLines.toLocaleString("en-US")} lines a day; by the end of their retention period ` +
  `${volume.toFixed(2)} GB, ${(volume * UNIT_PER_GB).toFixed(2)} units a month, ` +
  `${(volume * UNIT_PER_GB * 12).toFixed(0)} units a year of storage`);

// Report generation: every requirement is compiled once a quarter
const [QUARTER, FIXED, ITEM_HOURS] = [4, 2, 0.5];
const personHours = REQUIREMENT.reduce((t, g) =>
  t + QUARTER * (FIXED + g.item.length * ITEM_HOURS), 0);
console.log(`report generation: ${REQUIREMENT.length} requirements x ${QUARTER} quarters x ` +
  `(${FIXED} + items x ${ITEM_HOURS}) = ${personHours} person-hours/year`);
const attestation = Object.values(ITEM).filter((k) => k.producer === "provider");
console.log(`freshness of the ${attestation.length} documents coming from the provider: ` +
  `${Math.min(...attestation.map((k) => k.fresh))}-${Math.max(...attestation.map((k) => k.fresh))} days; ` +
  `freshness of the tenant's own record: 1-90 days`);

// Limit and remaining (fictional): the evidence store's cap
const LIMIT = 12;
console.log(`evidence store cap ${LIMIT} GB; used ${volume.toFixed(2)}, remaining ` +
  `${(LIMIT - volume).toFixed(2)} -> the audit log's daily line count can still grow by ` +
  `${Math.floor(((LIMIT - volume) * GB) / (BYTES_PER_LINE * ITEM["audit-log"].retention))
    .toLocaleString("en-US")} lines`);
```

```
12 requirement types, 26 evidence items, 32 requirement-item links

requirement type                                  items   from provider     own     gap  oldest (days)
G01 data residency constraint                         4               1       2       1            365
G02 retention lower bound                             3               0       3       0              7
G03 retention upper bound                             2               0       2       0              1
G04 right to deletion                                 3               0       2       1              1
G05 access-logging obligation                         2               0       2       0              1
G06 privileged-access evidence                        4               1       3       0            365
G07 encryption-at-rest evidence                       2               1       1       0            365
G08 encryption-in-transit evidence                    2               0       1       1              1
G09 key-rotation evidence                             3               2       1       0            365
G10 physical-access-and-destruction evidence          2               2       0       0            365
G11 recoverability evidence                           2               0       2       0             90
G12 incident-notification evidence                    3               1       2       0             30

requirements whose evidence stays in the gap: 3/12 -> G01 (data-flow-map); G04 (backup-deletion-confirmation); G08 (client-verification-record)

layer \ producer      provider       own    none    total
provider                     7         1       0        8
shared                       0         5       1        6
tenant                       0        10       2       12
total                        7        16       3       26
of the 14 items that sit outside the tenant's layer, 7 have evidence that does not come from the provider: backup-copy-inventory, backup-deletion-confirmation, audit-log, data-plane-access-record, encryption-configuration-scan, key-rotation-record, incident-timeline

16 items coming from the tenant's own record: 16,520 lines a day; by the end of their retention period 7.72 GB, 11.58 units a month, 139 units a year of storage
report generation: 12 requirements x 4 quarters x (2 + items x 0.5) = 160 person-hours/year
freshness of the 7 documents coming from the provider: 30-365 days; freshness of the tenant's own record: 1-90 days
evidence store cap 12 GB; used 7.72, remaining 4.28 -> the audit log's daily line count can still grow by 8,374 lines
```

The numbers are of the measurement class; their inputs are the assumptions above. Twelve
requirements resolve into twenty-six evidence items and thirty-two links. Of the twenty-six items,
seven come from the provider's document, sixteen from the tenant's own record, and three have no
producer. Item count is larger than requirement count, and link count is larger than item count; a
single item serves more than one obligation — the audit log appears in three separate
requirements, the key ownership attestation in two.

## Evidence's Two Producers

The first place worth reading in the requirement table is the second and third columns. G10 sits
entirely on the provider's side: both of its two items are documents, and the tenant has no record
it could produce there. G03 and G05 sit entirely on the tenant's side. The remaining nine
requirements are mixed, and their evidence file contains pieces of two different types. This
decides the practical shape of compliance work: meeting a requirement is not one owner's job — it
is assembling pieces coming from two producers.

The last column shows this assembly's weak link. **A requirement's evidence is as fresh as its
oldest piece.** For G05, freshness is one day, because both of its items are records kept daily.
For G01, G06, G07, G09, and G10, freshness is 365 days; each of these five requirements holds a
provider document renewed once a year, and the tenant's daily records do not bring the file's age
down. A gap of up to a year can remain between an event and the renewal of the document that
covers it; the provider also sets the renewal calendar, so this is a devolved decision, and it is
an item the tenant cannot speed up.

What the two producers produce is not the same kind of thing, and this distinction comes after the
numbers. The tenant's own record can be queried: give it a date range, filter to a subject, pull an
answer to a different question out of the same record, and recompile it retroactively if needed.
The provider's document is a closed output — it is accepted in the form it is given, no query can
be written into it, its scope cannot be extended, and a second version cannot be requested for a
resource it does not cover. Sixteen items are of the first type, seven of the second. The practical
consequence is this: when an auditor asks a question that is not in the table, the tenant has a
chance of producing an answer for sixteen items and none for seven; for those seven, the answer
that can be given is limited to what is written in the document.

Evidence stays in the gap for three requirements, and all three get named. In G01, the data flow
map is missing: there is no record showing which data flows to which region, so the link between
the tag in the inventory and the facility attestation cannot be established. In G04, the backup
deletion confirmation is missing: the deletion request gets recorded and propagated, but no record
is produced showing the deletion actually happened in the backup copies. In G08, the client
verification record is missing: the endpoint scan shows the server side, and there is no evidence
the client actually performed verification. What the three have in common is this: what is missing
is not a document, it is a **record flow that was never set up**. No one refused it, no one
withheld it — no one asked for it.

## The Boundary Redrawn on the Evidence Side

The cross table is this lesson's main measure. The layer columns say where responsibility sits, the
rows say who the evidence comes from, and the two do not line up. Of the eight items sitting in the
provider's layer, seven are covered by a document, one is not: the data-plane access record
happens entirely inside the provider, but the one who produces its evidence is the tenant, by
keeping that logging turned on. Of the six items in the shared layer, **none** come from the
provider's document; five come from the tenant's record, one comes from neither.

The total collapses this to a single line: of the fourteen items sitting outside the tenant's
layer, seven have evidence that does not come from the provider. In other words, the
responsibility split does not carry over to the evidence side as is; **the evidence boundary has
shifted toward the tenant relative to the layer boundary.** The backup copy inventory, the audit
log, the encryption configuration scan, the key rotation record, and the incident timeline are
work that happens in the shared layer, but it is the tenant who will do the showing when showing is
required. This distinction is not visible in the contract; it is visible in who compiles the
evidence file — and this is exactly where the compilation burden is born.

## The Ongoing Cost of Producing Evidence

Evidence is not produced once and done; it is an ongoing line item, and it is counted under two
headings. The sixteen items coming from the tenant's own record produce 16,520 lines a day; by the
end of their retention periods they hold 7.72 GB, costing 11.58 fictional units a month and 139 a
year in storage. The second heading is heavier: each of the twelve requirements is compiled once a
quarter, and that runs 160 person-hours a year. Putting the two line items side by side is this
lesson's result — evidence's ongoing cost is not mostly storage, it is **compilation labor**, and
it grows per item, not per requirement.

M20/K04's closed loop applies here too, and it adds one word: evidence is also a data class,
subject to its own retention period and its own residency constraint. The word it adds is this:
**the tenant does not produce half of this data class.** The freshness of the seven documents
coming from the provider runs 30 to 365 days, and that range is not the tenant's choice; the
freshness of the tenant's own record runs 1 to 90 days, and that range is the tenant's choice. How
fresh the evidence file can be is decided by both sides at once.

The limit side is counted too. The evidence store's cap is 12 GB, used is 7.72, remaining is 4.28.
That is enough for the audit log's daily line count to grow by 8,374 more lines; past that, either
the retention period has to be shortened — and retention period is itself a requirement — or the
cap has to be grown, which gets written onto the bill.

## Summary

- Twelve requirement types resolve into twenty-six evidence items and thirty-two links; seven of
  the items come from the provider's document, sixteen from the tenant's own record, three have no
  producer.
- Three requirements' evidence stays in the gap (data flow map, backup deletion confirmation,
  client verification record); for all three, what is missing is not a document, it is a record
  flow that was never set up.
- A requirement's evidence is as fresh as its oldest piece: five requirements have a freshness of
  365 days, because each holds a provider document renewed once a year, and the renewal calendar
  is not the tenant's.
- The shared-responsibility boundary does not stand in the same place on the evidence side: seven
  of the fourteen items sitting outside the tenant's layer have evidence that does not come from
  the provider, and none of the six items in the shared layer are covered by a document.
- The ongoing cost of producing evidence is two line items: 16,520 lines/day and 7.72 GB, costing
  139 fictional units a year in storage, plus 160 person-hours a year of report compilation. The
  second is the heavy one.
- 7.72 of the evidence store's 12 GB cap is full; the remaining 4.28 GB leaves room for the audit
  log to grow by 8,374 lines a day.

## Next Step

The topic closes here, and the table it leaves behind fits into a single sentence: in the rented
layer, security is narrowing who can do what, changing what the data shows when it is read, and
being able to show that both were done. All three were given a number — how many legitimate jobs
narrowing stops, how many access records isolation breaks, how many detection misses, and in which
requirement the evidence stays in the gap.

The one thing that was not given a number is their sum. Compliance auditing consumes a quota,
private endpoints consume a monthly rent per service and per network, signal collection consumes a
per-GB charge, evidence retention consumes a store limit; each was written in fictional units in
its own section, but none was set beside another. Access was narrowed, data was encrypted, and
evidence was produced — all of it has a bill, and that bill was never read across this topic. The
next topic opens the bill line by line: which item belongs to what, which team it falls on, and
which share cannot be assigned to any team at all.
