diff --git a/.claude-flow/daemon-state.json b/.claude-flow/daemon-state.json deleted file mode 100644 index a9e1f6e..0000000 --- a/.claude-flow/daemon-state.json +++ /dev/null @@ -1,179 +0,0 @@ -{ - "running": true, - "startedAt": "2026-07-20T16:44:54.772Z", - "workers": { - "map": { - "runCount": 11, - "successCount": 11, - "failureCount": 0, - "averageDurationMs": 8.090909090909092, - "isRunning": false, - "nextRun": "2026-07-20T19:29:55.184Z", - "lastStartedAt": "2026-07-20T19:14:55.176Z", - "lastRun": "2026-07-20T19:14:55.183Z" - }, - "audit": { - "runCount": 17, - "successCount": 17, - "failureCount": 0, - "averageDurationMs": 8.882352941176471, - "isRunning": false, - "nextRun": "2026-07-20T19:26:56.025Z", - "lastStartedAt": "2026-07-20T19:26:56.097Z", - "lastRun": "2026-07-20T19:26:56.134Z" - }, - "optimize": { - "runCount": 11, - "successCount": 11, - "failureCount": 0, - "averageDurationMs": 6.454545454545454, - "isRunning": false, - "nextRun": "2026-07-20T19:33:55.170Z", - "lastStartedAt": "2026-07-20T19:18:55.161Z", - "lastRun": "2026-07-20T19:18:55.166Z" - }, - "consolidate": { - "runCount": 6, - "successCount": 6, - "failureCount": 0, - "averageDurationMs": 7.5, - "isRunning": false, - "nextRun": "2026-07-20T19:50:55.096Z", - "lastStartedAt": "2026-07-20T19:20:55.092Z", - "lastRun": "2026-07-20T19:20:55.094Z" - }, - "testgaps": { - "runCount": 8, - "successCount": 8, - "failureCount": 0, - "averageDurationMs": 8.375, - "isRunning": false, - "nextRun": "2026-07-20T19:32:55.117Z", - "lastStartedAt": "2026-07-20T19:12:55.104Z", - "lastRun": "2026-07-20T19:12:55.114Z" - }, - "backup": { - "runCount": 1, - "successCount": 1, - "failureCount": 0, - "averageDurationMs": 9, - "isRunning": false, - "nextRun": "2026-07-21T16:54:54.808Z", - "lastStartedAt": "2026-07-20T16:54:54.797Z", - "lastRun": "2026-07-20T16:54:54.806Z" - }, - "harness": { - "runCount": 1, - "successCount": 1, - "failureCount": 0, - "averageDurationMs": 729, - "isRunning": false, - "nextRun": "2026-07-20T22:56:55.533Z", - "lastStartedAt": "2026-07-20T16:56:54.797Z", - "lastRun": "2026-07-20T16:56:55.526Z" - }, - "predict": { - "runCount": 0, - "successCount": 0, - "failureCount": 0, - "averageDurationMs": 0, - "isRunning": false - }, - "document": { - "runCount": 0, - "successCount": 0, - "failureCount": 0, - "averageDurationMs": 0, - "isRunning": false - } - }, - "config": { - "autoStart": false, - "logDir": "C:\\SiMS\\hq\\.claude-flow\\logs", - "stateFile": "C:\\SiMS\\hq\\.claude-flow\\daemon-state.json", - "maxConcurrent": 2, - "workerTimeoutMs": 960000, - "resourceThresholds": { - "maxCpuLoad": 9.600000000000001, - "minFreeMemoryPercent": 10 - }, - "ttlMs": 43200000, - "idleShutdownMs": 0, - "aiWorkersEnabled": false, - "workers": [ - { - "type": "map", - "intervalMs": 900000, - "offsetMs": 0, - "priority": "normal", - "description": "Codebase mapping", - "enabled": true - }, - { - "type": "audit", - "intervalMs": 600000, - "offsetMs": 120000, - "priority": "critical", - "description": "Security analysis", - "enabled": true - }, - { - "type": "optimize", - "intervalMs": 900000, - "offsetMs": 240000, - "priority": "high", - "description": "Performance optimization", - "enabled": true - }, - { - "type": "consolidate", - "intervalMs": 1800000, - "offsetMs": 360000, - "priority": "low", - "description": "Memory distillation (ADR-174)", - "enabled": true - }, - { - "type": "testgaps", - "intervalMs": 1200000, - "offsetMs": 480000, - "priority": "normal", - "description": "Test coverage analysis", - "enabled": true - }, - { - "type": "backup", - "intervalMs": 86400000, - "offsetMs": 600000, - "priority": "low", - "description": "Nightly memory DB backup (WAL-safe, rotated)", - "enabled": true - }, - { - "type": "harness", - "intervalMs": 21600000, - "offsetMs": 720000, - "priority": "low", - "description": "Self-optimizing harness loop (opt-in RUFLO_HARNESS_LOOP, $0-default)", - "enabled": true - }, - { - "type": "predict", - "intervalMs": 600000, - "offsetMs": 0, - "priority": "low", - "description": "Predictive preloading", - "enabled": false - }, - { - "type": "document", - "intervalMs": 3600000, - "offsetMs": 0, - "priority": "low", - "description": "Auto-documentation", - "enabled": false - } - ] - }, - "savedAt": "2026-07-20T19:26:56.135Z" -} \ No newline at end of file diff --git a/.claude-flow/metrics/codebase-map.json b/.claude-flow/metrics/codebase-map.json deleted file mode 100644 index 3ba49b1..0000000 --- a/.claude-flow/metrics/codebase-map.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "timestamp": "2026-07-20T19:14:55.182Z", - "projectRoot": "C:\\SiMS\\hq", - "structure": { - "hasPackageJson": true, - "hasTsConfig": true, - "hasClaudeConfig": true, - "hasClaudeFlow": true - }, - "scannedAt": 1784574895183 -} \ No newline at end of file diff --git a/.claude-flow/metrics/consolidation.json b/.claude-flow/metrics/consolidation.json deleted file mode 100644 index f0c5001..0000000 --- a/.claude-flow/metrics/consolidation.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "timestamp": "2026-07-20T19:20:55.094Z", - "distillationEnabled": true, - "patternsConsolidated": 0, - "memoryCleaned": 0, - "duplicatesRemoved": 0, - "episodes": 0, - "patternEmbeddings": 0, - "causalEdges": 0, - "promoted": 0, - "byProvenance": {}, - "namespaces": [], - "dryRun": false, - "corrupt": false, - "skipped": "no-db" -} \ No newline at end of file diff --git a/.claude-flow/metrics/performance.json b/.claude-flow/metrics/performance.json deleted file mode 100644 index 023cde6..0000000 --- a/.claude-flow/metrics/performance.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "timestamp": "2026-07-20T19:18:55.166Z", - "mode": "local", - "memoryUsage": { - "rss": 46977024, - "heapTotal": 21909504, - "heapUsed": 20452192, - "external": 3903735, - "arrayBuffers": 100670 - }, - "uptime": 9240.595012, - "optimizations": { - "cacheHitRate": 0.78, - "avgResponseTime": 45 - }, - "note": "Install Claude Code CLI for AI-powered optimization suggestions" -} \ No newline at end of file diff --git a/.claude-flow/metrics/security-audit.json b/.claude-flow/metrics/security-audit.json deleted file mode 100644 index 96771f6..0000000 --- a/.claude-flow/metrics/security-audit.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "timestamp": "2026-07-20T19:26:56.127Z", - "mode": "local", - "checks": { - "envFilesProtected": true, - "gitIgnoreExists": true, - "noHardcodedSecrets": true - }, - "riskLevel": "low", - "recommendations": [], - "note": "Install Claude Code CLI for AI-powered security analysis" -} \ No newline at end of file diff --git a/.claude-flow/metrics/test-gaps.json b/.claude-flow/metrics/test-gaps.json deleted file mode 100644 index 8f624f3..0000000 --- a/.claude-flow/metrics/test-gaps.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "timestamp": "2026-07-20T19:12:55.112Z", - "mode": "local", - "hasTestDir": false, - "estimatedCoverage": "unknown", - "gaps": [], - "note": "Install Claude Code CLI for AI-powered test gap analysis" -} \ No newline at end of file diff --git a/.gitignore b/.gitignore index b5f55e6..725a567 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,7 @@ ruvector.db # Database backups (D33) — contain plaintext credentials (D32); never commit backups/ + +# agent scratch (claude-flow daemon state/metrics) +.claude-flow/ +.claude/ diff --git a/docs/KNOWN-ISSUES.md b/docs/KNOWN-ISSUES.md new file mode 100644 index 0000000..fe16cbb --- /dev/null +++ b/docs/KNOWN-ISSUES.md @@ -0,0 +1,120 @@ +# Known issues & pending work — HQ Ops Console + +_Last updated: 2026-07-21 · after the D38 Client Detail redesign landed on `main`._ + +This is the honest list of what is **not** done, what is **not** verified, and what needs a human +decision. Everything here was found by review; none of it is speculative. Ordered by consequence. + +--- + +## 1. SECURITY — production Postgres password is in the repo and on the remote + +**Status: open. Owner decision parked.** + +The production Postgres connection string (with password) is hardcoded in +`apps/hq/src/db-pg.ts` (`HARDCODED_DATABASE_URL`), and it **is present on the `origin` remote** +(`gitea.simssoftware.in`). It was introduced in commit `45cfb83` (then in `server.ts`) and later moved +into `db-pg.ts`; both states have been pushed. A duplicate copy that had been added to +`apps/hq/test/db-resolve.test.ts` was removed in `6f50799`. + +**Why it matters:** under D31/D32 every client portal/gateway password, module secret and client DB +password is stored **in the clear**. This one credential is therefore the key to all of them. + +**The only real remediation is to ROTATE the Postgres password on the box.** Editing or reverting the +file does not remove it from history, and history is already distributed. + +Secondary (after rotation), pick one: +- move the value to a deploy-time env var / secrets file and revert the code to a placeholder — + **note the AWS box currently has no `.env`, so this requires an ops change there first**; or +- accept the hardcoded pattern and treat repo read access as equivalent to production DB access. + +--- + +## 2. BLOCKED — the real data has not been touched yet + +**Status: blocked on the local Postgres password.** + +The following were prepared and tested but **never run against the real database**, because the +local PostgreSQL 17 instance's credentials are not available to this session: + +- **Scrub of the "tecnostac" name from the real DB.** The earlier scrub ran against + `data/hq.db` — a near-empty leftover SQLite file (2 clients), **not** the live Postgres. The live + database very likely still contains the old company name, owner login and audit snapshots. +- **The onboarding template migration** over ~167 real projects + (`apps/hq/scripts/apply-onboarding-pipeline.ts`). +- **Redeploy** — the server currently running on `:5182` predates all of this work, so the console + in use does not yet reflect the redesign. + +Until this runs, the redesign is **code-complete but not live**. + +--- + +## 3. NOT VERIFIED — things nobody has actually observed working + +- **The Postgres migrations have never been executed against a real Postgres instance.** + Migrations `015`–`018` (`project_milestone.payment_id`, `.document_id`, `ticket.type`, + `client_module.created_at`) are statically reviewed and mirrored from the SQLite schema, but the + test suite's Postgres path is skipped without `HQ_PG_TEST_URL`. 5 tests are skipped for this reason. +- **The Payments tab was not screenshotted at 768px, nor at 1440px in dark theme.** The rest of the + redesign was verified in a real browser at 375 / 768 / 1440 × light + dark. + +--- + +## 4. DEFERRED TO ROADMAP (owner call) + +- **`gmail-connect.ts` and the APEX importer CLI use an unconditional `openDb()`** and therefore can + never reach Postgres — they will always target SQLite. `gmail-connect.ts` is a documented production + runbook step. Deferred because that area is not in active use yet. + +--- + +## 5. BEHAVIOUR CHANGES worth knowing + +- **Tables now scroll inside their own box, bounded at `70vh`, with a sticky header.** Previously the + whole page scrolled and (at desktop widths) tables silently dropped their rightmost columns. Short + tables are unchanged; long tables scroll internally. This affects every table screen. +- **Adding a module no longer asks for credentials.** They are captured when the "Account creation" + onboarding step is ticked, and remain editable from the module's Access panel. +- **The coarse module status is now driven by the status line.** Ticking Installation / Training / + Go-live advances it automatically; it never downgrades. + +--- + +## 6. MINOR BACKLOG (real, non-blocking) + +From the review passes, not yet fixed: + +- `bulkSetMilestone` couples to a literal error string (`'Milestone not found on this project'`); + rewording that throw would turn a skip into a whole-batch abort. Prefer a sentinel/typed error. +- `project.stall_days` (the setting, as opposed to the `?days=` query param) is not range-validated; + an absurd value produces a 400 rather than a crash, but it should be clamped for symmetry. +- Whitespace-only `?days=` input is treated as `0` rather than rejected. +- Two `/client-modules/:id/milestones` handlers `await` outside their `try` block (not reachable with + attacker-controlled input, and not a regression). +- `DraftInput.source` is a free-form string taken from the request body — any authenticated user can + tag a document `module_renewal` or `bulk_sms_topup`. Provenance label only, no money impact; a union + type would give a compile-time guard. +- `ClientDetail` still calls `getModules` / `getTicketTypes` on load in some paths; only the duplicate + fetch was removed. +- Chip/button tap targets are ~23px high on mobile — below the comfortable minimum, but this is a + pre-existing system-wide convention, not something this work introduced. + +--- + +## 7. REPO HYGIENE + +- **`.claude-flow/` is tracked in git** (6 files of agent daemon state/metrics). It is scratch and + should be removed from tracking and added to `.gitignore`. +- `apps/hq/scripts/migrate-sqlite-to-pg.ts` and `migrate-pg-to-pg.ts` are untracked working files. +- `apps/hq/schema.sql` is a stale generated snapshot (dated 2026-07-10) that no longer matches + `db.ts`, which is the source of truth. It does not even contain `project_milestone`. + +--- + +## How this list was produced + +The redesign went through per-task reviews during the build, then a whole-branch review, a four-lens +audit swarm, a real-browser responsive red-team, and a review of the fix commits themselves. Each +layer found defects the previous one could not — including a payment feature that was dead code, a +deploy script that would have written to a phantom database while reporting success, and a route any +authenticated user could crash the server with. Those are fixed. The items above are what remains.