Repository navigation
Conversation
Backend unit coveragePASS · minimum combined coverage 67.60%. Tests: 3642 passed, 0 failed, 0 skipped. Source files: 283.
Unit coverage includes every backend workspace. PostgreSQL/Redis integration tests run separately. Commit: 1f5ba00 · HTML, JSON, XML reports and job logs · attempt 1 |
PR reader API performanceResult: INCONCLUSIVE 5 inconclusive · 3 within threshold. Zero request failures across all six runs. Base Three independent runs per revision, each on a fresh GitHub-hosted ARM64 runner. 16 users, 60 seconds/run, 1,000 synthetic articles, cache off, five PgBouncer slots. Latency comparisonAll latency values are in milliseconds; lower is better. Values are medians of three runs.
Additional latency and throughput metricsEach cell shows base → PR. Latencies are in milliseconds.
Individual runs
How to interpret this reportRegressed / Improved: a p95 regression needs >20% and >20 ms increase in the medians and at least two head samples versus the base median. Improvements use the inverse threshold. Within threshold means the change did not meet both thresholds. Inconclusive: a within-revision p95 range >35% of its median and >20 ms is too noisy for a confident latency verdict. Inconclusive latency comparisons are non-blocking: the check passes without claiming an improvement. Confirmed regressions and test/report errors fail the PR gate. Throughput is descriptive: paced users do not measure maximum capacity. This uncached public API test does not establish production health, browser performance or worker capacity. Separate runners can differ in hardware or host load; repetitions and noise checks reduce but cannot eliminate that uncertainty. Full HTML/CSV reports and logs · attempt 1 |
Lighthouse · ⏸️ Not measuredTests did not pass for this commit. |
|


What changes and why?
Signed-in readers can enable browser notifications in Settings → Notifications to receive one personalized unread Must Read article at 9 AM in their local timezone. Permission is requested only after clicking Enable. The article comes from the reader's stable ranked selection; days without an eligible unread pick are skipped. All enabled browsers receive the same article using the earliest active registration's delivery timezone.
Browser delivery now has a reusable typed publisher, separate from daily article selection:
enqueue_web_pushpublishes an immutable message, audience, unique event key and expiry in the producer's database transaction.PushAudiencesupports one account, an account list, all consented accounts, or followers of any listed active topic/approved source.daily_must_readremains the only enabled producer, type, browser handler and consent option. Custom messages cannot reuse daily consent. Another type can use the same publisher/audiences after adding its policy, browser handler and explicit consent option; no custom composer or public send endpoint is introduced.Admin → Push analytics adds 7/30/90-day publication cohorts, daily trends and per-type totals for published events, distinct recipient accounts, browser jobs, relay acceptance, reported displays/clicks/opens, failures, skipped jobs, pending jobs and retry attempts. Click rate uses notifications with a reported display, and missing browser feedback remains unconfirmed. This aggregate admin view supports future types without exposing account IDs, endpoints or notification content.
The service worker reports successful display and validated click/navigation outcomes to the user API with its current cookie session and CSRF token. Receipts are first-write-only and bound to the original account, browser session and consent epoch. Passive authentication checks expiry and the current policy without renewing sessions or recording reader activity. A notification open never marks an article as read. Bounded retries/timeouts run outside the worker’s consent queue so telemetry cannot delay revocation.
Before displaying any queued push, the website worker verifies live server-side authorization for its original account, session, consent and attempted event. This prevents an already relay-accepted notification from revealing a previous account's personalized title after sign-out from either extension, whose origin cannot directly clear website worker storage. Failed or unavailable authorization suppresses that delivery without deleting consent.
Notification enrollment is cancelled when the account/session changes, expires or its settings component unmounts. Late responses and stale cleanup cannot restore or remove a newer binding. Temporary delivery pauses preserve existing enabled consent, allowing delivery to resume without revisiting settings. Compose supplies the same public feature configuration to admin analytics while keeping signing credentials in delivery workers only.
Standard Web Push/VAPID uses existing PostgreSQL, Redis, scheduler and RQ workers without a notification SaaS account or provider fee. Chrome and Edge extensions open website notification settings without adding extension permissions. Session/account/consent checks, per-type consent, local deduplication, safe article actions and serialized click/revocation prevent stale-account delivery. Workers validate the current authentication-policy fingerprint without receiving OIDC credentials. Relay TTL, payload expiry and retries stop at the earliest event or live authorization deadline.
Validation
0022and legacy0018passed, preserving existing records. The updated0023 → 0022 → 0023round trip, nullable receipt timestamps, event index and event/consent uniqueness checks passed.--no-editableflag. A new canary executes the production Docker dependency-stage arguments and proves first-party code is neither built nor imported in that stage.Gaps: relay delivery and system notification display are simulated in browser tests; live vendor-relay delivery and real Safari/iPhone/iPad devices are unverified. Hosted CI, CodeQL and AMD64/ARM64 runtime checks must pass on the updated head before merge. The previous head’s six-sample performance comparison passed. Its Sonar gate reported 75.3% new coverage against 80%, dominated by missing service-worker coverage reporting despite browser execution; the updated head must clear that gate before merge.
Native GitHub screenshot attachment upload is unavailable in this session, so UI screenshots are not attached. No review-only images are committed.
Rollout notes
0023with the coordinated application update; readiness expects this revision even while push is disabled. This refactors the same unreleased draft migration and adds nullable display/click/open timestamps plus an event-cohort index. Disposable development databases that applied the earlier draft0023need a coordinated reset/downgrade before testing the updated schema; published migrations are unchanged.scripts/generate_web_push_keys.py. Public configuration goes to user-api, scheduler and delivery workers; only workers receive private signing credentials. See the setup and publisher guide.http://localhost:3000(and HTTP loopback addresses); other reader hosts still require HTTPS. Use matching reader/site origins, HTTP development cookie mode and the registered local OIDC callback, then restart all affected services. Signing-key changes remain local and ignored; no credentials are committed.http-ece==1.2.1source archive, guarded by registry/version/SHA-256. CI and container dependency layers share this policy; unreviewed upgrades fail closed.DEVFEED_WEB_PUSH_ENABLEDwhile retaining the updated application/schema. Schema downgrade drops push subscriptions, events, claims and deliveries and must be coordinated with the earlier application version.Ready for review