Files
redmine/docs/redmineup_local_fork_changelog.md
Jason Thistlethwaite bd26c8894f Add production rollout tooling and semantic index ops docs
Capture the production plugin rollout workflow and Qdrant validation steps so operations stay repeatable. Also harden redMCP stdio/schema compatibility to keep diverse MCP clients and validators working.
2026-05-06 22:18:02 -04:00

14 KiB

RedmineUP Local Fork Changelog

The installed RedmineUP redmine_contacts and redmine_contacts_helpdesk plugins are treated as locally maintained legacy code for this Redmine 3.4.4 environment. Before risky edits, archive the current plugin directories in dist/ and record the purpose, touched behavior, and LAN test result here.

Current Checkpoint

  • Baseline:
    • Redmine 3.4.4
    • redmine_contacts 4.1.2 PRO
    • redmine_contacts_helpdesk 3.0.9 PRO
  • Strategic direction:
    • Treat helpdesk/customer data as first-class.
    • Prefer local-fork plugin edits when they unlock safer search/indexing.
    • Keep Redmine request paths independent from external worker/index failures.
  • Implemented locally:
    • redmine_event_outbox plugin with issue/journal/contact events.
    • Optional helpdesk outbox hooks for HelpdeskTicket and JournalMessage.
    • Read-only helpdesk_search/* JSON endpoints in the local helpdesk fork.
    • Standalone contact CLI and read-only helpdesk export/search CLI.
  • LAN deployment status:
    • Helpdesk search routes were deployed and route-loaded successfully on the LAN Redmine copy.
    • Short alias/usage routes were added to avoid noisy routing errors during manual browser testing.
    • Helpdesk mail import, Helpdesk metadata lookup, default non-email updates, and explicit outbound Helpdesk replies are live-smoke-tested through redMCP.
    • Helpdesk outbox/worker validation now has a repeatable live script.
  • Next meaningful milestone:
    • Run validate_helpdesk_outbox_worker.py after outbox or worker changes, then choose the external index target.

2026-05-06 - Production Plugin Rollout Via Unified Script

  • Touched areas:
    • plugins/redmine_contacts
    • plugins/redmine_contacts_helpdesk
    • plugins/redmine_event_outbox
    • deploy_redmine_prod_patches.sh
  • Purpose:
    • Apply the same plugin payload shape used by test-host post-import automation to production in a controlled, repeatable sequence.
    • Keep rollback simple by backing up plugin directories before each apply run.
  • Behavior/deployment tooling:
    • Added and used deploy_redmine_prod_patches.sh with one-command dry-run, apply, and rollback modes.
    • Deployment package assembled as dist/redmine-prod-plugin-rollout-20260506T210606Z.tar.gz for upload and unpack on production.
    • Script-level checks include Ruby syntax checks per plugin, plugin migration, Passenger restart, and optional API verification for include=journals,helpdesk behavior.
  • Production result:
    • Production rollout completed and reported working after deploy.
    • This confirms the production host now has the local plugin fork updates in place through the scripted deployment path.

2026-04-25 - redMCP Native Search, Filtering, And MCP Operations

  • Touched areas:
    • redMCP
  • Purpose:
    • Make Redmine's existing issue filtering and built-in text search explicit before adding external search infrastructure.
    • Make redMCP runnable as an MCP server for live client testing.
    • Make the network MCP server easier to debug and restart during local tests.
  • Behavior changed:
    • Added filterIssues() as a named alias for Redmine's /issues.json filtering.
    • Added search() for Redmine's built-in /search.json endpoint.
    • Added searchIssues() for issue-only Redmine text search.
    • Added projects(), listProjects(), and project() for Redmine's /projects.json APIs.
    • Added users(), listUsers(), user(), and projectMemberships() for Redmine's user and membership APIs.
    • Added ListQueryNormalizer so MCP list tools accept friendly paging, sorting, status, and date options while preserving raw Redmine filters/params overrides.
    • Added redMCP/bin/test-query-normalizer.php for no-network checks of Redmine query parameter normalization.
    • Added a shared MCP dispatcher and transport-specific server wrappers.
    • Added redMCP/bin/redmcp-server.php for stdio MCP clients.
    • Added redMCP/bin/redmcp-http-server.php for bearer-token-protected Streamable HTTP network clients on /mcp.
    • Added PID/status/stop handling to the HTTP server.
    • Added optional full-argument JSONL debug logging via --debug-log or MCP_DEBUG_LOG.
    • Added recursive credential redaction for MCP tool output and debug logs.
    • Added redMCP/bin/generate-bearer-token.php.
    • Both transports expose Redmine project reads, users, project memberships, filtering/search, issue CRUD, Helpdesk-aware reads, and explicit Helpdesk response tools.
    • Registered all MCP helper commands as Composer bin entries.
  • LAN test result:
    • php -l redMCP/app/RedmineClient.php passed.
    • php -l redMCP/bin/redmcp-server.php passed.
    • php -l redMCP/bin/redmcp-http-server.php passed.
    • php -l redMCP/bin/generate-bearer-token.php passed.
    • composer validate --working-dir=redMCP passed; Composer emitted PHP 8.5 deprecation notices from system Composer dependencies.
    • Live stdio MCP framing test passed for initialize, tools/list, and tools/call using redmine_search_issues against fud-helpdesk.
    • Live Streamable HTTP test passed for authenticated initialize, tools/list, and tools/call using redmine_search_issues.
    • redmcp-http-server.php refused to start without MCP_SERVER_TOKEN.
    • Unauthenticated /mcp returned 401; wrong path returned 404.
    • HTTP PID helpers reported stopped/running states, rejected a duplicate start, stopped the live process, detected a stale PID file, and started with --force.
    • Live Streamable HTTP tests passed for redmine_list_users, redmine_get_user, and redmine_list_project_memberships.
    • redmine_get_user redacted the returned Redmine api_key field.
    • redmine_list_project_memberships returned direct and inherited memberships for customer-service; fud-helpdesk returned a valid empty membership list.
    • php redMCP/bin/test-query-normalizer.php passed with coverage for paging, sort shortcuts, status aliases, date presets/ranges, free-text dates, and raw override precedence.
    • Live Streamable HTTP tests passed for friendly redmine_list_issues, redmine_search_issues, redmine_list_users, redmine_list_projects, and redmine_list_project_memberships arguments.
    • Debug logging wrote JSONL records with full project-tool arguments and did not include the bearer token, Authorization, or Redmine API key.
    • Token generation passed default, --bytes 48, and --env-line modes.
    • redmine_list_projects returned three projects from 117 total.
    • redmine_get_project returned fud-helpdesk by identifier and by id 117.
    • The live MCP tool calls returned issue search results from seven total for redMCP-smoke.

2026-04-25 - Test Helpdesk Credential Sanitization

  • Touched areas:
    • Test instance post-import tooling
    • Post-import validation
  • Purpose:
    • Ensure production database imports cannot leave real Helpdesk POP3/SMTP credentials on projects where Helpdesk is disabled but settings rows still exist.
  • Behavior changed:
    • reset_helpdesk_mail_settings.py now rewrites Helpdesk mail settings for every active project, not only projects with contacts_helpdesk enabled.
    • validate_test_instance.py checks every active project for Mailpit Helpdesk settings.
  • LAN test result:
    • ./reset_helpdesk_mail_settings.py --dry-run matched 52 active projects.
    • ./reset_helpdesk_mail_settings.py updated 1,092 setting rows across 52 active projects.
    • ./validate_test_instance.py passed and reported 52 active projects with matching Mailpit Helpdesk settings.

2026-04-25 - Outbox Worker Processing Policy

  • Touched areas:
    • External outbox worker
    • Worker operations documentation
  • Purpose:
    • Make the worker usable for bounded JSONL publishing before a message bus is chosen.
    • Add queue visibility and explicit processed-row cleanup for test-instance maintenance.
  • Behavior changed:
    • Default worker output is /tmp/redmine-outbox/derived_documents.jsonl.
    • --status reports pending, ready, locked, failed, and processed counts.
    • --purge-processed-days N previews processed-row cleanup; --apply-purge is required to delete rows.
    • Normal processing still marks rows processed only after successful output.
  • LAN test result:
    • ./redmine_outbox_worker.py --status reported 100 total rows, 100 ready, 0 locked, 0 failed, and 0 processed before the processing run.
    • ./redmine_outbox_worker.py --dry-run --batch-size 5 previewed the first five rows without marking them processed.
    • ./redmine_outbox_worker.py --batch-size 5 processed five rows and wrote six JSONL documents to /tmp/redmine-outbox/derived_documents.jsonl.
    • Follow-up status reported 95 pending, 95 ready, 0 locked, 0 failed, and 5 processed.
    • ./redmine_outbox_worker.py --purge-processed-days 30 previewed zero rows.
    • Follow-up ./validate_helpdesk_outbox_worker.py passed with controlled Helpdesk issue #39875; final status reported 118 total rows, 113 ready, 0 locked, 0 failed, and 5 processed.

2026-04-25 - Helpdesk Outbox Worker Validation

  • Touched areas:
    • Helpdesk test tooling
    • External outbox worker validation docs
  • Purpose:
    • Make Helpdesk outbox coverage repeatable after database refreshes and worker changes.
    • Validate worker enrichment against a real Mailpit-imported Helpdesk ticket without claiming rows or marking them processed.
  • Behavior checked:
    • Controlled Helpdesk import produces helpdesk_ticket.created, helpdesk_ticket.updated, journal_message.created, journal.created, and issue.updated rows.
    • Worker dry-run enrichment emits event, ticket, and message documents.
    • Derived message documents expose has_bcc_address but do not expose raw bcc_address.
  • LAN test result:
    • ./validate_helpdesk_outbox_worker.py passed against fud-helpdesk and fud-nohelpdesk.
    • Latest documented passing run created and closed controlled Helpdesk issue #39873.
    • Observed outbox rows: 1 helpdesk_ticket.created, 3 helpdesk_ticket.updated, 1 journal_message.created, 3 journal.created, and 2 issue.updated.
    • Worker dry-run enrichment produced 10 event, 6 ticket, and 2 message documents without claiming or marking rows processed.

2026-04-24 - Helpdesk/redMCP Smoke Validation

  • Touched areas:
    • redMCP
    • Helpdesk test tooling
  • Purpose:
    • Prove the LAN test instance can import a Helpdesk email, expose its Helpdesk metadata through redMCP, update a non-Helpdesk control issue, send an explicit Helpdesk reply, and verify outbound delivery through Mailpit.
    • Make customer-visible Helpdesk email opt-in in redMCP.
  • Behavior clarified:
    • RedMCP\RedmineClient::updateIssue() uses the normal Redmine REST API and does not send a Helpdesk email by default.
    • updateIssue(..., ['send_helpdesk_email' => true]) and sendHelpdeskIssueResponse() deliberately use the Helpdesk email path.
  • LAN test result:
    • ./helpdesk_smoke_test.py passed against fud-helpdesk and fud-nohelpdesk.
    • The smoke test verifies that a default issue update does not send Mailpit mail, while an explicit Helpdesk response does.
    • Latest documented passing run created and closed controlled Helpdesk issue #39871.

2026-04-24 - POP3 Get Mail Compatibility Fix

  • Touched plugin:
    • redmine_contacts
    • redmine_contacts_helpdesk
  • Purpose:
    • Fix Helpdesk POP3 retrieval on the LAN test host when Ruby 2.5 raises FrozenError: can't modify frozen String inside Net::POP3.
    • Allow Helpdesk outbound mail to use Mailpit's unauthenticated SMTP listener.
  • Behavior changed:
    • Changed POP3 message retrieval from msg.pop to msg.pop(String.new) so Ruby's POP3 code appends chunks into an explicit mutable destination string.
    • This does not change message handling semantics; it only avoids relying on Ruby's default empty string argument being mutable.
    • Changed Helpdesk SMTP delivery option construction to omit authentication, user_name, and password when the project SMTP authentication setting is blank.
  • LAN test result:
    • Deployed to /usr/share/redmine/plugins/redmine_contacts.
    • HelpdeskMailer.check_project(Project.find("fud-helpdesk").id) completed successfully and processed 1 message.
    • Deployed to /usr/share/redmine/plugins/redmine_contacts_helpdesk.
    • Mailpit rejected AUTH PLAIN with 502 5.5.1 Command not implemented. After blanking SMTP auth settings and omitting auth options, a Helpdesk test mail for issue #39863 was delivered to Mailpit.

2026-04-21 - Helpdesk Search Foundation

  • Archives created before plugin edits:
    • dist/redmine_contacts-4.1.2-local-before-helpdesk-search-20260421T215548Z.tar.gz
    • dist/redmine_contacts_helpdesk-3.0.9-local-before-helpdesk-search-20260421T215548Z.tar.gz
  • Touched plugins:
    • redmine_contacts_helpdesk
    • redmine_event_outbox
  • Purpose:
    • Make helpdesk ticket and message identity available to external search and indexing workers.
    • Avoid relying on Redmine issue author when helpdesk-created tickets use Anonymous.
  • Behavior changed:
    • Added read-only helpdesk_search/* JSON endpoints guarded by the existing view_helpdesk_tickets permission.
    • Added optional outbox hooks for HelpdeskTicket and JournalMessage.
  • Payload/content policy:
    • Include ids, source, direction, message id, and non-body address metadata.
    • Do not copy email bodies, private note text, attachments, or BCC addresses into event rows or the read API.
  • LAN test result:
    • Pending. Validate on the LAN Redmine copy by creating/updating a controlled helpdesk ticket and journal message, checking event_outbox_events, and calling the new helpdesk_search/* endpoints with a user/API key that has view_helpdesk_tickets.