# Data-handling account

This account describes inspected repository behavior at commit `6c38bae0f581dfebf581af30f0c2397ac7499e54` on 19 September 2026. It is not a record that deletion, access restriction or release approval has occurred. It covers the m1 loader/transformation/evaluation/result pipeline and static comparison CLI, not every historical experiment or copy on other machines. Only source schema metadata and existing code/documentation were inspected for this account; no source rows were loaded or printed.

## Source location and access

[Data setup](data-setup.md) is the authority for the Drive source, filename, byte size, expected SHA-256 and verified server-copy path. Keep using its ignored `data/elisa/` location and pass the source path explicitly when running from another worktree; ignored data are not inherited by worktrees. This document does not authorize downloading, copying or deleting the shared source.

[Git ignore rules](../.gitignore) exclude `data/`, CSV/Parquet files and `out/`. These rules reduce accidental ordinary Git additions; they are not filesystem access controls, encryption, retention enforcement or a block against forced additions. No Drive sharing settings, operating-system permissions, disk encryption, backup policy or other users' access were verified. Operators must restrict source access to the intended local accounts and manage any sharing outside this code; the application does not authenticate readers or set restrictive file modes.

The [loader](../src/dsh/m1/loader.py) reads the entire supplied Parquet into a PyArrow table, then separately reads the file in chunks to compute SHA-256. It records the computed checksum but does **not** compare it with the expected checksum in data setup. Verify that match before relying on the dataset identity. Keep the source stable during a run: reading and hashing are separate operations, not an atomic snapshot. Provenance records code/config versions and seed; the default code version is a short Git HEAD or `unknown`, not proof of a clean working tree.

## In-memory processing boundary

[Transformation](../src/dsh/m1/transform.py) returns an in-memory `ReleasedOutput` table plus metadata. The two defaults remove phone/SIM/device columns; the second also removes `enb_id`. They preserve row count/order and do not suppress rows or round values by default. The original source table remains available for evaluation. Dropping columns from a released table does not erase them from source memory or the source file.

[Integration](../src/dsh/m1/run.py) passes both source and released tables to the [utility adapter](../src/dsh/utility/adapter.py), which converts both to pandas. It gives the source table, including identifiers, to the privacy harness as `EvaluatorTruth`. The [privacy evaluator](../src/dsh/m1/privacy.py) projects allowed auxiliary columns from that truth, factorizes the subscriber identifier to internal codes, and builds pandas frames, sampled probes and candidate sets in memory. Evaluator-only identity/group mappings support judging attack outcomes; they are not fields of the saved result contract.

This separation is an application convention within one trusted process, not a sandbox or independently enforced access boundary. The m1 privacy harness assumes row alignment between release and truth; matching lengths alone do not prove correct alignment after arbitrary external transformations. Nothing inspected securely zeroes Arrow/pandas buffers or internal candidate sets. Objects may retain/share buffers, and garbage collection or process exit is not a certified memory-erasure procedure. See [field classification](analysis/field-classification.md) for why retained measurements also merit care.

## Written outputs and logs

`build_result` returns a typed result and validated JSON without itself writing files. `run` writes `<out_dir>/<config_id>.json` with `Path.write_text`, creating the output directory as needed and replacing an existing file of that name. The [m1 CLI](../scripts/m1_run.py) defaults to `out/m1/`; callers may choose a different directory. The write is not an atomic temporary-file-and-rename transaction, and previous versions may survive in backups or snapshots.

The saved result contains aggregate utility/privacy measurements, statuses/reasons, counts, coverage, field names/transformation metadata, provenance, assumptions and limitations. It has no field for source rows, released rows, target identifiers or evaluator truth. The inspected default pipeline does not export the transformed row table. Identifier **column names** may appear in removal metadata; this is distinct from saving identifier values. Schema validation checks structure, not anonymity. The integration's identifier-name string check is not a general detector for source values or sensitive free text.

The [comparison CLI](../scripts/compare_results.py) reads saved JSON and writes requested HTML/Markdown, or prints Markdown when neither output path is supplied. It displays aggregate metadata and the input result **basename**, not the source Parquet path. These rendered pages are additional retained output copies. The m1 CLI prints aggregate metrics/statuses, a checksum prefix, code version and output path. Shell capture, job logs, notebooks and browser copies may retain such output. Error handling does not provide a general redaction guarantee; custom parameters, free-text metadata and unusually named output files must be reviewed before sharing.

There is no automatic small-cell suppression, aggregate disclosure approval, cross-release risk check, authentication or expiry applied to these files. Aggregate output is not automatically safe for every audience; low counts and combined releases can disclose information. Missing/unsupported evaluations must remain explicit, and measured privacy rates do not certify anonymity. Inference is unsupported and no combined score exists at the pinned commit. Consult [measurement caveats](analysis/measurement-caveats.md) for limitations on data meaning.

## Temporary files and retention

The inspected m1 and comparison code contains no explicit raw-data temporary-file, cache or intermediate-table write. This observation does not audit library internals, OS swap, core dumps, notebook checkpoints, editor recovery files, shell redirection, container volumes, downloads or backups. No automatic source/output deletion or retention timer is implemented. Source tables, pandas copies and truth exist in process memory during evaluation; users of `build_result` can keep their process alive after the call.

Use an explicit, agreed retention end point for the source, derived outputs and execution artifacts. Inventory copies by location and owner without printing row contents. Include the original shared checkout, any manually copied worktree data, download directories, custom output directories, rendered pages, notebooks, job logs and shared/exported copies. A worktree's clean Git status does not establish that ignored source/output files are absent.

## Manual deletion procedure (not executed here)

1. Agree the exact copies and retention scope with their owners. Confirm no other task still needs the shared source path from data setup. Stopping one worktree's work does not authorize removing another task's input, the Drive original or someone else's backups.
2. Stop or finish readers, writers, notebooks and background jobs that use those copies. Close relevant processes to release open file handles and in-memory tables. Merely deleting a filename while a process holds it open can leave its data accessible to that process.
3. Enumerate the specific local source copies, generated result JSON, rendered pages and any known temporary/log/export artifacts to be removed. Resolve symlinks deliberately: unlinking a symlink removes the link, not its target; do not mistake either operation for deleting other copies. Avoid blanket cleanup of a repository/worktree or shared `data/` tree.
4. Remove each approved ordinary file using the operating system's normal deletion mechanism. For a shell, the pattern `rm -- /absolute/path/to/an/approved-file` unlinks exactly that named path; replace the placeholder only after checking the inventory. Do not run it against the documented shared source without the agreed deletion scope. Remove empty owned directories separately if needed. This is a procedure, not an instruction to delete files during documentation work.
5. Verify the inventoried paths are absent, jobs have stopped and no intended copy was missed. Record locations/scope, time, operator and verification outcome without source values. Arrange deletion/expiry of backups, snapshots, synced copies, trash and remote shares with the owners who control them; record inaccessible or retained copies as limitations rather than claiming completion.

Normal unlinking is logical deletion, not verified physical sanitization. Open handles, hard links, filesystem snapshots, backups, swap and SSD behavior can preserve data beyond a removed pathname. File overwriting is not a portable assurance of secure erasure on those storage systems. If stronger erasure is required, the storage/system owner must use an appropriate verified procedure; this repository supplies none. Accidental Git inclusion also requires separate handling of history/clones, since deleting the current working-tree file does not remove historical objects. No deletion or secure-erasure claim is made by this account.
