Skip to content

ADR 016 - UI Module service affiliation - #58

Open
Max-0e wants to merge 7 commits into
platform-mesh:mainfrom
Max-0e:feat/adr-16-L4-service-affiliation
Open

Max-0e wants to merge 7 commits into
platform-mesh:mainfrom
Max-0e:feat/adr-16-L4-service-affiliation

Conversation

@Max-0e

@Max-0e Max-0e commented Oct 6, 2026 •

Copy link
Copy Markdown

ADR 016 - UI Module service affiliation

This ADR addresses service affiliations to the Portal/UI Module.

Goals:

  • Align decisions to the correct layer to align implementation with RFC 008
  • make considerations when layer affiliations is not clear

Outside the scope:

  • Affiliate services with Authz & Auth

@Max-0e
Max-0e force-pushed the feat/adr-16-L4-service-affiliation branch from 8119130 to 5965f07 Compare October 6, 2026 08:41

@mjudeikis mjudeikis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few quick notes

Comment thread adr/016-L4-service-affiliation.md Outdated
To evaluate the affiliation of a service, this sections considers layer-association with possible options:

### Portal
The Portal should obviously be part of L4 as it is deeply coupled von OpenMFP and just represents the default implementation of a solution to operate platform mesh via a graphical user interface

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coupled von OpenMFP ? von? what does this mean? :D

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry some good old german denglish showing through. I did fix it this formulation from "von" to -> "with" i think that makes more sense :D

Comment thread adr/016-L4-service-affiliation.md Outdated
Comment on lines +123 to +129
effectively ommited services in modular Setups without L4:
- Portal (as in the current OpenMFP implementation)
- clearly this is the default implementation and thus should be omittable and replaceable
- IAM UI
- clearly this is the default implementation and thus should be omittable and replaceable
- Marketplace UI
- clearly this is the default implementation and thus should be omittable and replaceable

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A lot of current assumptions are built ontop the fact that anything, operating ontop of PM should have some kind of microfrontend feature. Meaning if user does BYO-UI, is the expectation that they need to handle this on their own (either roll their own micro-frontend framework) or just have everything statically compiled?

Current providers have this BYO-microfrontend concept. So for the UI to be fully modular, providers need to be, in a way, UI-agnostic. I didn't seen anything related to providerts in this doc.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I completely agree, that the provider side needs to be UI-agnostic as, at least from a PM-internal standpoint, the two CR's defining provider-to-UI relationships (ContentConfiguration & ProviderMetaData) are relatively generic from their API-Definition but especially the ContentConfiguration is validated and reconciled in a very opinionated way towards being a Luigi-Config and therefore a micro-frontend-framework-configuration. As I stated in the decision drivers decoupling to the micro-frontend-pattern should be desired but also has to be achievable.

In my opinion creating a BYO-portal should also mean finding a fitting solution to allow for more or less dynamic UIs based on installed/used providers. Wether that solution is micro-frontends or something else should not be a core PM decision/design-principle (as this decision should just be made for the default implementation i.e. L4). For this reason mainly the ContentConfiguration CR has to either:

  • be more flexible to accompany other solutions than micro-frontend-configurations
  • be considered a L4 concept where BYO-portal solutions must find their own solution for providers to handle UI extension

I did try to discuss this in the considerations for the extension-manager-operator and refered to this discussion in the Open-Question bit at the end, but maybe it is not clear enough in the current state of the doc, that this is the essential decision that needs to be made to define provider-to-UI relationships going forward.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if an adopter decides to skip the default implementation for the UI module and does a BYO-UI he cannot expect current provider mechanisms (the UI-part, not APIExport) and/or existing implementations to work like before. So if we want two arbitrary compositions to work together we can only rely on the Core and its contracts as well as the other modules interfaces.
So I would say: An adopter choosing a different UI must handle the UI-pluggability on his own - that's why he choose the "non-default" path. But he can rely on having KRM Resources like APIExport (today), ProviderMetadata and the marketplace virtual workspace (as proposed) from the Core module as well as other yet-to-be-defined contracts.


