release: 0.1.28

## Bump

- [ ] Major
- [ ] Minor
- [x] Patch

## Changelog

### Added

- `deploy_validation_pipeline` Mode 4: DataProduct + DMS mode — loads settings from DMS, discovers view configs from DataProduct API, and fires all orchestrators with `wait=False`; `view_external_id` now accepts `str | list[str] | None` to filter specific views
- `build_deployment_settings_from_props()` as canonical DMS-to-DeploymentSettings mapping in `_containers.py`

### Fixed

- `data_product_sync.py` missing from function zip bundle (caused `ModuleNotFoundError` in deployed function)
- DMS read failures: use `ViewId` instead of container ID so `Properties.load()` parses properties correctly
- DMS write failures: use `ContainerId` for `NodeOrEdgeData` source in `_save_sync_state`
- Timestamps stored as milliseconds integers instead of ISO 8601 strings (caused `CogniteAPIError`)
- `trigger_external_id_prefix` never stored in DMS container schema or upsert dict
- `TriggerSettings.external_id_prefix` missing default value (caused `ValidationError` for nodes deployed before fix)
- `list_versions` default limit exceeded CDF API max of 10
- `shacl_file_external_id` required in orchestrator even when `ruleset_references` is set; `ruleset_references` not forwarded to partition calls
- Redundant CDF Files uploads in DataProduct mode (settings and view config)
- `IndexError` when `list_versions` returns empty list in `deploy_validation_pipeline`
- `datetime.utcnow()` deprecated in Python 3.12+; replaced with `datetime.now(timezone.utc)`
- Broad `except Exception` narrowed to `CogniteAPIError` in `_load_settings_from_dms`
