Skip to content

feat: poison hearbeats - #1676

Open
scooterthedev wants to merge 9 commits into
hackclub:mainfrom
scooterthedev:hearbeat-poisoning
Open

feat: poison hearbeats#1676
scooterthedev wants to merge 9 commits into
hackclub:mainfrom
scooterthedev:hearbeat-poisoning

Conversation

@scooterthedev

Copy link
Copy Markdown
Member

No description provided.

Copilot AI lite review requested due to automatic review settings September 4, 2026 07:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are correctness and contract issues (notably the default_scope recursion risk and timezone-inconsistent cutoff coercion) that should be addressed before merge.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Adds a “heartbeat poisoning” mechanism to hide a user’s heartbeats up to an admin-defined cutoff (without deleting rows), plus a superadmin-only Admin API to apply/remove the ban and expose ban state. This fits into the moderation/admin tooling layer while ensuring downstream derived totals (dashboard rollups, leaderboard cache) are invalidated on state changes.

Changes:

  • Introduces User#apply_poison! / #remove_poison! and user fields (poisoned_until, poisoned_at, poison_reason) to track ban state.
  • Adds HeartbeatPoisoning to automatically exclude poisoned heartbeats by default, with a thread-local escape hatch (Heartbeat.including_poison).
  • Adds admin endpoints (GET/POST/DELETE /api/admin/v1/ban/:hackatime_id) with tests and Swagger/Rswag documentation updates.
File summaries
File Description
test/models/concerns/heartbeat_poisoning_test.rb Exercises hiding/unhiding behaviour, timezone cutoffs, and derived-data invalidation scheduling.
test/controllers/api/admin/v1/bans_controller_test.rb Integration tests for the admin ban API, including auth rules and response payload fields.
swagger/admin/swagger.yaml Documents the new ban endpoints and request/response schemas for the admin OpenAPI spec.
spec/requests/api/admin/v1/bans_spec.rb Rswag specs that generate/validate the admin Swagger for the ban endpoints.
db/schema.rb Reflects new poison-related columns and index on users.poisoned_until.
db/migrate/20260903120000_add_poison_to_users.rb Adds poison tracking columns + partial index to users.
config/routes.rb Adds admin routes for ban show/create/destroy.
app/models/user.rb Implements poisoning state, cutoff coercion/validation, and derived-data invalidation.
app/models/heartbeat.rb Mixes in HeartbeatPoisoning so poisoning affects heartbeat reads by default.
app/models/concerns/heartbeat_poisoning.rb Implements the default exclusion logic + including_poison override.
app/controllers/api/admin/v1/bans_controller.rb New superadmin-only controller to apply/remove poison and report ban state.
app/controllers/api/admin/application_controller.rb Adds an include_poison around_action to optionally include poisoned heartbeats for admin requests.
Review details
  • Files reviewed: 12/12 changed files
  • Comments generated: 8
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread app/models/concerns/heartbeat_poisoning.rb Outdated
Comment thread app/models/user.rb
Comment thread spec/requests/api/admin/v1/bans_spec.rb
Comment thread db/migrate/20260903120000_add_poison_to_users.rb Outdated
Comment thread spec/requests/api/admin/v1/bans_spec.rb
Comment thread spec/requests/api/admin/v1/bans_spec.rb Outdated
Comment thread swagger/admin/swagger.yaml Outdated
Comment thread swagger/admin/swagger.yaml Outdated
@greptile-apps

greptile-apps Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds heartbeat poisoning as a superadmin moderation capability.

  • Hides a user’s heartbeats before a configurable cutoff while retaining the underlying records.
  • Adds RESTful admin endpoints, strong parameter filtering, audit metadata and generated API documentation.
  • Refreshes dashboard, leaderboard and active-project derived data when poison state changes.
  • Preserves ingestion deduplication against hidden heartbeats and adds request and model coverage.

Confidence Score: 5/5

The PR appears safe to merge, with the previously reported findings resolved and no new actionable regression identified.

The latest changes correctly introduce a permitted parameter boundary without breaking the documented JSON body or tested plain-text date input. Every previous review thread is manually resolved, so no outstanding finding remains.

Important Files Changed

Filename Overview
app/models/concerns/heartbeat_poisoning.rb Defines the default visibility filter and scoped access to poisoned heartbeat records.
app/models/user.rb Owns poison state transitions, cutoff parsing and derived-data invalidation.
app/services/heartbeat_ingest.rb Performs deduplication against all stored heartbeats so poisoning does not break duplicate submissions.
app/controllers/api/admin/v1/bans_controller.rb Exposes authenticated superadmin operations with permitted ban parameters and bounded raw-date support.
app/jobs/cache/active_projects_job.rb Excludes poisoned activity from active-project cache generation.
config/routes.rb Declares the moderation endpoint through a RESTful singular resource.
spec/requests/api/admin/v1/bans_spec.rb Documents and exercises the new admin API contract through Rswag.
test/models/concerns/heartbeat_poisoning_test.rb Covers visibility, deduplication, cutoff semantics and derived-data refresh behavior.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  A[Superadmin ban request] --> B[Resolve user and cutoff]
  B --> C[Store poison state]
  C --> D[Default heartbeat scope]
  D --> E[Hide pre-cutoff heartbeats]
  C --> F[Refresh dashboard rollups]
  C --> G[Rebuild current leaderboards]
  C --> H[Refresh activity caches]
  I[Heartbeat ingestion] --> J[Unfiltered deduplication lookup]
  J --> K[(Stored heartbeat records)]
  L[Superadmin unban request] --> M[Clear poison state]
  M --> F
  M --> G
  M --> H
  M --> D
Loading

Reviews (6): Last reviewed commit: "Merge branch 'hearbeat-poisoning' of htt..." | Re-trigger Greptile

Comment thread app/models/concerns/heartbeat_poisoning.rb Outdated
Comment thread app/models/user.rb Outdated
Comment thread swagger/admin/swagger.yaml
Comment thread app/models/user.rb
Comment thread config/routes.rb
Comment thread app/models/user.rb
Comment thread app/models/user.rb Outdated
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
Comment thread app/controllers/api/admin/v1/bans_controller.rb
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.

2 participants