# DetachLabelFromPipelineItem

## Permission Scope

itemLabel

## Overview

Detaches a previously attached label from an item by deleting the PipelineItemLabel join row. Neither the label nor the item is otherwise modified.

## Business Rules

- The pair (itemId, labelId) must already exist as a PipelineItemLabel row
- An [PipelineItemChange](../model/PipelineItemChange.md) row is appended (changeType=LABEL, prevValue=labelId)

## Process Flow

```mermaid
flowchart TD
    A[Receive detachLabelFromPipelineItem input] --> B{PipelineItemLabel row exists?}
    B -->|No| C[Return LABEL_NOT_ATTACHED]
    B -->|Yes| D[Delete the PipelineItemLabel row]
    D --> F[Append PipelineItemChange row - LABEL]
    F --> E[Return deleted PipelineItemLabel]
```

## External Dependencies

- None

## Error Scenarios

- **LABEL_NOT_ATTACHED**: The label is not attached to the item

## Test Cases

- detaches an existing label from the item
- writes a PipelineItemChange for label detach
- returns error when the label is not attached to the item
