dealspace/CLAUDE.md

3.5 KiB

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:

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