Skip to content

PROTM-2271: Add secrets management API (ls/set/rm) - #182

Open
sandshoes wants to merge 1 commit into
mainfrom
tommy/protm-2271-ts-sdk-secrets-management-api
Open

sandshoes wants to merge 1 commit into
mainfrom
tommy/protm-2271-ts-sdk-secrets-management-api

Conversation

@sandshoes

Copy link
Copy Markdown
Contributor

Summary

Adds a client.secrets namespace for managing the actual server-side value of a Tinybird secret via the /v0/variables API, matching tb secret ls/set/rm in the Tinybird CLI.

This is a separate, complementary concern to the existing secret() helper (src/schema/secret.ts), which only emits a {{ tb_secret(...) }} template reference for datafiles and never talks to the API — that helper is untouched.

Linear: https://linear.app/tinybird/issue/PROTM-2271/typescript-sdk-add-secrets-management-api-lssetrm

What's included

  • src/api/secrets.ts — low-level listSecrets, createSecret, updateSecret, setSecret, removeSecret functions and a SecretApiError class, mirroring the structure of src/api/tokens.ts.
    • GET /v0/variables → listSecrets
    • POST /v0/variables (form body {name, value}) → createSecret
    • PUT /v0/variables/{name} (form body {value}) → updateSecret
    • DELETE /v0/variables/{name} → removeSecret
    • setSecret checks for an existing secret via GET /v0/variables/{name} first and then creates or updates, mirroring load_secrets/secret_set in the Python CLI (tinybird/tb/modules/secret.py, secret_common.py), including treating any failure of the existence check (404, permission error, etc.) as "doesn't exist yet".
  • src/client/secrets.ts — SecretsNamespace class exposing list() / set(name, value) / remove(name), following the exact structural template of TokensNamespace (src/client/tokens.ts).
  • Wired into TinybirdClient.secrets in src/client/base.ts the same way client.tokens is wired, and also into the Tinybird project client (src/schema/project.ts) alongside the existing tokens getter, for consistency.
  • New types exported from src/index.ts: SecretApiConfig, SecretInfo, SetSecretResult, RemoveSecretResult, plus listSecrets/createSecret/updateSecret/setSecret/removeSecret/SecretApiError.

Security

  • Secret values are never logged.
  • Success response bodies for create/update/delete are drained but never parsed or returned, so a value is never read back out of the API even if the endpoint happened to include it.
  • Any thrown error message/body has the submitted value redacted ([REDACTED]) before being surfaced, in case an API error response ever echoes it back.
  • list() only returns metadata (name, created_at, updated_at) — never a value.

Assumptions about /v0/variables response shapes (couldn't fully confirm against a live API)

  • GET /v0/variables returns { variables: [...] } — confirmed against the Forward CLI's Python client (tinybird/tb/client.py: secrets()), which reads response["variables"].
  • Each entry is metadata-only (name, created_at, updated_at) — inferred from tb secret ls's output columns in secret.py; not fully confirmed that the API never includes a value field, so SecretInfo is typed loosely and this SDK never surfaces anything beyond name/timestamps regardless of what's in the response.
  • GET /v0/variables/{name} (existence check): response body is intentionally never parsed or returned by this SDK — only response.ok is used — since it's unconfirmed whether this endpoint returns the plaintext value for an existing secret.
  • Create/update success response bodies: shape unconfirmed; intentionally drained and discarded rather than parsed, so no assumption is baked in and no potential value leak either.

Test plan

  • pnpm typecheck
  • pnpm test:run (all 1085 tests pass, including new src/api/secrets.test.ts and src/client/secrets.test.ts)
  • New tests cover: list, set (create path), set (update path), set (existence-check failure treated as not-existing), remove, and error paths including secret-value redaction in thrown errors

Add a `client.secrets` namespace that manages the actual server-side
value of a Tinybird secret via the `/v0/variables` endpoints, mirroring
`tb secret ls/set/rm` in the Python CLI. This is a separate,
complementary concern to the existing `secret()` helper in
`src/schema/secret.ts`, which only emits a `{{ tb_secret(...) }}`
template reference for datafiles and never talks to the API.

- `src/api/secrets.ts`: low-level `listSecrets`/`createSecret`/
  `updateSecret`/`setSecret`/`removeSecret` functions and a
  `SecretApiError` class, following the `src/api/tokens.ts` pattern.
  `setSecret` checks for an existing secret (`GET /v0/variables/{name}`)
  before deciding to create or update, mirroring `load_secrets`/
  `secret_set` in the Tinybird CLI.
- `src/client/secrets.ts`: `SecretsNamespace` class exposing
  `list()`/`set(name, value)`/`remove(name)`, wired into
  `TinybirdClient.secrets` in `src/client/base.ts` and into the
  `Tinybird` project client (`src/schema/project.ts`) the same way
  `tokens` already is.
- Secret values are never logged, never read back from success
  responses, and are redacted from any thrown error message/body in
  case the API ever echoes a submitted value back.
- Tests colocated per existing convention (`src/api/secrets.test.ts`,
  `src/client/secrets.test.ts`), covering list/set(create)/set(update)/
  remove and error paths, including value redaction.

Fixes PROTM-2271.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant