Skip to content

Issue Tracker

Overview

Issue Tracker is BigLedger’s own work-tracking applet: projects, issue types, sprints, labelled issues with comments, worklogs, attachments and sub-tasks, a drag-and-drop kanban board and an issues report. It is a TNT-USER applet, so it runs inside a tenant, but it is built for a support desk that tracks issues on behalf of several customer tenants: every issue carries the customer tenant it belongs to, a Tenants switcher at the top of the menu filters the list to one of them, and a platform-level table decides which customer tenants each login may see. An optional two-way sync mirrors issues into GitHub Issues and a GitHub Projects V2 board.

Nothing here posts a journal, moves stock or creates a financial document. Issue Tracker is the back-office face of the same bl_wf_issue_hdr table that the Unified Contact Center’s Issue Tracker panel writes to, and the two applets share the same Application Settings → Issue Category screen.

Measured 2026-09-16: 13 active catalogue links across 7 tenants; 2 logins hold a user-tenant link; no GitHub repository link exists yet.

The registry serves a staging bundle. bl_applet_hdr.property_json.es_module_url for IssueTrackerApplet points at …/issue-tracker-applet/staging/staging/…-elements-staging.js.gz, the path the repository’s staging publish script writes to; the production script publishes to …/issue-tracker-applet/production/. Every production tenant therefore loads whatever was last pushed to staging. Recorded in the registry-hygiene findings (LA4-P-14a).

Where it fits

DirectionWhatWhy
Same tableUnified Contact Center — Issue Tracker panelAn agent raising an issue from a conversation writes the same bl_wf_issue_hdr row; the eleven category-group slots are configured once and read by both applets.
Platform dataPlatform SysAdmin / Tenants V2The Tenants switcher lists rows from app_tenant_hdr; the user-tenant and repository-tenant links live in akaun_master.
SchedulingSchedulerThe GitHub reconciliation job is a bl_sch_crontab_hdr row in the tenant with queue code GITHUB_TO_ISSUE_HDR_SYNC_CRON_PROCESSOR.
ExternalGitHub Issues and Projects V2Outbound push from a dedicated queue table; inbound by signed webhook plus the reconciliation job.

Screens and menus

The application title bar reads Issue Tracker Applet; the registry name is Issue Tracker. app.routing.ts L45 sets the main path to applets/akaun/issue-tracker-applet, matching the registry routerLink. On open the applet redirects to Issues (L262–L266).

Start-up gate. Before any screen is useful the applet loads the login’s user-tenant links from akaun_master (tenant.effects.ts L140–L172). A login with no ACTIVE link gets a dialog that cannot be closed — “You do not have permission to access any tenants. Please contact your administrator.” — and re-opens itself if dismissed (app.component.ts L104–L121). With exactly one link the tenant is auto-selected; with several, the is_default row wins, then the most recent last_access_date, else a tenant-selection dialog (tenant.effects.ts L177–L219). Selecting a tenant writes last_access_date on the link row (L72–L107).

Main menu (menu-items.ts)

Menu itemRouteWhat it shows
Tenants— (drop-down with a search box)The customer tenants this login is linked to, from app_tenant_hdr filtered by the link table. Selecting one filters the Issues list to that tenant and stamps new issues with it.
Dashboard → Main-Dashboarddashboard/main-dashboardKPI strip (Total / To Do / In Progress / Pending / Done), filters (date from/to, assignee — default current user, sprint, status), three tabs: Board (kanban, cdkDropList columns), Worklogs, Analytics. New Issue opens the quick-create dialog and is disabled with the tooltip Please select a tenant first until a tenant is selected.
Dashboard → Issues Reportdashboard/dashboard-issues-reportA tree grid of issues with their worklogs as child rows; filters date from/to (both required before Reload enables), assignee, status, sprint; New Issue and Sync selected to GitHub. Columns: Issue Title, Issue Status, Assignee, Project, Sprint, Issue Key, Reporter, Issue Type, Create Date, Update Date, plus one column per issue category group.
ProjectsprojectsProject listing, create and edit (tabs Details, People, Issue Types, Notifications). The create page’s title reads Add Project 2.
IssuesissuesServer-side issue listing with Sync selected to GitHub; Add and row-click both open the issue detail page.
Categoriescategory-listingIssue categories (bl_wf_issue_label_hdr), with a tree parent picker.
Category Groupsgroup-category-listingCategory groups (bl_wf_issue_label_list_hdr, namespace WF_CATEGORY), with a Categories tab listing the group’s children.

