Core System Architecture Part 90 — Anonymous Network Notifications, Activity Inbox, Mentions, Interaction Aggregation, Digest & Privacy-Preserving Attention Architecture
SIAR — Secure, Local-First, Multi-Transport Communication Platform
Series: Core System Architecture
Part: 90
Status: Architecture specification
Primary language: Rust
Builds on: Core System Architecture Parts 17, 30–31, 43–46, 56, 61, 67–69, 74–75, 81–89
Primary purpose: define SIAR's notification, activity-inbox, interaction-aggregation, mention/reply/reaction delivery, push-wake, local attention state, digest, quiet-hours, priority, batching, deduplication, privacy-preserving attention, managed-policy, and lifecycle architecture without turning notifications into a behavioral surveillance or engagement-optimization system.
1. Purpose
Notifications sit between system events and human attention.
Poor notification architecture causes:
spam
privacy leaks
duplicated alerts
missed critical events
lock-screen exposure
engagement manipulation
server-side behavior profiling
The governing principle is:
SIAR notifications should deliver necessary attention signals while revealing the minimum metadata possible, respecting user control, batching low-value activity, and never becoming a mechanism for maximizing compulsive engagement.
2. Architectural Position
Domain / Interaction Event
│
▼
Notification Eligibility
│
▼
Aggregation / Priority
│
├── Local Activity Inbox
├── Push Wake Hint
├── Digest
└── Managed Alert
3. Core Separation
Keep distinct:
domain event
notification event
activity inbox item
push wake hint
user attention state
digest item
read/seen state
delivery receipt
4. Non-Goals
Part 90 does not create:
a global engagement timeline
a cloud database of every notification opened
behavioral push optimization
mandatory notification delivery for every event
lock-screen disclosure of private content
5. Notification Classes
#![allow(unused)] fn main() { pub enum NotificationClass { Security, Emergency, DirectCommunication, Mention, Reply, Reaction, SocialActivity, ContentUpdate, System, Managed, } }
6. Security
Examples:
new login
identity-key change
recovery started
7. Emergency
High-priority emergency/SOS event.
8. Direct Communication
Direct message/call.
9. Mention
Explicit mention.
10. Reply
Reply to user content.
11. Reaction
Reaction to user content.
12. Social Activity
Join request, invite, group event.
13. Content Update
Subscribed feed/channel update.
14. System
Sync/error/storage/system event.
15. Managed
Organization-scoped alert.
16. Notification Priority
#![allow(unused)] fn main() { pub enum NotificationPriority { Critical, High, Normal, Low, Background, } }
17. Critical
Security/emergency.
18. High
Direct call/message depending user preference.
19. Normal
Mentions/replies.
20. Low
Reactions/general updates.
21. Background
Non-attention sync status.
22. Hard Rule
Priority is domain/policy-derived, not engagement-score-derived.
23. Notification Event
#![allow(unused)] fn main() { pub struct NotificationEvent { pub event_id: NotificationEventId, pub class: NotificationClass, pub priority: NotificationPriority, pub subject: NotificationSubjectRef, pub source: NotificationSourceRef, pub privacy: NotificationPrivacyClass, } }
24. Event ID
Random/opaque.
25. No AccountId Encoding
Hard rule.
26. Notification Privacy Class
#![allow(unused)] fn main() { pub enum NotificationPrivacyClass { PublicSafe, PrivateMetadata, Sensitive, WakeOnly, } }
27. PublicSafe
Could appear with preview.
28. PrivateMetadata
Minimal generic text.
29. Sensitive
No content preview.
30. WakeOnly
Push contains only opaque wake signal.
31. Default For E2EE Private Events
WakeOnly or Sensitive.
32. Hard Rule
Private content is fetched after wake through normal authorization.
33. Notification Source Ref
#![allow(unused)] fn main() { pub enum NotificationSourceRef { Relationship(RelationshipId), SocialSpace(SocialSpaceId), Thread(ThreadId), Content(ContentId), System(SystemNotificationSource), } }
34. No Login Identity Required
Hard rule.
35. Notification Subject Ref
What is affected.
36. Example:
message
comment
security event
join request
37. Notification Projection
Domain events are transformed into minimal notification projections.
38. Hard Rule
Notification service does not receive full private domain objects unless required.
39. Projection Trait
#![allow(unused)] fn main() { pub trait NotificationProjection { fn project( &self, event: &DomainEvent, ) -> Option<NotificationEvent>; } }
40. Eligibility
Not all domain events generate notifications.
41. Eligibility Inputs
user preference
relationship policy
privacy mode
quiet hours
managed policy
event priority
42. Eligibility Decision
#![allow(unused)] fn main() { pub enum NotificationEligibility { DeliverNow, QueueForDigest, InboxOnly, Suppress, } }
43. Suppression
Valid normal behavior.
44. Hard Rule
Suppressed notification does not imply lost domain event.
45. Activity Inbox
Durable user-facing notification center.
46. Activity Inbox Item
#![allow(unused)] fn main() { pub struct ActivityItem { pub activity_id: ActivityId, pub class: NotificationClass, pub source: NotificationSourceRef, pub created_order: ActivityOrderKey, pub state: ActivityState, } }
47. Activity State
#![allow(unused)] fn main() { pub enum ActivityState { Unseen, Seen, Read, Archived, Dismissed, } }
48. Unseen
Never presented.
49. Seen
Displayed.
50. Read
User opened relevant context.
51. Archived
Retained but hidden from active inbox.
52. Dismissed
Removed from active attention.
53. Hard Rule
Activity state is attention state, not domain-authority state.
54. Dismissing Notification
Does not delete message/comment/security event.
55. Hard rule.
56. Local-First Activity Inbox
Client keeps local inbox state.
57. Server May Store
Encrypted account-sync projection if user enables multi-device sync.
58. No Global Plaintext Activity History
Hard rule.
59. Activity Inbox Scope
#![allow(unused)] fn main() { pub enum ActivityInboxScope { DeviceLocal, AccountEncrypted, ManagedWorkspace, } }
60. DeviceLocal
Strong privacy default.
61. AccountEncrypted
Own-device sync.
62. ManagedWorkspace
Managed events only.
63. Personal And Managed Inbox
Separate views/storage.
64. Hard Rule
Organization policy cannot inspect unrelated personal activity inbox.
65. Aggregation
Important to reduce spam.
66. Aggregate Examples
12 people reacted
3 replies in thread
5 updates from channel
67. Aggregation Key
#![allow(unused)] fn main() { pub enum AggregationKey { Thread(ThreadId), Content(ContentId), SocialSpace(SocialSpaceId), NotificationClass(NotificationClass), } }
68. No User-Based Global Aggregation Key
Hard rule.
69. Aggregation Window
#![allow(unused)] fn main() { pub struct AggregationWindow { pub duration: Duration, pub max_items: u32, } }
70. Reaction Aggregation
Strongly recommended.
71. Mention Aggregation
Limited.
72. Direct Messages
Usually not aggregated beyond conversation summary.
73. Emergency/Security
Never hidden in low-priority aggregate.
74. Hard Rule
Critical notifications cannot be downgraded into silent digest by generic aggregation.
75. Aggregated Activity
#![allow(unused)] fn main() { pub struct AggregatedActivity { pub aggregate_id: AggregateId, pub key: AggregationKey, pub count_class: CountClass, pub latest_order: ActivityOrderKey, } }
76. Public/Private Count Privacy
Use coarse count where small-cohort identity could leak.
77. No Public Actor List By Default
Hard rule.
78. Reaction Aggregation
Actor identities excluded from notification payload by default.
79. Replies
May include latest sender projection if relationship/group policy allows.
80. Mentions
Can identify mention actor in authorized scope.
81. Push Architecture
Push is wake infrastructure, not message transport.
82. Hard Rule
Push provider is not authoritative delivery channel.
83. Push Hint
#![allow(unused)] fn main() { pub struct PushWakeHint { pub hint_id: PushHintId, pub wake_class: PushWakeClass, pub opaque_locator: OpaqueWakeLocator, } }
84. Push Wake Class
#![allow(unused)] fn main() { pub enum PushWakeClass { Message, Call, Security, Activity, Sync, } }
85. Push Payload Must Not Contain
message plaintext
private comment text
contact graph
auth token
mailbox secret
86. Hard rule.
87. Push Provider Tokens
Sensitive infrastructure metadata.
88. Device-scoped.
89. No user social identity encoded.
90. Push Token Lifecycle
#![allow(unused)] fn main() { pub enum PushTokenState { Active, Rotating, Revoked, Expired, } }
91. Token Rotation
Supported.
92. Device removal revokes token.
93. Account deletion revokes token.
94. Hard rule.
95. Push Registration
Bound to device/account session where account mode used.
96. Local-only mode
No push required.
97. Android
Platform push optional.
98. Desktop
Local daemon notification path.
99. No dependency on push for correctness.
100. Hard rule.
101. Notification Fetch Flow
push wake
→ app wakes
→ authenticate local/device context
→ fetch mailbox/activity
→ authorize
→ decrypt locally
→ render
102. Push Provider Never Sees Decrypted Message
Hard rule.
103. Lock-Screen Privacy
Per-device.
104. Preview Policy
#![allow(unused)] fn main() { pub enum LockScreenPreviewPolicy { Hidden, SenderOnly, Generic, FullWhenUnlocked, } }
105. Default Sensitive
Generic/Hidden.
106. DeviceLocal Setting
Not centrally inferred.
107. Hard rule.
108. Mention Notification
Created by Part 89.
109. Must validate current access before rendering.
110. If parent deleted/revoked
Notification can become unavailable.
111. No stale content leak.
112. Hard rule.
113. Reply Notification
Thread scoped.
114. If user muted thread
InboxOnly or suppress.
115. Reaction Notification
Batch.
116. Default
Queue/aggregate.
117. No one alert per reaction storm.
118. Hard rule.
119. Reshare Notification
Optional.
120. Depends on creator preference.
121. Subscriber Updates
Usually feed/inbox/digest, not immediate push.
122. Hard Rule
New public content should not default to high-priority push merely to increase engagement.
123. Quiet Hours
User-controlled.
124. Quiet Hours Policy
#![allow(unused)] fn main() { pub struct QuietHoursPolicy { pub enabled: bool, pub start_local: LocalTime, pub end_local: LocalTime, pub bypass: BTreeSet<NotificationClass>, } }
125. DeviceLocal
By default.
126. Can sync semantic preference if user wants.
127. Timezone Local
Avoid central timezone tracking if unnecessary.
128. Hard rule.
129. Critical Bypass
User may allow security/emergency.
130. Managed Emergency
Can bypass managed quiet hours only if policy allows.
131. Hard Rule
Managed organization cannot bypass personal-profile quiet hours outside managed context.
132. Do Not Disturb
OS integration.
133. SIAR should respect OS DND.
134. No bypass unless platform APIs/user explicitly permit.
135. Hard rule.
136. Attention Budget
Optional user-controlled anti-spam mechanism.
137. Attention Budget
#![allow(unused)] fn main() { pub struct AttentionBudget { pub class: NotificationClass, pub max_interruptions: u16, pub window: Duration, } }
138. Interruptions
Push/sound/vibration.
139. Activity inbox still receives item.
140. Hard Rule
Exceeding budget downgrades interruption, not domain delivery.
141. Notification Channels
#![allow(unused)] fn main() { pub enum NotificationDeliveryChannel { InApp, OsNotification, PushWake, Email, ManagedWebhook, } }
142. InApp
Primary.
143. OS Notification
Local.
144. PushWake
Opaque wake.
145. Email
Optional external integration.
146. ManagedWebhook
Enterprise/admin events only.
147. Hard Rule
Private user interaction notifications never route to managed webhook unless explicitly managed-owned event.
148. Email Notification
Privacy-sensitive.
149. Default
Generic subject/body.
150. No private message plaintext.
151. User can choose richer preview if desired.
152. Hard rule.
153. Notification Preferences
Part 84 integration.
154. Global semantic preferences:
mentions
replies
reactions
security
group updates
feed updates
155. Per-Contact Override
Allowed.
156. Per-Thread Override
Allowed.
157. Per-Space Override
Allowed.
158. Effective Preference
Most specific + privacy/security floor.
159. Managed Overlay
Managed context only.
160. Hard rule.
161. Notification Preference Model
#![allow(unused)] fn main() { pub struct NotificationPreference { pub class: NotificationClass, pub behavior: NotificationBehavior, } }
162. Behavior
#![allow(unused)] fn main() { pub enum NotificationBehavior { Interrupt, Silent, Digest, InboxOnly, Disabled, } }
163. Security Class
May not permit Disabled for critical compromise warning in managed profile.
164. But user personal account policy separate.
165. Hard rule.
166. Digest Architecture
Digests summarize low/normal-priority activity.
167. Digest Types
#![allow(unused)] fn main() { pub enum DigestType { Activity, SocialSpace, Feed, SecuritySummary, Managed, } }
168. Activity Digest
Replies/reactions/mentions.
169. Social Space Digest
Group updates.
170. Feed Digest
Subscribed public content.
171. Security Summary
Noncritical security events only.
172. Managed Digest
Org events.
173. Critical Security
Never delayed into digest only.
174. Hard rule.
175. Digest Schedule
#![allow(unused)] fn main() { pub enum DigestSchedule { Manual, Daily, Weekly, Custom, } }
176. User Local Time
Local/device scheduling preferred.
177. Server digest
Can operate on encrypted/minimal activity if enabled.
178. Strong privacy baseline
Generate digest locally.
179. Hard rule.
180. Digest Inputs
Only eligible items.
181. No Hidden Behavioral Ranking
182. Digest Ordering
criticality
user pins
recency
183. Not dwell-time optimization.
184. Hard rule.
185. Digest Item
#![allow(unused)] fn main() { pub struct DigestItem { pub source: NotificationSourceRef, pub class: NotificationClass, pub summary: DigestSummaryRef, } }
186. Summary
Generated from authorized local content.
187. No central AI summary of private events by default.
188. Hard rule.
189. AI Digest
Optional on-device.
190. Input remains local.
191. No raw private notification upload.
192. Hard rule.
193. Digest Read State
Local.
194. No creator visibility.
195. No notification-open tracking by sender.
196. Hard rule.
197. Seen/Read State Synchronization
Privacy-sensitive.
198. Default
DeviceLocal.
199. Optional encrypted account sync.
200. Never exposed to notification source unless domain feature explicitly needs receipt.
201. Hard rule.
202. Delivery Receipt
Infrastructure-specific.
203. Means notification reached device/inbox.
204. Not same as read.
205. Not same as domain delivery.
206. Hard rule.
207. Notification Delivery State
#![allow(unused)] fn main() { pub enum NotificationDeliveryState { Pending, Queued, WakeSent, InboxDelivered, Displayed, Suppressed, FailedRetryable, FailedPermanent, } }
208. Displayed
OS/app rendered.
209. Does not mean user read.
210. Hard rule.
211. Notification Outbox
Transactional.
212. Domain event commit first.
213. Notification projection/outbox after committed state.
214. No notification before domain commit.
215. Hard rule.
216. Notification Worker
Idempotent.
217. Duplicate event
No duplicate visible alert.
218. Deduplication Key
#![allow(unused)] fn main() { pub struct NotificationDedupKey { pub event: NotificationEventId, pub device: DeviceId, } }
219. Device-scoped.
220. No global user identifier required.
221. Aggregation Dedup
Same reaction/update merged.
222. No counter inflation.
223. Hard rule.
224. Retry
Exponential backoff + jitter.
225. Push transient failure
Retry bounded.
226. Permanent invalid push token
revoke token.
227. No infinite queue.
228. Hard rule.
229. Queue Bounds
By:
items
bytes
age
priority
230. Low-priority expired items can collapse into digest.
231. Critical items retained according to security policy.
232. No unbounded notification backlog.
233. Hard rule.
234. Offline Devices
Inbox sync after reconnect.
235. Push unavailable
No correctness loss.
236. Messages/domain events remain durable elsewhere.
237. Hard rule.
238. Expired Activity
Low-value event can expire.
239. Example
typing/presence do not become inbox items.
240. Hard Rule
Ephemeral realtime state never becomes durable notification history.
241. Call Notification
Incoming call special path.
242. Realtime.
243. Time-sensitive.
244. If missed
create missed-call activity.
245. No detailed media metadata in push.
246. Hard rule.
247. Emergency Notification
Part 17/41/etc.
248. Priority Critical.
249. Distinct UI.
250. No marketing/social aggregation with emergency.
251. Hard rule.
252. Security Notification
Examples:
new device
key change
recovery
session replay
253. Security Event Source
Account/security service.
254. Security notifications stored locally/account encrypted.
255. No suppression by normal social mute.
256. Hard rule.
257. Identity-Key Change
High.
258. User should see before sending sensitive message where relevant.
259. No hidden dismiss-only path.
260. Account Lifecycle Integration
Deleted account:
no new personal notifications
revoke push token
delete/expire inbox sync according to lifecycle
261. Pending deletion
only deletion/security management alerts.
262. Hard rule.
263. Suspended Account
Security/appeal/account alerts may still deliver.
264. Social/activity notifications may suppress.
265. Managed Offboarding
Managed notification channel revoked.
266. Personal notifications unaffected.
267. Hard rule.
268. Contact Integration
Part 85.
269. Blocked contact
no direct notifications.
270. Existing public content interactions
local block policy hides/suppresses.
271. Stale sync cannot re-enable.
272. Hard rule.
273. Social Space Integration
Part 86.
274. Space mute.
275. Mention can optionally override space mute.
276. User controls.
277. Ban/removal
future space notifications stop.
278. Hard rule.
279. Feed Integration
Part 87.
280. Public feed updates usually InboxOnly/Digest.
281. User can promote source.
282. No feed source self-promotes to critical.
283. Hard rule.
284. Publishing Integration
Part 88.
285. Creator publication can trigger follower/subscriber update.
286. Subscribers' preference determines delivery.
287. Publisher cannot know who got push.
288. Hard rule.
289. Interaction Integration
Part 89.
290. Mention/reply/reaction/reshare event projections.
291. No direct sender-controlled push priority beyond allowed domain bounds.
292. Hard rule.
293. Authorization Integration
Part 81.
294. Notification rendering always revalidates content access.
295. Notification itself is not authorization proof.
296. Hard rule.
297. Authentication Integration
Part 82.
298. Session state needed for account inbox sync.
299. Local notification display can work offline.
300. No push token as auth credential.
301. Hard rule.
302. Profile/Preference Integration
Part 84.
303. Semantic preferences synchronized optionally.
304. OS-specific sound/vibration local.
305. No server storage of device-specific notification behavior unless required.
306. Hard rule.
307. Federation Integration
Remote events arrive through federation gateway.
308. Convert to local notification projection.
309. No remote domain push provider access to local device token.
310. Hard rule.
311. Remote domain never receives local push token.
312. Federation Notification Flow
remote event
→ federation gateway
→ local domain event
→ local notification projection
→ local delivery
313. No cross-domain direct push.
314. Hard rule.
315. Tenant/Managed Notifications
Organization can create managed alerts.
316. Scoped to managed profile.
317. Managed alert priority bounded by policy.
318. No "critical" flag self-selected by arbitrary sender.
319. Hard rule.
320. Managed Broadcast
Explicit elevated capability.
321. Emergency broadcast capability separate.
322. Rate limited.
323. Audit.
324. No unlimited org notification spam.
325. Hard rule.
326. Managed Notification Capability
#![allow(unused)] fn main() { pub struct ManagedNotificationCapability { pub organization: OrganizationId, pub classes: BTreeSet<NotificationClass>, pub max_priority: NotificationPriority, pub expires_at: Timestamp, } }
327. Notification Channels On Device
Examples:
Messages
Calls
Mentions
Security
Groups
System
328. Android Notification Channels
Map semantic classes.
329. Desktop categories
Equivalent.
330. UI semantic model shared.
331. Platform rendering separate.
332. Hard rule.
333. Notification Grouping
OS-level.
334. Conversation grouping.
335. Thread grouping.
336. Reaction aggregation.
337. No user graph inference on server needed.
338. Local Notification Renderer
#![allow(unused)] fn main() { pub trait NotificationRenderer { fn render( &self, item: &ResolvedNotification, policy: &DeviceNotificationPolicy, ) -> Result<RenderedNotification, NotificationError>; } }
339. Rendering After Local Decryption
Preferred.
340. Hard rule.
341. Notification Resolution
#![allow(unused)] fn main() { pub trait NotificationResolver { fn resolve( &self, event: &NotificationEvent, ) -> Result<ResolvedNotification, NotificationError>; } }
342. Resolution checks:
authorization
current deletion/revocation
block/mute state
profile projection
343. No stale preview.
344. Hard rule.
345. Activity Inbox Query
#![allow(unused)] fn main() { pub trait ActivityInboxRepository { fn page( &self, cursor: Option<ActivityCursor>, limit: usize, ) -> Result<ActivityPage, NotificationError>; } }
346. Bounded pagination.
347. No load-all activity history.
348. Hard rule.
349. Notification Preference Resolver
#![allow(unused)] fn main() { pub trait NotificationPreferenceResolver { fn behavior( &self, event: &NotificationEvent, context: &NotificationContext, ) -> Result<NotificationBehavior, NotificationError>; } }
350. Deterministic.
351. No behavioral engagement model.
352. Hard rule.
353. Aggregation Service
#![allow(unused)] fn main() { pub trait NotificationAggregator { fn ingest( &self, event: NotificationEvent, ) -> Result<AggregationDecision, NotificationError>; } }
354. Digest Builder
#![allow(unused)] fn main() { pub trait DigestBuilder { fn build( &self, eligible: &[ActivityItem], policy: &DigestPolicy, ) -> Result<NotificationDigest, NotificationError>; } }
355. No hidden content ranking model.
356. Digest Policy
#![allow(unused)] fn main() { pub struct DigestPolicy { pub schedule: DigestSchedule, pub included_classes: BTreeSet<NotificationClass>, pub max_items: u16, } }
357. Digest Size Bounded.
358. No Infinite Summary.
359. Notification Expiry
#![allow(unused)] fn main() { pub struct NotificationExpiryPolicy { pub class: NotificationClass, pub max_age: Duration, } }
360. Low-value short.
361. Security longer.
362. Expiry does not delete underlying domain event.
363. Hard rule.
364. Activity Retention
User-controlled/bounded.
365. Example:
7 days
30 days
90 days
366. Security event retention may differ.
367. No indefinite attention history by default.
368. Hard rule.
369. Deletion / Retraction
If source content deleted:
activity item becomes unavailable
preview removed
370. If interaction retracted:
notification can collapse/remove body
371. No stale deleted-content preview.
372. Hard rule.
373. Notification Tombstone
Minimal.
374. Prevents stale sync from restoring.
375. Notification Deletion Epoch
#![allow(unused)] fn main() { pub struct NotificationDeletionEpoch(pub u64); }
376. Monotonic.
377. Old inbox replicas rejected.
378. Hard rule.
379. Multi-Device Notification Sync
Possible sync:
dismissed
read/seen
archive
mute preference
380. Default privacy:
read state local.
381. User may opt into encrypted sync.
382. Dismissed security warning
can sync if desired.
383. No sender visibility.
384. Hard rule.
385. Multi-Device Duplicate Avoidance
Own devices each may receive wake.
386. Activity inbox event shared logically.
387. Local renderer decides alert.
388. Optional "first active device wins" optimization risky for privacy.
389. Initial baseline
Allow per-device rendering based on local preference.
390. No centralized live-device attention tracking.
391. Hard rule.
392. Device Activity
Do not upload "screen currently on"/"user actively viewing app" by default.
393. Hard rule.
394. Foreground Suppression
Local app can suppress OS notification when open.
395. No server needs foreground state.
396. Good privacy.
397. Notification Action Buttons
Examples:
Reply
Mark read
Mute
Accept call
398. Actions must reauthorize.
399. Notification action token
short-lived/local or audience-bound.
400. No long-lived auth token in notification payload.
401. Hard rule.
402. Quick Reply
Encrypt/sign via normal messaging path.
403. Notification shell is not message transport.
404. Hard rule.
405. Notification Deep Link
Opaque internal route.
406. Revalidates target.
407. No sensitive ID in external URL where avoidable.
408. Hard rule.
409. Email/External Digest
If enabled:
generic summary
safe links
no secret tokens beyond single-purpose short-lived link
410. Authentication required to view private content.
411. Hard rule.
412. Unsubscribe Link
For optional email.
413. Scoped single-purpose token.
414. Does not grant account access.
415. Hard rule.
416. Notification Abuse
Threats:
mention spam
reaction storms
group broadcast abuse
publisher push spam
managed alert abuse
417. Mention Spam
Part 89 rate limits.
418. Reaction Storms
Aggregate.
419. Group Broadcast
Elevated capability/rate limits.
420. Publisher Spam
Subscriber preferences + attention budget.
421. Managed Alert Abuse
Capability + audit + quota.
422. No sender override of user Disabled setting except security/emergency policy.
423. Hard rule.
424. Attention Safety
System should not optimize for:
open rate
return frequency
time-on-app
notification-induced sessions
as primary goals.
425. Hard rule.
426. Product Metrics
Allowed aggregate technical metrics:
delivery failure
push invalid token rate
digest generation latency
427. Avoid:
which notification made user return
conversion from notification to session
individual open propensity
428. Hard rule.
429. Notification Recommendation
Not needed.
430. No ML to choose emotional/persuasive push text.
431. Hard rule.
432. Notification Copy
Domain-defined neutral templates.
433. Example:
You have a new reply.
Security settings changed.
434. Avoid urgency inflation.
435. Only critical events use critical wording.
436. Hard rule.
437. Privacy Threat Model
Attacks:
push-provider metadata correlation
lock-screen leakage
activity history reconstruction
sender graph inference
cross-device correlation
438. Push Provider Correlation
Opaque payloads, minimized token mapping.
439. Lock-Screen Leakage
Local preview policy.
440. Activity History
Bounded/encrypted/local.
441. Sender Graph
No centralized per-contact notification ledger.
442. Cross-Device Correlation
No global attention telemetry.
443. Hard rule.
444. Operational Architecture
Components:
Notification Projector
Eligibility Engine
Aggregator
Activity Inbox
Push Wake Dispatcher
Digest Builder
Local Renderer
Preference Resolver
445. Notification Projector
Converts domain events.
446. Eligibility Engine
Applies semantics/preferences.
447. Aggregator
Combines low-value events.
448. Activity Inbox
Durable local/account state.
449. Push Wake Dispatcher
Opaque push hints.
450. Digest Builder
Local/optional account summary.
451. Local Renderer
Final privacy-aware presentation.
452. Preference Resolver
Effective notification intent.
453. No Single Central Notification Brain
Hard rule.
454. Service Boundaries
Server notification service knows:
event class
device token
opaque locator
priority
455. Should not know:
message plaintext
private profile details
social graph
precise user activity state
456. Hard rule.
457. Event Bus Integration
Part 75.
458. Domain events feed projector through scoped topics.
459. Notification service subscribes only needed projections.
460. No broad access to all private domain events.
461. Hard rule.
462. Database Integration
Part 74.
463. Server stores:
push token registry
minimal delivery queue
optional encrypted activity sync
464. Client stores:
activity inbox
seen/read state
local preferences
aggregates
465. No global notification analytics warehouse.
466. Hard rule.
467. Edge Integration
Part 78.
468. Push registration API L7.
469. Token validation.
470. No notification content inspection beyond external API metadata.
471. Internal Service Integration
Part 79.
472. Notification services use mTLS.
473. Secrets Integration
Part 80.
474. Push provider API key brokered/scoped.
475. No provider key in client.
476. Hard rule.
477. Authorization Integration
Part 81.
478. Notification action/deep link reauthorizes.
479. Authentication Integration
Part 82.
480. Session needed for account activity sync.
481. Push token not identity proof.
482. Hard rule.
483. Account Lifecycle Integration
Part 83.
484. Revocation/deletion/token cleanup.
485. Profile Integration
Part 84.
486. Notification semantic preferences.
487. Contact Integration
Part 85.
488. block/mute/contact-specific behavior.
489. Social Space Integration
Part 86.
490. space notification policies/managed broadcasts.
491. Feed Integration
Part 87.
492. feed digest/subscriber updates.
493. Publishing Integration
Part 88.
494. publication events.
495. Interaction Integration
Part 89.
496. replies/mentions/reactions/reshares.
497. Data Lifecycle
Part 67.
498. Activity/inbox retention.
499. Deleted source removes preview.
500. No stale restore.
501. Backup
Part 33.
502. Local inbox backup optional.
503. Push tokens excluded.
504. Read/unread optional.
505. Notification deletion epochs preserved if backed up.
506. Hard rule.
507. Federation
No remote domain receives local push token.
508. Remote event normalized through local domain.
509. Hard rule.
510. Serialization
Postcard internal.
511. RON preferences/config/export.
512. JSON external push provider API only.
513. Strict bounds.
514. No giant payload.
515. Push hint tiny.
516. Digest item count bounded.
517. Activity pagination bounded.
518. Hard rule.
519. Performance
Notification projection low-cost.
520. Aggregation in-memory + durable checkpoint.
521. Push dispatch async.
522. Digest batch.
523. Local renderer fast.
524. No domain transaction waits for push provider.
525. Hard rule.
526. Queue Priority
Critical
High
Normal
Low
Background
527. Reserved capacity for Critical/Security.
528. Low-priority collapsible.
529. No reaction storm starving security notification.
530. Hard rule.
531. Push Token Fanout
Per user device.
532. Bounded.
533. Invalid token cleanup.
534. No permanent dead token buildup.
535. Rate Limits
Per source/class/device.
536. No sender can create unlimited interrupting notifications.
537. Hard rule.
538. Digest Performance
Generate from local/activity summary state.
539. No need to scan entire content history.
540. Incremental aggregation.
541. Activity Inbox Pagination
Virtualized UI.
542. No load-all.
543. Crate Layout
Recommended:
crates/
├── siar-notification-core/
├── siar-notification-projection/
├── siar-notification-policy/
├── siar-notification-aggregation/
├── siar-activity-inbox/
├── siar-push-wake/
├── siar-notification-digest/
├── siar-notification-render/
├── siar-notification-observability/
└── siar-notification-testkit/
544. siar-notification-core
Owns:
event IDs
classes
priorities
privacy classes
errors
545. siar-notification-projection
Domain event → minimal notification projection.
546. siar-notification-policy
Eligibility/preferences/quiet hours/attention budgets.
547. siar-notification-aggregation
Reaction/reply/feed grouping.
548. siar-activity-inbox
Durable local/account-encrypted activity state.
549. siar-push-wake
Provider-independent opaque wake dispatch.
550. siar-notification-digest
Local/batched digest generation.
551. siar-notification-render
Platform-neutral resolved notification + UI adapters.
552. siar-notification-observability
Aggregate technical metrics only.
553. siar-notification-testkit
dedup/aggregation/privacy/lifecycle/failure tests.
554. Error Taxonomy
#![allow(unused)] fn main() { pub enum NotificationError { EventInvalid, Suppressed, SourceUnavailable, AuthorizationDenied, PushTokenInvalid, PushProviderUnavailable, QuietHours, RateLimited, DigestUnavailable, ActivityDeleted, AccountInactive, Internal, } }
555. Testing
Need dedicated notification/attention testkit.
556. Test Scenarios
private message wake
reaction storm
quiet hours
security alert
digest
557. Private Push Test
Push contains no plaintext.
558. Push Token Test
Token not usable as auth credential.
559. Reaction Aggregation Test
100 reactions produce bounded aggregate alerts.
560. Critical Priority Test
Security event not collapsed into low-priority digest.
561. Quiet Hours Test
Normal alert suppressed/digested.
562. Emergency Bypass Test
Only policy-approved critical class bypasses.
563. Block Test
Blocked contact creates no direct notification.
564. Mute Test
Muted thread becomes inbox/digest according to policy.
565. Mention Test
Current authorization rechecked before preview.
566. Deleted Content Test
Old notification preview removed/unavailable.
567. Deletion Epoch Test
Stale inbox sync cannot resurrect deleted activity.
568. Duplicate Delivery Test
Retry produces one visible activity.
569. Multi-Device Test
No server attention-state surveillance required.
570. Federation Test
Remote domain never receives local push token.
571. Managed Test
Org broadcast scoped to managed profile.
572. Account Deletion Test
Push tokens revoked/no new activity.
573. Digest Privacy Test
Local digest does not upload private contents.
574. Read-State Test
No sender sees notification-open state.
575. External Email Test
Private content requires authenticated fetch.
576. Attention Budget Test
Low-priority interruption downgraded, event retained.
577. Telemetry Test
No per-user open propensity or activity graph logged.
578. Fuzzing
Fuzz:
notification projection
push hint
activity envelope
digest state
aggregation key
579. Property Tests
Properties:
private event projection never produces plaintext push payload
critical notification cannot be downgraded by generic low-priority aggregation
deleted activity cannot return from stale sync
duplicate domain event does not create duplicate visible notification
580. Formal Verification Targets
Strong candidates:
delivery/dedup state machine
aggregation priority rules
deletion anti-resurrection
quiet-hours/bypass precedence
581. Kani Candidate
priority/eligibility/precedence invariants.
582. TLA+ Candidate
domain commit → notification outbox → retry → deletion race.
583. Loom Candidate
concurrent duplicate delivery + aggregation + read-state update.
584. Security, Privacy & Correctness Invariants
Mandatory:
1. Push providers receive opaque wake metadata only for private/E2EE events; private plaintext is fetched and decrypted after wake.
2. A notification is never authorization proof; content access is revalidated when the notification is resolved or opened.
3. Notification priority is derived from domain/security semantics and explicit user/managed policy, never from engagement propensity or behavioral scoring.
4. Reaction, feed, and low-value social events are aggressively aggregatable, while critical security/emergency notifications cannot be silently downgraded into low-priority digests.
5. Activity inbox state, seen/read status, quiet hours, and device presentation preferences remain local by default and are synchronized only through encrypted opt-in mechanisms.
6. Managed notification policy affects managed context only and cannot inspect or override unrelated personal notification state.
7. Blocked/revoked/deleted sources cannot continue producing actionable notifications, and stale sync/backups cannot resurrect deleted activity state.
8. Notification infrastructure never receives or exports a global who-notified-whom, who-opened-what, or per-user engagement graph.
9. Notification delivery/display state remains distinct from message delivery, content read state, and user engagement.
10. Push tokens are device-scoped routing metadata, never authentication credentials or social identities, and are revoked on device/account lifecycle changes.
11. Notification workers, digests, and delivery queues are bounded, idempotent, priority-aware, and cannot allow low-value storms to starve security/emergency events.
12. Notification systems optimize for timely, user-controlled attention—not return frequency, session length, open rate, or compulsive engagement.
585. Initial Production Scope
Implement first:
typed NotificationEvent/ActivityItem
semantic notification classes/priorities
privacy classification
domain-event projection layer
eligibility/preference resolver
local activity inbox
reaction/reply aggregation
quiet hours
attention budget
opaque push wake hints
push token lifecycle
device-local lock-screen preview policy
notification outbox/dedup/retry
local digest generation
managed notification isolation
multi-device encrypted inbox sync optional
deletion/revocation anti-resurrection
privacy-safe operational metrics
notification testkit
Then add:
on-device AI digest
advanced aggregate interaction summaries
cross-device encrypted attention-state sync
privacy-preserving multi-provider push routing
formal priority/dedup verification
enterprise digest/report adapters
586. Definition of Done
Part 90 is complete when:
- domain events project into minimal notification events
- private push payloads are opaque wake hints
- activity inbox is local-first
- seen/read state is private by default
- reactions/social events aggregate safely
- critical security/emergency alerts retain priority
- quiet hours and attention budgets work
- sender cannot bypass user notification policy
- managed notifications stay managed-scoped
- federation never receives local push tokens
- notification open/read behavior is not exposed to senders
- deletion/revocation removes actionable stale notifications
- queues/retries/dedup are bounded and idempotent
- digests can be generated locally without cloud private-content analysis
- telemetry excludes engagement-surveillance graphs
- push/aggregation/quiet-hours/digest/fuzz/formal tests are specified
587. Final Architecture
DOMAIN EVENT
│
▼
NOTIFICATION PROJECTION
│
▼
ELIGIBILITY / POLICY
│
┌───────────┼───────────┐
│ │ │
INTERRUPT INBOX ONLY DIGEST
│ │ │
▼ ▼ ▼
PUSH WAKE ACTIVITY LOG SUMMARY
│ │ │
└───────────┼───────────┘
▼
LOCAL RESOLUTION
│
▼
USER ATTENTION
Attention safety model:
minimal projection
+
local-first inbox
+
opaque push wake
+
priority semantics
+
aggregation
+
quiet hours
+
attention budgets
+
privacy-safe digests
+
no engagement profiling
not:
track every notification open, learn which alerts pull the user back fastest, and optimize pushes for maximum time-on-app
588. Final Principle
A notification should interrupt the user only when the event deserves attention according to the user's intent and security needs—not because a ranking system predicts it will increase engagement.
The correct model is:
project minimally
+
aggregate aggressively
+
interrupt selectively
+
wake opaquely
+
resolve locally
+
digest privately
+
respect quiet time
+
never profile attention
This architecture gives SIAR a privacy-preserving foundation for push wake, activity inboxes, mentions, replies, reactions, security alerts, digests, managed notifications, and attention control while preserving the anonymity, local-first, least-authority, and anti-surveillance guarantees established across Parts 34–89.