hub v0.39.0: offsite hardening — F4 credential re-issue, F2 scan retry, F5 save UX
F4: ReissueCredentials — explicit operator recovery for consumed-password dead-ends; resets the labelled resource's password (exactly-1 guard, red-proofed), stores a fresh one-time secret, bumps ConfigVersion. New hetznerapi.ResetBoxPassword for the dedicated path. F2: host-key scan retry-with-backoff (~60s ladder, red-proofed) — first save survives fresh-subaccount DNS lag. F5: config form disables submits + shows an in-flight notice (the re-click bait that caused live F1). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PSK5g6qYLknKj8u3QAFEr6
This commit is contained in:
@@ -96,6 +96,7 @@ type CloudAPI interface {
|
||||
GetStorageBox(ctx context.Context, boxID int64) (StorageBox, error)
|
||||
CreateStorageBox(ctx context.Context, req CreateBoxRequest) (createdID int64, action Action, err error)
|
||||
ChangeType(ctx context.Context, boxID int64, boxType string) (Action, error)
|
||||
ResetBoxPassword(ctx context.Context, boxID int64, password string) (Action, error)
|
||||
DeleteStorageBox(ctx context.Context, boxID int64) (Action, error)
|
||||
|
||||
// WaitAction polls the action to "success" (bounded); errors on "error" or timeout.
|
||||
@@ -270,6 +271,16 @@ func (c *Client) ChangeType(ctx context.Context, boxID int64, boxType string) (A
|
||||
return out.Action, err
|
||||
}
|
||||
|
||||
// ResetBoxPassword resets a dedicated box's (main-account) password. The password value is only ever in
|
||||
// the request body — never logged by the caller (F4 re-issue).
|
||||
func (c *Client) ResetBoxPassword(ctx context.Context, boxID int64, password string) (Action, error) {
|
||||
var out struct {
|
||||
Action Action `json:"action"`
|
||||
}
|
||||
err := c.do(ctx, http.MethodPost, fmt.Sprintf("/storage_boxes/%d/actions/reset_password", boxID), map[string]string{"password": password}, &out)
|
||||
return out.Action, err
|
||||
}
|
||||
|
||||
func (c *Client) DeleteStorageBox(ctx context.Context, boxID int64) (Action, error) {
|
||||
var out struct {
|
||||
Action Action `json:"action"`
|
||||
|
||||
Reference in New Issue
Block a user