Academy · Chapter 10 of 11 · ~50 minutes

Models, costs, operations.

A coding agent is only as economical as the decisions around it: which model for which task, how much context per run, how often runs are repeated and who sets which limits. This chapter explains the basics of tokens, caching and budgets and shows how the factory governs model choice, cost reporting, tenants, roles and operating modes.

~50 min Model routing · Costs · Budgets Tenants · Roles · Operations

Learning goals

After this chapter you can:

  • Choose models by task: explain why planning, building and reviewing deserve different model classes.
  • Understand tokens: distinguish input, output and cache tokens and estimate where in an agent run the costs arise.
  • Apply cost levers: keep context small, avoid repetitions, choose the right model class.
  • Follow the factory’s model choice: explain the precedence override → team → role default → CLI choice and find it again in the why-trace.
  • Read costs correctly: distinguish billed costs from estimates in subscription mode.
  • Set limits: use budgets, hard caps and token limits deliberately.
  • Understand operations: tell tenants, roles, SSO, operating modes, license tiers and deployment forms apart.

10.1 A model is not just a model: choosing by task

In the first chapters you learned that a coding agent consists of a language model, tools and a loop. The language model is the most interchangeable and at the same time the most expensive component. Providers almost always offer several model classes: large, slow, expensive models with a lot of judgment; mid-sized models as workhorses; small, fast, cheap models for simple, well-defined tasks. Names, versions and prices change on a monthly basis. The principle behind them stays stable.

The principle is: Not every task needs the strongest model. In everyday software work with agents, three task types can be distinguished that make very different demands.

Planning

When planning, the agent breaks a goal into work packages, weighs architecture options, and identifies dependencies and risks. Mistakes in this phase are expensive because they carry through all subsequent steps: a wrong cut produces ten wrong build runs. At the same time, the output of a planning run is comparatively short — a few Markdown files instead of hundreds of lines of code. A strong model pays off here: the extra cost per token applies to few tokens and avoids expensive downstream errors.

Building

When building, the agent implements a well-defined plan: creating files, writing code, adding tests, running the build, fixing errors. This work is extensive but mostly more mechanical. A solid mid-sized model usually handles it reliably if the task is precise — which is exactly what the spec and plan from chapters 4 and 5 ensure. This is where most of the token volume arises; the model class therefore has a strong effect on total costs.

Reviewing

When reviewing, a reviewer reads a diff and reports findings. Reviews are frequent, often run in parallel and work with limited context. A small, fast model is often sufficient here, especially since a good review process does not rely on an LLM alone anyway but adds rule-based checks (tests, static analysis, coverage checks) alongside it. Where a review is very demanding — a security assessment, for example — a stronger model can make sense.

Rule of thumb: Put the most expensive model where a mistake multiplies (planning, architecture, tricky reviews). Put the cheapest where many small, easily verifiable tasks occur. The workhorse goes in between.

Model choice is a configuration question, not a code question

Because models become outdated quickly, no model name should be hard-wired into tools, scripts or prompts. If you configure model choice centrally, you can switch in one place when a new model arrives — and know afterwards which run was produced with which model. This traceability is not just tidiness: when a result stands out, “which model was that?” is one of the first questions.

In the factory

Model choice precedence and capability routing

The factory separates model choice for planning and implementation via so-called capability routing: the settings run.routing.plan-model and run.routing.build-model determine which model plan runs get and which model build runs get. This way planning can get a stronger model than mechanical implementation, without a model name being hard-wired anywhere.

For every run, the factory resolves the model in a fixed order of precedence:

RankSourceWhere the value comes from
1overrideRouting override run.routing.plan-model or run.routing.build-model
2teamThe team’s preferred model: preferredModel of the developer agent, otherwise of the first agent with a model
3rollen-defaultRole default from the price table — only for the claude adapter
4adapter-defaultNo --model flag; the CLI chooses itself
Model selection precedence: 1 routing override, 2 team preference, 3 role default, 4 adapter default, each if configured; the first applicable source wins. Model selection precedence: 1 routing override, 2 team preference, 3 role default, 4 adapter default, each if configured; the first applicable source wins.

Open full-size graphicOpen full-size graphic

