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.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.