Revoke and recover
Revoke and recover
A license can be pulled. If you are an MVNE, you can pull one on an MVNO you provisioned. If you are an MVNO under the Hub, this is what would happen to you, and what would undo it.
What revocation is
Revocation is a change to a row on the parent's side, and nothing else. The parent marks the deployment revoked and revokes the license id it stamped. That is the entire action. It does not touch your cluster, because it cannot: there is no connection into it.
What the deployment does about it
It finds out on its own next check-in. Either the heartbeat comes back with lease_status: "revoked", or the next renewal gets a 410 Gone. Worst case that takes one PHONEHOME_INTERVAL (15 minutes by default).
Then it parks:
- The serving license is cleared from memory, and every gated business route answers
424 Failed Dependencywithparent lease revoked. Requests that fail authentication still get their401first, because the license gate sits behind auth. /healthstays up. The process does not exit, does not crash, and does not restart-loop. Kubernetes sees a healthy pod, and it is: it is quiesced, not broken.- Your data is untouched. The database is yours and it is still there, intact, with every row in it. Revocation stops the deployment serving. It deletes nothing.
- The heartbeat keeps running. A parked deployment keeps checking in, which is deliberate: the parent needs to see it parked rather than watch it go dark.
Restarting does not escape it. The park is in-memory, so a pod restart clears the flag, but the deployment comes straight back up holding a license the parent still considers revoked. It checks in, it is told revoked again, and it re-parks within seconds. The enforcement boundary is the parent, not any flag inside your cluster. There is nothing local to delete, reset, or edit that changes the answer.
The license agent behaves the same way. It writes LEASE_STATUS=revoked into the platform Secret, stops renewing, and starts polling that Secret every 30 seconds for one thing: a fresh activation code.
Deprovisioning is a separate, deliberate act. Revoking does not delete anything in your cluster. A full teardown is a revoke on the parent's side plus you running helm uninstall.
Recovering
Get a fresh activation code from the parent, then upgrade with it.
helm upgrade my-mvno solvegio/platform \
-f my-values.yaml \
--set activation.code=<new-code>
That is the whole runbook. There is no flag to set, no Job to delete, and no pod to restart.
Here is why it works. The helm upgrade changes the contents of the platform Secret, which is the object the license agent is already polling. The agent notices a code it has not consumed before, re-enrolls over the stale revoked license, clears LEASE_STATUS, and writes the fresh license back into the Secret. The API is watching /etc/platform/lease, so it picks the new license up in place and starts serving again. No rollout. Typically seconds.
Your signing key survives all of this. Recovery re-mints the license, and the deployment keeps its identity.
Confirm it landed:
kubectl -n my-mvno logs deploy/my-mvno-platform-license-agent --since=2m
kubectl -n my-mvno get secret my-mvno-platform-env \
-o jsonpath='{.data.PARENT_LEASE_TOKEN}' | base64 -d | head -c 20; echo
The agent's log shows the re-enrollment. A non-empty token confirms the Secret was patched. Then hit a gated route and check the 424 is gone.
Leaving the now-consumed code sitting in activation.code for your next ordinary upgrade is harmless. The agent has recorded it as consumed and will not replay it.
If recovery does not take
Two things to check before you reach for anything else.
The agent has to be running. It is a single-replica Deployment with a Recreate strategy, and that is a requirement, not a default worth tuning. Do not scale it up.
kubectl -n my-mvno get deploy my-mvno-platform-license-agent
And the code has to have actually reached the Secret. A helm upgrade that did not include --set activation.code=<new-code> renders the same Secret contents as before, and the agent correctly does nothing with a code it has already consumed.
kubectl -n my-mvno get secret my-mvno-platform-env \
-o jsonpath='{.data.ACTIVATION_CODE}' | base64 -d; echo
Anything beyond that belongs in Licensing failures.