Source credentials
Store a source credential once, then refer to it by name without putting its value in a recipe or log.
Store the value once and use its name in the recipe. When the worker fetches the source, it redeems a one-time handle for the credential. The value never appears in the recipe, receipt, events or command line.
Check saved connections first
Section titled “Check saved connections first”A warehouse or API your organization already connected stores its credential already. It needs no second copy under keys.
mr-data connections --dataset DATASET_ID --jsonUse the matching active connection’s connection_id and version_digest in the source’s connection member, with the query in parameter_values and a response reader in response. Set dataset.id to the granted dataset. Do not ask a person to re-enter a saved credential. If the connection is not granted to that dataset, an owner or administrator has to allow it in Settings → Connections & secrets.
A source without a saved connection uses a named secret.
Store a credential
Section titled “Store a credential”mr-data keys set noaa_token --value-file token.txt --jsonmr-data keys set noaa_token --value-file - --json # read it from standard inputmr-data keys list --jsonmr-data keys rm noaa_token --json| Argument | What it does |
|---|---|
set | list | rm |
set stores a credential under NAME, list names the ones this workspace holds, rm withdraws one. |
NAME |
The credential’s name: lowercase letters, digits, dashes and underscores, at most 63 characters, starting with a letter. Not needed by list. |
--value-file FILE |
With set, the file holding the value. - reads it from standard input instead. The client removes one trailing newline, because a credential stored with the one echo added fails at the source and nothing says why. |
--part NAME=VALUE |
With set, one named part of a shaped credential. NAME=@PATH reads that part off disk. Repeat once per part. It cannot be combined with --value-file. |
--json |
One JSON object instead of human lines. |
The value cannot be given on the command line. No argument holds one, so it cannot land in ps, in a shell history file, or in a CI log. The client checks the name before it resolves a credential and before it reads a value from disk. A mistyped name fails locally before any network request. A value is at most 65,536 bytes.
keys list returns names and their status (active or revoked), created_at and rotated_at. keys set returns the same plus rotation_generation. Nothing reads a value back.
Storing a name that already exists rotates it. Existing recipes keep working, because they reference the name and not the value.
Shaped credentials for a stream venue
Section titled “Shaped credentials for a stream venue”A keyed wss:// venue authenticates with two or three named parts rather than one opaque string. The vault stores one value per name, so this command composes the parts into one envelope.
mr-data keys set venue_key --part key_id=ABC123 --part private_key_pem=@signing.pem --jsonThe vault accepts four shapes, each by the set of parts it holds. The parts you name decide the shape, and a set that matches none of them is refused by name.
| Shape | Parts |
|---|---|
token |
token |
key_pair |
key_id, secret |
key_pair_passphrase |
key_id, secret, passphrase |
key_id_pem |
key_id, private_key_pem |
--part NAME=@PATH reads that part off disk, which is how a signing key arrives. A PEM is multi-kilobyte and has newlines in it. At most four parts compose one envelope, and the envelope is canonical JSON built locally and never echoed.
The venue’s connector document declares which parts its shape holds, and a set that does not match is refused.
Reference the name from a recipe
Section titled “Reference the name from a recipe”The credential reference is credential, a sibling of connector on the source. It takes either a secret_name, or a saved connection’s connection_id and connection_version_digest.
{ "name": "agency_feed", "source_class": "user_api", "data_classification": "public", "locator": { "kind": "https_url", "display_locator": "https://api.example.org/export.csv" }, "rights_claim": { "claimed_basis": "terms_of_service_asserted", "claim_evidence_digest": "sha256:…" }, "connector": { "adapter_id": "authenticated.https.api_key@1.0.0", "credential_mode": "opaque_reference", "origin": "https://api.example.org", "parameters": [{"name": "credential_scheme", "value": "bearer"}] }, "credential": {"secret_name": "agency_feed_key"}, "limits": {"max_source_bytes": 3145728}}Two rules the schema enforces:
- A credentialed source states
credential_mode: "opaque_reference"and has a siblingcredential. - A credential-free source states
credential_mode: "none"and does not have one.
The display_locator is the credential-free target. Never put a key, a token or a signed URL in a locator, a parameter, a prompt or a log.
Which source kinds accept a credential
Section titled “Which source kinds accept a credential”| Adapter | Credential | How it is presented |
|---|---|---|
authenticated.https.api_key@1.0.0 |
secret_name |
Exactly one connector parameter named credential_scheme, valued bearer or x-api-key. The worker does not infer a scheme from the URL. The adapter is one single-request CSV GET, and other connector parameters do not widen it. |
authenticated.https.api_key@2.0.0 |
secret_name |
generic_api.auth, and nothing else. It does not accept a credential_scheme parameter. auth.kind is bearer, header (with header_name, value_prefix, and optional key_encoding, pre_encoding_prefix, pre_encoding_suffix) or query (with query_name). |
authenticated.https.connector@3.0.0 |
secret_name |
Same generic_api shape, plus a required generic_api.limits and an optional job block. |
| Any adapter, through a saved connection | connection_id + connection_version_digest, or the connection shorthand |
The connection owns the endpoint, the authentication and the fixed inputs. The recipe supplies the query and how to read the result. |
stream.wss@2.0.0 |
Not in the recipe. | A keyed venue’s credential is named on the recording, with mr-data stream capture --secret NAME, because a build never reaches the venue. See Live streams. |
These take no credential and must state credential_mode: "none": public.https, public.https.collection@2.0.0, stream.wss@1.0.0, snapshot.artifact@1.0.0, document.projection@1.0.0 and external.openligadb. A page collection reads public addresses, and there is no credential to present to a link discovery found.
The worker never downgrades an authenticated user API into the credential-free fetcher. Hosted authenticated acquisition uses an allowlisted fixed adapter and a brokered single-use handle, bound to that attempt and that approved source. The worker has no direct vault access. It lends the redacted in-memory lease to that adapter for one call.
The full request grammar of the generic adapters covers path templates, static query and headers, typed parameters, pagination and the Reader pin. It is in Source kinds and connectors.
The dashboard as the alternative
Section titled “The dashboard as the alternative”Settings → Connections & secrets at app.mostlyright.md writes to the same vault. Use it when the person holding the credential is not the person at the terminal. Use it too when the credential comes out of a password manager that will not hand it to a file. What lands there is what mr-data keys list names, and a recipe references it the same way.
When a person has to finish it in a browser
Section titled “When a person has to finish it in a browser”One thing in this product needs a fresh interactive verification that a device credential cannot give, and it is not --confirm: publishing a dataset publicly, on organizations that require it. The refusal is THIN_CLOUD_STEP_UP_REQUIRED, and it names the dashboard address to open.
Releasing a held full run in the awaiting_sample_approval state used to be the second. It is not any more: any editor credential of the workspace may release it once its preview has sealed a table, so an agent can do it on your word. The browser path is unchanged and still works — open the run’s page and release it there. The platform writes a bounded preview you can download either way, and the release is fenced on the run’s expected_version so a run that moved in between is refused rather than released.
An ordinary large run gets a run confirmation instead. That is --confirm, and any authenticated caller of the paying workspace may settle it.
If a source refuses for want of a credential
Section titled “If a source refuses for want of a credential”Say that the source needs a credential, and name which one. Say who issues it, where to apply for it, and the command that enrols it. A rejected source with a route back is a decision somebody can revisit.
Say nothing about the storage mechanism, and never print, log or echo a credential value while diagnosing.
Write a recipe for where credential sits in the document. Fix a failed run for what an authentication refusal looks like on a run.