Use cases

What runs on Vennir, taken from the samples you can run.

Every use case here is a sample in the repository, with a link to it, or a way of ordering the platform is built for. In each sample one team owns every product; in your catalog, each product belongs to the team that owns that work, and the teams that order it are others.

The pattern

A platform team offers. Other teams order. Neither hands over a key.

This is what Vennir is built for. The team that knows a cloud, a database or a ticketing system publishes what it does as products, with its own identity and its own secrets. Every other team orders from the catalog, within the limits the owning team set.

The owning team

Publishes, and sets the limits

  • Which teams may run each action shareWith
  • Where each team may aim it allowedTargets
  • Whose runs wait for its maintainers approval
  • What its errors mean errors, help
Each install

Checks, twice

  • Whether the product is ready here
  • Inputs and outputs against their schemas
  • A target against the owning team's rules
  • Identity, secrets and image, again in the cluster
The ordering team

Orders, and sees its runs

  • From the Catalog, a cart, or a template's form
  • Or from a pipeline, a schedule or a bot
  • Follows, cancels and retries its own runs
  • Never sees the owning team's secrets
samples/gcp/team.yaml abridged
kind: Team
name: gcp
help:
  chat: "#gcp-team-help"               # where people ask when a step fails
allowedTargets:
  - teams: ["*"]
    gcp.project: ["sandbox-*"]          # any team, in sandbox projects
  - teams: ["*"]
    gcp.project: ["shared-*"]
    approval: true                   # shared projects, once a gcp maintainer approves
samples/gcp

A new service on Google Cloud.

A project, an image built from source, a Cloud Run service, and a Cloud SQL database for it. Every action looks before it creates, so a retried step is harmless.

dags/gcp-hello-world-dag.yaml · three steps · team gcp
  1. project.create gcpas gcp-project Finds the project, or creates it under a folder and links billing. projectId →
  2. build-image.create gcpas gcp-build-image Builds an image with Cloud Build from a source archive in GCS, unless it exists. imageUri →
  3. app-hosting.create gcpas gcp-app-hosting Deploys the image to Cloud Run, or returns the existing service's URL. serviceUrl
  4. cloud-sql.create gcpas gcp-cloud-sqloptional A Cloud SQL instance; the cart suggests it for app-hosting's database input. connectionName → app-hosting
Who it's for
App teams who need somewhere to run a service, without a Google Cloud role of their own.
Who owns which step
The gcp team owns all four. Each runs as its own ServiceAccount, granted only what it does: project can't touch Cloud Run, app-hosting can't make projects.
Credentials
None stored: GKE Workload Identity, optionally impersonating a second account named in the team's gcp-target secret.
Proven
On GKE Autopilot, 2026-10-25: a project, a Cloud Run service and a Cloud SQL instance made and deleted. Its readiness checks ran there in the paid proof run of 2026-10-31.
The gcp sample on GitHub Its DAG
samples/aws

Storage, an app and a database on AWS.

An S3 bucket with public access blocked, an App Runner service told its name, and an encrypted RDS for PostgreSQL instance whose password no step ever sees.

dags/aws-hello-world-dag.yaml · two steps · team aws
s3-bucket.createas aws-s3-bucket Finds the bucket, or creates it. A name another account owns fails as BUCKET_NAME_TAKEN.
bucketName → environment.BUCKET
app-runner.createas aws-app-runner Deploys an image as an App Runner service and waits for it to run, or returns the existing one's URL.
rds-postgres.createas aws-rds-postgres RDS generates the password and keeps it in Secrets Manager; the step outputs only that secret's ARN.
Who it's for
Teams on AWS who need a bucket, a web service or a database, without an IAM role of their own.
Who owns which step
The aws team owns all three, each bound to its own IAM role with only the actions it calls.
Careful deletes
A bucket that holds objects is refused (BUCKET_NOT_EMPTY); the database keeps a final snapshot. Nothing without the vennir-made tag is deleted.
Proven
On EKS Auto Mode with Pod Identity (2026-10-19, deletes 2026-10-25). Its SecretStore and readiness checks aren't proven yet.
The aws sample on GitHub Its DAG
API products

A backend your team runs, offered to other teams as an API.

The owning team adds an api.yaml and its OpenAPI file; calling teams sign in as they do at the console. The gateway forwards only what the spec describes and signs in to the backend itself, per request.

local/greetingsno cloud

A Service in the team's namespace

No backend credential: it checks the gateway's signed Vennir-Caller on every request, and says which team called. Shared with every team, 60 a minute.

See the sample →
gcp/hello-worldgoogleIdToken

The Cloud Run service app-hosting deployed

The service refuses anyone unsigned. The gateway federates its own ServiceAccount and presents a Google ID token; only GET / is forwarded.

See the sample →
aws/ordersawsSigV4

A Lambda function URL that requires IAM

Each request signed with SigV4 as a role the gateway assumes with its own ServiceAccount's token. Shared with the web team only, at 600 a minute.

See the sample →