According to the administration manual (as of v0.38.0), the role defaults for Claude Code are: Plan → Opus (claude-opus-5-5), Build → Sonnet (claude-sonnet-5-5); reviews run with Haiku by default (claude-haiku-5-5, configurable via softwarefabrik.review.claudecode.model; empty means no --model flag). Because of its price, Fable (claude-fable-5-1) is never a default and can only be selected via the team setting or an override. The specific IDs change with new model generations — the administration manual of the installed version is always authoritative.

Other adapters (Aider, Bedrock/Vertex/Azure, Local-LLM, Kimi) deliberately do not receive the Claude role default, because they pass --model unchanged to their own CLI. For Codex, Kimi, Gemini and Aider there is instead a default model per adapter under execution.<adapter>.model. This setting does not exist for Claude Code — since v0.33.0, its model comes from routing, team or role default.

Traceable in the why-trace

Every resolution is written to the signed audit chain as RUN_MODELL_AUFGELOEST, with the field quelle=override|team|rollen-default|adapter-default. On the /runs/{id}/trace page you therefore see not only which model ran, but also why it was this one: whether someone forced it via override, whether it came from the team or whether the role default applied.

How to configure it

  1. Team level (ADMIN only): Under /agents, open an agent definition (e.g. the developer) and enter a preferred model. Via /teams, you assemble the team you select for the run.
  2. Routing level: Under Settings, set run.routing.plan-model and/or run.routing.build-model if you want to force a fixed choice for all runs (or, via scope, for one project).
  3. Check: After the run, look in the why-trace to see which quelle applied.

10.2 Tokens: the currency of agents

Language models compute in tokens. A token is a piece of text — roughly a word fragment; in German a word often takes more tokens than in English, and source code with many special characters is also token-heavy. With API usage, billing is typically split into three kinds:

Token typeWhat it isTypical share in agent runs
InputEverything the model reads: system instruction, project context, tool definitions, prior conversation, file contents, tool resultsVery high — every round of the agent loop sends the growing conversation again
OutputWhat the model generates: text, code, tool callsMuch smaller, but usually more expensive per token than input
CacheReused input portions (reading from the cache) or storing them in the cache for the first time (writing)With long, unchanging prefixes, often the bulk of the input
Three cost drivers: input tokens (prompt, files, logs), output tokens (text, code, tool calls) and cache (reused context); no prices or proportions implied. Three cost drivers: input tokens (prompt, files, logs), output tokens (text, code, tool calls) and cache (reused context); no prices or proportions implied.

Open full-size graphicOpen full-size graphic

Why agent runs consume so much input

Remember the agent loop from chapter 2: the model thinks, calls a tool, gets the result, thinks further. In every round, the entire context so far is processed again — the instructions, the project context, all previous tool calls and their results. A run with forty tool calls therefore processes the beginning of the context roughly forty times. If the agent reads in a large log file or a long test report along the way, that text travels along into all following rounds.

This leads to an important insight: The cost of an agent run does not grow linearly with the size of the task, but rather with the number of rounds times the context size. An unclear task that forces the agent to search and experiment is therefore doubly expensive: more rounds and more context.

Prompt caching

Many providers offer prompt caching: an unchanging beginning of the context (prefix) is stored the first time and reused more cheaply in subsequent requests. This fits agents well, because instructions, tool definitions and project context stay identical from round to round. The details differ by provider (cache lifetime, minimum size, surcharge for writing, discount for reading); in general:

  • Writing to the cache usually costs somewhat more than normal input, reading costs considerably less.
  • Caching only works on a stable prefix. If you keep putting changing content at the beginning of the context (timestamps, random orderings), you prevent cache hits.
  • Agent CLIs usually use caching automatically. You influence it mainly indirectly: through stable project files and instructions.

Subscription instead of a token bill

Besides per-token API billing, providers of coding agents also offer subscriptions in which runs count against usage limits rather than a bill. The terms change frequently and are bound to the respective provider’s terms of use — in particular, who a personal subscription is intended for and for what purpose. For the factory, the current state is described in the user manual and on the subscription setup page.

In the factory

Recording, reporting and correctly reading costs

For each run, the factory records the tokens reported by the adapter and values them using a model price table. It lives in application.yml under softwarefabrik.models with input, output and cached prices per million tokens. Checking it against the official price pages is a fixed item in the release routine; the euro values are derived via a fixed approximation factor, not a daily exchange rate.

