Bug Report Plugin
The Bug Report plugin provides a user-facing form for submitting bug reports and feedback. Submissions are forwarded to a backend issue tracker (Redmine) and stored locally in a SQLite database for admin review.
Overview
The Bug Report plugin:
- Provides a UI widget ("Report a Problem") in the header menu
- Accepts bug reports and feedback submissions from users
- Forwards submissions to a configured backend (Redmine) as new issues
- Stores a local record of every submission for admin review
- Provides an admin panel card to view recent submissions
Configuration
Redmine Backend
plugins:
- module: codumentor.plugins.bug_report
class: BugReportPlugin
priority: 90
args:
backend:
type: redmine
url: "https://redmine.example.com"
api_key: "${REDMINE_API_KEY}"
project_id: "codumentor"
tracker_id: 1
status_id: 1
parent_issue_id: 37210
custom_fields:
- id: 33
source: user.display_name
- name: "Reporter Email"
source: user.email
- id: 40
value: "Codumentor"
Configuration Parameters
Backend (required)
| Parameter | Type | Description |
|---|---|---|
type | str | Backend type. Currently only "redmine" is supported. |
url | str | Base URL of the Redmine instance (e.g. https://redmine.example.com). |
api_key | str | Redmine API key for authentication. Supports ${ENV_VAR} expansion. |
project_id | str | Redmine project identifier where issues are created. |
Issue Fields
| Parameter | Type | Description |
|---|---|---|
tracker_id | int | Redmine tracker ID for the created issue. Used for both bug and feedback submissions. Default: 1. |
status_id | int | Redmine issue status ID on creation. Optional — omitted if not set. |
parent_issue_id | int | Redmine parent issue ID to create a subtask relationship. Optional — omitted if not set. |
Custom Fields
| Parameter | Type | Description |
|---|---|---|
custom_fields | list | List of custom field entries to include with every submission. |
Each entry has two parts:
- An identifier that tells Redmine which field to set — either
id(integer) orname(string). Passed through to the Redmine API unchanged. - A value, given as exactly one of:
value— a constant, sent verbatim.source— a dotted path into the injection context; the resolved value is sent. If the path is absent, the field is omitted from the submission.
custom_fields:
- id: 33
source: user.display_name # injected from context
- name: "Reporter Email" # identified by name instead of id
source: user.email
- id: 40
value: "Codumentor" # constant
##### Injection context
source: paths resolve against a stable, documented object built at submission time. Available keys:
| Path | Description |
|---|---|
user.id | Authenticated user ID, or "anonymous". |
user.display_name | Authenticated user's display name (empty for anonymous users). |
user.email | Reporter's email address (from the form). |
report.type | "bug" or "feedback". |
report.summary | The user-provided summary. |
conversation.id | Conversation ID, if provided. |
This context object and the field-resolution logic are backend-agnostic (backends/base.py), so future backends can reuse the same value/source mechanism.
API Reference
Submit a Report
POST /api/plugins/bug_report/submit
Creates a new bug report or feedback submission, forwards it to the configured backend, and stores a local record.
Request body:
| Field | Type | Required | Description |
|---|---|---|---|
report_type | str | Yes | "bug" or "feedback" |
summary | str | Yes | Short title (1–200 characters) |
details | str | No | Detailed description (up to 5000 characters) |
email | str | Yes | Reporter's email address |
include_conversation | bool | No | Include conversation context (default: true) |
conversation_id | str | No | Conversation ID to include |
include_environment | bool | No | Include environment info (default: true) |
environment | object | No | Custom environment key-value pairs |
attachment_filename | str | No | Name of attached file |
attachment_content | str | No | Base64-encoded attachment content |
Response:
| Field | Type | Description |
|---|---|---|
id | str | Backend issue ID (e.g. Redmine issue number) |
url | str | URL to view the issue in the backend |
error | str | Error message if submission failed |
Admin: Recent Reports
GET /api/plugins/bug_report/admin/recent
Returns the 5 most recent bug report submissions. Requires admin:* permission.
Admin: Test Connection
POST /api/plugins/bug_report/admin/test
Tests connectivity to the configured backend. Requires admin:* permission.
Response:
| Field | Type | Description |
|---|---|---|
ok | bool | Whether the connection succeeded |
message | str | Human-readable status message |
How It Works
Submission Flow
- User fills out the bug report form in the UI and submits
- The route handler extracts the authenticated user's display name and builds diagnostic info from conversation context and environment
- The payload is forwarded to the Redmine backend, which creates a new issue via the Redmine REST API
- The backend returns the new issue ID and URL
- A local record is stored in the SQLite database (
data/bug_reports.sqlite3)
Issue Creation in Redmine
The backend constructs a Redmine issue with the following fields:
project_id— from configtracker_id— from configsubject— the user-provided summarydescription— combined details and diagnostic infostatus_id— from config (if set)parent_issue_id— from config (if set)custom_fields— resolved from the configuredcustom_fieldslist (see below)
Custom Field Resolution
Each configured custom field is resolved at submission time by resolve_field in backends/base.py:
- The identifier keys (
idand/orname) are passed through to Redmine unchanged. - A
valueconstant is sent verbatim. - A
sourcepath is looked up in the injection context. If the path resolves to a value, it is sent; if the path is absent, the field is omitted from the submission.
Example config entry:
custom_fields:
- id: 33
source: user.display_name
If the authenticated user's display name is "Katalin Schaffer", the submitted custom field will be:
{"id": 33, "value": "Katalin Schaffer"}
Local Storage
Submissions are stored in a SQLite database at data/bug_reports.sqlite3 (configurable via CODUMENTOR_DATA_DIR environment variable). The schema includes:
id— unique local identifier (br_<hex>)created_at— UTC timestampuser_id— authenticated user ID or"anonymous"user_email— reporter's emailreport_type—"bug"or"feedback"summary— short titlebackend_id— backend issue ID (e.g. Redmine issue number)backend_url— URL to the backend issuestatus— submission status ("submitted")
UI Integration
The plugin registers two UI widgets:
- Report a Problem — header menu item (
x-bug-report-menu-item) - Bug Reports — admin panel card (
x-bug-report-admin-card), visible to users withadmin:*permission