Issue detail page

issues/:tenantCode/:issueGuid (app.routing.ts L73–L85) is the only issue create/edit screen. :issueGuid = new is create mode. The older Issue Create and Issue Edit view columns were removed from the page stack (issue-pages.service.ts L50–L52) and are unreachable; the quick-create dialog survives on the two dashboards.

The page is GitHub-shaped: click-to-edit title, a rich-text description, attachments in the main pane, a Details card in the sidebar (Assignee, Reporter, GitHub Repository, Project, Sprint, Label 1–3), a More Details block of custom fields, and three tabs — Comments, History (bl_wf_issue_event rows) and Worklogs (description, hours 0–24 in 0.5 steps, date). Buttons: New Issue, Sync with GitHub, Create Issue / Cancel in create mode, Save Changes / Cancel when the sidebar has unsaved edits.

Status is shown only as a read-only badge (issue-detail.component.html L66–L68); there is no control on this page for status, priority or issue type — the handlers exist (issue-detail.component.ts L1214, L1240, L1671) but nothing in the template calls them. Status changes are made by dragging a card between kanban columns; issue type is set only by the quick-create dialog.

Settings (gear)

The vendored shared settings navigation (shared-utilities/modules/settings/settings.component.html) hard-codes an Issue Tracker Settings group — Projects, Issue Types, Project Categories, Users, Teams, Sprint, User Tenant, Tenant Repository Link, Custom Fields Placement, Kanban Board — above the System Configuration group from settingItems (Application Settings, Field Settings, Default Selection), the shared Applet Access, the four server-side permission listings, Triggers (webhooks), and two Developer Tools links (Applet Log, Reset Applet State) that route to 404.

The Kanban Board link is behind *ngIf="isKanbanBoardAdmin". settings-container.component.ts L49 sets that flag with (result?.totalRecords || 0) >= 0, which is always true, so the link shows to everyone; the dashboard’s own copy of the same check (main-dashboard.effects.ts L162) uses > 0 and is the one that actually gates board administration.

The Projects screen under Settings is a second copy of the Projects screen: its edit page has only Details and Notifications (People and Issue Types are commented out, the Delete button too), and its create page drops the Project Key on save. Use the main-menu Projects screen.

Personalization

Field Settings (routes to the same unbound stub as Settings), Default Selection, Sidebar; the Preset Themes, Color Assist and Easy Navigation links route to 404. Profiles → My Profile is routed but linked from nowhere (its menu entry is commented out); it shows a read-only About Me tab. A Plans component tree exists in the repository with no route, no module import and empty templates.

Configuration

Before you can use it

