> For AI agents: the complete documentation index is available at /llms.txt, the full documentation bundle is available at /llms-full.txt.

# Workload Portfolio

Workload Portfolio is the Metallo context that owns Workloads. The Workload is its
aggregate root; its immutable, numbered revisions are children, saved and changed
together. A revision holds the execution specification and required inputs that
Execution Core plans from.

Execution Core and Pipeline Coordination reference exact Workload revisions. They
read saved Workloads through service-level owner adaptors in
<a href="/source/services/metallo/adaptors/workload_evidence.py.txt">`adaptors/workload_evidence.py`</a> and check
member access themselves.

## Registration

The registry enrols `workload_portfolio` with the shared PostgreSQL bootstrap,
which provisions its private database and restricted runtime role when explicitly
run. The context uses the baseline schema without its own migrations.

## Domain records

`domain.workload.Workload` keeps its Project, creating member, display name,
creation time, version and optional retirement. Revisions are numbered from one
without gaps. Each revision's specification is stamped with its Workload and
Project identity. Batch revisions use `queued-batch`; services use
`reconciled-service` with `serviceKind: application | huggingface-inference`.
Execution Core validates the complete execution intent when it plans a Run.

`to_mapping()` returns detached JSON-compatible data. `restore()` treats invalid
saved data as `CorruptState`.

## Internal operations

`application.handlers.WorkloadOperations` creates, revises, retires and reads one
Workload through the shared `CommandPort` and `QueryPort` and an explicit
`WorkloadAuthority`. `adaptors.postgres.operations(database, authority)` supplies
production PostgreSQL adaptors. `saved_workloads(database)` supplies trusted owner
reads for the cross-context adaptors.

Running a repository action creates its Workload, so creating, revising, retiring and
preparing Workloads need `workloads.manage`, and reads and the action catalogue
need `workloads.view` (#755). Access is checked before each command and
read. Denied access is rejected; unavailable or uncorrelated authority fails for
retry. The permission provider is a test-only double until the real provider is
connected.

## Repository actions

`application.repository_actions.ActionWorkloads.prepare` validates one
`actions.yaml` action and its parameter values, converts it in
`domain.actions` and creates, reuses or revises that action's Workload. Each Project
repository, branch and action has one Workload with a stable identity. The
`RepositoryActions` port reads `actions.yaml` and resolves repository URLs.
`metallo.adaptors.source_control_actions` implements it over Source Control's
repository queries, with the commit the file was read at; `metallo-requests`
composes it through `metallo.adaptors.source_control_owners` (#796), and tests use
their own doubles.
Invalid parameter values raise `ParameterErrors`, with one message per parameter.

New action revisions also retain the effective named parameter values, including
defaults, in optional `specification.actionParameters`. This display evidence is
bounded to 64 names of at most 128 characters and values of at most 4,096
characters. Credential-like names, and definitions annotated with boolean
`sensitive`, `secret` or `confidential`, retain a null value. These annotations
control display evidence; they do not provide Runtime secret delivery. Execution
commands keep their existing substitution behaviour.
An empty map records a parameter-free action; an absent map is legacy unknown
evidence and remains absent when old revisions are restored. Execution Core
copies the accepted revision's evidence into its Run, so later action edits
cannot alter an earlier Run's configuration.
An already accepted Pipeline keeps its exact legacy revision on replay when all
original execution material still matches. The new display field cannot force a
different revision for that accepted work. A new request records its parameters
in a new revision.

Both `slurm-job` and `k8s-job` prepare `queued-batch` revisions. They select `slurm`
and `k8s` respectively and share batch commands, parameter substitution, resources
and timeout validation. Kubernetes batch actions use the existing Job Runtime.
Their validation rejects service port and inference options, and reports
`unsupported_action_feature` for a positive `options.gpus` or any
`options.gpuClass`. An omitted GPU count or `gpus: 0` is valid.

For Slurm jobs and Kubernetes services, `options.gpus` asks for accelerator devices
and `options.gpuClass` names which one,
in the Site's own vocabulary: the offering component (`gh200`, `gh200-mig-1g.18gb`,
`l40`, `l40-shared`), never a Kubernetes resource name. The delivery's accelerator
class map, not this context, turns a class into `nvidia.com/...`. An action that names
no class keeps the legacy `gpu` class of one whole device. Whether the Site offers the
requested class is decided by Execution Core's admission against the Site's applied
limits, so a Workload can be written before its Site publishes the class.

`application.action_catalogue.ActionCatalogue.list` describes the actions on `main`
for a member, each with the reason the backend cannot run it, using the same checks
as a launch. Its `RepositoryDirectory` port resolves Themelio's repository paths,
and `adaptors.requests` answers the typed `list_actions` query
(<a href="/source/services/metallo/docs/epics/instantiate-and-run/runtime-endpoints.md.txt">runtime endpoints</a>).

Service actions accept `options.exposure: project | public`. The default is
`project`; batch actions reject this option. The choice becomes the immutable
revision's `endpointPolicy.exposure` and is copied into the accepted Run. A
public repository alone never publishes a running endpoint. The member needs
the existing Workload management and Run launch permissions to launch that
explicitly public action. Stop the Run to withdraw it; changing `actions.yaml`
affects subsequent launches.

## Persistence

`pharos.aggregates` holds one `kind = workload` snapshot with its revisions.
`pharos.command_receipts` holds command fingerprints and recorded outcomes. Both
are written in one transaction. Workloads are registered without a browser
projection and publish no events yet.

The context's first migration adds Workload Portfolio's copy of Beto's Project memberships,
Party states and provider bindings (`pharos.project_views`, `project_members`,
`party_views`, `party_bindings`, `project_access_invalidations`, `view_state`,
`view_checkpoints`), applied from Beto's integration events with consumer receipts and
loaded from Beto's checkpoints. The `metallo` process holds
`WORKLOAD_PORTFOLIO_VIEWS_BROKER_URL` and runs its eight consumers and synchroniser.
`PartyProjectAuthority` decides the Workload permission from it by Beto's rule once it is
loaded (#757), and defers unless Beto's latest Project authority (`pharos.project_authority`,
migration 0002) is ready, unexpired and describes the Project revision it holds (#798). Its caller,
`metallo-requests`, reads this view over the context's database and confirms every allowing decision
with Beto through its own query-only caller, `METALLO_REQUESTS_VIEWS_BROKER_URL` (#755).
<a href="/source/services/metallo/docs/epics/instantiate-and-run/party-project-views.md.txt">Design</a>.

<a href="/source/services/metallo/docs/epics/instantiate-and-run/workload-creation.md.txt">Design, remaining connections and verification</a>.

<details class="page-source"><summary>Page source</summary>

<a href="/source/services/metallo/contexts/workload_portfolio/README.md.txt">Source snapshot</a> · Revision `f928834c8`.

</details>
