Problem
The deployer-ui multi-tab lock design polls a backend endpoint that does not exist. In range42-deployer-ui, src/services/projectRepo/adapter.ts:231 starts a SharedWorker that does POST /v1/projects/{id}/heartbeat every 60s (the comment at :227 even calls it a "shim, spec §4"). There is no such route under app/routes/v1/projects/, so once the UI wires lock acquisition live, the worker will 404 every 60s.
Current state
- Project routes implement list / create / patch / compose / validate only (
app/routes/v1/projects/). No heartbeat / lock / unlock.
- A DB-backed lock with heartbeat already exists, but only at deployment scope:
WorkspaceLock model — app/core/models.py:136 (owner, acquired_at, heartbeat_at, heartbeat_interval_s)
acquire_lock / release_lock / heartbeat / cleanup_stale_locks — app/core/locks.py:34-102 (stale threshold = 3 × interval)
- Used during attempt start (
app/core/deploy_trigger.py:63-82) but no HTTP surface exposes it.
So there is no server-side notion of "who is currently editing this project."
Decision needed
- Add project-scoped session endpoints, reusing
app/core/locks.py:
POST /v1/projects/{id}/lock (acquire, returns owner/lease)
POST /v1/projects/{id}/heartbeat (refresh lease)
POST /v1/projects/{id}/unlock (release)
- Lets the backend detect concurrent editors across browsers/devices (the git
.lock file only coordinates within a shared repo).
- Or declare project locking purely client-side (git
.lock file) and remove the heartbeat worker's backend dependency in the UI.
Option 1 is the smaller change given locks.py already has the machinery; it just needs a project-scoped table/owner key + 3 thin routes.
Related
Blocks the lock-heartbeat sub-task of range42-deployer-ui#96 (activate git-backed live editing). Surfaced during a cross-repo analysis of the git-backed-projects pipeline.
Problem
The deployer-ui multi-tab lock design polls a backend endpoint that does not exist. In
range42-deployer-ui,src/services/projectRepo/adapter.ts:231starts a SharedWorker that doesPOST /v1/projects/{id}/heartbeatevery 60s (the comment at:227even calls it a "shim, spec §4"). There is no such route underapp/routes/v1/projects/, so once the UI wires lock acquisition live, the worker will 404 every 60s.Current state
app/routes/v1/projects/). Noheartbeat/lock/unlock.WorkspaceLockmodel —app/core/models.py:136(owner, acquired_at, heartbeat_at, heartbeat_interval_s)acquire_lock/release_lock/heartbeat/cleanup_stale_locks—app/core/locks.py:34-102(stale threshold = 3 × interval)app/core/deploy_trigger.py:63-82) but no HTTP surface exposes it.So there is no server-side notion of "who is currently editing this project."
Decision needed
app/core/locks.py:POST /v1/projects/{id}/lock(acquire, returns owner/lease)POST /v1/projects/{id}/heartbeat(refresh lease)POST /v1/projects/{id}/unlock(release).lockfile only coordinates within a shared repo)..lockfile) and remove the heartbeat worker's backend dependency in the UI.Option 1 is the smaller change given
locks.pyalready has the machinery; it just needs a project-scoped table/owner key + 3 thin routes.Related
Blocks the lock-heartbeat sub-task of range42-deployer-ui#96 (activate git-backed live editing). Surfaced during a cross-repo analysis of the git-backed-projects pipeline.