PrerequisiteWhereWithout it
An ACTIVE row in bl_module_wf_issue_user_tenant_link (akaun_master) for the login and each customer tenant it may seeSettings → User Tenant in this applet (platform endpoint core2/platform/dm/wf/issue-user-tenant-links/backoffice-ep)The non-closeable no tenants dialog at start-up; the issue query also returns empty (WFIssueHdrController.java L243–L250).
MST_API_TNT_MGT_TENANT_READ on the tenant rows the login is linked toPlatform permission tablesGET core2/platform/dm/tenants/query replaces each row the caller may not read with a stub carrying only the guid and status PERMISSION_DENIED (TenantController.java L85–L93, L402–L424), so the Tenants switcher has entries with no code or name and the selected tenant code is blank.
Server-side WF permissions for the login’s roleSettings → Server Side PermissionsEvery endpoint in the table under Feature visibility / permissions returns not authorised.
At least one Project (with a Key) and one Issue TypeProjects; Settings → Issue TypesThe quick-create dialog requires both; the detail page requires a project. The issue number is a per-project sequence, so a project with no key shares one counter bucket (WFIssueHdrUow.java L48–L57).
Issue category groups in namespace WF_CATEGORYCategory GroupsApplication Settings → Issue Category has nothing to select; the Issues Report has no category columns.
For GitHub sync: app_cfg_main rows GITHUB_LOGIN_CREDENTIAL (property_json.access_token, github_project_name) and GITHUB_PROJECT_CONFIG in akaun_master; one bl_module_wf_issue_github_repo_tenant_link row per repository with a webhook_secret and a wf_project_guid; a GitHub webhook pointed at core2/tnt/dm/wf/issues/github-webhook; a bl_sch_crontab_hdr row for GITHUB_TO_ISSUE_HDR_SYNC_CRON_PROCESSORSQL for app_cfg_main (no screen; GitHubConfig.java L47–L53), Settings → Tenant Repository Link, GitHub repository settings, the SchedulerOutbound sync fails with GitHub token is not configured in app_cfg_main; inbound deliveries are answered IGNORED for an unmapped repository and 401 for a missing secret; missed webhooks are never caught up.
For issue e-mail: a bl_wf_project_notification_subscription_config row per project and event (ISSUE_CREATED, ISSUE_UPDATED, ISSUE_DELETED) pointing at a UCC e-mail endpointProjects → edit → NotificationsNo e-mail is queued (WFIssueService.java L207–L226).

Note that the GitHub token is platform-global: one GITHUB_LOGIN_CREDENTIAL row in akaun_master serves every tenant (GitHubConfig.java L47–L50).

Applet settings

Settings live in three applet-local screens; none uses the shared FieldConfigurationComponent from blg-shared-utilities (this repository vendors its own copy of shared-utilities under micro-fe/projects/shared-utilities and has no .gitmodules). Anyone who can open Settings can change them; there is no per-setting authority.

Settings → Application Settings (application-settings.component.ts, saved with saveMasterSettingsInit, tenant-wide):

SettingWhat it controlsDefaultEffect when changed
Issue Category → Category Group 0…10, each with a Mandatory checkbox (ISSUE_CATEGORY_CATEGORY_GROUP_SETTINGS_LIST)Which category groups appear as pick-lists on an issue and which must be filledEleven empty slots (L57–L63)Read by the issue category tab (issue-edit-category.component.ts L100–L101, required at the template’s L8) and by the Issues Report, which adds one column per selected group (dashboard-issue-report.component.ts L182–L196). The same list drives the UCC applet’s Issue Tracker panel.

Two more keys sit in the same form and are written on every SAVE but have no control and no consumer: ISSUE_CODE_FORMAT (initial value <running_no>) and RUNNING_NUMBER_GENERATION_METHOD (initial RANDOM_NUMBER_GENERATOR) — application-settings.component.ts L45–L46; the template renders only the category slots, nothing in the applet reads either key, and the backend numbers issues from a database sequence with no format option (see Lifecycle). Do not plan an issue-code scheme around them.

Settings → Default Selection (default-settings.component.ts, saved with saveMasterSettingsInit):

SettingWhat it controlsDefaultEffect when changed
Default Kanban Board (DEFAULT_KANBAN_BOARD)Which board (bl_wf_issue_dashboard) the Main Dashboard loads its column order from-- None -- (null)The dashboard waits for a non-empty value before loading board links (dashboard-container.component.ts L246–L259); with none set, cards fall back to unsorted columns and same-column drag has no board to record the order against.

Default Branch and Default Location on the same screen are saved (DEFAULT_BRANCH, DEFAULT_LOCATION) but read by nothing in this applet — they are the document-applet template.

