Skip to main content

Portal Controller

Overview

The Portal Controller syncs Kratix Promises and Resource requests into a developer portal, such as Backstage or Cortex, from a single, unified integration. It replaces the Backstage Controller and SKE Cortex Controller, which are now deprecated in its favour. See Portal Controller for the full documentation.

The release manifest is available at:

http://syntasso-enterprise-releases.s3-website.eu-west-2.amazonaws.com/#ske-portal-controller/

Release Notes

v0.4.1 (2026-09-07)

Bug Fixes

  • Resource-request pipelines no longer leak ServiceAccounts and RBAC. Each resource request used to get its own ServiceAccount, Role and RoleBinding, and none of them were ever deleted. The resource-request pipelines of a Promise now share a single set, and deleting a Promise cleans up everything it created — including what earlier versions left behind.

v0.4.0 (2026-08-27)

Requires SKE Operator v0.34.0

Upgrade the SKE Operator to v0.34.0 first.

Features

  • The Portal Controller no longer needs the skeintegrations CRD. It reads its connections from a ConfigMap, so it can be installed on its own, without the SKE Operator. See Installing without the SKE Operator.

  • The Jobs the controller creates are now configurable. Labels, annotations and other pod settings come from the ske-portal-workloads-config ConfigMap, so the Jobs can satisfy cluster policies that would otherwise reject them. See Installation.

Bug Fixes

  • Immutable fields are now declared as immutable in generated Templates, so an edit that would change one is rejected up front rather than failing later.

  • The Portal Controller no longer consumes Kratix's manual-reconciliation flag.

v0.3.0 (2026-08-18)

Features

  • Portal Sync condition is now filtered out from the generated Entity.: similar to other Kratix-owned conditions, the Portal Sync conditions are no longer added to the resource Entity when they are generated.

  • Push-mode Templates record the request. A generated push Template now applies the resource request and then hands it to the Backstage backend, so the developer sees a pending request in the catalogue while the platform catches up rather than nothing at all. Pull-request Templates are unchanged.

Upgrade the Backstage plugins first

This release requires ske-backend v0.23.0 and ske-frontend v0.20.0 or later.

Upgrade the plugins before the Portal Controller. Doing it in that order is safe: the new plugins accept everything the current Templates send, so nothing changes until the controller follows.

In the other order, newly generated push Templates carry a record-request step that an older backend rejects. Because that step runs after the request has been applied, the developer sees a failed task for a resource that was in fact created.

v0.2.0 (2026-07-30)

The first release of the Portal Controller: one integration for every developer portal your platform exposes.

Until now, each portal needed its own controller, its own SKEIntegration, and its own customization CRD. Adding a second portal meant running a second controller, and the two had little in common. The Portal Controller replaces that with a single integration that declares every portal on one resource, generates entities through one pipeline, and gives Promise authors one way to shape what those entities look like.

Both the Backstage Controller and the SKE Cortex Controller are deprecated as of this release. They continue to work, so you can migrate when it suits you. See Migrating from Backstage and Migrating from Cortex.

What you gain over the standalone controllers

The Portal Controller generates the same entities the standalone controllers did. What changes is everything around them:

Standalone controllersPortal ControllerPortals
Portals per platformOne SKEIntegration per type, so one Backstage and one CortexEvery portal on one SKEIntegration, including two Backstage instances side by sideBoth
Opting a Promise inPer-portal wiringOne label, kratix.io/portal-<type>, and a single Resource can opt back outBoth
Customizing what is generatedBackstage had BackstageEntityCustomization, one pipeline shared by the Promise and its Resources. Cortex had a handful of annotations and no way to edit the generated documentsPortalCustomization with independent promise and resource lanes, for every portal typeBoth
Expressing a customizationTyped entityGenerationOptions fields, or a hand-written containerDeclarative Portal Patch recipes, with your own container still availableBoth
ReportingPer-controllerOne PortalBindingReady condition plus a per-type sync condition and an entity URL annotationBoth
Reviewing requestsNot available: submitting a form applied it immediatelypull-request delivery mode raises the request as a pull request, and update and delete go through review tooBackstage
Where entities are writtenA Destination you create and label environment: backstage beforehandThe portal creates and owns its Destination and state store, or adopts an existing oneBackstage

For Cortex specifically, the headline change is customization. The standalone controller generated its entity and workflows the one way it knew how, and the only levers were annotations. A Cortex portal now runs the same generate → configure → writer pipeline as every other portal, so you can reshape the generated entity and workflows at both the Promise and the Resource level. See Cortex examples.

Two things become portal-wide rather than per-Promise: the Cortex fixed namespace, previously the kratix.io/cortex-fixed-namespace annotation, and the Backstage single-page form. Both are now adapterConfig.generate.args flags on the portal. Where you need them per Promise, the hideNamespaceManifest and singleSpecPage Portal Patch recipes do that job.

Features

  • One integration, many portals. Declare every portal your platform exposes on a single SKEIntegration of type: portal-controller. Portals of the same type can coexist, so a staging and a production Backstage are two entries rather than two installations. See Installation.

  • Opt in with a label. A Promise or Resource request joins a portal by carrying kratix.io/portal-<type>, instead of needing a dedicated resource per portal. A single Resource can opt back out without affecting its Promise. See Bind a Promise to a portal.

  • Request review with pull-request delivery. Backstage portals can run in pull-request mode, where submitting the generated form raises a pull request against a Git repository instead of applying the request directly. Nothing reaches the platform until a human merges it, and updates and deletions go through the same review. Currently GitHub only. See Delivery modes.

  • Backstage portals manage their own destination. A portal can create and own the Kratix Destination and state store it writes entities to, rather than requiring you to wire one up beforehand. Platforms that already manage Destinations can adopt an existing one instead. See Backstage.

  • Customizable Cortex entities and workflows. A Cortex portal runs the same generate → configure → writer pipeline as every other portal type, so the generated entity and workflows can be reshaped at both the Promise and the Resource level. It also runs a status exporter and a setup Job that provisions the shared entity and relationship types the integration depends on. See Cortex.

  • Shape entities declaratively. The new PortalCustomization resource, which replaces BackstageEntityCustomization, runs containers that edit generated documents before they ship, with separate lanes for the Promise and its Resources. Paired with Portal Patch, most customizations are a few lines of declarative recipe rather than a hand-written script. See Customization.

Known issues

  • Portal Patch recipes that target the ske-configure-resource step, including hideNamespaceManifest, fail under pull-request delivery mode, because that step only exists in push mode. A recipe that matches nothing aborts the sync, so no entity ships.