Admin already has POST /api/admin/v1/vms (admin_create_vm, lnvps_api_admin/src/admin/vms.rs:1230) for any user — takes template_id, image_id, ssh_key_id, ref_code, reason, dispatches WorkJob::CreateVm async, returns a job id.
No admin SSH-key management needed — struck from the ask. ssh_key_id already just references one of the target user's own keys (verified server-side to belong to user_id); users manage their own keys today via the existing ssh-key routes. Confirmed 2026-07-30 — my original flag on this was wrong, based on there being no admin-owned ssh-key route rather than reading what admin_create_vm actually requires.
The actual gap
admin_create_vm/WorkJob::CreateVm only accept template_id (the fixed VmTemplate catalog) — no path to a custom spec. Templates are a shrinking share of real orders; most are custom-spec today.
The customer side already does this end to end: v1_create_custom_vm_order (lnvps_api/src/api/routes.rs:1081) takes ApiCustomVmRequest (cpu/memory/disk/disk_type/disk_interface/cpu_mfg/cpu_arch/cpu_feature/pricing_id), converts it to a VmCustomTemplate (lnvps_api/src/api/model.rs:747), and calls sub_handler.vm_provisioner().provision_custom(...) synchronously (no job queue involved). Region comes from pricing_id → VmCustomPricing.region_id — VmCustomTemplate itself carries no region field (lnvps_db/src/model.rs:1200, 1229).
Admin needs the same inputs: user + region (via a VmCustomPricing in that region) + spec + image + the user's existing ssh key, then create. Open implementation call: keep admin creation on the existing async job-queue shape (extend WorkJob::CreateVm, or add a variant, worker calls provision_custom), or have admin_create_vm call provision_custom directly like the customer route does. Either way, spec validation/pricing/provisioning already exist and run daily on the customer path — this is substantially wiring, not new provisioning logic.
Not settled
Whether the fixed-template admin create path stays alongside this once it ships, given templates are barely used for real orders now.
Admin already has
POST /api/admin/v1/vms(admin_create_vm,lnvps_api_admin/src/admin/vms.rs:1230) for any user — takestemplate_id,image_id,ssh_key_id,ref_code,reason, dispatchesWorkJob::CreateVmasync, returns a job id.No admin SSH-key management needed — struck from the ask.
ssh_key_idalready just references one of the target user's own keys (verified server-side to belong touser_id); users manage their own keys today via the existing ssh-key routes. Confirmed 2026-07-30 — my original flag on this was wrong, based on there being no admin-owned ssh-key route rather than reading whatadmin_create_vmactually requires.The actual gap
admin_create_vm/WorkJob::CreateVmonly accepttemplate_id(the fixedVmTemplatecatalog) — no path to a custom spec. Templates are a shrinking share of real orders; most are custom-spec today.The customer side already does this end to end:
v1_create_custom_vm_order(lnvps_api/src/api/routes.rs:1081) takesApiCustomVmRequest(cpu/memory/disk/disk_type/disk_interface/cpu_mfg/cpu_arch/cpu_feature/pricing_id), converts it to aVmCustomTemplate(lnvps_api/src/api/model.rs:747), and callssub_handler.vm_provisioner().provision_custom(...)synchronously (no job queue involved). Region comes frompricing_id→VmCustomPricing.region_id—VmCustomTemplateitself carries no region field (lnvps_db/src/model.rs:1200,1229).Admin needs the same inputs: user + region (via a
VmCustomPricingin that region) + spec + image + the user's existing ssh key, then create. Open implementation call: keep admin creation on the existing async job-queue shape (extendWorkJob::CreateVm, or add a variant, worker callsprovision_custom), or haveadmin_create_vmcallprovision_customdirectly like the customer route does. Either way, spec validation/pricing/provisioning already exist and run daily on the customer path — this is substantially wiring, not new provisioning logic.Not settled
Whether the fixed-template admin create path stays alongside this once it ships, given templates are barely used for real orders now.