A public research pilot by Airport51 · University partners invited
Your camera can see in the dark. Sort of.
Covered camera sensors still produce rare one-frame signals. Most are sensor noise or processing
artifacts; some may be caused by ionizing particles, including secondary particles created when cosmic rays
strike Earth's atmosphere. Radar51 is a privacy-first experiment designed to compare these signals across many
ordinary devices — the first step toward a planetary sensing
network Airport51 hopes to develop with university research partners. Camera frames stay on your device.
Only derived measurements are shared.
The public pilot isn't open yet. When it is, your scan will appear as an aggregated cell, never as an exact point.
Lab devices only. The three dots are Airport51's own hardware. No public participant data is shown, because none has been collected yet.
Coarse cells, on your device. If you share location, it's rounded to a coarse grid cell (roughly 10 km or larger) before anything leaves your device. Exact coordinates are never retained for public users.
Small-count hiding. Cells with fewer than three active participants stay hidden, and map updates are published with a delay — so a lone scan in a sparse area can't identify anyone.
Location is optional. Scans without location contribute to global totals but are not placed on the map. A broad region can be selected manually; location is never inferred from an IP address.
How it works
Three minutes. No images stored or uploaded.
A scan is the whole product: cover the lens, let the sensor stare into darkness, and watch it count.
STEP 01
Cover the lens
Tape, a finger, or just place your phone face-down-camera-up on the table. Radar51 works best when your camera sees nothing at all.
STEP 02
Scan for 3 minutes
The app watches the darkness and counts single-frame transients — tiny flashes no human would notice. Frames are processed in memory on your device and immediately discarded. Only derived measurements are uploaded.
STEP 03
Light up the map
Your contribution joins an aggregated map cell after the privacy threshold is met and the publication delay has passed. Exact locations are never shown. One scan is a data point; thousands could create an open cross-device dataset for studying how noisy, uncalibrated sensors behave across locations, devices, and time.
Stations
Got an old phone? Give it a second life.
That retired phone could become a dedicated Radar51 station. The browser pilot supports short scans; continuous station mode will require the Radar51 station app — built with wake-lock handling, thermal and battery monitoring, and scheduled observation windows, because a browser tab alone can't watch reliably around the clock.
Laptops work for scans too. If your webcam is already covered with a slider or tape — perfect. Don't change a thing.
“The only app that works better with your camera covered.”
Minimal info only: device type, region, power. Never a precise address or coordinates.
STATION · ATTIC-AUSTIN● SIMULATED PREVIEW
uptime................. 11d 04h
lens................... dark ✓
motion................. still ✓
raw transients/hr...... 263
classified candidates.. pending
baseline............... 259 ± 31
anomaly index.......... +0.1σ
images uploaded........ 0 — ever
Simulated preview — the station app is in development.
The science, honestly
What are we actually detecting?
Silicon meets sky
Camera sensors are silicon. Ionizing particles — including secondary muons produced when cosmic rays interact with the upper atmosphere — occasionally strike that silicon and leave a one-frame fleck of light. So do hot pixels, thermal noise, electronics, and local radioactivity. Physics projects like CREDO and DECO have published peer-reviewed research separating the two using phone cameras.
Bad sensors, good patterns
One device is a terrible instrument: noisy, uncalibrated, moody. That's the point. Radar51 tests whether many imperfect sensors, each compared against its own baseline, show patterns no single sensor could — across regions, devices, and time.
PLAIN LANGUAGE: Radar51 makes no safety claims, measures no dose, and issues no alerts. Most bright pixels are noise, not particles. We count sensor events, publish the aggregate data openly, and write up what we find.
DECO and CREDO pioneered smartphone particle detection and have collected millions of camera events. Radar51's experiment is a privacy-first network in which raw camera frames never leave public participants' devices — each device learns its own baseline and uploads only derived measurements.
No frames uploadedNo public-user camera frames ever leave the device. Only derived features and counts are shared.
Self-referenced stationsEvery station is compared against its own baseline — not against a universal number that no two cameras agree on.
Network over detectionPatterns across many devices and time matter more than any individual bright pixel.
Open by defaultAggregate methodology and data are published openly as the project develops.
PUBLIC MODE
· no frames uploaded
· derived features + counts only
· approximate, optional location
· open to everyone
CALIBRATED RESEARCH MODE
· Airport51 / university-controlled devices
· known cameras, controlled lens coverage
· full event frames where science requires
· formal calibration + environment metadata
The initiative
One experiment today. A planetary instrument tomorrow.
One device is a terrible sensor. A hundred million devices are a new kind of scientific instrument — not one giant telescope pointed at one spot, but a distributed network watching the whole Earth at once.
The dark-frame experiment is phase one. Later phases may combine dark-frame observations with external space-weather data and additional device sensors to investigate wider atmospheric and ionospheric correlations. That's a research question the network is designed to ask — not a capability we claim today.
INITIATIVE · ROADMAPv0.1
PHASE 01dark-frame network● IN PROGRESS
PHASE 02space-weather & ionosphere correlations○ RESEARCH QUESTION
PHASE 03sky-event triangulation○ PLANNED
PHASE 04planetary research network○ AMBITION
We want to build this with universities. Radar51 sits at the crossing of space physics, mobile sensing, AI, and privacy-preserving data science — and we're inviting research groups to shape the methodology, validate the data, and co-author what the network finds. No partnership exists yet; that honesty is the invitation.
Radar51 is an open experiment by Airport51 — an AI research port where models are tested, ideas get stress-flown, and projects like this one take off. The interesting part of Radar51 isn't the app; it's the pattern-finding behind it. We publish how it works as we go.
Choose your path
Three ways in.
Participate
Run the 15-second darkness test now, join the 3-minute public scans at launch, or give a retired phone a second life as a station.
The scanner launches soon. The launch list opens shortly — until the sign-up system is connected (double opt-in, no open or click tracking), reach us directly and we'll notify you at launch.
Radar51 temporarily reads covered-camera frames so the sensor can be analyzed. In public mode it does not save or upload photos or video — frames are processed in memory on your device and immediately discarded; only derived measurements are uploaded. Calibrated research nodes operated by Airport51 or universities follow a separate research protocol and consent process.
Does it know where I live?
Only roughly, and only if you allow it. Location is optional; when shared, it's rounded to a coarse grid cell (roughly 10 km or larger) on your device before anything is sent. Cells with fewer than three active participants are never shown on the public map, and exact coordinates are never retained.
Is this a radiation detector?
No. It's a research experiment counting sensor events. It is not a safety instrument and never will pretend to be one.
What does it cost?
Nothing. The data is published openly. Radar51 exists because Airport51 wanted to build it.
My phone is ancient. Is that a problem?
Not at all. Older phones can still be useful because Radar51 compares each device against its own baseline. Device age isn't automatically an advantage or disadvantage — the pilot will publish compatibility results by model.
Is a university involved?
Not yet — and we won't pretend otherwise. We're actively in conversation with research groups and our goal is to run Radar51 as a joint initiative with multiple universities. If that's you, write to us.
Version 0.1 (draft) · Radar51 is a research pilot by Airport51 · 5900 Balcones Drive STE 100, Austin, TX 78731, USA · research@airport51.ai
EFFECTIVE DEMO NOTICE. The 15-second browser demonstration processes covered-camera frames locally and uploads nothing. The remaining provisions on public submissions, location, retention, and open-data publication are draft rules for the future public pilot.
Radar51 asks people to point a covered camera at nothing and share what the sensor saw. That only works if the privacy design is stronger than a slogan. This page describes the rules the system is built to enforce. It is a draft: nothing is collected from the public until this policy is final and the pilot opens.
Camera frames
Public participant mode: camera frames are processed temporarily in memory and are never stored or uploaded.
Calibrated research mode: Airport51- or university-controlled research nodes may retain selected event frames under a separate research protocol, access policy, and consent process. This mode never applies to public participants' devices.
The 15-second browser demo uploads nothing at all — not even the transient count.
Exact location: precise coordinates are never uploaded and never retained for public participants.
What a full public scan will send
A single derived measurement packet (schema R51-OP/1) containing: observation duration, frames analyzed and missed, delivered resolution, test-quality verdict, per-event derived features (area, length, width, peak z-score, timing — never pixels), software versions, and an optional coarse location cell. You can inspect the exact packet before it is sent, and choose share, share without location, save locally, or cancel and delete.
Location rules
Location is optional. Scans without location contribute to global totals but are not placed geographically. Participants may optionally select a broad region manually. Radar51 does not infer observation location from an IP address.
When shared, location is rounded on your device to a coarse grid cell of roughly 10 km or larger before anything is sent.
Cell size grows in sparsely populated areas; a fixed radius is not equally private everywhere.
Public cells require at least three distinct participants — an absolute minimum, not a universal rule. Radar51 may require a higher threshold, a larger cell, or a longer delay for sparse areas, persistent stations, repeated observations, or combinations of metadata that raise re-identification risk. Publication is delayed by at least 24 hours.
Cells that appear only once are suppressed. Protection relies on coarse cells, delay, participation thresholds, dynamic cell sizing, and suppression; if a formal statistical-noise method (e.g. differential privacy) is added later, its exact parameters will be published before use.
Server logs and IP addresses
Web servers see network connections regardless of what an app uploads. Radar51's own servers will truncate IP addresses at ingestion, keep no linkage between IP and observation packets, retain access logs no longer than 7 days, and never use logs for analytics or profiling. These rules also depend on upstream processors — hosting, CDN, firewall, and email providers — which may log connections before our application sees them. The final policy will name each processor and its configuration; where a processor cannot meet a rule, this policy will say so explicitly. No third-party analytics, no advertising trackers, no fingerprinting. Fonts and all assets are served first-party.
Email
When the launch list is connected, it will use double opt-in, with open tracking and click tracking disabled. Unsubscribe will remove the address permanently, and addresses will never be shared or matched against observation data. Until then, people may contact Airport51 directly by email.
Correction and withdrawal
Before an observation is included in a public data release, the participant may request its withdrawal via research@airport51.ai. After publication, Airport51 can remove it from future hosted releases and recompute future aggregates, but cannot guarantee removal from copies already downloaded by third parties. Station keys can be revoked by their owner at any time.
Summary in one sentence: public participants' frames stay on their device, location is coarse and optional, small counts are hidden, logs are minimized and short-lived, and you can see exactly what would be sent before anything is sent.
This draft will be finalized before any public data collection begins. Substantive changes will be listed in the public changelog.
Radar51 · Airport51 research pilot · comments to research@airport51.ai
Radar51 measures single-frame bright transients on covered consumer camera sensors and tests whether patterns emerge across many devices. This document describes what is measured, how validity is decided, and — deliberately at equal length — what the method cannot claim.
1. What is measured
With the lens covered, a camera sensor should see nothing. In practice it produces a noise floor plus rare bright transients. Sources include thermal and read noise, hot and warm pixels, camera ISP behavior, local radioactivity, and ionizing particles — including secondary particles (mostly muons) from cosmic-ray air showers, as demonstrated by projects such as DECO and CREDO. Radar51 counts and characterizes transients; it does not, in the browser pipeline, classify their physical origin.
2. Pipeline
Darkness gate. The mean frame luminance must stay below a darkness threshold for a sustained period before measurement begins.
Temporal per-pixel calibration. A short frame series is collected. For every pixel, the temporal median and temporal median absolute deviation (MAD) are computed. Each pixel gets its own baseline and noise estimate; there is no universal brightness threshold. Pixels far above the global baseline are pre-masked as hot.
Transient detection. A candidate pixel exceeds its own median + max(k·MAD·1.4826, floor) threshold in the current frame but not the previous one. Persistently bright pixels are masked as hot (with counters that reset, so intermittent pixels are not permanently condemned).
Clustering. Candidates are grouped by 4-connectivity. Per cluster: area, bounding-box length and width, peak per-pixel z-score, edge distance, and timing. Oversized clusters mark the frame as junk rather than as events, and frames containing more than three separate clusters are rejected whole as ambiguous — many simultaneous clusters are more likely a processing artifact or light disturbance than multiple particles, and nothing is cherry-picked from them.
Leak rejection. Whole-frame leaks (mean rise) and localized leaks (fraction of bright pixels) return the run to the darkness gate and are logged as restarts.
Validity verdict. Every run is graded before any count is reported (section 3).
3. Test validity
A transient count without a quality assessment is not a measurement. Every run receives one of four verdicts:
Verdict
Triggered by
Valid
Full duration observed, stable baseline, no leaks, adequate frame rate, few missed frames.
Valid with limitations
Minor leaks with recovery, >2% missed frames, low frame rate, several junk frames.
Inconclusive
Repeated leak restarts, baseline drift during the run.
Invalid
Page hidden (tab switch, minimize, screen lock), camera stream muted or ended, resolution below minimum, frame rate below 10 fps, >30% frames missed. No count is reported.
Frame delivery is tracked with requestVideoFrameCallback metadata (presentedFrames), giving a defensible observed-duration and missed-frame measurement.
4. Two modes
Public mode: no frames uploaded ever; derived features and counts only; coarse optional location. Calibrated research mode: Airport51- or university-controlled devices, known camera models, controlled lens coverage, environmental metadata, and full event frames where scientifically required. Public data builds the network; calibrated data validates it.
5. Known limitations
This list is part of the methodology, not a footnote. Claims that ignore it are wrong.
The browser pipeline detects bright transients, not particles. No physical classification is performed client-side.
Consumer camera ISPs denoise, sharpen, and compress in ways that are undocumented and device-specific. Some real events are certainly destroyed; some artifacts certainly survive.
Uncontrolled temperature, battery state, and sensor age shift noise floors between and within runs.
Browsers may adjust exposure and gain within accepted constraints; manual sensor control is rarely available on the web platform.
Short scans (15 s – 3 min) are dominated by noise statistics; genuine particle candidates on a single small sensor are expected at rates of a few per day, not per minute (cf. DECO's published experience).
Event morphology at consumer resolutions is coarse; browser-mode cluster features are indicative, not classificatory.
Participation density, device-model mix, and run duration confound any naive spatial comparison of raw counts. Coverage and baselines must be normalized before anomaly claims.
A browser tab is not a reliable continuous instrument; continuous stations require the planned native station app.
Nothing in the current dataset demonstrates ionospheric or space-weather sensitivity. That is a research question for later phases, not a capability.
6. Versioning and provenance
Every observation records schema, detector, classifier, and calibration versions plus browser family and delivered camera settings (see R51-OP/1). Classifications are never overwritten: reclassification by a newer model is appended and linked to the same observation, so "classified as noise by model 0.4, reclassified as candidate by model 0.8" is a queryable fact.
7. References
Vandenbroucke, J., et al. (2016). Measurement of cosmic-ray muons with the Distributed Electronic Cosmic-ray Observatory, a network of smartphones. Journal of Instrumentation 11, P04019. DOI: 10.1088/1748-0221/11/04/P04019
Frames with more than three clusters are now rejected whole as ambiguous instead of accepting the first three by traversal order; a separate event_list_truncated flag reports when the 50-record event list caps out.
2026-07
browser-demo-0.6.1
Frame-accounting fixes (frames skipped while processing counted separately from camera-missed frames); raw cluster count separated from accepted event count with an explicit truncation flag; 30-frame calibration; processing-resolution ceiling (~960×540) with delivered resolution recorded separately; Worker/canvas failure handling produces an invalid verdict instead of a stall.
University research groups: this draft is explicitly offered for critique. The fastest way to improve it is to tell us where it is wrong — research@airport51.ai.
Version 0.1 (draft) · Radar51 · Airport51 · research@airport51.ai
Radar51's value is the dataset and the method, not the app. Both will be open. This page states the policy in advance so it can be judged — and held against us — before the first byte of public data arrives.
What will be published
Aggregated observation data: per-cell, per-time-window counts and quality metrics, following the privacy rules (≥3 participants per cell, ≥24 h delay, small-count suppression).
Derived event features per R51-OP/1: morphology, timing, z-scores — never camera frames from public participants.
The full methodology, calibration procedures, and every classifier version with its change history.
Negative results. A month in which nothing interesting happened is a publishable month.
What will never be published
Public participants' camera frames (they are never uploaded in the first place).
Exact locations, raw IP-derived data, or anything enabling re-identification of a participant.
Cells or time windows that fail the small-count suppression rules.
Format and license
Data releases will be versioned, checksummed files (JSON/CSV/Parquet) under an open license — proposed: CC BY 4.0 for data, with the analyzer source under an OSI-approved license. Each release will carry a machine-readable schema and a Dataset JSON-LD description. Classifications are append-only: newer models add classifications, they never silently rewrite old ones.
Default map view
The first public map will show observation coverage (valid device-minutes, participation, quality) — not raw event intensity, which mostly maps participation density and noisy phone models. A baseline-adjusted anomaly layer comes later, only after per-device normalization is validated in the calibrated pilot.
Status today: three Airport51 lab devices, zero public observations, no dataset. This page exists so the rules predate the data.
Version 1, draft 0.1 · July 2026 · Radar51 / Airport51 · research@airport51.ai · example packet
R51-OP/1 defines a privacy-preserving, versioned, signable measurement packet for distributed sensor observations. The first application is dark-frame camera transient detection, but the envelope is sensor-agnostic by design: the long-term product is an open protocol for turning ordinary sensors into auditable research observations.
Design principles
No raw sensor frames from public participants. Only derived features travel.
Quality before quantity. Every packet carries a validity verdict; invalid observations report no counts.
Version everything. Schema, detector, classifier, calibration, and privacy transformation are all versioned per packet.
Append-only classification. New models add classifications linked to the same observation; nothing is overwritten.
Inspectable before sending. Clients must be able to show the user the exact packet prior to upload, with share / share-without-location / save-locally / cancel options.
Observation packet (R51-OP/1-draft-0.1)
Field
Type
Notes
schema_version
string
"R51-OP/1-draft-0.1"
detector_version
string
e.g. "browser-demo-0.6.2", "station-android-1.0.2"
classifier_version
string | null
null when no classification was performed
calibration_version
string
calibration procedure identifier
privacy_version
string
version of the location-coarsening / suppression rules applied
station_mode
string
public | public-demo | station | research-node | sample-illustration
browser
object
family + major_version only. Never a full user-agent or fingerprint.
observation_ms
int
validated observed duration
frames_analyzed
int
frames actually processed
camera_frames_missed
int
from presented-frame metadata deltas (camera delivered, compositor missed)
frames_skipped_while_processing
int
camera delivered a frame while the analyzer was busy; counted separately from missed
delivered_resolution
[int,int]
from track.getSettings(), not the request
processing_resolution
[int,int]
analysis resolution after the memory-safety ceiling (~960×540); equals delivered when no downscale
effective_fps
float
frames_analyzed / observed seconds
camera_settings
object
width, height, frame_rate, facing_mode as actually delivered
all sub-threshold-area clusters observed, including those in rejected frames
accepted_event_count
int
clusters accepted as events. Frames with more than three separate clusters are rejected whole as ambiguous (counted in junk_frames and ambiguous_frames) — clusters are never cherry-picked from a crowded frame.
ambiguous_frames_rejected
bool
true when at least one frame was rejected for cluster multiplicity
event_list_truncated
bool
true when the per-packet event-record cap (50) was reached, so accepted_event_count may exceed the records retained
coarse_location_cell
string | null
grid cell ID ≥ ~10 km, computed on-device; null = not shared. Never inferred from IP.
events
array
see event record below; empty for invalid tests
uploaded
bool
whether this packet was actually transmitted; always false for demo builds
note
string | null
free-text annotation; demo builds use it to state the packet was never sent
Event record
Field
Type
Notes
time_offset_ms
int
from validated scan start
area_px
int
connected-component size (4-connectivity)
length_px
float
bounding-box major dimension
width_px
float
bounding-box minor dimension
orientation_deg
float | null
null when below the resolution needed to estimate it
No pixel values, no frame data, no timestamps convertible to absolute wall-clock location, no device identifiers.
Signing envelope (planned, not yet implemented)
Each packet is wrapped in a signed envelope — the "Proof of Observation": a payload hash (SHA-256), an Ed25519 signature, and a key ID. Public one-time scans sign with a rotating pseudonymous key generated locally, never linked to a person. Dedicated stations may opt into a stable station key, controlled and revocable by the owner. The server appends receipt time, packet hash, server signature, software acceptance status, and validation flags. This does not prove a device behaved honestly; it proves the packet was not altered after submission and makes the custody chain inspectable — the honest limit of what client signing can claim.
Classification records (append-only)
A classification record references an observation by hash and adds labels (noise | hot-pixel | leak | candidate) with confidences and a classifier version. A later model adds a new record referencing the same observation. History is never rewritten: "classified as noise by model 0.4, reclassified as candidate by model 0.8" must remain a queryable fact.
Versioning rules
Schema changes bump the draft number; breaking changes bump the protocol name (R51-OP/2).
Servers must accept and archive packets from older detector versions, flagging them with their acceptance status rather than rejecting silently.
The privacy-transformation version must change whenever coarsening or suppression rules change, so any release of aggregates can state exactly which rules produced it.
Open questions for reviewers
Is the event feature set sufficient for morphology-based reclassification without frames? What is missing?
Minimum viable anti-abuse posture for unauthenticated public packets?
Should coarse_location_cell use an existing scheme (e.g. S2 / H3 at fixed coarse levels) for interoperability? Current lean: H3, resolution ≤ 5.
Rotating-key schedule: per-scan, daily, or per-session?
A complete, valid observation packet with illustrative values. Generated from data embedded in this page — no separate file exists on the server.
SAMPLE DATA — no camera used
15-second darkness test
Cover your camera completely — tape, a finger, or place the phone face-down-camera-up on the table. On a laptop, close the webcam slider or hold a finger over it.
No photos or video files are stored or uploaded. Camera frames are processed temporarily in your browser and immediately discarded — nothing leaves this page, not even the count.
DEMO: darkness & transient detection only — not the full scientific classifier.
Waiting for darkness…
Still seeing light. Cover the lens fully.
light level: —
Calibrating this camera's dark baseline…
Collecting a frame series to compute a per-pixel temporal baseline — results are judged against this device, not a universal number. Rapid demonstration calibration; full public scans will use a longer calibration period.
# R51-OP/1 — Radar51 Observation Protocol, version 1 (DRAFT)
Status: draft 0.1 · July 2026 · Radar51 / Airport51 · research@airport51.ai
This protocol is offered for public review before any public data collection begins.
## Purpose
R51-OP/1 defines a privacy-preserving, versioned, signable measurement packet for
distributed sensor observations. The first application is dark-frame camera
transient detection, but the envelope is sensor-agnostic by design: the long-term
product is an open protocol for turning ordinary sensors into auditable research
observations.
Design principles:
1. **No raw sensor frames from public participants.** Only derived features travel.
2. **Quality before quantity.** Every packet carries a validity verdict; invalid
observations report no counts.
3. **Version everything.** Schema, detector, classifier, calibration, and privacy
transformation are all versioned per packet.
4. **Append-only classification.** New models add classifications linked to the same
observation; nothing is overwritten.
5. **Inspectable before sending.** Clients must be able to show the user the exact
packet prior to upload, with share / share-without-location / save-locally /
cancel options.
## Observation packet (R51-OP/1-draft-0.1)
| Field | Type | Notes |
|---|---|---|
| `schema_version` | string | `"R51-OP/1-draft-0.1"` |
| `detector_version` | string | e.g. `"browser-demo-0.6.2"`, `"station-android-1.0.2"` |
| `classifier_version` | string\|null | null when no classification was performed |
| `calibration_version` | string | calibration procedure identifier |
| `privacy_version` | string | version of the location-coarsening / suppression rules applied |
| `station_mode` | string | `"public"` \| `"public-demo"` \| `"station"` \| `"research-node"` \| `"sample-illustration"` |
| `browser` | object | `family` + `major_version` only. Never a full user-agent or fingerprint. |
| `observation_ms` | int | validated observed duration |
| `frames_analyzed` | int | frames actually processed |
| `camera_frames_missed` | int | from presented-frame metadata deltas (camera delivered, compositor missed) |
| `frames_skipped_while_processing` | int | camera delivered a frame while the analyzer was busy; counted separately from missed |
| `delivered_resolution` | [int,int] | from `track.getSettings()`, not the request |
| `processing_resolution` | [int,int] | analysis resolution after the memory-safety ceiling (~960×540); equals delivered when no downscale |
| `effective_fps` | float | frames_analyzed / observed seconds |
| `camera_settings` | object | `width`, `height`, `frame_rate`, `facing_mode` as actually delivered |
| `camera_capabilities` | string | capability probe result: `"probed"` \| `"unavailable"` \| `"constraints-rejected"` |
| `test_quality` | string | `"valid"` \| `"valid-with-limitations"` \| `"inconclusive"` \| `"invalid"` |
| `quality_flags` | object | `light_leak_restarts`, `junk_frames`, `ambiguous_frames`, `baseline_drift`, `hidden_page`, `stream_interrupted` |
| `baseline` | object | `mean`, `noise_median` (temporal per-pixel MAD summary) |
| `raw_cluster_count` | int | all sub-threshold-area clusters observed, including those in rejected frames |
| `accepted_event_count` | int | clusters accepted as events. Frames with more than three separate clusters are rejected whole as ambiguous (counted in `junk_frames`) — clusters are never cherry-picked from a crowded frame. |
| `ambiguous_frames_rejected` | bool | true when at least one frame was rejected for cluster multiplicity |
| `event_list_truncated` | bool | true when the per-packet event-record cap (50) was reached, so accepted_event_count may exceed the records retained |
| `coarse_location_cell` | string\|null | grid cell ID ≥ ~10 km, computed on-device; null = not shared |
| `events` | array | see below; empty for invalid tests |
| `uploaded` | bool | whether this packet was actually transmitted; always `false` for demo builds |
| `note` | string\|null | free-text annotation; demo builds use it to state the packet was never sent |
### Event record
| Field | Type | Notes |
|---|---|---|
| `time_offset_ms` | int | from validated scan start |
| `area_px` | int | connected-component size (4-connectivity) |
| `length_px` | float | bounding-box major dimension |
| `width_px` | float | bounding-box minor dimension |
| `orientation_deg` | float\|null | null when below the resolution needed to estimate it |
| `peak_z_score` | float | (peak luminance − pixel temporal median) / pixel noise estimate |
| `persistence_frames` | int | 1 = single-frame transient |
| `edge_distance_px` | int | distance of cluster to nearest frame edge |
No pixel values, no frame data, no timestamps convertible to absolute wall-clock
location, no device identifiers.
## Signing envelope (planned, not yet implemented)
Each packet is wrapped in a signed envelope — the "Proof of Observation":
{
"payload": { ...observation packet... },
"payload_hash": "sha256:...",
"signature": "ed25519:...",
"key_id": "r51k_...",
"key_class": "rotating-pseudonymous | station-stable"
}
- Public one-time scans sign with a **rotating pseudonymous key** generated
locally; it is never linked to a person and rotates on a short schedule.
- Dedicated stations may opt into a **stable station key**, controlled and
revocable by the owner.
- The server appends: receipt time, packet hash, server signature, software
acceptance status, and validation flags.
This does not prove a device behaved honestly. It proves the packet was not
altered after submission and makes the custody chain inspectable — which is the
honest limit of what client signing can claim.
## Classification records (append-only)
{
"observation_ref": "sha256:...",
"classifier_version": "cls-0.8.0",
"classified_at": "2026-09-14T00:00:00Z",
"labels": [{"event_index": 0, "label": "noise|hot-pixel|leak|candidate", "confidence": 0.87}]
}
A later model adds a new record referencing the same observation. History is
never rewritten: "classified as noise by model 0.4, reclassified as candidate by
model 0.8" must remain a queryable fact.
## Versioning rules
- Schema changes bump `r51-observation-0.x`; breaking changes bump the protocol
name (R51-OP/2).
- Servers must accept and archive packets from older detector versions, flagging
them with their acceptance status rather than rejecting silently.
- The privacy transformation version must change whenever coarsening or
suppression rules change, so any release of aggregates can state exactly which
rules produced it.
## Open questions for reviewers
1. Is the event feature set sufficient for morphology-based reclassification
without frames? What is missing?
2. Minimum viable anti-abuse posture for unauthenticated public packets?
3. Should `coarse_location_cell` use an existing scheme (e.g. S2 / H3 at fixed
coarse levels) for interoperability? (Current lean: H3, resolution ≤ 5.)
4. Rotating-key schedule: per-scan, daily, or per-session?
*Example packet: see the #protocol-example view on radar51.com.*