# Dealspace (muskepo.com) M&A deal workflow platform for investment banking data rooms. Built for Misha (Michael Muskepo / Johan's son). Primary builder: Mira (James assists). ## Ground Rules Johan is the architect. You are the collaborator. 1. **Discussion first.** Default is conversation. No code until asked. 2. **Minimal diffs.** Change only what's requested. 3. **Less code, better architecture.** Flag opportunities to consolidate. 4. **Ask, don't assume.** Ambiguous → ask first. 5. **No unsolicited files.** 6. **Mention concerns once, then execute.** ## Architecture ``` cmd/server/ — main binary entry point (embeds website/) api/ — REST API handlers lib/ — shared: auth, crypto, db, rbac, types mcp/ — MCP server (planned v2.0) portal/ — deal room UI (Go templates) website/ — muskepo.com marketing site (go:embed) migrations/ — SQLite migrations docs/ — specs and design docs ``` **Build:** ```bash make build # local build make build-linux # linux/amd64 with CGO + fts5 make deploy # build-linux + deploy to Shannon (root@82.24.174.112) make test # run tests (CGO + fts5) ``` ## Environments | Environment | Host | URL | |-------------|------|-----| | Production | root@82.24.174.112 (Shannon) | dealspace.jongsma.me | | Local | forge (192.168.1.16) | - | Deploy path on Shannon: `/opt/dealspace/` ## Key Design Docs - `MVP.md` — v1.0 scope (what ships, what doesn't) - `API-SPEC.yaml` — REST API spec - `EMBED-SPEC.md` — embedded portal spec - `MCP-SPEC.md` — MCP server spec (v2.0) - `ONBOARDING-SPEC.md` — invite/onboarding flow ## RBAC Roles 7 roles: `ib_admin`, `ib_member`, `seller_admin`, `seller_member`, `buyer_admin`, `buyer_member`, `observer`. Workstream-scoped permissions. All enforced at DB level — not just UI. ## Data Model `Project → Workstream → Request List → Request → Answer` Key fields on requests: `assignee_id`, `return_to_id`, `origin_id` (routing chain). ## Security Non-Negotiables - **Pre-dataroom content is DB-level invisible to buyers** — not a UI filter - **PDF watermarking** at serve time: `{user_name} · {org_name} · {datetime} · CONFIDENTIAL` - **Audit log** on every access grant, file download, status change, login — never disabled - **File storage:** compressed + encrypted - **TOTP required** for admin roles ## Data Access Architecture Three choke points in `lib/dbcore.go` — ALL entry data goes through these: - `EntryRead(db, cfg, actorID, projectID, filter)` — all reads - `EntryWrite(db, cfg, actorID, entries...)` — all writes - `EntryDelete(db, actorID, projectID, entryIDs...)` — all deletes **RBAC:** Every choke point calls `CheckAccess()` before touching data. `actorID=""` = system/internal (always granted). **No stubs, no wrappers for writes/deletes.** Callers use `EntryWrite`/`EntryDelete` directly. Read-path convenience helpers are acceptable — they must delegate to `EntryRead`. **FORBIDDEN:** - `db.Exec()`, `db.Query()`, `db.QueryRow()` outside dbcore.go - New wrapper functions that bypass choke points - Any modification to `lib/dbcore.go` without Johan's explicit approval **Encryption/compression:** Files stored via the designated path in dbcore.go only. Never handle file crypto inline in handlers. ## Current Status (Mar 2026) - Mira is primary builder (Misha's AI) - Portal templates and layouts in progress - Invite flow, auto-assign UI (spec 3.b.2) pending - SMTP not yet configured - v1.0 target: 6 sprints, demoable to Misha after Sprint 2