Settings → Field Settings renders eight mat-slide-toggles (Unit Discount, SST/VAT/GST, WHT, Blanket Order, Segment, G/L Dimension, Profit Center, Project) with no form binding and a SAVE button with no handler (field-configuration.component.html). Nothing is persisted.

Personalization → Default Selection is routed directly while written as a child component: @Input() appletSettings$ is never bound, the subscription that would populate it is commented out (personal-default-settings.component.ts L31–L39), and the first change to either drop-down throws on this.appletContainer.bl_applet_exts (L41). SAVE emits to no listener. Nothing is persisted.

Settings in other applets that control this applet

SettingWhere it is setEffect here
GITHUB_LOGIN_CREDENTIAL, GITHUB_PROJECT_CONFIG (app_cfg_main, akaun_master)SQL; POST …/issues/sync-github/sync-config/backoffice-ep refreshes the project schemaToken, target project and the Projects V2 field map for every tenant.
bl_sch_crontab_hdr.event_properties for the reconciliation job (limit, maxIssues ≤ 1000, defaultLookbackHours 24, overlapMinutes 5, migrationTenants, migrateAllLinkTenants)SchedulerHow far back the catch-up reads and which repository links it processes (GithubToIssueHdrSyncCronProperties.java L52–L56).
Project notification configsProjects → NotificationsWho receives the issue e-mails.

Feature visibility / permissions

bl_applet_client_side_perm_dfn holds no rows for IssueTrackerApplet (2026-09-16), so Applet Access has nothing to grant and no screen can be hidden per role.

Server-side permissions are checked per endpoint in the backend with the pattern OWNER or ADMIN, else the verb. The families the applet’s screens hit:

ScreenPermission family (verbs OWNER, ADMIN, MEMBER, CREATE, UPDATE, DELETE, READ unless noted)Where enforced
Issues, sprints, GitHub syncTNT_API_DM_WF_ISSUE_* — sprints reuse the issue family; the sync endpoint needs UPDATE, the config refresh ADMINWFIssueHdrController.java L56–L184, WFIssueSprintHdrController.java L46–L118, WFIssueSyncGithubController.java L71–L141
Comments, worklogs, attachments, linked issues, issue-user linksTNT_API_DM_WF_ISSUE_COMMENT_*, …_ISSUE_WORKLOG_*, …_ATTACHMENT_*, …_ISSUE_TO_ISSUE_LINK_*, …_ISSUE_USER_LINK_*the matching controllers under controller/tenant/dm/wf/issue/
Kanban boards and card orderTNT_API_DM_WF_ISSUE_DASHBOARD_*, …_ISSUE_DASHBOARD_LINK_* (no MEMBER)WFIssueDashboardController.java L44–L60, WFIssueDashboardLinkController.java L45–L115
Dashboard reportsTNT_API_WF_DASHBOARD_ISSUE_PER_{PROJECT,ASSIGNEE,STATUS}_{OWNER,ADMIN,READ}DashboardController.java L42–L102
Projects, project categories, issue typesTNT_API_DM_WF_PROJECTS_*, …_PROJECT_CATEGORIES_*, …_ISSUE_TYPE_*ProjectController.java L83–L172 and siblings
Categories, category groupsTNT_API_WF_ISSUE_LABEL_*, TNT_API_DM_WF_ISSUE_LABEL_LIST_*IssueLabelController.java L134–L182, IssueLabelListController.java L119–L223
User Tenant linksBL_MODULE_WF_ISSUE_USER_TENANT_LINK_* (platform endpoint)WFIssueUserTenantLinkController.java L47–L123
Tenant Repository linksMST_API_DM_APP_GITHUB_ISSUE_REPO_TENANT_LINK_* (akaun_master permission)WFIssueGithubRepoTenantLinkController.java L68–L69

Four naming prefixes coexist (TNT_API_DM_WF_, TNT_API_WF_, BL_MODULE_WF_, MST_API_DM_APP_); a permission set built from the first prefix alone leaves the reports, categories and both link screens unauthorised.

