feat(cli): add project and function secrets commands - #3021
Merged
Merged
Conversation
# why We want to add secrets support to the browse cli. In order to do so, we need to first introduce a common library that is a wrapper around the REST api, and then hook it into the cli tool. For simplicity, we choose the list secrets endpoint as the first CRUD operation that will be exposed to the cli tool # what changed - Adds a library for wrapping around the secrets api - implements the first command to retrieve a list of secrets # test plan - [x] unit tests - [x] pointed this branch at a local api and confirmed listing secrets (metadata only) on test projects works
# why We want to add secrets support to the browse cli and is a continuation of the efforts introduced in this PR: #2946. In this particular PR, we add support GET/DELETE on a secret # what changed - Add GET and DELETE support # test plan - [x] unit tests - [x] point cli at local secrets api
### why We want to add secrets support to the browse cli and is a continuation of the efforts introduced in this PR: #2946. In this particular PR, we add support for creating a secret by retrieving the public key for the project, reading the secret value from an env variable, a value piped to stdin, or prompting them in a password prompt (the inquire package), encrypting the value with the public key, then calling the create secret endpoint with the secret key name and the encrypted value. ### what changed - Adds a command to create a secret ### test plan - [x] unit tests - [x] point cli at local secrets api, verify encrypted secrets value lands in local db
### why We want to add secrets support to the browse cli and is a continuation of the efforts introduced in this PR: #2946. In this particular PR, we add support for updating a secret by retrieving the public key for the project, reading the secret value from an env variable, a value piped to stdin, or prompting them in a password prompt (the inquire package), encrypting the value with the public key, then calling the update secret endpoint via patch with the provided secret-id and the encrypted value. ### what changed - Adds a command to update a secret ### test plan - [x] unit tests - [x] point cli at local secrets api, verify encrypted secrets value lands in local db and is updated --------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
### why We want to add secrets support to the browse cli and is a continuation of the efforts introduced in this PR: #2946. In this particular PR, we add support for attaching a secret to a function. ### what changed - Adds a command to attach a secret to a function ### test plan - [x] unit tests - [ ] point cli at local secrets api, verify encrypted secrets value lands in local db and is updated
### why We want to add secrets support to the browse cli and is a continuation of the efforts introduced in this PR: #2946. In this particular PR, we add support for detaching a secret from a function. ### what changed - Adds a command to detach a secret from a function ### test plan - [x] unit tests - [x] point cli at local secrets api, verify encrypted secrets value lands in local db and is updated
### why We want to add secrets support to the browse cli and is a continuation of the efforts introduced in this PR: #2946. In this particular PR, we add support for listing secrets attached to a specific function ### what changed - Adds a command to list secrets attached to a function ### test plan - [x] unit tests - [x] point cli at local secrets api, verify encrypted secrets value lands in local db and is updated
🦋 Changeset detectedLatest commit: c874d61 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 33 files
Architecture diagram
sequenceDiagram
participant U as User/CLI
participant C as Command Handler
participant I as Secret Input
participant S as Seal Service
participant A as API Helper
participant B as Browserbase API
participant F as Function API
Note over U,B: Secret Management Flow (Create/Update)
U->>C: Browse command with args/flags
alt Create or Update
C->>I: readSecretValue()
alt --env flag
I->>I: Read from process.env
else --stdin flag
I->>I: Read stream from stdin
else Interactive TTY
I->>I: Hidden prompt via @inquirer/password
end
I-->>C: Uint8Array value
C->>A: create/updateSecret()
A->>B: GET /v1/secrets/keypair
B-->>A: { keypairId, publicKey }
A->>S: sealSecret(publicKey, value)
S->>S: Validate public key (32-byte X25519)
S->>S: HPKE seal with AES-256-GCM
S-->>A: sealedSecretValue (base64)
alt Create
A->>B: POST /v1/secrets {secretKey, keypairId, sealedSecretValue}
else Update
A->>B: PATCH /v1/secrets/{id} {keypairId, sealedSecretValue}
end
B-->>A: Secret metadata
A-->>C: Secret object
C-->>U: JSON output
C->>C: Zeroize Uint8Array buffer
end
Note over U,F: Function Secret Attachment Flow
alt Attach
U->>C: functions secrets attach <functionId> <secretId>
C->>A: attachFunctionSecret()
A->>F: POST /v1/functions/{id}/secrets
F-->>A: 204
A-->>C: void
else Detach
U->>C: functions secrets detach <functionId> <secretId>
C->>A: detachFunctionSecret()
A->>F: DELETE /v1/functions/{id}/secrets/{secretId}
F-->>A: 204
A-->>C: void
end
Note over U,B: List/Get/Delete Metadata Flow (No Decryption)
alt List project secrets
U->>C: cloud secrets list [--limit --cursor --start-at --end-at]
C->>A: listSecrets() with query params
A->>B: GET /v1/secrets?{pagination}
B-->>A: { data, limit, nextCursor }
A-->>C: SecretPage
C-->>U: JSON output
else Get secret
U->>C: cloud secrets get <secretId>
C->>A: getSecret()
A->>B: GET /v1/secrets/{id}
B-->>A: { id, secretKey }
A-->>C: Secret metadata
C-->>U: JSON output
else Delete secret
U->>C: cloud secrets delete <secretId>
C->>A: deleteSecret()
A->>B: DELETE /v1/secrets/{id}
B-->>A: 204
A-->>C: void
else List function secrets
U->>C: functions secrets list <functionId> [--limit --cursor --start-at --end-at]
C->>A: listFunctionSecrets()
A->>F: GET /v1/functions/{id}/secrets?{pagination}
F-->>A: { data, limit, nextCursor }
A-->>C: SecretPage
C-->>U: JSON output
end
Note over B: API Error Handling
B-->>A: Error response (400/403/404/409)
A-->>C: Throw error
C-->>U: Non-zero exit + stderr message
Reply with feedback, questions, or to request a fix.
Re-trigger cubic
shrey150
approved these changes
Sep 23, 2026
Merged
AzamAbdul
pushed a commit
that referenced
this pull request
Sep 23, 2026
Release Browse independently of the Stagehand SDKs. Merging this PR publishes the CLI from the merged commit. ## 0.11.0 ### Minor Changes - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add `browse functions secrets attach` to attach an existing project secret to a function by ID. - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add `browse cloud secrets create` with public-key lookup, local encryption, and secret input from stdin, a named environment variable, or a hidden prompt. - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add `browse functions secrets detach` to remove a function-secret attachment without deleting the project secret. - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add commands to retrieve project secret metadata and delete a project secret by ID. - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add `browse functions secrets list` to list attached secret metadata with cursor pagination and creation-time filters. - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add `browse cloud secrets list` to list project secret metadata with pagination and date filters. - [#3021](#3021) [`2c098f4`](2c098f4) Thanks [@AzamAbdul](https://github.com/AzamAbdul)! - Add `browse cloud secrets update` to replace a secret value by ID with local encryption and stdin, environment variable, or hidden prompt input. ### Patch Changes - [#2799](#2799) [`21f4443`](21f4443) Thanks [@shrey150](https://github.com/shrey150)! - Use catalog source paths when cloning templates and print setup commands that match the generated project's package manager and Python environment. Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
why
Browse needs commands to manage project secrets and attach them to Functions. The seven component PRs were merged into
agent/browse-v4-7-context-names; this PR brings those changes onto currentmainatfbcdf61.what changed
browse cloud secretscommands to list, get, create, update, and delete secrets, including client-side encryption for create/update and password input support.browse functions secretscommands to attach, detach, and list secrets for a function.Cherry-picked in order from #2946, #2949, #2967, #2990, #3006, #3007, and #3009. All seven applied without conflicts. The secrets implementation is unchanged from the original branch. This branch retains main's Browse 0.10.0 release and excludes the old parent branch's context-name and eval changes.
test plan
Validated locally on macOS with Node 24.18.0 and pnpm 11.23.0:
pnpm install --frozen-lockfile— passed.pnpm exec turbo run build --filter=browse— all four tasks passed (protocol, extension, SDK, CLI).pnpm --filter browse lint— formatting, ESLint, and TypeScript passed.pnpm --filter browse test:cli— 36 files / 471 tests passed, using an isolated daemon directory and umask 022.pnpm exec node --import tsx scripts/release/check-changesets.tsandgit diff --check— passed.Validation covers the built CLI and local contract fixtures; no production secrets were created or modified.