fix(addons): keep grants made under a deployment blanket as the install's own

The document validator requires a blanket grant to name a revision of the
switch in the document. A deployment-fixed mode is never written there,
so its grants have no revision to name. Record them as the grant of the
install or upgrade that made them; the audit line still carries the
blanket tag.

Assisted-by: Claude:claude-sonnet-5-5 go
This commit is contained in:
Ettore Di Giacinto committed 2026-11-03 22:52:09 +00:00
1 parent 5d194ceab5
commit 2140e56aa5
2 files changed
+8 -5

No files matched your search

+7 -2
View File
@@ -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 {
+1 -3
View File
@@ -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)
}
}