Miksu ja Pate Elisa · Elina's questions 1 / 6
Elina, the product manager persona from Elisa's challenge brief

Elina · Product Manager, Elisa

Three questions she cannot ask today.

Where should Elisa focus product development: gaming or streaming?
Which apps should Elisa prioritise for network-quality improvements to reduce customer complaints?
Which base stations are overloaded and should get a capacity upgrade?

Our algorithm · TrimAndJitterV3

What happens to a row.

Before · original rows (fictional example)
TrimAndJitterV3
After · TrimAndJitterV3, same rows
Removed Multiplied by random noise Withheld: fewer than five alike rows Rare combination
Remove phone, SIM, device and station identifiers
Keep app, radio, region and the ten-minute window
Withhold combinations with fewer than five rows
Multiply every measurement by exp(Laplace(0, 0.05))
Release no subscriber alias
Removing IDs only1 in 3 subscribers still had a row unlike anyone else's.
Grouping 25 apps into 6Gaming and streaming merged. Question 1 gone.
Adding an aliasSame answers, and three known facts re-link 4 in 5 subscribers.

On the transformed data

Two of her questions, answered from the anonymised output.

Question 1

Focus product development on gaming or streaming?

5G medians

OriginalTransformed

Focus on Gaming: it is the worse-served experience (5G radio latency 114 ms vs 72 ms for Streaming). Same answer after.

Question 2

Which apps to prioritise for network-quality improvements?

Share of slow 5G downloads, top six

OriginalTransformed

Prioritise VPN and IM: they have by far the largest share of unusually slow downloads. Same ranking after.

Also intact after anonymisation

Both answers come from app × network groups — no subscriber identity needed.

Limits of the output

What this anonymised output cannot answer.

Question 3 · unavailable

Which base stations are overloaded and should get a capacity upgrade?

The station identifier is removed on purpose.

What else we give up, and why

No subscriber grouping

No alias. No heavy-user, churn or per-customer questions.

By design

Sparse groups lost

138 of 144 quality groups kept. Lost: Chat, VoIP and file transfer on 5G.

Side effect

Numbers distorted

IoT on 5G, share of laggy records: 36.2% → 44.1%.

Side effect

Sample limits

Fabricated times, randomised locations. No real congestion event shown.

Data

Measured on the same file · identifiers removed vs TrimAndJitterV3

Privacy measurement of TrimAndJitterV3.

Utility kept · identifiers removed → TrimAndJitterV3

Elina's analyst can, on this one output:

  • Compare gaming and streaming experience per network
  • Rank apps for network-quality improvements
  • Ask the next app × network question without a new release

Appendix · reproducible

TrimAndJitterV3 as one Python notebook.

What is in it

  • The whole algorithm as one pandas function (~25 lines)
  • Before/after on fictional rows
  • Bit-for-bit check against the pipeline on the full 1.1 M-row file
  • The four privacy benchmarks on the released table
  • Elina's three questions, answered from the anonymised output — and from the base data

Where

notebooks/TrimAndJitterV3.ipynb

github.com/konemall1/digital_sovereignty_hack_2026 · rendered outputs committed · pipeline id c15_window_k5_noise5

PYTHONPATH=src python notebooks/build_trim_and_jitter_v3.py re-executes it: same seed, same checksum, same numbers.

Appendix · Miksu ja Pate

Sources, classification, tests, provenance, handling.

Every number on the slides maps to a saved artifact below. Judges do not need to run anything: the artifacts are committed files.

A1 · Every number and where it comes from

A2 · Field classification (22 source columns)

Technical risk classes from docs/analysis/field-classification.md. No column is unconditionally non-identifying: every retained value stays attached to a row and can contribute to a fingerprint. Legal classes are provisional.

A3 · The transformation: TrimAndJitterV3 (configuration id c15_window_k5_noise5)

Definition in src/dsh/m1/configs.py, operations in src/dsh/m1/transform.py, applied in this order:

  • drop_fields = msisdn, imsi, imei, enb_id. Phone, SIM, device and station identifiers are removed from the released table.
  • time_coarsen = window. The supplied ten-minute event window is released as is. Region (province), application category and radio access type are released unchanged.
  • noise = {scale: 0.05}. Each of the 14 released measurement columns is multiplied, value by value, by exp(Laplace(0, 0.05)) from one seeded generator and clipped to [0, column maximum]. Multiplicative and unbounded, so not a ±5% band; no privacy budget is accounted, so not differential privacy.
  • k_suppress = 5 on the cell (time_start, province, application_category, radio_access_type): rows whose cell has fewer than five rows are withheld. 2,205 of 1,099,340 rows (0.2%). Five rows in a cell can belong to one subscriber.
  • pseudonym = false, app_coarsen = false, round = none.

