Extract Cloud Connector business logic to a library
# Summary
The Cloud Connector team is launching a strategic initiative to centralize business logic into a shared library, enabling multi-backend support and eliminating redundant code across services.
**Timeline** (subject to change - see below)
<table>
<tr>
<th>Release</th>
<th>Date</th>
<th>Milestone</th>
</tr>
<tr>
<td>17.7</td>
<td>December 2024</td>
<td>
Python library release
Ruby Architecture Decision Record (ADR)
</td>
</tr>
<tr>
<td>17.10</td>
<td>March 2025</td>
<td>Ruby library release</td>
</tr>
</table>
**Objectives:**
* Standardize Unit Primitive configurations into a single source of truth
* Establish a unified codebase for core Cloud Connector functionality
* Streamline integration of new backend services
**Implementation:**
1. New shared library repository: https://gitlab.com/gitlab-org/cloud-connector/gitlab-cloud-connector
2. Languages: Python and Ruby implementations (Go later)
3. Integrating with AI Gateway, Duo Workflow service, CustomersDot, and GitLab Rails
4. Migrating existing implementation, including unit primitive configuration
**Key benefits:**
* **Technical**
* Reduced Complexity: Centralized business logic and standardized components
* Faster Development: Streamlined backend service integration,
* Improved Maintainability: Single source of truth for shared functionality
* Improved Domain Modeling: Clear separation between core Cloud Connector domain logic and other services
* **Business Impact**
* Faster Time to Market: Accelerated delivery of new cloud integration features
* Reduced Risk: More reliable cloud service connections through standardized implementations
* Lower Costs: Decreased engineering effort needed for maintenance and new integrations
## Problem Statement
Cloud Connector is moving to a [multi-backend world](https://gitlab.com/gitlab-org/gitlab/-/issues/468196 "Cloud Connector: multi-backend support") sooner or later.
However, several pieces of logic are specific to Cloud Connector and unspecific to the AI gateway that were built out entirely within the AI gateway code base for reasons of iterating faster.
Also, there is a Cloud connector client logic related to CloudConnector configuration and unit primitives that are duplicated in Rails monolith, CustomersDot, and Ai Gateway
Components that could be extracted to a shared library:
* OIDC key discovery
* JWT token validation
* HTTP header verification
* Unit primitives (configuration and API)
* Issuing JWT tokens
## Solution
We will to move to a library based approach where code that all backends must execute will be built and owned by ~"group::cloud connector" and linked to each backend individually.
We will create `gitlab-org/cloud-connector` sub-group for code/projects that we own. Similar to `gitlab-org/cloud-connector-team` that we have for management staff.
The mono repo for cloud connector library will be: `gitlab-org/cloud-connector/gitlab-cloud-connector`
The structure of the shared library:
```shell
└── gitlab-cloud-connector
├── config
│ └── backend_services
│ └── ai_gateweay
│ └── unit_primitives
│ ├── code_suggestions.yml
│ └── explain_vulnerability.yml
├── src
│ ├── golang
│ ├── python
│ │ ├── authentication
│ │ └── unit_primitives
│ └── ruby
│ └── unit-primitives
├── tools
├── tasks
└── spec
```
The structure will be organized in the following way:
- src/ruby - published Ruby Gem package used by clients: Gitlab monolith and Gitlab Rails. It would contain the library/api for reading CloudConnector unit primitive configuration and logic for self-issuing JWT tokens
- src/pything - published Pything pip package: Containing both client and server Cloud Connector logic (unit primitive API, JWT token validation, HTTP header verification and OIDC key discovery)
- tools - Cloud connector tools such as YML schema validators, dedicated tool for adding new Unit primitive, etc
- tasks - Rake tasks run by CI/CD gitlab-cloud-connector project, such as YML validation
- spec - tests for Cloud connector tools and assets (schema)
## Timeline
<table>
<tr>
<th>Milestone</th>
<th>Items</th>
</tr>
<tr>
<td>
17.6 (November)
_update: will carry over into 17.7_
</td>
<td>
**Summary:** V1 Python library (supporting JWT validation only) is complete and integrated with Python backends (AI gateway, Duo Workflow)
**Activities:**
* **V1 Python library is complete and integrated (supporting JWT validation only)**
* _can't guarantee 100% hitting 17.6. There is a huge reliance on collaboration with other groups and they could be busy so the review/approval/validation process may stretch things a bit._
* Prepare for the Ruby library work by cleaning up the UP config files in their existing format
* Support license type in existing Unit Primitive format, for CDot only
* (this is not great as it creates a gap between CDot and gitlab.com, but we will live with it for now)
**Output:**
* python library is integrated into python backends: AIG and DWF services (moved to 17.7)
**Outcomes:**
* All service code for authentication (validating JWT tokens) is replaced by the library
* All services can benefit from library updates
* Adding new Python backend services to CC will be faster/easier in the future for these teams
</td>
</tr>
<tr>
<td>17.7 (December)</td>
<td>
**Summary:** Architecture Design Review (ADR) for V1 Ruby library is completed and reviewed by stakeholders.
**Activities:**
* Python library clean up tasks.
* _writing tests (we miss a lot of coverage), writing docs on library usage (we have nothing now), cleaning up the AI GW/DW from the tests that are too cloud-connector-specific (some to delete, some to move into our repo), and some (small but inevitable) refactor_
* Start Ruby library design (we may begin this earlier in 17.6)
* Go through the new Unit primitive format
* Analyze what we are losing when we remove “services”
* Review backwards compatibility plan
* e.g. Watch out for the upgrade path where things break for 24 hours
* Create ADR that defines what we plan to do
* Address the big question: Self Hosted models, they are using some database application settings per Unit Primitive, and relying on a service name called Self Hosted model, it is a bit of an untangling job.
* Do we need to support only a feature available only on gitlab.com vs Self Managed
* Discussions on analytics
* Problems where UPs are used for tracking only rather than actual features
* The API format itself
* **Share with other teams via the ADR**
* JWT issuance moved to V1 Ruby library and CDot/Rails updated to use it (can be done in parallel to the UP design work above)
* Define and agree migration plan for library (including UP config migration to component config/ folder)
**Output:**
* agreed plan addressing backward compatibility, how we handle self-hosted models, analytics etc.
</td>
</tr>
<tr>
<td>17.8 (January)</td>
<td>
**Activities:**
* Start working on V1 Ruby library (supporting Unit Primitive configuration)
</td>
</tr>
<tr>
<td>17.9 (February)</td>
<td>
**Activities:**
* Roll out V1 Ruby library to CDot
* Continue to use existing Unit Primitive YML files for Gitlab.com
</td>
</tr>
<tr>
<td>17.10 (March)</td>
<td>
**Summary:** V1 Ruby library is completed and integrated into CDot and GitLab rails
**Activities:**
* Roll out V1 Ruby library to Gitlab.com
* Update Python library to use Unit Primitive configuration files
* SSOT for Unit Primitives is now the library yml files.
* Implement a tool for adding/updating the configuration
**Output:**
* Ruby library is integrated into CDot and Gitlab Rails
**Outcome:**
* Supported capabilities:
* Both services (CDot and Rails) code for authentication (creating JWT token) is replaced by the library method
* both services can automatically benefit from library updates
* Unit primitives SSOT for Ruby services is now the [**component config folder**](https://gitlab.com/gitlab-org/cloud-connector/gitlab-cloud-connector/-/tree/main/config?ref_type=heads)
* Unit primitives SSOT for Python services is now the [**component config folder**](https://gitlab.com/gitlab-org/cloud-connector/gitlab-cloud-connector/-/tree/main/config?ref_type=heads)
</td>
</tr>
</table>
epic