feat(admin): POST /api/instances creates a Free cloud instance
Provisions the control-plane instance and its owner, records the admin_instances row, issues and injects a Free licence, and emails the customer where it is and when it expires. Licence issuance and email cannot fail the request. The instance exists and the customer can sign in; rolling back something they can already see would be worse than shipping it unlicensed for staff to fix. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -18,6 +18,11 @@ const (
|
||||
StatusActive = "active"
|
||||
StatusLapsed = "lapsed"
|
||||
StatusCancelled = "cancelled"
|
||||
|
||||
// StatusDeleted marks an instance the control plane has reaped. The row is
|
||||
// kept because the licence history references it and support questions
|
||||
// outlive the instance.
|
||||
StatusDeleted = "deleted"
|
||||
)
|
||||
|
||||
// Account statuses.
|
||||
@@ -75,7 +80,12 @@ type Instance struct {
|
||||
CurrentLicense string `bson:"current_license,omitempty" json:"current_license,omitempty"`
|
||||
RelinkCount int `bson:"relink_count" json:"relink_count"`
|
||||
InjectFailedAt *time.Time `bson:"inject_failed_at,omitempty" json:"inject_failed_at,omitempty"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"created_at"`
|
||||
// NoticesSent holds the lifecycle notice keys already emailed for the
|
||||
// CURRENT term ("expiring", "expired", "delete_7", "delete_1"). Renewal
|
||||
// clears it, so the next term starts the sequence again. It is what stops a
|
||||
// restart re-sending a notice.
|
||||
NoticesSent []string `bson:"notices_sent,omitempty" json:"notices_sent,omitempty"`
|
||||
CreatedAt time.Time `bson:"created_at" json:"created_at"`
|
||||
}
|
||||
|
||||
// License is append-only. A renewal writes a new row and sets SupersededBy on
|
||||
|
||||
Reference in New Issue
Block a user