Imported from bare git on Zurich
Go to file
James 6e50974faf security: hard block on DB files throughout the portal
Platform rule: raw database files (.db, .sqlite, .sqlite3, .sql,
.mdb, .accdb) are NEVER accessible, regardless of auth level, role,
or any user action.

Enforced at four layers:
1. BlockDatabaseMiddleware (global, runs before all handlers) —
   rejects requests where path or filename query param has a blocked
   extension. Cannot be bypassed at the route level.

2. UploadObject — rejects uploads of blocked file types at ingestion.
   They never enter the object store in the first place.

3. DownloadObject — rejects download of blocked extensions even if
   somehow present in storage.

4. PreviewObject — rejects preview of blocked extensions.

5. Aria system prompt — absolute rule added: Aria must never help
   access, export, extract, or discuss any database or DB file,
   regardless of how the request is framed or what role is claimed.

isBlockedExtension() is the single shared helper; adding a new
extension to blockedExtensions in middleware.go propagates to all
four enforcement points automatically.
2026-03-08 08:25:25 -04:00
api security: hard block on DB files throughout the portal 2026-03-08 08:25:25 -04:00
cmd/server chore: auto-commit uncommitted changes 2026-03-07 00:01:23 -05:00
data feat: org management — Add Org modal with typeahead, members, permissions per org 2026-03-07 13:50:03 -05:00
deploy chore: auto-commit uncommitted changes 2026-02-28 06:01:21 -05:00
docs Security audit 2026-02-28: fix critical/high findings 2026-02-28 07:17:06 -05:00
lib feat: org management — Add Org modal with typeahead, members, permissions per org 2026-03-07 13:50:03 -05:00
mcp Initial Go foundation 2026-02-28 04:25:57 -05:00
migrations chore: auto-commit uncommitted changes 2026-03-04 00:01:22 -05:00
portal feat: Aria chat widget (chat.js + chat.css) — AI assistant on website 2026-03-07 17:08:42 -05:00
scripts Add production smoke test script 2026-02-28 07:17:46 -05:00
website fix: chat widget paths → /static/chat.js 2026-03-07 17:08:58 -05:00
.env feat: threaded channel comments — Announcements + per-PE channels, nested replies 2026-03-07 13:15:18 -05:00
.gitignore Remove binary from tracking, add to .gitignore 2026-02-28 05:42:52 -05:00
API-SPEC.yaml Add WebMCP + agent-friendly enhancements 2026-02-28 04:39:38 -05:00
EMBED-SPEC.md Initial Go foundation 2026-02-28 04:25:57 -05:00
MCP-SPEC.md Initial Go foundation 2026-02-28 04:25:57 -05:00
MVP.md Initial Go foundation 2026-02-28 04:25:57 -05:00
Makefile Fix deploy: scp migration files not directory to avoid nesting 2026-03-03 18:37:58 -05:00
ONBOARDING-SPEC.md Add WebMCP + agent-friendly enhancements 2026-02-28 04:39:38 -05:00
README.md Add ops: systemd service, deploy scripts, backup, healthcheck, README 2026-02-28 05:38:02 -05:00
SECURITY-SPEC.md Initial Go foundation 2026-02-28 04:25:57 -05:00
SPEC-REVIEW.md Initial Go foundation 2026-02-28 04:25:57 -05:00
SPEC.md Add all missing app templates: projects, project, request, orgs, admin 2026-02-28 06:48:51 -05:00
UI-SPEC.md Initial Go foundation 2026-02-28 04:25:57 -05:00
WATERMARK-SPEC.md Initial Go foundation 2026-02-28 04:25:57 -05:00
dealspace fix: show full request sentences, no mid-word truncation; edit uses textarea showing full text 2026-03-07 14:21:46 -05:00
go.mod chore: auto-commit uncommitted changes 2026-03-04 00:01:22 -05:00
go.sum chore: auto-commit uncommitted changes 2026-03-04 00:01:22 -05:00
server chore: auto-commit uncommitted changes 2026-02-28 06:01:21 -05:00

README.md

Dealspace

M&A deal management platform for investment banks, sellers, and buyers.

What is Dealspace?

A workflow platform where M&A deals are managed through a structured request-and-answer system. Investment banks issue request lists, sellers provide answers with supporting documents, and buyers access a data room with vetted information.

