feat(adminsite): licence delivery, paste instructions and relink

The blob is shown inline as well as offered as a file, because a licence is
signed public data bound to one instance -- useless anywhere else -- and a
blocked download must never leave a paying customer stuck. Admin now returns
it to its owner for the same reason.

Relink shows the remaining allowance from the backend's max_relinks rather
than a hardcoded 3, and at zero it disables and says to contact support
instead of failing at the API.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
mrhid6
2026-07-25 21:06:21 +01:00
co-authored by Claude Opus 5
parent 242a587340
commit 92ac1eeb62
6 changed files with 282 additions and 1 deletions
+9 -1
View File
@@ -146,7 +146,15 @@ func getInstanceLicense(c *gin.Context) {
c.JSON(http.StatusNotFound, gin.H{"error": "no licence issued yet"})
return
}
c.JSON(http.StatusOK, lic)
// The owner gets the blob itself: it is signed public data bound to their
// own instance, and the download endpoint hands over the same bytes. The
// struct tag hides it, so the fields are listed explicitly.
c.JSON(http.StatusOK, gin.H{
"license_id": lic.LicenseID, "instance_id": lic.InstanceID, "tier": lic.Tier,
"deployment": lic.Deployment, "limits": lic.Limits, "features": lic.Features,
"issued_at": lic.IssuedAt, "expires_at": lic.ExpiresAt, "reason": lic.Reason,
"issued_by": lic.IssuedBy, "blob": lic.Blob,
})
}
func downloadInstanceLicense(c *gin.Context) {