# Features — sync_coordinator

Evidence date: 2026-10-01.

Source: `git@bitbucket.org:overdrive/sync_coordinator.git`, `main` at `0e109de` (2026-08-17).

"Current" means present on `main` and reachable from `SyncEngine.exe` or from the test project. There is no issue tracker. A behaviour is planned only when a file says it is not implemented yet. `docs/anniesapp/` describes another application; those notes are listed separately and are not features of `SyncEngine.exe`.

## Current features

### F-01 — CLI sync engine

`SyncEngine.exe` (.NET Framework 4.8, x64). Modes: `all` (default), `access`, `mysql`, `schema-only`.

Source: `SyncEngine/Program.cs`, `SyncEngine/Sync/SyncOrchestrator.cs`, `README.md`.

Origin: `c40b663` and earlier `14616ce`. Status: **current**. Confidence: high.

### F-02 — Single-instance guard

Global mutex `Global\SyncCoordinator.SyncEngine`. Second process exits 3 before reading `.env`.

Source: `SyncEngine/Sync/SyncInstanceLock.cs`. Tests: `SyncInstanceLockTests`.

Origin: `a697f33`. Status: **current**. Confidence: high.

### F-03 — `.env` configuration and validation

Loads `.env`, rejects placeholder paths, checks mode-specific required settings, copies `.env` to the build output when present.

Source: `SyncEngine/Configuration/EnvSettings.cs`, `SyncOptions.cs`, `SyncOptionsValidator.cs`, `SyncEngine.csproj` target `CopyEnvToOutput`, `config/.env.example`. Tests: `SyncOptionsValidatorTests`.

Status: **current**. Confidence: high.

### F-04 — Access schema discovery

User tables and columns via ACE OLEDB, including AutoNumber. DAO enrichment for defaults and validation. Indexes, relationships, and query SQL via system tables, COM fallback, and optional `config/access-views.json`.

Source: `SyncEngine/Access/AccessSchemaReader.cs`, `AccessApplicationSysReader.cs`, `AccessDaoHelper.cs`, `AccessViewConfigLoader.cs`, `AccessIndexGrouper.cs`.

Access Runtime workaround (DAO open when `Access.Application` cannot be created): `a5773a1`. Status: **current**. Confidence: high.

### F-05 — SQL Express database and schema provision

Connects through `master`, creates the target database if missing, then creates or alters tables, primary keys, indexes, foreign keys, defaults, NOT NULL where safe, check constraints, and T-SQL views. Adds four `_sync_*` columns on mirrored tables.

Source: `SyncEngine/SqlServer/SqlServerConnectionFactory.cs`, `SqlSchemaProvisioner.cs`, `SqlSchemaKeyBuilder.cs`, `SqlIdentityHelper.cs`, `SqlViewTranslator.cs`, `AccessTypeMapper.cs`, `AccessDefaultTranslator.cs`, `AccessValidationTranslator.cs`.

Guide: `docs/sync/access-sql-express-compatibility.md`. Tests: `SqlViewTranslatorTests`, `SqlSchemaKeyBuilderTests`, `SqlIdentityHelperTests`, `AccessTypeMapperTests`, `AccessDefaultTranslatorTests`, `AccessValidationTranslatorTests`, `AccessIndexGrouperTests`.

Origin of the fuller mirror: `4fe50dd`, `1c57ef3`. Status: **current**. Confidence: high.

### F-06 — Access data sync with hash skip and soft delete

Paged read by primary key (single or composite). Upsert when the SHA256 hash changes. Soft-delete rows not seen this run. Per-run checkpoints only.

Source: `SyncEngine/SqlServer/SqlDataSync.cs`, `SyncEngine/SqlServer/DataSyncPrimaryKeyHelper.cs`, `SyncEngine/Sync/ChangeDetector.cs`, `SyncEngine/Sync/SoftDeleteTracker.cs`, `SyncEngine/Metadata/SyncMetadataRepository.cs`.

Tests: `DataSyncPrimaryKeyHelperTests`, `ChangeDetectorTests`. Status: **current**. Confidence: high.

### F-07 — Unique-key collision handling

On SQL errors 2601 and 2627, classify duplicate, stale, remap, or recycle. Remap renames the occupying code with suffix `_removed` and can retarget `refProductID` children.