## Decision Drivers
- omittability without interrupting core functionality
- coupling to Authorization-Services especially when they're absent

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do we plan to manage auth/authz in ui-agnostic system? Is the plan that users authenticate to external OIDC and talks to PM system using JWT token from external IDP with shared trust OR there are smth else in mind?

How would this work in the case where PM is configured to use multiple IDPs? Do we need to standardise on some tenant-to-IDP mapping API for any ui to consume?

@Perseus985 Perseus985 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leaving some comments :) Pinging @BergCyrill so he can also give his two-cents ^^

Comment thread adr/016-L4-service-affiliation.md Outdated
@@ -0,0 +1,150 @@
# ADR 016: L4 service affilitaion

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: We moved away from the "Layer" wording and re-re-introduced the "Module" with the recent amendment. Same for L3 / L2 yadda yadda :)

Suggestion: ADR 016: UI Module... <- pls change the filename also ;)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And since the whole RfC-008 amendment was more or less mostly about the word "layer" vs "module" we should be picky here - we called it modules with boundaries now.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All references of the nomenclature Layer should be replaced by now, unfortunately the branch name also includes "L4" I hope thats fine, since changing the branch would require a new PR without the existing discussions I think. If not I would suggest, we create a new PR when the ADR is actually in a mergable-state when necessary.

Comment thread adr/016-L4-service-affiliation.md Outdated
Since the RFC calls for replaceability rather than just optionality, the graphql-schema could be defining the strong API-Contract for other UI implementations and act as the boundary that seperates L4 services.

#### gateway as L4 service
While possible, the graphql-layer could be omitted fully when operating API-only. This would then require direct kubernetes-api calls via `kubectl` and remove the active service discovery as well as automatic api-schema generation that the graphql-gateway provides.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd challenge this one: the Kubernetes API already does both.

