---
phase: 39-barkey-dataclass-clickhouse-layer
plan: 01
subsystem: api
tags: [dataclass, refactoring, expand-contract, clickhouse]

# Dependency graph
requires: []
provides:
  - "BarKey frozen dataclass in python/opendeviationbar/types.py"
  - "_resolve_bar_key() expand-contract helper"
  - "27 ClickHouse functions accepting BarKey as first argument"
affects: [40-barkey-orchestration-kintsugi, 42-barkey-deprecation-removal]

# Tech tracking
tech-stack:
  added: []
  patterns:
    - "Expand-contract: _resolve_bar_key() destructures BarKey back to locals at function entry"
    - "Function-level import of _resolve_bar_key to avoid circular imports"
    - "TYPE_CHECKING import of BarKey for type annotations"

key-files:
  created:
    - python/opendeviationbar/types.py
  modified:
    - python/opendeviationbar/__init__.py
    - python/opendeviationbar/clickhouse/bulk_operations.py
    - python/opendeviationbar/clickhouse/query_operations.py
    - python/opendeviationbar/clickhouse/maintenance.py
    - python/opendeviationbar/clickhouse/bar_count_api.py
    - python/opendeviationbar/clickhouse/checkpoint_operations.py
    - python/opendeviationbar/clickhouse/cache.py
    - python/opendeviationbar/clickhouse/write_lock.py

key-decisions:
  - "BarKey import inside function body (not module level) to avoid circular imports"
  - "deduplicate_bars uses isinstance check instead of _resolve_bar_key due to None-able params"
  - "Parameters after threshold_decimal_bps given defaults to satisfy Python syntax when threshold becomes optional"

patterns-established:
  - "Expand-contract 3-line block: import _resolve_bar_key, resolve key, destructure to locals"
  - "BarKey in TYPE_CHECKING block for annotations, _resolve_bar_key at runtime"

requirements-completed: [BARKEY-01, BARKEY-02, BARKEY-05]

# Metrics
duration: 22min
completed: 2026-03-30
---

# Phase 39 Plan 01: BarKey Dataclass + ClickHouse Layer Summary

**Frozen BarKey(symbol, threshold_decimal_bps, ouroboros_mode) dataclass with expand-contract adoption across all 27 ClickHouse layer functions**

## Performance

- **Duration:** 22 min
- **Started:** 2026-03-30T13:01:40Z
- **Completed:** 2026-03-30T13:23:44Z
- **Tasks:** 3
- **Files modified:** 9

## Accomplishments

- Created BarKey frozen dataclass in types.py with \_resolve_bar_key expand-contract helper
- Updated all 27 ClickHouse layer functions across 7 files to accept BarKey as first argument
- Full backward compatibility preserved: all existing callers pass (symbol, threshold) unchanged
- Re-exported BarKey from opendeviationbar.**init** for public API access

## Task Commits

Each task was committed atomically:

1. **Task 1: Create BarKey dataclass and resolve helper** - `0b42213` (feat)
2. **Task 2: Update 27 ClickHouse functions** - `77e4889` (refactor)
3. **Task 3: Verify backward compatibility** - verification only, no commit needed

## Files Created/Modified

- `python/opendeviationbar/types.py` - BarKey frozen dataclass + \_resolve_bar_key helper (NEW)
- `python/opendeviationbar/__init__.py` - Re-export BarKey, add to **all**
- `python/opendeviationbar/clickhouse/bulk_operations.py` - 6 functions updated (BulkStoreMixin)
- `python/opendeviationbar/clickhouse/query_operations.py` - 6 functions updated (QueryOperationsMixin)
- `python/opendeviationbar/clickhouse/maintenance.py` - 6 functions updated (MaintenanceMixin)
- `python/opendeviationbar/clickhouse/bar_count_api.py` - 3 functions updated (BarCountMixin)
- `python/opendeviationbar/clickhouse/checkpoint_operations.py` - 4 functions updated (CheckpointOperationsMixin)
- `python/opendeviationbar/clickhouse/cache.py` - 1 function updated (invalidate_open_deviation_bars_by_range)
- `python/opendeviationbar/clickhouse/write_lock.py` - 1 function updated (cache_write_lock)

## Decisions Made

- BarKey uses function-level import of \_resolve_bar_key (not module-level) to prevent circular imports between types.py and ouroboros.py
- deduplicate_bars special-cased with isinstance(BarKey) check because both symbol and threshold are legitimately None for the "optimize all" mode
- Parameters after threshold_decimal_bps (e.g. start_date, end_date in checkpoint ops) given empty-string defaults to satisfy Python syntax requirement that default-having params cannot precede non-default params

## Deviations from Plan

None - plan executed exactly as written.

## Known Stubs

None - all functions are fully wired.

## Issues Encountered

- Pre-existing test failures unrelated to this change: test_ouroboros.py (OrphanedBarMetadata import), test_arrow_input_oracle.py (field naming), test_heartbeat_health_levels.py (severity assertion). None are caused by BarKey changes.

## User Setup Required

None - no external service configuration required.

## Next Phase Readiness

- Phase 40 can proceed: BarKey is available and all CH functions accept it
- Orchestration layer (kintsugi, sidecar, checkpoint) callers can adopt BarKey in Phase 40
- Phase 42 will remove deprecated individual-param paths after full adoption

---

_Phase: 39-barkey-dataclass-clickhouse-layer_
_Completed: 2026-03-30_
