Add guest links for temporary shared access
Handing a dog sitter the ability to log a pee meant handing them the account password: permanent, total control, revocable only by changing it. Settings → Guest access now mints a URL that does the one thing instead. A link is a session, not an account. Opening /guest/<token> inserts an ordinary session row against the owner's user_id, tagged with the link it came from, so every data path downstream — sync, photos, the profile — stays scoped by user_id exactly as before and needed no changes at all. Only the capability checks differ by role, which is what kept this from touching the sync contract. Redemption is a plain GET so tapping the link in a message works, and the 303 to / leaves the token out of the address bar, bookmarks and the PWA start URL. What a guest cannot change is enforced in the upsert, not in the UI. The WHERE clause gains a logged_by_share test: an owner (empty share id) may change anything, a guest only rows carrying their own link's id. A sitter can fix up their own entries and cannot rewrite or delete one of the owner's, including everything logged before this existed, since those rows carry the empty id too. Deletes come along free, being tombstones. The test is on the link id rather than its label because two links can easily both be "Sitter", and the id is also why /api/me hands the guest its share id: the client needs it to know what to grey out. The exercise library is the owner's on the same reasoning — a guest trains against it but the server drops any exercise a guest sends. Attribution is stamped from the session on insert and left out of DO UPDATE SET, so it is decided once by whoever logged the event and survives every later edit. It never comes off the wire, so it cannot be forged — a guest re-POSTs the owner's whole event list on every sync, but those rows already exist and keep their stored values. Expiry is a date the owner picks; the link dies at the end of that day in their own timezone, which the client computes because the server has no way to know it. Sessions are capped at the link's own end, and every request re-checks the link is live rather than trusting the session row, so revoking kicks a guest out on their next request instead of whenever their session happens to lapse. Only the token hash is stored, as with session tokens, so the URL is shown once at creation and cannot be read back. The client side follows from that. A guest opening someone else's entry gets the edit dialog read-only rather than a form that would silently discard what they typed, and mergeSynced takes the server's copy for anything they may not change — otherwise a refused write would sit in their cache forever showing an edit that never happened. An ended link wipes their cached copy of someone else's history and says so, rather than offering a sign-in form they have no password for.
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
[
|
||||
{ "date": "2026-09-06", "text": "You can hand someone temporary access without giving them your login. Settings → “Guest access” creates a link — say who it's for and pick the last day it should work — and whoever opens it lands straight in the app on your dog, able to log events and read all the history and charts. They can't change your entries: a guest may fix up or delete what they logged themselves, but everything you logged is read-only to them, and so is the puppy profile, the pedigree ID, your reminders, the exercise list, other guest links and deleting the account. You can still edit anything on your own account, theirs included. The link is shown once when you make it, so copy it then; every live link is listed in Settings with when it expires and when it was last used, and Revoke cuts access off immediately, mid-session. Anything logged on a link is tagged with that link's name in the History log — “💧 Pee · Anna” — and the tag sticks even if you edit the entry afterwards" },
|
||||
{ "date": "2026-09-04", "text": "The three day-long charts — “By hour of day”, “When sleeping” and “When walking” — now mark the current time with a small vertical line and caret. On the sleeping and walking rows it also shows where today's row stops, and it lines the same clock position up across every day above it" },
|
||||
{ "date": "2026-09-01", "text": "Removed the walking goal from the Walk trend — the dashed target line, its legend chip and the ✓ that marked a day as met. It came from the “five-minute rule” (five minutes per month of age, twice a day), which is a widely repeated rule of thumb rather than veterinary guidance, and the app was stating it more confidently than it deserved. The chart is now just a record of what you walked, against yesterday and the average" },
|
||||
{ "date": "2026-09-01", "text": "The 7d / 14d / 30d buttons have moved out of the Sleep panel onto their own “Charts cover” row, just under the Log event buttons. They always set the window for every chart on the page — training, timing, sleep, walks, pees/poos/meals — but sitting inside the Sleep panel made them look like a sleep setting" },
|
||||
|
||||
Reference in New Issue
Block a user