foundry

Foundry's operational spine is starting to show

  • foundry
  • ki-console
  • provisioning
  • kubernetes
  • openrs
  • ors-appliance
  • dcb

The last Foundry post showed the adoption loop becoming real.

An authenticated Console user could request an ILL workspace, Console could create a durable Service, a Foundry-side bridge could claim the provisioning command, Loom could create the workspace and activate ILL, and the local runtime could prove the resulting application through the browser.

That was an important moment because it moved Foundry out of the purely developer-runtime question.

The next question was sharper:

How do we actually provision a production-shaped Foundry system and connect it to a wider onboarding, trial, and service-management flow?

That is the work this short follow-up bookends.

From local proof to operational spine

The work after the Console adoption-loop proof was about the operational spine underneath that proof.

If Console is going to let someone request a trial, create a service, or activate a hosted workspace, Foundry has to be able to receive that intent through a clear provider boundary. It has to know what installation it belongs to, how trust is established, how commands are claimed, how reconciliation starts, how substrate work is reported, and when a workspace is ready enough to show back to a user.

That is the difference between a promising local demo and something that can become a real hosted or self-hosted operating model.

This slice tightened that spine.

Loom now owns more of the upstream command intake shape. Console is not treated as a hidden script runner or a special local shortcut. It is an upstream system asking a Foundry installation to perform lifecycle work. That keeps the separation clean: Console owns product, service, onboarding, and trial flow; Loom owns Foundry workspace intent, capability activation, reconciliation intent, and runtime readback.

That boundary matters because Foundry should not become the product console, and Console should not become the Foundry executor.

sequenceDiagram
participant User as Console user
participant Console as KI Console
participant Loom as Loom lifecycle API
participant Executor as Substrate executor
participant Runtime as Foundry runtime

User->>Console: request trial service
Console->>Loom: provision workspace + capabilities
Loom->>Loom: persist intent and create reconciliation run
Executor->>Loom: claim next reconciliation step
Executor->>Runtime: materialise substrate side effects
Executor->>Loom: report sanitized step outcome
Loom->>Console: expose service/runtime readback
Console->>User: show provisioning state and access URL

The important shift is that Console expresses service intent, while Loom and the executor boundary own Foundry lifecycle and substrate work.

The command shape is intentionally boring. The spice is in what it refuses to contain: no Docker paths, no Kubernetes object templates, no private credentials, and no module-specific provisioning script.

{
  "command": "service.provision",
  "providerTarget": "foundry-hosted-test",
  "service": {
    "slug": "park-hill-ill-trial",
    "displayName": "Park Hill ILL Trial"
  },
  "desiredState": {
    "workspaceId": "park-hill-ill-trial",
    "requestedCapabilities": ["ill"]
  },
  "correlation": {
    "serviceId": "svc_01hy...",
    "offeringRef": "foundry-ill-workspace-local"
  }
}

Bootstrapping trust

The other part of the question is installation.

A production-shaped Foundry system cannot depend on a long bespoke checklist of manual secrets, admin tokens, and one-off Kubernetes commands. There will always be operator details, but the target experience needs to be closer to:

  1. Console creates a pending Foundry installation or zone enrollment.
  2. The operator runs one generated command for the chosen substrate.
  3. Foundry installs itself, establishes trust, and registers its return path.
  4. Console can see that this installation is now able to receive provisioning work.
sequenceDiagram
participant Admin as Console admin
participant Console as KI Console
participant Installer as Foundry installer
participant K8s as Kubernetes substrate
participant Loom as Loom

Admin->>Console: create bootstrap enrollment
Console-->>Admin: generated install command
Admin->>Installer: run command with one-time token
Installer->>K8s: install or upgrade Helm release
Installer->>Loom: seed provider private key into secret store
Loom->>Console: redeem enrollment and register public key
Console->>Loom: send future provisioning commands via trusted target

Bootstrap enrollment turns the hosted setup question into a one-time trust exchange instead of a bundle of permanent shared secrets.

The current implementation is deliberately thin, but it now points in that direction.

Foundry has a documented BootstrapEnrollment model. Loom has a database-backed secret-store surface for provider trust material. The Kubernetes bootstrap path can redeem a one-time Console enrollment without handing the installer a broad Console platform-admin token.

That is the first meaningful reduction of the trust problem into something explicit and evolvable.

{
  "kind": "BootstrapEnrollment",
  "id": "be_01hz...",
  "target": {
    "providerTarget": "foundry-hosted-test",
    "substrate": "kubernetes",
    "zone": "hosted-trial"
  },
  "trust": {
    "tokenUse": "one-time",
    "installerRegistersPublicKey": true,
    "privateKeyStorage": "loom-secret-store"
  },
  "status": "pending"
}

The next Foundry slices need to keep pushing this into a product-grade shape: Console should be able to create, revoke, and inspect bootstrap enrollments; the install command should be generated from the selected substrate and environment; trust rotation should become a normal operation; and install status should be visible without reading a Kubernetes runbook.

Capability materialisation without hard-coding ILL

The hosted trial target is ILL, but the kernel must not become an ILL appliance.

