A provisioned workload never holds a long-lived secret
Instead of a provider baking a static API key or password into a VM at boot, a bid can attach a com.publicdomainrelay.temp.compute.config.wif.simple record: a pointer to an OIDC issuer the workload can prove its own identity to, in exchange for a short-lived token scoped to exactly what it needs.
The record
issuer_uri | The OIDC issuer the workload will authenticate against. |
to_issue | Opaque exchange identifier (e.g. exchange-custom-droplet-oidc-poc). The OIDC token audience is set independently at issue time via the aud field in the issue request body. |
actx | Team or context identifier (e.g. a did:plc key). Used as the {actx} template variable in subject. |
subject | Template for the identity the token asserts. Variables: {actx}, {did-plc-key}, {role}. |
token_path | Where the provisioning prove step writes the service account token on the guest. Read by fedproxy-client at runtime. |
url_path | Where the issuer base URL is written on the guest. Read by fedproxy-client to construct issue endpoint calls. |
actx_path | Where the team / context identifier is written on the guest. Read by fedproxy-client for subject template substitution. |
url_route | The RBAC-gated token issue endpoint path on the issuer (e.g. /v1/oidc/issue). Called by fedproxy-client to mint workload-scoped tokens. |
accept_path | Filesystem path on the guest where the signed market.accept bundle (accept.json) is written by cloud-init. fedproxy-client reads this at startup to discover issuer URL, token paths, and OIDC configuration. |
$type: com.publicdomainrelay.temp.compute.config.wif.simple
accept_path: /root/secrets/publicdomainrelay.com/market/accept.json
issuer_uri: https://droplet-oidc.example.com
to_issue: exchange-custom-droplet-oidc-poc
actx: {team-plc-key}
actx_path: /root/secrets/digitalocean.com/serviceaccount/team_uuid
token_path: /root/secrets/digitalocean.com/serviceaccount/token
url_path: /root/secrets/digitalocean.com/serviceaccount/base_url
url_route: /v1/oidc/issue
subject: actx:{actx}:plc:{did-plc-key}:role:{role}
createdAt: 2026-07-11T12:00:00Z
This is orthogonal to policy mode: policy decides whether a workload gets scheduled at all; WIF decides what it can authenticate as once it's running.
A real deployment: fedproxy.com
The reference bidder uses this pattern to hand a freshly provisioned VM a browser-accessible terminal without ever shipping it a static password.
A small OIDC + RBAC service the provider runs
Exposes POST /v1/oidc/prove and POST /v1/oidc/issue (plus /.well-known/openid-configuration and /.well-known/jwks). /v1/oidc/prove validates an SSH-signed provisioning proof; /v1/oidc/issue is an RBAC-gated endpoint that mints short-lived, audience-scoped OIDC tokens for ongoing workload use.
A systemd service cloud-init installs on the guest
Runs with AUTH_PLUGIN=oidc and MARKET_ACCEPT_JSON_PATH, reads the signed accept bundle to discover issuer URL and token paths, then calls POST /v1/oidc/issue to mint ATProto-scoped tokens for relay XRPC operations. Opens an outbound tunnel so the VM is reachable at a stable subdomain without any inbound port.
A credential fetched, not shipped
Once the VM holds its scoped token, it calls the relay for its own credentials record. The relay's middleware validates the OIDC bearer before returning anything. No password was ever baked into the image.
The exchange, step by step
The provider attaches a wif.simple config to its bid, naming an issuer it already runs and encoding paths, exchange identifier, subject template, and context identifier.
The requester's own RBAC records what that issuer is trusted to authorize, before accepting anything from this provider.
Before provisioning, the provider bakes the accept.json into the cloud-init user_data via injectAcceptBundle and enriches the cloud-config with a provisioning-token.service one-shot that holds a signed provisioning JWT. On first boot, cloud-init writes the accept bundle to accept_path and registers the provisioning service.
Provisioning prove: provisioning-token.service signs the provisioning JWT with ssh-keygen -Y sign -n prove-sshd using the guest's SSH host key, then POSTs the signature to POST /v1/oidc/prove at issuer_uri. On success, it writes the returned service account token to token_path and the issuer URL to url_path.
Workload identity: fedproxy-client starts with AUTH_PLUGIN=oidc, reads the accept bundle from accept_path, loads the service account token, and calls POST /v1/oidc/issue (RBAC-gated) to mint a short-lived ATProto-scoped OIDC token for each relay operation. The token expires; nothing longer-lived was ever issued.