Skip to content
RunConcepts

Runtime concepts

The model behind everything in this tab: how a System’s declared shape becomes Kubernetes workloads, what a release actually names, what the GitOps repository contains, and why nothing touches a cluster except through it. Read this page before the Deploy section; every page there assumes it.

The build side ends with a System host: the .NET project that declares which Components exist, which Resources join them, and which Ports and Services sit at the System’s edges (The system host). The host’s graph verb prints that declaration as interchange JSON of kind SystemTopology (topology.intropy.io/v1). This document is the contract between the two halves of Intropy: the deployment tooling consumes it, and nothing else from the source tree.

{
"apiVersion": "topology.intropy.io/v1",
"kind": "SystemTopology",
"system": "order-flow",
"components": [
{
"name": "order-extractor",
"kind": "extractor",
"publishes": [{ "pubsub": "pubsub", "topic": "orders" }],
"ports": [{ "port": "order-extractor-source", "direction": "in" }],
"uses": ["idempotency-service", "business-incident-service"]
}
]
}

intropy manifests inspect derives the deployment model from that topology plus the scaffold records each component carries in .intropy/scaffold.json. Every component maps to a workload kind: extractors run as CronJobs (wake, pull, publish, exit), while loaders and other Components run as long-lived Deployments. Each workload gets a Dapr sidecar through pod annotations, and the System’s Topic and Port Resources materialize as Dapr components:

components
order-extractor extractor cronjob
order-loader loader deployment
ports
order-extractor-source external system not declared
order-loader-destination external system not declared

Note what the port rows do not say. The topology names a port; it never decides what the name resolves to. The adapter’s binding type, address, and credentials are environment-owned deployment configuration, which is why the same System runs against drop folders on a laptop and SFTP endpoints in production without a rebuild. See intropy manifests for the command surface.

A release gives the images CI built for one source commit a durable version. intropy release create order-extractor --version 1.4.2 publishes an immutable OCI release manifest to the registry, beside the component’s images, recording the version, the source commit, the exact image digests, and notes generated from the commits since the previous release. An annotated git tag (order-extractor/v1.4.2) is pushed alongside it, but the OCI manifest is the release.

Publishing a release changes no environment. Whatever each environment was running, it still is. That split (naming bits versus shipping them) is what the rest of the model leans on: a version always resolves the same digests, so deploying 1.4.2 next week ships exactly what 1.4.2 meant today, and rolling back is pinning an older version rather than rebuilding an older commit. Releases covers the workflow.

One Git repository declares what every environment runs. A deploy.yaml at its root marks it as deployable and states the registry, the ArgoCD endpoint, and the environment graph:

schemaVersion: 1
registry: harbor.intropy.io
argocd:
server: argocd.intropy.io
appNamespace: customer-fluxia
environments:
dev: { sync: auto }
staging: { sync: auto, promotesFrom: [dev] }
prod: { sync: manual, promotesFrom: [staging], requireSourceHealthy: true }

The environments block is a graph, not a list. sync: auto environments are reconciled by ArgoCD as soon as a commit lands; a sync: manual environment records intent and waits for a person to apply it. promotesFrom declares the legal promotion edges, and requireSourceHealthy demands the source environment prove it ran the bits before they move on. Promote and sync walks through the semantics.

Each component lives at domains/<domain>/<system>/<component>/, with a component.yaml beside a kustomize base/ and one overlay per environment:

schemaVersion: 1
name: order-extractor
sourcePaths: [integrations/domains/orders/order-flow/order-extractor/]
images:
- name: harbor.intropy.io/integrations/order-extractor
environments: [dev, staging, prod]

These are ordinary, editable files owned by the GitOps maintainers. The CLI creates missing ones on a review branch when a System is onboarded, and edits exactly one line of an overlay when a deployment happens; everything else is normal, reviewed Git work. GitOps repository covers the setup.

An environment is nothing more than the set of image digests its overlays pin, plus the configuration around them. ArgoCD continuously reconciles each cluster toward what the repository declares, so the repository is the deployment state: deploying is a commit, the Git history is the deployment history, and rollback is pinning an older release.

intropy deploy respects that boundary strictly. It edits the repository and asks ArgoCD questions; it never runs kubectl, and nothing it does reaches a cluster except by ArgoCD reconciling a commit. Promotion copies digests verbatim from one overlay to another rather than resolving anything, which is what makes “prod runs the bytes staging tested” a checkable fact: deploy status prints the ladder and says whether every environment runs the same digests.

Alongside the digest, each overlay carries two annotations: deploy.internal/source-commit (which commit produced these bits) and deploy.internal/release (which release they came from, when they came from one). They exist so that status and promote can answer “what is this environment running” from the repository alone.