Commit Graph

101 Commits

Author SHA1 Message Date
cdf85f6364 audit week 1: creator ID tracking, channel-queue migration, deprecation cleanup
QUAL-006  store ticket.creatorId on creation; legacy split-pop returned the
          message ID for discord-msg-* tickets, breaking transcript DM, close
          log, and channel rename for context-menu-created tickets. Adds the
          field to the Ticket schema and writes a one-shot backfill script
          (scripts/backfill-creatorId.js, dry-run by default).

QUEUE-001 add enqueueOverwrite + enqueueTopic to services/channelQueue.js
          (chain on renameChains alongside enqueueMove). Migrate handleAdd /
          handleRemove / handleMove / handleTopic so permissionOverwrites,
          setParent, and setTopic no longer race pending renames or sends.
          handleMove now uses the existing enqueueMove. Initial overwrites in
          handleTicketModal stay inline; channel doesn't exist yet so no race.

DISCORD-001 replace ephemeral: true with flags: MessageFlags.Ephemeral across
            broccolini-discord.js, handlers/sharedHelpers.js, handlers/buttons.js,
            handlers/commands.js. runDeferred opts now take { flags } directly.

SEC-003   /gmailpoll min interval is 30s. Drop the 5s/10s slash-command
          choices and clamp Math.max(30000, ms) in handleGmailPoll for
          defense in depth.

QUAL-001  upgrade silent .catch(() => {}) on the lastActivity updateOne in
          handlers/messages.js to log via logError, so transient Mongo errors
          surface in the debug channel instead of disappearing.

QUAL-002  drop await from logError/logWarn calls in services/staffThread.js
          and services/pinMessage.js — fire-and-forget per CLAUDE.md hard rule.

QUAL-003  wrap stray setTimeouts (handleConfirmCloseRequest force-close timer,
          runFinalClose channel-delete + overflow-cleanup, checkAutoClose
          delete-after-email) in trackTimeout via lazy require so they clear
          on shutdown.
2026-05-08 20:19:14 +00:00
e3b3b8d48c refactor handleButton into a dispatch table
Each customId now maps to a named handler in one of two tables:
FREE_BUTTON_HANDLERS (open-ticket panel, tag-delete cancel — no ticket
lookup) or TICKET_BUTTON_HANDLERS (anything fired inside a ticket channel
— the dispatcher does the lookup once before delegating). The dynamic
`confirm_delete_tag::*` id is matched by prefix.

To find a button's logic, search handle<Name>Button or handleTagDelete*.

Other cleanups in the same pass:
- Move findTicketForChannel and runDeferred from handlers/commands.js to
  the new handlers/sharedHelpers.js so both files share one source of
  truth. runDeferred now also calls logError(verb, ...) — was logged ad
  hoc in buttons.js, missing in commands.js. Strictly additive.
- Hoist three inline `require('../services/...')` calls (staffThread,
  pinMessage, debugLog) to top imports.
- Collapse escalate_to_tier2 and escalate_to_tier3 into one
  handleEscalateButton(interaction, ticket) that derives the tier from
  customId. Same for confirm_close / confirm_close_with_email /
  confirm_close_no_email — one handleConfirmCloseRequest deriving
  sendEmail from customId.
- Decompose the 156-line handleConfirmClose into runFinalClose +
  buildTranscriptText + formatDateForTranscript + renderTranscriptHeader
  + dmTranscriptToCreator + postCloseLogEntry. Each piece is testable in
  isolation.
- Decompose handleClaim into applyClaim + applyUnclaim.
- Extract buildOpenTicketModal() and postTicketWelcomeEmbeds() so the
  ticket-creation modal flow is readable top-to-bottom.

No behavior change. handleButton + handleTicketModal exports preserved;
24/24 modules load clean (sharedHelpers.js is the new one).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:57:43 +00:00
3ac23466b2 refactor handleCommand into a dispatch table
Each slash command and context-menu entry is now its own named function;
handleCommand looks the name up in COMMAND_HANDLERS and delegates. Finding
where a command lives is now "grep handle<Name>" instead of scrolling 600
lines of sequential ifs.

Other cleanups in the same pass:
- Restore ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle
  to the top-level discord.js destructure. ActionRowBuilder was used at
  runtime by /response delete and /panel but had been dropped from the
  imports based on a stale "unused" diagnostic — those paths would have
  thrown ReferenceError. Hoisting the previously-inline /signature
  imports as well.
- Hoist `logTicketEvent` to the top imports (was inline-required at three
  callsites).
- Extract findTicketForChannel(), runDeferred(), and fetchLoggingChannel()
  helpers — replaces the lookup-then-defer-then-try-catch boilerplate
  repeated in nearly every branch.
- Pull the force-close timer body into finalizeForceClose() and
  postTranscript() so the timer registration is one line.
- Pull the panel button-row construction into buildPanelButtonRow().
- Split /response into its own RESPONSE_SUBCOMMANDS dispatch + per-sub
  handlers.
- Consolidate the duplicated transcript date formatter into one local fmt().

