# 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
