Plain answers to the questions that come up most, written so they hold up when quoted out of context — by a person skimming, or by an AI assistant answering on our behalf. Every answer says what is real today and links to the doc that proves it.
Vocabulary you don't recognize: the glossary. Full navigation: the docs map.
SecuraCV is open-source video and sensor infrastructure that outputs semantic events — "large object crossed boundary," "presence in restricted zone" — in a signed, hash-chained log, instead of a pile of searchable footage. The platform is SecuraCV; the device is called a Canary; the company is Errer Labs. → why witnessing matters · the whitepaper
A watcher keeps footage and can later be asked who was in it. A witness keeps a checkable record of what happened and structurally cannot answer who. The promise isn't that tampering is impossible — it's that tampering becomes visible. → the brand doc
Both, and either alone. The witness kernel (src/) is a Rust
daemon you can point at cameras you already own (any camera that serves an
RTSP stream, USB, or via Frigate). RTSP decoding is a non-default build feature
(rtsp-ffmpeg / rtsp-gstreamer; RTSP setup), and there is no
ONVIF discovery or control code, only the camera's RTSP stream. A Canary is a small ESP32-based device running our firmware. Many
people run just one or the other. → the full stack
Three audiences deliberately: makers who print and flash their own; buyers who want a pre-flashed kit and a QR code; and the people who can't build their own — elders, renters, the non-technical. → the brand doc
Apache-2.0, inbound=outbound with a DCO. The trademarks ("SecuraCV," the
Canary marks) are protected separately, and the "Works with SecuraCV" badge
is free for anyone to earn. → LICENSE ·
LICENSING.md · TRADEMARK.md ·
legal posture
No — and it can't. There is no face-recognition code in the codebase to
enable or disable. The same is true of license-plate reading, gait analysis,
person re-identification, and demographic (age/gender/race) estimation. The
object classes the system can emit are Person, Vehicle, Animal, Package
(plus Unknown, for a detection the backend could not class) — not Face,
not LicensePlate. This is Invariant II, and adding any of it is a rejected
pull request, not a configuration change.
→ spec/invariants.md · why not even a Face ID-style
"recognize only my family," and what the research recommends instead:
Face ID without a face at the camera
Not through the normal path — there isn't one. Raw frames live in a short
buffer with no public accessor (Invariant I). The only way to raw media is
break-glass: a time-bounded, audited unseal that requires n-of-m trustee
approvals. No single person can do it alone — not the owner, not us.
→ spec/break_glass.md ·
why exports work this way
You run break-glass with your trustees. You configure the quorum up front and rehearse it before you need it (the Lab has an Operator's Bench for exactly this rehearsal). An export ships as a self-verifying evidence envelope a recipient can check without our tools. → the operator guide · evidence lifecycle
No. Logs stay local, there is no remote indexing and no telemetry (Invariant
IV). No account is required to run it. Dependencies that phone home are
forbidden by policy. → AGENTS.md dependency policy
The one honest footnote on the kernel is the iPhone app — see the next question. The other footnote is the Canaries themselves: a networked Canary talks to the MQTT broker you point it at, fetches a small signed update manifest once a day (no identifier rides on the request, and nothing installs unless you press Install or opt into Auto Update), and a display syncs its clock over SNTP and — only if you switch it on at the glass, on a display that has never had a hub configured — fetches an anonymous weather forecast. A Canary WAP used as its own access point makes no outbound connection at all. Every one of those paths is listed in the security model, with the host test that pins its request shape where one exists (SNTP has none); none reaches us, because there is nothing of ours to reach. The desktop Flasher and Lab fetch their own updates, and any image you choose to flash, from the project's public GitHub releases.
It's a fair thing to ask, so here is the whole of it. Two things need to reach you when you aren't standing next to a Canary: your fleet list (so your iPad knows what your iPhone paired) and an alert when you're away (iOS will not keep a connection open in your pocket — instant push on iPhone must travel through Apple, which is a platform fact, not our choice).
Those two things ride your own iCloud private database. Not ours — we have
no server at all. What goes in is a fleet list with no secrets in it, and a wake
that carries one coarse word (tamper / integrity / offline / pattern)
and nothing else: no device name, no room, no time of ours, no event content.
The sentence you actually read is composed on your phone from your own data,
which is why a locked screen only ever says "Something needs your attention."
What never goes in: footage, frames, anything reversible to them, event content, precise times, or any key or token. Those are Invariants I and III, and they are not negotiable for convenience.
There is now a third thing, and it is the only one another person can see. If you ask someone to be told when an alarm of yours goes unanswered, they are invited to one folder in your iCloud that holds nothing but "an alarm wasn't answered" — and the folder is the boundary, so they cannot see your Canaries, their names, your history, or any footage. Not because we filter it: because that is all they were invited to. Their phone writes the words they read; even the sentence never travels. You invite people through Apple's own sharing sheet, and removing them is one tap.
It's opt-in and reversible — away alerts stay off until you arm an "Anywhere" rule, and turning them off deletes the subscription outright; nobody else is ever told anything until you invite them. Not signed into iCloud at all? The app works locally; iCloud is convenience, never a gate. → iCloud as the backend we don't have, which also argues the parts that are imperfect rather than only the parts that are good
Not by default. Every Canary with a broker link ships it as plain MQTT,
so the broker username and password cross your own LAN in the clear until
you say otherwise. (The flagship's ESP32-CAM, WROOM and Freenove ports are
built without one.) Every one of those links can be provisioned for TLS
except the Canary Display nightstand-c6's, which is built plain-only and
refuses every TLS mode. On the rest, TLS is verified against a CA
certificate you supply; Canary Display, Canary Sense, Canary Vision and the
flagship firmware/canary build can instead pin the broker certificate's
SHA-256 fingerprint, and the Canary WAP is CA-only. (A fourth mode, lab,
skips verification — it is chosen by name and warns on every connect, and
the WAP refuses it.) You set the mode from the Broker encryption select in
either flasher's broker block (Canary Display, Sense and Vision), on the
WAP's own /mqtt page, or in the flagship's setup wizard or its
bearer-gated POST /api/mqtt/config. Once a flagship is set up, its pages
carry its API token only to a request that already sends it, after one tap
of its BOOT button (one tap, one page load), or over the Canary's own WiFi,
which broadcasts only while the Canary is off your home network; reached by
a public DNS name, they get no token and a 403
(Step 3 has the
whole rule). The hub plan adds the broker's TLS listener with
--with broker_tls, from a certificate you already have. An incomplete
setup — a CA mode with no CA, a pin mode with no pin — refuses to connect
rather than quietly downgrading to plain.
Honest status: compile-tested by CI and host-tested (the decision, both flashers' forms, the wizard, the flagship's page-token rule); not yet run against a TLS broker on hardware, and the page-token rule not yet bench-tested. → firmware variant audit · Home Assistant setup, Step 3
Events are bucketed into 10-minute windows so the log can prove that something happened without becoming a minute-by-minute diary of when you leave the house. Precision is treated as a privacy cost, not a free feature. → timestamping
No, twice. There is no bulk search and no identity selector (Invariant VII), and
a new detection rule cannot be applied to already-recorded data — the
ReprocessGuard checks the ruleset hash (Invariant VI). You cannot decide in
March to have been surveilling in January.
Each event carries a hash of the previous event plus an Ed25519 signature, so any deletion or edit breaks the chain and verification fails loudly. You can verify offline, with our verifier or your own. → log verification
A compromised host. We write that down rather than gloss it: if an attacker owns
the machine the kernel runs on, guarantees that depend on that machine no longer
hold. What survives and what doesn't is documented.
→ the root paradox ·
spec/threat_model.md
The number of requests per run is constant (every subject to every TSA, an empty ledger anchored over a fixed sentinel), so the count carries no signal. The TSA does see the digests, so it can notice a receipt-ledger digest that stops repeating; anchoring a single per-run ledger-heads leaf (planned with the Merkle tree) removes that. → timestamping
No. Treat it as prototype software under active development. Frame
isolation, hash-chained logging, and break-glass quorum are implemented and
exercised in CI. Much of the firmware is CI-verified, not yet
hardware-verified — v1 is deliberately held until it's proven on real
devices. Boards are individually labeled verified or compile-tested so you
can tell which is which.
→ v1 roadmap · launch review ·
bench-test runbook
No certification claims — no FIPS, no Common Criteria. Selling the radios legally requires FCC work that is not finished, and a published third-party security audit is on the list as worth more than any feature for a trust product. Until those land, the copy stays present-tense about what's real.
Which is why we sell plastic, not radios. The plans and the firmware are free, and the only physical thing on offer is a printed enclosure set — a plastic shell is not a radio, so it carries no equipment authorization at all. You buy your own board, flash our firmware from the browser, and build it. Building a handful for your own use is expressly fine under 47 CFR 15.23, which asks builders to use good engineering practice rather than to file anything.
We don't make claims about your board's authorization — that's between you
and whoever made it. Some ESP32 boards are built on a pre-certified module and
some are built on bare silicon; the boards we document (firmware/boards/)
list the MCU, not a module grant, and we haven't looked the grants up yet. If
that matters to you, check the specific board on fccid.io before you buy.
The day we ship a boxed, pre-flashed device is the day we owe a Part 15B test on
it — and we'll have done it before that box exists, not after.
→ SECURITY.md · claims and risk audit
· compliance diligence
No. log_anchor verify --policy checks that two distinct TSAs countersigned
the same ledger head and records which one you declared qualified; whether a
TSA is on a trusted list is something you check and write down, not something
the software can prove.
→ timestamping
No. The Beacon channel is designed to a smoke-detector-grade bar, but it
is a 🟡 draft spec with firmware scaffolding — not a certified life-safety
device, and not a replacement for one. It is also explicitly not a
neighborhood-watch or suspicious-person reporting system.
→ spec/beacon_channel_v0.md
Two ways: run cargo run --bin demo, then break the log on purpose and watch
verification fail — or open the Lab, where the real shipping firmware runs
in your browser compiled to WebAssembly, flashes a simulated blank chip, and
shows its cryptographic birth certificate.
→ the demo · the Lab
Depends what you want. A spare Raspberry Pi for the hub; ESP32-S3/C3/C6-class boards for Canaries; nothing at all to try the Lab. The recommended first build is Canary WAP. → the full stack · getting started with Canaries · hardware guides
Quite possibly. The supported-board table
(firmware/boards/README.md) goes beyond the
XIAO: the AI-Thinker ESP32-CAM and generic ESP32-WROOM-32 DevKits (classic
ESP32), the Freenove ESP32-S3 camera kit, and the C3 Super Mini all have
registered, CI-built ports — each with an honest per-board note on what it
can and can't sense, and a tier that says whether anyone has bench-validated
it yet. Flashing a board that's been in a drawer (or came from a marketplace
seller)? Read unflashed board intake first —
bring it up cold. Board not listed? A port is a pin map plus a build config,
one PR, no core code: firmware/PORTING.md.
Yes — optionally. The hub runs headless by default and never needs one. But
plug an HDMI touchscreen into the Pi (a 7" 1024x600 IPS panel with USB touch
is the reference) and the setup's opt-in display extra installs
HAOSKiosk, a community app that runs a browser on the hub itself and shows
your dashboard on that screen, touch included. In the desktop Flasher it's
the "Also install the hub display" tick; by hand it's --with display (or
just install HAOS Kiosk Display from its repository in the app store). One
step stays yours: give the screen a dedicated non-admin Home Assistant user
(a screen only views dashboards, so it shouldn't hold an admin password),
type that login into the app's Configuration tab, and press Start — the
installer never carries any password. No vendor cloud and no new account;
the screen fetches only what your dashboard already fetches on any device
that opens it. Honest status: same bar as self-setup itself — host-tested,
awaiting its first validated run on real hardware.
→ the full stack
Why did I still meet Home Assistant's setup wizard after the Flasher? And can my phone finish the hub?
Two reasons, both fixed in the Flasher now, and yes. The Flasher's first-boot watch used to count any answer on the hub's port as "up" — but Home Assistant OS serves a "Preparing Home Assistant" page for the minutes Core takes to download on a first boot, so the account creation fired at a page that couldn't create one, gave up after thirty seconds, and you met the wizard. The watch now asks Home Assistant's own setup API and acts only when it answers (preparing and ready are different words on screen), and the self-setup run retries "not ready yet" on its own. The second reason is that the account is created by a companion on your network after boot, and the Flasher was the only companion — if it was closed, nobody created the account.
The SecuraCV iPhone app is now that companion too: Fleet → Options → Set up a hub or a Canary (or Set up a hub on the Add your first Canary card on Today). It finds the hub on your Wi-Fi by itself, waits for Home Assistant to actually exist, creates your account over Home Assistant's own setup API, finishes the wizard pages, checks the login works, and then asks Home Assistant for the same things its Settings page would — the Mosquitto broker, a login for your Canaries (minted on the phone, kept in its Keychain), the broker connection, Frigate and the witness kernel — narrating each step and naming what stays yours. The one thing no second device does for you is install the SecuraCV integration's files — that is one click of your own: open the SecuraCV panel in the hub's sidebar and press Install the integration and restart Home Assistant (the terminal one-liner in the guide remains the fallback; the investigation has the history). Honest status: host-tested; the first validated run on a real first boot is still owed, and the by-hand path in the guide always works. → a truly headless hub install, the full stack
Home Assistant setup → Frigate integration → the Verified Timeline card.
Yes — locally, and voice input never comes from a Canary. (A Canary's own mic, where fitted, hears only an on/off loudness envelope — in stock builds for smoke/CO alarm cadences, in dev builds also for opt-in transients like knocks and glass breaks — and it is structurally unable to carry speech.) The hub runs Home Assistant's fully local voice stack (Whisper speech-to-text, Piper text-to-speech, an optional wake word), so "is the fleet OK?" and "what was the last witness event?" are answered on your own Pi with nothing leaving the house. Voice input comes from a dedicated satellite — your phone's push-to-talk button, or a wake-word box whose stated job is listening — and the intents are read-only by construction: no sentence arms, disarms, or unseals anything, because a spoken word carries no signature. Transcribing what the world says near a witness device remains forbidden forever (Invariant II). → the recipe · the design and its contract
Apple Home: yes, two lanes — the design is the Apple Home design doc. The shape: the fleet appears in the Home app as sensor accessories (motion/occupancy/contact/tamper/liveness — by default no more than a dumb PIR would report; one opt-in setting can add the coarse object class — person, vehicle, animal, package — never identity), so your automations can answer the witness — lights on when a person crosses the driveway, the whole house responding to tamper. Built today: the hub speaks HAP directly (bridge site B, no Home Assistant in the path — the pairing transcript is proven by tests driving an independently written controller, but it has not yet paired against a real Apple TV or HomePod, and the Apple Home quickstart — which has the two-minute wizard — says so plainly until it has), and if you run the Home Assistant hub, HA's own HomeKit Bridge projects the securacv sensors with zero new code — the worked recipe is apple-home-homekit-bridge.md. Device-native pairing (a Canary in the Home app with no hub at all) and Matter are still design, per the RFC's phasing table.
HomeKit Secure Video: no — and on purpose. HKSV's core loop uploads the raw clip on every motion trigger, which is exactly what Invariant I ("No Raw Export by Design") forbids, and no Canary has a media plane to offer it anyway. The verdict is argued once, with revisit triggers, in the RFC §2. The event half of Apple Home — the half automations actually run on — is fully open to us, and it's the half we do better than a camera.
No. Print the case, buy the parts anywhere, flash it yourself — the whole path is open. Kits exist for people who'd rather not. Independent vendors can sell kits under the free "Works with SecuraCV" badge. → the ecosystem · vendors
| You want | Build |
|---|---|
| A first device, general purpose | Canary WAP |
| Camera + person detection into Home Assistant | Canary Vision |
| Presence/breathing care with no camera | Canary Sense |
| A doorway that's very hard to sneak past | Canary Sentinel — not yet flashable: the fusion core is host-tested and its network firmware is compile-gated in CI, but nothing has run on hardware and there is no released build; use a Canary Sense or Vision today |
| A doorbell | Nothing that rings today. The Vision Doorbell case is a released, sealed, plate-mounted case for a Canary Vision — a person witness in a doorbell shape. Its button is wired, but the shipping firmware does not read it, and the shipping model detects people, not packages. The doorbell itself — the ring, the package chain, night sensing, radar, the doormat depth sensor — is design only: the doorbell dossier |
| A wall display for the household | Canary Display |
| A kid's bedside clock + lamp with a companion | The Nightlight (the nightlight display flavor) |
| Pool/spa water chemistry (pH, ORP, temp) | Canary Pool (design-stage) |
Open it again. From version 0.3.8 the Flasher repairs this itself: it leaves a breadcrumb as each launch advances and reads the last one on the way up, before it builds a window, so a launch that never arrived gets fixed rather than repeated. You may see a short note telling you what it found.
If it still won't open, one of three things happened, and the app's own
launch.log says which (~/Library/Application Support/com.securacv.flasher/
on macOS, ~/.local/share/com.securacv.flasher/ on Linux):
- A leftover
espflashorrpibootfrom the killed run is still holding your board. The Flasher now reaps these at startup; to check by hand,pgrep -fl 'espflash|rpiboot'. - A saved session left mid-write. Cleared automatically on the next launch — once. You'd re-enter the Wi-Fi network name and device names you last used; no password was ever stored, so nothing secret is lost.
- A self-update that was interrupted. This is the one nothing in the app can fix, because the repair would have to run from the copy that moved: installing an update moves the app bundle, so a force quit part-way can leave it missing or incomplete. Reinstall from the latest Flasher release. Nothing you have flashed is affected — a Canary keeps the firmware it has, and the board can't be bricked.
Force quitting is never dangerous to a device. A flash interrupted at any stage is re-flashable: the ESP32's first-stage bootloader is mask ROM, and a half-written hub card is simply written again.
First, the honest line: the SecuraCV iPhone app is on TestFlight by invite today; its App Store release is pending (the apps page says the same). With it, a Sense, Vision or WAP needs no key typed. Out of the box those three open a small Bluetooth setup door for their first half hour after power-on. Open the app near the Canary: a card appears within seconds ("A new Canary is nearby"). Tap Continue, tap Pair when iOS asks, pick your Wi-Fi from the networks the Canary itself can see and type the password once; the phone then says is on . The phone can remember your Wi-Fi, on that phone only, so the second Canary is two taps. For a Sense or Vision the same card hands it your hub as well — the broker's address and login ride over with the Wi-Fi, so it shows up in Home Assistant without a visit to the Flasher. The all-rounder Canary build has no door and always uses the setup network below.
Without the app — or for the all-rounder Canary — the setup network:
the Canary raises SecuraCV-XXXX; join it from any phone with the key it
printed on its serial console at boot (the Flasher's done card shows the
same key for a Sense, Vision or WAP it just flashed) and the setup page
opens on its own. For makers: the door is the open
Improv Wi-Fi standard over an encrypted
Bluetooth link, and on a WAP the same tap trades a one-time claim ticket for
the pairing receipt over your Wi-Fi — see
magic pairing (design).
When the door is open — the rule, in the firmware's own words: for a
device nobody owns yet, and for an owner's own tap — never for a device that
has an owner and a bad day. A Canary with no Wi-Fi saved opens it for 30
minutes after power-on (unplug and replug to get another 30). A Sense or
Vision that already has Wi-Fi opens it for 60 seconds when you tap its BOOT
button. A Canary whose saved Wi-Fi has merely stopped working (the router
rebooted, you changed the password) does not open it — it raises its
SecuraCV-XXXX recovery network instead, which needs the key printed for
it. So a Canary on your network offers nothing to a stranger's phone, on a
good day or a bad one.
The older paths stay as the fallback: the SecuraCV-XXXX setup network with
its printed key, a display's glass QR (a display shows a QR instead of
opening a door — a screen beats a radio), and the WAP's own setup page once
it is paired.
Honest status: the bytes and the rules are host-tested on both ends; the radio, the iOS pairing sheet and the BOOT button on each board have not yet been tried on a bench. → magic pairing (design)
Most likely the window closed. A Canary with no Wi-Fi saved opens its
Bluetooth setup door for 30 minutes after it is powered on, then shuts
it so a unit forgotten in a drawer is not claimable from the street for the
rest of its life. Unplug it and plug it back in: the window starts again.
(On a Sense or Vision a tap on the BOOT button opens it for a minute too.)
The card also goes away for fifteen seconds of silence — the phone has to
keep hearing the Canary, so walk closer — and once the Canary has joined
your Wi-Fi it shuts the door for good, which is the card doing its job. If
you need it before the app does, the SecuraCV-XXXX setup network with its
printed key is always there.
That is the door being shut on purpose: a Canary that has an owner is not
re-pointable at a new network from across the room. To change its Wi-Fi
yourself: on a Sense or Vision, tap its BOOT button once (a short press
— under a second) and the door opens for 60 seconds; or power-cycle a unit
that has no Wi-Fi saved. On a WAP, which has no tap door in this
version, use its own setup page (Settings → Wi-Fi on the dashboard, or the
SecuraCV-XXXX network when it is off your home network) — or tell it to
forget its Wi-Fi from the dashboard (Settings → Wi-Fi → Forget, the
/api/wifi/forget route), which clears the stored network and opens the
door again for half an hour from that moment. There is no button gesture
that factory-resets a WAP today. A Canary whose saved network is just
down right now keeps the door shut and raises its recovery network
instead; fix the router, or use that network's printed key.
For Wi-Fi, yes. The door is the open Improv Wi-Fi standard, so the Home
Assistant companion app (and the improv-wifi web SDK in a browser that
speaks Web Bluetooth) can hand a new Sense, Vision or WAP your Wi-Fi exactly
as the SecuraCV app does; the Canary then shows up over MQTT like any other.
What those clients do not get is the SecuraCV pairing: the claim ticket
lives in our own companion service, which a standard client never looks
for, so a WAP set up from Home Assistant's app has Wi-Fi and is then paired
in the SecuraCV app: tap it under Ready to pair on the Fleet tab and add it
with its recovery kit (canary-recovery-kit.json, which its own setup page
saves after a short BOOT tap). Home Assistant's own "Improv via BLE" integration needs a Bluetooth
radio on the Home Assistant machine itself; through an ESPHome Bluetooth
proxy the one-tap pairing cannot complete — expected, and untested.
→ Home Assistant setup
It crosses Bluetooth once, encrypted: the Canary refuses the credentials write on an unencrypted link (that is why iOS shows its pairing sheet the first time), so a passive listener learns nothing. The Canary stores the password only once it has actually joined with it, in the same place the setup network's wizard would. The phone keeps it only if you let it — "remember this Wi-Fi for the next Canary" — and then only in this phone's Keychain (device-only, never iCloud Keychain, never our cloud, which does not exist), and only after a Canary itself said it joined: an unproven password is not one worth remembering. "Forget" on the Set up screen clears it. The WAP's pairing key is a different thing, and it never rides Bluetooth at all (the claim ticket above).
Forget the network on your phone, then scan the QR again.
iPhone: Settings → Wi-Fi → the (i) beside SecuraCV-XXXX → Forget This
Network. Android: long-press the network in the Wi-Fi list → Forget.
Then rescan the QR on the glass, or join by hand with the name and password
printed under it.
Why it happens: your phone saves a network by its name, and a display on firmware 2.4.9 or older gave its setup network a new password on every boot while keeping the same name. So the second time your phone met that network it rejoined silently with the password it had stored, the display refused it, and the phone reported a plain join failure rather than asking you for the new one — which is why retyping never got a chance and re-flashing made it worse. Newer firmware mints that password once and keeps it, so the name and password on the glass stay true; a phone that already saved an old one still needs that single Forget.
If the display has been sitting on the join screen for a while it will say this on its own glass too.
AGENTS.md — the canonical brief, read by Claude Code, Codex,
Gemini CLI, Copilot, Cursor, Cline, Windsurf, and Qwen Code via their own
entrypoint files. It carries the privacy invariants, the naming rules, the repo
map, and the CI gates you will trip. Then the glossary for
vocabulary and docs/FLIGHT_RULES.md for the engineering
constitution.
Adding any identity-inferring capability; giving RawFrame a public accessor or
a Clone; overselling a security property in a doc comment; a performance claim
with no benchmark; the word "flock" for a group of Canaries; a new doc that
isn't on the docs map; or a vocabulary change that doesn't start in
spec/witness_dictionary.json.
→ CONTRIBUTING.md · AGENTS.md
A company called Flock soured the word, so a group of Canaries is a fleet —
in copy, device strings, product names, identifiers, and comments. The one
exception is the Unix flock(2) syscall, which is a real API name.
SECURITY.md — please don't open a public issue for a
vulnerability.