# Split SiMS into two independent projects: HQ and Store **Date:** 2026-07-16 **Status:** Approved, pending implementation plan ## Why `C:/SiMS/Store Software` currently holds two products that are not one product. **HQ** (`apps/hq`, `apps/hq-web`) is internal: our client book, their projects, proforma-invoice billing, call tracking, AMC contracts, AWS cost recovery, payments and reminders. It is the commercial record of the business. **Store** (`apps/pos`, `apps/store-server`, `apps/backoffice`) is the product we sell: GST retail management deployed on client premises. They are independent projects and should be developed, deployed and released as such: - **Different audiences.** HQ is internal-only; Store ships to ~300 clients. - **Different databases.** Two SQLite schemas with no conceptual overlap. HQ: `client`, `module`, `document`, `interaction`, `amc_contract`, `aws_usage`, `payment`, `reminder`, `staff_user`. Store: `item`, `batch`, `bill`, `purchase`, `stock_movement`, `party`, `counter`, `store`, `tenant`. Four names collide (`audit_log`, `doc_series`, `setting`, `tax_class`) but they are different definitions in different DBs — shared in appearance only. - **Different cadences.** Of 75 commits, 60 touch HQ and 2 touch Store. The repo is already HQ wearing a Store name. - **Confidentiality.** A single tree means every Store branch, contractor handout, or repo copy carries our client book and revenue data in its history. ## Decisions | # | Decision | Choice | |---|---|---| | 1 | Split shape | Two separate git repos | | 2 | Shared code | Fork into each repo, trimmed to what each uses | | 3 | History | HQ inherits the existing 60 commits; Store starts fresh | | 4 | Docs | Trim each side to only what that repo needs | | 5 | Repo name | `C:/SiMS/hq` (keep — matches docs/14, DEPLOY-HQ.md, `@sims/hq`, 60 commits) | | 6 | Project tracking | Out of scope — split first, build after | Rejected: a third shared repo and a private npm registry. Both add versioning overhead to solve a divergence risk the evidence says does not exist (see below). ## Target layout ``` C:/SiMS/ ├── hq/ ← current repo, 60 commits preserved │ ├── apps/{hq, hq-web} │ ├── packages/{domain, auth, billing-engine, ui} ← trimmed, names kept │ ├── docs/ ← HQ-only, renumbered │ ├── DEPLOY-HQ.md │ └── README.md, STATUS.md ← STATUS.md is new └── store/ ← fresh git init ├── apps/{pos, store-server, backoffice} ├── packages/{domain, billing-engine, auth, ui, config, scanning, search-core} ├── docs/ ← the remaining 15 docs └── README.md, STATUS.md, BUILDING.md ``` Each repo gets its own `package.json` (`sims-hq` / `sims-store`), `tsconfig`, `vitest.config`, `.gitignore`, and `CLAUDE.md`. Neither references the other at any point — no workspace links, no relative paths across roots, no doc citing a file it does not contain. ## Shared code: fork, trimmed HQ's dependency on shared packages is shallow and fully verified — utilities and a design system, no shared schema or business logic. **HQ keeps the package names** (`@sims/domain`, `@sims/auth`, `@sims/billing-engine`, `@sims/ui`) and removes files underneath. Import specifiers are unchanged, so **no import statement in HQ's app source changes** — not one of `apps/hq`'s 75 files or `apps/hq-web`'s 14. What changes is narrow and enumerable: the four `index.ts` barrels (drop the removed `export *` lines), and `apps/hq-web`'s `package.json` + `vite.config.ts` (drop the dead `@sims/printing` dependency and alias). | Package | HQ keeps | HQ drops | |---|---|---| | `domain` | `ids`, `money`, `business-day`, `doc-series`, `gstin`, `documents` | `tenancy`, `masters`, `batch`, `outbox` | | `auth` | `pin` | `lockout`, `permissions`, `session` | | `billing-engine` | `compute`, `tax` | `returns`, `gst-returns` (588 lines) | | `ui` | all 5 files | — | | `printing` | — | whole package | Store's `packages/` is untouched. ### Closure verification (done, 2026-07-16) Every trim is a clean cut — verified by reading the imports, not by assumption: - `compute.ts` imports `./tax` and four **types** from `@sims/domain` (`BillLine`, `BillTotals`, `Paise`, `IsoDate`) — all in files HQ keeps. - `tax.ts` imports only `IsoDate`. - `documents.ts` imports only from `money` and `business-day`. - `pin.ts` imports only `node:crypto` — no `@sims` deps. - `ui` has no `@sims` deps at all (`react` + its own `theme`). - Nothing HQ retains imports `tenancy`, `masters`, `batch`, or `outbox`. The reverse edges (`batch → business-day`, `masters → money`) are one-way and drop cleanly. - `@sims/printing` is declared in `apps/hq-web/package.json` and aliased in its `vite.config.ts`, but **imported by no source file** — a dead dependency. ### Why forking is safe The divergence risk for forked code is GST computation. It does not apply: **tax rates are dated DB rows, not code.** `tax_class` rows carry `effective_from`/`effective_to` and resolve by the bill's business date, with the Sept-2025 GST 2.0 slab change cited in `tax.ts` as the precedent. HQ reads its own `tax_class` table; Store reads its own. A rate change is a row insert per DB, never a code edit. What remains in `compute.ts` is stable arithmetic — CGST/SGST/IGST split, rounding. It has no reason to change often, and the two products are entitled to diverge: HQ invoices software modules, Store bills retail goods. ## History The current repo becomes `C:/SiMS/hq`: all 60 HQ commits preserved, then one commit removing Store paths. No `filter-repo` surgery. `C:/SiMS/store` gets `git init` and one clean initial commit. It loses only 2 commits (one titled `wip`) and gains a guarantee: **zero HQ bytes in its history, permanently.** This is the confidentiality boundary, and it is only real if the Store history starts empty. ## Docs Trimmed per repo — each doc cut to what that side actually needs. **HQ** (renumbered `00`–`04`): | New | From | Treatment | |---|---|---| | `00-HQ-CONSOLE-SPEC.md` | `14-SPEC-HQ-CONSOLE.md` | As-is | | `01-ADMIN-SUPPORT-CONSOLE.md` | `11-ADMIN-SUPPORT-CONSOLE.md` | As-is | | `02-PROJECT-RULES.md` | `16-PROJECT-RULES.md` | Trimmed: keep money, config-over-code, document rules; drop counter/POS rules | | `03-DECISIONS.md` | `06-DECISIONS.md` | Extract D15 + HQ-only calls | | `04-DB-AND-CONFIG.md` | `07-DB-AND-CONFIG.md` | Trimmed: D12 portable-repo pattern, dated tax-class config | Plus `DEPLOY-HQ.md` as-is, a rewritten `README.md`, and a **new `STATUS.md`**. **Store**: the remaining 15 docs, with D15/HQ references pruned from `06-DECISIONS.md` and the HQ rows removed from `README.md`'s doc table. ### HQ has no STATUS.md The largest app in the repo (75 files, at go-live per `DEPLOY-HQ.md`) has no build-state doc. `STATUS.md` covers only the Store product. HQ's current state had to be reconstructed from source and `git log`. Write one during the split, covering the built surface: clients, modules and price book, documents (QT/PI/INV/CN) with templates/PDF/share links, interactions, AMC, AWS usage, payments, recurring plans, reminders with Gmail send and bounce handling, reports, dashboard, audit, APEX import, scheduler. ## Verification The split is done when, for each repo independently: 1. `node_modules` removed and `npm install` run fresh 2. `npm run typecheck` passes 3. `npm test` passes 4. No path resolves outside its own root Typecheck is the real proof of the fork closure — a missed dependency fails immediately and loudly. Additionally, confirm the confidentiality boundary holds rather than assuming it: searching `C:/SiMS/store/.git` for client, AMC, and AWS-cost terms must return nothing. ## Out of scope - **Project tracking.** Listed as a core HQ concept but not built — no `project` table, no repo module, no UI. It is a feature to design and build, not code to move. Deferred so the split stays mechanical: pure move-and-verify, with no new feature to confuse a failure with. - **Conversion reporting.** `client.status` (`lead`/`active`/`dormant`/`lost`) exists but has no lead-to-won reporting on it. Wanted alongside the existing conversation log (`interaction`), but after the split. - **Oracle 12c adapter** (Store, pending Classic DDL) and the **46 wireframe back-office screens** (Store) are unaffected by this work. ## Risks | Risk | Mitigation | |---|---| | A trimmed file is needed by something unread | Typecheck on a fresh install in each repo catches it immediately | | Store history retains HQ data | Fresh `git init`, verified by searching `.git` | | Docs cite files that no longer exist in their repo | Grep each repo's docs for cross-references to removed paths | | HQ's dead `@sims/printing` alias breaks its Vite build when dropped | Remove from both `package.json` and `vite.config.ts` together; build verifies |