feat(workspace): bl workspaces hipaa accept|decline|status + --accept-not-hipaa on deploy/apply#299
feat(workspace): bl workspaces hipaa accept|decline|status + --accept-not-hipaa on deploy/apply#299devin-ai-integration[bot] wants to merge 3 commits into
bl workspaces hipaa accept|decline|status + --accept-not-hipaa on deploy/apply#299Conversation
Adds three subcommands under 'bl workspaces hipaa' to manage the new
workspace HIPAA opt-in flag from the CLI:
- accept PUT /workspaces/{name}/hipaa with hipaaOptIn=true
- decline PUT /workspaces/{name}/hipaa with hipaaOptIn=false
- status GET /workspaces/{name} to print current state
accept/decline prompt for y/N on a TTY; pass -y/--yes (or run with a
non-TTY stdin and --yes) to skip the prompt for CI. The --workspace
global flag targets a non-current workspace.
bl deploy / bl apply already surface the controlplane's HIPAA error
verbatim via extractErrorMessage ("error" field), so no changes are
needed there.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| workspaceName := resolveWorkspaceName() | ||
|
|
||
| if !assumeYes && !confirmHipaaChange(workspaceName, optIn) { | ||
| core.Print("Aborted.\n") | ||
| return | ||
| } | ||
|
|
||
| client := core.GetClient() | ||
| if client == nil { | ||
| err := fmt.Errorf("no API client available. Please run 'bl login' first") | ||
| core.PrintError("Workspace", err) | ||
| core.ExitWithError(err) | ||
| } |
There was a problem hiding this comment.
🟡 Interactive confirmation prompt happens before client availability check
In runWorkspaceHipaaUpdate, the user is prompted for interactive confirmation (line 227) before the API client availability check (line 232-237). If the user is not logged in (core.GetClient() returns nil), they will go through the full TTY confirmation dialog, type "y", and only then be told they need to run bl login. The cheap, non-interactive client check should precede the interactive prompt to avoid wasting the user's time on an operation that is guaranteed to fail.
| workspaceName := resolveWorkspaceName() | |
| if !assumeYes && !confirmHipaaChange(workspaceName, optIn) { | |
| core.Print("Aborted.\n") | |
| return | |
| } | |
| client := core.GetClient() | |
| if client == nil { | |
| err := fmt.Errorf("no API client available. Please run 'bl login' first") | |
| core.PrintError("Workspace", err) | |
| core.ExitWithError(err) | |
| } | |
| workspaceName := resolveWorkspaceName() | |
| client := core.GetClient() | |
| if client == nil { | |
| err := fmt.Errorf("no API client available. Please run 'bl login' first") | |
| core.PrintError("Workspace", err) | |
| core.ExitWithError(err) | |
| } | |
| if !assumeYes && !confirmHipaaChange(workspaceName, optIn) { | |
| core.Print("Aborted.\n") | |
| return | |
| } |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Good catch — fixed in 83d59b7. Moved the core.GetClient() nil-check above the TTY confirmation so an unauthenticated user gets the bl login message immediately instead of after typing through the y/N dialog.
Move the cheap core.GetClient() nil-check above the y/N TTY prompt so that an unauthenticated user is told to run 'bl login' immediately rather than after typing through the entire confirmation dialog. Reported by Devin Review on PR #299. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Aligns the CLI with controlplane PR #3941 (post semantic-flip):
- 'bl workspaces hipaa accept' now grants STANDING consent to deploy
in non-HIPAA-compliant regions/products (workspace.hipaaUnsafe=true).
- 'bl workspaces hipaa decline' revokes that standing consent
(workspace.hipaaUnsafe=false).
- 'bl workspaces hipaa status' reports whether non-HIPAA-compliant
deploys are allowed or blocked for the workspace.
The PUT body and GET response are renamed to 'hipaaUnsafe' to match the
new controlplane field.
Adds '--accept-not-hipaa' to 'bl deploy' and 'bl apply'. When set, every
resource upsert routed through handleResourceOperation sends the
X-Blaxel-Acknowledge-Not-Hipaa: true header so the controlplane permits
a single non-HIPAA-compliant deploy even when workspace.hipaaUnsafe is
false. The flag is process-scoped (set once per invocation) and applies
to every resource in the apply / deploy batch.
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
There was a problem hiding this comment.
LGTM
Previous comment (client nil-check before prompt) was addressed in 83d59b7. The semantic flip and --accept-not-hipaa flag in ba9bce9 are correctly implemented — package-level process-scoped state is appropriate for a CLI, header injection is in the right place, and the confirmation prompt logic is sound. No correctness, security, or data-loss issues.
Tag @mendral-app with feedback or questions. View session
bl workspaces hipaa accept|decline|statusbl workspaces hipaa accept|decline|status + --accept-not-hipaa on deploy/apply
Summary
CLI complement to the HIPAA opt-in feature landing in
controlplane#3941. Adds three subcommands underbl workspaces hipaa:bl workspaces hipaa acceptPUT /workspaces/{name}/hipaawithhipaaOptIn=truebl workspaces hipaa declinePUT /workspaces/{name}/hipaawithhipaaOptIn=falsebl workspaces hipaa statusGET /workspaces/{name}, printsaccepted/declinedacceptanddeclineprompt with[y/N]on an interactive TTY; pass-y/--yes(or run without a TTY plus--yes) to skip the prompt in CI.-w/--workspaceflag still targets a non-current workspace.HipaaOptInfield onWorkspaceyet, so the commands use the genericclient.Get/client.Putdirectly against the new controlplane endpoint and decode the response into a small local struct. When the SDK is regenerated post-merge, this code keeps working with no changes required.bl deploy/bl applyalready pipe controlplane 4xx responses throughextractErrorMessage(cli/apply.go), which reads theerrorfield on the JSON body — exactly the field the HIPAA validation incontrolplane#3941populates. The CP message ("HIPAA compliance is required to deploy …") will surface verbatim in the deploy failure line.Review & Testing Checklist for Human
bl workspaces hipaa accepton a workspace whose admin has not previously toggled the flag — confirm the workspace settings UI in app reflects the new value after the call.bl workspaces hipaa accept --yesfrom a non-TTY (e.g. piped) succeeds; without--yesit should refuse with a clear stderr message.bl deployagainst a HIPAA-gated region withhipaaOptIn=false— verify the failure line shows the controlplane HIPAA error (not a generic 400). This is exercised by the same regions configured incontrolplane#3941'shipaaBlocking.productsmap.bl workspaces hipaa accept— should surface the controlplane's 403/permission error verbatim.Notes
client.Workspaces.UpdateHipaa(...)if desired, but the current generic-client approach has no migration cost.Link to Devin session: https://app.devin.ai/sessions/485196f78a1e4fd19e97919a72ac3bd1
Requested by: @Joffref
Note
Adds
bl workspaces hipaa accept|decline|statussubcommands to manage workspace-level HIPAA consent (hipaaUnsafeflag). Also adds--accept-not-hipaatobl deploy/bl applyfor per-invocation consent via anX-Blaxel-Acknowledge-Not-Hipaaheader. Uses the generic HTTP client with a local struct to work aroundsdk-gonot yet exposing the new field.Written by Mendral for commit ba9bce9.