Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

CU-868f7hkrj Fixed Novu provider for ios and bugfix for voice.#237

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ucswift merged 3 commits intomasterfromdevelop
Aug 17, 2025

Conversation

@ucswift
Copy link
Member

@ucswiftucswift commentedAug 17, 2025
edited by coderabbitaibot
Loading

Summary by CodeRabbit

  • New Features

    • Added a new APNS provider identifier for responder notifications.
  • Improvements

    • Push notifications expanded with iOS-specific APNS overrides, unified payload structure, consistent .wav sounds, badge/category handling, and critical alert support.
    • Android payloads standardized for clearer data fields.
  • Refactor

    • Outbound voice call flow converted to asynchronous operations and now returns success status to improve reliability and scalability.

@request-info
Copy link

Thanks for opening this, but we'd appreciate a little more information. Could you update it with more details?

@coderabbitai
Copy link
Contributor

coderabbitaibot commentedAug 17, 2025
edited
Loading

Walkthrough

Converted outbound voice provider API from synchronous to asynchronous returning Task, updated CommunicationService to await it, implemented async Twilio calls in the Number provider, reworked NovuProvider notification payloads (added apns overrides and simplified sound naming), and added a NovuResponderApnsProviderId field to ChatConfig.

Changes

Cohort / File(s)Summary
Outbound Voice: Async API migration
Core/Resgrid.Model/Providers/IOutboundVoiceProvider.cs,Core/Resgrid.Services/CommunicationService.cs,Providers/Resgrid.Providers.Number/OutboundVoiceProvider.cs
Interface method changed fromvoid CommunicateCall(...) toTask<bool> CommunicateCallAsync(...). CommunicationService now awaits the async call. Number provider implementation converted toasync Task<bool>, uses TwilioCreateAsync calls, returns boolean success/failure with earlyfalse exits.
Novu notification payload adjustments
Providers/Resgrid.Providers.Messaging/NovuProvider.cs
SendNotification rebuilt to construct a single serialized payload string; renamed/usedchannelName; addedapns overrides (badge, sound using.wav, category, eventCode, critical), moved Android fields intodata, removed legacy/unused blocks; no public API signature changes.
Configuration addition
Core/Resgrid.Config/ChatConfig.cs
Addedpublic static string NovuResponderApnsProviderId = "" field to ChatConfig.

Sequence Diagram(s)

sequenceDiagram  participant Caller as CommunicationService.SendCallAsync  participant Voice as IOutboundVoiceProvider  participant Carrier as Telephony API  Caller->>Voice: CommunicateCallAsync(deptNumber, profile, call)  activate Voice  Voice->>Carrier: CreateCallAsync(normalizedNumber, call details)  Carrier-->>Voice: result (success/failure)  deactivate Voice  Voice-->>Caller: Task<bool> (success/failure)
Loading
sequenceDiagram  participant App as AnyService  participant Novu as NovuProvider  participant Push as Novu API  App->>Novu: SendNotification(eventCode, data)  Novu->>Novu: Build payload (channelName, fcm/android/apns overrides, sound .wav)  Novu->>Push: POST /events/trigger with payloadString  Push-->>Novu: HTTP response  Novu-->>App: Result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

I thump my paws, the calls now wait,
Async hops tidy up the state.
Twilio answers, true or false,
Novu hums with APNS pulse.
A rabbit grins — the push is great. 🐇


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between99d6f6f and16571c2.

