Lesson map
Lesson 08 published. Map, example, EX022.
flowchart TD
N0["Learning outcomes"]
N1["8.1 Modules"]
N2["8.2 Validate on write"]
N3["8.3 API versioning"]
N4["8.4 Partial updates"]
N5["8.5 Bulk import"]
N6["8.6 Concurrency"]
N7["8.7 Applied note"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
N7 --> EX["Worked example"]
EX --> Q["Exercise EX022"]
Logical drawing
flowchart LR
N0["Learning outcomes"]
N1["8.1 Modules"]
N2["8.2 Validate on write"]
N3["8.3 API versioning"]
N4["8.4 Partial updates"]
N5["8.5 Bulk import"]
N6["8.6 Concurrency"]
N7["8.7 Applied note"]
N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX022"]
[Learning outcomes]
|
v
[8.1 Modules]
|
v
[8.2 Validate on write]
|
v
[8.3 API versioning]
|
v
[8.4 Partial updates]
|
v
[8.5 Bulk import]
|
v
[8.6 Concurrency]
|
v
[8.7 Applied note]
|
v
[Worked example] --> [Exercise EX022]
Learning outcomes
You will (1) structure modules for the platform; (2) validate inputs; (3) version APIs carefully.
8.1 Modules
Scope loader, finder schema, report exporter — each with tests and a README. Splitting the platform this way lets each part fail and be tested on its own. The scope loader's tests feed it the synthetic /26 with SWIFT at .20 and check that the exclusion survives every input format. The findings schema's tests reject records without required fields. The exporter's tests compare generated reports with saved expected files. Each README states what the module does, what it refuses to do and who reviews changes to it.
8.2 Validate on write
FindingsDesk rejects tickets missing owner or evidence hash. Rejecting incomplete tickets at the moment of writing is cheaper than chasing them later. A finding without an owner has nobody to fix it, and a finding without an evidence hash cannot be checked against the file it claims to describe. Sam's validation returns a message naming the missing field, so an analyst can correct the ticket immediately instead of guessing why it failed. FindingsDesk applies the same required-field rule to bulk imports and API calls, so neither route can create a finding without an owner.
8.3 API versioning
PulseMap v2 adds fields without breaking v1 consumers. Existing consumers of PulseMap, such as the monthly board export, read v1 fields and must keep working when new fields such as technique IDs per method card appear. Adding fields is safe; renaming or removing them is a breaking change that needs a new version and a migration period. Sam's contract tests run the v1 consumer against the v2 server on every build, so an accidental break fails CI rather than the next board pack.
8.4 Partial updates
PATCH must not clear required fields accidentally. A client that sends only a changed severity must not wipe the owner or evidence hash by omission. FindingsDesk treats PATCH as 'change these fields only' and re-runs validation on the merged record, so a partial update cannot produce a ticket that would have been rejected on creation. Sam's tests send PATCH requests with one field at a time and confirm every other required field survives unchanged. The same rule protects the evidence hash during bulk edits.
8.5 Bulk import
CSV import of findings dry-runs first and caps row counts. A dry run shows what the import would create, update or reject, including any host outside the TRB scope, before anything is written. The row cap limits the damage a wrong file can do, and the next applied note shows why both limits exist. Only after an analyst reviews the dry-run summary does the real import run, and the summary is attached to the import record. The dry-run summary lists each rejected row with its reason, such as a host outside the TRB scope, so the analyst can fix the file.
8.6 Concurrency
Optimistic locking prevents two analysts overwriting the same ticket silently. Each ticket carries a version number. When an analyst saves, FindingsDesk checks that the version has not changed since the ticket was opened; if a colleague saved first, the second save is refused and the analyst sees both versions. Without this, one analyst's severity change could silently erase another's new evidence, and nobody would know which view of the finding was current. The refused analyst merges the two versions by hand, and the merge is logged.
8.7 Applied note
Bulk import caps at 500 rows and requires a second approver above 100. Sam saw an analyst almost import a scanner dump that included out-of-scope hosts as "informational". Caps and approvers are boring on purpose. An 'informational' out-of-scope host is still evidence that someone tested outside the ROE, so it needs review, not quiet storage. The second approver checks the dry-run summary against the signed scope before larger imports proceed. The approver is never the person who ran the scan, so the check is independent.
8.8 Migration drills
Schema migrations run on a copy with checksums before and after. Sam records row counts. A migration that changes counts silently fails the drill. Checksums and row counts on the copy show whether a migration preserved every finding and evidence reference. If counts differ, the migration is fixed and rerun on a fresh copy; production is never used as the test. Sam keeps the before and after figures with the migration script so a reviewer can confirm the drill passed.
8.9 Idempotent writes
Ticket updates are idempotent by finding id. Double delivery from flaky networks cannot create duplicate F1s. Because each update is keyed by finding ID, applying the same request twice leaves the ticket in the same state as applying it once. This matters at TRB, where VPN links to the assessment zone drop often, and duplicate findings would inflate counts in board reports.
Idempotent ticket updates saved TRB when a flaky VPN resubmitted the same finding create call twelve times. FindingsDesk showed one F1, not twelve. Sam adds that story to onboarding so engineers stop fearing "exactly-once" as academic. Twelve duplicate F1 tickets would have shown twelve open critical findings to the board and paged the owner twelve times. Idempotency made the network failure harmless, which is exactly what engineers need to see before they trust the design. New engineers now test retries in their first week.
8.10 Bulk-import dry run
FindingsDesk's bulk import dry-run once revealed 40 hosts outside the ROE embedded in a scanner CSV. The import blocked. Sam thanks the dry-run in the retrospective more than any new feature shipped that month. Forty out-of-scope hosts in an assessment database would have looked like authorized test results and could have prompted follow-up work against systems nobody had approved. The dry-run turned a silent data problem into a visible decision, and the scanner configuration that produced the CSV was corrected before the next window.
8.11 Approval threshold at 100 rows
FindingsDesk's approval threshold at 100 rows exists because a 2,000-row dump once queued overnight and page-stormed owners. Sam documents the incident id beside the constant in code. Linking the constant to the incident record tells future engineers why the threshold exists before they decide to raise it. Without the comment, 100 looks arbitrary and invites removal. With it, anyone changing the value can read what happened when large imports ran unreviewed and paged owners all night. The comment names ENG-441 and the date of the change.
The incident id is ENG-441 in the course archive. The archive entry describes the overnight queue, how many owners were paged and the change that introduced the approval threshold. A reviewer who finds the constant can follow the link and judge the history directly. The same practice applies to the 500-row cap: every safety limit in FindingsDesk points to the reason it was set, so limits are changed deliberately rather than by someone tidying the code.
Worked example (synthetic TRB)
Sam adds a FindingsDesk check: empty emergency_contact in ROE metadata blocks engagement start.
Synthetic case — Riverstone Transit Bank (TRB). The bank, Sam Ito, TrackScope/FindingsDesk/PulseMap and all figures are invented for teaching.
Errors and limits
This book grants no authority to test real banks or payment systems. Labs use documentation-range addresses and synthetic data only; exploit code is never provided.
Exercises
- EX022 — Reject rule. Name two fields that should block ticket creation if empty.
Show marking criteria
Rubric: 3 = two of owner, evidence hash, severity; 2 = one; 1 = title colour; 0 = none. - EX023 — Dry-run import. Why dry-run bulk import?
Show marking criteria
Rubric: 3 = catch schema errors before write; 2 = partial; 1 = no need; 0 = none. - EX024 — Optimistic lock. What problem does optimistic locking prevent?
Show marking criteria
Rubric: 3 = silent overwrite of concurrent edits; 2 = partial; 1 = slow UI; 0 = none.
Synthesis
Platform code validates, versions and refuses to start unsafe engagements.
Continue studying — chapter 08 of 40
← Chapter 07 (draft) · Course chapter index · Chapter 09 (draft) →