ADR-0007: Hand-off to a phone through a passive NFC tag

Context

Rafa: "For the recording transfer the MVP can probably do an airdrop or something to phones as a .txt file or notes? … think about the most basic wireless way to transfer to a phone while keeping the device basically offline."

Options

Option Device transmits? Phone side Verdict
AirDrop yes (Apple's proprietary Wi-Fi link) native Not possible without Wi-Fi hardware and Apple's protocol
Bluetooth LE yes app needed Brings back an always-available radio
USB-C cable no needs an adapter/app Kept for debug only
Data over sound speaker needed app The device doesn't speak
Blinking the LEDs into the camera no custom web page Charming but slow and finicky; revisit for v02
Passive NFC tag (ST25DV64KC) no — the phone powers the tag native on iPhone XS+ and Android; opens a link Chosen

Decision

Consequences

# ADR-0007: Hand-off to a phone through a passive NFC tag

- **Status:** accepted for v01 (Rafa, 2026-10-12); the read button is replaced by holding the eye (ADR-0013)
- **Date:** 2026-10-12
- **Amends:** ADR-0001 (no radio), ADR-0004 (physical access only)
- **Requirements touched:** P-09, P-12, S-08

## Context
Rafa: "For the recording transfer the MVP can probably do an airdrop or something to phones as a .txt file or notes? … think about the most basic wireless way to transfer to a phone while keeping the device basically offline."

## Options
| Option | Device transmits? | Phone side | Verdict |
|---|---|---|---|
| AirDrop | yes (Apple's proprietary Wi-Fi link) | native | Not possible without Wi-Fi hardware and Apple's protocol |
| Bluetooth LE | yes | app needed | Brings back an always-available radio |
| USB-C cable | no | needs an adapter/app | Kept for debug only |
| Data over sound | speaker needed | app | The device doesn't speak |
| Blinking the LEDs into the camera | no | custom web page | Charming but slow and finicky; revisit for v02 |
| **Passive NFC tag (ST25DV64KC)** | **no — the phone powers the tag** | **native on iPhone XS+ and Android; opens a link** | **Chosen** |

## Decision
- A dynamic NFC tag on the device's I2C bus, under the tail's roof. The device writes one NDEF URI record into the tag's EEPROM; the phone's field powers the tag and reads it.
- **RF side disabled by default** (ST25DV RF-disable register). It is enabled only while the read button is held, for at most 10 s; then the tag is wiped.
- The note travels in the URL **fragment**: `https://<reader>/#g1.<base64url(deflate)>`. Browsers never send the fragment to the server, so the reader page (`v01/reader/index.html`) is a static file that decodes it locally and offers Share → Notes, Save .txt, or Copy. It removes the fragment from the address bar after reading.
- The tag holds 8 KB. Export packs outcomes first, then gist, then attributed, and drops the highest-resolution material first if it doesn't fit (`firmware/goldfish/handoff.py`).

## Consequences
- "Basically offline" holds: nothing on the device can initiate a transmission, and the tag is inert unless a person is holding the button and a phone is touching the tail.
- Once on the phone, the note is outside Goldfish's control (memo, belief 4). The reader page says so.
- The reader page needs a home on an HTTPS domain. Candidates: Cloudflare Pages or GitHub Pages. Not deployed yet.
- Certification: a passive tag with no transmitter of its own; confirm treatment with the EMC lab before DVT.
- Register addresses in `st25dv.py` must be verified against ST's datasheet before first use.