📒 Files selected for processing (1)
  • Providers/Resgrid.Providers.Messaging/NovuProvider.cs (6 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • Providers/Resgrid.Providers.Messaging/NovuProvider.cs
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branchdevelop

🪧 Tips

Chat

There are 3 ways to chat withCodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag@coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag@coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on oursupport page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type@coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add@coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add@coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add@coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a.coderabbit.yaml file to the root of your repository.
  • Please see theconfiguration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation:# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit ourStatus Page to check the current availability of CodeRabbit.
  • Visit ourDocumentation for detailed information on how to use CodeRabbit.
  • Join ourDiscord Community to get help, request features, and share feedback.
  • Follow us onX/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🔭 Outside diff range comments (2)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (2)

198-201:User APNS provider ID appears incorrect (uses Unit provider ID).

UpdateUserSubscriberApns passesChatConfig.NovuUnitApnsProviderId for a user subscriber. GivenUpdateUserSubscriberFcm usesNovuResponderFcmProviderId, the APNS counterpart should likely be the responder/user APNS provider ID, not the unit one. This likely mis-associates user devices to the unit integration in Novu.

Apply this diff ifChatConfig.NovuResponderApnsProviderId exists:

-      return await UpdateSubscriberApns($"{code}_User_{userId}", token, ChatConfig.NovuUnitApnsProviderId);+      return await UpdateSubscriberApns($"{code}_User_{userId}", token, ChatConfig.NovuResponderApnsProviderId);

If the responder APNS provider ID isn’t defined in ChatConfig, please confirm the intended value and adjust accordingly.


320-349:Restore iOS .caf sound files in NovuProvider and honor enableCustomSounds

The other providers still emit.caf for iOS while NovuProvider now hard-codes only.wav, which will break any iOS app bundling.caf assets. Also, theenableCustomSounds flag is passed into your public API but never used—consider falling back to a generic “beep” when it’s disabled.

• File: Providers/Resgrid.Providers.Messaging/NovuProvider.cs
Method: GetSoundFileNameFromType(Platforms platform, string type)

Diff suggestion:

     private string GetSoundFileNameFromType(Platforms platform, string type)     {+        // iOS assets are .caf; others use .wav+        var ext = platform == Platforms.iOS ? ".caf" : ".wav";          if (type == ((int)PushSoundTypes.CallEmergency).ToString())         {-            return "callemergency.wav";+            return "callemergency" + ext;         }         else if (type == ((int)PushSoundTypes.CallHigh).ToString())         {-            return "callhigh.wav";+            return "callhigh" + ext;         }         else if (type == ((int)PushSoundTypes.CallMedium).ToString())         {-            return "callmedium.wav";+            return "callmedium" + ext;         }         else if (type == ((int)PushSoundTypes.CallLow).ToString())         {-            return "calllow.wav";+            return "calllow" + ext;         }         else if (type == ((int)PushSoundTypes.Notifiation).ToString())         {-            return "notification.wav";+            return "notification" + ext;         }         else if (type == ((int)PushSoundTypes.Message).ToString())         {-            return "message.wav";+            return "message" + ext;         }         else         {-            return $"{type}.wav";+            return $"{type}{ext}";         }     }

Also, consider updating this method signature to accept the existingenableCustomSounds parameter and, when it’sfalse, return a generic"beep" sound (e.g."beep.caf" on iOS,"beep.wav" elsewhere).

🧹 Nitpick comments (6)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (3)

352-359:Unused helper (FormatForAndroidNativePush) and stale Android sound handling.

This helper appears unused after the refactor and the new FCM overrides no longer set a custom sound for Android (only defaultSound). If custom Android sounds are desired when enableCustomSounds is true, this path needs to be wired back in; otherwise, remove the unused helper to reduce dead code.


377-467:Legacy payload builders likely dead code; consider removal or alignment.

CreateAndroidNotification and CreateAppleNotification seem to be legacy builders that aren’t used after moving to Novu “overrides”. Keeping both shapes increases drift and confusion.

  • Either remove these builders if definitively unused, or
  • Reuse them to assemble the override payload to ensure one source of truth for fields, sound, priorities, and category mapping.

21-58:Prefer IHttpClientFactory or a shared HttpClient for resiliency and testability.

Multiple methods new-up HttpClient and set common headers. Consider injecting IHttpClientFactory (or an HttpClient) and centralizing common headers to:

  • Avoid socket exhaustion from frequent instantiation
  • Improve testability (mock handlers)
  • Consolidate auth/idempotency header logic

I can draft a minimal refactor using IHttpClientFactory if desired.

Core/Resgrid.Services/CommunicationService.cs (1)

205-213:Awaiting the voice call is correct; consider handling the boolean result.

You’re now awaiting the async voice call, but discarding the boolean. If the provider indicates failure (returns false), you could log or take fallback action.

Example:

  • var success = await _outboundVoiceProvider.CommunicateCallAsync(...);
  • if (!success) Logging.LogWarning("Outbound voice call failed for {UserId}/{CallId}");
Providers/Resgrid.Providers.Number/OutboundVoiceProvider.cs (2)

42-44:Consider basing success on Twilio response and catching exceptions here.

Right now the method returns true immediately after CreateAsync. If Twilio returns an error (exception thrown) it will bubble up; if it succeeds but Twilio marks the call failed quickly, you still return true. Optionally:

  • Wrap Twilio CreateAsync in try/catch here and return false on exception, logging the error.
  • Check phoneCall.Status or ErrorCode to decide success (best-effort).

I can provide a diff adding try/catch and minimal status validation if you want stricter semantics for the boolean.

Also applies to: 56-58


33-59:Minor duplication between mobile/home call paths.

The two branches differ only by the target number accessor. Extracting a small local function to create the call reduces duplication and centralizes options assembly.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between3a4fde6 andf6189ef.

📒 Files selected for processing (4)
  • Core/Resgrid.Model/Providers/IOutboundVoiceProvider.cs (1 hunks)
  • Core/Resgrid.Services/CommunicationService.cs (1 hunks)
  • Providers/Resgrid.Providers.Messaging/NovuProvider.cs (5 hunks)
  • Providers/Resgrid.Providers.Number/OutboundVoiceProvider.cs (4 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.cs

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.cs: Prefer functional patterns and immutable data where appropriate in C#
Use modern C# features appropriately
Use meaningful, descriptive names for types, methods, and parameters; avoid unclear abbreviations
Separate state from behavior (e.g., use records for state and place operations in separate static classes)
Prefer pure methods over methods with side effects
Use extension methods appropriately for domain-specific operations
Design for testability; avoid hidden dependencies inside methods and prefer explicit, pure functions
Minimize constructor injection; keep the number of injected dependencies small
Prefer composition with interfaces to extend behavior

Files:

  • Core/Resgrid.Model/Providers/IOutboundVoiceProvider.cs
  • Core/Resgrid.Services/CommunicationService.cs
  • Providers/Resgrid.Providers.Number/OutboundVoiceProvider.cs
  • Providers/Resgrid.Providers.Messaging/NovuProvider.cs
🧬 Code Graph Analysis (2)
Providers/Resgrid.Providers.Number/OutboundVoiceProvider.cs (2)
Core/Resgrid.Model/Providers/IOutboundVoiceProvider.cs (1)
  • Task (7-7)
Core/Resgrid.Config/NumberProviderConfig.cs (1)
  • NumberProviderConfig (5-54)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (2)
Providers/Resgrid.Providers.Bus/NotificationProvider.cs (1)
  • GetSoundFileNameFromType (371-424)
Providers/Resgrid.Providers.Bus/UnitNotificationProvider.cs (1)
  • GetSoundFileNameFromType (400-460)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (6)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (2)

241-249:Verify FCM override property names and priority values.

In the overrides you’re setting:

  • android.priority = "high"/"normal" (OK for FCM legacy)
  • notification.priority = "max"/"default"
  • notification.channelId (camelCase)
  • notification.defaultSound

FCM (v1) typically expects:

  • notification.priority as an enum (PRIORITY_MAX/DEFAULT) or numericnotification_priority in some schemas
  • notification.channel_id (snake_case)
  • sound as "default" or a file name (not defaultSound)

Given this is Novu’s overrides format, please verify the expected schema. If Novu passes these straight to FCM, the current keys/values may be ignored.

If Novu expects snake_case and FCM-aligned fields, consider:

-                  channelId = type,-                  defaultSound = true,+                  channel_id = type,+                  default_sound = true,                   sticky = channelName == "calls" ? true : false,-                  priority = channelName == "calls" ? "max" : "default",+                  notification_priority = channelName == "calls" ? 5 : 3,

Please validate against Novu’s documentation for fcm overrides; if their schema expects the current keys, ignore this suggestion. I can help adjust once we confirm the correct schema.


260-271:APNS override shape: confirm placement of custom fields and sound format.

You added an apns block with badge, sound (name/critical/volume), category, type, and eventCode. Two concerns:

  • Custom fields like type and eventCode may need to be top-level (outside aps) but still inside apns payload, or under a specific payload node, depending on Novu’s schema.
  • Sound naming: you’re using GetSoundFileNameFromType(Platforms.iOS, type) which now returns .wav (see below). If the iOS app bundles .caf files (common), .wav may not exist and sound won’t play.

Please confirm Novu’s APNS override schema and ensure the app bundles the sound files with matching extensions. If the app uses .caf, revert to .caf for iOS (see suggestion below).

Core/Resgrid.Model/Providers/IOutboundVoiceProvider.cs (2)

7-7:Async, result-bearing signature is a good move.

Switching to Task enables callers to await and react to success/failure. API surface looks appropriate.


1-9:No lingering CommunicateCall usages found—migration to CommunicateCallAsync is complete
I ran the provided searches and confirmed:

  • No calls to the old CommunicateCall(...)
  • Only the new CommunicateCallAsync(...) exists in the interface, implementation, and call sites

All synchronous references have been removed.

Providers/Resgrid.Providers.Number/OutboundVoiceProvider.cs (2)

15-16:Async conversion and Task return look good.

This aligns with the interface change and enables proper awaiting upstream.


25-33:Verify E.164 normalization and plus-prefixing.

Twilio expects E.164; current logic only adds a leading '+' for some 11-digit numbers. If numbers can enter as 10 digits (US local) or lack '+', consider central normalization to a canonical format before this provider (preferred), or enforce here.

If normalization isn’t guaranteed upstream, add a conservative guard, e.g., prepend '+' when already in international format. I can propose a helper if needed.

Copy link
Contributor

@coderabbitaicoderabbitaibot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🔭 Outside diff range comments (1)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (1)

320-349:Restore platform‐specific sound file extensions in NovuProvider.GetSoundFileNameFromType

The current implementation always returns “.wav”, which will break iOS custom sounds (other providers use “.caf” on iOS and “.wav”/“.mp3” on Android). Update as follows:

• File: Providers/Resgrid.Providers.Messaging/NovuProvider.cs
Method: GetSoundFileNameFromType (lines 320–349)

Apply this diff to match NotificationProvider/UnitNotificationProvider mapping:

   private string GetSoundFileNameFromType(Platforms platform, string type)   {-    if (type == ((int)PushSoundTypes.CallEmergency).ToString())-    {-      return "callemergency.wav";-    }+    if (type == ((int)PushSoundTypes.CallEmergency).ToString())+    {+      if (platform == Platforms.iOS) return "callemergency.caf";+      return "callemergency.wav";+    }     else if (type == ((int)PushSoundTypes.CallHigh).ToString())     {-      return "callhigh.wav";+      if (platform == Platforms.iOS) return "callhigh.caf";+      return "callhigh.mp3";     }     else if (type == ((int)PushSoundTypes.CallMedium).ToString())     {-      return "callmedium.wav";+      if (platform == Platforms.iOS) return "callmedium.caf";+      return "callmedium.mp3";     }     else if (type == ((int)PushSoundTypes.CallLow).ToString())     {-      return "calllow.wav";+      if (platform == Platforms.iOS) return "calllow.caf";+      return "calllow.mp3";     }     else if (type == ((int)PushSoundTypes.Notifiation).ToString())     {-      return "notification.wav";+      if (platform == Platforms.iOS) return "notification.caf";+      return "notification.mp3";     }     else if (type == ((int)PushSoundTypes.Message).ToString())     {-      return "message.wav";+      if (platform == Platforms.iOS) return "message.caf";+      return "message.mp3";     }     else     {-      return $"{type}.wav";+      if (platform == Platforms.iOS) return $"{type}.caf";+      return $"{type}.mp3";     }   }

If your iOS bundle only contains “.wav” assets, adjust the mapping accordingly to avoid missing sound files.

🧹 Nitpick comments (2)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (2)

4-4:Remove unused using RabbitMQ.Client

RabbitMQ.Client isn’t referenced in this file. Drop the import to keep things tidy.

Apply this diff:

-using RabbitMQ.Client;

263-267:enableCustomSounds parameter is ignored for APNS

The SendNotification signature includes enableCustomSounds, but APNS sound is always set to a custom file. If you intended to honor the flag (e.g., use system default when false), gate the sound block accordingly.

Apply this diff to conditionally include the sound block:

-                sound = new-                {-                  name = GetSoundFileNameFromType(Platforms.iOS, type),-                  critical = channelName == "calls" ? 1 : 0,-                  volume = 1.0f-                },+                sound = enableCustomSounds ? new+                {+                  name = GetSoundFileNameFromType(Platforms.iOS, type),+                  critical = channelName == "calls" ? 1 : 0,+                  volume = 1.0f+                } : null,

Also set NullValueHandling.Ignore to avoid emitting null sound.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and betweenf6189ef and99d6f6f.

📒 Files selected for processing (2)
  • Core/Resgrid.Config/ChatConfig.cs (1 hunks)
  • Providers/Resgrid.Providers.Messaging/NovuProvider.cs (6 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**/*.cs

📄 CodeRabbit Inference Engine (.github/copilot-instructions.md)

**/*.cs: Prefer functional patterns and immutable data where appropriate in C#
Use modern C# features appropriately
Use meaningful, descriptive names for types, methods, and parameters; avoid unclear abbreviations
Separate state from behavior (e.g., use records for state and place operations in separate static classes)
Prefer pure methods over methods with side effects
Use extension methods appropriately for domain-specific operations
Design for testability; avoid hidden dependencies inside methods and prefer explicit, pure functions
Minimize constructor injection; keep the number of injected dependencies small
Prefer composition with interfaces to extend behavior

Files:

  • Core/Resgrid.Config/ChatConfig.cs
  • Providers/Resgrid.Providers.Messaging/NovuProvider.cs
🧬 Code Graph Analysis (1)
Providers/Resgrid.Providers.Messaging/NovuProvider.cs (3)
Core/Resgrid.Config/ChatConfig.cs (1)
  • ChatConfig (3-21)
Providers/Resgrid.Providers.Bus/UnitNotificationProvider.cs (1)
  • GetSoundFileNameFromType (400-460)
Providers/Resgrid.Providers.Bus/NotificationProvider.cs (1)
  • GetSoundFileNameFromType (371-424)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (4)
Core/Resgrid.Config/ChatConfig.cs (1)

16-16:Config key addition aligns with provider usage; ensure it's populated at runtime

The new NovuResponderApnsProviderId matches the new usage in NovuProvider. Please ensure this is wired into your configuration (appsettings, env vars, secrets) in all environments—an empty string will cause Novu credential updates to fail.

Would you like me to scan the repo for where ChatConfig values are populated and open a follow-up item if this one isn’t being set?

Providers/Resgrid.Providers.Messaging/NovuProvider.cs (3)

200-201:Correct provider ID for User APNS updates

Good catch switching to NovuResponderApnsProviderId; this aligns user APNS tokens with the responder integration.

Confirm that Core/Resgrid.Config/ChatConfig.NovuResponderApnsProviderId is set for all environments; otherwise APNS token updates will silently fail (HTTP 4xx).


225-225:Rename to channelName improves clarity

Using channelName consistently improves readability across the FCM/iOS branching logic.


280-284:Serialize once and reuse: good optimization

Serializing the payload once into payloadString simplifies the code and avoids repeated serialization work.

Comment on lines +259 to +271
{
badge=count,
sound=new
{
name=GetSoundFileNameFromType(Platforms.iOS,type),
critical=channelName=="calls"?1:0,
volume=1.0f
},
type=type,
category=channelName,
eventCode=eventCode,
},

Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify APNS override shape matches Novu’s schema

The overrides.apns block sets badge/sound/category directly. Novu’s schema for APNS overrides may expect an aps payload wrapper (e.g., overrides.apns.payload.aps.{badge,sound,category}) and custom fields (eventCode/type) outside aps. If this shape is off, APNS may ignore the fields.

Would you verify against Novu’s overrides schema and example for APNS?


🌐 Web query:

What is the expected JSON schema for the "overrides.apns" payload in Novu's v1 events/trigger API? Provide an example including badge, sound with critical/volume, and category.

💡 Result:

The expected JSON schema for theoverrides.apns payload inNovu's v1 events/trigger API should closely follow theApnsConfig structure used by Firebase Cloud Messaging (FCM), as Novu internally uses this format for push overrides[1][3]. This allows you to specify detailed APNs (Apple Push Notification Service) payload options, such asbadge,sound (with critical and volume), andcategory.

Example JSON Structure

{"overrides": {"apns": {"payload": {"aps": {"badge":5,"sound": {"critical":1,"name":"default","volume":0.8          },"category":"MY_CATEGORY"        }      }    }  }}

Key fields explanation:

  • badge
    Integer. Specifies the badge number for the app icon.

  • sound
    Object. Includes:

    • "name": String, the sound file name ("default" or custom).
    • "critical": Integer (1 for critical alert, 0 for non-critical).
    • "volume": Float (0.0 to 1.0).
  • category
    String. Used for grouping or to enable specific notification actions.

Schema Reference

The schema should match:

{"overrides": {"apns": {"payload": {"aps": {"badge":<integer>,"sound": {"critical":<integer>,   // 0 or 1"name":<string>,"volume":<float>        // 0.0 through 1.0          },"category":<string>        }      }    }  }}
  • Wrap these settings in theaps payload object as per APNs and FCM standards[1][3].
  • Additional APNs fields (e.g.,alert,thread-id, etc.) can also be provided in theaps dictionary.

Notes

  • Critical sound notifications require the app to have the proper entitlement.
  • Novu processes this JSON as-is and relays it to APNs using the FCM or relevant provider integration[1][3].

For further customizations or to validate your payload, refer to theApnsConfig documentation[3].

Citations:


Adjust APNS override to include thepayload.aps wrapper

The currentapns object is not nested underpayload.aps as required by Novu’s schema. Badge, sound, and category must live insidepayload.aps, with custom fields (type,eventCode) alongsideaps.

Please update in Providers/Resgrid.Providers.Messaging/NovuProvider.cs (lines 259–271):

-   apns = new-   {-       badge = count,-       sound = new-       {-           name = GetSoundFileNameFromType(Platforms.iOS, type),-           critical = channelName == "calls" ? 1 : 0,-           volume = 1.0f-       },-       type = type,-       category = channelName,-       eventCode = eventCode,-   },+   apns = new+   {+       payload = new+       {+           aps = new+           {+               badge = count,+               sound = new+               {+                   name = GetSoundFileNameFromType(Platforms.iOS, type),+                   critical = channelName == "calls" ? 1 : 0,+                   volume = 1.0f+               },+               category = channelName+           },+           type = type,+           eventCode = eventCode+       }+   },

This aligns with the expected JSON:

"overrides": {"apns": {"payload": {"aps": {"badge":5,"sound": {"critical":1,"name":"default","volume":0.8        },"category":"MY_CATEGORY"      },"type":"<your_type>","eventCode":"<your_eventCode>"    }  }}

@ucswift
Copy link
MemberAuthor

Approve

Copy link

@github-actionsgithub-actionsbot left a comment

Choose a reason for hiding this comment

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

This PR is approved.

@ucswiftucswift merged commit963535b intomasterAug 17, 2025
5 of 6 checks passed
@coderabbitaicoderabbitaibot mentioned this pull requestAug 27, 2025
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@coderabbitaicoderabbitai[bot]coderabbitai[bot] left review comments

@github-actionsgithub-actions[bot]github-actions[bot] approved these changes

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

2 participants

@ucswift

[8]ページ先頭

©2009-2025 Movatter.jp