Discovery is /apis per workspace (in kcp it reflects the workspace's APIBindings on top of the built-in APIs), and the schema is generated automatically from the APIResourceSchemas under /openapi/v3.

The gateway's listener builds its GraphQL schema from that OpenAPI. So omitting the gateway loses GraphQL itself (composed queries, the playground), not discovery or schema generation.

Same for the cons below: the API contract without the gateway is the KRM API itself, which is the Goal from my understanding.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also add here that we should move things not required in a module out of it to reduce the footprint (resources) and also increase on security & stability. The gateway was explicitly named to not be part of a API-only platform mesh deployment for this reason in RfC-008

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point, especially when looking at it from a API-only operation standpoint, this service is not needed at all and, as Kevin said, is essentially just a wrapper with some build-in conveniences (like composed queries etc.) and not the API-Contract itself.
I wrote this with the heavily biased perspective of the replaceabilty aspect of the UI Module, where conveniences that GraphQL (and the implementation of this service in general) offers are something that most UI implementation would probably leverage anyway. But as we discussed here this does not make it a core functionality of PM, hence should be part of the UI Module.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have now added a third option that describes the variant to handle all three cases as first class choices:

  • headless API-only -> no gateway deployed
  • default UI module -> gateway as part of default UI module
  • BYO UI module -> optional deployment of the kubernetes-graphql-gateway independently from other default UI module service

Comment thread adr/016-L4-service-affiliation.md Outdated
If it is the latter, the schema-validation and internal model currently implemented should be more generic and be configurable so the actual platform-mesh user may use it for their own portal implementation (without Luigi).
The operator also defines `ProviderMetaData` which essentially imposes the same question as the `ContentConfiguration` due to it being unclear if the concept of provider MetaData being stored/managed by platform-mesh's services is a core feature or an implementation detail of the current/defalt ui implementation.

### terminal-controller-manager

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure the terminal-controller-manager belongs in this ADR at all: it's off by default and, as far as I know, mostly used for demos. I'd see it as an optional extension to the UI / Platform Mesh rather than part of the UI module.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1; we also said in the RfC "In security-hardened and compliance-heavy environments, fewer running components means a smaller attack surface".
So including something like the terminal-controller in the Core module seems to be an anti pattern.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I agree and get your arguments, I'm not sure if omitting the service completely in this ADR is the best way, since Kevin already gave good reasons to affiliate the service to the UI as a extension of the current/default implementation, which drives the decision very clearly towards it being a UI Module service. But still the service is part of the monorepo and clearly some "part" of the Platform Mesh project and this ADR aims to either place a service that is part of the UI solution into either the UI or any other (even though mostly Core-) Module.
Since the decision is pretty clear, due to Kevin's arguments, there is no need for a wide discussion but imo documenting the decision is worth it anyway.

### Marketplace UI
The Marketplace UI just as the IAM UI represents a microfrontend part of the current/default ui implementation.

### extension-manager-operator

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would see the ContentConfigurations as UI. And I think we have to split the extension manager here: as you said, ProviderMetadata comes from here too, but the marketplace needs it.

RFC 008 puts the marketplace mechanism into Core but still lists ProviderMetadata as UI/optional, and the WG left that slicing for "when it's needed". I'd do it here and move ProviderMetadata to Core.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree ProviderMetadata can move to be a core API as e.g. marketplace.platform-mesh.io. I'd also make a separate type that makes an APIExport part of the marketplace, which is then the marker to offer an APIExport in the marketplace in the first place - similar to how that was done via ContentConfiguration so far.

ContentConfiguration should only carry UI specific additions over the ProviderMetadata.

#### gateway as L1 service with option to disable
This is essentially the same variant as the 'gateway as L1 service' the the exeption that the service, even though being considered a L1-/Core-service, can be disabled when not needed. For example in API-only operation where direct interaction with `kubectl` is acceptable/desired. This does make an API-only deployment potentially more lightweight when the GraphQL-API is not needed, but at the same time adds complexity to deployments, breaks the API-Contract that L4 would depend on if deployed later and defies the clear affiliation of the service to L1, which in turn could mean that the gateway must define its own layer, that can be omitted/replaced, which would not align with RFC 008. Additionally when fully disabled remote cluster access would need to fully work around the current centrally managed solution handled via the `ClusterAccess` CRD.

### virtual-workspaces

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The marketplace mechanism is Core (RFC 008), and the marketplace virtual workspace is how consumers discover what they may bind. So that one belongs in Core; only the contentconfigurations virtual workspace stays UI. So we have to split here^^

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I described a suggestion for the split of the virtual-workspaces service into one affiliated with the default UI implementation as it is coupled to the ContentConfiguration CRD.
And one that handles the core marketplace mechanism which is always present as its part of PM's core.
Please let me know if the description for this is clear enough or needs to be fleshed out in more detail.

The decision for the virtual-workspaces service depends directly on the layer affiliation of the extension-manager-operator, as its only purpose is to compose data from the two CRD's `ContentConfiguration` and `ProviderMetadata` (and `ApiExports`'s, but this does not matter in the context of this decision).
If the extension-manager-operator's CRDs are not considered core platform-mesh functionalities the principle of the served `MarketplaceEntry`'s is not as well.

### iam-service

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I would leave the iam-service out of here and only mention the IAM UI. And say that for the UI module the graphql gateway is our entry point.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would challenge this one, as imo the iam-service serves kind of the same purpose like the graphql-gateway but without (in the current state at least) the CRD under the hood.
As I mentioned in the ADR for authentication the iam-service currently lives in a kind of gray-zone as long as it is not decided, what exactly acts as the interface/boundary: the ResolverService-go-Interface or dedicated CRDs (for Roles an Users).
As there are no open standard for User/Role Management this boundary must be defined by PM in some way and depending on where this boundary lives the iam-service might just implement a GraphQL layer on top of the actual boundary itself which in turn makes it very comparable to the graphql-gateway.

ref:#62 (comment)

Comment thread adr/016-L4-service-affiliation.md Outdated
Comment on lines +140 to +141
- kubernetes-graphql-gateway
- this should be a L1 service that fulfills the API-Contracts defined by the GraphQL-Schemas, it should not be able to be disabled so that the defined contract always holds

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Following up on L79: I'd keep the gateway in the UI module, but as its interface with its own switch, separate from the default implementation (portal, IAM UI, marketplace UI). That covers all three setups: headless (both off), bring-your-own UI on the gateway (gateway on, portal off), and the full default.

