Skip to content

Add Set up custom push notifications how-to#5080

Open
shannonbradshaw wants to merge 6 commits into
viamrobotics:mainfrom
shannonbradshaw:shannonbradshaw/custom-push-notifications
Open

Add Set up custom push notifications how-to#5080
shannonbradshaw wants to merge 6 commits into
viamrobotics:mainfrom
shannonbradshaw:shannonbradshaw/custom-push-notifications

Conversation

@shannonbradshaw
Copy link
Copy Markdown
Collaborator

@shannonbradshaw shannonbradshaw commented May 28, 2026

Summary

Documents the end-to-end flow for routing trigger push notifications to a custom mobile app instead of the Viam mobile app. Closes the docs follow-up identified during review of #5079.

The new page at docs/monitor/custom-push-notifications.md covers:

  • Firebase service-account JSON upload through viam organizations firebase-config set (with the constraint that it's the Admin SDK service account, not google-services.json / GoogleService-Info.plist).
  • Device-token registration: Flutter SDK wrappers (uploadDevicePushToken / deleteDevicePushToken / getDevicePushTokens) for the one language that has them today, plus raw gRPC notes for Python / TypeScript / Go / C++.
  • The fragment-ownership trust gate: a non-Viam application only delivers if the machine imports a fragment owned by the same organization that uploaded the Firebase config. com.viam.viammobile is exempt by literal name.
  • Trigger config with the application field.
  • Verify / troubleshoot keyed to the actual server-side log messages (trigger push notification failed: app authorization check, recipient is not a robot owner or operator).

Cross-links added from docs/monitor/alert.md, docs/data/trigger-on-data.md, docs/reference/triggers.md, and both the application line and the organizations firebase-config set entry in docs/cli/reference.md.

Open questions for @clintpurser and @martha-johnston

Design rationale: why fragment-ownership?

The page documents what the fragment-ownership trust gate is, but not why the design uses fragment ownership rather than a direct grant API. Two options:

  1. Leave the page as-is (what only); the design rationale isn't load-bearing for someone setting this up.
  2. Add a short rationale paragraph in section 3 ("Authorize the machine") explaining the trust model.

Happy either way — if (2), what's the right one-paragraph explanation?

Technical accuracy spot-check

The page makes several claims I want a second pair of eyes on, especially ones that involve client-side or private-repo behavior I cannot fully verify from public source:

  1. Stale-token threshold (section 2, Token lifecycle). I wrote "the Viam mobile app re-uploads if the stored token is older than 30 days." This came from the viam-mobile Flutter implementation. Is 30 days current and worth surfacing as guidance for third-party apps, or should the page just say "re-upload periodically" without the specific number?
  2. com.viam.viammobile as the only exempt application ID. Verified in app/triggers/push_notification.go:14-15 as a literal const. Are there or will there be other exempt IDs (an enterprise variant, a partner app) that the page should mention or future-proof against?
  3. Payload data fields (section 5). I list event_type, robot_part_id, machine_name, part_name, app_id based on pushNotificationData() plus pushPayloadData(). Is that the complete and stable set, or are additions expected that third-party app developers should code for defensively?
  4. Recipient "must have accepted push notification permissions." I describe this as a client-side OS permission gate — if the user rejects, no token is registered, no notification is delivered, no server-side error. Is that the right framing, or is there a server-side check I missed?
  5. Fragment-import button label. Section 3 instructs readers to use the configuration-block dialog and click Add fragment. Confirmed in app/ui/src/lib/components/robot/add-resource-menu/create-block-modal/create-block-dialog.svelte:31. Just flagging in case there's an updated UI flow in flight.

A quick "looks right" / "fix N" reply is plenty — no need to write copy.

Test plan

  • Netlify deploy preview renders the new page at /monitor/custom-push-notifications/ with a clean sidebar entry between Set up alerts and Default control interface.
  • All four cross-links resolve in the deploy preview: /monitor/alert/, /data/trigger-on-data/, /reference/triggers/, /cli/reference/.
  • In-page anchor #troubleshoot works; cross-page anchors /cli/reference/#organizations-firebase-config-set, /cli/reference/#login, and /hardware/fragments/#save-your-own-configurations jump correctly.

🤖 Generated with Claude Code

Documents the end-to-end flow for routing trigger push notifications
to a custom mobile app instead of the Viam mobile app: Firebase
service-account upload via `viam organizations firebase-config set`,
device-token registration through the Flutter SDK or raw gRPC, the
fragment-ownership trust gate that authorizes a machine to receive
pushes for a non-Viam app, trigger config with the `application`
field, and a verify/troubleshoot section keyed to the actual server-
side log messages.

Cross-links: docs/monitor/alert.md, docs/data/trigger-on-data.md,
docs/reference/triggers.md, and the application field plus
`organizations firebase-config set` section of docs/cli/reference.md.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@netlify
Copy link
Copy Markdown

netlify Bot commented May 28, 2026

Deploy Preview for viam-docs ready!

Name Link
🔨 Latest commit 6ac358a
🔍 Latest deploy log https://app.netlify.com/projects/viam-docs/deploys/6a1da396abf355000813fda7
😎 Deploy Preview https://deploy-preview-5080--viam-docs.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 41 (🔴 down 5 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 92 (no change from production)
PWA: 70 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@viambot viambot added the safe to build This pull request is marked safe to build from a trusted zone label May 28, 2026
| `device_token` | FCM registration token from `FirebaseMessaging.getToken()`. On iOS, call `getAPNSToken()` first; FCM normalizes both. |
| `device_uuid` | A stable device identifier. Android: `android.id` from `device_info_plus`. iOS: `identifierForVendor`. |

User identity comes from the authenticated Viam session on the call, so there is no `user_id` parameter.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

probably don't need to call out the lack of a user_id parameter

A user can have parallel tokens for `com.viam.viammobile` and a custom app, and only the matching set receives any given push.
- Viam prunes dead tokens automatically when FCM reports "not registered."
No server-side cleanup is required for stale tokens.
- Calling `DeleteDevicePushToken` on logout is still recommended so a shared device does not receive notifications for the previous user.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
- Calling `DeleteDevicePushToken` on logout is still recommended so a shared device does not receive notifications for the previous user.
- Calling `DeleteDevicePushToken` on logout is still required so a shared device does not receive notifications for the previous user.

Comment on lines +135 to +136
`com.viam.viammobile` is exempt from this check.
Triggers targeting the Viam mobile app work on any machine the recipient owns or operates.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

might be unnecessary since this section is about third party apps

@martha-johnston
Copy link
Copy Markdown
Contributor

overall looks good but I left a couple of suggestions

The page documents what the fragment-ownership trust gate is, but not why the design uses fragment ownership rather than a direct grant API. Two options:

  1. Leave the page as-is (what only); the design rationale isn't load-bearing for someone setting this up.
  2. Add a short rationale paragraph in section 3 ("Authorize the machine") explaining the trust model.

Happy either way — if (2), what's the right one-paragraph explanation?

also, in reference to this question, I don't personally think we need to give a full explanation as to why this is the design. it's just to add an extra layer of security so that only app owners can send push notifications to their app. without this, anyone who knows the bundle id could theoretically send push notifications to an app they don't own

shannonbradshaw and others added 5 commits May 28, 2026 13:20
The "import that fragment" step was vague. Replace with the actual
click sequence the configuration-block dialog uses (`+` →
**Configuration block** → search → **Add fragment**) and link to the
existing fragments how-to for the "create a fragment" half of the
step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The "the Viam mobile app re-uploads if the stored token is older
than 30 days" detail came from internal mobile-app code; it can't
be verified from public source and is implementation detail that
third-party app authors should choose for themselves. Replace with
generic guidance to pick a cadence on app startup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ements

The Required-fields table stated `FirebaseMessaging.getToken()`,
`getAPNSToken()`, `android.id`/`device_info_plus`, and
`identifierForVendor` as if they were Viam requirements. They are
the Viam mobile app's choices and one valid pattern per platform.
Reframe to separate the Viam requirement (an FCM token; a stable
device identifier) from the Viam-mobile-app implementation.

Surfaced by the identifier sweep during the Playbook 1 pass: these
identifiers do not appear in any in-scope public repo and were
sourced to the private viam-mobile repo only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three Missing/Prose findings surfaced by walking the page as a
first-time reader:

- F-WALK-1: Prereqs list mentioned `viam login` but left readers
  staring at `--org-id <your-org-id>` placeholders with no path to
  find their org ID. Added one bullet pointing to app.viam.com and
  `viam organizations list`.
- F-WALK-2: Section 3 implied (correctly) that the fragment's
  owning org must match the Firebase-config-owning org, but did
  not name the cross-org case. Added a one-sentence clarification
  that the check compares the fragment's owner, not the machine's.
- F-WALK-3: Section 5 verify step did not point readers to the
  Troubleshoot table for the "no notification arrived" case. Added
  a one-line pointer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

safe to build This pull request is marked safe to build from a trusted zone

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants