Track the Hack Bot verifies hackers, synchronizes organizer roles, and provides the Hack the Hill Discord-to-OpenProject task workflow.
- Node.js 24
- A Discord application installed in the Organizer and Community servers
- PostgreSQL and OpenProject, if the task integration will be enabled
-
Clone the Repository
git clone https://github.com/hackthehill/track-the-hack-bot.git cd track-the-hack-bot -
Install dependencies
npm ci
-
Configure the environment
cp .env.example .env
Fill in the core Discord, role, log-channel, Track the Hack URL, and HMAC values in
.env.CLIENT_IDis required when registering commands. The remaining OpenProject, PostgreSQL, mapping, and optional Azure OpenAI values are documented in .env.example.The core runtime values are:
Variable Purpose DISCORD_TOKENDiscord bot token COMMUNITY_GUILD_IDCommunity server ORGANIZER_GUILD_IDOrganizer server COMMUNITY_GUILD_HACKER_ROLE_IDRole assigned after verification COMMUNITY_GUILD_ORGANIZER_ROLE_IDOrganizer role managed in the Community server ORGANIZER_GUILD_ORGANIZER_ROLE_IDSource Organizer role and mapping-admin role LOG_CHANNEL_IDCommunity verification log channel TRACK_THE_HACK_URLPublic Track the Hack application URL INTERNAL_API_SECRETShared secret for signed verification requests PORTis optional and defaults to4000. -
Register Discord commands
npm run register
Run this once for a new Discord application and again whenever the command definitions change.
-
Build and start the bot
npm run build npm start
For development with automatic restarts, use
npm run devinstead.
Enable the Server Members Intent and Message Content Intent in the
Discord Developer Portal. Install the application with the bot and
applications.commands scopes in both servers. The bot needs access to the
channels it operates in, including permission to read message history and send
messages. It also needs Manage Roles and Manage Nicknames, with its bot role
above the Hacker and Organizer roles that it manages.
/verify: Get a Community-server verification link./sync: Synchronize the configured Organizer role and nicknames to the Community server./help: Show server-specific command help./task create: Members-role users in the Organizer server create tasks; the title is required, while the project can be selected explicitly or inferred from the channel category or assignee's team. Description, assignee, accountable user, priority, size, dates, and estimates are optional./task view|assign|reschedule|close|reopen|announce: Manage an existing task./task link-user,/task configure-category,/task reconcile: Organizer-only identity, category mapping, and ambiguous-create recovery commands.- Message → Apps → Create OpenProject task: Create from a message with a backlink.
- Message → Apps → Draft OpenProject task with AI: Create a private, reviewable proposal in an AI-allowlisted channel; it never auto-creates a task.
The bot also synchronizes the configured Organizer role and nickname when a member joins the Community server.
The integration is enabled when OPENPROJECT_BASE_URL, OPENPROJECT_API_KEY,
DATABASE_URL, ORGANIZER_GUILD_ID, ORGANIZER_GUILD_MEMBER_ROLE_ID, and
ORGANIZER_GUILD_ORGANIZER_ROLE_ID are valid. If they are not, verification,
synchronization, and help remain available while task interactions are disabled.
On startup, the bot creates or updates its PostgreSQL schema and seeds identity
and category mappings from the environment. Organizers can then maintain those
mappings with /task link-user and /task configure-category. Members can
access projects associated with their channel category or configured team
roles. OPENPROJECT_BLOCKED_CHANNEL_IDS disables task creation in selected
channels.
Projects, priorities, types, users, and sizes are loaded from OpenProject. New
tasks default to today and seven days ahead. Similar open tasks are rejected;
manual /task create requests can use allow_duplicate to override that check.
Manual AI drafting requires an allowlisted channel in
OPENPROJECT_AI_CHANNEL_IDS and configured Azure OpenAI endpoint/deployment.
Automatic extraction is controlled separately by OPENPROJECT_AUTOMATION_MODE:
offdisables automatic extraction.shadowstores proposals without posting review cards.reviewposts human-review cards after the configured channel idle period.
Azure OpenAI authentication uses managed identity rather than an API key. The bot bounds the context, aliases Discord identities, redacts common credentials and contact details, and rejects matching sensitive discussions before making an Azure request. For a manually requested draft, the requester can explicitly override a false positive for that one minimized request; the approval expires after ten minutes and is never available to automatic extraction. This reduces exposure but is not a guarantee. Keep automatic extraction off until it has been evaluated on representative conversations.
The Compose configuration runs the bot with PostgreSQL for local development
and smoke testing. After configuring .env, start it with:
POSTGRES_PASSWORD=change-me docker compose -f docker-compose.local.yml up --buildProduction runs as a private Azure Container App with managed PostgreSQL. The
bot exposes /healthz and /readyz; Track the Hack calls /verify over private
HTTPS with x-track-the-hack-timestamp and x-track-the-hack-signature
(HMAC-SHA256 over timestamp.body). Invalid or expired signatures are rejected.
Bot-specific deployment and release guidance is in
infra/README.md.
Contributions are welcome! For major changes, please open an issue first to discuss what you would like to change.
This project is licensed under the MIT License. See the LICENSE file for more information.
For more information, please contact us at development@hackthehill.com.