Plan: Move Slack Assistant services into brainforge-platform (Railway)

Date: 2026-03-21
Status: Draft
Audience: Platform / AI team

Goal

Consolidate Slack assistant workloads from the separate Railway project slack-assistant into brainforge-platform, so platform web, workers, and Slack apps share one project for operations, access, and deploy visibility—without changing app behavior unless intentionally updated.

Scope

In scope

  • Recreate equivalent Railway services under brainforge-platform (same repo, same apps/slack-apps/brainforge-assistant root).
  • Copy env configuration, domains, and GitHub deploy wiring; cut over Slack + internal URLs; decommission old services after validation.
  • Update repo docs (root directory path, service names) and Platform RAILWAY_PROJECT_IDS if used.

Out of scope (unless explicitly decided)

  • Rewriting the Slack app or merging multiple apps into one Railway service.
  • Moving unrelated projects (google-workspace-mcp, openwork-labs, etc.).

Current vs target

TodayTarget
Railway projectslack-assistantbrainforge-platform
Services (observed)Nudge-Agent, brainforge-test-assistant, brainforge-assistant-ghSame roles as new services (names can match or be renamed for clarity, e.g. brainforge-assistant, brainforge-assistant-test, nudge-agent)
Repo / rootbrainforge-platform monorepo, subpath deployUnchanged: apps/slack-apps/brainforge-assistant

Note: Railway has no “move service between projects.” Migration is create → copy env → cut over → retire.

Preconditions

  • Railway CLI auth: railway whoami (see standards/03-knowledge/engineering/setup/railway-cli-setup.md).
  • Access to Brainforge Slack app settings (URLs for commands, events, interactivity).
  • Access to any consumers of assistant base URLs (e.g. HubSpot nudge BRAINFORGE_ASSISTANT_URL, Linear webhooks, internal docs).
  • 1Password / secret source for duplicating variables (same items as today, new service targets).
  • Agreed naming: whether to keep service names *-gh / Nudge-Agent or standardize (document the decision before cutover).

Phase 1 — Inventory

  1. For each service in slack-assistant, record:
    • Service name, public URL(s), custom domain(s).
    • Root directory (should be apps/slack-apps/brainforge-assistant).
    • Builder (Railpack/Nixpacks), build command (npm install), start command (npm run start).
    • Full env var set (export from Railway or document names; do not paste secrets into tickets).
  2. Map which Slack app / slash commands / webhooks point to which URL (prod vs test vs nudge).
  3. List downstream references: apps/hubspot-lead-nudge/README.md, standards/.../slack-ticket-approval.md, vault links, any hardcoded *.up.railway.app URLs.

Exit criteria: One table: service → URL → Slack surfaces → dependents.

Phase 2 — Create services in brainforge-platform

  1. railway link --workspace Brainforge --project brainforge-platform --environment production (or staging first if you prefer).
  2. For each required role, railway add --service <name> (see standards/03-knowledge/engineering/setup/github-railway-repo-and-services-without-ui.md).
  3. Connect GitHub repo brainforge-ai/brainforge-platform, branch main (or your standard).
  4. Set source root directory to apps/slack-apps/brainforge-assistant for each service.
  5. Confirm build/start match Phase 1 (typically install + npm run start).
  6. Do not cut traffic yet: either use temporary Railway-generated URLs or attach domains only after env copy.

Exit criteria: New services build and deploy successfully (health OK) with test or non-prod secrets first if available.

Phase 3 — Copy secrets and behavior flags

  1. Copy variables from old service → new service (1:1 per role), including Azure, Slack tokens, REPO_CONTEXT_*, Linear, Ops channel IDs, etc.
  2. Preserve test vs prod semantics:
    • RAILWAY_ENVIRONMENT_NAME, DEPLOYMENT_BRANCH, TEST_MODE, test Slack tokens—must match how apps/slack-apps/brainforge-assistant/ENVIRONMENT.md defines test mode.
  3. Regenerate or reuse public URLs; attach custom domains if the old stack used them.

Exit criteria: Parity checklist signed off per service (same env keys; values verified in a secure way).

Phase 4 — Cutover

  1. Slack app configuration (per URL that moved):
    • Slash commands → https://<new-host>/slack/commands
    • Event subscriptions → https://<new-host>/slack/events
    • Interactivity → https://<new-host>/slack/interactive
    • Linear webhooks (if applicable) → https://<new-host>/slack/linear-webhook
  2. Update HubSpot nudge (or any job) BRAINFORGE_ASSISTANT_URL to the production assistant base URL.
  3. Update internal docs / env examples that reference old hostnames.
  4. Run smoke tests:
    • URL verification (Slack)
    • /brainforge or prod command, @ mention, thread behavior
    • Test command path if applicable (/brainforge-test, etc.)
    • Nudge / internal POST routes if used
  5. Monitor Railway logs and Slack for 24–48 hours.

Rollback: Keep old services running until cutover is verified; revert Slack URLs and consumer env vars to old base URLs if needed.

Exit criteria: No regressions on critical paths; old URLs no longer required for production traffic.

Phase 5 — Cleanup and governance

  1. Scale down or delete services in slack-assistant; archive or delete the empty project when safe.
  2. Platform deploy-status: If RAILWAY_PROJECT_IDS is set on the web app, remove the old project ID so only brainforge-platform remains (see apps/platform/src/lib/railwayApiServer.ts and .env.example).
  3. Docs:
    • Fix apps/slack-apps/brainforge-assistant/README.md §5: root directory apps/slack-apps/brainforge-assistant (not slack-apps/...).
    • Update knowledge/engineering/railway-setup-review-2026-03-07.md “Current Railway Shape” or add a line “Slack assistant: consolidated into brainforge-platform as of <date>.”
  4. Optional: add a short operator blurb under standards/03-knowledge/engineering/setup/ (“Slack assistant lives in brainforge-platform”) if the team wants a single setup pointer.

Risks and mitigations

RiskMitigation
Wrong env on new service (prod vs test tokens)Copy from correct source service; label rows in inventory; smoke test in test channel first.
Slack URL cache / typoChange one surface at a time; keep rollback URLs documented.
Missed consumer (cron, another app)Phase 1 dependency grep + `rg ‘brainforge-assistant
Deploy-status noiseTighten RAILWAY_PROJECT_IDS after consolidation.

Success criteria

  • All Slack assistant traffic for Brainforge uses services under brainforge-platform.
  • slack-assistant project retired or empty with team agreement.
  • Repo and playbook references updated; no stale slack-apps/brainforge-assistant path in deployment instructions.
  • Prior shape notes: knowledge/engineering/railway-setup-review-2026-03-07.md
  • CLI / no-UI service creation: standards/03-knowledge/engineering/setup/github-railway-repo-and-services-without-ui.md
  • App env contract: apps/slack-apps/brainforge-assistant/ENVIRONMENT.md