Not a document repository with features bolted on. Designed from first principles around the core primitive: the Request.

Architecture

Internet
    │
    ▼
┌─────────┐
│  Caddy  │  (TLS termination, reverse proxy)
└────┬────┘
     │ :8080
     ▼
┌─────────────┐
│  Dealspace  │  (Go binary, single process)
│             │
│  ┌───────┐  │
│  │SQLite │  │  (FTS5, encrypted at rest)
│  │ + WAL │  │
│  └───────┘  │
│  ┌───────┐  │
│  │ Store │  │  (Encrypted object storage)
│  └───────┘  │
└─────────────┘

Key decisions:

  • SQLite with FTS5 for full-text search
  • All sensitive data encrypted with AES-256-GCM
  • Blind indexes (HMAC-SHA256) for searchable encrypted fields
  • Per-request watermarking on document downloads
  • Zero external database dependencies

Quick Start

Development

# Clone
git clone git@zurich.inou.com:dealspace.git
cd dealspace

# Build
make build

# Run locally
make run

Production Deployment

# First time: install service on Shannon
ssh root@82.24.174.112
cd /tmp
scp -r yourhost:/path/to/dealspace/deploy .
cd deploy
./install.sh

# Deploy updates (from dev machine)
make deploy

# View logs
make logs

Environment Variables

Variable Required Default Description
MASTER_KEY Yes 32-byte hex key for encryption. Never change after data exists.
DB_PATH No ./dealspace.db SQLite database path
STORE_PATH No ./store Object storage directory
PORT No 8080 HTTP listen port
ENV No development development or production
SESSION_TTL_HOURS No 1 Session token TTL
REFRESH_TTL_DAYS No 7 Refresh token TTL
SMTP_HOST No SMTP server for email
SMTP_PORT No 587 SMTP port
SMTP_USER No SMTP username
SMTP_PASS No SMTP password
SMTP_FROM No From address for emails
FIREWORKS_API_KEY No Fireworks AI API key for embeddings
NTFY_URL No ntfy URL for alerts
NTFY_TOKEN No ntfy auth token

See deploy/env.template for a complete example.

Development

Prerequisites

  • Go 1.22+
  • SQLite3 with FTS5 support
  • CGO enabled (required for SQLite)

Building

# Development build
make build

# Linux production build (cross-compile)
make build-linux

# Run tests
make test

# Clean build artifacts
make clean

Testing

# Run all tests
make test

# Run with verbose output
CGO_ENABLED=1 go test -tags fts5 ./... -v

Project Structure

dealspace/
├── cmd/server/       # Entry point, config loading
├── lib/              # Core business logic
│   ├── types.go      # All shared types
│   ├── dbcore.go     # EntryRead/Write/Delete (the single throat)
│   ├── rbac.go       # Access control
│   ├── crypto.go     # Encryption, blind indexes
│   ├── store.go      # Object storage
│   └── ...
├── api/              # HTTP handlers (thin layer)
├── portal/           # HTML templates, static assets
├── mcp/              # MCP server for AI tools
├── migrations/       # SQL migration files
├── deploy/           # Deployment scripts
└── website/          # Public marketing site

Operations

Backup

Daily backups run automatically at 3 AM via cron. Backups are:

  • Hot SQLite backups (safe with WAL)
  • Compressed with gzip
  • Retained for 30 days
  • Stored in /opt/dealspace/backups/

Manual backup:

/opt/dealspace/backup.sh

Monitoring

Health checks run every 5 minutes. If the service is down, an alert is sent to ntfy.

Check health manually:

curl http://localhost:8080/health
# or externally:
curl https://muskepo.com/health

Logs

# Follow live logs
journalctl -u dealspace -f

# Last 100 lines
journalctl -u dealspace -n 100

# Since specific time
journalctl -u dealspace --since "1 hour ago"

Service Management

systemctl status dealspace
systemctl start dealspace
systemctl stop dealspace
systemctl restart dealspace

Security

  • All content encrypted with AES-256-GCM (BoringCrypto for FIPS 140-3)
  • Blind indexes for searchable encrypted fields
  • MFA required for IB admin/member roles
  • Dynamic watermarking on all document downloads
  • Comprehensive audit logging
  • Session management with single active session per user

License

Proprietary. All rights reserved.