Operator actions in the report reply (D1, R-314/R-279/R-177, decision 185)
The hub may ask the running controller for a CLOSED list of actions, carried in the report ACK (operator_actions) and answered on the next report (operator_action_results): offsite_backup_now, abandon_stop, abandon_extend (1-30 days), run_job (fill-watch, offsite-integrity, offsite-proof, disk-health-check). Unknown action/job/argument -> refused, nothing called. Once per id (in memory; every action is safe to repeat). - internal/report/opactions.go: the executor; results re-sent until the hub stops listing the id. - scheduler.RunNow: refuses unknown / already-running jobs; OnDemand(ctx) makes an operator's offsite-integrity run even when not due. - ExtendAbandon never shortens the countdown and refuses in the hub phase; StopAbandon reports failure when the hub cancel failed (it said success). - Report ACK read cap 4 KiB -> 64 KiB (an ACK over the cap dropped every field in it). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
@@ -51,8 +51,14 @@ type PushResponse struct {
|
||||
// Claim (v0.122.0, F-4) — the hub's active claim-code state (bcrypt hash + generation) for
|
||||
// the customer-claim gate. nil on an old hub / no claim row → the cache stays as-is.
|
||||
Claim *ClaimStatus `json:"claim"`
|
||||
// OperatorActions (R-314/R-279/R-177, `09` §3 decision 185) — the operator's pending actions for
|
||||
// this box, listed until their result arrives (opactions.go). Absent on an old hub = none.
|
||||
OperatorActions []OperatorAction `json:"operator_actions"`
|
||||
}
|
||||
|
||||
// maxPushResponseBytes bounds the report ACK read (see Push).
|
||||
const maxPushResponseBytes = 64 << 10
|
||||
|
||||
// Pusher sends reports to the central hub.
|
||||
type Pusher struct {
|
||||
hubURL string
|
||||
@@ -126,8 +132,10 @@ func (p *Pusher) Push(report *Report) error {
|
||||
continue
|
||||
}
|
||||
|
||||
// Read response body to parse customer_blocked field
|
||||
respBody, _ := io.ReadAll(io.LimitReader(resp.Body, 4096))
|
||||
// Read response body to parse customer_blocked field. The cap was 4 KiB; an ACK over it fails to
|
||||
// parse and EVERY field in it is dropped (floor, config version, escrow, operator actions), so it
|
||||
// is 64 KiB now — far above any real ACK, still a bound.
|
||||
respBody, _ := io.ReadAll(io.LimitReader(resp.Body, maxPushResponseBytes))
|
||||
resp.Body.Close()
|
||||
|
||||
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
|
||||
|
||||
Reference in New Issue
Block a user