Skip to content

Parallax Bug Reporter

Summary — A drop-in JavaScript widget embedded in the Parallax APEX app: a floating button on every page that captures diagnostics + a screenshot, asks the user for a title/description/type/urgency/impact, writes a BUG_REPORTS row, and POSTs the payload to an n8n webhook that opens a Jira ticket and emails the team. The flow is one-way — once submitted, the reporter never hears back, nothing tracks lifecycle or SLA, and the STATUS column drives nothing. This page is the current-state baseline ahead of a redesign.

Field Value
Component Bug Reporter (widget v1.1.0) — part of Parallax
Parent app 01 Parallax (Oracle APEX, schema UR)
Implementation repo git.projecteidos.com/vishnu/parallax (local /home/coder/parallax/)
Source snapshot apps/data/bug-reporter/ (point-in-time copies)
Status table BUG_REPORTS (+ V_BUG_REPORTS view)
APEX AJAX process AJX_BUG_REPORTER_LOG
Webhook target n8n (legacy O1) → Jira + email — see 25 n8n
Owner Vishnu Kant (vishnukant@projecteidos.com)
Last reviewed 2026-06-02

1. At a glance

The Bug Reporter is a self-contained widget (bug-reporter.js, ~81 KB, served as an APEX static application file) that any APEX page can mount with a single BugReporter.init(...) call. In Parallax it is mounted globally via the APEX Global Page (page 0), so the button appears on every authenticated page.

On submit it does two things: (1) inserts a row into BUG_REPORTS through an APEX AJAX process, and (2) POSTs the full payload (including screenshot and attachments) to an n8n webhook, which is what actually raises the Jira ticket and sends the notification email. After that, communication stops — there is no acknowledgement to the reporter, no status updates, and no link back from Jira to the BUG_REPORTS row. See §8 Gaps.

2. What it captures & asks

Captured automatically (no user effort):

  • Console — a ConsoleInterceptor wraps console.error/console.warn and listens for window error + unhandledrejection, retaining the last 50 entries with stack + timestamp.
  • APEX contextappId, pageId, sessionId, appUser, debugMode, and all page-item values (P*_*). Items whose name matches a sensitive list (password, credit_card, ssn, pin, cvv, secret, token) are stored as [REDACTED].
  • Environment — browser + OS (parsed from UA), screen + viewport size, timezone, language, online flag, full user-agent, URL, referrer.
  • Screenshot — captured with html2canvas (bundled as a local static file, no CDN). Auto-taken for bug reports; the modal hides itself during capture.
  • Reporter identity — name/email/role prefetched from the server (GET_USER_INFO, source APEX workspace users or UR_USERS).

Asked of the user:

  • Type — Bug Report or Feature Request (toggle; feature requests skip the auto-screenshot).
  • Title + Description (both required).
  • Urgencylow | medium | high | critical (relabelled "Priority" for features).
  • Impactsingle_user | team | multiple_teams | organization.
  • Attachments — up to 3 files, 5 MB each (images, PDF, text/log/json).

3. Architecture & components

Four layers cooperate:

  1. Client widgetbug-reporter.js + the html2canvas static file, both hosted as APEX static application files (no external CDN). Renders the floating button (draggable, snaps to nearest edge), the modal form, and the success state.
  2. Global wiring — APEX Global Page (page 0). A Page Load dynamic action ("Initialize Bug Reporter") calls BugReporter.init({ apexProcessName: 'AJX_BUG_REPORTER_LOG' }), colours the button to the theme header, and runs a MutationObserver that hides the button whenever an APEX dialog/modal is open. Gated by the server-side condition :APP_USER != 'nobody' (authenticated users only). Source: apps/data/bug-reporter/p00000-global-page.yaml.
  3. Server (APEX + DB) — the AJAX process AJX_BUG_REPORTER_LOG services four calls from the widget: default (insert a report from x01 JSON), GET_USER_INFO, GET_WEBHOOK_CONFIG, and UPDATE_WEBHOOK. Backed by the BUG_REPORTS table, V_BUG_REPORTS view, and audit trigger (see §4).
  4. Routing (n8n → Jira) — the webhook receiver lives in n8n on legacy O1; it creates the Jira ticket and emails the team. See 25 n8n §7. This hop currently runs through Adam's personal Atlassian API token (KI-044).
sequenceDiagram
    actor U as User (Parallax page)
    participant W as bug-reporter.js
    participant P as AJX_BUG_REPORTER_LOG
    participant DB as BUG_REPORTS
    participant N as n8n webhook
    participant J as Jira + email
    U->>W: Click button, fill form, Submit
    W->>W: Gather diagnostics + screenshot
    W->>P: x01 = report JSON (no screenshot)
    P->>DB: INSERT row (STATUS = NEW)
    W->>P: GET_WEBHOOK_CONFIG (url + key)
    W->>N: POST full payload (incl. screenshot, X_API_KEY)
    N->>J: Create ticket + email team
    W->>P: UPDATE_WEBHOOK (sent flag + response)
    W-->>U: Success toast (auto-close 5s)
    Note over U,J: No path back to the reporter after this point

4. Data model

