mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-28 20:21:50 +01:00
The automatic default only covers services that start after the deploy. A workspace that was already running when the feature landed would keep serving `http://127.0.0.1:<port>` as its canonical URL indefinitely, because startup reconciliation adopted any healthy backend as-is. Startup reconciliation now classifies every persisted managed row through `decideManagedRuntimeExposureBackfill` and stops the eligible HTTP-only ones, so the desired-state restart that already runs at the end of reconciliation brings them back through the ordinary fail-closed exposure lifecycle — same workspace, same runtime-service row, relocated port only when the old one cannot be published. The decision function is pure and every branch carries a reason code, because "which pre-feature workspaces get touched" is the whole risk of this change: - `already_exposed` makes repeated deploys and restarts converge instead of churning listeners. - `deliberate_opt_out` is checked before broker availability, so an opt-out never depends on host state. - `no_configured_service_entry` refuses to stop a row we could not restart — reprovisioning works by stopping the backend and letting desired state bring it back, so without a config entry we would take a service down for good. - `stopped_defaults_on_next_start` leaves stopped rows to the start path. A backfilled row also drops its HTTP `url` at the moment it is stopped rather than keeping it until the restart succeeds: if the restart fails, the fail-closed contract is no URL, not a working HTTP one. The shared supertest setup pins `PAPERCLIP_MANAGED_RUNTIME_HTTPS=off` so suites that start a service named `paperclip-dev` do not behave differently on a broker-capable host than on CI; the suites that exercise the default opt back in. Covered: 12 decision branches, plus an end-to-end integration test that starts a pre-feature workspace on a pinned legacy port over plain HTTP, reconciles, and asserts the same row comes back on a verified `https://<host>:<42xxx>` URL with the old HTTP backend gone — then reconciles again and asserts zero broker calls and an unchanged port.