spotlight_secret
The spotlight_secret resource, and the secret resource of the API: a
workspace's credential that Spotlight puts in a request header or query
parameter on requests to the hosts it is bound to. Its value never enters a
sandbox.
| Kind | Endpoint | Terraform | Address |
|---|---|---|---|
secret | /api/resources/workspaces/{workspaceId}/secrets | spotlight_secret | <name> |
See Resource API for the operations, headers and errors every kind shares.
Example
resource "spotlight_secret" "acme_api_key" {
workspace_id = spotlight_workspace.acme.id
name = "ACME_API_KEY"
bindings = [
{ host = "api.acme.example", prefix = "Bearer " },
]
value_wo = var.secret_acme_api_key
value_wo_version = 1
}
resource "spotlight_secret" "maps_key" {
workspace_id = spotlight_workspace.acme.id
name = "MAPS_KEY"
bindings = [
{ host = "maps.googleapis.com", carrier = "query", name = "key" },
]
value_wo = var.secret_maps_key
value_wo_version = 1
}
resource "spotlight_secret" "acme_signing" {
workspace_id = spotlight_workspace.acme.id
name = "ACME_SIGNING"
source = {
kind = "aws-secrets-manager"
secret_id = "acme/signing"
field = "secret"
}
}Fields
| Field | Type | Default | Description |
|---|---|---|---|
name | string | required | Capitals, digits and _, starting with a capital, at most 64 characters. Fixed: an update that changes it is refused; Terraform replaces the resource. |
source.kind | string | built-in | built-in or aws-secrets-manager. Where the value lives. |
source.secretId | string | none | For aws-secrets-manager: the secret's name or ARN, 1 to 2,048 of A-Z a-z 0-9 / _ + = . @ : -. |
source.field | string | none | For aws-secrets-manager: one key of the JSON the secret holds. No whitespace, at most 256 characters. |
bindings | array of objects | [] | The hosts the secret is sent to. At most 32, each host once. |
valueWo | string | none | Write-only. The value, for built-in. Not empty, at most 64 KiB. |
valueWoVersion | integer | none | At least 0. A change, with a new valueWo, rotates the value. |
rotatedAt | string | read-only | When the value was last set, as an RFC 3339 time. |
In Terraform, value_wo is write-only and needs Terraform 1.11 or later.
Sources
source.kind | Value |
|---|---|
built-in | Kept by Spotlight, sealed. valueWo is required on create, whenever valueWoVersion changes, and when a secret moves to built-in from another source. |
aws-secrets-manager | Read from AWS Secrets Manager when the secret is used. valueWo is refused: cannot be set on a secret read from AWS Secrets Manager. |
For a run, a secret from AWS Secrets Manager is read by
egress with the host's own AWS identity, among the
names SPOTLIGHT_EGRESS_READS allows; see
Host settings. For an
integration request made by Spotlight, it is read only when the deployment
reads from AWS Secrets Manager; otherwise the request fails with
Secret <NAME> could not be read. This deployment does not read from AWS Secrets Manager.
Bindings
| Field | Type | Default | Description |
|---|---|---|---|
host | string | required | One hostname of at least two labels, lowercased, with no scheme, port or path, as in api.acme.example. |
carrier | string | header | header or query. Where the value is put: a request header or a query parameter. |
name | string | authorization for a header | The header or query parameter the value is put in, at most 128 characters. Spotlight holds a header name in lower case. A query parameter has no default, is made of letters, digits and . _ ~ -, and keeps its case. |
prefix | string | "" | Up to 64 printable ASCII characters written before the value, as in Bearer . Allowed for both carriers. |
A header may not be host, content-length, content-type,
transfer-encoding, connection, upgrade, te or trailer.
| Message | Cause |
|---|---|
is where the secret is worn: header or query | A carrier other than header or query. |
is the request header the secret is worn in, as in authorization or x-api-key | A header name that is not a valid header, or one of those above. |
is the query parameter the secret is worn in, as in key or api_key | A query parameter without a name, or with other characters. |
In Terraform, the provider refuses a query binding without a name at plan
time with A query parameter must be named.
A secret is sent only over HTTPS, and only to a hostname equal to a bound
host. A request to any other address goes without it. A value of more than
one line cannot be sent: Secret <NAME> holds more than one line. It cannot be sent in a request.
A call that would send two secrets in the same header or query parameter to
one host is refused with 409 and
Secrets <A> and <B> are both worn in <slot> toward the same host. A request can carry only one of them.,
where <slot> is the header's name or ?<parameter>.
In what a host answers to a tool call, including an error that repeats the
URL or the key, every spelling of the value Spotlight sent, and of the value
without its prefix, is replaced by [secret]. This happens before the answer
is recorded in the task's journal or handed to the agent. An error reaching
the host says [secret] in the value's place.
In a query parameter
On a request Spotlight makes, such as an integration tool's call, the
parameter's first occurrence is set to the prefix and the value. Later
occurrences of the parameter are dropped, and a missing parameter is added at
the end. The rest of the query is kept as it was, in its order and its
encoding. A redirect to another host never carries the value; the parameter
reads [secret] there. In a run's sandbox,
egress rewrites the query the same
way, and only where the request carries the stand-in as that parameter's
value.
Where a secret is named
A secret is named as secret.<NAME>.
| Where | Field | Checked when written |
|---|---|---|
| Integration | webhook.verify.hmac.secret | no |
| Integration | webhook.verify.token.secret | no |
| Integration | a request's auth.secrets | no |
| Integration | connection.manual.secrets | no |
| Harness profile | mcpServers[].env values | yes |
A secret that is named but not defined fails where it is used, with
Secret <NAME> not found. Please define it first. A webhook whose signing
secret is not defined answers a plain 401. See
Delivery address.
A skill declares the secrets it needs in the
secrets of its SKILL.md, by name only.
No expression may read a secret's value. See Evaluation.
Rules
- Writing a secret needs the
manage-secretspermission. See Roles and permissions. - A secret still named by an integration or a harness profile cannot be
deleted. The delete is refused with
409andSecret <NAME> is in use. Used by: <names>. - No read, list, import, export or configuration change holds the value. A configuration change records the value version and the bound hosts.
- A secret belongs to the workspace, and every team in it can name it.