OpenCyber Academy
Rapid course · Lesson 7 · English
Course code: OCA-016Lesson 07: OCA-016-A007

Preservation, timestamps and package integrity

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

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:

  1. Decision purpose: what the evidence could change.
  2. Producer and fields: what system is expected to know, including timestamp and identifier semantics.
  3. Selection: the smallest defensible time and object range, including explicit exclusions.
  4. Custodian and authority: who can retrieve the data and who can approve the operation.
  5. Retention question: whether the source still contains the interval and when it may cease to.
  6. Receipt design: which exact source, query, object, acquisition time and transformation would be recorded if collection happens.
  7. 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.

Worked answers

EX017 — Worked result

R13 claim/limit: the available summary reports one session in its time range, but contains no device or location field. Missing detail cannot identify a device or person; it is not a finding that the session came from the expected staff device. R14 without T1: the summary says no further edits after R9 within its queried range, but the exact range and filters are absent from R14 itself. R14 with exercise-only T1: the illustrative query concerns desk-a booking edits in application-audit at 09:00 ≤ event < 09:12 UTC; it does not cover later times, another account, ingestion delay or a different source. A proposed next check asks the authorized application custodian for a new bounded query beginning at 09:12 and ending at a documented, sufficiently ingested cutoff, with source, account filters and completeness recorded. Even a zero-row result would be limited to that new scope.

Further reasoning: Canonical R14 states only that its query showed no further edits after R9 within the queried range; its exact start, end, filters, run time and ingestion coverage are not supplied. Optional T1, when explicitly invoked, introduces application-audit, account desk-a and 09:00 ≤ event < 09:12 UTC. It does not cover 09:12 itself, later events, another account or delayed ingestion. To investigate later activity, request a newly bounded query with a documented source, filter, interval, run time, collection status and ingestion-health check. R13's one-session summary lacks device and location details. It does not show that the session was on an expected device, and it cannot establish human attribution. A strong answer preserves both the narrower negative-query result and its untested assumptions.

EX019 — Worked result

Lesson table; scroll horizontally to read all columns →

Collection-note field Model entry before a learner runs the optional fixture
Case/item and state HL-IR-001/E1; planned classroom transcription, not a completed export
Source and event range Synthetic book records R9 at 09:03 UTC and R14 at 09:12 UTC; R14's underlying query interval is unspecified unless the separate T1 card is explicitly used
Collector and authority Learner analyst, within the fictional incident lead's classroom scope for supplied records only
Collection time and location Not applicable until a file is actually created; then record the learner's real local time, file path and access restriction
Transformation and original Fixture transcribes two rows as UTF-8 text; the book table is the retained source of the classroom transcription
Limitation No production log was acquired; a saved file cannot prove the source system's completeness, clock or identity attribution

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.

If the learner ran fixture.py, replace the planned state with completed local fixture, record the actual creation time and scratch path, and attach the measured 235-byte SHA-256 value from the lab. Never invent a 09:20 collection time simply because the scenario's discovery checkpoint was 09:20.

MIN2 worked extension:

The original E1 collection note describes a synthetic transcription and distinguishes a planned local exercise from a file actually created by the learner. A separate review-view manifest would record the original E1/book source pointer, bounded permitted rows, retained fields, excluded fields, intended analyst role, transformation method and its version. If no derived file was made, the creation time, location and digest remain not applicable. If a local file was produced, record its actual creation time and compute its own measured digest if required; the original E1 digest does not attest changed bytes. The derivative remains a working selection, not an authenticated production export or evidence of source completeness.

HOLD2 worked extension:

E1 is a synthetic transcription whose actual local creation time and measured digest belong in the collection note only if the learner actually generated the file. A separate source-hold ledger reference could identify a planned control for a named audit producer and record status as not supplied because no actual source hold is in the canonical Round B evidence. If a later fictional custodian response were provided, it would require its own control identifier, applicable authority, scope, reported activation, non-destructive check and release/review fields. The E1 digest supports limited consistency of E1's saved bytes; it cannot establish that the underlying source stopped deleting records. A source-hold release entry and a collected-copy retention decision remain different records. The original E1 table format and its source/copy distinctions must be preserved.

