feat(registry): service stage semantics + sandbox admin list improvements
Deploy to Production / deploy (push) Successful in 3m16s

- Sandbox search without ?stage= defaults to DEVELOPMENT (was PRODUCTION),
  so freshly registered services are discoverable by default
- DEPRECATED and DECOMMISSIONED rejected at creation with 400 (lifecycle-only)
- PRODUCTION accepted at creation for established services going live immediately
- Admin sandbox list now returns non-null createdAt and expiresAt (toInstant fix
  for Hibernate 6 returning LocalDateTime from timestamptz native queries)
- Admin UI sandbox list shows Created column
- BDD: sandbox-admin-list.feature + sandbox-stage.feature (47 scenarios, all green)

Co-Authored-By: Mira Rehfeld <noreply@anthropic.com>
This commit is contained in:
Carsten Rehfeld
2026-05-18 22:30:21 +02:00
parent 1fd481a2d9
commit c2532fc241
5 changed files with 198 additions and 15 deletions
@@ -83,6 +83,7 @@ tr:hover td { background: #161b22; }
<th>Services</th>
<th>Requests</th>
<th>Location</th>
<th>Created</th>
<th>Expires</th>
</tr>
</thead>
@@ -96,6 +97,7 @@ tr:hover td { background: #161b22; }
<td>{sb.serviceCount}</td>
<td>{sb.totalRequests}</td>
<td>{#if sb.location != null}{sb.location}{#else}<span style="color:#484f58"></span>{/if}</td>
<td data-created="{sb.createdAt}" style="color:#8b949e">{sb.createdAt}</td>
<td class="{#if sb.expired}expired{#else}ok{/if}" data-expires="{sb.expiresAt}">{sb.expiresAt}</td>
</tr>
{/for}
@@ -119,6 +121,10 @@ document.querySelectorAll('[data-expires]').forEach(td => {
const days = Math.round((d - now) / 86400000);
td.textContent = days < 0 ? ('expired ' + (-days) + 'd ago') : ('in ' + days + 'd');
});
document.querySelectorAll('[data-created]').forEach(td => {
const d = new Date(td.dataset.created);
td.textContent = d.toISOString().slice(0, 10);
});
</script>
</body>
</html>