Fields

Issue (detail page, create mode)

FieldMeaningRequiredNotes / validation
TitletitleYes — toast Title is required to create an issue (issue-detail.component.ts L1432–L1435)Plain input; no length limit in the UI.
DescriptiondescriptionNoTextarea on create, rich-text editor on edit.
Assigneemain_assigneeNoUser pick-list (bl_wf_user_hdr).
Reportermain_reporterRead-only; the current login (L1480).
GitHub Repositorygithub_repo_full_name, and rewrites guid_tenant / tenant_code to the repository’s tenant (L1391–L1399)NoBuilt from the repository-tenant links of the tenants this login may see; auto-selects the first when the issue has none (L1359–L1385).
Projectwf_project_guidYes — toast Project is required to create an issue (L1449–L1451)No Not Selected option.
Sprintsprint_hdr_guidNo
Label 1–3label_hdr_0_guidlabel_hdr_2_guidNoThe header has eleven label slots; the page exposes three.
Custom fieldscustom_field_jsonPer placement — <field> is requiredOne control per ACTIVE, visible placement for bl_wf_issue_hdr, in display_order; renderers for text, textarea, dropdown, date and numeric. On Save Changes the JSON is rebuilt from the placements, so keys with no placement are dropped (L1531–L1545).
Status, Priority, Issue typeissue_status, priority, issue_type_guidNot editable here. Create sends status: 'ACTIVE' and priority: 'medium' (L1474–L1493) and no issue type.

Issue (quick-create dialog, dashboards)

FieldRequiredNotes
TitleYes
DescriptionNo
AttachmentsNoUp to 20 MB each; larger files are skipped with a toast.
Issue TypeYes
ProjectYes
PriorityNoDefault MAJOR
StatusNoDefault TO DO
Sprint, AssigneeNo
TenantSeparate selector; sets github_repo_full_name from the tenant’s repository link.

The dialog and the detail page default priority differently (MAJOR vs medium) and neither value is validated by the backend — priority and issue_status are free text on bl_wf_issue_hdr (L44, L63).

Project (main-menu Projects)

FieldRequiredNotes
Project NameYes, ≤255
Project CodeYes, ≤255Read-only after save.
Project KeyNoThe prefix bucket for the issue sequence; only the main-menu copy saves it.
Project TypeNoPublic / Private
Project CategoryYes (create)
LeadYes (create)
Default AssigneeNo
DescriptionNo

Sub-tabs: People (e-mail, verified against existing logins, rank default MEMBER), Issue Types (multi-select), Notifications (event name, single user, current assignee / reporter / user / project lead checkboxes, single e-mail address, team).

Sprint, Issue Type, Project Category, Kanban Board

ScreenFieldsRequiredImmutable after save
SprintName, Code, Period, Start Date, End DateName (≤255), Code (≤100 on edit)
Issue TypeName, Code, DescriptionName (≤255), CodeCode
Project CategoryName, Code, DescriptionName (≤255), CodeCode
Kanban BoardCode, Name, DescriptionCode, Name (≤255)Code; Description is collected and never saved (kanban-board-create.component.ts onSubmit)

Issue Type and Project Category creates check for a duplicate code client-side (Issue type code already exists!).

Custom Fields Placement

FieldRequiredDefaultNotes
Custom FieldYesFrom bl_tnt_custom_field_definition
Target TableYesbl_wf_issue_hdrThe only option
Display OrderYes0
StatusYesACTIVE
Visible / Required / Read Only / Searchable / List ColumnNoVisible on; others offRequired is what makes the field mandatory on the issue page. Booleans are stored as the strings true / false.

User Tenant link, Tenant Repository link

