Inspiration
A dental office or a small warehouse still has a door and no receptionist. Ring already sees who is standing there. The missing piece is a desk: who was expected, a decision that does not depend on a model's mood, and a record a landlord or an insurer can replay. A camera that describes a visitor is not a person who can let them in.
What it does
Threshold is that desk. Ring is the doorbell, the camera, and the record of the event. The operator keeps an expected-visit diary. When someone arrives, policy returns admit, escalate, or deny. An on-window visit whose purpose matches the evidence is admitted and gets one single-use code. Anyone else waits on a five-minute countdown for a person, or is denied. The model may describe the scene. A grammar check rejects any field that tries to smuggle a verdict. The code is a mock lock: shown once, stored as a hash, and rejected on a second use or after it expires. Every decision is a hash-chained ledger row.
How I built it
The repo is a pnpm monorepo. A Ring client verifies webhook HMAC on the raw body, opens a WHEP session, takes a snapshot, and tries a chime. A local emulator signs fixture doorbell events, so a judge can run the path with no Playground token. Policy is deterministic TypeScript: the diary window and the evidence hint decide, not the model. Optional Amazon Bedrock vision runs only when BEDROCK_MODEL_ID is set; text that fails the grammar falls back to fixture evidence. The operator console is a Next.js diary, live desk, audit replay, and DoorBench page. DoorBench is 200 offline scenarios: a baseline that always admits, the real policy as treatment, and a skip-expiry ablation.
Challenges I ran into
Ring's public scope is ava.v1:read. There is no lock or unlock API, so a real strike could not be the demo. Playground tokens last about 30 minutes, are pasted by hand, and do not POST webhooks to localhost, so the doorbell and the camera cannot share one credential. Webhook HMAC has to cover the exact raw body; re-serializing JSON fails verification. Live view has a 30-second battery cap, so WHEP is hard-cancelled at 25 seconds. The model had to stay out of the decision: if the grammar sees a verdict key, that text is thrown out.
Accomplishments that I'm proud of
On 200 DoorBench scenarios the treatment issues 0 false grants. A baseline that admits with no diary issues 159 (79.5%). Skipping the visit window still issues 20. A forged webhook returns 401. A duplicate request id is a no-op. A grant after the countdown returns 409 and writes nothing. The audit page replays the chain, and a tampered copy fails without changing the stored rows. Judges can run the emulator, the tests, and the desk with one shared HMAC key and no AWS account.
What I learned
A read API can be the eyes and the system of record and still not be the lock. The useful boundary is small: the model fills a strict grammar, and policy is the only thing that admits. Fixture fallbacks and an honest latency budget mattered more than a live percentile I had not measured. The friction that slowed the demo was operational: short tokens, no localhost webhooks, and no actuator scope.
What's next for Threshold
A partner lock-actuator scope would replace the mock lock with a real strike. A webhook sandbox that can POST to localhost, longer sandbox tokens, and stable Playground device ids would let the doorbell and the camera share one script. The ledger should move off the in-memory HMAC chain onto durable storage. Live p50 and p95 stay blank until a Playground run measures them. The buyer is still the site that pays for a desk that is not a person, and for a ledger a landlord or an insurer can replay.
Built With
- javascript
- nextjs
- node.js
Log in or sign up for Devpost to join the conversation.