From 984b950f80bdd12574cb42bcf29de1e192a4e034 Mon Sep 17 00:00:00 2001 From: Keysat Date: Fri, 19 Jun 2026 13:57:05 -0500 Subject: [PATCH] Mobile Phase 2: read-only Contacts surface + shared BottomSheet/useIsMobile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Builds the mobile-first Contacts surface (<768px): a read-only A-Z directory (sticky last-name letter headers) + segmented All/Investors/Prospects tabs + pinned search -> full-screen detail (info with tap-to-copy email, opportunities, comm history) -> a sort bottom-sheet. Contacts stays read-only on mobile per design/BRIEF.md §3b (create/edit live on the Grid). Lands the shared mobile primitives, deferred from Phase 1 and designed against this first consumer (no dead code): (built on the Phase-1 .bottom-sheet CSS; scrim/Escape/pointer drag-to-dismiss) and useIsMobile() (768px matchMedia). ContactsPage becomes a rules-of-hooks-safe wrapper that mounts MobileContactsPage or the renamed-but-untouched DesktopContactsPage, so desktop is unchanged. New CSS is JS-gated to the mobile component; grew the :root/mobile var set per DESIGN §9 instead of hand-picking hexes. Verified: render-smoke green + a throwaway jsdom interaction harness mounting the real app at 375px (list/grouping/sort-sheet/detail/back, 14/14). Deploy- pending (folds into the next s9pk with P0/P1/view-reorder). --- AGENTS.md | 9 +- ROADMAP.md | 23 +- frontend/index.html | 526 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 547 insertions(+), 11 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 4912306..05dc137 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -75,7 +75,7 @@ Subsystem rules live in `docs/guides/` and lazy-load in Claude Code via `.claude - **Env:** secrets in `.env` (gitignored); names in `.env.example`. Verified names: `ANTHROPIC_API_KEY`, `SPARK_CONTROL_URL`, `SPARK_CONTROL_VERIFY_TLS`, `QDRANT_URL`, `X_API_KEY`, `CRM_DB_PATH`, `CRM_DEV_DB_PATH`. Also used: `CRM_SECRET_KEY` (beta/prod), `CRM_HOST`/`CRM_PORT`, `CRM_DATA_DIR`; digest mailer: `CRM_DIGEST_SENDER` (DWD impersonation sender) + `SMTP_HOST`/`SMTP_PORT`/`SMTP_SECURITY`/`SMTP_FROM`/`SMTP_USERNAME`/`SMTP_PASSWORD` (SMTP fallback); daily digest (Phase B): `CRM_DIGEST_ENABLED` + `CRM_DIGEST_SEND_HOUR` **only seed the first-boot default** — the live control is the DB policy (`app_settings.digest_policy`, set in Settings → Admin). - **Config placement:** operational/feature toggles live in the **admin panel**, DB-backed via `app_settings` (read-merge through a `load_*_policy(conn)` helper shared by the API + any scheduler; precedence DB-row → env-seed → default), so they're discoverable and take effect live. Reserve StartOS actions / env for **secrets and deploy-time config** (SMTP creds, API keys, DWD sender). Precedent: `digest_policy` (`GET/PATCH /api/admin/digest/policy`), `fundraising_backup_policy`. - **Agent/bot API access — three roles now (`admin`/`member`/`bot`).** `require_admin` is the only hard gate; everything else is "authenticated" (member, admin, *and* bot all pass). The **`bot` role** (added v0.1.0:89) is authenticated-but-never-admin: `require_bot_or_admin` gates agent-facing endpoints (e.g. `/api/intake/email-proposals*`) so a bot credential reaches *only* what it needs, never user-management/settings/security. Provision it via Settings → Admin edit-user dropdown (kept out of the teammate-invite form). **Two axes to keep separate as more agent capability lands:** the role controls *reach* (which endpoints); the per-feature human draft→approve gate controls *autonomy* (acting unattended). Money/merge/delete mutations stay behind the approval gate regardless of role. Don't build a finer capability/scope system until real NL-mutation endpoints exist to scope against. -- **Design:** before building or changing any user-facing UI, read `design/DESIGN.md` and `design/tokens.tokens.json` and conform to them. The **mobile-first redesign landed** (Claude Design round-trip distilled into the contract 2026-06-19): the authority for mobile/responsive work is **`DESIGN.md` §8** + the tokens `mobile` and `color.light` groups; `design/BRIEF.md` is the input brief and `design/_imports/2026-06-19/` the provenance + per-surface interaction reference (the comps are Claude Design runtime prototypes — re-author each surface in the app's React idiom + real API, not drop-in). A **light theme** is adopted as a planned, toggle-gated feature (dark stays default). (Note: inline `style={{}}` objects can't respond to media queries; responsive layout belongs in the CSS `