Defined in installation-script-bug-reporter.sql:

  • BUG_REPORTSID RAW(16) DEFAULT SYS_GUID() PK; TITLE, DESCRIPTION, REPORTER, REPORT_DATA (CLOB, constrained IS JSON — holds the full diagnostics blob), SCREENSHOT_BLOB, ATTACHMENTS_BLOB/_META, webhook tracking (WEBHOOK_SENT, WEBHOOK_RESPONSE, WEBHOOK_SENT_AT), AI_ANALYSIS, and audit columns. Three CHECK domains:
  • URGENCY ∈ {low, medium, high, critical}
  • IMPACT ∈ {single_user, team, multiple_teams, organization}
  • STATUS ∈ {NEW, TRIAGED, IN_PROGRESS, RESOLVED, CLOSED, WONT_FIX} (default NEW)
  • V_BUG_REPORTS — reporting view that shreds REPORT_DATA JSON into columns (APP_ID, PAGE_ID, BROWSER, OS, PAGE_URL, REPORTER_EMAIL) and exposes HAS_SCREENSHOT/HAS_ATTACHMENTS flags.
  • TRG_BUG_REPORTS_AUDIT — sets CREATED_* on insert, UPDATED_* on update, and auto-stamps RESOLVED_AT when STATUS first moves into RESOLVED/CLOSED.
  • Indexes on CREATED_ON, STATUS, REPORTER, URGENCY.

Note — columns present but inert today: STATUS (nothing transitions it from the app), RESOLVED_AT (trigger would fire, but nothing updates status), AI_ANALYSIS, and the WEBHOOK_* set are written but never read back into any workflow.

5. End-to-end lifecycle (today)

  1. User clicks the button → modal opens → diagnostics + screenshot gathered, form validated (title + description required).
  2. submitToApex — POSTs x01 = report JSON to AJX_BUG_REPORTER_LOG, which inserts the BUG_REPORTS row. Screenshot and attachments are stripped from this call (too large for the AJAX f01 path — there is an in-code TODO for chunked upload).
  3. resolveWebhookCredentialsGET_WEBHOOK_CONFIG returns the URL + key from server-side application items.
  4. submitToWebhook — POSTs the full payload (including screenshot + attachments) to n8n with an X_API_KEY header. If a webhook is configured it must succeed, otherwise the whole submit is treated as failed.
  5. updateWebhookStatusUPDATE_WEBHOOK writes the sent flag + response back onto the row.
  6. Success view shows a generated bugId and auto-closes after 5 s.

n8n then creates the Jira ticket and emails the team. Nothing flows back to the reporter or to BUG_REPORTS after step 6.

6. Configuration & secrets

  • Webhook URL / key are never hard-coded in the client. They are resolved server-side from APEX Application Items G_BUG_REPORTER_WEBHOOK_URL and G_BUG_REPORTER_WEBHOOK_KEY (each with a matching application computation), returned via GET_WEBHOOK_CONFIG. The key is sent to n8n as the X_API_KEY header.
  • apexProcessName defaults to AJX_BUG_REPORTER_LOG (set explicitly in the Global Page init).
  • userInfoSource toggles whether reporter identity comes from APEX workspace users or the UR_USERS table.

7. Source artifacts

  • Snapshot (this repo): apps/data/bug-reporter/bug-reporter.js, p00000-global-page.yaml, installation-script-bug-reporter.sql, with a README mapping each back to its authoritative location.
  • Authoritative source (parallax repo): widget at application/shared_components/files/bug_reporter_js.sql (+ _min_js), AJAX process application/shared_components/logic/application_processes/ajx_bug_reporter_log.sql, webhook items/computations under application/shared_components/logic/application_{items,computations}/g_bug_reporter_webhook_{url,key}.sql, install script application/deployment/install/install_installation_script_bug_reporter.sql.
  • Install / how-to: docs/BUG_REPORTER_INSTALLATION_GUIDE.md in the parallax repo (https://git.projecteidos.com/vishnu/parallax/-/blob/main/docs/BUG_REPORTER_INSTALLATION_GUIDE.md).

8. Gaps & limitations (redesign inputs)

These are the current-state problems the redesign should address — captured here, not solved:

  • No reporter feedback loop — the submitter gets a client-side toast and a bugId only; they never learn whether it was triaged, worked, or fixed.
  • No bug lifecycle / events — the STATUS domain exists but nothing transitions it; Jira is the de-facto tracker with no sync back to BUG_REPORTS. The two systems diverge immediately.
  • No SLA — no urgency→response-time mapping, no breach tracking, no escalation path.
  • Webhook depends on a personal token — the n8n→Jira hop runs through Adam's personal Atlassian API token; its expiry silently breaks ticket creation (KI-044, migration tracked under RM-046).
  • One-way comms — the team gets the initial new-bug email; there are no further updates in either direction.
  • Screenshot path gap — screenshots bypass the APEX insert (size limit) and are only delivered if a webhook is configured; a BUG_REPORTS row can therefore have HAS_SCREENSHOT = N even though the user took one. In-code TODO for chunked upload.
  • Latent / unused capabilityAI_ANALYSIS column and the enableAIAnalysis widget option exist but are inert.
  • Single-instance assumptionBugReporter.init warns and no-ops on re-init; the global-page show condition is a hard-coded page-id allowlist string, easy to drift from reality.
  • Parent app: 01 Parallax
  • Routing / Jira hop: 25 n8n (§7 Atlassian-touching workflows)
  • Token risk: KI-044 · migration RM-046
  • Source snapshot: apps/data/bug-reporter/
  • Install guide (parallax repo): https://git.projecteidos.com/vishnu/parallax/-/blob/main/docs/BUG_REPORTER_INSTALLATION_GUIDE.md