No behavior change. All 23 modules still load clean; handleCommand,
handleContextMenu, handleAutocomplete, runEscalation, and runDeescalation
exports are preserved (handlers/buttons.js imports the last two).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:51:29 +00:00
83b6b4ae0c simplify: rename CONFIG channels, dedup hasStaffRole, drop enforceEmbedLimit
- Rename CONFIG.TRANSCRIPT_CHAN -> CONFIG.TRANSCRIPT_CHANNEL_ID and
  CONFIG.LOG_CHAN -> CONFIG.LOGGING_CHANNEL_ID across 9 callsites so
  CONFIG keys match their .env names — no more "grep .env, find nothing"
  for new readers
- Replace handlers/commands.js#hasStaffRole with utils.js#isStaff
  (was a verbatim copy)
- Delete utils.js#enforceEmbedLimit and its 2 callsites; both inputs are
  bounded well under the 6000-char Discord embed cap, so the trim was
  defensive code that never fired

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:45:18 +00:00
840b6bfcf8 simplify: prune dead code, dedup gmail send, drop neutered log stubs
- Remove no-op log stubs (logGmail, logAutomation, logSecurity, logSystem)
  and ~17 callsites; dead counters in tickets.js and gmail-poll.js go too
- Dedup three near-identical Gmail send paths into sendThreadedEmail helper
- Drop dead Mongoose fields: broccoliniTicketId, lastSyncedBroccoliniArticleId,
  renameCount, renameWindowStart, reminderSent, staffChannelId,
  unclaimedRemindersSent, lastMessageAuthorIsStaff
- Drop dead config fields and their .env.example entries
- Inline api/botClient.js (3-line wrapper, 2 callers)
- Trim unused exports across utils.js, tickets.js, configSchema.js, debugLog.js
- Fix handlers/messages.js to use isStaff() — old partial check ignored
  ADDITIONAL_STAFF_ROLES, so those members were treated as customers
- Drop unused deps p-queue + dotenv-expand; move mongodb to devDependencies

