b.basis.no

INTERNAL TECHNICAL WALKTHROUGH

Inside the platform — a guided tour of the stack.

First the shape of a customer tenant. Then we follow one change all the way through — from a developer's laptop and a git push to an integration running in production.

local development CI Argo CD runtime prod
Apache Camel riding a Kubernetes container raft with Argo CD and the runtime logos — the platform mascot
Internal Walkthrough — June 2026
b.AGENDA

What we'll cover

b.ARCHITECTURE · GIT STRUCTURE
Git repository structure
b.ARCHITECTURE · THE CUSTOMER TENANT
Customer tenant — clusters and components
b.THE MENTAL MODEL

Follow one change from local development to prod

Local devcode & push
CIbuild · scan
CDArgo CD
RuntimeKubernetes
Promotiondev→test→prod

We'll dive into each link, then come back to this map. Next: local development

b.STEP 1 · LOCAL DEVELOPMENT

Build and test on your laptop, then push

  • Scaffold from a template repo (Camel Quarkus or .NET)
  • Write the route — real code in your own repo
  • Run & test locally — fast inner loop
  • git push to main → triggers CI
same

Two runtimes, one workflow. The platform doesn't care which language — it cares about the contract.

./mvnw quarkus:dev
Quarkus started in 1.4s · Listening on :8080
camel routes: order-to-partner (Started)
./mvnw test
BUILD SUCCESS — 42 passed
git commit -m "feat: order-to-partner mapping"
git push origin main
→ triggers CI in the integration repo
 
dotnet run
Now listening on :8080 · Camel/.NET host
runtime unit: stock-query (Started)
dotnet test
Passed! — 18 tests
git commit -m "feat: stock-query endpoint"
git push origin main
→ same contract, same pipeline
 
click a tab or press 1 / 2 — same workflow, two runtimes
b.WHERE WE ARE
Local devcode & push
CIbuild · scan
CDArgo CD
RuntimeKubernetes
Promotiondev→test→prod

The push landed. Next: continuous integration

b.CI 1/3 · SHARED WORKFLOWS

CI runs from one shared set of workflows

CI = on every change, automatically build, test, and package. A PR on a feature branch runs build + test for fast feedback; a merge to main also builds the image and bumps the catalog. The logic lives in one shared place.

integration-platform-shared/.github/workflows
java-ci · dotnet-ci
build & test — runs on PRs and main
container-build
build image, push to Harbor, output digest
catalog-promote
update the catalog with the new digest
why

One change to the shared workflow updates CI for every integration repo.

build

The test build gives fast PR feedback; container-build then produces the final, scanned image that ships.

integration repo · .github/workflows/release.yml
on: { push: { branches: [main] } }
jobs:
  build:
    uses: basis-no/integration-platform-shared/
      .github/workflows/container-build.yml@main
  promote:
    needs: build
    uses: …/catalog-promote.yml@main
    with: { image-digest: ${{ needs.build… }} }
# a few lines per repo — the logic lives in shared
b.CI 2/3 · BUILD & PUSH

The runner builds and pushes a digest; Harbor scans on push

self-hosted runner · nonprod · egress via Squid
# container-build.yml on the build runner
./mvnw -q package         21s
docker build --build-arg HTTPS_PROXY=… 34s
push harbor.cust/nonprod/order-to-partner
digest sha256:9f3a7c4e…
# Harbor scans the pushed image (Trivy)
↳ scan  0 critical · 0 high
 
net

Runners reach the internet only through Squid — proxy args are passed into the Docker build. No Docker-in-Docker.

safe

The build runner has no kubeconfig. It can't touch a cluster — it only produces an artifact.

scan

Harbor scans on push (Trivy is built in). The image lands first, then gets scanned in the registry.

runners

Today self-hosted VMs per customer; we're exploring ephemeral Kubernetes runners spun up per job.

b.CI 3/3 · UPDATE THE CATALOG
CI updates the catalog — app-repo CI opens a PR that bumps the digest; the catalog repo's Action validates the JSON schema before merge
b.WHERE WE ARE
Local devcode & push
CIbuild · scan
CDArgo CD
RuntimeKubernetes
Promotiondev→test→prod

The catalog now says what should run. Next: how it gets deployed

b.STEP 3 · WHY A CATALOG

Three ways to get code onto a cluster

✕ push-based CD

CI runs kubectl / helm straight at the cluster.

  • CI needs cluster credentials
  • Needs network opening from runner → cluster
  • Manual changes drift from Git
  • Hard across many repos
~ Argo auto-discovers repos

Each app repo declares its own deploy; Argo scans them.

  • No single release truth
  • Every repo reinvents deploy
  • Governance scattered
✓ one catalog repo

