package authz import "errors" // Typed rejection sentinels — one per pipeline stage so the reconcile layer can // distinguish "rejected" (a real signed op that failed a check) from "malformed" // from a future "not yet signed". All are errors.Is-friendly: Verify wraps them // with %w plus context. var ( // ErrMalformed: the armor/SSHSIG/blob could not be parsed (not a rejection of // a well-formed op — bad input). ErrMalformed = errors.New("authz: malformed signature or blob") // ErrNamespace: SSHSIG namespace != the fixed felhom-op-v1 domain separator. ErrNamespace = errors.New("authz: namespace mismatch") // ErrUnknownSigner: the signing key's material is not in the pinned allow-list. ErrUnknownSigner = errors.New("authz: signer not in allowed set") // ErrBadSignature: cryptographic verification failed (tamper / wrong key). ErrBadSignature = errors.New("authz: signature did not verify") // ErrTarget: target.host_id is not this box. ErrTarget = errors.New("authz: target mismatch") // ErrExpired: now > expires_at. ErrExpired = errors.New("authz: op expired") // ErrNotYetValid: now < issued_at (minus clock-skew tolerance). ErrNotYetValid = errors.New("authz: op not yet valid") // ErrReplay: the nonce was already recorded in the window. ErrReplay = errors.New("authz: replay (nonce already seen)") )