Pulso now has real user accounts. As of 3 August it signs people in through Supabase Auth with email and magic links, and all seven collection tables in Postgres are scoped by user_id behind row-level security, which replaces the single shared token that had been standing in for a login since the app was built for exactly one person: me.
The schema work came first, on 2 August, and it was the part that actually mattered. Watches, shortlist, wear, stories, service, prices and shares all carry a user_id now, and the isolation is enforced by the database rather than by whichever route handler happens to remember. That distinction is the whole point. If ownership is a check I write by hand in every endpoint, then the app is only as safe as my worst afternoon. Putting it in the database means a route I write badly next month still cannot hand somebody else’s collection to the wrong person. The auth swap this morning was the easy half, once the rows already knew who owned them.
Also today, the nightly price refresh got told there is more than one person now. It used to be a straight run through my watches, which is fine when the total is my collection and nobody else’s. With multiple users that same loop turns into a bill that scales with signups, so it now staggers the work and runs under a global cap rather than a per-user one. That is a lesson I paid for on 1 August, when a scheduler bug looped on restart and burned through real credit before it ran out.
What this still is not is an app anyone else can use. The invite flow, per-user AI budgets, per-user upload paths and a tested Postgres restore all sit unbuilt in the backlog, and I am not inviting a single person off the waitlist until the restore drill has actually been run rather than merely planned.