push-notifications — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited push-notifications (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are in AUTONOMOUS MODE. Do NOT ask questions. Execute the full pipeline below without pausing for user input. Make reasonable decisions using sensible defaults.
PURPOSE: Set up a complete push notification system for mobile and/or web platforms. This includes provider SDK installation, credential configuration, a notification service layer, foreground and background notification handling, topic/channel management, deep link routing, and verification that notifications deliver correctly.
INPUT: $ARGUMENTS
The user may specify:
If no arguments, auto-detect the platform and use FCM as the default provider.
=== PHASE 1: PLATFORM DETECTION ===
Step 1.1 — Detect Client Platform
Scan for project files to determine the platform:
| File / Pattern | Platform | Default Provider |
|---|---|---|
| pubspec.yaml | Flutter (iOS + Android + Web) | FCM via firebase_messaging |
| package.json with "react-native" | React Native (iOS + Android) | FCM via @react-native-firebase/messaging |
| package.json with "expo" | Expo (React Native) | Expo Notifications (wraps FCM/APNs) |
| package.json with "next" or "react" | Web | FCM via firebase/messaging or Web Push API |
| Podfile / *.xcodeproj | Native iOS | APNs directly or FCM |
| build.gradle with android | Native Android | FCM |
Record: PLATFORM, CLIENT_ROOT, PROVIDER
Step 1.2 — Detect Backend
Scan for a backend server (notifications need a server component):
Record: BACKEND_FRAMEWORK, BACKEND_ROOT
Step 1.3 — Check Existing Push Setup
Search for existing push notification code:
expo-notifications, firebase-admin
If complete push notification system exists, report it and exit. If partial, identify gaps and extend.
=== PHASE 2: CLIENT SDK INSTALLATION ===
Step 2.1 — Install Client SDK
Based on platform and provider:
Flutter + FCM:
flutter pub add firebase_messaging firebase_core
flutter pub add flutter_local_notifications # for foreground displayEnsure firebase_core is initialized in main.dart. Run flutterfire configure if Firebase is not yet configured.
React Native + FCM:
npm install @react-native-firebase/app @react-native-firebase/messaging
cd ios && pod installExpo + Expo Notifications:
npx expo install expo-notifications expo-device expo-constantsWeb + FCM:
npm install firebaseCreate public/firebase-messaging-sw.js service worker.
Native iOS + APNs:
OneSignal (any platform):
flutter pub add onesignal_flutternpm install react-native-onesignalStep 2.2 — Install Server SDK
On the backend (for sending notifications):
FCM (via firebase-admin):
npm install firebase-adminpip install firebase-adminAPNs (direct):
npm install apn or npm install @parse/node-apnpip install apns2OneSignal:
npm install @onesignal/node-onesignalpip install onesignal-sdk=== PHASE 3: CREDENTIAL CONFIGURATION ===
Step 3.1 — Configure Provider Credentials
FCM:
FIREBASE_PROJECT_ID=
FIREBASE_PRIVATE_KEY=
FIREBASE_CLIENT_EMAIL= NEXT_PUBLIC_FIREBASE_VAPID_KEY=APNs:
APNS_KEY_ID=
APNS_TEAM_ID=
APNS_KEY_PATH=./certs/AuthKey.p8
APNS_BUNDLE_ID=com.yourapp.idOneSignal:
ONESIGNAL_APP_ID=
ONESIGNAL_API_KEY=Add all variables to .env.example with descriptions.
Step 3.2 — Platform-Specific Configuration
Flutter / Android:
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="default_channel"/>Flutter / iOS:
React Native / Android:
React Native / iOS:
Web:
importScripts('https://www.gstatic.com/firebasejs/10.x/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.x/firebase-messaging-compat.js');
firebase.initializeApp({ /* config */ });
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
self.registration.showNotification(payload.notification.title, {
body: payload.notification.body,
icon: '/icon-192x192.png',
});
});=== PHASE 4: NOTIFICATION SERVICE (SERVER) ===
Step 4.1 — Create Notification Service
Create a server-side notification service:
class NotificationService {
async sendToDevice(params: {
token: string;
title: string;
body: string;
data?: Record<string, string>;
imageUrl?: string;
badge?: number;
sound?: string;
channelId?: string;
}): Promise<{ success: boolean; messageId?: string }>
async sendToTopic(params: {
topic: string;
title: string;
body: string;
data?: Record<string, string>;
}): Promise<{ success: boolean; messageId?: string }>
async sendToMultiple(params: {
tokens: string[];
title: string;
body: string;
data?: Record<string, string>;
}): Promise<{ successCount: number; failureCount: number; failedTokens: string[] }>
async subscribeToTopic(params: {
tokens: string[];
topic: string;
}): Promise<{ success: boolean }>
async unsubscribeFromTopic(params: {
tokens: string[];
topic: string;
}): Promise<{ success: boolean }>
}The service MUST:
Step 4.2 — Create Device Token Management
Create an API endpoint and storage for device tokens:
Route: POST /api/notifications/register-device
Route: DELETE /api/notifications/unregister-device
Create a device token model/table:
DeviceToken {
id: string
userId: string
token: string (unique)
platform: "ios" | "android" | "web"
createdAt: DateTime
lastUsedAt: DateTime
}Step 4.3 — Create Notification API Endpoints
Route: POST /api/notifications/send
Route: POST /api/notifications/send-topic
=== PHASE 5: CLIENT-SIDE HANDLING ===
Step 5.1 — Permission Request
Create a permission request flow:
Flutter:
final messaging = FirebaseMessaging.instance;
final settings = await messaging.requestPermission(
alert: true, badge: true, sound: true,
provisional: false, // set true for quiet notifications on iOS
);
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
final token = await messaging.getToken();
// Send token to backend
}React Native:
const authStatus = await messaging().requestPermission();
if (authStatus === messaging.AuthorizationStatus.AUTHORIZED) {
const token = await messaging().getToken();
// Send token to backend
}Web:
const permission = await Notification.requestPermission();
if (permission === 'granted') {
const token = await getToken(messaging, { vapidKey: VAPID_KEY });
// Send token to backend
}The permission flow MUST:
Step 5.2 — Foreground Notification Handling
When the app is in the foreground, notifications are NOT displayed by default on most platforms. Create a foreground handler:
Flutter:
React Native:
Web:
Step 5.3 — Background Notification Handling
Configure background message handling:
Flutter:
React Native:
Web:
Step 5.4 — Notification Tap / Open Handling
Handle what happens when a user taps a notification:
Flutter:
React Native:
Web:
=== PHASE 6: TOPICS AND CHANNELS ===
Step 6.1 — Create Topic Management
Define standard topics for the application:
TOPICS = {
GENERAL: 'general', // All users
ANNOUNCEMENTS: 'announcements', // Product announcements
MARKETING: 'marketing', // Promotional content (opt-in)
}Create a notification preferences screen/page:
Step 6.2 — Create Android Notification Channels
For Android (required for Android 8.0+):
Channels:
- default: General notifications (importance: high)
- messages: Chat messages (importance: high, vibration: true)
- updates: App updates (importance: default)
- marketing: Promotional (importance: low)Create channels during app initialization, before any notification is received.
Step 6.3 — Deep Link Configuration
Set up deep linking so notification taps navigate to the correct screen:
Flutter:
data: { route: '/orders/123', type: 'order_update' }
→ Navigate to OrderDetailScreen(orderId: '123')React Native:
Web:
The deep link handler MUST:
=== PHASE 7: VERIFICATION ===
Step 7.1 — Static Verification
Run the project's linter and type checker:
flutter analyzetsc --noEmit and npx eslint .Fix all errors introduced by the push notification integration.
Step 7.2 — Integration Checklist
Verify and report:
=== OUTPUT ===
Print the following summary:
Platform: [detected platform] Provider: [selected provider] Backend: [detected backend framework]
| File | Purpose |
|---|---|
| [path] | [description] |
| Variable | Purpose | Where to get it |
|---|---|---|
| [KEY] | [purpose] | [provider console URL] |
| Method | Path | Purpose |
|---|---|---|
| POST | /api/notifications/register-device | Register device token |
| DELETE | /api/notifications/unregister-device | Remove device token |
| POST | /api/notifications/send | Send to specific user |
| POST | /api/notifications/send-topic | Send to topic subscribers |
| Topic | Description | Default |
|---|---|---|
| general | All users | Subscribed |
| announcements | Product updates | Subscribed |
| marketing | Promotional | Opt-in |
firebase messaging:send --json '{"token":"...","notification":{"title":"Test"}}'=== NEXT STEPS ===
After push notification integration:
/email to add email as a fallback notification channel."/analytics-tracking to track notification open rates and engagement."/auth-provider to link notifications to authenticated users."/integrate audit to check overall integration health."=== DO NOT ===
============================================================ SELF-HEALING VALIDATION (max 3 iterations) ============================================================
After completing the integration, validate:
IF STILL FAILING after 3 iterations:
============================================================ SELF-EVOLUTION TELEMETRY ============================================================
After producing output, record execution metadata for the /evolve pipeline.
Check if a project memory directory exists:
~/.claude/projects/skill-telemetry.md in that memory directoryEntry format:
### /push-notifications — {{YYYY-MM-DD}}
- Outcome: {{SUCCESS | PARTIAL | FAILED}}
- Self-healed: {{yes — what was healed | no}}
- Iterations used: {{N}} / {{N max}}
- Bottleneck: {{phase that struggled or "none"}}
- Suggestion: {{one-line improvement idea for /evolve, or "none"}}Only log if the memory directory exists. Skip silently if not found. Keep entries concise — /evolve will parse these for skill improvement signals.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.