What goes into the valuation

  • Input, output and cache-read tokens per model.
  • Cache-write tokens (recorded since v0.34.0): they are not included in the input tokens and are valued at 1.25 times the input price.
  • The CLI’s own cost estimate is shown in the why-trace as a cross-check — it is not a bill.
  • If several models run within one Claude run (subagents, for example), the tokens of all models count; as a known limitation, the price of the most expensive model is applied to all tokens.

Three special cases you need to know

CaseReported asMeaning
Unknown model (no entry in the price table)€0Deliberately conservative: better no value than an invented one. A €0 run with many tokens is a hint to check the table.
Flat-rate models (k3, kimi-for-coding)€0With a flat rate there are no token costs; the view shows marginal costs, not license costs.
Claude subscription modeEuro value with labelValued like API runs, but labeled “estimate (API rate), not billed”.

The last point is the most important reading note: in Claude subscription mode, runs count against your subscription’s usage limits; no separate API bill arises. The euro values the factory still reports represent the generated load at the API rate. They still count in consumption and therefore against the budget and hard cap.

The cost views

RouteContent
/analyticsCosts per project, run, provider and in comparison, each as CSV
/mandanten/kostenConsumption per tenant (also as .csv), with a column “of which estimate (EUR)”
/mandanten/seat-kostenConsumption per seat, i.e. per triggering user (derived from run.triggered_by, also as .csv)
/runs/{id}/traceCosts of a single run alongside model, policy, approvals and gate result

In the CSV exports, the estimate column is called Davon-Schaetzung-Abo-EUR. Runs without an auth marker (e.g. with the mock adapter) and runs from versions before the marker was introduced carry no label. On the dashboard you additionally see token consumption and costs for the last 14 days.

10.3 Cost levers: what really saves

Anyone who wants to reduce agent costs often thinks of a cheaper model first. That is one lever, but rarely the biggest. The most effective levers act earlier.

Lever 1: Precise tasks

A precise goal with clear acceptance criteria drastically reduces the number of rounds. The agent has to search less, guess less and rework less. This is where the work from chapter 4 (specs and EARS) and chapter 5 (planning) pays off directly in tokens: a build run against a well-cut backlog item with bound acceptance criteria is shorter than a run with the goal “finish the order management”.

Lever 2: Keep context small and stable

  • Small: Only put into the context what the task needs. Huge log outputs, generated files or dependency directories are expensive ballast.
  • Stable: Project files, instructions and guardrails should not change with every run. This helps caching and makes results more comparable.
  • Curated: A well-maintained project memory with the most important decisions is better than a growing pile of unfiltered notes.

Lever 3: The right model class

As described in 10.1: a strong model for planning, the workhorse for building, a small model for reviews. What matters is measuring the choice, not guessing. If a cheaper build model needs twice as many correction loops, it is not cheaper in the end.

Lever 4: No blind repetitions

A failed run that is restarted unchanged costs the same again — with a similar chance of success. A repetition is only worthwhile if new information is added: compiler output, test failures, a reviewer finding, a merge conflict, a changed instruction. This is exactly the principle the factory implements in its correction loop (chapter 6): it feeds the build or gate feedback into the repeated run and limits the number of attempts.

Lever 5: Small steps

A large run that fails on a trifle after an hour burns a lot. Several small runs, each with a verifiable result, fail more cheaply and can be corrected in a more targeted way. It is the same logic as with small pull requests — except that money is also at stake here.

Beware of automation: Features that trigger runs on their own (follow-up plan runs, routines, automatic dispatch of workflow tasks) are convenient, but generate ongoing costs. Switch them on deliberately and set budgets beforehand.

In the factory

Budgets, token limits and capacity protection

The factory offers several levels for limiting consumption. They complement each other:

MechanismLevelEffect
mandant_budgetTenant, monthly in EUREither observe-only or as a hard cap (enforce): when exceeded, no new runs are started.
budget.daily.tokens / budget.weekly.tokensSettingsToken limits per day or week with a soft threshold
Workflow budgetWorkflowApplies before the start of the next task of a parallel workflow (chapter 7)
Capacity protectionInstanceLimits the number of concurrent runs
One active run per workspaceProjectOnly one run at a time per project workspace; different projects and separate worktrees run in parallel

A known limitation: the per-seat evaluation exists (/mandanten/seat-kosten), but the hard cap only applies per tenant. If you need to limit users individually, today that requires organizational rules or separate tenants.

