diff --git a/core/application/addon_hostgrants.go b/core/application/addon_hostgrants.go index b5ee04275a..20faf5c0f9 100644 --- a/core/application/addon_hostgrants.go +++ b/core/application/addon_hostgrants.go @@ -363,7 +363,12 @@ func (g *addonHostGrants) Stage(ctx context.Context, s addons.GrantStage) error } blanketMode = m[1] blanketRev, _ = strconv.ParseUint(m[2], 10, 64) - source = hostgrants.SourceBlanket + // Revision 0 means the switch was never set in the document: the + // deployment fixed the mode. Those grants stay the install's own, since + // a blanket grant must name a revision of the document. + if blanketRev != 0 { + source = hostgrants.SourceBlanket + } } for range 3 { snap, err := g.store.Snapshot(ctx) @@ -414,7 +419,7 @@ func (g *addonHostGrants) Stage(ctx context.Context, s addons.GrantStage) error patch.Addons = map[string]*hostgrants.AddonGrants{s.AddonID: &entry} ev := hostgrants.AuditGrant tag := "" - if source == hostgrants.SourceBlanket { + if s.Blanket != "" { ev, tag = hostgrants.AuditBlanketGrant, blanketMode+"@rev"+strconv.FormatUint(blanketRev, 10) } _, err = g.store.UpdateAudited(ctx, patch, snap.Revision, "stage-"+s.OperationID+"-r"+strconv.FormatUint(snap.Revision, 10), func(n hostgrants.Snapshot) error { diff --git a/core/services/addons/hostgrants/document.go b/core/services/addons/hostgrants/document.go index 0a0451bba0..6a5ba7522f 100644 --- a/core/services/addons/hostgrants/document.go +++ b/core/services/addons/hostgrants/document.go @@ -357,9 +357,7 @@ func validate(s Snapshot) error { if !validText(op.By) || !validText(op.Version) || !validTime(op.At) { return invalid("metadata of %q for %q", op.Name, id) } - // Revision 0 on a blanket grant means the deployment fixed the mode and - // the document never held it. - if (op.Source != SourceBlanket && op.BlanketRevision != 0) || op.BlanketRevision > s.Blanket.Revision { + if (op.Source == SourceBlanket) != (op.BlanketRevision != 0) || op.BlanketRevision > s.Blanket.Revision { return invalid("blanket revision of %q for %q", op.Name, id) } }