Following the data through a feature
A data flow review follows personal data from where it comes in to where it ends. It asks where it goes, who sees it, how long it stays and why.
A review catches problems on paper, before a feature ships. It is a way of thinking, and not a certificate that anything is lawful.
By the end of this lesson
Note
I can review a feature's data flow against a checklist.
Key words
| Word | What it means | Example |
|---|---|---|
| Data flow | the path personal data takes through a feature | |
| Checklist | a list of questions each step must answer | |
| Approved place | somewhere you have decided data may go | our database |
| Reader | a person or group who can see the data | |
| Purpose | the reason a step uses the data |
The cells students fill in are left blank in this preview.
A flow is a list of steps
Write each step of the journey as one row. A step has a name, the data it uses, the place it goes to and who can read it there.
It also has the days it is kept, whether it was redacted first and the reason it is used. Five questions turn those rows into a review.
The five checks
| Check | It fails when | Example from the Run |
|---|---|---|
| Sent out unredacted | Data goes to an unapproved place, not redacted | App to model |
| Too many readers | The readers include everyone | Log write |
| No limit | No number of days is set | Log write |
| Kept too long | The days are over your limit | Weekly export, 400 days |
| No purpose | No reason is written down | Weekly export |
The cells students fill in are left blank in this preview.
The review reports each failure
Check each step in order and list every failure it has. One step can fail several checks. A step that fails none adds nothing to the list.
Count the failures by check. Then you can see that, for example, three steps have no limit, and fix them together.
A common mistake
Warning
Many people think a flow that passes the checklist is compliant with the law. It is not. It only shows that five questions have answers. Rules differ by place and by use, so a person with the right skills decides. This lesson is not legal advice.
Write the model helper, part 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const base = process.env.AI_URL || \"http://ai:4000\";' '// The token counts of a reply, or null when the reply carries none.' 'function count(data, name) {' ' return data.usage && typeof data.usage[name] === \"number\" ? data.usage[name] : null;' '}' > model.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the model helper, part 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function ask(messages, sample, max) {' ' try {' ' const res = await fetch(base + \"/v1/chat/completions\", {' ' method: \"POST\",' ' headers: { \"content-type\": \"application/json\", authorization: \"Bearer lab\" },' ' body: JSON.stringify({ model: \"lab\", messages: messages, max_tokens: max || 100 }),' ' signal: AbortSignal.timeout(30000),' ' });' ' if (res.ok === false) throw new Error(\"status \" + res.status);' ' const data = await res.json();' ' const text = data.choices[0].message.content;' ' return { text, inTokens: count(data, \"prompt_tokens\"), outTokens: count(data, \"completion_tokens\"), recorded: false };' ' } catch (error) {' ' console.log(\"Recorded sample: no model answered (\" + error.message + \").\");' ' return { text: sample, inTokens: null, outTokens: null, recorded: true };' ' }' '}' 'module.exports = { ask };' >> model.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the flow reviewer, part 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const { ask } = require(\"./model\");' 'const approved = [\"our app\", \"our database\"];' 'const limit = 90;' 'const flow = [' ' { step: \"Form to app\", data: [\"email\", \"message\"], to: \"our app\", who: [\"support\"], keep: 30, redacted: false, why: \"Answer the customer\" },' ' { step: \"App to model\", data: [\"message\"], to: \"model host\", who: [\"model host\"], keep: 0, redacted: false, why: \"Write a reply\" },' ' { step: \"Log write\", data: [\"email\"], to: \"our database\", who: [\"everyone\"], keep: null, redacted: false, why: \"Debugging\" },' '];' > review.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the flow reviewer, part 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'flow.push({ step: \"Weekly export\", data: [\"email\"], to: \"analytics vendor\", who: [\"analyst\"], keep: 400, redacted: true, why: \"\" });' 'flow.push({ step: \"Cache\", data: [], to: \"our app\", who: [\"support\"], keep: 1, redacted: false, why: \"Speed\" });' 'function check(s) {' ' const out = [];' ' if (s.data.length > 0 && approved.indexOf(s.to) < 0 && s.redacted === false) out.push(\"sent out unredacted\");' ' if (s.who.indexOf(\"everyone\") >= 0) out.push(\"too many readers\");' ' if (s.keep === null) out.push(\"no limit\");' ' else if (s.keep > limit) out.push(\"kept too long\");' ' if (s.why.trim().length === 0) out.push(\"no purpose\");' ' return out;' '}' >> review.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Write the flow reviewer, part 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'async function main() {' ' let failing = 0;' ' flow.forEach(function (s) {' ' const f = check(s);' ' if (f.length > 0) failing = failing + 1;' ' console.log(s.step + \" -> \" + (f.length === 0 ? \"passes\" : f.join(\", \")));' ' });' ' console.log(\"steps that fail: \" + failing + \" of \" + flow.length);' ' const q = \"In one short sentence, why write down the purpose of each step that uses personal data?\";' ' const sample = \"A written purpose shows why the data is used, so a step with no reason stands out.\";' ' const reply = await ask([{ role: \"user\", content: q }], sample, 60);' ' console.log(\"model said: \" + reply.text);' '}' 'main();' >> review.js"Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Run the flow reviewer
docker exec -w /home/node/project agent node review.jsShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
What the Run prints
| Line | What it shows |
|---|---|
| Form to app -> passes | Approved place, a reason and a limit |
| App to model -> sent out unredacted | A message left without redaction |
| Log write -> too many readers, no limit | Two failures in one step |
| Weekly export -> kept too long, no purpose | Two more failures |
| Cache -> passes | No data, and it stays in our app |
| steps that fail: 3 of 5 | The summary |
| model said: ... | A sentence. The words differ each run |
The cells students fill in are left blank in this preview.