# 02 - Architecture ## Local-first rule SQLite is the runtime source of truth. MariaDB is sync transport plus setup and migration tooling. ```text browser -> Gin handlers -> SQLite -> pending_changes background sync <------> MariaDB ``` Rules: - user CRUD must continue when MariaDB is offline; - runtime handlers and pages must read and write SQLite only; - MariaDB access in runtime code is allowed only inside sync and setup flows; - no live MariaDB fallback for reads that already exist in local cache. ## Sync contract Bidirectional: - projects; - configurations; - `vendor_spec`; - pending change metadata. Pull-only: - components; - pricelists and pricelist items; - partnumber books and partnumber book items. Readiness guard: - every sync push/pull runs a preflight check; - blocked sync returns `423 Locked` with a machine-readable reason; - local work continues even when sync is blocked. - sync metadata updates must preserve project `updated_at`; sync time belongs in `synced_at`, not in the user-facing last-modified timestamp. ## Pricing contract Prices come only from `local_pricelist_items`. Rules: - `local_components` is metadata-only; - quote calculation must not read prices from components; - latest pricelist selection ignores snapshots without items; - auto pricelist mode stays auto and must not be persisted as an explicit resolved ID. ## Configuration versioning Configuration revisions are append-only snapshots stored in `local_configuration_versions`. Rules: - create a new revision only when spec or price content changes; - rollback creates a new head revision from an old snapshot; - rename, reorder, project move, and similar operational edits do not create a new revision snapshot; - current revision pointer must be recoverable if legacy or damaged rows are found locally. ## Naming collisions UI-driven rename and copy flows use one suffix convention for conflicts. Rules: - configuration and variant names must auto-resolve collisions with `_копия`, then `_копия2`, `_копия3`, and so on; - copy checkboxes and copy modals must prefill `_копия`, not ` (копия)`; - the literal variant name `main` is reserved and must not be allowed for non-main variants. ## Vendor BOM contract Vendor BOM is stored in `vendor_spec` on the configuration row. Rules: - PN to LOT resolution uses the active local partnumber book; - canonical persisted mapping is `lot_mappings[]`; - QuoteForge does not use legacy BOM tables such as `qt_bom`, `qt_lot_bundles`, or `qt_lot_bundle_items`.