- this should be a L1 service that fulfills the API-Contracts defined by the GraphQL-Schemas, it should not be able to be disabled so that the defined contract always holds
- iam-service
- the iam-service is clearly not a L4 service thus should be considered as L1 in the scope of this ADR even though in following ADRs for L2 and L3 affiliation could change to L2 or L3

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To make my comments easier to follow I took the liberty of creating a diagram :-D
Thats how I would read the split (based on my review comments)

Image

I think it would be good to have something like this in the ADRs, whichever way we decide. It helped me to follow it much better.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a really good diagram. I 100% agree with this, that is what I was thinking about when we were talking about modules in PM.

@BergCyrill BergCyrill left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What I am missing in this ADR is the UI modules interfaces. RFC 008 requires every module to expose its capability through a defined interface, preferably KRM, and to declare its dependencies and its behavior when an optional dependency is absent

edit: after talking back to Kevin I should amend my comment: Having some kind of table with interfaces ("in"/"out") as well as a diagram would help. If we then keep this structure in the ADRs for the other modules they should fit together well.

Comment on lines +116 to +118
The IAM service essentially has the same scenarios as the kubernetes-graphql-gateway regarding it's api contract providing read- and write-functionality via GraphQL.
The key difference is the coupling of the iam-service to L3 and L2 as its primary function is to manage identity (Authentication) and access (Authorization) data.
For this reason in **none** of the possible scenarios should the iam-service be considered a L4 service. As the scope of this ADR does not include L3 and L2 the iam service should primarily be considered as a L1 service, though ADR's for L3 and L2 might affiliante the iam service as L3 or L2.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about that also respectively would disagree to some extend.
We wanted to define some APIs as a "glue"/contract between the modules. For now the sole purpose of having the iam-service is that it serves the iam-ui.
And since we want to drive authorization (&authentication) in non-UI deployments also a KRM-based API would serve us better than having some graph-ql contract in my point of view.

Comment thread adr/016-L4-service-affiliation.md Outdated
Comment on lines +123 to +129
effectively ommited services in modular Setups without L4:
- Portal (as in the current OpenMFP implementation)
- clearly this is the default implementation and thus should be omittable and replaceable
- IAM UI
- clearly this is the default implementation and thus should be omittable and replaceable
- Marketplace UI
- clearly this is the default implementation and thus should be omittable and replaceable

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if an adopter decides to skip the default implementation for the UI module and does a BYO-UI he cannot expect current provider mechanisms (the UI-part, not APIExport) and/or existing implementations to work like before. So if we want two arbitrary compositions to work together we can only rely on the Core and its contracts as well as the other modules interfaces.
So I would say: An adopter choosing a different UI must handle the UI-pluggability on his own - that's why he choose the "non-default" path. But he can rely on having KRM Resources like APIExport (today), ProviderMetadata and the marketplace virtual workspace (as proposed) from the Core module as well as other yet-to-be-defined contracts.

@Max-0e Max-0e changed the title ADR 016 - L4 service affiliation ADR 016 - UI Module service affiliation Oct 19, 2026
Maximilian Oedinger added 5 commits October 19, 2026 11:22
Signed-off-by: Maximilian Oedinger <maximilian.oedinger@sva.de>
Signed-off-by: Maximilian Oedinger <maximilian.oedinger@sva.de>
Signed-off-by: Maximilian Oedinger <maximilian.oedinger@sva.de>
Signed-off-by: Maximilian Oedinger <maximilian.oedinger@sva.de>
Signed-off-by: Maximilian Oedinger <maximilian.oedinger@sva.de>
@Max-0e
Max-0e force-pushed the feat/adr-16-L4-service-affiliation branch from 7879f04 to a16291d Compare October 19, 2026 09:23
@ntnn

ntnn commented Oct 26, 2026

Copy link
Copy Markdown
Member

@Max-0e Please present the RFC in tomorrows TSC. Thank you!

Max-0e and others added 2 commits October 27, 2026 07:31
Signed-off-by: Maximilian Oedinger <maximilian.oedinger@sva.de>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants