Skip to content

Add iOS Live Activity push support#309

Open
bgoncal wants to merge 19 commits into
mainfrom
pr-278
Open

Add iOS Live Activity push support#309
bgoncal wants to merge 19 commits into
mainfrom
pr-278

Conversation

@bgoncal
Copy link
Copy Markdown
Member

@bgoncal bgoncal commented Jun 3, 2026

Continuation from PR: #278
iOS PR: home-assistant/iOS#4696
Adds data model translator to delivery live activity push to iOS.

rwarner and others added 9 commits April 28, 2026 12:44
Live Activity push tokens from ActivityKit are direct APNs tokens
(hex-encoded), not FCM tokens. The existing iOSV1 endpoint cannot
handle them — this adds a dedicated iOSLiveActivityV1 endpoint that
sends directly to the APNs HTTP/2 API using JWT authentication,
bypassing FCM entirely.

New files:
- apns.js: APNs HTTP/2 client with ES256 JWT auth (Node built-ins
  only, no new dependencies). JWT cached and rotated every 45 min.
  HTTP/2 sessions cached per environment (sandbox/production).
- live-activity.js: payload builder for start/update/end events.
  Maps content_state fields to the HALiveActivityAttributes struct
  expected by the iOS companion app. Sets apns-push-type: liveactivity
  and routes to correct APNs topic using bundle ID from registration_info.

Updated files:
- handlers.js: adds handleLiveActivityRequest(), which validates hex
  APNs tokens, applies rate limiting, sends via apns.js, and handles
  BadDeviceToken (400) without error reporting.
- index.js: exports iOSLiveActivityV1 Cloud Function.
- webapp.js: adds /api/sendPush/iOS/liveActivity/v1 route for local dev.

Tests: 20 tests across fixture-driven createPayload tests and
handleLiveActivityRequest integration tests covering success, token
validation, rate limiting, APNs error mapping, and end-event
rate-limit bypass.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves createLiveActivityPayload() from the standalone live-activity.js
into ios.js as a second export, keeping all iOS-specific logic in one
place consistent with the existing android.js/ios.js pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Follows the existing test naming convention (legacy.test.js -> legacy.js)
now that the Live Activity payload builder lives in ios.js.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix misleading comment in webapp.js (was "Import the functions from index.js")
- Validate APNs token length (must be exactly 64 hex chars) in isValidApnsToken; add test
- Normalize apnsEnvironment to 'sandbox'|'production' to prevent unbounded session cache growth
- Guard JSON.parse in apns.js against non-JSON APNs responses
- Fix test: pass body overrides flat to createLiveActivityRequest (not nested under body:)
- Add explanatory comments throughout apns.js, ios.js, and handlers.js for non-obvious decisions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Firebase Admin SDK v13.5.0+ supports the liveActivityToken field in the
apns config object, which tells FCM to automatically set
apns-push-type: liveactivity and route the notification to APNs. This
eliminates the need for a custom direct APNs HTTP/2 client.

Changes:
- Delete apns.js (custom HTTP/2 + JWT APNs client) — no longer needed
- Bump firebase-admin from ^12.1.0 to ^13.5.0
- Rewrite ios.js: createPayload detects live_activity_token in request
  body and builds FCM payload with apns.liveActivityToken (camelCase)
- Remove handleLiveActivityRequest from handlers.js — existing
  handleRequest + messaging.send() handles everything
- Remove iOSLiveActivityV1 endpoint from index.js and webapp.js
- Rewrite tests for FCM-based delivery path
- Update fixtures to use FCM payload structure

The relay server no longer needs APNS_TEAM_ID, APNS_KEY_ID, or
APNS_PRIVATE_KEY environment variables. HA core sends both the FCM
registration token (push_token) and the Live Activity APNs token
(live_activity_token) to the same /api/sendPush/iOS/v1 endpoint.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All live activity pushes (start, update, end) now count against the rate
limit. End events still have an APNs delivery cost, so exempting them was
not justified.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
HALiveActivityAttributes must only appear in push-to-start payloads —
APNs rejects update/end payloads that include attributes-type.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@bgoncal bgoncal self-assigned this Jun 3, 2026
Copilot AI review requested due to automatic review settings June 3, 2026 15:42
@bgoncal bgoncal mentioned this pull request Jun 3, 2026
4 tasks
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds iOS Live Activity push payload translation and accompanying fixture-driven/integration tests so the relay can send ActivityKit Live Activity updates through FCM’s apns.liveActivityToken support.

Changes:

  • Add Live Activity detection and payload builder in functions/ios.js (including aps mapping and a dedicated analytics label).
  • Add extensive Jest coverage for Live Activity payload construction and handleRequest integration, plus JSON fixtures.
  • Minor cleanup/housekeeping updates (webapp handler comment, dependency entry formatting).

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
functions/webapp.js Updates an inline comment to reflect handler imports.
functions/ios.js Adds Live Activity payload builder and content-state translation logic.
functions/test/ios.test.js Adds fixture-driven and integration tests for iOS Live Activity payloads.
functions/test/fixtures/live-activity/start-push-to-start.json Adds “start” Live Activity fixture input/expectations.
functions/test/fixtures/live-activity/update-basic.json Adds basic “update” Live Activity fixture input/expectations.
functions/test/fixtures/live-activity/update-full.json Adds full-field “update” Live Activity fixture input/expectations.
functions/test/fixtures/live-activity/end.json Adds “end” Live Activity fixture input/expectations.
functions/package.json Updates dependencies, but currently with a formatting inconsistency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread functions/test/ios.test.js Outdated
Comment thread functions/package.json
Comment thread functions/ios.js Outdated
Comment thread functions/ios.js Outdated
Comment thread functions/ios.js Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented Jun 4, 2026

Codecov Report

❌ Patch coverage is 90.36145% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.98%. Comparing base (142579d) to head (51da700).

Files with missing lines Patch % Lines
functions/live-activity.js 93.42% 5 Missing ⚠️
functions/legacy.js 57.14% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #309      +/-   ##
==========================================
+ Coverage   77.24%   78.98%   +1.73%     
==========================================
  Files           9       10       +1     
  Lines         545      628      +83     
  Branches      147      197      +50     
==========================================
+ Hits          421      496      +75     
- Misses        105      113       +8     
  Partials       19       19              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@bgoncal bgoncal marked this pull request as ready for review June 4, 2026 22:28
@bgoncal bgoncal marked this pull request as draft June 5, 2026 09:43
@bgoncal bgoncal marked this pull request as ready for review June 5, 2026 12:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants