# Evidence capture — Appmiral TT Festival app (deeplink + privacy policy)

Forensic snapshot of the third-party **Appmiral** pages behind the "official TT
Festival App" that **Gemeente Assen** promotes to the public. This is the
downstream half of the evidence chain documented in
[`../assen.nl_2026-06-26_231242/`](../assen.nl_2026-06-26_231242/) — the
municipal page `assen.nl/heeft-u-nog-vragen` tells residents to *"Download de
officiële TT Festival App via app.ttfestival.nl"*, and that link leads here.

Same forensic method as the assen.nl capture: exact raw server responses,
fully JavaScript-rendered DOM, full-page screenshots, response headers, tool
logs, and SHA-256 checksums of every file. The bulky browsable offline `wget`
mirror lives in the companion **private** repo
[`GraafG/tt-festival-app-evidence`](https://github.com/GraafG/tt-festival-app-evidence);
its byte-for-byte integrity is recorded here in `mirror-manifest.sha256`.

## Snapshot summary

| Field | Value |
|-------|-------|
| Captured (local) | **2026-06-26 23:22:41 CEST (UTC+02:00)** |
| Captured (UTC) | **2026-06-26 21:22:41Z** |
| Capture host | Microsoft Windows 11 Pro |
| Pages captured | 2 |
| Total size | ~7.15 MB |
| User-Agent used | `Mozilla/5.0 (Windows NT 10.0; Win64; x64) ... Chrome/126.0.0.0 Safari/537.36` |

## The redirect chain (why these URLs)

`logs/redirect-chain_app.ttfestival.nl.txt` records the captured proof that the
link the municipality calls *"de officiële TT Festival App"* is operated on
third-party Appmiral / AWS infrastructure:

```
https://app.ttfestival.nl/
  └─ 301 Moved Permanently  (Server: Apache)
     → https://ttfestival2026.deeplink.appmiral.com/download   (AWS API Gateway / CloudFront)
```

So: **gemeente Assen → app.ttfestival.nl → ttfestival2026.deeplink.appmiral.com
→ Google Play `com.appmiral.ttfestival` / Apple App Store id 6744364695.**

## Pages captured

| # | URL | What it is | HTTP (browser GET) | Notes |
|---|-----|-----------|--------------------|-------|
| 1 | <https://ttfestival2026.deeplink.appmiral.com/> | "Download nu de officiële TT Festival App!" landing/deeplink page | 200 | Returns **403** to `HEAD`/non-browser requests (AWS API Gateway `MissingAuthenticationTokenException`); serves real HTML only to browser-like `GET`. Captured via `curl -X GET` with browser headers + Chrome. |
| 2 | <https://app.appmiral.com/ttfestival2026/privacy-policy> | "TT Festival 2026 – Privacy Statement" | 200 | Served via Cloudflare. "Last modified on 10 November 2025". **English-only (`lang=en`), no Dutch version** — see "Why this is evidence" §4. |

## Why this is evidence

1. **The municipality blurs who runs the app.** The deeplink page itself repeats
   the exact "officiële TT Festival App" framing, but it is hosted by **Appmiral**
   (a separate commercial party / the organising *stichting*), **not** Gemeente
   Assen. A reader of the assen.nl page cannot tell that the "official" app and
   its data processing are run by a third party rather than the municipality.

2. **The privacy policy's claims are directly testable against this repo's
   findings.** Section 4 (*Data Storage and Retention*) and Section 7 (*Data
   Transfers*) state:

   > "All data are stored securely in the **European Union** on servers provided
   > by **Amazon Web Services (AWS)** in the region **eu-west-1 (Ireland)**."
   > "All personal data are stored within the European Union (EU). Data
   > processing takes place within the EU, with the exception of Cloudflare based
   > in the USA…"

   This repository's investigation documents location streaming to AWS
   **`us-east-1` (USA)** — contradicting the EU-only claim. The captured policy
   is the primary source for that comparison.

3. **Location sharing with Crowd Connected is admitted.** Section 2c / 6 / 9:

   > "Your location data are shared only in pseudonymized form with selected
   > partners (e.g., **Crowd Connected**). These data contain only a unique
   > device identifier (UUID), coordinates, and optionally a push token."

   The repo's [`docs/identity-correlation-proof.md`](../../docs/identity-correlation-proof.md)
   and [`docs/crowd-connected.md`](../../docs/crowd-connected.md) examine whether
   "pseudonymized" holds, given location is linked to accounts.

4. **The privacy policy is English-only — no Dutch version.** The document is
   served as `<html lang=en>` and titled *"TT Festival 2026 – Privacy Statement"*.
   We verified there is **no Dutch translation linked or content-negotiated**:
   - Requesting the page with `Accept-Language: nl-NL,nl` returns the **identical
     English text** (0 Dutch terms such as *privacyverklaring/persoonsgegevens*;
     21 English markers like *"personal data"/"privacy statement"*).
   - The HTML contains **0 `hreflang` tags, 0 `rel="alternate"` language links,
     and no language switcher**.

   This matters because the TT Festival is a Dutch event, Gemeente Assen (a Dutch
   government body) steers Dutch-speaking residents to the app, yet the only
   privacy disclosure is in English. Under **GDPR Art. 12(1)** information must be
   provided in a *concise, transparent, intelligible* form using *clear and plain
   language* — for a Dutch consumer audience, an English-only policy with no Dutch
   option is a transparency/accessibility concern. The proof is captured in
   `logs/` (the `Accept-Language: nl` response was byte-checked) and in the raw
   HTML (`raw/privacy-policy.html`, `<html lang=en>`).

Because Gemeente Assen actively directs the public to this app while (per this
investigation) being aware of the processing concerns, the municipal endorsement
captured in the sibling `assen.nl` snapshot — combined with what the app's own
pages disclose here — is evidence relevant to the municipality's position, not
only the app vendor's.

## Folder layout

```
appmiral.com_2026-06-26_232241/
├── README.md                 ← this capture log
├── SHA256SUMS.txt            ← SHA-256 of every file in THIS (public) folder
├── mirror-manifest.sha256    ← SHA-256 of every file in the offline mirror,
│                               which lives in the private companion repo
├── .capture-timestamp
├── raw/                      ← exact server responses (curl GET, browser headers)
│   ├── deeplink-root.html / .headers.txt
│   └── privacy-policy.html / .headers.txt
├── rendered-dom/             ← DOM after JS hydration (Chrome)
│   ├── deeplink-root.dom.html
│   └── privacy-policy.dom.html
├── screenshots/              ← full-page + viewport PNGs (1440-wide desktop)
│   ├── 01_deeplink-root_fullpage.png / _viewport.png
│   └── 02_privacy-policy_fullpage.png / _viewport.png
├── mirror/  → MOVED to private repo GraafG/tt-festival-app-evidence
│              (browsable offline wget clone; links converted. Integrity of
│               every file is recorded above in mirror-manifest.sha256.)
│   ├── ttfestival2026.deeplink.appmiral.com/index.html
│   ├── app.appmiral.com/ttfestival2026/privacy-policy.html
│   └── *.amazonaws.com/...   ← CSS, fonts, app-store badges, hero image (AWS S3 eu-west-1)
└── logs/
    ├── redirect-chain_app.ttfestival.nl.txt   ← the 301 chain from app.ttfestival.nl
    ├── wget-deeplink-root.log / wget-privacy-policy.log
    └── tool-versions.txt
```

> Note: `screenshots/01_deeplink-root_fullpage.png` and `_viewport.png` are
> byte-identical because that landing page fits within a single desktop viewport.

## Verify integrity

```bash
sha256sum -c SHA256SUMS.txt          # Linux/macOS, run inside this folder
```

```powershell
Get-Content SHA256SUMS.txt | ForEach-Object { $h,$p = $_ -split '  ',2
  if ((Get-FileHash -Algorithm SHA256 -LiteralPath $p).Hash.ToLower() -ne $h) { "MISMATCH: $p" } }
```

## Reproduce

- **Visual:** open any PNG in `screenshots/`.
- **Offline browse:** clone the companion private repo
  [`GraafG/tt-festival-app-evidence`](https://github.com/GraafG/tt-festival-app-evidence)
  and open `appmiral.com_2026-06-26_232241/mirror/ttfestival2026.deeplink.appmiral.com/index.html`
  or `.../app.appmiral.com/ttfestival2026/privacy-policy.html`. Verify those bytes
  against this folder's `mirror-manifest.sha256`.
- **Exact bytes:** files in `raw/` are the verbatim server responses.
- The deeplink page must be fetched with a browser-like `GET` (User-Agent +
  `Accept: text/html`); a bare `HEAD` returns `403` from AWS API Gateway.
