Skip to content

feat: notify when a device is down, and restart the box from the phone - #56

Merged
Leitet merged 2 commits into
mainfrom
cursor/push-and-restart-0d20
Aug 27, 2026
Merged

feat: notify when a device is down, and restart the box from the phone#56
Leitet merged 2 commits into
mainfrom
cursor/push-and-restart-0d20

Conversation

@frahlg

@frahlg frahlg commented Aug 26, 2026

Copy link
Copy Markdown
Member

Contract-pair: srcfl/ftw@cursor/push-driver-down-0d20

What changed

The phone app can now hear two more facts from the box, and it can restart the box from the Box screen.

Notifications (paired catalogue with the box):

  • driver.offline — “If a device goes quiet”
  • fuse.over_limit — “If the house draws more than the fuse allows”

Turning notifications on enables the new kinds with the rest. An existing subscription sees two new toggles, off until saved. box.unreachable still has no switch.

Restart (already POST /api/restart on the box, Configure):

  • Owner only, hidden from viewers and from a box that has not spoken.
  • Confirm, then one passkey ceremony, then 202. The app says the box comes back on its own. No reconnect button.

Why

Hannes had to use Termius/Tailscale from work when a driver stuck, and there was no lock-screen for a driver being down. Fredrik asked for both while we were on the Pixii blip.

Boundaries

  • Not a settings dump. Restart is a recovery act on the Box screen, confirmed like sign-out.
  • The box still decides. The app only asks.
  • An older box without these catalogue kinds simply does not offer them; a save never sends a kind the box’s document lacks.
  • The public demo Box screen still cannot turn notifications on or restart — it has no identity. Its sentence now names a device that stops answering.

Verification

  • Focused vitest (Notifications, Restart, Box, push-contract, api-passthrough, App): 86 passed.
  • svelte-check: 0 errors. Production build succeeded.
  • GitHub CI verify passed on Node 24.
  • Browser walkthrough of the real Box screen (dev simulator): notifications copy, Chrome permission prompt, restart confirm / cancel / now. The simulator has no service worker and no passkey, so those two actions stop at the honest sentences; the success paths are the tests.

box_notifications_and_restart.mp4
Box screen with notifications and restart
Restart confirmation
Phone-width Box screen

Checklist

  • I checked open pull requests that touch the same files (webapp feat(app): native-feel pass #55 does not touch Box/Notifications).
  • Tests cover the changed behaviour and its failure path.
  • A human reviewed every changed web/UI view in a browser.
  • A Changeset is included.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 2 commits August 26, 2026 18:14
Two lock-screen kinds join the catalogue — a device gone quiet, and the
house drawing more than the fuse — and the Box screen can restart FTW
so a stuck driver does not need Termius from work.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
The public demo still cannot turn notifications on, but the sentence
should name the same events a real home can now hear.

Signed-off-by: Cursor Agent <cursoragent@cursor.com>

Co-authored-by: Fredrik Ahlgren <fredrik@sourceful-labs.com>
@cloudflare-workers-and-pages

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
ftw-webapp 2554794 Commit Preview URL

Branch Preview URL
Aug 26 2026, 06:19 PM

@frahlg
frahlg marked this pull request as ready for review August 26, 2026 18:35

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2554794289

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/lib/notify/kinds.ts
Comment on lines +15 to +16
'driver.offline',
'fuse.over_limit',

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Hide notification kinds absent from the box document

On an existing subscription connected to an older box whose rules document lacks these new kinds, Notifications.svelte still iterates every entry in RULE_KINDS, so both unsupported toggles are displayed. Although NotifyStore.#writeRules correctly filters them out before sending, it then applies the returned document and silently resets the toggles to off after Save, leaving users with controls that can never take effect. Derive the displayed kinds from the types present in the loaded rules document.

Useful? React with 👍 / 👎.

Comment thread src/views/Restart.svelte
error = null
stage = 'restarting'
try {
await callBox<{ status?: unknown }>(site, { method: 'POST', path: '/api/restart' })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Clear the restarting state once reconnection completes

After the restart request returns 202, no success path ever changes stage from restarting. App.svelte keeps previously opened views mounted even while navigating between tabs, so the automatic disconnect/reconnect does not recreate this component; the Box screen consequently says “Restarting” for the rest of the app session and permanently suppresses another restart attempt. Observe the session returning to streaming, or otherwise reset the stage after reconnection.

Useful? React with 👍 / 👎.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 2554794. Configure here.

<p>
A few words on the lock screen when something at home matters: the car is
charged, your box updated itself, or it went quiet. Nothing is sent until
charged, a device goes quiet, or the box itself. Nothing is sent until

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broken notifications intro copy

Medium Severity

The offline notifications teaser ends with or the box itself, which is an incomplete phrase. Readers never learn what happens with the box, unlike the parallel DemoBox sentence that finishes the idea.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2554794. Configure here.

<p>
A few words on the lock screen when something at home matters: the car is
charged, your box updated itself, or it went quiet. Nothing is sent until
charged, a device goes quiet, or the box itself. Nothing is sent until

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra toggles on older boxes

Medium Severity

The kinds list always renders every RULE_KINDS entry, including driver.offline and fuse.over_limit, even when those types are absent from the box’s rules document. A save correctly omits missing kinds, so those toggles can appear, be flipped, and then snap back off after save.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 2554794. Configure here.

@cursor
cursor Bot requested review from Leitet and davmoz August 26, 2026 18:39

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a non-blocking comment: Cursor Bugbot skipped on this head, so this is not approved. Human review is needed; assigned two reviewers.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@miravoss26 miravoss26 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the diff. This adds a manual box-restart control to the phone app (owner-only, step-up gated, confirm-before-send) plus two new lock-screen notification kinds (driver.offline, fuse.over_limit) mirroring the existing ntfy rules.

  • Authz: Restart.svelte only renders when site.heardFromBox && canAsk (owner role + api.passthrough cap), tested for the viewer role showing nothing and no box connection showing nothing.
  • Safety: restart is gated behind a confirm step and a step-up ceremony before POST /api/restart fires; a stray tap on the confirm screen doesn't restart (tested).
  • Consistency: the two new push kinds are threaded through push-catalogue.yaml, kinds.ts, and the sim API's RULE_TYPES together — nothing half-wired.
  • CI green (registry-drift check, verify, Cursor security/bugbot all pass).

No blocking findings. Safe to merge from my read.

@Leitet
Leitet merged commit 5a3dd8a into main Aug 27, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants