- Add contracts/NotificationContract.v1.ts (frozen TypeScript interface) - Add contracts/notification.v1.schema.json (JSON Schema) - Add contracts/notification.v1.hash (SHA-256 hash for integrity) - Add scripts/generate-contract-schema.js (schema generator) - Add scripts/check-contract.sh (validation script) Contract v1 is now frozen as single source of truth for cross-platform notification content. All platforms must conform to this contract. See docs/0017-Daily-Notification-Contract-Freeze.md for details.
134 lines
3.5 KiB
TypeScript
134 lines
3.5 KiB
TypeScript
/**
|
|
* NotificationContract.v1.ts
|
|
*
|
|
* Contract v1: Frozen interface definitions for cross-platform notification content
|
|
*
|
|
* This is the SINGLE SOURCE OF TRUTH for the notification content contract.
|
|
* Both Android and iOS MUST conform to this exact interface.
|
|
*
|
|
* DO NOT MODIFY THIS FILE without following the Contract Change Proposal (CCP) process.
|
|
* See docs/0017-Daily-Notification-Contract-Freeze.md
|
|
*
|
|
* @author Matthew Raymer
|
|
* @version 1.0.0
|
|
* @frozen true
|
|
*/
|
|
|
|
/**
|
|
* Notification content item (v1)
|
|
*
|
|
* Core data structure for notifications that the plugin can schedule and display.
|
|
* All times are in epoch milliseconds.
|
|
*
|
|
* @contract v1 - DO NOT MODIFY without CCP
|
|
*/
|
|
export interface NotificationContent {
|
|
/** Unique identifier for this notification */
|
|
id: string;
|
|
|
|
/** Notification title (required) */
|
|
title: string;
|
|
|
|
/** Notification body text (optional) */
|
|
body?: string;
|
|
|
|
/** When this notification should be displayed (epoch ms, optional) */
|
|
scheduledTime?: number;
|
|
|
|
/** When this content was fetched (epoch ms, required) */
|
|
fetchTime: number;
|
|
|
|
/** Optional image URL for rich notifications */
|
|
mediaUrl?: string;
|
|
|
|
/** Cache TTL in seconds (how long this content is valid) */
|
|
ttlSeconds?: number;
|
|
|
|
/** Deduplication key (for idempotency) */
|
|
dedupeKey?: string;
|
|
|
|
/** Notification priority level */
|
|
priority?: 'min' | 'low' | 'default' | 'high' | 'max';
|
|
|
|
/** Additional metadata (opaque to plugin) */
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
/**
|
|
* Reason why content fetch was triggered (v1)
|
|
*
|
|
* @contract v1 - DO NOT MODIFY without CCP
|
|
*/
|
|
export type FetchTrigger =
|
|
| 'background_work' // Background worker (WorkManager/BGTask)
|
|
| 'prefetch' // Prefetch before scheduled notification
|
|
| 'manual' // User-initiated refresh
|
|
| 'scheduled'; // Scheduled fetch
|
|
|
|
/**
|
|
* Context provided to fetcher about why fetch was triggered (v1)
|
|
*
|
|
* @contract v1 - DO NOT MODIFY without CCP
|
|
*/
|
|
export interface FetchContext {
|
|
/** Why the fetch was triggered */
|
|
trigger: FetchTrigger;
|
|
|
|
/** When notification is scheduled (if applicable, epoch ms) */
|
|
scheduledTime?: number;
|
|
|
|
/** When fetch was triggered (epoch ms) */
|
|
fetchTime: number;
|
|
|
|
/** Additional context from plugin (opaque) */
|
|
metadata?: Record<string, unknown>;
|
|
}
|
|
|
|
/**
|
|
* Scheduling policy configuration (v1)
|
|
*
|
|
* @contract v1 - DO NOT MODIFY without CCP
|
|
*/
|
|
export interface SchedulingPolicy {
|
|
/** How early to prefetch before scheduled notification (ms) */
|
|
prefetchWindowMs?: number;
|
|
|
|
/** Retry backoff configuration */
|
|
retryBackoff: {
|
|
/** Minimum delay between retries (ms) */
|
|
minMs: number;
|
|
/** Maximum delay between retries (ms) */
|
|
maxMs: number;
|
|
/** Exponential backoff multiplier */
|
|
factor: number;
|
|
/** Jitter percentage (0-100) */
|
|
jitterPct: number;
|
|
};
|
|
|
|
/** Maximum items to fetch per batch */
|
|
maxBatchSize?: number;
|
|
|
|
/** Deduplication window (ms) - prevents duplicate notifications */
|
|
dedupeHorizonMs?: number;
|
|
|
|
/** Default cache TTL if item doesn't specify (seconds) */
|
|
cacheTtlSeconds?: number;
|
|
|
|
/** Whether exact alarms are allowed (Android 12+) */
|
|
exactAlarmsAllowed?: boolean;
|
|
}
|
|
|
|
/**
|
|
* Contract metadata
|
|
*
|
|
* Used for runtime handshake and validation
|
|
*/
|
|
export const CONTRACT_V1 = {
|
|
version: 'v1',
|
|
schemaFile: 'contracts/notification.v1.schema.json',
|
|
hashFile: 'contracts/notification.v1.hash',
|
|
frozen: true,
|
|
createdAt: '2025-01-28'
|
|
} as const;
|
|
|