DVPPython Studio
Module 6: Shape trustworthy data / Build 3 of 4

Protect dataset provenance

Record explicit source-byte hashes and detect changed or missing fixtures without confusing parity with authenticity.

Runs on your computer · 60–90 minutes · no paid services

Download practice filesFiles, commands & notes

Without JavaScript, use the step links and keep your files on your computer.

One useful idea

A SHA-256 digest is a repeatable summary of bytes. Matching a supplied digest says those bytes match that reference; it does not authenticate the author or prove ownership, rights, safe content, truthful judgments or unchanged JSON meaning. Even whitespace can change a digest. Keep source observations separate from review decisions.

The manifest has exact integer schema_version=1, algorithm="sha256" and sorted entries. Each entry is locator, actual integer bytes and lowercase 64-character sha256. Choose explicit relative locators, not arbitrary recursive discovery: at most 1,000 unique paths, at most 240 characters each, slash-separated. No absolute/drive/traversal/backslash/empty/dot segments, known links, reserved Windows device names or trailing-dot/space components. Use an existing owned root and regular files up to 16 MiB; hash 65,536-byte chunks.

Verification validates the whole manifest before reading. Return ok, checked and ordered mismatches: each has locator plus changed or missing. Catch FileNotFoundError narrowly for a missing observation. Unsafe paths, malformed schema, permissions and programming faults remain visible errors, not missing or verified results. Preserve the input manifest. An empty manifest checks zero files; ok=True is not a nonempty dataset certificate.

Known-link/parent checks are safeguards for supplied fixtures, not protection from hostile filesystem races or mounts. The teaching example mutates only an owned temporary copy, never source fixtures or real media. A user who can replace both data and an unsigned manifest can supply new matching hashes; authenticity needs another reviewed trust mechanism.

Refresh first: Bytes, resource lifetime and read-back, Read-only fixture inventory.

Trace a finished example

from pathlib import Path
from tempfile import TemporaryDirectory
from dataset_tools.core import make_manifest, verify_manifest

with TemporaryDirectory(prefix="dvp-provenance-example-") as temporary:
    root = Path(temporary)
    path = root / "note.json"
    path.write_bytes(b'{"count": 1}\n')
    manifest = make_manifest(root, ["note.json"])
    before = verify_manifest(root, manifest)
    print(before["ok"], before["checked"])
    with path.open("ab") as stream:
        stream.write(b" ")
    after = verify_manifest(root, manifest)
    print(after["ok"], after["mismatches"][0]["reason"])

The manifest hashes one owned fixture. The first comparison matches its bytes. Appending one space changes both byte length and digest, so verification reports changed. The JSON value could still mean the same thing; this comparison concerns bytes only.

The finished implementation is in dataset_tools/core.py. Reading it is guided practice, not independent evidence.

Predict a whitespace edit

Can an extra space change SHA-256 while the JSON value stays equal?

Compare your answer · self-reviewed

Yes. Hashes compare bytes, not parsed semantic values. Keep the byte observation separate from a meaning claim.

Find a false missing file

Should PermissionError be converted to missing?

Compare your answer · self-reviewed

No. Catch only the declared missing-file exception. Permissions or unexpected faults must remain visible rather than produce a misleading reconciliation.

Recall the empty case

What does ok=True with checked=0 establish?

Compare your answer · self-reviewed

Only that an empty manifest has no mismatches. It does not establish that a nonempty dataset or portfolio has been checked.

Change it, then build your own

One controlled change

Create two new text fixtures in an owned folder, change one copy and remove the other owned copy. Predict changed versus missing. Try a duplicate or traversal locator before any file access.

Your independent task

Implement make_manifest and verify_manifest in practice.py. Reviewed locator/root/streamed-digest/manifest-schema helpers may be reused and disclosed. Write your own explicit sorted workflow and narrow missing-file boundary, preserving manifest ownership. Do not call the reference task functions or mutate original fixtures. Keep unsafe/malformed/I/O faults distinct from observed changed/missing bytes.

What success looks like

The build3 group checks actual byte hashes, sorted locators, mutation/missing detection, empty evidence, type/schema/path/size refusals and exposed unexpected I/O faults. The demo mutates only its owned temporary copies. Matching hashes never award a quality, rights, authentication or independent portfolio pass.

Hint 1 · a question

Which original facts must remain fixed while you compare a changed copy? Write the manifest shape before hashing.

Hint 2 · a concept cue

Validate all locators/schema, hash explicit regular files in chunks and retain sorted entries. Verification compares actual size and digest without rewriting the manifest.

Hint 3 · a localized example

hashlib.sha256(b"sample").hexdigest() describes those bytes. It does not prove who authored them or whether a supplied preference is true.

Need the complete worked solution?

Open dataset_tools/core.py from the kit. Trace it, close it, then try fresh inputs in your own files. Treat the attempt as guided; seeing the solution does not award a practical pass.

Course help is guidance, not independent evidence. With JavaScript, opening help records guidance locally; otherwise note it in your README. Reset does not erase that history.

Repair a failed check

If mutation still reports ok, compare actual bytes against the original digest rather than rehashing and overwriting that reference. If unsafe locators reach files, validate first. If missing and permission failures look the same, narrow the catch. If order varies, sort by the declared locator.

NotImplementedError means a practice stub is still unfinished. Read the failing test name and the last error line. Change one behavior, rerun that build, then rerun all implemented builds.

Show it works on new inputs

Author a manifest for two new fixtures, then change/delete only owned copies and record both observations. Show unchanged input-manifest data and one unsafe-locator refusal. Explain what parity establishes and what an editable unsigned manifest cannot authenticate.

Self-review: name the input, result, refused case and reason. Your local test output and explanation are separate from a quiz score; this page does not certify a pass.

Keep the idea

Provenance observations are useful when their limits are explicit. Byte equality is not judgment verification or authenticity.