package hostops import ( "context" "crypto/ed25519" "slices" "github.com/carlosframework/platform/internal/hostclaim" "github.com/carlosframework/platform/internal/hostfence" "github.com/carlosframework/platform/internal/hostresolve" "github.com/carlosframework/platform/internal/release" ) // MoveLossKind reports a claim op kind whose target loss the moves owner // resolves. Doors use it only to route; the typed methods check again. func MoveLossKind(kind string) bool { return slices.Contains(moveLossKinds, kind) } // InspectMoveLoss is ControlWriter.InspectMoveLoss under the authority's // own root signer and deployment bucket. func (a *ProductionAuthority) InspectMoveLoss(ctx context.Context, actor, account, app, host, box string) (hostresolve.Inspection, error) { if a == nil || a.Control == nil { return hostresolve.Inspection{}, ErrContract } return a.Control.InspectMoveLoss(ctx, a.Signer, a.Directory.Bucket, actor, account, app, host, box) } // DeclareMoveLoss is ControlWriter.DeclareMoveLoss under the authority's // own root signer and deployment bucket. func (a *ProductionAuthority) DeclareMoveLoss(ctx context.Context, actor, account, app, host, box string, in hostfence.Submission) error { if a == nil || a.Control == nil { return ErrContract } _, err := a.Control.DeclareMoveLoss(ctx, a.Signer, a.Directory.Bucket, actor, account, app, host, box, in) return err } // DeclaresMoveTargetLoss reports whether a submitted declaration's signed // challenge declares the loss of a move's target, the rollback path // (move-target-lost), and of which move and instance incarnation. A // destroyed-local-only declaration, which changes no move state, is not // one, and neither is a challenge that does not verify under pub. The move // log names only a target loss (Plan 6 final re-review 1, N1). func DeclaresMoveTargetLoss(pub ed25519.PublicKey, in hostfence.Submission) (op, incarnation string, ok bool) { var c hostfence.Challenge if len(pub) != ed25519.PublicKeySize || release.VerifyRootEnvelope(pub, in.Challenge, &c) != nil { return "", "", false } if c.Consequences.Transition != moveLossTransition || c.Op.ID == "" { return "", "", false } return c.Op.ID, c.HolderIncarnation, true } // MoveTargetLossOf reports whether a loss record's signed consequences are // the loss of a move's target (its recovery intent is move-target-lost), and // of which move and instance incarnation. A destroyed-local-only record is // not (Plan 6 final re-review 1, N1). func MoveTargetLossOf(l hostclaim.LossRecord) (op, incarnation string, ok bool) { in, err := decodeMoveLossIntent(l.ConfirmedConsequences.RecoveryIntent) if err != nil { return "", "", false } return in.Move, in.Incarnation, true }