# Copilot instructions for shopdb-flask Follow these when suggesting code. They are enforced by a naming/style hook and by CI (`.github/workflows/ci.yml`) - suggestions that break them fail the build. `CONTRIBUTING.md` is the full authority; this is the short version. ## Naming (LOCKED - the hook rejects violations) - **DB tables**: lowercase, concatenated, plural. No underscores, no dashes. `machines`, `networkdevices`, `businessunits` - NOT `machine_types`, `BusinessUnits`. - **DB columns**: lowercase, concatenated, singular. No underscores. `machineid`, `lastzabbixsync`, `isactive` - NOT `machine_id`, `last_zabbix_sync`. - **Foreign keys**: referenced table (singular) + `id`: `locationid`, `vendorid`. - **Booleans**: `is`/`has` prefix: `isactive`, `isshopfloor`. - **Index names**: `idx__` (underscores allowed here only). ### Python - A variable, attribute, function, or dict key that holds a DB value MUST match the column name exactly - do NOT convert to snake_case. Column `machineid` -> `Machine.machineid`, `{"machineid": 1}`, local `machineid`. - Pure code that does NOT mirror a DB field uses normal snake_case (PEP 8): `loop_count`, `current_user`, `validate_input()`. - Classes: PascalCase, spelled out (`NetworkDevice`, `AssetType`). ### JavaScript / Vue - A JS variable holding an API field value matches the API key exactly - do NOT camelCase it. API `{"machineid": 1}` -> `response.machineid`, never `machineId`. - Components: PascalCase (`AssetDetail.vue`). CSS classes: lowercase-with-dashes. ### API - Endpoints: lowercase plural nouns, no underscores/dashes: `/api/networkdevices`. - Query params + response keys match column names: `?locationid=5`, `{"machineid": 1, "lastzabbixsync": "..."}`. ### Allowed acronyms only Universal: id url api http https json jwt sql os ip dns csv pdf cors ttl uuid html css orm. Domain: cmm cnc pc usb vnc winrm ssh ssl tls tcp udp smtp ldap vlan sso dnc focas clm mtconnect. Anything else: spell it out. ### Banned shorthand Never use `cfg ctx mgr req res env util helper` or `db` as a standalone variable name. Spell out: `config context manager request response environment utilities`. `_bp` is fine only as a suffix with a meaningful prefix (`printers_bp`). ## Style (ASCII only) - NO emojis anywhere - code, comments, strings, UI. - NO em-dashes, en-dashes, Unicode arrows, or smart quotes. Plain ASCII only. - Comments default to NONE. Add one only when the WHY is non-obvious; keep inline `#`/`//` comments terse. Docstrings stay normal English. - Dark theme is the default; keep UI functional and professional. ## Architecture (do not violate) - **Plugins are the product.** Plugin code lives in `plugins//{models,api,services,schemas}/` with a `manifest.json` (single source of truth: name, version, dependencies, api_prefix) and a `BasePlugin` subclass in `plugin.py`. - **Plugins never import core internals.** Use the contract surface `shopdb.api` (e.g. `from shopdb.api import db, Asset, success_response`). Adding to that surface is a contract-version bump + a `docs/PLUGIN-HOOKS` update in the same PR. - **Migrations, never `db.create_all()`.** The core Alembic chain is in `migrations/versions/`; each plugin owns its own chain under `plugins//migrations/`. New schema = a new migration with an idempotent guard and a real downgrade. Migrations must run clean on strict MySQL 8. - **Asset model is the platform contract.** Physical things are an `Asset` plus a plugin subtype row linked by `assetid` (FK, `ON DELETE CASCADE`). Consumables with quantities are standalone tables, not assets. - **Ledger pattern**: a cached `quantityonhand` moves in the SAME commit as the signed transaction row it reflects. ## Before you finish a change Run the three gates (CI runs the same): ``` python -m pytest tests/ -q cd frontend && npx vitest run && npm run build && cd .. bash scripts/check-naming-and-style.sh ``` Commits: short present-tense subject, body says WHY. No AI/tool attribution in commit messages, code comments, or docs.