Enterprise Plugin Security
Security specification of the Enterprise Plugin: what permissions the process needs, what firewall rules apply and what data it actually exchanges with Q247. A short version of this split is also on the Connectors page; this is the full, technical specification.
Process permissions
The plugin runs in a local directory and does not require administrator privileges. While working, it creates temporary subdirectories in the current directory, into which it fetches the code history and increments; once the effort and calorie analysis is finished, they are deleted automatically.
It also runs a local database, in which it stores configuration, connection parameters and the repository information needed for communication.
The plugin has no access to any directory outside its own home directory.
Firewall rules
Outbound traffic
| Source | Source port | Destination | Destination port | Purpose |
|---|---|---|---|---|
| plugin host | any | address of the Client's Git repository | 443 | The plugin connects over HTTPS to fetch data from the Git repository. |
| plugin host | any | Q247 backend | 443 | The plugin sends increment "fingerprints" over HTTPS to the central panel and fetches connector configuration and the list of repositories to scan. Destination addresses are provided by the Q247 deployment team. |
| plugin host | any | the Client's Jira or Confluence instance | 443 | The plugin reads tickets, statuses and pages when the Jira and Confluence integrations are enabled. |
Inbound traffic
By default, all inbound traffic to the plugin host must be blocked.
The only exception concerns deployments where the plugin receives webhooks from a Jira or Confluence Data Center instance. In that case, traffic from those instances must be allowed on the port on which the plugin listens for webhooks; the port number for a given deployment is provided by the Q247 deployment team. The traffic stays inside the Client's network and does not require access from the internet.
Cloud versions of Jira and Confluence do not need any inbound rule, because their events reach a receiver on the Q247 side.
TLS inspection at the firewall
If the Client's firewall terminates TLS connections and re-signs them with its own certificate, the plugin will not recognize the Q247 backend's certificate and the connection will fail. The solution is to hand the deployment team a PEM file with the corporate CA certificate, as described in Installation. Certificate verification is disabled only as an emergency measure.
Data exchange
All communication between the Enterprise Plugin and the Q247 Management Portal is secured with HTTPS:
- Minimum TLS version: 1.2
- HTTPS only: yes
The content of code changes, as well as the content of tickets and pages, stays on the plugin host. The analysis runs locally, and only its result, together with the metadata needed for the metrics, goes to Q247. The tables below list this metadata exhaustively.
Events from code repositories
| Category | What exactly |
|---|---|
| Change identification | commit identifier, remote repository address, repository type, authorship timestamp |
| Author | committer's first name, last name and e-mail address, in the form recorded by Git |
| Commit message | the full message content, without truncation. It is needed to recognize the ticket key and AI tool trailers, so it goes to Q247 in full |
| List of changed files | file paths and names, together with the number of inserted and deleted lines and the calorie score of each of them |
| Change summary | number of files, number of inserted and deleted lines |
| Branches | names of the branches the commit was on at the moment of scanning |
| Analysis result | calorie score, effort vector, name and version of the model that calculated it |
| Q247 context | organization and project identifier |
| Ticket key | the identifier recognized in the commit message, together with its prefix |
| Diagnostic data | information on whether the file list or the change content was trimmed due to size, together with numbers describing the scale of the trimming |
File paths are necessary for File Pattern Exclusions to work and for recognizing duplicate commits, so they are passed along with every event and stored. The commit message is passed in full, because the ticket key and the AI tool trailer are read from it; at the same time it is text written freely by a person, so its content depends entirely on the team's practice.
The actual content of the files, that is the diff between code versions, is removed before sending and never leaves the plugin host.
Events from pull requests
The plugin recognizes pull and merge requests as a separate kind of event. It passes: title, full description, URL, identifier and number, target branch together with information about its protection, status, draft flag, list of commit identifiers included in the request, merge commit identifier, timestamps (opening, ready for review, first and last review, merge, close) and the list of reviewers with their e-mail addresses and review result.
Repository information
| Direction | What is passed |
|---|---|
| Q247 → plugin | Git server address, connector access data and the list of repositories to scan |
| Plugin → Q247 | repository name, URL, group name, synchronization and scan status together with the date |
The access token to the repositories travels only in the first direction, together with the connector configuration. The plugin does not send the token to Q247. The exception is the Generic GIT connector, in which the credentials are part of the repository address and reach Q247 together with that address. If the connector uses an environment variable, the token does not pass even in that direction: only the variable name is stored in Q247.
AI tool telemetry
If the organization uses AI Tool Logs, the plugin passes daily summaries per user: the e-mail address identifying the person in the AI tool, the day, the tool name, the number of tokens broken down into input, output and cache, the cost, the number of generated and deleted lines, the number of commits and pull requests, the number of sessions and the active working time.
Prompts and model responses are not passed. Only counters are passed.
Retention results
Code persistence is calculated locally, by comparing the state of the repository after 1, 7, 30 and 90 days. The following reach Q247: commit identifier, the share of lines that survived at each of the four points, the number of added lines, whether the commit ended up on the main branch, the names of the branches used as the reference point, and the timestamp of the calculation.
Events from Jira and Confluence
The same mechanism, local content analysis and sending only the result, applies to Jira and Confluence, which the Enterprise Plugin handles through webhooks, not scanning:
Ticket information (Jira):
- ticket key and type, URL,
- assignee, together with their first name, last name and e-mail address, and the previous assignee,
- status change history: the status name before and after the change, the category of each of them and the moment of the change, needed for Lead Time and Cycle Time,
- calorie score,
- number of inserted and deleted characters and the number of files in the change, without their content,
- list of identifiers of the changed fields.
From the status history, Q247 builds a summary of the ticket's lifecycle, covering the moment of first entering work, the moment of completion, the number of returns and the time ranges assigned to particular people.
Page information (Confluence):
- page identifier and space key, URL, and for a wiki also the page path,
- author, together with e-mail address,
- calorie score,
- list of identifiers of the changed fields.
Diagnostic data and plugin version
Besides data about the work, the plugin passes information needed to maintain the integration: its version number with every connection, and error reports, containing the error message content, the repository address and the project identifier where the error occurred. These serve diagnostics on the Q247 side and do not contain the content of the analyzed data.
List of changed fields
The event carries information about which fields were changed, without their new values. The dictionary is closed and shared for Jira, Confluence and Azure DevOps:
| Identifier | What it concerns |
|---|---|
title | title, corresponds to the summary field in Jira |
description | description |
body | content of the page or wiki document |
message | version comment, that is the comment on the change record |
status | status change |
assignee | change of the assigned person |
comment | adding or changing a comment |
acceptanceCriteria | acceptance criteria |
reproSteps | reproduction steps |
deleted | deletion |
The dictionary is closed: a change to a field outside this list is not reported. The change content, stored locally for the purposes of the analysis, is removed before sending, so only the information that a given field was changed is passed.
Clarifying the scope of content
The content of tickets, pages and comments is not passed to Q247. There is, however, one exception.
Q247 recognizes the link between a Confluence page and a ticket by searching for its identifier in the page content, its title and the version comment. The recognized identifier is passed as metadata, so a fragment of the page content reaches the backend when it contains a reference to a ticket.
A value longer than 64 characters is skipped entirely, not truncated. The limit operates on the Q247 side, when moving the event to the analytics layer, so within the event itself the value is stored in the form in which it was recognized.
Webhook receiver authentication
The webhook receiver is authenticated with a separate, random API key generated for each organization and embedded in the webhook URL. A request with an unknown or incorrect key is rejected with an unauthorized response.
Because the secret is part of the address, the webhook address itself must be treated like a password: do not put it in tickets, internal documentation or chat channels.
Access to code repositories
Access to the source repositories is handled by the appropriate access tokens, with which the plugin connects to the repository. Only read access is required; the token must be configured that way on the SCM side.
The plugin reads all repositories it has access to (any restrictions are set in the SCM system itself or through the token's permission scope), and it also locally reads the increment history from these repositories.
See also
- Connectors: what stays local at the Client and what reaches Q247, described from the administrator's perspective
- Installation: Cloud Plugin versus Private Plugin