Not recorded yet. The lesson below is complete and runnable today — the video is added later without touching this page.
recordings/B1.19.mp4A team that has just shipped agents writes an agentic control list. Every row is right, and it reports coverage against the wrong denominator — saying nothing about the older, more reachable controls an attacker will actually start from.
One index carrying both eras, a three-valued status measured against what runs rather than what is documented, an owner per row, and coverage reported per era rather than blended.
Score the twenty-two controls and read the two coverage lines separately — the gap between them is the finding.
The agentic control list a team writes the week after shipping agents is correct, complete about the wrong thing, and reassuring. It scores ten new controls and says nothing about the twelve that were required before any of this existed — which are older, more reachable, and where an attacker will actually start.
What it covers. The full control index for CyberTravels: the twelve controls that were required before agents existed, the ten the agents added, what each is scored at today, and the lesson that owns it.
Why a security engineer needs it. A control list written the week after shipping agents covers the new rows and reports coverage against the wrong denominator. Vulnerability scanning, supply chain, environment segregation, encryption at rest and in transit, input validation, change management, DMZ termination, credentials, PKI, key lifecycle and logging did not stop applying — several of them are what the agents broke. The control it builds is: one index with an era column, a three-valued status measured against what runs, an owner per row, and coverage reported per era rather than blended.
This is an index lesson. It is the reference you come back to, and the place a programme gets sequenced from.
A control list written after shipping agents covers the new rows and reports a number about the wrong denominator — while the older, more reachable controls an attacker actually starts from go uncounted.
Index both eras in one table: the twelve controls that predate agents and the ten that arrived with them, each scored in place, partial or absent against what runs, with an owner per row.
Coverage per era, never blended. CyberTravels scores 50% on the foundation and 10% on the agentic layer across 22 controls, and two of the absent rows were required before it shipped an agent.
Measure this
| what to measure | denominator or target |
|---|---|
| control coverage per era | share per era, never blended — CyberTravels scores 50% on the foundation and 10% on the agentic layer across 22 controls |
TWO ERAS, ONE INDEX
+--------------------------------------------------------------+
| AGENTIC workload identity . delegated authority . JIT |
| (10 rows) provenance . default-deny . sandbox . egress |
| budgets . agent telemetry . human oversight |
+--------------------------------------------------------------+
| FOUNDATION vuln mgmt . supply chain . prod/non-prod |
| (12 rows) crypto at rest . crypto in transit . input val |
| SDLC + change . DMZ . creds . PKI . KMS . logs |
+--------------------------------------------------------------+
the list most teams write -> the top box only
the exposure they actually have -> both boxes
where an attacker starts -> the bottom box
status is three-valued, because pass/fail rounds up:
in place | partial | absent
and coverage is reported PER ERA. one blended number hides the
gap the index exists to surface.B1.18 registered the twelve risks the agents brought. This lesson is the other index, and it is the one that gets skipped: every control CyberTravels needs, including the dozen that were required before it shipped a single agent.
The failure this prevents is specific and common. A team that has just built an agentic platform writes an agentic control list — provenance, default-deny, sandboxing, egress, budgets, telemetry. Every row on it is right. The list reports coverage of the ten controls somebody thought of last quarter and says nothing about the twelve that were true in 2015, and those are where an attacker starts, because they are older, more reachable and much better understood than anything involving a model.
So the index carries both, in one table, with a column that says which era each control belongs to:
The foundation — true before agents, and still true. Vulnerability scanning. Supply chain and SBOM. Production and non-production segregation. Encryption at rest. Encryption in transit. Input validation. SDLC and change management. Termination of externally initiated connectivity in a DMZ. Credential management. PKI. KMS key lifecycle. Logging and monitoring.
The agentic layer — new, and sitting on top of it. Workload identity per agent. Delegated authority that narrows. Just-in-time authorisation. Provenance at ingress. Default-deny on the tool call. Sandboxed execution. Egress control. Budgets and stop conditions. Agent telemetry. Human oversight that survives volume.
This is the part worth reading slowly. Agents did not make change management obsolete; they broke the assumption underneath it, which was that a human read every change. They did not replace credential management; they made one shared service account span four agents, so a rotation breaks all four and an incident cannot be attributed to one. They did not remove the DMZ; they made egress the direction that matters, because an agent with tool access initiates outbound calls the perimeter was never shaped for.
Every foundation row in the index carries a line saying what the agents changed about it. A row with an empty line is a row nobody has thought about yet.
Each row is in place, partial or absent, against what is running rather than what is documented. Three values rather than two, because with a pass/fail scheme almost everything gets rounded up to pass, and partial is the honest answer for most controls in most estates.
And coverage is reported per era, never blended. One overall number hides exactly the gap the index exists to surface.
Four columns make this an index rather than a poster: the control, the era, the status, and the lesson that owns it. The fourth is the one that decides whether anything changes.
A status with no owner regresses silently between measurements — somebody records partial, nobody is accountable for the other half, and the next measurement finds the same word. In this commons the owner is a lesson id, so every row in the index is a thing you can go and read. In your organisation it is a team, and the rule is the same: a row with no owner will be absent again next quarter.
Watch the two coverage lines rather than the overall one. The gap between them is the finding, and the last block is the sentence to take to whoever funds this: the foundation rows that are absent are ordinary controls that were already required, and they are listed by id.
The skill — skills/architecture/control-baseline-index/SKILL.md
name: control-baseline-index
description: >-
Index every control an agentic platform needs — the ordinary ones that predate
agents and the agentic ones that do not — score each as in place, partial or
absent, and name the lesson that owns it. Use when asked what controls an AI
or agent platform needs, to build or review a control baseline, to check
whether a security programme is only covering the AI-specific rows, or when
coverage is being reported against a list that was never complete.
allowed-tools: Read, Grep, Glob, BashControls: Cross-cutting — control baseline and coverage
A team that has just shipped agents writes an agentic control list: provenance, default-deny, sandboxing, egress, budgets. Every row on it is correct, and the list is a trap. It reports coverage of the ten controls somebody thought of last quarter and says nothing about the dozen that were required before any of this existed — and those are where an attacker starts, because they are older, more reachable and better understood.
The fix is one index with both eras in it and a status per row. The era column is what makes the point arguable: when foundation coverage and agentic coverage are printed side by side, "we are doing AI security" stops being a defensible summary of an estate that shares one service account across four agents.
Building a control baseline for a system that has agents in it, reviewing one somebody else built, or auditing a coverage claim that sounds higher than the estate feels. Also when a programme has to be sequenced: the absent foundation rows almost always come first.
1 — List the controls that were always required. Vulnerability management, supply chain, environment segregation, encryption at rest and in transit, input validation, SDLC and change management, perimeter and DMZ termination, credential management, PKI, key lifecycle, logging and monitoring. Write them before you write a single agentic row, so the list is not shaped by what is currently interesting.
2 — Add what the agents introduced. Workload identity, delegated authority that narrows, just-in-time authorisation, provenance at ingress, default-deny on the tool call, sandboxed execution, egress control, budgets and stop conditions, agent telemetry, and human oversight that survives volume.
3 — Mark each row with what the agents changed about it. Most foundation rows are not replaced; they are stressed. Change management did not stop applying when a model started authoring changes — it started failing on volume. A row whose note is empty is a row you have not thought about yet.
4 — Score each row in place, partial or absent against what is actually running, not what is documented. Partial is the honest answer for most, and a scoring scheme with only two values pushes teams to round up.
5 — Name the owning control for each row — the team, and here the lesson. A row with no owner is a row that will be absent again next quarter.
6 — Report coverage per era, never blended. One overall number hides exactly the gap this index exists to surface.
Input — the index committed at the top of scripts/control_baseline_index.py. Edit the rows and re-run: every count, percentage and verdict below is derived from them, not hard-coded.
Output — the tail of a real run:
coverage by era
------------------------------------------------------------------------------
foundation ##########.......... 50% 2 in place, 8 partial, 2 absent (n=12)
agentic ##.................. 10% 0 in place, 2 partial, 8 absent (n=10)
overall ######.............. 32% (n=22)
The run continues past this with every absent row, what it needs, and what the agents changed about it. test_skills.py executes the script on every build, with no model configured — so what CI proves is that it runs and refuses legibly, not that it prints these lines. The output above is a recorded run against a real model, and nothing re-diffs it: a model's answer is not reproducible, and this repository does not claim otherwise anywhere it can be checked.
{
"index": [{"id": "str", "domain": "str", "control": "str", "era": "str",
"status": "str", "agent_note": "str", "owns": "str"}],
"coverage": [{"era": "str", "score": 0.0, "in_place": 0, "partial": 0,
"absent": 0, "n": 0}],
"absent": ["str"]
}
Three ways to do this lesson. Pick one. They run the same procedure against the same code — what changes is who drives it, and how much you see.
The agent reads the lesson, explains the idea, fetches the code, runs the check and answers your questions as you go. This is the one to take if you are here to learn.
Install it, once. From the folder you cloned. --all does every agent it finds on your machine:
python3 scripts/install_skills.py --all --lessons B1.19Then restart your agent and open it in that folder. On Windows, if python3 says Python was not found, use python instead.
Then pick b1-19-the-control-index:
| agent | install just for this agent | start it |
|---|---|---|
| Claude Code | python3 scripts/install_skills.py --tool claude --lessons B1.19 | type /b1-19-the-control-index |
| GitHub Copilot (VS Code) | python3 scripts/install_skills.py --tool copilot --lessons B1.19 | type /b1-19-the-control-index in Chat |
| Cursor | python3 scripts/install_skills.py --tool cursor --lessons B1.19 | type / in Agent chat and search for it |
| Codex | python3 scripts/install_skills.py --tool agents --lessons B1.19 | type $b1-19-the-control-index, or run /skills |
No agent, no conversation. The same lesson executes and prints the same readback. Take this one if you have no assistant, if you are reviewing rather than learning, or if you want the result without the teaching around it.
python3 scripts/lesson.py B1.19Neither of the above, and no model needed. The first command writes CyberTravels exactly as it stood at the end of this lesson; the second prints the diff — the lines this lesson added or changed, and nothing from any later one.
python3 scripts/checkpoint.py --at B1.19 --out work/cybertravels
python3 scripts/checkpoint.py --at B1.19 --diffOn Windows, type python wherever these say python3 — and use \ instead of / in the paths. Everything else is identical. A0.0 step 2 explains why.
Ways 1 and 2 need a model; way 3 does not. A signed-in Claude Code CLI needs no API key, and any OpenAI-compatible endpoint works too. With neither, the audit exits 2 and says so rather than inventing an answer. A0.0 sets this up.
Ways 1 and 2 both end with the same readback: What I did, What changed, The number and Read this next. A step that was skipped or refused is reported as exactly that, never as a pass.
If you did the last lesson’s challenge, expect this to stop. Most challenges ask you to edit the code, and ways 1 and 2 will not overwrite your edits: you get stopped, not a failure, with two options — --out for a fresh folder that keeps your work, or --force to discard it and start this lesson clean.
Twenty-two controls indexed — twelve that predate agents and ten that arrived with them — each with its era, its status and the lesson that owns it. Then coverage scored separately per era, which is where the point lands: the foundation is half-covered and the agentic layer is barely started, and two of the absent rows are ordinary controls that were required before CyberTravels shipped anything. An index of only the agentic rows would have reported a number about the wrong denominator.
Write the same table for one system you run, foundation rows first and before you write a single agentic row — the order matters, because a list started from what is currently interesting inherits that shape. Then score it against what is running rather than what is documented. If your foundation coverage is below your agentic coverage, you have found the sequencing problem this lesson exists for.
What you can do now. You can draw an agentic system as named components, say which of the five patterns it is, and place any of fifteen risks on the component it attacks. That is the vocabulary the rest of the commons runs on.
What you still cannot do. Not one of those fifteen lessons fixed anything. You can now describe precisely how a system fails and you have no control to point at — which is deliberate, because a control chosen before the risk is named is a control chosen by whoever sold it to you.
Chapter B2 starts closing them, and it starts with the two that close the most: knowing who is calling, and marking what came in from outside. Next → B2.1, agent identity.
Skill source: skills/architecture/control-baseline-index