ScreenFieldsRequiredNotes
User TenantEmail Address (with Verify and Send Invite), Tenant, Tenant Code (derived), Is Default; Status on editEmail, TenantThe login subject is resolved from the verified e-mail; SAVE stays disabled until verification succeeds (user-tenant-link-create.component.ts L189–L203).
Tenant Repository LinkTenant, Tenant Code (derived), GitHub Repository (owner/repository), GitHub Project (owner/projectNumber), Webhook Secret (masked; blank on edit keeps the stored value), Sync Bot Login, Create missing issues (on), Import attachments (off), Sync project fields (off), StatusTenant, GitHub Repository, StatusTwo client-side rules re-checked against the server before save: a tenant cannot link the same repository twice, and a repository can belong to only one tenant (github-repo-tenant-link-validation.services.ts L18–L79; case-insensitive).

Users, Teams, Category Groups

ScreenFieldsRequiredImmutable after save
UserUsername, Name, User Type, GitHub Username, Email Address (verify / invite), Description; Status on editUsername, Name (≤255), EmailUsername
TeamDetail: Team Name, Team Code, Website, Description; Address: Address 1–2, Postal Code (5 chars), City, State, Country; Users tab on edit (users multi-select, rank default MEMBER)Name (≤255), CodeTeam Code
Category GroupCode, Name, Type, Param Code, Param Name, StatusCode, Name, Param Code, Param NameCode
CategoryCategory Group, Category Code, Category Name, Description, Parent (tree)Code, Name

bl_wf_user_hdr.github_username is what the inbound sync matches a GitHub assignee against.

Lifecycle and effects

Issue Tracker writes only workflow tables — bl_wf_issue_hdr, bl_wf_issue_comment_hdr, bl_wf_attachment_hdr, bl_wf_issue_worklog, bl_wf_issue_event, bl_wf_issue_dashboard(_link), bl_wf_issue_sprint_hdr, bl_wf_project_hdr and their links — plus two akaun_master link tables. No *DataConsistencyObject signum, no JournalPostingTypeHandler entry, no stock processor; grep of the wf packages for journal, generic-document and stock services finds only unused imports.

Statuses

bl_wf_issue_hdr carries two independent status columns. status is the platform row status (ACTIVE / INACTIVE / DELETED); issue_status is the workflow status shown on the board and is free text with no enum, no default and no backend transition rule — the quick-create dialog seeds TO DO, the detail page seeds nothing, and a kanban drop writes whatever the target column is named (dashboard-container.component.ts, onKanbanDrop). The inbound GitHub sync maps GitHub closed to status = INACTIVE and open to ACTIVE, never DELETED (WFIssueInboundGithubService.java L486–L490).

Create and update

The detail page posts to core2/tnt/dm/wf/issue-hdrs/backoffice-ep (wf-issue-hdr.service.ts L12; WFIssueHdrController.java L67–L92). That controller checks TNT_API_DM_WF_ISSUE_CREATE and calls WFIssueHdrUow.create directly — it does not run WfIssueDataConsistencyObject (L78). The title, project and issue-type rules in that validator apply only to the older core2/tnt/dm/wf/issues endpoints used by the quick-create dialog and by UCC (WFIssueService.java L47, L89). On the detail page the only guards are the client-side toasts.

The issue number comes from AppSequenceCounterUow.incrementAndGet("bl_wf_issue_hdr", "ISSUE_TRACKER", [project key]) and is written to both issue_key and issue_number (WFIssueHdrUow.java L46–L59). Only the first container of a batch is numbered. There is no configurable prefix or format in the backend; the PROJ-n style shown in the UI is the project key concatenated client-side.

After a successful create or update the controller writes a bl_wf_issue_event row (ISSUE_CREATED / ISSUE_UPDATED; L80–L86, L131) and, when the issue has a github_repo_full_name, enqueues it on bl_wf_issue_sync_to_github_queue (L90, L135; WFIssueGithubSyncQueueService.java L52–L107 — never throws, so a slow GitHub cannot fail a save). Delete writes no event row (ISSUE_DELETED exists in WFIssueEventConstants but is never persisted), and event writes are wrapped in a swallowed try (WFIssueService.java L61–L63), so History is best-effort.

E-mail: an ISSUE_EMAIL_NOTIFICATION job is queued only when the project has a notification config row for the event; recipients are the union of assignee, reporter, creator, the configured single user and the last updater (IssueEmailNotificationProcessor.java L94–L121). The config’s property_json keys single_email_address, single_user, current_assignee, current_reporter, current_user are cast directly — a missing key throws.

Tenant scoping — what the Tenants switcher does and does not do

All issues live in the login tenant’s database; the API visa is built from sessionStorage.tenantCode (shared-utilities/visa.ts L6) and never changes when a tenant is selected. Selecting a customer tenant only adds tenant_guids = <guid> to the issue query, which the backend turns into guid_tenant IN (:tenant_guids) (WFIssueHdrUow.java L220). On GET …/issue-hdrs/backoffice-ep/query the backend fills that filter from the login’s user-tenant links only when the caller sent none (WFIssueHdrController.java L252–L254); a caller who supplies tenant_guids explicitly is not intersected with the link table, and the sibling GET /backoffice-ep, GET /backoffice-ep/{guid} and GET /backoffice-ep/query/count apply no tenant filter at all (L180–L223, L275–L290). Treat the user-tenant link as a UI convenience — which tenants appear in the picker — not as a security boundary between the customer tenants tracked in one database.

GitHub sync

DirectionTriggerWhat it doesWhere
OutboundEvery create/update of an issue with a repository, and Sync selected to GitHub on the Issues list and Issues Report (POST …/issues/sync-github/backoffice-ep)Creates or updates the GitHub issue (title, body, labels by bl_wf_issue_label_hdr.code, assignees by github_username, open/closed from status), uploads attachments, sets Projects V2 fields (priority, dates, sprint by date overlap then by exact iteration title, custom fields from GITHUB_PROJECT_CONFIG). A pending event for the same issue is not queued twice.IssueHdrToGithubSyncProcesor.java (queue ISSUE_HDR_TO_GITHUB_SYNC, its own table), WFIssueSyncGithubService.java
Inbound, real timeGitHub webhook issues and issue_comment events to POST core2/tnt/dm/wf/issues/github-webhookVerifies X-Hub-Signature-256 with the repository link’s webhook_secret (fails closed on a blank secret), drops events sent by sync_bot_login, answers 202 ACCEPTED and applies the change on a background thread after re-fetching the issue from GitHub so a delayed delivery cannot overwrite newer edits. Rows it creates are attributed to the anonymous login subject.WFIssueGithubWebhookController.java L124–L225, GitHubWebhookSignature.java L44–L74
Inbound, catch-upbl_sch_crontab_hdr job GITHUB_TO_ISSUE_HDR_SYNC_CRON_PROCESSOR, or POST …/issues/sync-github/reconcile-github/backoffice-epRe-reads everything GitHub updated since the link’s last_sync_time minus overlapMinutes (first run: defaultLookbackHours), applies it idempotently via github_last_inbound_hash, then advances last_sync_time to the run start. A repository whose link row is unusable is skipped and logged, not failed.GithubToIssueHdrSyncCronProcessor.java L176–L262

Loop safety: inbound writes go through WFIssueInboundGithubService, never through the controller, so they do not enqueue an outbound push (IssueHdrToGithubSyncProcesor.java L46–L50).

The webhook worker is an in-process bounded pool (2–4 threads, queue 500); a restart discards what is queued and the reconciliation job is the recovery (WFIssueGithubWebhookController.java L60–L72, L107–L114).

What VOID / delete reverses

There is no VOID. Delete on an issue, sprint, board or link sets the row’s status to DELETED through the ordinary delete endpoint; nothing downstream is reversed because nothing downstream is posted. Deleting a GitHub-linked issue locally does not close it in GitHub (delete does not enqueue an outbound event).

