Skip to content

dangeranger/hackie-slack

Repository files navigation

Hackie Slack, a modern Slackin using Cloudflare Workers

A modern self-invite gateway for Slack communities, built for Cloudflare Workers.

Features

  • Landing page with Slack member count and approximate online count
  • Email-confirmed self-invite flow
  • Permanent opt-out suppression link
  • Code of Conduct acceptance gate before Slack invite link redirect
  • Bot protection with Cloudflare Turnstile
  • App-level rate limits and event audit logging (D1)
  • Scheduled Slack stats refresh every 15 minutes
  • Cloudflare Web Analytics beacon support

Architecture

  • Runtime: Cloudflare Workers + Hono
  • Data: Cloudflare D1
  • Email: Cloudflare SendEmail binding
  • Abuse control: Turnstile + app throttling (+ Cloudflare Rate Limiting rule)
  • Stats source: Slack Web API

Quick Start

  1. Install dependencies:
npm install
  1. Create D1 database:
npm run db:create
  1. Update wrangler.jsonc with your database_id.

  2. Apply migrations:

npm run db:migrate:local
npm run db:migrate:remote
  1. Set required secrets:
npx wrangler secret put TURNSTILE_SECRET
npx wrangler secret put SLACK_BOT_TOKEN
npx wrangler secret put EMAIL_ENCRYPTION_KEY
npx wrangler secret put EMAIL_HASH_KEY

For local dev, copy .dev.vars.example to .dev.vars and fill values.

  1. Update wrangler.jsonc vars:
  • APP_BASE_URL
  • EMAIL_FROM
  • TURNSTILE_SITE_KEY
  • SLACK_SHARED_INVITE_URL
  • COC_VERSION
  • ANALYTICS_TOKEN (optional)
  1. Start local dev:
npm run dev

Required Slack Scopes

Create a Slack app/bot token with:

  • users:read
  • users:read.presence

Required Cloudflare Setup

SendEmail

  • Verify sending domain and sender address.
  • Configure DMARC/SPF/DKIM.

Turnstile

  • Create a Turnstile widget.
  • Use test keys for staging/local.

Cloudflare Rate Limiting (recommended)

Create a dashboard rate-limit rule for:

  • Path: POST /api/invite-request
  • Limit: 20 requests / 10 minutes / IP

This Worker also enforces a local fallback IP/email limit in D1.

Routes

  • GET / landing page
  • POST /api/invite-request submit email + Turnstile token
  • GET /confirm?token=... render explicit confirmation page (non-mutating)
  • POST /confirm perform confirmation transition, then show CoC
  • POST /api/consent accept CoC, redirect to Slack invite URL
  • GET /optout?token=... render explicit opt-out confirmation page (non-mutating)
  • POST /optout suppress future invites
  • GET /healthz health check

Data Model

Defined in migrations/0001_initial.sql:

  • invite_requests
  • invite_tokens
  • suppression_list
  • workspace_stats
  • event_log

Testing

npm test

Deployment

npm run deploy

Changelog

Generate the changelog from Conventional Commit messages:

npm run changelog

Preview without writing to CHANGELOG.md:

npm run changelog:preview

Why this format

The generated output follows Keep a Changelog and Common Changelog so release notes stay:

  • Consistent and easy to scan over time
  • Focused on user-facing changes instead of internal noise
  • Easy to consume in pull requests and release announcements

Which commits are included

Changelog generation is based on Conventional Commits and provides:

Curated summary sections are produced for:

  • feat -> Added
  • perf, refactor -> Changed
  • revert -> Removed
  • fix -> Fixed
  • docs -> Documentation
  • chore -> Chores
  • Commits with security-related content in the body -> Security

Each release also includes a ### Changelog section with the full commit list for the release range:

  • Full-list entries use this format: - [#123] <commit-subject> @<committer-id>
  • [#123] appears only if a PR/issue reference exists in the commit message.
  • <committer-id> is derived from GitHub noreply author email when available.
  • Types such as test, ci, build, style, and other conventional types are included in the full list even when omitted from curated summary sections.

Breaking changes are preserved and marked as **BREAKING** in summary entries.

How to read CHANGELOG.md

  • ## [Unreleased] - YYYY-MM-DD is the current unreleased set of changes.
  • Section headers (Added, Changed, Removed, Fixed, Documentation, Chores, Security) describe change categories.
  • Each bullet is one commit summary, optionally prefixed with scope (for example, **app:**).
  • ### Changelog includes the compare link plus the full commit list for that release block.
  • Once release tags are added (for example, v0.2.0), changelog sections naturally split by tag history and Unreleased contains only commits after the latest tag.

Notes

  • This is intentionally single-workspace in v1.
  • For non-enterprise Slack, final step is redirect to a managed shared invite URL.
  • Opt-out suppression is indefinite until removed manually.

Data Retention Policy

  • Expired invite tokens are deleted after 30 days.
  • Stale invite requests older than 90 days are deleted for statuses PENDING_CONFIRM, CONFIRMED, and EXPIRED.
  • Event logs older than 180 days are deleted.
  • Cleanup runs in every scheduled() invocation.

Production Hardening

  • Slack API calls use retry with exponential backoff, jitter, and Retry-After handling for 429/5xx.
  • Slack API calls use request timeouts to avoid long-hanging scheduled executions.
  • Presence estimation tolerates partial failures and marks refresh stale when error rate is too high.
  • Turnstile verification uses request timeout and fails closed on network/timeout errors.
  • State-changing POST routes enforce same-origin Origin/Referer checks.
  • Invite request email_hash and ip_hash use versioned HMAC hashing with EMAIL_HASH_KEY.
  • HTML responses use nonce-based CSP (no unsafe-inline), with stricter defaults (default-src 'none', frame-ancestors 'none', object-src 'none').
  • Security headers include HSTS, COOP/CORP, no-referrer policy, and no-store cache-control.
  • Runtime config guard returns 503 when required production env values are missing; /healthz returns only coarse ok status.

About

Secure Slack self-invite gateway built with Cloudflare Workers, Hono, D1, Turnstile, and the Slack API

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors