Run three proposals through an intake path and reconcile it with the log

applied · 75 min · Objective 4.1

Task

Apply the whole of objective 4.1 to your lab: build a single front door for new AI use, tier three proposals through it, keep the result in a register with conditions and review dates, handle a material change, and then test the path the way the lesson says to test it, by comparing what the register approves with who the gateway log shows actually using the system.

Steps

  1. Write lab/intake.md, the one front door: at least five questions, each on a line starting Q1:, Q2: and so on, covering what data and its highest classification, which model, who uses the output, whether it acts or decides about people, and whether it faces customers.
  2. Create lab/ai-use-register.csv with header id,use_case,owner,users,max_data_class,faces_customers,decides_about_people,tier,status,approved_on,review_by,conditions. users is semicolon-separated; max_data_class is one of your documents' labels; yes/no columns hold yes or no; status is proposed, approved, rejected or retired; dates are YYYY-MM-DD.
  3. Tier with one rule and apply it mechanically: high if the use decides about people or reaches restricted data; otherwise medium if it faces customers or reaches confidential data; otherwise low. Run three proposals: UC-01, your own user asking the retrieval app about non-restricted documents; UC-02, the invented user customer-demo asking product FAQ questions; UC-03, using the app to shortlist job applicants against the salary bands in docs/restricted/. Approve the first two with conditions and a review date; record UC-03 as rejected or proposed for full review, with the reason in conditions.
  4. Write lab/integration-map.csv with header ai_activity,existing_process,owning_function,line, one row each for enterprise risk management, third-party risk, data governance and privacy, change management, security architecture review, incident response and internal audit. line is 1, 2 or 3 from the three lines model; the CoE must not appear at line 3.
  5. Make one material change for real: swap in a different small model, or add a new document source to the index (created as secai-docs, the documents' owner since lesson 17, with the same classification, owner and department front matter as the rest). Add a new register row for the changed use and mark the row it supersedes retired.
  6. Send a few requests to the gateway (POST $GW/ask, HTTPS on 127.0.0.1:8088 since lesson 13, JSON body with user and question) as UC-01's user and as customer-demo, then two as intern-unregistered, a user in no register row. That is planted shadow use.
  7. Run the verify block. Any user in the log other than the planted one is real unregistered use from earlier labs, such as a test identity from the injection labs: register it as its own use and re-run until only the planted user remains.

Verify

cd ~/secai-lab
grep -c '^Q[0-9]*:' lab/intake.md
python - <<'EOF'
import csv, json, datetime
rows = list(csv.DictReader(open("lab/ai-use-register.csv", encoding="utf-8")))
today = datetime.date.today().isoformat()
def tier(r):
    if r["decides_about_people"] == "yes" or r["max_data_class"] == "restricted":
        return "high"
    if r["faces_customers"] == "yes" or r["max_data_class"] == "confidential":
        return "medium"
    return "low"
appr = [r for r in rows if r["status"] == "approved"]
print(len(rows), "register rows,", len(appr), "approved,",
      sum(r["status"] == "retired" for r in rows), "retired")
print("tier disagrees with the rule:", [r["id"] for r in rows if r["tier"] != tier(r)])
print("approved with no conditions or review date:",
      [r["id"] for r in appr if not r["conditions"] or not r["review_by"]])
print("approved past their review date:", [r["id"] for r in appr if r["review_by"] < today])
print("high tier approved:", [r["id"] for r in appr if r["tier"] == "high"])
covered = {u.strip() for r in appr for u in r["users"].split(";")}
seen = {json.loads(l)["user"] for l in open("logs/gateway.jsonl", encoding="utf-8") if l.strip()}
print("users in the log with no approved use:", sorted(seen - covered))
im = list(csv.DictReader(open("lab/integration-map.csv", encoding="utf-8")))
print(len({r["existing_process"] for r in im}), "existing processes mapped")
print("CoE at line 3:", sum("coe" in r["owning_function"].lower() and r["line"] == "3" for r in im))
EOF

Five or more intake questions; at least four register rows with one retired; every tier list, condition list, review list and high-tier list empty; exactly one unapproved user, intern-unregistered; seven or more existing processes; and zero CoE rows at line 3. If the user list is empty, the check has missed your planted traffic: look at how your gateway records user.

Notes

The reconciliation in the last step is the lesson's test of an approval path made literal: the path is judged by the use it did not see. In a real organisation the log would be a web proxy or OAuth consent list rather than your gateway, which lesson 31's applied lab practises. Revert to the snapshot afterwards only if you want the old model back; the register should then gain a row recording that change too.

This is an independent study companion for CompTIA SecAI+ CY0-001 and is not produced by or endorsed by CompTIA.