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. |
||
|---|---|---|
| api | ||
| cmd/server | ||
| data | ||
| deploy | ||
| docs | ||
| lib | ||
| mcp | ||
| migrations | ||
| portal | ||
| scripts | ||
| website | ||
| .env | ||
| .gitignore | ||
| API-SPEC.yaml | ||
| EMBED-SPEC.md | ||
| MCP-SPEC.md | ||
| MVP.md | ||
| Makefile | ||
| ONBOARDING-SPEC.md | ||
| README.md | ||
| SECURITY-SPEC.md | ||
| SPEC-REVIEW.md | ||
| SPEC.md | ||
| UI-SPEC.md | ||
| WATERMARK-SPEC.md | ||
| dealspace | ||
| go.mod | ||
| go.sum | ||
| server | ||
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.