Keelcroft / GitLab Issues Sync for Jira / Privacy
Privacy Policy
Effective 30 October 2026 upon publication. GitLab Issues Sync for Jira is published by Keelcroft. Privacy contact: support@keelcroft.com.
This app transfers configured issue content between Jira and GitLab.
Destination permissions govern copies. Source audiences are not preserved, and public destination projects can expose copied content. Pause, unlink and uninstall do not erase those copies.
Scope
This policy explains how GitLab Issues Sync for Jira processes information when installed in Jira Cloud. The app runs entirely on Atlassian Forge. There is no vendor-hosted backend: Forge calls GitLab directly, and no customer data is relayed through infrastructure operated by Keelcroft. The app contains no advertising, no external analytics, and no AI services.
Information read and transferred
Administrators select directions, mappings and creation/import rules. Linked issues are synchronized; qualifying unlinked issues can create a counterpart through an enabled automatic-creation rule or an explicitly started backlog import. Enabling sync alone does not import the backlog. Depending on these settings, data processed or transferred includes:
- Issue summaries/titles, descriptions, labels and mapped statuses. Optional workflow mapping uses explicit labels plus GitLab's binary open/closed state, not its native custom-status API.
- Mapped priority labels, existing milestone names, due/start dates, weights, components and supported custom field values. Settings and content may contain business or personal information.
- Explicit assignee mappings containing Jira account IDs and GitLab usernames; GitLab numeric user IDs are looked up for assignment.
- Optional new comments after linking, including text, source IDs and author display names for attribution. Restricted/internal Jira comments and GitLab internal/system notes are excluded. Comment edits and deletions are not mirrored.
- Optional files after linking: Jira attachments and GitLab uploads referenced in notes, including filenames, types and bytes. Attribution comments/notes and copied files become destination content. Backlog imports do not import historical comments or files.
New connections default descriptions, comments and files to Both directions. Existing description settings are retained; missing legacy comment/file settings remain Off unless explicitly enabled. Formatting conversion supports common Markdown/rich-text constructs, not every GitLab extension. Images remain links rather than embedded Jira media; a copied link does not grant source access.
Authenticated issue/note webhook payloads and provider reads can contain more information than the selected transfer fields. Raw payloads, descriptions, rich documents, comment text and file bytes are processed transiently during a pass, not archived in the event journal. Comment reads stop at five pages of 100 per side; copies are limited to ten per direction/pass, with visible shortening after 30,000 source characters. Files are limited to 10 MiB and three per direction/pass; bytes are buffered before checking size. These are not unlimited-history, streaming-memory or malware-scanning guarantees.
Confidential issues and destination audiences
Confidential GitLab issue export is blocked by default for new, missing and legacy settings, including linked pairs. Blocked confidential rows are excluded before backlog preview titles are collected. A project administrator can explicitly opt in after a warning. The app does not configure Jira issue security or preserve GitLab audiences. Filters, trigger labels and mappings are selection controls, not access-control equivalence.
This safeguard is not a write ACL: confidentiality changes during a pass can race, and a direct write/create may occur before response/read-back refusal. Disabling export does not remove existing copies. Review destination permissions before allowing transfer, including when a source becomes more restricted later.
Durable information stored by the app
The following records use ordinary Forge storage unless identified as secrets. They are not an archive of complete source issues, but identifiers, configuration, failure values and file-access references can still be sensitive.
- Connection configuration: instance/API root and project path; field/direction/status, priority, custom-field and assignee maps; conflict policy; default Jira issue type and label/type rules; JQL, trigger/exclude labels and other selection filters; optional workflow prefix/rules; the explicit confidential-export boolean; enable state/timestamps and webhook ID. Names, labels and query text can contain customer information. These settings are not secret storage.
- Links and lookup entries: Jira issue ID/key, GitLab issue number/URL, per-field SHA-256 digests, agreement state and timestamps. Digests minimize retained content but are not encryption or anonymization; low-entropy values may be guessable.
- GitLab upload recovery: per-issue stages contain source label/ID, file digest, start time and, when known,
uploadReference. The reference is/uploads/<secret>/<encoded-filename>: it retains an upload secret and encoded filename, potentially personal data and a sensitive file-access reference. A non-expiring fence retains source identifiers, digest and start time. This is not merely an anonymous digest and is not the GitLab access token. - Jira upload recovery: stages contain source label/ID, file digest, start time and, when known, the returned attachment ID, with a separate upload fence recording source identifiers. Both destinations' recovery journals are capped at 100 stages per issue and have no automatic app TTL. Digests incorporate filename, MIME type and a content hash. Raw file bytes, authors and provider Markdown are not stage fields; the GitLab encoded filename exception above is retained.
- Backlog import: one latest run per connection stores run/connection IDs, direction, up to 500 source IDs and visible keys, offsets, counts, status and timestamps, plus at most twenty failure key/reason entries of up to 300 characters per reason. Failures may include field names or rejected values and are not anonymous metadata. Preview titles and issue bodies are not saved in that run. It has no automatic TTL and is overwritten by the next run.
- Scheduled recovery cursors: a global last-connection ID and per-connection hashed destination/enable scope, last link ID, optional pending link ID and five-minute bucket. These contain no issue values/provider bodies and have no automatic TTL.
- Event journal: origin, record/event identifiers, outcomes, attempts, timestamps, field names written/mismatched and import batch/creation metadata where applicable. No raw issue field values, comment text or file bytes are saved here. Entries expire 90 days after their latest write. Replay reads both platforms again.
- Copy claims: deduplication keys and timestamps used during copying. Comment claims are normally removed after a pass and may be reclaimed after ten minutes; that is not a guaranteed ten-minute deletion TTL.
Credentials
The supplied GitLab access token and generated root webhook secret use Forge encrypted secret storage. GitLab's webhook token and signing token are derived from that root secret. Raw access tokens, webhook secrets and signatures are not returned to the interface or written to application logs. The interface reports token presence rather than its value. Pause clears the webhook secret, not the access token; external token revocation is a separate action in GitLab.
External destinations
- gitlab.com — configured issue, note, upload, assignment, field and webhook operations.
- A customer-approved self-managed GitLab host — requires your Atlassian organisation administrator's customer-managed egress approval. The app cannot add hosts itself; this path is not a claim of completed self-managed live testing.
Administration, previews and background execution
Administrative operations re-check Jira project administration on the server using the signed project context; license checks also apply to protected controls. Import Jira selection runs as the administrator. Background sync, queued imports and scheduled recovery use the app-permission path and do not freshly impersonate or re-authorize the initiating administrator at every step. These checks do not prove that every destination viewer has equivalent source access.
Backlog preview titles are transient. Pair Preview reads both records but returns only field names, decision/conflict/override codes, mapping problems, timestamp and configured comment/file directions, not field values, authors, bodies, filenames or URLs. It writes no issue or storage record and queues no replay. Sanitized operational errors may still be shown. A preview is not an immutable consent reservation.
Application decision logs contain operational identifiers, outcomes and reason codes, not raw issue content, access tokens, upload references or webhook credentials. This log minimization does not remove the durable configuration, failure values or sensitive upload references disclosed above.
Retention and removal
- Connection/maps, links/indexes, upload recovery, import runs and recovery cursors have no automatic app TTL. Relevant manual operations remove only their stated records; a new import overwrites its latest-run record.
- Pause retains the access token, settings, links and history. It records disabled state before attempting webhook removal; failed cleanup retains the hook ID for retry. Work already in flight may finish.
- Confirmed unlink removes pair/index entries, not configuration, all event history, recovery stages or destination copies. There is no general disconnect/delete-connection control.
- Event records expire 90 days after latest write. Upload recovery and cursors do not inherit that expiry.
- Uninstall affects the entire app installation. Forge-hosted storage retention/deletion after uninstall is 0–28 days under Atlassian's platform lifecycle, not an immediate-erasure promise.
- Uninstall does not revoke GitLab tokens, guarantee removal of an external webhook, or erase issues, copied comments/files, links or attribution already written into Jira/GitLab. Manage those in the destination and revoke tokens separately. See Data deletion.
Contact
Send privacy, access or deletion questions to support@keelcroft.com. Report suspected vulnerabilities to the same address with the subject line “Security”. Include the Jira site, but never send passwords or API tokens.