That distinction shaped a lot of the work.

Loom now exposes a first-class reconciliation action for ensure-capability-backend-service. That sounds small, but it is important. It means an activated capability can produce descriptor-derived backend service intent, and a substrate executor can materialise that intent without Loom, Helm, Envoy, or foundryctl learning special rules for mod-ill.

{
  "action": "ensure-capability-backend-service",
  "workspace": "park-hill-ill-trial",
  "capability": "ill",
  "versionRef": "ill-2.1.3",
  "target": {
    "serviceId": "mod-ill",
    "image": "docker.libsdev.k-int.com/knowledgeintegration/mod-ill:2.1.3",
    "healthPath": "/admin/health",
    "routes": ["/ill", "/_/tenant"]
  }
}

ILL is the fixture. The pattern is the product.

The local Docker path now consumes Loom’s action planning for backend service and tenant work before performing the host-side Compose and HTTP mechanics. The Kubernetes path gained an early hosted executor that can claim Loom reconciliation steps and create descriptor-derived backend Deployment and Service resources.

sequenceDiagram
participant Loom as Loom reconciliation
participant Executor as Hosted executor
participant API as Kubernetes API
participant Backend as Capability backend
participant Envoy as Data plane

Loom->>Executor: claim ensure-capability-backend-service
Executor->>Loom: read descriptor-derived target
Executor->>API: create or verify Deployment and Service
API-->>Executor: backend service available
Executor->>Backend: readiness check
Executor->>Loom: complete backend-service step
Loom->>Executor: later claim tenant and route steps
Executor->>Envoy: publish descriptor-derived routes

The executor should materialise generic capability intent. ILL is useful test data, not a reason to teach the kernel about ILL.

That gives the hosted path a real next foothold. The work ahead is clear: tenant provisioning, route publication, identity bootstrap, runtime verification, and terminal Console readback need to become the same kind of descriptor-driven executor work.

The positive part is that those are now named pieces of the system, not vague deployment magic.

The Kubernetes shape is becoming discussable

Kubernetes is still early in Foundry, but it is no longer just a Helm skeleton.

The chart has the baseline substrate shape: Loom, platform services, database wiring, Envoy, ingress, and executor plumbing. The hosted executor can claim work. Workspace shell routing through Envoy has been proved at the install level. Capability backend service materialisation has a first generic implementation.

The route publication contract was also tightened: a rendered ConfigMap or a running Envoy pod is not enough. Foundry should only call route publication complete when an actual request through the selected data plane proves the workspace or capability path works.

That is the right bar. It keeps the project honest without confusing intermediate artifacts with a working runtime.

The next Kubernetes Foundry iteration needs to turn that bar into the normal hosted proof path.

Why pause here?

This feels like the right place to bookend the Foundry slice for now.

Foundry has moved from “can we run a real module outside the old platform shape?” through “can a developer work on one module without understanding the whole platform?” into “can a Console-driven onboarding flow request a real service and have Foundry begin to provision it through a production-shaped boundary?”

There is more to do, but the next questions are now much better formed.

A different challenge has become the more urgent lab question.

In the OpenRS / ORS-Appliance arena, the question is whether we can provide an appliance that fills the long tail of systems we may want to connect with DCB in an open and standards-compliant way.

That is Foundry-adjacent in a very direct sense because the obvious follow-up question is:

Can ORS-Appliance run as just another Foundry app?

If Foundry is the runtime and operational model for packaging, activating, hosting, and sustaining specialist library capabilities, then ORS-Appliance is a good test of that ambition. It is not simply another vertical module like ILL or Licenses, but it has many of the same pressures: onboarding, configuration, identity, routing, service boundaries, deployment shape, operational visibility, and a need to work across diverse institutional contexts.

ORS-Appliance also stretches the question in a useful way. It asks whether Foundry can support not only user-facing specialist applications, but also integration appliances that help libraries connect local systems to wider networks such as DCB without each system needing bespoke platform work.

That makes the pivot less a departure from Foundry than a test of one of Foundry’s central claims.

Can we take something that serves a real operational need, define its capability boundary, make it deployable, make it configurable, expose the right routes and management surfaces, and eventually make it available through the same onboarding and trial machinery we have been shaping for Foundry?

That question has a very practical descriptor-shaped version:

{
  "kind": "foundry-capability",
  "id": "ors-appliance",
  "role": "integration-appliance",
  "routes": {
    "admin": "/ors",
    "standardsApi": "/ors/api"
  },
  "connects": ["local-ils", "dcb-network"],
  "requires": {
    "configuration": "institution-specific",
    "observability": true,
    "standardsCompliance": true
  }
}

That is not an implementation claim yet. It is the next research question made concrete enough to test.

That is where the lab is turning next.

We will come back to the Foundry-specific questions with sharper evidence: hosted route publication, identity bootstrap, tenant provisioning, terminal Console readback, trust rotation, and the production trial path. For now, the important thing is that the operational spine is no longer just an architectural aspiration. It has started to take shape in code, and ORS-Appliance gives us a timely way to test what that spine can carry.