Skip to content

feat: tier pushes by urgency and group them per session - #238

Merged
samuelloranger merged 4 commits into
mainfrom
feat/push-levels
Oct 5, 2026
Merged

samuelloranger merged 4 commits into
mainfrom
feat/push-levels

Conversation

@samuelloranger

Copy link
Copy Markdown
Owner

What and why

Every push looked and sounded the same, so an agent waiting on an answer was buried among routine completions, and two sessions in one repo were indistinguishable. Pushes now carry an urgency level and a per-session grouping.

  • tether-notify: derives a level from the category/state (waiting, question, permission -> urgent; done -> quiet; anything else -> normal). notify gains an optional --session; state and hold set the session and level themselves.
  • Relay: maps level to the APNs envelope. urgent: time-sensitive, sound, relevance 1. normal: active, sound. quiet: passive, no sound. Sets thread-id from an opaque key when given.
  • NSE: sets the subtitle to the session name, falls back to the session as threadIdentifier when the relay supplied none, and re-states interruption level / relevance so the extension does not flatten them.

Cleartext vs ciphertext

  • Inside the ciphertext (new optional JSON fields): session, level.
  • In cleartext to the relay: only level and threadKey, a truncated SHA-256 of host label + session name. The relay sets thread-id from that opaque key; the session name never reaches it. The NSE sets the readable subtitle from the decrypted payload.
  • Wire format base64(nonce[12] || ciphertext || tag[16]) is unchanged.

Backward compatibility

  • Old tether-notify builds send neither field: the relay treats a missing, unknown or non-string level as normal and omits thread-id; a malformed thread key is dropped rather than rejecting the push. Note that normal now adds interruption-level: active, which matches iOS's default.
  • Old payloads without session/level leave the NSE behaviour unchanged.

Follow-up

The com.apple.developer.usernotifications.time-sensitive entitlement is deliberately not added: it needs an App ID capability change in the Apple developer portal first and would break release signing. Until then iOS delivers time-sensitive pushes as active. Enabling it is a separate change.

Verification

  • go build, go vet, go test in apps/tether-notify (new tests: level derivation, thread key stability/opacity, relay request body, session/level on state and hold pushes).
  • Relay bun test and typecheck (new tests: schema defaulting, per-level envelope, thread-id, end-to-end request).
  • bun run lint.
  • The NSE decode logic lives in the extension target, which TetherKit does not link, so it has no unit test; iOS build is covered by CI.

@samuelloranger
samuelloranger merged commit 3fca798 into main Oct 5, 2026
3 checks passed
@samuelloranger
samuelloranger deleted the feat/push-levels branch October 5, 2026 10:21
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.

1 participant