forked from retoor/devplacepy
A new tunnel row was inert at pending until the next WorkspaceService tick picked it up, so the editor certificate waited up to 30 seconds before the ACME order even started. Opening a workspace and reaching its public hostname in that window served the wildcard default certificate and produced ERR_CERT_COMMON_NAME_INVALID in the browser. certs.certify now owns the whole transition - provisioning, issue, active or failed, then the owner notification - and both callers use it. provision.ensure schedules it for the editor tunnel the moment the workspace exists, claiming the row synchronously so the tick can never issue the same host twice and burn a duplicate-certificate slot. The service loop keeps calling certify per pending row as the safety net for user-created tunnels and for rows created while molohttp was unconfigured. Issuance is a loop task rather than an await: an order takes about ten seconds and certs.issue allows up to 180, which would hang the workspace POST. The task is held until it completes so it cannot be collected mid flight. resume also restarts the idle clock, and the workspace routes gain HTTP-level tests covering every refusal path they had none for.