A4 · Test assumptions

  • Singling out (singling_out_k_anonymity): released rows partitioned by the released categorical quasi-identifiers (window, region, application, radio type; station where released). A subscriber counts when at least one of their released rows has k = 1. Exact over the whole table; evaluator truth used only to count subscribers. Singled out is not identified.
  • Numeric fingerprint (numeric_fingerprint): 1,500 sampled raw observations; the attacker knows the row's categorical fields and its 14 measurements to ±1%. Reports unique candidates and, from evaluator truth, correct matches. Prosecutor model, perfect auxiliary knowledge.
  • Linkage: single-record linkage on (window, region, application), 500 sampled targets; alias-chaining only runs where an alias is released (c16: 78.8% unique candidates from three observations). Cross-release test relinks subscribers between two independent releases. Absence of an alias does not prove absence of linkage through other fields.
  • Inference (inference_application_category): class-majority rule; the application is called inferable when at least 90% of the rows sharing a subscriber's quasi-identifier class carry one application. One rule, one threshold, not every attacker.
  • Quality groups (experiments/mikael_app_quality): app × radio type × measurement cells with at least 30 valid records; p10/p50/p90 and the share of records beyond a fixed raw-file threshold (download ≤ raw p10, latency ≥ raw p90). A lost cell is unavailable, never zero. Normalised quantile error is a share of the cell's p90−p10 spread; tail-share error is in percentage points. Row-weighted, not person-weighted.

A5 · Provenance

  • Source file: the fabricated Elisa Parquet, SHA-256 36be13cea8c2ea9448317fb026c09de967242df06e7c00b8e6256fd89c48a214, 1,099,340 rows, 199,195 subscribers. Not in the repository.
  • Privacy and utility tests: scripts/m1_run.py --seed 42 at evaluator git:bbaf4ad for id_removal and c15_window_k5_noise5 (also c16, c17, c18). Utility and k-anonymity figures are exact over the full table; sampled attacks vary by a point or two across seeds.
  • Quality groups: experiments/mikael_app_quality/evaluate.py at commit c787395, seed 42; results in experiments/mikael_app_quality/results.json and RESULTS.md.
  • Alias cost (78.8%): c16_window_k5_noise5_key, same evaluator run. Grouping loss: c17_hour_groups_k5_noise10 reports the app traffic mix as unsupported.
  • Reading: docs/results-at-a-glance.md, docs/analysis/decision-business.md (latest section; earlier sections hold superseded figures), docs/analysis/reproduction.md, docs/analysis/measurement-caveats.md.
  • Elina, her question and the photo: slide 4 of Elisa's challenge deck (docs/sources/elisa-challenge.md, mockups/assets/README.md). Test categories: Elisa's Day 2 message citing EDPB Guidelines 02/2026.
  • Notebook implementing TrimAndJitterV3 and answering the three questions from the released table: notebooks/TrimAndJitterV3.ipynb (rendered outputs committed; built by notebooks/build_trim_and_jitter_v3.py).
  • Example rows on slides 2 and 4 are fictional. No source identifier appears in this deck.

A6 · Data handling: implemented and proposed

From docs/data-handling.md (inspected code, not a record of deletion or approval).

  • Implemented: identifiers are dropped inside the transformation; the evaluator holds the identity mapping only in process memory to score tests; saved results hold aggregate metrics, statuses and metadata, no rows and no identifiers; the source stays outside the repository in an ignored directory.
  • Not implemented: automatic source or output deletion, retention timers, workspace access control, cross-release accounting, small-cell approval for aggregates. Deletion is a documented manual procedure that has not been executed. Git ignore rules are not access controls.
  • Proposed: analysts work on the transformed output in a managed workspace rather than local downloads; one release per period; retention end point agreed per copy.

A7 · Sample limitations

  • Dates are fabricated (six windows ten minutes apart); locations were assigned by a random function; 81.5% of subscribers appear in several provinces within one window. No journeys, forecasts, real congestion events or causal effects of upgrades can be read from it.
  • Measurement units are as supplied and unvalidated; medians are shown in the file's own units.
  • Nothing here is a legal determination; no output is called anonymous.

Evidence and limitations