EX020 — Worked result

Lesson table; scroll horizontally to read all columns →

Claim Supported? Reason
The named E1.txt produced equal SHA-256 values at the two recorded checks Yes, if the learner actually measured and retained both values This is the direct comparison of the checked bytes under the stated method.
No byte change was detected in that named copy between the checks Yes, within the hash method and trustworthy-check assumptions Equality supports a limited consistency finding, not a broader provenance claim.
The original application log was complete and true No E1 is a transcription; the digest cannot reveal omitted or false source rows.
The source clock and actor identity were correct No A digest has no independent clock or identity context.
The export or collection had organizational authority No Permission is a decision record, not a property of the digest.

Specify the file, method and check times. Two matching values copied from the same mistaken note would not become proof of authenticity.

Further reasoning: If the learner actually created E1 and repeated the stated SHA-256 checks, the equality supports consistency of the named copy bytes at those checks, subject to method and record trust. The modified E1 variant with a different digest establishes only that the modified teaching bytes differ from those of E1. The source layer is not authenticated by the digest: E1 was transcribed from the synthetic R9/R14 table, and the underlying canonical R14 query manifest is incomplete. The interpretation layer also remains uncertain: none of the copied bytes proves who controlled desk-a or whether B19 was authorized. A 2-point answer must name the file and distinguish copy consistency from provenance, complete coverage and permission; generic claims that the evidence is "verified authentic" fail that boundary.

MIN2 worked extension:

Matching E1 SHA-256 values at two actual checks support only a bounded consistency claim about the specified copied bytes and method. They do not show that the source was complete, correctly timed, lawfully collected or authorized for broader distribution. A technical reviewer may need a derived view with unnecessary contact fields excluded. The view's field policy, row scope and transformation receipt must be recorded separately from the raw copy's integrity comparison. Neither redaction nor a digest establishes anonymization or human attribution; those require their own substantiation.

EX021 — Worked result

Lesson table; scroll horizontally to read all columns →

Order Record and supplied UTC time Source and time kind Specific uncertainty or unsupported inference
1 R9, 09:03 Booking audit; reported B19 edit time The account label does not identify the human or prove the edit was authorized.
2 R10, 09:04 Training plan; supplied plan-record time This is not an effective approval time or proof that the plan was first written after R9. Ask the training owner for the applicable version and approval evidence.
3 R12, 09:08 Staff interview note; supplied note time The recollection does not establish the time of every recalled action, the completeness of the task list or who performed the B19 edit.
4 R15, 09:14 Retention notice; supplied notice time The source's retention-start anchor and actual deletion deadline remain unknown; this notice does not start a new 24-hour clock.
5 R16, 09:16 Service-owner note; supplied note time Requesting an impact check and describing pause authority do not establish that the check or pause was approved and executed.

Separate availability note: All five cards first become available to the learner with R9–R16 at the simulated 09:20 review. None may justify the earlier 09:05 R1–R8 decision. These are differently typed source-card times, not five instances of a single operation clock. No local copy-creation time, source-ingestion time or completed collection follows from this table.

The supplied order is R9 → R10 → R12 → R15 → R16. It cannot establish who made the B19 edit, whether it was authorized or whether it caused the patron's report. R10's record time does not date the plan's first authorship or effective approval; R15's notice time does not anchor deletion. The training owner and source custodian would need to supply those distinct missing records through the authorized route. Those requests remain proposed.

If optional T1 is used, its event-time interval is 09:00 ≤ event < 09:12 UTC. It excludes an event exactly at 09:12 as well as later events. Its specified window and account filter do not establish ingestion completeness. Without T1, canonical R14's exact window remains unspecified. A full-credit answer gives a limit for each of the five rows, not merely a correct sort.