Related applets

  • Unified Contact Center — its Issue Tracker panel writes to the same issue table through the …/issues/ucc/backoffice-ep endpoints and reads the same eleven category-group slots.
  • Platform SysAdmin and Tenants V2 — the tenant rows the Tenants switcher lists and the platform permission that lets a login read them.
  • Scheduler — hosts the GitHub reconciliation job.

Troubleshooting

SymptomCauseFix
A non-closeable dialog You do not have permission to access any tenants on every openThe login has no ACTIVE bl_module_wf_issue_user_tenant_link row (app.component.ts L80–L83). Measured 2026-09-16, two logins on the platform have one.An administrator adds the login under Settings → User Tenant (verify the e-mail, pick the tenant, tick Is Default for the usual one).
The Tenants drop-down shows entries with no name, or Switched to tenant: undefinedGET core2/platform/dm/tenants/query returns a PERMISSION_DENIED stub for tenants the login cannot read (TenantController.java L85–L93, L402–L424).Grant MST_API_TNT_MGT_TENANT_READ on those tenant rows in the platform permission tables.
The Issues list is empty although issues existThe login’s user-tenant links point at other tenants; the query is filtered to the linked guid_tenant values (WFIssueHdrController.java L243–L254). Or the issues were created with a different GitHub Repository selection, which rewrites guid_tenant.Link the login to the right tenant; check the repository selection on the affected issues.
Sync with GitHub on the issue detail page always failsThe button posts to …/issues/sync-github/two-way/backoffice-ep (wf-issue-sync-github-backoffice-ep.service.ts L94, L139–L151), and the backend at d332871 maps only /backoffice-ep, /sync-config/backoffice-ep and /reconcile-github/backoffice-ep (WFIssueSyncGithubController.java L82, L135, L195).Use Sync selected to GitHub on the Issues list or the Issues Report, which post to the existing /backoffice-ep. Recorded as a product defect.
Outbound sync rows fail with GitHub token is not configured in app_cfg_mainNo GITHUB_LOGIN_CREDENTIAL row, or its property_json.access_token is blank (GitHubConfig.java L64–L84).Insert the row in akaun_master with a token carrying repo, read:org, read:project; then call the sync-config endpoint.
Sync-config returns Could not find GitHub project for ‘Token lacks read:org / read:project, or github_project_name is not owner/number (GitHubConfigSyncService.java L44–L49).Fix the token scopes or the value.
GitHub shows the webhook delivery as 401The repository link’s webhook_secret is blank or differs from the one configured in GitHub; a blank secret rejects everything (GitHubWebhookSignature.java L47–L51).Set the same secret on both sides; on the edit screen a blank field keeps the stored secret, so re-enter it to change it.
GitHub shows 200 IGNOREDRepository … is not mapped to a tenantNo ACTIVE link row for that owner/repo (WFIssueGithubWebhookController.java L161–L162).Create the link under Settings → Tenant Repository Link.
Inbound issues are skipped, reconciliation reports SKIPPEDThe link row has no wf_project_guid — the sequence needs a project — or create_missing_issues is off.Set the project on the link row.
Changes made in GitHub while the service was down never arriveWebhooks are not retried indefinitely and the in-process queue is lost on restart.Schedule the reconciliation job every 10–15 minutes with a lookback larger than the interval (ucc#401).
A GitHub assignee shows as the anonymous userNo bl_wf_user_hdr row has that github_username (WFIssueInboundGithubService.java L497–L508).Set GitHub Username on the user under Settings → Users.
Issue e-mails never go outNo notification config row for the project and event, or a config whose property_json lacks one of the five keys (IssueEmailNotificationProcessor.java L94–L100).Create the row under Projects → Notifications with the checkboxes set.
Application Settings SAVE appears to save an issue code formatISSUE_CODE_FORMAT and RUNNING_NUMBER_GENERATION_METHOD are persisted but read by nothing.Nothing to fix; issue numbers are a per-project sequence.
Field Settings toggles or Personalization defaults do not persistUnbound stub / unbound routed component (see Configuration).Nothing to fix in the applet; recorded as product findings.

Related documentation

Last updated on