One repo holds desired state for all integrations.

  • Single, reviewed source of truth
  • App repos = code; catalog = releases
  • Argo generates apps from it

The catalog separates "what code exists" from "what should run where" — and makes the second one reviewable.

b.STEP 3 · HOW ARGO CD WORKS
Argo CD reconciles the cluster to the catalog — ApplicationSet generates one Application per IntegrationRelease, rendered through the shared integration-app Helm chart
b.STEP 3 · ARGO CD, LIVE

What it looks like in the Argo CD UI

Argo CD UI — every integration as an application, Synced & Healthy, and the live resource tree

What you see there

  • Every integration is an app — Synced & Healthy, across dev/test/prod
  • Sync status — is the cluster matching the catalog?
  • Health — are the pods actually up?
  • The resource tree — everything the chart generated (Deployment → ReplicaSet → Pods, Service, HTTPRoute, ESO → Secret)
  • History & diff — what changed; roll back by reverting the catalog
demo

We go deeper live at the end — drilling into one integration's tree and watching it self-heal.

b.WHERE WE ARE
Local devcode & push
CIbuild · scan
CDArgo CD
RuntimeKubernetes
Promotiondev→test→prod

Argo CD synced it. Next: what it looks like running in the cluster

b.STEP 4 · THE REQUEST PATH
The request path — Traefik matches the host + basePath and strips the prefix to the app pod; the pod's egress goes to in-cluster data, internal systems like SFTP/SAP, or the internet via a forward proxy
b.STEP 4 · SECRETS & VAULT
Secrets — ESO in the workload cluster authenticates to OpenBao (Vault) with a JWT; a policy per ServiceAccount decides which paths it can read
b.STEP 4 · OBSERVABILITY
Observability — each workload cluster runs its own Alloy collector feeding local Loki (logs) and Prometheus (metrics); the central Grafana in management queries each cluster as a proxy datasource, never remote-write
b.WHERE WE ARE
Local devcode & push
CIbuild · scan
CDArgo CD
RuntimeKubernetes
Promotiondev→test→prod

It runs in dev. Next: moving it to test and prod

b.STEP 5 · PROMOTION

Promotion: copy the same digest, dev → test → prod

Promotion — the same digest copied dev → test → prod, each step a catalog pull request
PR: promote order-to-partner · dev → test
# environments/test/integrations/order-to-partner.yaml
  image:
    repository: harbor.cust/nonprod/order-to-partner
-    digest: sha256:1c0ffee…
+    digest: sha256:9f3a7c4e…
  revision: "1.4.2"
# the exact dev digest — reviewed → merge → Argo syncs test
b.THE WHOLE JOURNEY

From a laptop to production

Local devcode & push
CIbuild · scan
CDArgo CD
RuntimeKubernetes
Promotiondev→test→prod

Plain code in Git · promotion is a reviewed change · the cluster converges. Now — the layer that makes it friendly.

b.THE EXPERIENCE LAYER

The dashboard sits on top of all of it

Integration platform dashboard — overview
state

Desired-state actions — onboard, promote, start/stop — become a catalog commit or PR. Argo CD does the rest.

run

Runtime actions — resend, pause/resume — go through a Cluster-agent in each cluster. Direct, but audited.

see

One view across dev / test / prod: health, messages, logs, metrics — the friendly face over Argo CD, the catalog, Harbor and the runtime.

Live demo: a change from push to running, promoted and operated — all from here.

b.THE EXPERIENCE LAYER · UNDER THE HOOD

How the dashboard is built — and where it's going

stack · one container in the management cluster
frontend
React 19 · Vite · TypeScript · Tailwind · Recharts
backend
FastAPI (Python) — the dashboard API
deploy
single image · Helm chart · in the management cluster
what an operator does · config, never data
reads
desired state (catalog) · actual state (Argo CD) · Prometheus / Loki / Grafana
writes
Git PRs to the catalog — create an integration repo, edit a spec, or pin a new image from Harbor
cluster-agent · one per integration cluster
transport
outbound-only — pushes heartbeat/status, polls a command queue
runtime
a small Rust binary
scope
reads Argo CD & calls admin APIs locally — not a remote kubectl
next

Roadmap: live updates to the browser via SSE / WebSocket (polling today) · a runtime command queue for pause · resume · resend, fully audited.

Reads desired & actual state and writes config back as Git PRs — one pane of glass, never in the data path.

b.WHERE WE'RE GOING

Thanks

  • Next runtime: prove the .NET template against the same contract
  • Runtime adapter: a framework-specific Camel / .NET adapter for safe message handling and database writes — idempotency and resend
  • CI as a feature: managed, autoscaling runners (ARC / GARM)
  • Infra automation: look into automating deployment of the infra stack
One platform, every integration — the integration platform overview
Opening