Source: `SyncEngine/SqlServer/UniqueKeyCollisionClassifier.cs`, `UniqueKeyCollisionResolver.cs`, called from `SqlDataSync`. Tests: `UniqueKeyCollisionClassifierTests`.

Origin: `506a8c6` (2026-08-14). Status: **current**. Confidence: high.

### F-08 — Table exclude list

Comma-separated `ACCESS_SQL_EXCLUDE_TABLES`. Example excludes switchboard and named delivery-note leftovers.

Source: `SyncEngine/Configuration/TableExcludeFilter.cs`. Tests: `TableExcludeFilterTests`. Status: **current**. Confidence: high.

### F-09 — MySQL product publish

Active (`_sync_is_deleted = 0`) products from `tblProduct` with lookups, multi-row upsert of 500, match on `code`. Withdrawn rows are counted, not updated in MySQL.

Source: `SyncEngine/MySql/MySqlProductSync.cs`, `ShopProductSql.cs`, `ShopSchemaValidator.cs`. Tests: `MySqlProductSyncTests`.

Speed change (multi-row upsert): `517f5a6`. Status: **current**. Confidence: high.

### F-10 — Field mapping, slug, price, visibility

URL-safe slug, daily-rate price to two decimals, Camera Ready to `is_visible`, truncation to documented maxima.

Source: `SyncEngine/MySql/ProductFieldMapper.cs`. Tests: `ProductFieldMapperTests` (19 methods).

Slug change: `ba43ca4`. Status: **current**. Confidence: high.

### F-11 — Insert-only shop images and preserved web columns

`image_url_*` are not in the duplicate-key update list. `is_featured`, `featured_sort`, `web_copy`, and `web_notes` are never written.

Source: `SyncEngine/MySql/ShopProductSql.cs`. Origin: `517f5a6`. Status: **current**. Confidence: high.

### F-12 — Configurable barcode, image, and product-id columns

`config/product-sync-map.json`. Lookup table names in that file are not applied.

Source: `SyncEngine/Configuration/SyncOptions.cs` (`ProductSyncMap`), `config/product-sync-map.json`. Status: **current** for the three used fields. Confidence: high.

### F-13 — Shop sync log, API fallback, local JSONL

MySQL `shop_sync_log`, then `POST` with `X-Shop-Sync-Key`, then `logs/shop-sync-log-failed-*.jsonl`.

Source: `SyncEngine/MySql/ShopSyncLogClient.cs`, `ShopSyncLogApiClient.cs`, `ShopSyncLogLocalWriter.cs`. Tests: `ShopSyncLogClientTests`, `ShopSyncLogClientFallbackTests`, `ShopSyncLogApiClientTests`, `ShopSyncLogLocalWriterTests`.

Status: **current**. Confidence: high.

### F-14 — MySQL TLS 1.2 pin and reconnect

Connection string forces TLS 1.2 and a 30-second connect timeout. Connection-loss errors are classified and the failed chunk is retried on a new connection.

Source: `SyncOptions.MySqlConnectionString`, `MySqlConnectionFailures.cs`, `MySqlConnectionHolder.cs`. Tests: `MySqlTlsConnectionStringTests`, `MySqlConnectionFailuresTests`.

Origin: `8d227b6`. Status: **current**. Confidence: high.

### F-15 — Dry run

`SYNC_DRY_RUN` skips database writes listed in the PRD (FR-014) and still writes `shop_sync_log`.

Source: dry-run branches in `SqlSchemaProvisioner`, `SqlDataSync`, `SoftDeleteTracker`, `MySqlProductSync`, `ShopSchemaValidator`. Status: **current**. Confidence: high.

### F-16 — Retries

Polly around batch writes. `SYNC_MAX_RETRIES` default 3.

Source: `SyncEngine/Sync/BatchProcessor.cs`. Origin: `b7e6338`. Status: **current**. Confidence: high.

### F-17 — Operator logging and run audit

Console and daily log file. SQL Express `sync_metadata.runs`, `checkpoints`, `schema_versions`. Summary lines from `SyncStatistics`.

Source: `Program.cs`, `SyncEngine/Logging/SyncStatistics.cs`, `SyncEngine/Metadata/SyncMetadataRepository.cs`, `SyncEngine/Sync/SyncErrorFormatter.cs`. Tests: `SyncStatisticsTests`. Status: **current**. Confidence: high.

### F-18 — In-repo operator documentation