Recommended setup order

  1. Observe first: set a budget per tenant without enforce and collect typical runs for a week or two.
  2. Evaluate in /analytics which projects and run types drive consumption.
  3. Then activate the hard cap with a buffer and set token limits as an early warning.
  4. For cost-free practice, use the mock adapter (SOFTWAREFABRIK_EXECUTION_ADAPTER=mock): it goes through the complete run lifecycle without a real agent.

10.4 Tenants, roles and the four-eyes principle

As soon as more than one person works with agents, two questions arise: Who may do what? and Who sees what? The first is answered by a role model (RBAC, role-based access control), the second by tenant separation.

Roles: graduated permissions

Good role models for agent platforms separate at least three things: reading, executing and approving. Executing means letting agents write code — this costs money and changes repositories. Approving means taking responsibility for a result. If you do not separate these permissions, you lose the four-eyes principle: the same person commissions the agent and waves its result through.

Tenants: hard visibility boundaries

A tenant is an isolated unit — a department, a customer or a subsidiary, for example. A tenant’s data must not be visible to others, not even via guessed IDs. This is more than a convenience feature: agent runs contain source code, requirements, logs and costs, i.e. often confidential information.

Single sign-on

In companies, identity usually comes from a central identity provider (OIDC). An important security principle here: the integration must never accidentally extend access. New, automatically created users should start with minimal permissions; the actual assignment remains a deliberate administrative act.

In the factory

Roles, tenants and SSO

Role model

The factory has five roles in ascending order: VIEWER < DEVELOPER < MAINTAINER < OWNER < ADMIN.

Capabilityfrom role
ReadingVIEWER
Executing runs, creating and editing specsDEVELOPER
Approving runs, approving specs, managing integrations/secretsMAINTAINER
Tenant administrationADMIN (the OWNER level is planned but currently carries no permissions of its own)
Account management, policy-as-code, compliance profiles, attestation, exportADMIN

You manage accounts under /admin/nutzer (ADMIN only): create them, assign tenant and role, set active/inactive, reset passwords. A lockout protection prevents the last active administrator from being demoted or deactivated. With run.approval-segregation you enforce segregation of duties: whoever triggered a run may not approve it themselves.

ADMIN is not a super admin for data. Even an administrator remains tenant-scoped for projects, runs, logs and costs. Only account management and project assignment are isolation-free. If an admin cannot see other tenants’ projects, that is correct — the solution is the tenant assignment.

Tenants

Under /mandanten you create tenants and assign projects. A user belongs to exactly one tenant; without a tenant, the instance runs in single-tenant mode. Projects, runs and all derived data are tenant-scoped — access via a foreign ID fails, safeguarded by a dedicated test. Policy, audit, costs and export are separated per tenant. For maximum separation (e.g. VS-NfD), a separate instance per tenant remains the most conservative option.

SSO

OIDC login is optional and configuration-driven. Users who are created automatically at their first SSO login (just-in-time provisioning) deliberately receive the role VIEWER without a tenant. An administrator then assigns role and tenant.

Model and adapter governance on three levels

  1. Global: execution.adapter.default and the default models in the settings.
  2. Project: allowed adapters per project, maintained as the model policy on the project page (MAINTAINER and above). It is enforced when a run is created; a violation produces RUN_POLICY_DENIED.
  3. Tenant: Policy-as-code (/policy-as-code, field erlaubteAdapter, chapter 9) can restrict the allowed adapters tenant-wide. A tenant policy can only tighten the global one, never undercut it.

A run with a disallowed adapter is rejected and documented as RUN_POLICY_DENIED.

10.5 Deployment forms and operating modes

Agent platforms are operated in very different ways: from an individual on their own laptop to an isolated government installation without internet. The deployment form decides three questions:

  • How does the model come into play? Personal subscription, API key, cloud gateway or local model.
  • How many people share the instance? Roles, tenants and budgets depend on this.
  • How much network is allowed? From “everything” to “nothing” (air gap).

One point deserves special attention: Personal subscriptions are personal. A subscription intended for an individual’s use of a coding agent is not access that a team should share via a common platform. As soon as several people use an instance, the runs belong on API keys or a gateway — with clean billing and clear terms of use.

Configuration without restarts

A configuration hierarchy is helpful in everyday work: general defaults globally, deviations per user or project. That way not every project has to define everything anew, and special cases remain visible where they belong.