Net: -583 LOC source + -57 LOC lockfile. All 23 modules load clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 18:37:14 +00:00
d5547e5eea remove stale docs/ tree and gitignore comment
8 untracked .bak*/.dubignore files and empty docs/architecture, docs/setup, docs/ also removed from disk.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:20:47 +00:00
602c6c0191 remove diff-paste garbage files
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:19:44 +00:00
6b94791813 cleanup and simplify
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 02:15:18 +00:00
d1e1408256 email fixes 2026-04-21 20:54:49 +00:00
8e362c607d mvp: neuter debug log helpers, strip config keys, update tagline 2026-04-21 20:18:59 +00:00
410f8b043e fix: add Escalate button to email ticket welcome embed
gmail-poll.js was hand-rolling its own Close+Claim-only action row.
Replaced with getTicketActionRow({ escalationTier: 0 }) — same helper
panel-created tickets use. Email and Discord tickets now show identical
buttons on creation: Close, Claim, Escalate.
2026-04-21 19:50:11 +00:00
2a04e3964c trim settings-site to match stripped bot
- delete public/js/notifications.js (521 LOC)
- remove notifications/patterns/surge/chat/priority/bosscord/accountinfo/threads UI sections
- remove 3 /api/notifications/* proxy routes from server.js
- untrack settings-site backup files from git
- ~926 LOC removed from settings-site
2026-04-21 19:34:10 +00:00
60c302276b more removals 2026-04-21 17:32:00 +00:00
ce62b7a94a cleanup: untrack .bak3 backups; dedupe + broaden bak gitignore pattern 2026-04-21 17:26:35 +00:00
f3ee27ed7a more mvp strip 2026-04-21 17:24:03 +00:00
6d579207f3 untrack CLAUDE.md, settings-site/CLAUDE.md, .claude/ (local-only)
Added CLAUDE.md to .gitignore (unanchored — matches nested too).
2026-04-21 17:21:39 +00:00
431622d05c untrack .claude/ local settings 2026-04-21 17:20:19 +00:00
b1f66107c0 untrack CLAUDE.md 2026-04-21 17:20:09 +00:00
b764bc98c7 untrack CLAUDE.md 2026-04-21 17:19:39 +00:00
5de05a0d01 strip: remove unused CloseRequest mongoose model
Close-button confirmation uses the in-memory pendingCloses Map
(handlers/pendingCloses.js), not this persisted schema. Zero readers.
2026-04-21 16:57:09 +00:00
34dc55c20b strip: remove /backup /export /search /stats /fix-stale-tickets + analytics module
- delete handlers/analytics.js
- remove trackInteraction calls; replace trackError with logError().catch(() => {})
- remove 5 slash commands from register.js
- remove BACKUP_EXPORT_CHANNEL_ID from config + schema + .env.example
2026-04-21 16:44:01 +00:00
fa7d4af132 strip: delete stale docs/ and broccolini_bot_context.md
Both were saturated with references to removed features.
Regenerate fresh post-MVP.
2026-04-21 16:32:05 +00:00
ca737039f8 strip: remove data-forensics scripts from parent IB-Discord-Bot project
Kept: backup-env.js, test-mongodb.js (wired to npm run test-mongodb).
2026-04-21 16:19:39 +00:00
bf901039bc mvp & email signature 2026-04-21 16:15:18 +00:00
071fae2ea3 strip: drop gitlab CI, stray git/ dir, FEATURES.md; untrack CLAUDE.md; ignore *.bak* 2026-04-21 16:04:54 +00:00
3300a7fc19 untrack CLAUDE.md (local-only) 2026-04-21 16:03:00 +00:00
1a46fb696a cleanup: remove strip backup files 2026-04-21 15:57:51 +00:00
636348d824 strip: remove pattern/surge/chat alert monitoring + unused commands
- delete services/{patternChecker,patternStore,surgeChecker,chatAlertChecker,staffNotifications,staffChannel,notificationRegistry,notificationEnabled,staffPresence}.js
- remove /notification, /staffnotification, /tag, /priority
- /escalate: drop action param, always unclaim
- purge PATTERN_*, SURGE_*, CHAT_ALERT_*, STAFF_* env vars from config + .env.example
- drop StaffNotification model
- ~2500 LOC removed
- settings-site /internal/notifications/* endpoints gone (UI will 404 until trimmed)
2026-04-21 15:57:18 +00:00
298cf13d5c settings site changes pre-mvp-strip 2026-04-21 15:30:40 +00:00
74d7f49c8d test 2026-04-21 14:32:34 +00:00
Sam Kintop
c6edc5c0bf remove files 2026-04-21 09:13:59 -05:00
33b1f276c6 audit 2026-04-20 18:05:36 +00:00
d73422555d rename path: fix env-var mismatch, gut canRename gate, add primary-bot fallback on 401/403/429
- secondary rename-bot token was set as RENAME_TOKEN in .env but utils/renamer.js reads RENAMER_BOT; silently no-op'd every rename (host .env renamed separately)
- services/tickets.js canRename gutted to an always-ok shim; Mongo 2/10min per-channel gate is redundant since renames flow through RENAMER_BOT's own bucket. Ticket.renameCount / renameWindowStart remain as orphan fields (no migration)
- handlers/buttons.js + commands.js: drop the four "Channel renamed too quickly" else-branches and the rename-countdown label suffix; replace .catch(() => {}) with .catch(err => logError('rename', err)...)
- services/channelQueue.js: executeRename falls back to channel.setName(currentName) when renamer throws err.fallback === true (401/403/429); classifies non-fallback errors as renameQueue:token/permission (401/403) or renameQueue:secondary-bot ratelimited (429)
- utils/renamer.js: on 401/403 throw err.fallback=true immediately; on 429 respect retry_after up to 2000ms then throw err.fallback=true
- docs: align CLAUDE.md, docs/api/DISCORD_API_VALIDATION.md, docs/architecture/CRITICAL_FILES_AND_HOW_IT_WORKS.md

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 15:56:06 +00:00
fcce7c3e86 changes 2026-04-20 14:56:55 +00:00
8a45b59b28 phase 9 notification toggles (per-alert, per-category, master; default-disabled) 2026-04-18 23:51:59 +00:00
39a5482516 phase 8 server-side validation (configSchema, inline field errors, partial-success semantics) 2026-04-18 19:54:47 +00:00
23a02c87d9 settings-site: phase 6 accessibility (ARIA combobox/listbox pattern, keyboard nav, modal focus trap, toast a11y, contrast + typography fixes) 2026-04-18 19:30:15 +00:00
0f62fb9020 phase 5 dynamic alert registry (bot canonical, settings-site with fallback) 2026-04-18 19:14:51 +00:00
e2443fd94a settings-site: phase 4 client refactor (split app.js into focused modules, shared dropdown helper, strict-CSP-ready) 2026-04-18 18:04:46 +00:00
0ac6debcf9 settings-site: phase 3 stack hygiene (express 5, drop node-fetch, engines, nvmrc) 2026-04-18 16:48:24 +00:00
3e2bf919e9 settings-site: phase 2 correctness fixes (proxy helper, /healthz, datetime-local min, health polling) 2026-04-18 16:32:37 +00:00
84c7a50cc3 settings-site: phase 7 mobile responsiveness 2026-04-18 16:26:39 +00:00
d134f5f678 broccolini-bot: bind internal API to 0.0.0.0 for bridge access; mount .env for config persistence 2026-04-18 16:26:37 +00:00
21618efbad security hardening 2026-04-18 11:10:41 +00:00
a409203025 manual commit 2026-04-10T20:51:10Z 2026-04-10 20:51:10 +00:00
785b2e5b8f manual commit 2026-04-10T20:31:52Z 2026-04-10 20:31:52 +00:00
cda5019918 manual commit 2026-04-10T20:16:18Z 2026-04-10 20:16:18 +00:00
f8d323b0c7 manual commit 2026-04-10T20:01:57Z 2026-04-10 20:01:57 +00:00
95c3e2a88a manual commit 2026-04-10T19:59:04Z 2026-04-10 19:59:04 +00:00
71d6e0a045 manual commit 2026-04-10T19:57:09Z 2026-04-10 19:57:09 +00:00