`README.md`, `docs/sync/*` (getting started, build and test, configuration, architecture, Access compatibility, shop products), `docs/anniesapp/*`.

Doc move into subfolders: `0e109de` (2026-08-17). Status: **current**, with broken README links (see discrepancies). Confidence: high.

### F-19 — Access Runtime COM probe script

`scripts/Test-AccessRuntimeCom.ps1`. Documented for PowerShell 2.0 hosts (SBS 2011 / Windows 7). Status: **current** as a manual script. Not part of the sync run. Confidence: high.

### F-20 — Unit test suite

MSTest project `SyncEngine.Tests`, 24 test classes, 136 `[TestMethod]` attributes. No integration test against Access or a database server is in the tree.

Source: `SyncEngine.Tests/*.cs`, `docs/sync/build-and-test.md`. Status: **current**. Confidence: high that the tests exist. They were not run for this document.

## Recently changed

| When | Commit | What changed for operators |
|---|---|---|
| 2026-08-17 | `0e109de` | Docs split into `docs/sync/` and `docs/anniesapp/`. README links were not updated |
| 2026-08-14 | `506a8c6` | Unique `strCode` (and similar) collisions remap or recycle instead of failing the insert |
| 2026-07-29 | `517f5a6` | Shop image URLs no longer overwritten. MySQL writes batched |
| 2026-07-21 | `8d227b6` | MySQL TLS 1.2 pin and logging |
| 2026-07-20 | `a5773a1` | Metadata sync on Access Runtime-only machines |
| 2026-06-22 | `ba43ca4` | SEO/URL-safe slugs |
| 2026-06-18 | `a697f33` | One process per machine |
| 2026-06-18 | `f79676b` | Access `.mdb` removed from git |

## Planned or unimplemented

### P-01 — Primary-key overrides

`config/table-overrides.json` contains `{ "primaryKeys": {} }`. `docs/sync/configuration.md` calls it a placeholder and states it is not referenced in code. Tables without a detected key are skipped. No other roadmap item was found.

Status: **planned** only in the sense that the file and the doc say "future". No date or owner. Confidence: high that it is unused.

### P-02 — `productTable` and `lookupJoins`

Present in `product-sync-map.json`. Configuration doc says they are not used. Status: **not a feature**. Changing the JSON does not change the query.

### P-03 — `SYNC_PLATFORM_TARGET`

Loaded from `.env` into `SyncOptions.PlatformTarget` and never read. Bitness is compile-time `PlatformTarget` in the csproj files. Status: **not a feature**. Documented as an operator reminder.

## Not features of this repository

### AnniesApp front-end

`docs/anniesapp/` records linked-table setup, a table inventory, query and report smoke tests, and a delivery-note form parity report. It names VBA (`mdSqlExpress`, `EnsureUsysSqlConfigTable`, `ResolveSqlOdbcDriver`) and `scripts/Resolve-SqlOdbcDriver.ps1`. That script is not in the tree. The only script here is `Test-AccessRuntimeCom.ps1`.

Status: **documented alongside the engine**. Implementation is elsewhere or missing. **Unknown / Requires Confirmation** which repository holds AnniesApp.

### CI4 web shop

Consumes `shop_products`. Owns migrations and `POST /api/shop-sync/log`. Not in this repo.

### SonarQube project file

Listed in the onboarding scan's top-level tree. Not in git. Status: **absent**.

## Removed

| Item | Evidence | Status |
|---|---|---|
| `New_Annies_Angels_be.mdb` tracked in git | `f79676b` deletes the blob; `.gitignore` ignores it | **removed from source control**. Operators are expected to keep a local copy. The file is not evidence of current schema |
| Docs at `docs/*.md` (flat) | `0e109de` moves them | **moved**, not deleted. README still points at the old paths |

No feature flag or code path was found that removes a previously shipped CLI mode.

## Discrepancies

- README "Documentation" table links `docs/getting-started.md`, `docs/build-and-test.md`, `docs/configuration.md`, `docs/sync-architecture.md`, `docs/access-sql-express-compatibility.md`, and `docs/shop_products.md`. Those paths are not in the tree. The files are under `docs/sync/`.
- `docs/sync/index.md` prescribes `feature/TASK-XXX-*` branches and `[TASK-XXX]` commits. History uses `main`, `josh_work`, and freeform subjects.
- Batch size: example `.env` sets 2000; code default is 5000.
