ADR-028: LabletDefinition Initial Status (PENDING_SYNC)¶
| Attribute | Value |
|---|---|
| Status | Accepted |
| Date | 2026-02-25 |
| Deciders | Architecture Team |
| Related ADRs | ADR-023 (Content Sync Trigger), ADR-027 (Version Auto-Increment) |
| Implementation | Content Synchronization Plan ยง2 (AD-CS-006), ยง3 (Phase 1) |
Context¶
LabletDefinitions go through a lifecycle from creation to active use in LabletSessions. The content synchronization feature introduces a new constraint: definitions must have their content package downloaded from Mosaic and stored in RustFS before they can be used for session creation.
This raises the question of what status a newly created definition should have, and what controls should apply before content is synchronized.
Current Status Enum¶
The existing LabletDefinitionStatus includes:
ACTIVEโ Definition is ready for useDEPRECATEDโ Definition has been superseded (still usable for existing sessions)DELETEDโ Soft-deleted (not usable)
Problem¶
If new definitions are created as ACTIVE, a LabletSession could be scheduled against a definition that has no content in RustFS, causing session instantiation failure (no SVN.zip to deliver to LDS).
Decision¶
1. New Status: PENDING_SYNC¶
Add PENDING_SYNC to LabletDefinitionStatus:
class LabletDefinitionStatus(str, Enum):
PENDING_SYNC = "PENDING_SYNC" # NEW: Created, awaiting content sync
ACTIVE = "ACTIVE" # Ready for LabletSession creation
DEPRECATED = "DEPRECATED" # Superseded by newer version
DELETED = "DELETED" # Soft-deleted
2. Creation โ PENDING_SYNC¶
All new definitions are created with status = PENDING_SYNC:
CreateLabletDefinitionCommand โ LabletDefinition.create()
โ status = PENDING_SYNC
โ sync_status = None (not yet requested)
3. PENDING_SYNC Permissions¶
| Operation | Allowed on PENDING_SYNC? | Notes |
|---|---|---|
| Edit (update fields) | โ Yes | Users can refine definition before sync |
| Synchronize (trigger sync) | โ Yes | User must explicitly click "Synchronize" |
| Create LabletSession | โ No | Blocked โ no content available |
| Deprecate | โ Yes | User can abandon before sync |
| Delete | โ Yes | User can discard |
4. Status Transitions¶
PENDING_SYNC โ (user triggers sync) โ sync_status=sync_requested
โ (content sync succeeds) โ ACTIVE
โ (content sync fails) โ PENDING_SYNC (with error, can retry)
ACTIVE โ (re-sync detects change) โ DEPRECATED
โ new version created as ACTIVE (see ADR-027)
ACTIVE โ (user deprecates) โ DEPRECATED
ACTIVE โ (user deletes) โ DELETED
PENDING_SYNC โ (user deletes) โ DELETED
5. Session Creation Guard¶
The CreateLabletSessionCommand handler must validate:
if definition.state.status != LabletDefinitionStatus.ACTIVE:
return self.bad_request(
f"Definition '{definition.state.name}' v{definition.state.version} "
f"is {definition.state.status.value} โ only ACTIVE definitions can be used"
)
Rationale¶
Why PENDING_SYNC (not DRAFT)?¶
PENDING_SYNCclearly communicates what the definition is waiting for (content synchronization)DRAFTimplies the user is still editing, which is a separate concern (editing is allowed in PENDING_SYNC)- The name aligns with the sync pipeline terminology used throughout the system
Why not auto-sync on creation?¶
- Content sync requires a
form_qualified_namewhich must resolve in Mosaic โ this may fail - Users may want to configure all fields before triggering sync
- Sync involves external network calls (Mosaic, RustFS) that could be slow or fail
- Explicit sync gives users control over timing and retry
Why block session creation (not warn)?¶
- A session without content in RustFS will fail at instantiation (LDS cannot find
SVN.zip) - Allowing creation and deferring the error creates a confusing user experience
- Hard blocking is consistent with the existing validation pattern in
CreateLabletSessionCommandHandler
Why allow edits in PENDING_SYNC?¶
- Users may create a definition, realize a field is wrong, and want to fix it before sync
- No content has been downloaded yet, so there's no consistency concern
- Reduces friction โ no need to delete and recreate to fix a typo
Consequences¶
Positive¶
- Prevents session creation against unsynchronized definitions (eliminates a class of runtime failures)
- Clear lifecycle: PENDING_SYNC โ ACTIVE โ DEPRECATED/DELETED
- User retains full control (edit before sync, explicit sync trigger)
- Consistent with the sync pipeline flow (definition must have content before use)
Negative¶
- Adds a state to the lifecycle (increased status management complexity)
- Users must take an explicit action (click "Synchronize") after creation
- UI must display the PENDING_SYNC status clearly and guide users to the sync action
Risks¶
- User confusion: "Why can't I create a session?" (mitigated: clear error message with status and guidance)
- Stale PENDING_SYNC definitions: users create but never sync (mitigated: UI can show a warning, and admins can clean up via list filter)