Credential store

One selector owns every application credential, including cloud/provider credentials, service tokens, and SSH host keys:

{
  "credentials": {"store": "skarbiec"},
  "secrets": {
    "skarbiec": {
      "consumer": "stado",
      "token_file": "~/.stado/stado-skarbiec-token"
    }
  }
}

Stado has no built-in Skarbiec address. It takes WC_SKARBIEC_URL, then secrets.skarbiec.url, then the address stado service directory publish wrote for this host into ~/.stado/forwards/skarbiec.local from the service directory. A host that none of these names Skarbiec for has no address, and every credential read refuses with that rather than dialing a port nothing may serve.

credentials.store is the committed source of truth. STADO_CREDENTIALS_STORE is its process-level override. Supported locators are skarbiec, skarbiec://<https-origin>, and file://<absolute-path>. The file backend is an owner-only local/offline manager; Skarbiec adds encryption, scoped grants, audit, recovery recipients, and remote HTTPS access.

Changing the environment selector does not make Stado read an empty backend. It creates a fail-closed pending migration:

export STADO_CREDENTIALS_STORE=file:///secure/stado-credentials.json
stado credentials migrate

Without an environment override, stado credentials migrate --to <locator> performs the same change. Migration snapshots every active item and its type, requires an empty destination, copies and reads every value back, commits credentials.store, and only then removes the source items. A failed copy, verification, config write, or source cleanup rolls back to the previous store. Normal reads and writes remain blocked while the environment and committed selectors differ.

stado credentials CRUD and provider reads use this selector. Stado's Skarbiec field readers use the secrets.skarbiec identity, not per-operation consumer sections. There is no OpenSSH-file substitute for host channels. The bootstrap bearer remains outside the selected store: putting the grant needed to unlock Skarbiec inside that same vault would be circular. The owner-only file is named by secrets.skarbiec.token_file and its exact capabilities are recorded in Skarbiec, not in this JSON document.

Recovering an unlock phrase

stado credentials try-unlock [--host <host>] [--keychain-only] tests unlock phrases against a vault with Skarbiec's own skarbiec key-doctor, one phrase at a time, and names the source of the phrase that opens it, never the phrase. Without --host it tests the phrases that survive in transcript output against the local vault. With --host it runs on that host: it first restores a readable vault backup it finds under ~/.stado, then tries the host's macOS Keychain entry skarbiec-vault, then the transcript phrases; --keychain-only tries the Keychain entry alone. A phrase that opens the vault is written to the host's owner-only unlock file.

A Keychain that holds no skarbiec-vault item is no failure. One that cannot be read for another reason is said on stderr with security's exit status and its own words, and with --keychain-only the run is refused with that cause rather than reported as a phrase that does not open the vault. A key-doctor that answers without a report is refused with its exit status, its output and its errors, and no phrase is judged.

Source: this website