Disambiguate task vs activity NIP-52 calendar events on shared relays #25

Open
opened 2026-04-26 22:13:16 +00:00 by padreug · 0 comments
Owner

Problem

The tasks module and activities module both use NIP-52 calendar event kinds (31922/31923) on the same Nostr relay. This causes task events ("Put out the recycling", "Put the chickens to bed") to appear in the activities feed as community events.

Currently we filter by checking for event-type: task tag or a status tag on kind 31922 events (NIP-52 only defines status on RSVP kind 31925, not on calendar events). This works as a stopgap but is fragile — manually created events may not have these tags, and future modules could introduce other non-activity calendar events.

The core challenge

NIP-52 calendar events are a general-purpose format. There's no built-in mechanism to distinguish "this is a community activity" from "this is a household task" from "this is a meeting." Both are valid kind 31922 events per spec.

Possible solutions

1. Custom event-type tag convention

  • Tasks publish with ['event-type', 'task'], activities with ['event-type', 'activity']
  • Activities feed filters in only event-type: activity (whitelist, not blacklist)
  • Pros: Simple, explicit
  • Cons: Non-standard tag, other Nostr clients won't know about it

2. Use t (hashtag) tags as categories

  • Tasks publish with ['t', 'task'] or ['t', 'chore']
  • Activities publish with ['t', 'event'] or domain-specific tags like ['t', 'concert']
  • Activities feed subscribes with #t filter excluding task-related hashtags
  • Pros: NIP-12 compliant, relay-level filtering possible
  • Cons: Fragile if tags aren't consistent, can't filter at relay level with negation

3. Separate relay channels

  • Tasks publish to a different relay or different relay namespace
  • Activities only subscribe to the "community" relay
  • Pros: Clean separation, no filtering needed
  • Cons: Requires relay infrastructure decisions, harder to manage

4. Use different Nostr kinds for tasks

  • Tasks could use a dedicated kind (e.g., from the application-specific range 30000-39999)
  • NIP-52 kinds reserved for true calendar events only
  • Pros: Clean protocol-level separation, relay filtering works natively
  • Cons: Breaks NIP-52 compatibility for tasks, need to define/document the new kind

5. Author-based filtering

  • Activities feed only shows events from known community/organizer pubkeys
  • Tasks are personal (user's own pubkey) and naturally excluded
  • Pros: Works without any tag conventions
  • Cons: Breaks open discovery — new organizers wouldn't appear until added

Current workaround

ActivitiesNostrService.parseNostrEventToActivity() filters out events with event-type: task tag or a status tag on kind 31922 (since NIP-52 doesn't define status on calendar events, only on RSVPs).

References

## Problem The tasks module and activities module both use NIP-52 calendar event kinds (31922/31923) on the same Nostr relay. This causes task events ("Put out the recycling", "Put the chickens to bed") to appear in the activities feed as community events. Currently we filter by checking for `event-type: task` tag or a `status` tag on kind 31922 events (NIP-52 only defines `status` on RSVP kind 31925, not on calendar events). This works as a stopgap but is fragile — manually created events may not have these tags, and future modules could introduce other non-activity calendar events. ## The core challenge NIP-52 calendar events are a general-purpose format. There's no built-in mechanism to distinguish "this is a community activity" from "this is a household task" from "this is a meeting." Both are valid kind 31922 events per spec. ## Possible solutions ### 1. Custom `event-type` tag convention - Tasks publish with `['event-type', 'task']`, activities with `['event-type', 'activity']` - Activities feed filters *in* only `event-type: activity` (whitelist, not blacklist) - Pros: Simple, explicit - Cons: Non-standard tag, other Nostr clients won't know about it ### 2. Use `t` (hashtag) tags as categories - Tasks publish with `['t', 'task']` or `['t', 'chore']` - Activities publish with `['t', 'event']` or domain-specific tags like `['t', 'concert']` - Activities feed subscribes with `#t` filter excluding task-related hashtags - Pros: NIP-12 compliant, relay-level filtering possible - Cons: Fragile if tags aren't consistent, can't filter at relay level with negation ### 3. Separate relay channels - Tasks publish to a different relay or different relay namespace - Activities only subscribe to the "community" relay - Pros: Clean separation, no filtering needed - Cons: Requires relay infrastructure decisions, harder to manage ### 4. Use different Nostr kinds for tasks - Tasks could use a dedicated kind (e.g., from the application-specific range 30000-39999) - NIP-52 kinds reserved for true calendar events only - Pros: Clean protocol-level separation, relay filtering works natively - Cons: Breaks NIP-52 compatibility for tasks, need to define/document the new kind ### 5. Author-based filtering - Activities feed only shows events from known community/organizer pubkeys - Tasks are personal (user's own pubkey) and naturally excluded - Pros: Works without any tag conventions - Cons: Breaks open discovery — new organizers wouldn't appear until added ## Current workaround `ActivitiesNostrService.parseNostrEventToActivity()` filters out events with `event-type: task` tag or a `status` tag on kind 31922 (since NIP-52 doesn't define status on calendar events, only on RSVPs). ## References - NIP-52 spec: https://github.com/nostr-protocol/nips/blob/master/52.md - Tasks module: `src/modules/tasks/services/TaskService.ts` - Activities filter: `src/modules/activities/services/ActivitiesNostrService.ts:137-143`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/webapp#25
No description provided.