# DDR-0022: Session Lifecycle and Framed vs Unframed Traffic Handling

Status: Approved
Date: 2025-12-22
Applies to: elkm1/elke27_lib (E27 only)

Related ADRs:
- ADR-0004: E27 Transport and Session Model
- ADR-0006: E27 Cryptographic Model and Key Handling

Related DDRs:
- DDR-0003: E27 Message Layer Architecture
- DDR-0015: E27 Link Layer Framing and Deframing
- DDR-0020: Silent Failure Behavior on Invalid Credentials
- DDR-0021: Cryptography Library Selection for E27 Implementation

---

Context

The Elk E27 protocol uses two distinct transport behaviors over a single TCP connection:

1. Unframed, clear-text JSON messages
2. Framed, encrypted binary messages

These behaviors vary by session phase and are not interchangeable. Incorrect framing or encryption results in silent panel failures and non-obvious timeouts.

---

Decision

The E27 session lifecycle is formally defined as follows:

Phase 1: Discovery
- Panel sends discovery JSON (e.g., ELKWC2017)
- Client sends API_LINK request
- Messages are clear-text JSON
- Messages are NOT framed
- Messages are NOT encrypted

Phase 2: Linking
- Client sends API_LINK request as clear-text JSON (unframed)
- Panel responds with framed, encrypted (schema-0) data
- Client decrypts response to obtain link key and link HMAC

Phase 3: Hello
- Client sends hello request as clear-text JSON (unframed)
- Panel responds with clear-text JSON containing encrypted fields
- Session key and session HMAC are decrypted using the link key

Phase 4: Authenticated Session
- All subsequent messages are:
  - Framed using E27 link-layer framing
  - Encrypted using the session key
  - Processed via the presentation layer

---

Implementation Rule

The session module SHALL be responsible for:
- Determining whether outgoing messages are framed or unframed
- Routing incoming bytes to either:
  - Direct JSON parsing for unframed traffic
  - The link-layer deframer for framed traffic

Lower layers MUST NOT infer session phase or framing requirements.

---

Rationale

This strict separation:
- Matches observed panel behavior
- Prevents accidental framing of API_LINK and hello messages
- Centralizes protocol state decisions in session.py
- Simplifies debugging and recovery from silent failures

The panel’s silent failure behavior makes this separation mandatory.

---

Consequences

- session.py is the authoritative owner of session state
- linking.py manages the API_LINK exchange but does not own socket state
- presentation.py assumes encrypted, framed payloads only
- Any future protocol extensions must explicitly define framing requirements

This decision is binding for all E27 session handling.
## Length field and CRC inclusion semantics (clarification)

Clarification
- The E27 length field (2 bytes, little-endian) includes the CRC.
- The length value covers:
    protocol byte
    + payload bytes (ciphertext or clear data)
    + CRC (2 bytes)
- The length does NOT include the start character (0x7E).

Wire format (conceptual)
    START (0x7E)
    PROTOCOL (1 byte)
    LENGTH (2 bytes, little-endian, clear)
    DATA (N bytes)
    CRC (2 bytes, little-endian)

Where:
    LENGTH = 1 (protocol)
           + N (data bytes)
           + 2 (CRC)

Transmission properties
- START (0x7E) is not counted in LENGTH.
- LENGTH and PROTOCOL are always transmitted in the clear.
- CRC is calculated over:
    protocol + length bytes + data
  and is included in the LENGTH count.

Rationale
- This matches the official API Communications Documentation.
- This behavior is consistent with observed panel traffic and Node-RED reference implementations.
- Including CRC in LENGTH allows the receiver to know frame termination before CRC validation.

Implications
- frame_build MUST:
    - compute CRC first,
    - append CRC,
    - then compute LENGTH including CRC.
- deframe_feed MUST:
    - treat CRC bytes as part of the frame payload length,
    - validate CRC only after full LENGTH bytes are received.
- Unit tests MUST assert:
    - correct LENGTH calculation for empty payloads,
    - correct handling of CRC-inclusive lengths,
    - rejection of frames where LENGTH excludes CRC.

Cross-references
- DDR-0021: E27 framing, escaping, and CRC validation rules
- DDR-0024: Framed vs unframed traffic lifecycle
- ADR-010x: E27 transport and framing architecture
