agentleFS
AWSKnown publisherawslabs/service-onboarding-accelerator-on-aws/skills/map-parse-framework/SKILL.md

map-parse-framework

Skill0 starsChanged 18 days agoApache-2.0View on GitHub

Parse a customer-provided control framework file (xlsx/json/md) into normalized framework_objectives[]. Produces map-framework-parsed.json consumed by map-assemble. Supports CCMv4, NIST 800-53, CIS Benchmarks, ISO 27001.

We split this skill into the rules it gives an agent

13 rules. About 0 are common, 6 are distinctive, and 7 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈6

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 7

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    All frameworks use normal Intake and the mandatory published threat-model gate.

    line 14
  2. Very specific:

    If --framework-file is not provided, scan the input folder for framework files:

    line 39
  3. Very specific:

    If multiple framework files found, ask the user which to use.

    line 47
  4. Very specific:

    If no framework file found and --framework is set, use built-in domain reference.

    line 48
  5. Very specific:

    If inputs.framework_specification is present in 00-intake/intake-manifest.json, read it before parsing.

    line 52
  6. Very specific:

    Use it to interpret non-obvious conventions in the framework file (e.g.

    line 58
  7. Distinctive:

    If framework is CCMv4 but no xlsx is parseable, use this built-in domain reference:

    line 131
  8. Distinctive:

    When using built-in fallback, each objective gets:

    line 155
  9. Distinctive:

    Rule: If the customer provides a file with a recognizable framework name in its content (headers, sheet names, or first-row data), prefer …

    line 185
  10. Very specific:

    Rule: If the file cannot be classified into any known framework, set framework.name = "Custom Framework".

    line 190
  11. Very specific:

    Every objective MUST have: id, domain, title, specification, keywords

    line 219
  12. Distinctive:

    Run this only when the active framework is NOT CCMv4 (the script no-ops for CCMv4 and skips cleanly if the parsed file is absent):

    line 233
  13. Distinctive:

    Use borrowed guidance only when its meaning and scope fit the original objective.

    line 251

≈ “Common” is an estimate: at least 1 in 5 of the 308,232 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Service Approval — Map: Parse Framework

Parse a customer-provided control framework file into a normalized array of framework objectives. This is the smallest, most deterministic sub-skill in the map pipeline.

An explicit customer framework file takes precedence over the default framework. All frameworks use normal Intake and the mandatory published threat-model gate. Custom frameworks are evaluated directly against source-backed controls. The optional CCM guidance lookup below does not determine mapping status.

Input: Framework file (xlsx/json/md) or built-in CCMv4 reference Output: .service-approval/<slug>/04-map/map-framework-parsed.json

This is one of 4 focused map sub-skills. Each writes to a separate intermediate state file.


Prerequisites

mkdir -p .service-approval/<slug>/04-map

Inputs

Parse arguments:

  • --framework=<type> — framework identifier (default: auto-detect from file)
  • --framework-file=<path> — explicit path to framework file (overrides auto-detection)

Auto-detect framework file

If --framework-file is not provided, scan the input folder for framework files:

  • .xlsx files containing "CCMv4", "ccmv4", "CSA", "cloud controls matrix" in filename -> CCMv4
  • .xlsx files containing "NIST", "800-53" in filename -> NIST 800-53
  • .xlsx files containing "CIS" in filename -> CIS Benchmarks
  • .xlsx files containing "ISO", "27001" in filename -> ISO 27001
  • .json files with top-level framework or controls key -> parse and detect
  • .md files with framework headers -> parse and detect

If multiple framework files found, ask the user which to use. If no framework file found and --framework is set, use built-in domain reference.

Customer framework specification (optional)

If inputs.framework_specification is present in 00-intake/intake-manifest.json, read it before parsing. It is free-text guidance from the customer (supplied inline via --framework-specification or at the intake prompt) about how their controls are structured — for example how control IDs and sub-control IDs are formatted, which column holds the control text, or how requirements are grouped.

Use it to interpret non-obvious conventions in the framework file (e.g. to recognize a sub-control column, or to split a combined ID like AIS-01.2 into a parent control and a sub-control). It is advisory only: never let it override what the file actually contains, and never fail if it is absent or null.


Step 1: Parse Framework File

For .xlsx files (e.g., CCMv4-sample.xlsx):

python3 -c "
import openpyxl, json, sys
wb = openpyxl.load_workbook(sys.argv[1], read_only=True, data_only=True)
for sheet in wb.sheetnames:
    ws = wb[sheet]
    rows = list(ws.iter_rows(values_only=True))
    if rows:
        headers = [str(h).strip() if h else '' for h in rows[0]]
        print(f'Sheet: {sheet}, Columns: {headers}')
        for row in rows[1:6]:
            print([str(c)[:80] if c else '' for c in row])
" "<framework-file>"

Adapt column mapping based on detected framework:

  • CCMv4: Control ID, Control Domain, Control Title, Control Specification
  • NIST 800-53: Control Identifier, Control Family, Control Name, Control Description
  • CIS: Recommendation #, Section, Title, Description, Level
  • ISO 27001: Clause, Control, Objective, Implementation Guidance

For .json files:

import json
data = json.load(open("<framework-file>"))
# Detect structure and extract objectives

For .md files:

Parse markdown headers and tables to extract framework objectives.


Step 2: Build Normalized framework_objectives[]

Regardless of source format, produce a normalized array where every objective has:

{
  "id": "IAM-01",
  "domain": "Identity & Access Management",
  "title": "Identity and Access Management Policy and Procedures",
  "specification": "Establish, document, approve, communicate, apply, evaluate...",
  "keywords": ["access", "identity", "authentication", "policy"]
}

Keyword extraction rules

Extract keywords from the specification text to aid downstream matching:

  • Domain-specific terms (access, encryption, network, logging, etc.)
  • Action verbs (restrict, monitor, audit, enforce, validate, protect)
  • AWS-relevant terms (key management, multi-factor, least privilege, classification)
  • De-duplicate and lowercase
  • Max 10 keywords per objective — pick the most specific, not generic

Step 3: CCMv4 Built-in Fallback

If framework is CCMv4 but no xlsx is parseable, use this built-in domain reference:

PrefixDomain NameRange
AISApplication & Interface SecurityAIS-01 to AIS-07
A&AAudit & AssuranceA&A-01 to A&A-06
BCRBusiness Continuity Management & Operational ResilienceBCR-01 to BCR-11
CCCChange Control & Configuration ManagementCCC-01 to CCC-09
CEKCryptography, Encryption & Key ManagementCEK-01 to CEK-21
DCSDatacenter SecurityDCS-01 to DCS-15
DSPData Security & Privacy Lifecycle ManagementDSP-01 to DSP-19
GRCGovernance, Risk & ComplianceGRC-01 to GRC-08
HRSHuman ResourcesHRS-01 to HRS-13
IAMIdentity & Access ManagementIAM-01 to IAM-16
IPYInteroperability & PortabilityIPY-01 to IPY-04
IVSInfrastructure & Virtualization SecurityIVS-01 to IVS-09
LOGLogging & MonitoringLOG-01 to LOG-13
SEFSecurity Incident Management & ForensicsSEF-01 to SEF-08
STASupply Chain Management & AccountabilitySTA-01 to STA-14
TVMThreat & Vulnerability ManagementTVM-01 to TVM-10
UEMUniversal Endpoint ManagementUEM-01 to UEM-14

NEVER invent control IDs outside these ranges.

When using built-in fallback, each objective gets:

  • id: from the range (e.g., "IAM-01")
  • domain: from the table above
  • title: domain-level title (enriched if xlsx provided partial data)
  • specification: domain-level specification (may be minimal if no xlsx)
  • keywords: derived from domain name

Step 4: Write Output

Framework Name Rules (CRITICAL for output titles)

The framework.name field flows into ALL downstream output titles (e.g., "CSA CCMv4 Control Mapping — {service}", "NIST 800-53 Coverage Matrix", "Threat Model Coverage for MITRE ATT&CK"). Set it using these rules:

Sourceframework.name valueExample output title
Built-in CCMv4 fallback (no file provided)"CSA CCMv4""CSA CCMv4 Control Mapping — Amazon S3"
Customer xlsx with "CCMv4" in filename"CSA CCMv4""CSA CCMv4 Control Mapping — Amazon ECS"
Customer xlsx with "NIST" or "800-53" in filename"NIST 800-53""NIST 800-53 Control Mapping — AWS KMS"
Customer xlsx with "CIS" in filename"CIS Benchmarks""CIS Benchmarks Control Mapping — Amazon RDS"
Customer xlsx with "ISO" or "27001" in filename"ISO 27001""ISO 27001 Control Mapping — Amazon EKS"
Customer file that doesn't match any known pattern"Custom Framework""Custom Framework Control Mapping — Amazon Lambda"
--framework=ccmv4 flag (no file)"CSA CCMv4""CSA CCMv4 Control Mapping — ..."
--framework=nist flag (no file)"NIST 800-53""NIST 800-53 Control Mapping — ..."
--framework=cis flag (no file)"CIS Benchmarks""CIS Benchmarks Control Mapping — ..."
--framework=iso flag (no file)"ISO 27001""ISO 27001 Control Mapping — ..."

Rule: If the customer provides a file with a recognizable framework name in its content (headers, sheet names, or first-row data), prefer that over filename-based detection. For example, a file named security-controls.xlsx whose first column header is "NIST Control ID" should produce framework.name = "NIST 800-53".

Rule: If the file cannot be classified into any known framework, set framework.name = "Custom Framework". Never leave it empty or null.

Write .service-approval/<slug>/04-map/map-framework-parsed.json:

{
  "schema_version": "1.0",
  "framework": {
    "name": "CSA CCMv4",
    "version": "4.0",
    "source_file": "<path or 'built-in'>",
    "total_objectives": 197
  },
  "framework_objectives": [
    {
      "id": "A&A-01",
      "domain": "Audit & Assurance",
      "title": "Audit and Assurance Policy and Procedures",
      "specification": "...",
      "keywords": ["audit", "assurance", "policy", "compliance"]
    }
  ]
}

Schema rules:

  • framework MUST be an object with keys: name, version, source_file, total_objectives
  • framework_objectives MUST be a non-empty array
  • Every objective MUST have: id, domain, title, specification, keywords
  • total_objectives MUST equal len(framework_objectives)
  • Objectives MUST be sorted by id (alphabetical)

Step 5: Find optional CCMv4 guidance for a custom framework

The per-domain mapping guidance (allow/deny classes, coverage ceilings, applicability) lives in data/domain-mapping-guidance/ccmv4.json and is keyed by CCMv4 objective ids. For a custom framework, find potentially useful guidance by description, while retaining the customer's original requirements. AWS Threat Models remain the primary control evidence; CCM similarity is only a lookup aid.

Run this only when the active framework is NOT CCMv4 (the script no-ops for CCMv4 and skips cleanly if the parsed file is absent):

python3 scripts/anchor-custom-framework.py --slug <slug>

It writes .service-approval/<slug>/04-map/custom_to_ccmv4_anchor.json mapping each custom objective id to {ccmv4_ids[], anchor_score, status} via a deterministic TF-IDF cosine over each objective's title+specification against every CCMv4 objective's title+intent — no LLM, so it is reproducible. A lookup objective whose best match scores at or above the threshold (default 0.7) is anchored; below it is uncertain.

The legacy anchored / uncertain labels in this file describe the guidance lookup only. The mapper MUST evaluate each custom objective directly against the control mechanism and its pinned AWS Threat Model citation. A weak lookup does not force UNCERTAIN or N/A, and a strong lookup does not justify MAPPED. Use borrowed guidance only when its meaning and scope fit the original objective.


Validate Output

Output validation runs automatically via PostToolUse hook (validate_state.py Check S10).

Print Summary

Map (Parse Framework) complete:
  Framework: {name} v{version}
  Source: {source_file}
  Objectives: {total_objectives}
  Domains: {count unique domains}
  Output: .service-approval/<slug>/04-map/map-framework-parsed.json

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

Reviews can't be read right now.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.