Week 2, day 2. Work through the teaching and the worked checkpoint before attempting the assigned exercise(s). Compare your artifact with the final worked result only afterward.
2.3 Preserve what supports the next decision
NIST SP 800-86 provides guidance on incorporating forensic techniques into incident response, including work with different data sources. Its publication page expressly frames the guidance as an IT investigation aid and calls for management and legal consultation on applicable requirements. This rapid course therefore teaches a minimal reproducibility record, not a certified forensic collection method or a legal chain of custody.
For each synthetic record that matters, note the source system, the exact time range and timezone, the person who exported or copied it, the permission used, the collection time, where the original remains, where the working copy is stored and how access to it is limited. Record transformations: an export may sort rows, normalize timestamps or omit fields. Preserve the unmodified export when authorized, and analyze a separate working copy. If a source is volatile or automatically deleted soon, tell the incident lead so the collection decision can be prioritized.
An integrity hash can detect whether a particular byte sequence changes between two checks. For example, a team can calculate SHA-256 over a copied file at collection and again before review. A matching value supports that the checked copy has not changed between those checks, assuming the method and record are trustworthy. It does not prove the source log was complete, that its clock was correct, that the exporter had permission, or that the events actually happened. A hash of a screenshot says nothing about omitted rows. Explain these limits in the case note.
Lesson table; scroll horizontally to read all columns →
| Collection-note field | Example for a synthetic classroom export |
|---|---|
| Case and item | HL-IR-001, item E1 |
| Source and range | Proposed booking-audit event-time selection, 08:30–09:15 UTC; producer, filter and available rows remain to be confirmed |
| Collector and authority | Analyst; fictional incident lead's classroom authorization |
| Collected at | Not performed in this illustrative card; R9–R16 reach the learner only at 09:20. Record the actual later local time if a teaching copy is created |
| Method | Planned only: transcribe permitted synthetic rows as UTF-8 after release in an authorized scratch directory; this is not a production export |
| Copy and access | Planned local training copy E1.txt in an authorized scratch directory; learner only if created |
| Integrity note | SHA-256 of the exact saved bytes, recorded before and after analysis if a file is created |
| Transformation and limitation | No production source; table is invented, and export formatting can change bytes |
This table is a model for an exercise note. A real organization needs its approved preservation, retention, privacy and evidence-transfer procedures. Never collect broader data merely to make a training exercise look realistic.
Prioritize a preservation request before copying
NIST SP 800-61 Rev. 3, RS.AN-06 and RS.AN-07 addresses the provenance, integrity and restricted access of response records, and the collection and retention of incident data under an organization's procedures. The preservation queue below is OpenCyber Academy's classroom method for deciding what to request next; it is not a NIST form or a substitute for an organization's policy. The question is not “Which source contains the most data?” It is “Which authorized, minimal observation could change the next decision, and which opportunity to obtain it may be lost?”
Write a separate card for each candidate source. Name the decision it could change, the smallest relevant field and interval, its custodian, the known or unknown loss path, the approval needed, the expected handoff artifact and the claim that would remain unproved even after collection. This reuses Module 1's proposed evidence-readiness contract, but now the case has a live decision point. A source that may expire soon deserves immediate contact even if the cause is uncertain; a source with no confirmed loss clock may still need a parallel availability check. Do not convert the words “high priority” into an unverified deadline. Conversely, an indefinitely retained document is not automatically less important to the hypothesis: it may simply permit a later request after the fragile source is safeguarded.
For a copy request, distinguish four states: proposed, a bounded request has been written; approved, an accountable owner has authorized its stated scope; collected, a specified copy has actually been acquired with an acquisition receipt; and verified, a reviewer has performed and recorded specified checks on that item. State what was verified: bytes, selection, provenance or another named property, not “everything.” Protecting records in place does not itself move a copy request to collected. A source-hold request follows a separate control lifecycle, including reported application and a bounded effect check where such a mechanism exists. Neither lifecycle substitutes for the other. Record each actual state change, actor, time and source pointer; leave missing receipts pending. This is the book's teaching model, not a required NIST form. The relevant NIST principles concern recording investigative actions and preserving the integrity and provenance of incident information under organizational procedures; see SP 800-61 Rev. 3, RS.AN-06 and RS.AN-07.
When two requests compete for attention, compare them without inventing a numerical risk score:
Lesson table; scroll horizontally to read all columns →
| Question | What to record | Failure of a shallow answer |
|---|---|---|
| Decision value | Which current choice could change, and what observation would discriminate? | “Useful someday” gives no reason to expose unrelated data now. |
| Loss and delay | What policy, observed failure or owner statement supports the loss concern? Is the policy anchor known? | Adding a stated retention period to an event timestamp may fabricate a deadline. |
| Authority and feasibility | Who can approve, who can retrieve, which selection is feasible, and what if the custodian cannot act? | An analyst's urgency does not grant permission or prove that a source is accessible. |
| Exposure and fidelity | Which people and fields are included, what filters or transformations are applied, and how will an unmodified authorized copy be distinguished from a working view? | A broad export increases exposure; a narrow, undocumented filter can hide relevant rows. |
The first contact may be the incident lead to obtain approval, the source custodian to establish a retention anchor, or both through an approved escalation path. Several requests can proceed in parallel; the queue ranks decision and loss concerns, not a fixed order of technical commands. Keep the case record and the protected evidence store separate. A case note may point to an item and its access owner without copying sensitive raw records into a widely read ticket. Record the retention rule for the collected copy separately from the source's own deletion rule. If an expected source is unavailable, record who confirmed that, which interval or field is missing and how the next decision must be narrowed. Do not fill the gap with an invented export.
Event time, discovery time and collection time are different facts
An event may occur at one time, enter a logging service later and be seen by an analyst later still. In the supplied classroom table, R9 says that an edit was recorded at 09:03 UTC. R15, at 09:14, communicates a retention rule; it does not restart the retention period for R9. Without the actual source's deletion policy, no learner can calculate an exact expiry from those two timestamps. The safe operational question is: What is the oldest relevant record's retention deadline at its source, and how soon can an authorized custodian preserve a narrow copy? Escalate that uncertainty instead of writing a fabricated deadline.
When merging records from different systems, retain the original timestamp and its timezone or offset. Add a normalized UTC field separately and record how it was obtained. A timestamp without an offset is ambiguous; a clock that is five minutes slow may reverse apparent order. The case table supplies UTC for teaching, but a real analyst would check source clock configuration and collection delay before claiming a precise cross-system sequence. R13's summary omits device and location detail, so the absence of those fields is a source limitation, not a negative finding about the session.
Preservation should also be proportionate. For the next Harbor Library decision, a bounded booking-audit interval and the account's relevant sign-in summary may be useful. Exporting all patrons, all departments or unrelated accounts could increase privacy risk without improving the decision. A narrow export can still omit a relevant event; record the selection rule and keep an authorized unmodified original when available. Module 2 teaches the logic of a collection request and a copy-integrity check. Production evidence handling belongs to the organization's approved procedures and qualified personnel.
Source time, arrival, visibility, query, release and collection
A timestamp must identify both whose clock it uses and what transition it describes. A useful ledger distinguishes these fields:
Lesson table; scroll horizontally to read all columns →
| Field | Meaning and boundary |
|---|---|
| Source event or source-record time | When the source reports an operation, document observation or notice; identify which kind rather than calling every card time an operation time |
| Receiver arrival time | When a named collector or transport accepted a record, if actually measured |
| Query-visible time | When the selected store/index could return the record; an upstream arrival receipt need not establish search visibility |
| Query run time and selection | When the query ran, separately from its source, filters and selected event-time interval |
| Learner release or analyst discovery | When the classroom permitted use of a card; in a real case, record receipt and recognition separately where they differ |
| Copy acquisition time | When a particular export or local teaching copy was actually acquired or created, not when its represented event occurred |
Source clocks can be wrong, and pipeline implementations differ. A field called ingested_at needs a documented producer meaning: it might represent receipt, storage acceptance or indexing. Do not silently substitute one for another. NIST SP 800-92 discusses log generation, transmission, storage and use; this particular ledger is the book's instructional method, not a NIST schema.
In the canonical Round B packet, R9 reports a 09:03 booking edit; R10 has a 09:04 plan-record timestamp, not a verified approval time; R15 has a 09:14 notice timestamp, not a retention start; R16 has a 09:16 owner-note timestamp, not an executed account change. All four become available to the learner at 09:20. Their actual receiver-arrival, indexing and acquisition times are not supplied. R14's printed 09:12 is the supplied card's time, not a complete query-execution manifest. Only the explicitly hypothetical T1 card assigns a 09:12 query run and its particular event window.
The difference from a source-card time to 09:20 is therefore a source-to-learner-release interval, not a measured transport or ingestion delay. Preserve the original text and offset, the normalized UTC value, its source-time kind and the release boundary. RFC 3339 documents date-time representations and offsets; an offset does not authenticate a clock or reconstruct a missing timestamp. R9 remains unavailable to the 09:05 R1–R8 decision despite its earlier event time.
2.4 Worked example: the second alert
The following records are also fictional and extend Module 1. They are the complete input for this chapter's exercises. No live system or external account is involved. Exercise timing: the Module 1 analyst made the 09:05 decision from the then-supplied R1–R8 snapshot. This chapter releases R9–R16 to the learner at the simulated 09:20 review. Several events in the new table have earlier timestamps; the time an event occurred and the time the analyst received its record are different facts.
Lesson table; scroll horizontally to read all columns →
| ID | UTC time | Source | Observation |
|---|---|---|---|
| R9 | 09:03 | Booking audit | desk-a changed booking B19 from Room 1 to Room 3. |
| R10 | 09:04 | Training plan | The planned exercise mentions B17 and B18; it does not mention B19. |
| R11 | 09:06 | Help desk | A second patron reported that the time on B19 looked wrong. |
| R12 | 09:08 | Staff interview note | The staff member said they edited B17 and B18 during training but did not recall editing B19. |
| R13 | 09:10 | Identity summary | The account had one session in the available time range; the summary omits device and location detail. |
| R14 | 09:12 | Application audit | No further booking edits are shown after R9 within the queried range. |
| R15 | 09:14 | Retention notice | Detailed booking audit records are deleted after 24 hours unless an authorized copy is retained. |
| R16 | 09:16 | Service-owner note | The owner requests an impact check before any account change and can approve a short booking-service pause if needed. |
Step 1: distinguish the operation from the reported symptom. R9 is labeled booking audit and reports a change to B19's room, from Room 1 to Room 3. R11 is a help-desk report that B19's time looked wrong. The shared booking ID makes a bounded comparison useful; it does not make these the same field or establish that the room change caused the time complaint. R14 is separately labeled application audit. Confirm source identity and field semantics before treating R9 and R14 as one continuous log.
Step 2: split the hypotheses into testable propositions. H1 asks whether the relevant edits were within scheduled training. R10's plan names B17/B18, not B19; R12 is a recollection rather than an exhaustive approval record. H2 asks whether the B19 operation fell outside the approved task set. Neither proposition directly identifies the person controlling the account. Ask the training owner for the complete applicable plan, version, effective approval time and any B19 addendum. A document received at 09:20 may describe an earlier approval; its arrival time alone neither validates nor invalidates that earlier authority. A newly issued retrospective approval must not be presented as permission that existed at 09:03.
H3 addresses the patron's reported display or synchronization problem. Test the reported time separately from the audited room change. A proposed comparison should identify B19, the exact field, an owner-approved target and version, the authoritative stored value and its observation time, and the patron-facing value with its own observation time. None of these comparison values is supplied by R1–R16. The following are conditional interpretations, not new case facts:
Lesson table; scroll horizontally to read all columns →
| Future comparison, if authorized and adequately evidenced | Narrow conclusion | Remaining limitation |
|---|---|---|
| The relevant patron view differs from the authoritative stored time, while that stored time agrees with the applicable approved target | Supports a discrepancy between those observed representations | Does not establish the synchronization mechanism or explain the room edit |
| Contemporaneous view and stored time agree with each other but both differ from the applicable target | Weakens a display-only explanation for that observed state; supports a bounded target/state discrepancy | Does not establish its cause or exclude a separate earlier transient display problem |
| A target, version, relevant observation time or trustworthy source is missing | The proposed comparison remains unverified | Neither “correct” nor “corrupted” is warranted from the complaint alone |
A later correct view cannot, without historical evidence, prove that the earlier complaint was mistaken. Likewise, a room mismatch does not independently corroborate a time-field complaint. Keep the observations, hypothesized relationship and unanswered question separate.
Step 3: request the smallest discriminator that can change the decision. The training owner can address task authorization; the service owner and application custodian can define the bounded field comparison; the identity custodian can address a separately authorized session-correlation question. An identity-summary request cannot substitute for an approved-task-list check. Request source availability and preservation in parallel where justified by R15, without declaring an export, hold or loss. The incident lead retains the 09:35 review, or an earlier review on a separately verified new unexplained edit or substantiated source-availability concern. No account or service change is authorized merely by producing this analysis.
Lesson table; scroll horizontally to read all columns →
| Case decision at 09:20 UTC | Rationale | Owner | Review trigger |
|---|---|---|---|
| Preserve the supplied booking and identity records in the classroom case note; request an authorized impact check in a real response. | The B19 edit is not yet explained and detailed audit retention is short. |
Incident lead is the proposed approval owner for bounded analysis and a separate source request; analyst records only the synthetic case note unless a local exercise copy is actually created and documented. P-A/P-B remain proposed. | Training-owner answer, new booking edit or the next review at 09:35 UTC. |
This decision does not clear or accuse the staff member. It states what is known, what can be lost and who may authorize the next action. If the impact check found broad damage, a containment proposal would need to reach the service owner and incident lead promptly; Module 3 will compare those options.
Worked 09:20 preservation queue
The learner receives R9–R16 at the simulated 09:20 review. R9 reports a 09:03 edit, but was not available for the learner's 09:05 decision. R15 reports a 24-hour policy concerning detailed booking-audit records, not a measured countdown or a completed deletion. The policy anchor, oldest-row availability, enforcement behavior and any authorized copy or source hold remain unconfirmed. Ask the custodian what the copy provision means in this source's actual procedure; do not assume that saving an export changes the source's removal mechanism. The queue records proposed requests, not approvals or completed preservation. R15's rule must not be borrowed for R14's separately labeled application-audit source, R11's help-desk record or R13's identity source without an explicit custodial mapping and policy confirmation.
Lesson table; scroll horizontally to read all columns →
| Request and decision value | Loss/coverage question | Owner and proposed minimal scope | State at 09:20 and remaining limit |
|---|---|---|---|
P-A: detailed booking audit for B17–B19, plus R14's application-audit query description; could reconstruct recorded edits and support a separate impact comparison. |
R15 names 24-hour deletion, but the policy anchor, oldest available row and exact last safe time are unknown. R14's filter and ingestion coverage are also unspecified. | Incident lead seeks approval; application custodian checks a proposed 08:30–09:20 UTC event window, booking IDs and available raw fields, then records each source, filter, run time and export method. | Proposed. No detailed copy, confirmed deadline, complete query or approved booking state has been supplied. |
P-B: identity-session detail relevant to desk-a; could test whether an application action shares a session key. |
R13 is only a summary without device or location; its source retention and key semantics are unknown. | Incident lead asks identity administrator for availability, retention and a restricted time/field selection. Any cross-source join requires schema and clock checks. | Proposed. No person, device, location or actor attribution follows from R13. |
P-C: approved training task list and version; could test whether B19 was actually in scope. |
R10 lists B17/B18; the plan's version, approval time and completeness need confirmation. No deletion deadline is supplied. | Training owner supplies only the relevant signed or approved task list and its version history through the approved case route. | Proposed. R12's recollection is context, not a substitute for the plan or proof of who edited B19. |
P-D: help-desk report and service comparison; could bound user-facing harm. |
R11 is a report, not a measured patron count; the database and displayed view may disagree. | Service owner and help desk plan a restricted B19 comparison, separating the report from a patron-facing check and an approved state. | Proposed. No population-wide impact estimate or restored-service claim is supported. |
P-A receives prompt attention because the fictional retention notice identifies a plausible loss path and the detailed rows could change the next containment or impact decision. The lead should seek a custodian-confirmed policy anchor and a safe collection time immediately. R9 is labeled booking audit while R14 is labeled application audit; the request must ask whether these are the same producer or two different paths, rather than treating their summaries as one complete log. P-B can run in parallel because its retention is unknown, not known to be unlimited. P-C and P-D remain important to interpretation and harm; they are not discarded merely because the audit may be more volatile. The proposed P-A range is deliberately broader than R9's single timestamp yet bounded by the booking question. It is a request for custodian review, not an assertion that those filters exist, that the source contains every event, or that the lead has approved exporting patron data.
Suppose the application custodian later returns a restricted file. The analyst would record its actual collection time, the approved selection, source timezone, any transformation, byte count or applicable integrity check, storage/access owner and reviewer. The analyst would also ask for the query manifest behind R14's quiet summary: source, booking/account filters, half-open event interval, query run time, ingestion coverage and source-health limitations. Without that manifest, a copied R14 sentence still cannot establish that no edits occurred after R9. If the custodian instead reports that the detailed interval has already expired, the response lead records the failed request and who confirmed it, preserves the remaining source pointers within scope, and changes the claim from “we checked the detailed audit” to “the detailed audit was unavailable for this interval.” Neither branch may be silently backdated to 09:05.
A concise 09:20 handoff can therefore say: “R9 records a B19 edit at 09:03 UTC; R10 omits B19 from the listed training tasks, and R15 reports a 24-hour detailed-audit retention rule whose anchor we have not verified. At 09:20 we propose P-A to the incident lead and ask the application custodian to confirm availability, selection and the actual policy deadline; no production copy, hold or account restriction is recorded here.” This wording lets the next analyst see both the reason for urgency and the boundary of current evidence. Exercise EX018 asks the learner to make that request independently.
Preservation as an authorized transaction
A useful preservation request names why a source matters before specifying how much data should be copied. The next question is whether B19 was an approved operation and whether the booking service's current state matches what the service owner expects. This favors bounded booking-change evidence, an approved task-list version and appropriately limited identity details—not a bulk export of all patron records.
For each source request, prepare:
- Decision purpose: what the evidence could change.
- Producer and fields: what system is expected to know, including timestamp and identifier semantics.
- Selection: the smallest defensible time and object range, including explicit exclusions.
- Custodian and authority: who can retrieve the data and who can approve the operation.
- Retention question: whether the source still contains the interval and when it may cease to.
- Receipt design: which exact source, query, object, acquisition time and transformation would be recorded if collection happens.
- Residual uncertainty: which causal or completeness claims would remain unproved.
The existing P-A and P-B queue illustrates this. P-A can be addressed promptly because R15 reports a deletion risk for detailed booking audits. P-B can proceed in parallel as an availability inquiry because identity-source retention is unspecified. Neither source should be treated as collected merely because the analyst assigned it priority.
The states proposed → approved → collected → verified are not interchangeable. A written request is proposed. An incident-lead authorization covers only its recorded scope. A collected object needs an identifiable receipt. Verification identifies what was checked, such as the exact copied bytes or selection manifest, and what was not checked. Privacy restrictions and access controls apply to the collected copy independently of the source's original retention policy.
NIST SP 800-86 discusses forensic work across data sources from an IT incident-response perspective and expressly does not offer legal advice or an all-inclusive procedure. Harbor Library's request card is a beginner teaching method, not a chain-of-custody certification or permission to collect real personal data.
2.5 Contained lab: preserve and check a synthetic extract
The lab below is deliberately smaller than a forensic acquisition. It teaches which bytes a digest covers and which conclusions still require other evidence. Use a new, empty, authorized scratch directory on a computer you control, with Python 3 and no network connection. The generated text is invented for this book; it contains no real account, endpoint or patron data. Running the script creates two small files in the current directory and refuses to overwrite existing names. If either name already exists, stop and choose a different scratch directory; do not remove an existing file to make the lab run.
The extract has two rows that transcribe R9 and R14. It is a learning fixture assembled from this chapter's table, not an original log from Harbor Library. R14 summarizes the queried audit range; it does not assert that no later edit occurred outside that range. Save and run the following as fixture.py inside the scratch directory:
from hashlib import sha256
from pathlib import Path
payload = (
b"case_id|record_id|time_utc|source|observation\n"
b"HL-IR-001|R9|2026-10-11T09:03:00Z|booking-audit|desk-a changed B19 from Room 1 to Room 3\n"
b"HL-IR-001|R14|2026-10-11T09:12:00Z|application-audit|no further edits in the queried range after R9\n"
)
with Path("E1.txt").open("xb") as output:
output.write(payload)
saved = Path("E1.txt").read_bytes()
print(len(saved), sha256(saved).hexdigest())
altered = saved.replace(b"Room 3", b"Room 4")
with Path("E1-modified.txt").open("xb") as output:
output.write(altered)
saved_altered = Path("E1-modified.txt").read_bytes()
print(len(saved_altered), sha256(saved_altered).hexdigest())
Failure-path check: two exclusive creations are not one atomic transaction. The required new empty directory avoids ordinary filename collisions. Python's exclusive-create file mode refuses to overwrite an existing target, but each call protects only its own file. In a separately labeled failure rehearsal where only E1-modified.txt already exists, the first write can create E1 and print its digest before the second write raises FileExistsError. That is a partial local attempt, not completion of both files and not an overwrite of the pre-existing file. Record which file was actually created, which operation failed and what was left unchanged. Stop; do not delete the existing object or switch to an overwrite mode to obtain the expected transcript. A new authorized empty directory permits an independent attempt with its own recorded state.
For a collection note, record the actual local time when the creation is performed. A recorded start/end interval may honestly bound the operation; a later observation time or filesystem timestamp with unverified semantics must not be relabeled as an exact creation receipt. When a time was not recorded, say so. The synthetic 09:20 review does not supply a local acquisition time.
Procedure. First, predict whether both files will have the same byte length and whether their SHA-256 digests will match. Then run the script and record both output lines. Read E1.txt and E1-modified.txt to locate the intentional one-byte change. Re-run the first digest on E1.txt and compare it with the saved value. Finally write a collection note identifying the exact file, byte count, local collection time, synthetic source, authorized classroom scope, transformation and storage location. If you cannot run Python, reason from the displayed bytes and use the worked result to check your conclusion; software execution is not required to answer the conceptual question.
The byte count is a useful reproducibility check, but equal length is not equal content. A matching digest on E1.txt at two checks supports the limited statement that the bytes checked were the same at those two times, assuming the digest calculation and recorded values are trustworthy. A differing digest for the deliberately altered copy shows that this check detects that particular edit. Neither result verifies the truth of R9 or R14, completeness of the original query, correctness of a clock, identity of the editor, legal authority or whether data left the service. The example uses SHA-256 as an integrity check, not as proof of authenticity.
Expected submission: the two byte counts and digests, one sentence explaining why the hashes differ, a collection note for E1.txt, and two explicit limits on the integrity claim. Rubric: one point each for correct byte/digest comparison, correctly identified modification, complete source-and-authority note, and limits that distinguish copy integrity from source truth. A score of 4/4 means the classroom task is reproducible, not that a real forensic process has been completed. The exact expected output and a model note are in the final worked-results section after EX026.
A digest needs an object, a check time and a bounded claim
The E1 exercise has two different objects before its second file is read: altered, a byte string in the Python process, and E1-modified.txt, a named file. Hashing the first describes the intended output buffer. Reading the second and hashing the returned bytes describes what that read obtained from the named file. Those claims can agree in an ordinary successful run, but they are not the same measurement.
The revised listing above uses saved_altered = Path("E1-modified.txt").read_bytes() after the second file is closed and computes its second printed result from saved_altered. The first file already used this read-back pattern. The payload, intentional one-byte change and two expected output lines are unchanged. Python's Path.read_bytes documentation describes reading a file's binary contents; exclusive creation addresses a different question: whether an existing filename is overwritten.
Neither operation authenticates the original producer, verifies a storage device's crash durability, locks out a concurrent writer or records an uninterrupted custody history. Use the authorized private scratch environment specified above, rather than a shared or adversarial directory. A read-back error is a failed measurement, not a reason to substitute the intended buffer and label it a successful file check. Record the actual partial state and error; leave unperformed checks unperformed.
A reproducible integrity statement therefore needs at least the named object, the bytes or digest actually measured, the check time or recorded operation interval, and the comparison reference. The reference must be preserved as a separate record. Computing a new digest and silently replacing the old reference does not explain an unexpected difference. A timestamp in the file describes its content; it is not the time at which the analyst created or checked that file.
Intended byte string --write--> Named local file --read--> Bytes obtained
| |
v v
Hash of intended output Hash of this read
|
Compare with retained reference
|
Report object, time and limits
Text alternative: A buffer hash measures the buffer. A file read produces the bytes for a file-check hash. Compare that measured value with the retained reference and identify the check's time and object. None of these steps establishes source truth, full query coverage, uninterrupted custody or production collection authority.
Equal endpoints do not reconstruct the interval between them
Suppose an authorized reviewer checks a copy at two instants and obtains the same digest. That is useful evidence about those observations. It cannot establish that the copy remained unchanged at every unobserved instant between them. The distinction does not require a hash collision: a byte sequence could change and later be replaced by exactly the original sequence.
The following independent example supplies three invented in-memory states, named first, middle and last. They are not observations of E1, an R-series record or a real storage system. The middle state is supplied solely to make two possible histories distinguishable. Run this complete Python 3 listing in a fresh session. It creates and changes no files and needs no network access.
from hashlib import sha256
# Independent in-memory illustration, not E1 or an R-series record.
original = b"practice-value=3\n"
changed = b"practice-value=4\n"
histories = {
"UNCHANGED": (original, original, original),
"CHANGED_THEN_SAME": (original, changed, original),
"CHANGED_AT_END": (original, changed, changed),
}
for label, states in histories.items():
first, middle, last = (sha256(value).hexdigest() for value in states)
print(f"{label} endpoints_equal={first == last} "
f"middle_equals_first={middle == first}")
Work the example before running: UNCHANGED and CHANGED_THEN_SAME have exactly the same first and last bytes. An observer given only those endpoints cannot distinguish their histories. The supplied middle observation separates them. CHANGED_AT_END instead leaves different bytes at the final observation, so the endpoint comparison detects that particular change. The program illustrates limited observability; it does not determine who changed a file, whether any real change occurred, or how a production evidence store should be implemented.
The appropriate wording is “the measured values matched at the two recorded checks”, not “the copy could never have changed.” Additional authorized custody records, access controls and observations may strengthen a real preservation account, but their existence and scope must be evidenced separately. A third matching sample would still not observe every instant. NIST SP 800-86 provides source-aware forensic guidance in an IT response context, not a certification that this classroom copy has legal evidentiary standing.
Independent checkpoint practice
First predict and then reproduce the program's three lines. Submit three claim-review rows with claim | supported finding | missing evidence | next safe step for these deliberately faulty statements: A, “the former sha256(altered) expression was a read-back of the second file”; B, “matching endpoint hashes prove the copy never changed”; and C, “the second exclusive creation failed, so the first file was never created.” For C, use the explicitly supplied failure scenario in which only E1-modified.txt existed initially and the first output line was printed. Do not infer that scenario from every possible error.
Then predict the E1 program's outcome for four separately prepared starting states: neither output name exists; only E1 exists; only E1-modified exists; both exist. Record expected printed-line count, whether either new file is created and which existing bytes must remain untouched. These are predictions unless actually tested. The ordinary learner run still requires a fresh authorized directory with neither output present; do not delete an existing object to create a convenient starting state.
Use EX019's existing collection-note format to record only what was actually created and measured. Keep EX020's five claim rows, adding the endpoint limitation to their existing explanations rather than treating it as a new exercise. This supplementary checkpoint does not change the course's exercise count or confer collection authority. Assess the artifact by whether the learner identifies the measured object, preserves the initial and partial states, limits the endpoint inference and proposes a source-supported next check. Worked checkpoint answer.
2.6 Temporal coverage lab: what the analyst knew, and when
A useful timeline has at least two clocks: event time, as recorded by a source, and discovery time, when the responder received or recognized that record. A third time, collection time, marks when a copy was created and should be recorded separately. A query also has a coverage interval: the source and filters searched, the beginning and end of the search, and any ingestion delay or missing fields. These fields answer different questions. Sorting on one timestamp without naming which clock it represents can produce a fluent but false case history.
The Harbor Library example makes this visible. The learner's 09:05 decision used R1–R8. R9 records a 09:03 edit but is released to the learner with R9–R16 at the 09:20 review. The later discovery does not move the edit forward in time, and the earlier event time does not make it legitimate evidence for the 09:05 decision. An analyst should preserve both times so a reviewer can reconstruct what was actually knowable at each checkpoint. This is an original classroom workflow consistent with the source-aware investigation described in NIST SP 800-86; that older guide does not prescribe this book's specific fixture or scoring rule.
Exercise-only card T1 — illustrative query metadata. Imagine that a custodian now supplies the missing scope for R14: source application-audit; booking-edit events with event times at or after 09:00 and before 09:12 UTC; account filter desk-a; query run at 09:12 UTC. T1 is not one of R1–R16 and must not be used to rewrite the 09:05 decision or to pretend the original R14 supplied its own start and end. Even with T1, the statement “no further edit after R9 in this query” covers only that source, account filter and interval. It says nothing about another account, a delayed record or an edit at 09:13. Without T1, R14's exact interval remains unknown.
The following optional lab runs entirely in memory with Python 3's standard library. It creates no files, sends no network requests and uses only fictional timestamps. R10's 05:04-04:00 text is an exercise rendering of its existing 09:04 UTC value, not a new event or a claim about any real location's timezone rules. The offset is explicit; the script does not guess one.
from datetime import datetime, timedelta, timezone
rows = [
("R9", "2026-10-11T09:03:00+00:00", "2026-10-11T09:20:00+00:00"),
("R10", "2026-10-11T05:04:00-04:00", "2026-10-11T09:20:00+00:00"),
("R15", "2026-10-11T09:14:00+00:00", "2026-10-11T09:20:00+00:00"),
]
def utc(text):
try:
value = datetime.fromisoformat(text)
except (TypeError, ValueError) as exc:
raise ValueError("INVALID_TIMESTAMP") from exc
if value.tzinfo is None or value.utcoffset() is None:
raise ValueError("OFFSET_REQUIRED")
return value.astimezone(timezone.utc)
def release_interval(source_text, release_text):
source, released = utc(source_text), utc(release_text)
if source > released:
raise ValueError("SOURCE_AFTER_RELEASE")
if any(value.second or value.microsecond for value in (source, released)):
raise ValueError("MINUTE_PRECISION_REQUIRED")
minutes = (released - source) // timedelta(minutes=1)
return source, released, minutes
for record_id, source_text, release_text in rows:
source, released, minutes = release_interval(source_text, release_text)
print(
f"{record_id} source={source:%H:%M} UTC "
f"released={released:%H:%M} UTC interval={minutes} min"
)
# Independent malformed-input controls, not additional R-series facts.
for label, text in (
("NO_OFFSET", "2026-10-11T09:03:00"),
("FUTURE_SOURCE", "2026-10-11T09:21:00+00:00"),
("BAD_CLOCK", "2026-10-11T25:03:00+00:00"),
("SUB_MINUTE", "2026-10-11T09:03:30+00:00"),
):
try:
release_interval(text, rows[0][2])
except ValueError as exc:
print(f"{label}: {exc}")
else:
raise AssertionError(label + " was not rejected")
Time-label clarification and input contract: source means the source-card time: an edit for R9, a plan record for R10, and a retention notice for R15. released means the learner's 09:20 release. The dates and offsets are the existing synthetic fixture, not new case evidence. This minute-aligned exercise requires an explicit UTC offset and refuses a source timestamp later than its release under the assumed comparable clocks. It rejects sub-minute values rather than silently rounding them. This is not a general RFC 3339 validator or a real clock-verification tool. In particular, Python's datetime documentation explains that converting a naive datetime can use the machine's local timezone; this program rejects that ambiguity before conversion.
Interpret the time field before ordering the records
A timestamp's representation and its meaning are different. Converting 05:04-04:00 to 09:04 UTC preserves the represented instant; it cannot tell us whether that instant is an operation, a plan record, an approval, a source query or an analyst's later acquisition. Sorting correctly formatted values without identifying those meanings can create a false causal or authorization sequence.
For example, a faulty reading says: “R9's edit is at 09:03 and R10's plan is at 09:04, therefore the operation preceded its authorization.” The ordering of the two supplied record times is correct, but the conclusion needs an effective authorization time that R10 does not provide. The plan-record time is not proof of when the plan was first written or approved. Ask the training owner for the applicable version and approval evidence; do not infer that authorization was either present or absent from this ordering alone.
The same error can create a fabricated preservation deadline. R15's 09:14 timestamp belongs to a retention notice. It is not a supplied retention-start timestamp for R9. Neither adding 24 hours to 09:14 nor adding it to R9's 09:03 establishes a deletion instant without the source policy's actual anchor and enforcement semantics. Keep the loss concern visible while the custodian clarifies it.
For EX021, retain five rows and annotate each supplied timestamp with its kind: R9 reports an edit; R10 identifies a plan record; R12 an interview note; R15 a retention notice; R16 a service-owner note. A note's timestamp is not automatically the time of every action discussed in it. Add a specific uncertainty in each row, not one general disclaimer that hides which inference is missing. The common 09:20 learner release remains a separate field or table note; it is neither a source event nor evidence that a local copy was created.
Independent self-check: Before opening EX021's final answer, explain why a plan-record time cannot settle prior authorization and why a notice time cannot start an unprovided deletion clock. Then identify the owner and missing record that could resolve each question. Correct arithmetic, correct source-time meaning and sufficient evidence for a decision are three separate requirements.
Predict the original three intervals and all four rejection reasons before running. None of the malformed-input controls is an R-series event. A chronological rejection calls for investigation of timestamp meaning and clock assumptions; it does not establish malicious activity. Keep ingestion, query execution and copy creation unknown when they have no separate evidence.
Procedure: (1) Before running it, convert R10's offset time by hand and predict the three source-to-learner-release intervals. (2) Run the code in an authorized local scratch environment, or calculate the outputs from the shown values if Python is unavailable. (3) Make a three-row table with record ID, original timestamp including offset, normalized UTC source-card time and kind, learner-release time, source-to-learner-release interval and whether the record was available at 09:05. (4) Draw the coverage interval from T1 as 09:00 ≤ event < 09:12 UTC and put R9, the T1 end and the 09:20 review on it. (5) Write two sentences: the strongest conclusion supported by R14 with T1, and the next authorized check needed to assess activity after 09:12. Keep the R15 retention notice separate from any assumed deletion instant.
Expected evidence: R9 is 09:03 UTC and released to the learner 17 minutes later; R10 is 09:04 UTC and released 16 minutes later; R15 is 09:14 UTC and released six minutes later. None was in the learner's R1–R8 snapshot at 09:05. With T1, R14 supports only that this narrow query showed no further matching edit before 09:12. The unqueried period after 09:12 is an evidence gap, not a verified quiet period. The learner should request a new bounded query or an approved source comparison, record its filter and end time, and check whether logging and ingestion were working. R15 reports a 24-hour detailed booking-audit policy with an authorized-copy provision; it does not give enough deletion-policy detail here to calculate the precise expiry of R9 from its event timestamp alone.
Assessment rubric: one point each for correct R10 normalization, three correct source-to-learner-release intervals, the 09:05 availability boundary, a T1 coverage statement that excludes post-09:12 activity, and a narrow authorized follow-up with retention uncertainty. Five points show the classroom reasoning is reproducible; they do not certify a real evidence acquisition or establish who edited B19. The printed output and a model coverage statement appear after the Module 2 synthetic-extract result in the final appendix.
A query envelope is narrower than a case conclusion
A log search is a measurement operation over a specified source and filter, not a universal statement about everything that happened. An empty or apparently quiet result is meaningful only in the context of its query envelope:
Lesson table; scroll horizontally to read all columns →
| Envelope field | What a reviewer must know |
|---|---|
| Producer/source | Was the booking audit, application audit or another source queried? |
| Event-time interval | What beginning and end were selected, and was the end exclusive? |
| Identity/booking filters | Which account, booking IDs or operation kinds were included or excluded? |
| Query run time | When did the result reflect the available index? |
| Ingestion completeness | Through which event-time boundary was the relevant source demonstrably indexed? |
| Source health and retention | Were generation, collection and storage functioning during the interval? |
| Returned rows and transformations | Were rows missing, deduplicated, normalized or otherwise transformed? |
R14 is intentionally narrow: it reports no further booking edits after R9 within its queried range. Canonical R14 does not provide the complete envelope. R9 is labeled booking audit while R14 is labeled application audit. Treating them as a single fully covering source would silently merge producers without evidence.
This distinction exposes two different kinds of "nothing found." One is no row matched this particular query at this query time. The other, much stronger statement would be the necessary producers were functioning, the selection was correct, the source's relevant events were all collected and indexed, and no qualifying event occurred in the bounded interval. The former does not establish the latter.
The existing T1 exercise supplies illustrative metadata only when expressly invoked, and T2 demonstrates late arrival. The new VQ2 lab below goes a step further: it asks when the metadata itself would be adequate to support even a bounded negative statement. A query that covers the correct event interval but was run before ingestion had caught up is insufficient; so is a query with complete ingestion for the wrong account.
NIST SP 800-92 provides primary guidance on log generation, collection and management. This older publication supports the need to understand those stages; the envelope and acceptance gate are original instructional models, not a NIST query specification.
2.7 Delayed log arrival: when a quiet query changes
Section 2.6 established a query envelope: source, event-time interval, account filter and time at which a query was run. A fifth field matters when records travel through a collection pipeline: ingestion time, when a record becomes available to the queried store. An event may have occurred inside the requested interval yet be absent from a query run before its arrival. The absence is a statement about the store's visible contents at that query time, not a final statement about every event that happened in the interval. NIST SP 800-92 treats log management as a process of generating, transmitting, storing and using records. It is a 2006 high-level guide, not a specification for the exercise algorithm below. This book's delayed-arrival fixture and scoring rule are original classroom material.
Use four different times or bounds in the case note. The event time comes from the producing application and may itself be inaccurate if the source clock is wrong. The ingestion time is when the queried store accepted the row; it says nothing by itself about when the analyst read it. The query run time is when the analyst or custodian asked the store for matching rows. The event-time window describes which event timestamps the query selects. A discovery time records when the result reached the response team. If the store can supply only some of these fields, mark the rest unknown. A later query returning more rows does not automatically mean a new event happened after the earlier query.
The canonical Harbor Library R14 card says only that its available query showed no further booking edits after R9 within its queried range. T1 in section 2.6 adds an exercise-only event window and account filter. It does not supply an ingestion-completeness guarantee. At a real response desk, an analyst might request source health, pipeline delay and collector error information from the logging owner, but this beginner exercise supplies no such operating measurements. An empty interval should therefore be written as “no matching row visible in this query as run,” followed by its bounds. It should not be written as “no edit occurred.”
Optional T2 replay: a late row in the same event window
T2 is a separate counterfactual replay, not a new R-series record and not an amendment to the main case. Reset to the fictional 09:12 query snapshot, then imagine the following four synthetic rows. L1 transcribes R9 for this replay. L2–L4 are invented only to exercise query semantics; do not use them in EX014–EX026, Module 3 or the Module 4 tabletop unless a question explicitly names T2.
Lesson table; scroll horizontally to read all columns →
| Replay row | Account | Event UTC | Ingested UTC | Classroom observation |
|---|---|---|---|---|
| L1 | desk-a |
09:03 | 09:04 | B19 booking edit, representing R9 in this replay |
| L2 | desk-a |
09:10 | 09:18 | B21 booking edit, visible only after delayed ingestion |
| L3 | helper-b |
09:11 | 09:11 | B22 booking edit under a different account |
| L4 | desk-a |
09:12 | 09:13 | B23 booking edit at the excluded end boundary |
The replay query selects application-audit booking edits under desk-a with 09:00 ≤ event time < 09:12 UTC. Its second condition is that the row was ingested no later than the query run time. The end boundary is exclusive. Assume all four clocks are correct, all rows belong to the same fictional date and no other filter exists; these are classroom assumptions, not evidence about production logging. First run the mental query at 09:12, then repeat the same event window and account filter at 09:20. Before looking at code, predict exactly which L IDs each run returns and which exclusion rule removes each other row.
This optional program operates only on the in-memory T2 fixture. Its last column is treated as query-visible time; T2 assumes no additional delay between the listed ingestion and search visibility. This simplifying assumption must not be applied to a real collector without checking its semantics. All rows use one fictional UTC day and comparable accurate clocks. The parser validates HH:MM, and the program rejects a row visible before its event under those assumptions. It validates the whole supplied packet before filtering, so an irrelevant account cannot hide malformed timestamps. It is still not a production parser, a transport simulation or an ingestion-completeness check.
import re
rows = (
("L1", "desk-a", "09:03", "09:04"),
("L2", "desk-a", "09:10", "09:18"),
("L3", "helper-b", "09:11", "09:11"),
("L4", "desk-a", "09:12", "09:13"),
)
def minute(text):
if not isinstance(text, str) or not re.fullmatch(r"[0-9]{2}:[0-9]{2}", text):
raise ValueError("BLOCK_INVALID_HHMM")
hour, minute_part = map(int, text.split(":"))
if not (0 <= hour <= 23 and 0 <= minute_part <= 59):
raise ValueError("BLOCK_INVALID_HHMM")
return hour * 60 + minute_part
def visible_at(query_time, sample_rows=rows):
query = minute(query_time)
validated = []
# Validate the supplied packet before applying account/time filters.
for row_id, account, event_time, visible_time in sample_rows:
event, visible = minute(event_time), minute(visible_time)
if visible < event:
raise ValueError("BLOCK_VISIBILITY_BEFORE_EVENT:" + row_id)
validated.append((row_id, account, event, visible))
return [
row_id for row_id, account, event, visible in validated
if account == "desk-a"
and minute("09:00") <= event < minute("09:12")
and visible <= query
]
for query_time in ("09:12", "09:20"):
print(query_time, ",".join(visible_at(query_time)))
for label, query, sample in (
("BAD_MINUTE", "09:12", rows + (("X", "desk-a", "08:63", "09:04"),)),
("INVALID_QUERY", "25:99", rows),
("VISIBLE_BEFORE_EVENT", "09:12",
rows + (("X", "desk-a", "09:10", "09:00"),)),
):
try:
visible_at(query, sample)
except ValueError as exc:
print(f"{label}: {exc}")
else:
raise AssertionError(label + " was not rejected")
without_l2 = tuple(row for row in rows if row[0] != "L2")
print("OMITTED_L2:", ",".join(visible_at("09:20", without_l2)))
assert rows[1] == ("L2", "desk-a", "09:10", "09:18")
Predict the original two query results, the three malformed-input rejections and the omitted-row control. 08:63 must not be normalized accidentally to 09:03; 25:99 is not a valid query clock. An earlier visibility time contradicts this fixture's declared clock contract. In real evidence, such a discrepancy could instead reflect a misunderstood field or source clock and would need investigation.
The OMITTED_L2 case is equally important: every remaining field is well formed, but the later query returns only L1 because L2 was removed from that variant's input. Syntax validation cannot discover a record it was never given. Retain the complete original packet separately. Neither a successful parser run nor a repeated quiet query establishes source completeness. These controls remain outside canonical R1–R16 and add no exercise ID. Assess their reasoning within the existing five-point T2 rubric's timing, exclusion and bounded-follow-up criteria.
Work the result in three passes. First apply only the account and event-time filters: L1 and L2 qualify, L3 fails the account filter, and L4 sits exactly at the exclusive end. Then apply the ingestion cutoff: at 09:12 L2 is not yet visible, whereas at 09:20 it is. Finally compare the two results without changing the event times. The extra row in the second run is a late arrival, not a new post-09:12 event. Its presence would cause the response lead to revisit any conclusion that relied on the first query's apparent quiet period. It would not, by itself, identify who performed the edit or prove malicious intent.
The replay makes a useful operational distinction. A complete interval would require credible evidence that the source generated expected events, the transport accepted them, any buffering and retries were accounted for, the queried store indexed them, and the query covered the relevant source and filters through a defensible cutoff. An analyst cannot establish all that from the latest row's timestamp. A logging owner might supply a documented ingestion-lag bound or an independently monitored watermark, but the owner would have to state what that watermark means and what failures it excludes. This book supplies neither a watermark nor a service-level promise. A second empty query would remain bounded by its own run time and pipeline state.
Submission and rubric. Submit a two-row query time | returned IDs | reason for every excluded ID table, a one-sentence correction of the overclaim “nothing happened after R9,” and a request to the fictional application/logging custodian naming the event window, account filter, query run time and ingestion-health question. Score one point each for the 09:12 result, 09:20 result, correct explanations of L3 and L4, recognition that L2's event time did not move, and an authorized follow-up that distinguishes query coverage from account attribution. A 5/5 answer is a sound classroom interpretation; it is not verification of a real logging pipeline. The exact output and a worked answer appear in the final appendix after the Module 2 temporal-coverage result.
2.8 Evidence package audit: integrity is one link in a longer chain
The E1 file in section 2.5 is a synthetic transcription of book records R9 and R14. Its SHA-256 value can help a second learner check whether the working bytes changed. To assess a claim about the underlying booking service, a reviewer would still need to know who supplied the source, what query or export produced it, which fields or rows were excluded, what transformations were made, whether the source clock and logging path were functioning, and whether collection was permitted. NIST SP 800-86 discusses evidence work across data sources but explicitly does not offer an all-inclusive forensic or legal procedure. The exercise below is a training review of a small invented package, not a chain-of-custody certification.
Think of three layers. The source layer is an application or identity system and its original records. The copy layer is a specific exported byte sequence plus a query or selection manifest. The analysis layer is the learner's chronology, hypothesis table and decision note derived from the copy. A digest for the copy can check the copy's bytes at two times. It cannot retroactively create a missing source layer or prove the analysis layer's interpretation. Conversely, a well-written analysis cannot repair a silently truncated export. Give each layer a pointer in the case record so the next reviewer knows what can actually be reopened.
For the E1 classroom file, a minimal package manifest might contain the following fields. Status matters: a planned export and a collected copy are different artifacts. The example assumes the learner actually ran fixture.py; if they did not, they must label byte count and digest as expected values from the book, not measurements they performed.
Lesson table; scroll horizontally to read all columns →
| Manifest field | Model entry after the local fixture runs | Limit the reviewer must retain |
|---|---|---|
| Item and status | HL-IR-001/E1, learner-created teaching copy |
Not a production application export |
| Source and selection | Book section 2.5 payload transcribing R9 and R14; two data rows | R14's original query bounds remain unspecified without optional T1 |
| Authority and operator | Learner's local scratch directory under classroom permission | No permission to collect a real library's records follows |
| Creation and transfer times | Learner's actual local creation time; later handoff time only if a handoff occurs | Do not substitute fictional event time for file creation time |
| Bytes and integrity check | 235 bytes; SHA-256 of E1.txt as printed by the fixture |
A matching value checks these bytes, not source truth |
| Transformations | UTF-8 teaching text assembled by the listed Python payload | The payload omits source metadata not shown in R9/R14 |
| Location and access | Local named file, restricted to the learner or authorized reviewer | The book provides no real storage-control evidence |
| Supported use | Practice a bounded collection note and an integrity comparison | No attribution, exfiltration or full audit-coverage conclusion |
The second learner should check the manifest against the actual file and script, not against a confident sentence in a handoff. Confirm the byte count and digest for the file received, read the two data rows, inspect the source and selection note, then compare the proposed conclusion with the package's stated limit. If the values match but the query selection is unknown, the second learner may say the copy is byte-consistent with the recorded digest; they may not say the queried service had no other edits. If the values differ, retain both copies and their labels in the classroom exercise, stop relying on the disputed copy, and ask which bytes were changed or transferred incorrectly. Never silently overwrite one copy with the other to make the hashes agree.
Optional peer-audit drill. Imagine three variants of a package handed to you at the 09:20 review. Variant A contains the expected E1.txt, its 235-byte count, digest, script and the manifest above. Variant B contains E1-modified.txt but labels it E1.txt while retaining the original digest. Variant C contains the exact E1 bytes and digest but omits the source-selection and authority fields. For each variant, write (1) what the byte comparison supports, (2) which claim about R9/R14 remains blocked, (3) what you would ask the sender to supply and (4) whether the package is usable for a classroom copy-integrity demonstration versus an operational incident conclusion. This drill is separate from EX014–EX026 and uses no real data.
The acceptance criterion is deliberately narrow. Variant A can pass the classroom copy-integrity check if the reviewer repeats the calculation; it still cannot prove R14's underlying query was complete. Variant B fails the claimed byte identity, regardless of whether the change was accidental or deliberate; that causal question is not answered by the digest mismatch. Variant C can have identical bytes yet fail the provenance and authorization review. A simple five-point rubric awards one point for distinguishing A's two kinds of claim, one for correctly rejecting B's recorded digest match, one for C's missing provenance and authority, one for a specific repair request for each variant, and one for a handoff sentence that labels every unperformed check. A model comparison is given in the final appendix.
When preparing a real handoff, ask the next analyst to reproduce one consequential claim: locate its source pointer, re-run or review the approved selection, verify the copy if one exists, and identify the decision that would change if the claim fails. This is a quality check on the team's reasoning. It does not replace specialist evidence handling where legal, privacy, disciplinary or contractual obligations apply. Module 3 will use the same separation when it asks whether a successful backup job is also a tested and accepted recovery.
Distinguish source, copy and interpretation
A digest can support a byte-consistency comparison for a named object at named checks. It does not prove that the source exporter was authorized, that every relevant event was emitted, that the source clock was correct, or that the copied rows identify a human.
The existing E1 laboratory already proves the narrower mechanism: two equally sized classroom files with one changed byte produce different SHA-256 values. Repeating that code here would not add learning. Instead, audit whether a proposed conclusion relies on one of three independent layers:
Lesson table; scroll horizontally to read all columns →
| Layer | What it can support | What remains to check |
|---|---|---|
| Source | A producer is designated for the business question | Its authority, schema, health, clocks and coverage |
| Copy | A selected byte sequence and its integrity check are documented | Source selection, permissions, transformations and missing rows |
| Interpretation | The investigator relates records to hypotheses | Identifier meanings, competing explanations and disconfirming evidence |
A perfect digest at the copy layer cannot fill a gap in the source layer. Two files could be byte-identical copies of a truncated export. A complete export might still fail to identify the person behind a shared account label. A reviewer must be able to point to the exact layer checked rather than say vaguely that "the evidence is authentic."
A common false positive is to interpret R13's one-session summary as proof of a particular physical operator. R13 omits device and location details, and session counts alone do not authenticate the person at the keyboard. The existing Q1 exercise intentionally shows how matching identifiers and time windows can remain ambiguous; this proposal does not rewrite Q1 or the canonical R13.
Worked checkpoint
A matching digest demonstrates that the classroom copy still matches the digest used for comparison. It does not authenticate the original producer, fill a missing time window or prove that a requested source was actually retained.
Practice — Lesson 07
EX017 — What the summary cannot prove
Objective: test the limits of negative evidence. Inputs: R13, R14 and, for this question only, the optional T1 metadata. Output: two short claim/limit pairs and one proposed follow-up query. First assess R14 without T1; then state exactly what T1 adds and what it still cannot cover after 09:12. Explain why R13 does not establish that the desk-a session came from the expected staff device. A score of 2 distinguishes missing device fields from a negative device finding and names the query's filter and interval.
Extension: Before using optional T1, describe exactly which fields of R14's query envelope are missing. When using T1, distinguish a bounded event-time filter from an ingestion-completeness guarantee; name the first excluded boundary.
For full credit: The learner says that even optional T1 ends before 09:12 and does not authenticate logging completeness, another account or activity at and after 09:12. R13's missing device field remains unknown rather than a negative device finding.
Worked answer: EX017 in the final appendix.
EX019 — Collection note
Objective: make an exercise extract reviewable. Inputs: the E1 fixture in section 2.5 and R9/R14. Output: a collection-note table with case/item ID, source and event range, collector, authority, actual local collection time if a file was created, copy location, transformation and limitation. If no file was created, label the note planned and leave collection time and digest not applicable; do not pretend an export occurred. A score of 2 identifies E1 as a synthetic transcription, distinguishes original book text from the working file and records access scope. A made-up digest is not required.
State criterion within the existing 0–2 rubric: A completed local E1 file, a second-file failure and a planned collection are different states. Record only the file, time, integrity measurement, transfer or disposal actually evidenced; mark unrecorded or unperformed fields explicitly. Do not claim that failure to create the second file invalidated or erased an already created first file. A retained copy is not an applied source hold. This criterion adds no row-count requirement, exercise ID or production permission.
MIN2 supplementary task (after the required artifact):
Additional task: Keep E1's original provenance and state requirements. Add a separate planned derivative manifest: original source pointer, approved row interval/objects, fields retained, fields excluded, transformation version and intended recipient. Do not reuse E1's digest as if it authenticated new derived bytes; compute a new digest only if a local file was actually created and measured.
For full credit: Source and derived views are explicitly distinguished, and no collection/creation time or digest is fabricated. The original E1 transcript and its existing instructions remain unchanged.
HOLD2 supplementary task (after the required artifact): Preserve the original collection-note table for E1 and its actual-versus-planned status. Add a separate named source-hold ledger reference with its own proposal, authority, reported control, effect check and release/expiry fields. If no source hold was executed, mark these fields not applicable or not supplied, rather than repeating E1's copy hash as proof of source preservation.
For full credit: Source-control lifecycle and copied-item custody are distinct. The original E1 byte/transformation and access limits remain as written; no source hold, collection time or digest is fabricated.
Worked answer: EX019 in the final appendix.
EX020 — Hash claim
Objective: bound an integrity claim. Inputs: the named E1 bytes, the two digest checks and section 2.5. Output: a five-row claim table: two statements the comparison supports and three it does not, each with a one-sentence reason. Specify which file and times were checked rather than saying “the evidence is authentic.” A score of 2 distinguishes copy consistency from source truth, completeness and collection authority.
Extension: For one claim that a matching E1 digest supports, name its exact evidence layer (copy). For one claim it cannot support, name the missing source/selection or interpretation layer. Keep the E1 lab's original numbers and bytes unchanged.
For full credit: Matching hashes concern chosen bytes; they do not attest producer completeness, collection permission or the person responsible for B19.
MIN2 supplementary task (after the required artifact):
Additional task: Keep the existing five-row supported/unsupported hash-claim table. Add one sentence explaining why equal digests of a source copy do not authorize sharing the source's personal fields with a broader team, and why a projected view requires its own recorded transformation and limits.
For full credit: Byte consistency remains separate from source authenticity, completeness, permission and confidentiality. No statement that masking or hashing makes information automatically anonymous is accepted.
Worked answer: EX020 in the final appendix.
EX021 — Time ordering
Objective: order source-reported times without inventing operation, approval or collection times. Inputs: R9, R10, R12, R15 and R16; use T1 only for the optional final sentence. Output: exactly five ordered rows with ID, supplied UTC time, source and time kind, and one specific uncertainty or unsupported inference for that row. Mark the common 09:20 learner release separately from these source-card times; it does not supply local collection or source-ingestion times. Optionally state which interval T1 leaves uncovered, including its exclusive end. A score of 2 identifies the edit, plan-record, interview-note, retention-notice and service-owner-note times correctly, preserves the learner-release boundary, and does not turn record order into proof of authorization, attribution or a deletion deadline.
Worked answer: EX021 in the final appendix.