Skip to content

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 use
  • DEPRECATED โ€” 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_SYNC clearly communicates what the definition is waiting for (content synchronization)
  • DRAFT implies 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_name which 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)