The first Foundry post showed the visible part of the experiment: a real FOLIO Licenses application running inside Lattice, backed by mod-licenses, authenticated through Zitadel, and routed through Envoy without Okapi or Eureka.
That was the right first proof, but it was still a spike. The next question was whether the result could start to become an operational platform shape rather than a clever local demo.
Evidence first
Before talking about control-plane structure, it is worth grounding the claim in the application again. The earlier screenshots showed Licenses rendering, but not much actual data moving through the system. This time the browser flow creates a real license through the UI and then searches for it.

The browser verification watches the POST to mod-licenses through Envoy, checks the response, returns to the Licenses list, searches for the generated license name, and verifies that the created record is present in the search response.

That matters because this is not a mock Licenses screen. The path exercises Lattice, the wrapped ui-licenses microfrontend, Envoy routing, Zitadel-backed browser authentication, compatibility support APIs such as settings and tags, and the real mod-licenses backend.
What changed underneath
The last chunk of work moved Loom from static spike data toward a service-provider control plane.
Loom now has Flyway-managed Postgres schema for the operational facts it needs to own:
- workspaces;
- presentation hostnames;
- workspace tenant keys;
- capability activations;
- selected support-interface versions, such as settings and tags.
That last point is deliberately phrased as operational state. Loom is not becoming the place where products are sold, offerings are managed, or systems users request tenants. That belongs upstream, in the separate ki-console cluster. Loom’s job in this project is to execute selected operational intent: create this workspace, activate this capability, publish the runtime shape, and drive reconciliation.
The runtime endpoint now has a more strategic path too. If persisted lifecycle rows exist, Loom can derive the runtime document from that state. If not, it falls back to the original YAML snapshot so the local spike remains usable while the service grows up.
This gives us a useful transition:
- the spike still runs;
- the current local developer workflow is preserved;
- mutable workspace and activation intent has a real persistence shape;
- Lattice still consumes runtime configuration instead of knowing how to infer tenant state itself;
- Envoy remains the data plane, not the control plane.
What we avoided
The most important design decision in this increment may be what did not happen.
We did not add a provisioning UI to Loom. We did not make Loom a product or offering management system. We did not turn the local Docker scripts into Loom’s core behaviour. We did not enable public mutation routes before authentication, authorization, and idempotency had a credible contract.
Instead, Loom now has disabled mutation diagnostics for the next set of service-provider commands. Those diagnostics describe unresolved principal state, authorization state, and scoped idempotency without storing bearer tokens or raw idempotency keys. They are guard rails, not a claim that lifecycle mutation is ready.
That is a small distinction, but it keeps the architecture honest. A service that can create tenants and activate services needs a stronger contract than a local script with an HTTP wrapper.
Why this is a useful boundary
The Foundry split is becoming clearer:
- Loom records and reconciles operational intent.
- Lattice renders a workspace from runtime configuration.
- Envoy executes routing and compatibility decisions.
- Platform services provide shared support interfaces without pretending every support API is a business bounded context.
- FOLIO modules remain real FOLIO modules, with compatibility translation at the edge where needed.
The Licenses proof is now doing two jobs. It is still the visible application that tells us whether the stack actually works, but it is also the test fixture for the lifecycle model. If a workspace has Licenses activated, Loom should be able to say what runtime Lattice should load, what tenant key the backend needs, which support-interface versions are selected, and what reconciliation steps are required to bring that into being.
Next sprint
The next sprint should make Loom accept authenticated lifecycle intent rather than importing it from the spike snapshot.
The target is not a console. ki-console remains the likely systems-user surface. The target here is the service-provider boundary:
- accept a create-workspace intent from an authorized caller;
- accept an activate-capability intent for Licenses;
- persist both intents with durable idempotency;
- return a reconciliation-required response instead of pretending side effects completed immediately;
- create durable reconciliation run records before any local executor performs substrate-specific work.
If that holds, Foundry will have moved from “we can run one FOLIO app locally” to “we have the beginning of a control-plane contract that can create and activate that app deliberately”.
That is the next line worth crossing.