This repository contains the source code for the LFX v2 platform project service.
The LFX v2 Project Service is a RESTful API service that manages projects within the Linux Foundation's LFX platform. It provides endpoints for creating, reading, updating, and deleting projects with built-in authorization and audit capabilities.
/readyz
:GET
- checks that the service is able to take in inbound requests/livez
:GET
- checks that the service is alive/projects
:GET
- fetch the list of projects (Note: this will be removed in favor of using the query service, once implemented)POST
- create a new project
/projects/:id
:GET
- fetch a project's base information by its UIDPUT
- update a project's base information by its UID - only certain attributes can be updated, read the openapi spec for more detailsDELETE
- delete a project by its UID
/projects/:id/settings
:GET
- fetch a project's settings information by its UIDPUT
- update a project's settings by its UID
This service handles the following NATS subjects for inter-service communication:
lfx.projects-api.get_name
: Get a project name from a given project UIDlfx.projects-api.get_slug
: Get a project slug from a given project UIDlfx.projects-api.slug_to_uid
: Get a project UID from a given project slug
The LFX v2 Project Service generates a set of tags for projects and project settings that are sent to the indexer-service. These tags enable searchability and discoverability of projects through OpenSearch.
When projects are created or updated, the following tags are automatically generated:
Project Field | Tag Format | Example | Purpose |
---|---|---|---|
UID | Plain value | f1545930-b9b7-420d-942b-eb53c1a63428 |
Direct lookup by ID |
UID | project_uid:<value> |
project_uid:f1545930-b9b7-420d-942b-eb53c1a63428 |
Namespaced lookup by ID |
ParentUID | parent_uid:<value> |
parent_uid:efc80205-b0b3-4943-9395-2b634985a142 |
Find child projects of a parent |
Slug | Plain value | test-project-tags-indexed |
Direct lookup by slug |
Slug | project_slug:<value> |
project_slug:test-project-tags-indexed |
Namespaced lookup by slug |
Name | Plain value | Updated Foo Foundation |
Text search by project name |
Description | Plain value | Updated description for tag testing |
Full-text search in descriptions |
Project settings generate a separate set of tags:
Settings Field | Tag Format | Example | Purpose |
---|---|---|---|
UID | Plain value | f1545930-b9b7-420d-942b-eb53c1a63428 |
Direct lookup by ID |
UID | project_uid:<value> |
project_uid:f1545930-b9b7-420d-942b-eb53c1a63428 |
Namespaced lookup by ID |
MissionStatement | Plain value | Updated mission statement for testing tags |
Full-text search in mission statements |
Tags serve multiple important purposes in the LFX system:
-
Indexed Search: Tags are indexed in OpenSearch, enabling fast lookups and text searches across projects
-
Relationship Navigation: Parent-child relationships can be traversed using the parent_uid tags
-
Multiple Access Patterns: Both plain value and prefixed tags support different query patterns:
- Plain values support general text search (e.g., "find projects containing 'foo'")
- Prefixed values support field-specific search (e.g., "find projects with slug 'test-project'")
-
Data Synchronization: When projects or settings are updated, their tags are automatically updated, ensuring search results remain current
- Kubernetes
- Helm
-
Install the
lfx-platform
helm chart from lfx-v2-helm repo. This is a general helm chart that is used for all LFX platform services. It contains all of the dependencies packaged in kubernetes that are needed by the platform: NATS, Heimdall, Authelia, Traefik, etc..Either read the official instructions from the repo containing the chart, or run the commands below:
# Create namespace (recommended). You should use this for all LFX services. You may already have the namespace created if you have worked on another LFX service. In that case, you can proceed to the next command. kubectl create namespace lfx # Install the chart via the OCI registry. # Note: change the version to use the latest (or desired) chart version according to the releases for the lfx-platform chart: https://github.com/linuxfoundation/lfx-v2-helm/pkgs/container/lfx-v2-helm%2Fchart%2Flfx-platform helm install -n lfx lfx-platform \ oci://ghcr.io/linuxfoundation/lfx-v2-helm/chart/lfx-platform \ --version 0.1.12
-
Install the
lfx-v2-project-service
helm chart from this current repository. You have two options: either install from the OCI registry or from the source. If you don't plan to develop the service, you can just use the packaged version from the github packages.# From OCI registry # Note: check the latest (or desired) version from https://github.com/linuxfoundation/lfx-v2-project-service/pkgs/container/lfx-v2-project-service%2Fchart%2Flfx-v2-project-service helm install -n lfx lfx-v2-project-service \ oci://ghcr.io/linuxfoundation/lfx-v2-project-service/chart/lfx-v2-project-service \ --version 0.4.0 # From source (current local directory) helm install -n lfx lfx-v2-project-service ./charts/lfx-v2-project-service
-
After installing the required helm charts, you should have the project REST API running on your machine in kubernetes, and can therefore start making some requests to the API.
-
Get an ID token from the Authelia IdP server.
In order to make a request to the service via Traefik, you need to be making an authenticated request as a valid Authelia user. If you have the lfx-platform chart installed from the previous steps, then you can use the
kubectl
CLI tool to get the list of users that you can use for authentication. They are stored in kubernetes as a secret resource.kubectl get secret authelia-users -n lfx -o json
The list of users in Authelia are set by the lfx-platform chart to help for testing basic scenarios. You can find the users and how they are set up in Authelia from lfx-v2-helm repo chart Currently, the list is as follows:
committee_member_1 committee_member_2 project_admin_1 project_admin_2 project_super_admin
Currently, you should use the existing token helper script to generate the ID token. The script is only accessible if you are LF staff. The team has a TODO in order to include the helper script in a public repo or come up with a better solution for generating ID tokens for local testing.
If you have access to the token helper script, run the following command to get the ID token. Note that you will be prompted in your web browser to log in as one of the valid Authelia users. Use the kubernetes secret
authelia-users
as previously mentioned to determine the password for each user. Use the username and password for the user you want to authenticate with.id_token=$(./token_helper.py); echo $id_token
-
Use the ID token in the Authorization Header to make a request to the project service
You can find documentation about the list of API endpoints supported by the service by looking at the OpenAPI specification file
For now, try to make a request to list the projects:
curl -H "Authorization: Bearer $id_token" http://lfx-api.k8s.orb.local/projects
You should get a response as follows. Running the app container via the lfx-v2-project-service Helm chart should run an init container that creates a root project. The UID will be a random UUID, but the slug, description, and other fields should be the same.
{ "projects": [ { "uid": "81570bff-3267-4942-80f3-d469437a46d6", "slug": "ROOT", "description": "A root project for teams permissions assignment, ordinarily hidden from users.", "name": "ROOT", "public": false, "autojoin_enabled": false, "created_at": "2025-07-31T00:41:54Z", "updated_at": "2025-07-31T00:41:54Z", "mission_statement": "A root project for teams permissions assignment, ordinarily hidden from users." } ] }
If you get a
403 Forbidden
error, then you need to check that the ID token you are passing to the project service is valid and not expired. Once you have an ID token, you can check its expiration and other user metadata on the token using this auth server API call:curl -s https://auth.k8s.orb.local/api/oidc/userinfo \ -H "Authorization: Bearer $id_token" | jq -c .
Next, try to create a project:
curl -X POST http://lfx-api.k8s.orb.local/projects \ -H "Authorization: Bearer $id_token" \ -H "Content-Type: application/json" \ -d '{ "name": "My Test Project", "slug": "my-test-project", "description": "A test project created via API", "parent_uid": "<ROOT_PROJECT_UID_GOES_HERE>", "public": false, "autojoin_enabled": false }'
You should get a response like:
{ "uid": "7bdc6e40-8cc8-4536-b537-e6cd31ce058d", "slug": "my-test-project", "description": "A test project created via API", "name": "My Test Project", "public": false, "parent_uid": "81570bff-3267-4942-80f3-d469437a46d6", "autojoin_enabled": false, "created_at": "2025-08-12T19:43:24Z", "updated_at": "2025-08-12T19:43:24Z" }
Then try to get the newly created project:
curl -H "Authorization: Bearer $id_token" http://lfx-api.k8s.orb.local/projects/<NEW_PROJECT_UID_GOES_HERE>
You should get a response just like the POST project endpoint:
{ "uid": "7bdc6e40-8cc8-4536-b537-e6cd31ce058d", "slug": "my-test-project", "description": "A test project created via API", "name": "My Test Project", "public": false, "parent_uid": "81570bff-3267-4942-80f3-d469437a46d6", "autojoin_enabled": false, "created_at": "2025-08-12T19:43:24Z", "updated_at": "2025-08-12T19:43:24Z" }
├── .github/ # Github files
│ └── workflows/ # Github Action workflow files
├── api/ # API contracts and specifications
│ └── project/ # Project service API
│ └── v1/ # API version 1
│ ├── design/ # Goa API design specifications
│ └── gen/ # Generated code from Goa design
├── charts/ # Helm charts for running the service in kubernetes
├── cmd/ # Services (main packages)
│ └── project-api/ # Project service API entry point
├── internal/ # Internal service packages
│ ├── domain/ # Domain logic layer (business logic)
│ │ └── models/ # Domain models and entities
│ ├── service/ # Service logic layer (service implementations)
│ ├── infrastructure/ # Infrastructure layer
│ │ ├── auth/ # Authentication abstractions
│ │ └── nats/ # NATS messaging and repository implementation
│ ├── middleware/ # HTTP middleware components
│ └── log/ # Logging utilities
└── pkg/ # Shared packages
└── constants/ # Shared constants and configurations
To contribute to this repository:
- Fork the repository
- Commit your changes to a feature branch in your fork. Ensure your commits
are signed with the Developer Certificate of Origin
(DCO).
You can use the
git commit -s
command to sign your commits. - Ensure the chart version in
charts/lfx-v2-project-service/Chart.yaml
has been updated following semantic version conventions if you are making changes to the chart. - Submit your pull request
For more details about development on this repository, read the DEVELOPMENT.md.
To create a new release of the project service:
-
Update the chart version in
charts/lfx-v2-project-service/Chart.yaml
prior to any project releases, or if any change is made to the chart manifests or configuration:version: 0.2.0 # Increment this version appVersion: "latest" # Keep this as "latest"
-
After the pull request is merged, create a GitHub release and choose the option for GitHub to also tag the repository. The tag must follow the format
v{version}
(e.g.,v0.2.0
). This tag does not have to match the chart version: it is the version for the project release, which will dynamically update theappVersion
in the released chart. -
The GitHub Actions workflow will automatically:
- Build and publish the container images (project-api and root-project-setup)
- Package and publish the Helm chart to GitHub Pages
- Publish the chart to GitHub Container Registry (GHCR)
- Sign the chart with Cosign
- Generate SLSA provenance
- The
appVersion
inChart.yaml
should always remain"latest"
in the committed code. - During the release process, the
ko-build-tag.yaml
workflow automatically overrides theappVersion
with the actual tag version (e.g.,v0.2.0
becomes0.2.0
). - Only update the chart
version
field when making releases - this represents the Helm chart version. - The container image tags are automatically managed by the consolidated CI/CD pipeline using the git tag.
- Both container images (project-api and root-project-setup) and the Helm chart are published together in a single workflow.
Copyright The Linux Foundation and each contributor to LFX.
This project’s source code is licensed under the MIT License. A copy of the
license is available in LICENSE
.
This project’s documentation is licensed under the Creative Commons Attribution
4.0 International License (CC-BY-4.0). A copy of the license is available in
LICENSE-docs
.