Skip to content

Application lifecycle

This document defines the lifecycle of an Application in Balyze.

It describes the possible states of a candidature, the allowed transitions between them, and the principles governing state changes.


Purpose of the lifecycle

The application lifecycle exists to:

  • represent the real progression of a candidature
  • enforce clear state transitions
  • prevent inconsistent or ambiguous application states
  • support future extensions without breaking existing rules

The lifecycle is explicit, finite, and intentionally constrained.


Application states

At the current stage, an Application can be in one of the following states:

Draft

The initial state of an application.

Characteristics:

  • the application has not been submitted
  • structural information may still be adjusted indirectly
  • no submission timestamp is set
  • the application is not considered active

This state is temporary and internal to the user.


Submitted

The application has been formally submitted.

Characteristics:

  • the submission timestamp (applied_at) is set
  • the application becomes historically relevant
  • structural data is frozen
  • contextual data remains editable

Once an application is submitted, it represents a point-in-time intent.


In progress

The application is actively being processed.

This state may represent:

  • ongoing exchanges
  • interviews
  • follow-ups
  • waiting periods

The application remains editable only within predefined contextual boundaries.


Rejected

The application process has ended unsuccessfully.

Characteristics:

  • no further progression is expected
  • the application is considered closed
  • historical data must remain intact

This is a terminal state.


Accepted

The application process has ended successfully.

Characteristics:

  • the application is considered completed
  • no further lifecycle transitions are expected
  • the application remains accessible for historical reference

This is a terminal state.


Allowed transitions

The lifecycle follows a strictly controlled transition graph:

  • draftsubmitted
  • submittedin_progress
  • in_progressrejected
  • in_progressaccepted

Transitions are intentionally unidirectional.


Forbidden transitions

The following transitions are explicitly not allowed:

  • returning to draft after submission
  • skipping directly from draft to terminal states
  • modifying structural data after submission
  • reopening a rejected or accepted application

These restrictions preserve historical consistency and simplify domain rules.


Editability and lifecycle interaction

Lifecycle transitions directly impact what data may be modified.

Key principles:

  • structural data is frozen after submission
  • contextual data remains editable throughout the lifecycle
  • lifecycle state changes are always explicit actions

Detailed editability rules are documented separately.


Enforcement strategy

Lifecycle rules are enforced at the domain service layer.

  • Controllers do not implement lifecycle logic
  • Models do not orchestrate transitions
  • Policies handle authorization, not lifecycle validity

This ensures consistent enforcement across all entry points.


Out of scope considerations

The following aspects are intentionally excluded at this stage:

  • automatic transitions
  • time-based state changes
  • external system synchronization
  • analytics-driven lifecycle extensions

These concerns may be revisited in later versions.


Rationale

This lifecycle favors clarity and predictability over flexibility.

By limiting transitions and freezing structural data early, the system:

  • avoids ambiguous application states
  • preserves historical accuracy
  • reduces long-term complexity

Future extensions can build upon this foundation without breaking existing assumptions.