In the factory

Operating mode, deployment forms, license tiers and settings

Operating mode betrieb.modus

ModeIntended forEffect
EINZELPLATZ_ABOPersonal use: the subscription holder runs the factory themselves on their own machine, with their own subscription, on the unmodified CLISubscription mode (execution.<adapter>.auth-mode=subscription) possible for Claude, Codex and Kimi; a configured API key is then actively removed from the subprocess
TEAM_API_POOLSeveral people on one instanceBlocks subscription login and enforces API key mode

The factory does not check whether a key is present in TEAM_API_POOL mode. For Claude Code, ANTHROPIC_API_KEY must be set in the environment of the app process; according to the administration manual (v0.38.0), an Anthropic key stored under /integrations is displayed and validated but currently not passed on to the CLI.

Deployment forms

FormDescription
Single workstationOne person, one machine, usually subscription mode of a coding CLI; Postgres in a container, factory native
TeamSeveral users on one instance, RBAC active
Multi-tenantSeveral mutually isolated tenants on one instance
Air gapWithout network access: local-llm adapter (e.g. Ollama, vLLM, LM Studio), container sandbox with --network=none, license without back channel, PR poller off

A public SaaS offering with self-registration is not covered.

License tiers

The factory comes in three tiers with the same signed license format. Runs, agents and team features per the license model, the spec rows per the administration manual (section 13b) and SPEC-005:

CriterionCommunityProfessionalEnterprise
Runs per day101001000
Parallel agents31050
Team features, SSO, audit log——yes
Specs (spec-driven development)—yesyes
SDD governance (policy obligation, export 2.1, metrics; target state per SPEC-005)——yes

Without an active license system (softwarefabrik.license.v1.enabled=false), the respective feature flag alone decides, e.g. softwarefabrik.spec.enabled. LLM costs are not included in any license; you pay for model usage directly to the provider.

Settings

All settings follow the scope hierarchy PROJECT > USER > GLOBAL > YAML and take effect without a restart, with at most five minutes of caching; values you change via the user interface apply immediately. Every change creates an audit entry. Vendor keys are not maintained in the settings but under /integrations — AES-GCM-encrypted, with provider validation.

Monitoring and backup

  • /actuator/health (incl. secrets health), /actuator/info (version, build number), /actuator/prometheus (metrics, ADMIN only).
  • You need to back up three things: the PostgreSQL database, the workspace directory with the projects’ Git repositories, and the attestation key together with the secrets master key.
  • After every restore, run the chain verification under /attestierung: an incomplete backup shows up there as CHAIN_BREAK.

10.6 Summary

  • Choose model classes by task: strong for planning, workhorse for building, small for reviews — and measure the choice.
  • Agent costs grow with rounds times context size. Precise tasks and a small, stable context are the biggest levers.
  • Prompt caching rewards stable prefixes; cache writes cost somewhat more, reads considerably less.
  • Repeat only with new information.
  • The factory resolves the model by override → team → role default (Claude only) → CLI choice and attests the source.
  • Euro values in Claude subscription mode are estimates at the API rate, not a bill.
  • Budgets first observe-only, then as a hard cap per tenant; the seat view evaluates but does not limit.
  • Roles separate executing and approving; ADMIN is not a data super admin; SSO users start as VIEWER without a tenant.
  • Personal subscriptions belong on a single workstation; teams work in TEAM_API_POOL.

Exercise

Exercise: A cost and model concept for a team

Starting point: A team of five developers and a technical lead wants to use the factory for two products. Product A is an internal tool, product B processes customer data. The lead wants nobody to approve their own runs and the costs per product to be visible.

  1. Decide which operating mode fits and justify it in one sentence.
  2. Sketch a role concept: Who gets DEVELOPER, who MAINTAINER, who ADMIN? Which setting ensures that nobody approves their own run?
  3. Decide whether you create one or two tenants. What are the pros and cons of each option for cost reporting and visibility?
  4. Define a model strategy for plan, build and review runs. Via which settings or team fields do you implement it, and where do you check after a run whether it applied?
  5. Plan the budget rollout in three steps.
Solution outline