Who calls: the teams in shareWith, each with its own rate. The local one runs on kind; the cloud two are still to be proven in their billed run (TODO.md).

samples/local

One product, five languages, no cloud.

The same small text product in Python, TypeScript, Go, PowerShell and Rust. It proves an install end to end on your laptop, and it's the starter a new team copies for the language it uses.

five-languages · each step takes the previous step's text Succeeded
  1. title-casePython Hello From Five Languages
  2. reverseTypeScript segaugnaL eviF morF olleH
  3. slugGo segaugnal-evif-morf-olleh
  4. upper-casePowerShell SEGAUGNAL-EVIF-MORF-OLLEH
  5. rot13Rust FRTNHTANY-RIVS-ZBES-BYYRU
input: hello from five languages
Who it's for
Anyone proving an install end to end, and a new team: vennir catalog create copies the starters for the languages it picks.
Who owns which step
The local team owns all five. They need no secrets and no ServiceAccount of their own, so they run as soon as the team is published.
Tested like it runs
Contract tests run against the built image, the request mounted at /platform/input, with no network.
Also as a template
shout-backwards chains two of them behind a one-field form, shared with every team.
The local sample on GitHub The template
samples/local/products/ticket

What a run made, kept after the run, and deleted on purpose.

A pretend ticketing system, nothing really created, that shows the whole life of a resource: preview it, make it, wire something to it, and delete it later from What runs made.

  • Preview. plan says what open would do, for Preview and for whoever approves.
  • Wiring. Put a watch alone in the cart and the order adds open for it, or offers a ticket you have.
  • Cleanup. Delete runs close or unwatch. A ticket still watched waits for an admin, unless its watches go first.
  • Capacity. maxRunning: 2, as a ticketing system that limits its calls would ask.
The ticket sample on GitHub
What runs made made for local
T-dd864760Made Rotate the staging certificate local/ticket · by ticket.open · Used by W-eb026c68 Ask an admin
W-eb026c68Deleting release-oncall on T-dd864760 local/ticket-watch · by ticket.watch · Uses T-dd864760
Once the watch is Deleted, the ticket's Delete runs close for the team it was made for.
Ordering bots

Your own storefront, ordering through a bot.

A self-service page or an event consumer places orders for your team: it runs the published templates you list for its bot, and nothing else, and hears back when each one finishes.

your storefront, placing an order ordering bot
# the samples' one template; yours will be your own
curl -X POST "$VENNIR/api/vennir.console.v1.TemplateService/RunTemplate" \
  -H "Authorization: Bearer $VENNIR_TOKEN" -H "Content-Type: application/json" \
  -d '{"team": "local", "name": "shout-backwards",
       "onBehalfOf": "[YOUR TEAM]", "requestId": "order-1042",
       "parameters": {"text": "hello world"}}'

# the same requestId again returns the run already started
# not on its list: TEMPLATE_NOT_ORDERABLE · anything else: ORDERS_ONLY

# later, posted to your callback URL
Vennir-Signature: t=<unix seconds>,v1=<hex>
{"type": "order.finished", "requestId": "order-1042",
 "template": "local/shout-backwards", "state": "SUCCEEDED", …}
Who it's for
A team that runs its own ordering page or system and wants Vennir behind it.
Who owns which step
The template's steps stay their products' teams', with their identities and approvals. The order runs for your team, under its quota.
Limits
60 orders a minute unless the install says otherwise; past it, 429 with Retry-After.
Hearing back
A signed post to an https URL under a host the install allows, retried five times. examples/order-receiver is a receiver in Go.
The order receiver on GitHub Bots and automation guide
Keyless bots

CI running templates, with nothing stored to leak.

A release pipeline runs your team's templates or submits its DAGs as a team bot that signs in with the CI job's own identity, from one repository and, if you choose, one branch.

  1. 1 · The job Asks GitHub Actions or GitLab for an ID token for this install's audience.
  2. 2 · ExchangeToken The console checks the repository and branch against the bot's card. Any other is refused.
  3. 3 · An hour as the bot A token good for one hour, with exactly what the bot may do in its team.
  4. 4 · RunTemplate Runs the template; a requestId from the CI run makes a retried job the same run.
.gitlab-ci.yml Keyless
deploy:
  id_tokens:
    VENNIR_ID_TOKEN:
      aud: [THE AUDIENCE THE BOT'S CARD SHOWS]
  script:
    - export VENNIR_TOKEN=$(jq -n --arg t "$VENNIR_ID_TOKEN" '{idToken: $t}' | curl -s -X POST $VENNIR/api/vennir.console.v1.AuthService/ExchangeToken -H 'Content-Type: application/json' -d @- | jq -r .token)
    - # then RunTemplate or SubmitExecution, as the bot, for an hour

A bot is always made with a token; once CI sign-in works, revoke it and the card shows Keyless. Which CIs an install accepts is its setting (GitHub Actions and gitlab.com by default). The guide.

Start from a sample. Make it your team's.

A new catalog repository starts from catalog-template, with the samples to copy from. Adding a product needs no change to Vennir itself.

Get started The catalog template