Skip to content

Surface the notification tag, and the facts packed into notification_id - #354

Open
dchaudhari7177 wants to merge 1 commit into
RyanDFIR:mainfrom
dchaudhari7177:feat/333-notification-tag-and-id
Open

Surface the notification tag, and the facts packed into notification_id#354
dchaudhari7177 wants to merge 1 commit into
RyanDFIR:mainfrom
dchaudhari7177:feat/333-notification-tag-and-id

Conversation

@dchaudhari7177

Copy link
Copy Markdown
Contributor

Closes #333.

The decision the issue leaves open

Worth deciding whether to emit the raw id, the decoded parts, or both.

Decoded parts, with the raw id as the fallback. A row reading p#https://calendar.google.com/#1event-notification asks the reader to decode it by hand every time, and the origin is already the record's URL and the tag is already its own row — so most of that string is a restatement. The parts that are not said anywhere else are persistence and who raised it, so those become rows:

Body: Standup in 10 minutes
Tag: event-notification
Persistent: Yes
Raised By: Page

The id's own value is emitted only when the type digit says 0 (notification id). When it says 1 the value is the tag, and the Tag row already has it.

When the string does not decode, decode_notification_id returns None and the caller prints the id whole. So a future format change costs the decoded rows but never the data — which is the reason it returns None rather than guessing at the parts it can see.

persistent_notification_id

The issue asks to confirm it is ever populated before spending a row on it. I could not: it is None throughout the sample here too, exactly as reported. It is emitted only when truthy, so it costs nothing today and appears the day it is populated rather than needing a second PR.

Verified

tests/test_notification_id.py. Red before green, with only chrome.py stashed:

$ python -m pytest tests/test_notification_id.py -q
14 failed, 1 passed          # before
5 passed, 10 subtests passed # after

Covering:

  • the real corpus id from bf4sa_2026_bob-2 — decodes to persistent, page-raised, developer tag event-notification, which agrees with what ccl parses independently
  • the n and b variants, which the corpus does not contain
  • an origin/tag containing further # characters — partition() splits on the first, and the test pins that rather than leaving it to chance
  • an empty tag, which still decodes
  • ten shapes that must decode to None: too short, unknown persistence flag, unknown raiser flag, no separator, separator with nothing after it, unknown type digit, and an opaque handle

Full suite: 253 passed, 2 skipped, 90 subtests (up from 248/2/80, all new).

Scope

The Tag: line is the whole fix for the common case, as the issue says. The decoder is 30 lines and pays for itself in the two flags the tag cannot give you — but if you would rather ship only the tag and leave the id alone, the decoder is one self-contained static method and its tests, and I will drop it.

ccl parses a notification's developer tag and its notification_id, and
get_platform_notifications used neither, so both were dropped. The tag is the
slot a site overwrites -- Google Calendar reuses event-notification for every
reminder -- so without it six rows from one recurring channel look exactly like
six unrelated alerts, which is the question the output could not answer.

Tag is now a value row. notification_id is decoded rather than printed raw:

    p#https://calendar.google.com/#1event-notification
    ||                            |
    ||                            +- 0 = notification id, 1 = developer tag
    |+- b browser-raised, # page-raised
    +- p persistent, n non-persistent

giving Persistent and Raised By rows. The id's own value is emitted only when
it is a notification id, since when it is a developer tag the Tag row already
says it.

decode_notification_id returns None for anything that does not match rather
than guessing, and the caller then prints the id whole -- so a format change
costs the decoded rows but never the data.

persistent_notification_id is emitted when populated. It was None throughout
the sample, so this may never fire; guarding on truthiness costs nothing and
means it appears the day it does.

Tests cover the real corpus id from bf4sa_2026_bob-2, the browser-raised and
non-persistent variants, an origin containing a hash, an empty tag, and ten
shapes that must decode to None.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Surface the notification tag and id that ccl already parses

1 participant