(1) TEAM_API_POOL, because several people use one instance; personal subscriptions are intended for a single workstation. (2) The five developers as DEVELOPER, two experienced people additionally as MAINTAINER for approvals, a dedicated operations account as ADMIN for tenants, accounts and budgets; enable run.approval-segregation. (3) Two tenants cleanly separate visibility, policy and budget — sensible because product B processes customer data and needs stricter rules; downside: users belong to exactly one tenant, so anyone working on both products needs an organizational solution. With one tenant, the project costs in /analytics are sufficient for cost reporting. (4) Plan runs with a strong model (run.routing.plan-model), build runs with the workhorse (run.routing.build-model or preferredModel of the developer agent), reviews with the small review model; check in the why-trace via RUN_MODELL_AUFGELOEST and the quelle field. (5) Observe-only mandant_budget → evaluation in /analytics and /mandanten/kosten → hard cap with buffer plus token limits as an early warning.

Chapter questions

  1. Why is a more expensive model often worthwhile for planning runs compared to build runs?

    Model answer

    Planning mistakes multiply, because all subsequent build runs build on the plan. At the same time, a plan run produces comparatively little output. The extra cost per token therefore applies to few tokens and prevents expensive downstream errors. Build runs, by contrast, produce most of the volume for rather mechanical work, where a mid-sized model is usually sufficient.

  2. Explain why the cost of an agent run does not grow linearly with the size of the task.

    Model answer

    In every round of the agent loop, the entire context so far is processed again: instructions, project context, all tool calls and their results. Costs therefore grow roughly with the number of rounds times the context size. Unclear tasks increase both, and large outputs that are read in inflate every subsequent round.

  3. A build run with the claude adapter ran with Sonnet, even though you entered Opus on the developer agent. What is the most likely cause, and where do you check?

    Model answer

    A routing override run.routing.build-model takes precedence over the team’s preferred model. Alternatively, a different team was selected. In the why-trace (/runs/{id}/trace), RUN_MODELL_AUFGELOEST with quelle=override, team, rollen-default or adapter-default shows where the model came from.

  4. Why does a run with the Aider adapter not get a Claude role default?

    Model answer

    Aider (like Bedrock/Vertex/Azure, Local-LLM and Kimi) passes --model unchanged to its own CLI or backend. A Claude model name would be wrong or meaningless there. For these adapters, the default model per adapter or the CLI’s choice applies.

  5. In the cost view, a Claude run shows a euro amount with the note “estimate (API rate), not billed”. What does that mean, and does the amount count against the budget?

    Model answer

    The run ran in subscription mode and counts against the subscription’s usage limits; no API bill arises. The factory still values the tokens at the API rate to make the generated load visible. The amount counts in consumption and therefore against the budget and hard cap.

  6. A run with several hundred thousand tokens shows €0. What are the two possible explanations?

    Model answer

    Either it is a flat-rate model (e.g. k3, kimi-for-coding), for which €0 is deliberately recorded, or the model has no entry in the price table in application.yml and is conservatively valued at €0. In the second case, the table should be extended.

  7. An administrator complains that she cannot see another tenant’s projects. Is that a bug? What needs to be done?

    Model answer

    Not a bug: in the factory, ADMIN is not a super admin for data. Projects, runs, logs and costs remain tenant-scoped. Only account management and project assignment are isolation-free. The solution is the tenant assignment (assign the account or project to the right tenant) or a deliberate organizational arrangement.

  8. Why do users newly created via SSO receive the role VIEWER without a tenant, and which general principle lies behind this?

    Model answer

    An SSO integration must never accidentally extend access. Minimal permissions at first login and a deliberate administrative assignment of role and tenant implement the principle of least privilege and fail-safe defaults.

  9. Transfer: You are asked to cut your team’s agent costs by a third. Name three measures in the order in which you would examine them, and justify the order.

    Model answer

    Example: (1) Make tasks more precise and cut them smaller (specs with acceptance criteria, backlog items instead of a mega-goal), because that reduces rounds and context at the same time. (2) Stop repetitions without new information and evaluate correction loops, because blind retries are pure waste. (3) Only then adjust the model classes per task and measure the effect in /analytics, because a cheaper model with more corrections can end up more expensive.

  10. Which three things do you need to back up, and why does the attestation key belong to them?

    Model answer

    The PostgreSQL database, the workspace directory with the Git repositories, and the attestation key together with the secrets master key. Without the attestation key, the signed audit chain can no longer be verified later; without the master key, stored secrets can no longer be read. After the restore, the chain verification under /attestierung shows whether the backup was complete.