Stub
2026 TestFlight betaNative iOS · On-device reading · Money as read · Private matching
The whole cinema night in one app: what’s on, the friends you go with, the booking handed to the cinema’s own checkout, and the stub you keep afterwards. Aggregators own the moviegoer; Stub is built so every booking lands with the cinema, and so its own server learns as little as it can.
The cinema should keep the customer
Most people find a film on an aggregator, book through it, and the cinema never learns who came. Stub covers the night end to end: what’s on near you, a plan your friends can answer, and then a hand-off to the cinema’s own checkout with the session already chosen. Booking seats inside Stub through the cinema’s Vista was built against the sandbox and then parked on purpose: the sale, and the risk that comes with it, stays with the cinema.
After the film, the ticket is read on the phone and kept, and each release prints its own edition — a ticket designed for that film, with your seat and your night on it.
An amount is shown only as it was read
An amount Stub shows, sums or sends is a claim, so every one carries where it came from. Money is held in integer minor units, never a float. Currency is an ISO 4217 code or nothing — no default, and nil is an answer. Each amount records whether it was printed, confirmed, typed or came from the cinema, and whether it is one seat, the whole booking or unknown. A session keeps the cinema’s own wall clock with no zone, because a 9 pm Saturday in Los Angeles is Sunday in UTC. Currencies are never added together. When only some nights have a price, the season says so: paid · 6 of 9.
A baseline the model has to beat
Vision reads the ticket on the device. A rule-based parser reads it first, always; the on-device model reads it with that draft in hand and is scored against it. On the eleven fixtures the rules get every field right in a millisecond, while the model takes a median of 11.7 seconds — so the rules’ draft goes on screen first, and shutter-to-keepable fell from 4.20 to 1.50 seconds. The honest gap is written down too: the corpus of real tickets is still empty, so there is no field rate yet worth quoting.
A match the server can’t read
When two friends both want the same film, both are told. Stub’s server never learns which film. Each phone keeps a private key in the Keychain; for each friend it agrees a secret only the two phones share (X25519, then HKDF), and sends the film as a token hashed under it. The server holds tokens it cannot read and only notices when two of them match.
Done means under budget on the oldest phone
Every budget is an Apple number or derived from one, on the oldest iPhone Stub supports: first frame in 400 ms, a tap answered in 100 ms, a ticket keepable 1.5 s after the shutter. UI tests measure launch, signposts, hitches, memory and CPU; a script fails any run that is over budget or stopped measuring something, on every push. A budget can be tightened in any commit; raising one takes a written reason.
In beta, not yet on the App Store
Build 1046 went to TestFlight on 4 November 2026. The source is private while it is in beta.