package hostguard import ( "context" "github.com/carlosframework/platform/internal/hostclaim" ) // AdmissionFenced reports whether the host's admission is closed for the // installation and session captured names on claim c. It is With's own // reading of the record (record.admits), exposed for region HA ยง5.3's row // decision ("the source in releasing until its admission fence closes"): // closed whenever With would refuse on the record, so a stop root that // began (ActiveFence) or completed (a FenceJournal receipt) for that // session, and also an inactive or retired installation, a stamp that is // not the active one, or another incarnation on the record. Absence is // never evidence: a retired fenced installation still reads closed. With's // other refusals (no record, a malformed record, a claim for another host // or incarnation) are errors, never "open". It takes no lock: the record // is replaced atomically, and callers already hold the host lock // (Activate's reader, WithLocal) or need no lock for one consistent read. // The claim is the caller's fresh read. It grants nothing. func (g Guard) AdmissionFenced(host string, c *hostclaim.Claim, captured Captured) (bool, error) { if c == nil || c.Holder == nil { return false, ErrNoHolder } if c.Host != host || c.Holder.Incarnation == "" { return false, ErrMalformedClaim } if c.Holder.Incarnation != captured.Incarnation { return false, ErrClaimIncarnation } if g.Root != nil { r, err := g.Root.read(host) if err != nil { return false, err } return r.admits(c, captured) != nil, nil } if g.FenceView != nil { v, err := g.FenceView(context.Background(), host, captured) if err != nil { return false, err } if err := v.validate(host, captured); err != nil { return false, err } if v.admit(host, captured, c.Holder.Session) != nil { return true, nil } } r, err := readRecord(g.DataDir, host) if err != nil { return false, err } // Every refusal admits gives is a record state, never a read failure. return r.admits(c, captured) != nil, nil }