Service Approval — Map: Framework Mapping
Map each generated control to framework objectives individually. This is the most reasoning-heavy sub-skill in the map pipeline. It produces quality-gated framework mappings with rationale.
Inputs:
.service-approval/<slug>/04-map/map-framework-parsed.json— normalized framework objectives.service-approval/<slug>/04-map/map-controls-generated.json— controls with rich metadata
Output: .service-approval/<slug>/04-map/map-framework-mapped.json
Schema: schemas/map-framework-mapped.schema.json — encodes status enum strictly MAPPED or N/A (iter-14 Class F15-revised), coverage enum, control_id pattern matching map-controls-generated, and per-mapping required fields. See also the "Schema rules" section below.
This is one of 4 focused map sub-skills. Each writes to a separate intermediate state file.
Prerequisites
test -f .service-approval/<slug>/04-map/map-framework-parsed.json && echo "framework: OK" || echo "ERROR"
test -f .service-approval/<slug>/04-map/map-controls-generated.json && echo "controls: OK" || echo "ERROR"
Load both inputs:
python3 -c "
import json
fw = json.load(open('.service-approval/<slug>/04-map/map-framework-parsed.json'))
cg = json.load(open('.service-approval/<slug>/04-map/map-controls-generated.json'))
print(f'Framework: {fw[\"framework\"][\"name\"]} — {len(fw[\"framework_objectives\"])} objectives')
print(f'Controls: {len(cg[\"controls\"])}')
"
Context Available to This Skill
For each control, you have access to:
description— what the control doesmechanism— the AWS enforcement mechanismsecurity_rationale— 2-3 sentence reasoning chain from mitigation goal to enforcementframework_keywords— domain/mechanism keywords for candidate matchingcondition_keys,actions,resource_types— technical detailsmitigation_ids,parameters_controlled— traceability
The security_rationale field is your PRIMARY context. It explains why this control exists
and what security goal it achieves. Use it to reason about framework objective alignment instead
of relying on keyword matching alone.
Phase 1: Map Controls to Framework Objectives
Iterate over EVERY framework_objectives[] entry. For each objective:
1.1 Per-objective analysis (REQUIRED)
CRITICAL — Do NOT batch-map controls to entire domains. Each individual objective MUST be evaluated separately, even when objectives share a domain. The rationale for mapping CTRL-X to IAM-01 must be different from IAM-02, because the objectives ask different things.
Step 1: Read the objective specification. For each framework objective, read its full title AND specification text. Understand what the objective actually requires — not just which domain it's in.
Step 2: Build candidate control list. Use framework_keywords from each control to build
an initial candidate list. Then read each candidate's security_rationale to assess fit.
Step 3: Evaluate each candidate individually. For each candidate control:
- Does this control's specific mechanism directly address what the objective is asking for?
- Read the
security_rationale— does the reasoning chain connect to the objective's requirement? - Write a 1-sentence
rationaleexplaining the SPECIFIC connection.
Rationale quality rules:
- GOOD: "SCP denies CreateMemory without KmsKeyArn, directly enforcing encryption key generation requirements"
- BAD: "Addresses Encryption and Key Management Policy and Procedures" (just restating the objective title)
- BAD: "Addresses Key Generation" (too vague, no mechanism mentioned)
- The rationale MUST mention the control's mechanism (SCP deny, Config rule check, KMS key policy, etc.)
- The rationale MUST NOT be the objective title or a rephrasing of it
Step 4: Assign confidence based on specificity:
- High: The control's mechanism directly implements what the objective requires (e.g., KMS key policy -> CEK-10 "Key Generation")
- Medium: The control contributes to the objective but doesn't fully implement it (e.g., Config CMK check -> CEK-09 "Encryption Audit" — detects but doesn't enforce)
- Low: The control is tangentially related through shared domain only (e.g., tag policy -> IAM-03 "Identity Inventory" — tags support inventory but aren't identity management)
Step 5: If no controls have a specific rationale, mark the objective as:
- N/A with a reason (e.g., "Managed by AWS under shared responsibility", "Organisational HR control", "No backup/DR API for this service")
1.2 Coverage assignment (confidence-coverage consistency)
After mapping controls to an objective, assign coverage using these HARD RULES:
| Highest confidence among mapped controls | Maximum coverage level |
|---|---|
| High | FULL |
| Medium (no High) | PARTIAL |
| Low (no Medium or High) | SUPPORTS |
| No controls | N/A |
FULLrequires at least oneHighconfidence controlPARTIALrequires at least oneMediumconfidence controlSUPPORTSis the maximum for objectives with onlyLowconfidence controls- Never assign
FULLwhen all controls areLowconfidence
Phase 2: Quality Gates (MANDATORY)
All rules below are HARD RULES — violations are validation failures that MUST be fixed before writing output.
Rule 1 — Confidence-coverage consistency
Already enforced in Phase 1 Step 5. Verify with validation script.
Rule 2 — No domain-level spray mapping
If any two consecutive objectives in the same domain have the EXACT same set of control IDs mapped, this is a spray signal requiring review. If three or more consecutive objectives in the same domain share identical control sets, this is a hard validation failure.
Each objective within a domain asks a different question — the control set SHOULD differ. When objectives share controls, each mapping MUST have a distinct rationale referencing the specific objective requirement. Iteration 15 had 13 spray clusters (e.g., AIS-01 through AIS-06 all mapping to the same 2 controls, BCR-01 through BCR-11 all mapping to 1 control).
How to fix: For each spray cluster:
- Read each objective's specification — they ask different things
- For objectives where the controls genuinely apply, write unique rationales
- For objectives where controls DON'T apply, remove the mapping and mark N/A if no other controls fit
- For domains like BCR (backup/DR) where the service has no relevant API, mark most objectives N/A rather than mapping a single weak control to every objective in the domain
Rule 3 — No single control mapped to >15 objectives
If a control appears in more than 15 framework_mapping entries, review every mapping individually. Most controls are specific enough that they should map to 3-8 objectives. >15 indicates keyword spray, not genuine alignment.
How to fix: For each mapping where this control appears:
- Re-read the objective specification
- Re-read the control's
security_rationale - If you cannot write a specific rationale connecting them, REMOVE the mapping
- Prioritize: keep the mapping where the control's mechanism most directly addresses the objective
- Target: each control should map to 3-12 objectives
Rule 4 — Organizational process domains
Framework objectives about organizational processes MUST NOT be mapped to purely technical controls:
- BCR domain (BCR-01 to BCR-11): Cover backup plans, DR exercises, communication plans. Only map to controls that DIRECTLY implement backup, replication, or DR capabilities — NOT generic infrastructure controls. Multi-AZ != backup. Multi-AZ != DR exercise.
- HRS, DCS, UEM, STA domains: Almost always N/A for cloud service technical controls.
- GRC domain: Only map to controls implementing governance automation (Config rules for compliance, tag policies for classification) — not operational controls.
- AIS domain: Application security PROCESSES (design reviews, security testing). Only map controls that enforce secure deployment patterns or automated security checks.
Rule 5 — Rationale required and mechanism-consistent
Every control-to-objective mapping MUST include a rationale string. Additionally:
5a — Rationale-control consistency: The rationale MUST describe the mechanism of the MAPPED control, not a different control. After writing each mapping:
- Look up the mapped
control_idin the controls - Confirm the rationale describes THAT control's specific mechanism
- If the rationale describes a different control's mechanism, fix the rationale or the control_id
- Common error: mapping CTRL-RES-PRV-004 (VPC endpoint policy) but writing a rationale about aws:SecureTransport (which is CTRL-RES-PRV-003)
Rule 6 — Max controls per objective at High confidence
If more than 5 controls map to a single objective at High confidence, review each individually.
Bulk high-confidence mapping indicates overly broad keyword matching.
Rule 7 — Orphaned control review
After building the initial mapping, check for controls not mapped to any objective. For each:
- Read the control's mechanism and
security_rationale - Search framework objectives for alignment by mechanism (not just domain keyword)
- If a genuine match exists, add the mapping with a specific rationale
- Only leave a control orphaned if it truly has no framework objective match
Phase 3: Domain Keyword Guide
Use as a STARTING POINT for candidate controls, then apply per-objective evaluation:
| Keywords in objective | Primary domain | Candidate control types |
|---|---|---|
| Access/Identity/Role/Principal/Auth | IAM | IAM policies, SCPs, permission boundaries |
| Encryption/KMS/CMK/TLS/Certificate | CEK | KMS key policies, encryption configs |
| Network/VPC/Subnet/Endpoint/Firewall | IVS | VPC endpoints, SGs, network policies |
| Logging/CloudTrail/CloudWatch/Audit | LOG | CloudTrail, CloudWatch, logging configs |
| Tagging/Owner/Classification/Governance | GRC | Tag policies, Config rules |
| Config Rule/Compliance | A&A | Config rules, conformance packs |
| Backup/Recovery/Resilience/Multi-AZ | BCR | Only if service has backup/DR API |
| Change/Configuration/Baseline/Drift | CCC | Config rules, Guard rules, drift detection |
| Vulnerability/Patch/Scan | TVM | Vulnerability scanning, patching automation |
| Incident/Forensics/Response | SEF | CloudTrail, alarms, runbooks |
| Data/Privacy/PII/Classification | DSP | Encryption, tagging, data lifecycle |
| AI/ML/Model/Guardrail/Prompt | AIS | Only secure deployment pattern controls |
Phase 4: Write Output
Write .service-approval/<slug>/04-map/map-framework-mapped.json:
{
"schema_version": "1.0",
"framework_mapping": [
{
"objective_id": "IAM-01",
"domain": "Identity & Access Management",
"title": "Identity and Access Management Policy and Procedures",
"status": "MAPPED",
"coverage": "FULL",
"reason": "Multiple preventive and detective controls enforce IAM policies for this service",
"controls": [
{
"control_id": "CTRL-ACC-PRV-001",
"confidence": "High",
"rationale": "Permission boundary restricts service actions to approved set, directly implementing least-privilege access provisioning"
}
]
},
{
"objective_id": "DCS-01",
"domain": "Datacenter Security",
"title": "...",
"status": "N/A",
"coverage": "N/A",
"reason": "Physical datacenter security is managed by AWS under the shared responsibility model",
"controls": []
}
],
"framework_coverage_summary": {
"total_objectives": 197,
"mapped": 137,
"not_applicable": 60,
"by_domain": {
"IAM": { "total": 16, "mapped": 14, "not_applicable": 2, "coverage_percentage": 87.5 },
"CEK": { "total": 21, "mapped": 19, "not_applicable": 2, "coverage_percentage": 90.5 }
}
},
"quality_gate_results": {
"rule_1_confidence_coverage": "PASS",
"rule_2_no_spray": "PASS",
"rule_3_max_15_per_control": "PASS",
"rule_4_org_process_domains": "PASS",
"rule_5_rationale_present": "PASS",
"rule_6_max_5_high_per_objective": "PASS",
"rule_7_orphan_review": "PASS",
"orphaned_controls": []
}
}
Schema rules:
framework_mappingMUST include ALL objectives (mapped + N/A) — every one from map-framework-parsed.json- Each entry MUST have:
objective_id,domain,title,status,coverage,reason,controls statusMUST be EXACTLY"MAPPED"or"N/A"— case-sensitive, no substitutes. Do NOT use"UNMAPPED","NOT_APPLICABLE","n/a", or any other variant. Downstream validators (validate_state.pyCHECK-S13 at line 892;validate_pipeline_integrity.pyat line 263) countstatus == "N/A"verbatim for summary metrics and rationale-completeness checks; other tokens silently bypass those checks.validate_state.pyalso enum-validatesstatusat CHECK-S13 — unknown values now fail fast.controls[]MUST be array of{control_id, confidence, rationale}objectsconfidenceMUST be EXACTLY one of"High","Medium","Low"— PascalCase, case-sensitive. Do NOT emit"high","medium","low"or any other variant; the schema's enum is tightened to PascalCase only (MR-8 review). Every iter-14 through iter-18 archive uses PascalCase exclusively, so this rule documents what the skill has always produced.rationaleis REQUIRED on every control mappingframework_coverage_summaryMUST be populated with per-domain breakdownquality_gate_resultsMUST report PASS/FAIL for each ruleorphaned_controlslists control IDs not mapped to any objective
Framework-Agnostic Design
This skill works with ANY control framework, not just CCMv4. The framework objectives
come from map-framework-parsed.json which is produced by the map-parse-framework
sub-skill. Supported formats:
- CCMv4 (Cloud Controls Matrix v4)
- NIST 800-53 rev5
- CIS Benchmarks
- ISO 27001:2022
- Custom frameworks (any Excel/JSON/Markdown with objective IDs + descriptions)
The mapping logic uses the objective's description and control_specification text
to match against control rationale and description. No framework-specific keywords
are hardcoded — the same confidence scoring works across all frameworks.
Quality cap: No control may map to more than 5 objectives. If a control matches >5, keep only the 5 highest-confidence matches. This prevents spray-mapping where generic controls (like tagging) map to every objective.
Validate Output
Output validation runs automatically via PostToolUse hook. The JSON Schema (see Schema above) hard-fails on status / coverage / control_id drift per the enum details at "Schema rules". validate_state.py::check_framework_mapped retains the 7 quality-gate rules (Rule 1 confidence-coverage consistency, Rule 2 domain spray, Rule 3 ≤15 objectives per control, Rule 5 rationale required, Rule 6 ≤5 High per objective, Rule 7 orphaned controls) plus cross-file lookups against map-controls-generated and map-framework-parsed.
Print Summary
Map (Framework Mapping) complete:
Framework: {name} — {total} objectives
Mapped: {mapped} ({mapped_pct}%)
N/A: {na}
Quality gates: all PASS
Orphaned controls: {count}
Output: .service-approval/<slug>/04-map/map-framework-mapped.json