Skip to content

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bastion

Local-first sales operations platform: personal/team/company dashboards, annual quotas, revenue actuals, Stripe imports, HubSpot CRM sync, lead-response SLAs, call/email quality evaluation, CRM hygiene, behaviour scores and audit history.

Architecture: TypeScript modular monolith with ports and adapters. Runs entirely on a developer laptop today; moves to AWS later by swapping infrastructure adapters and configuration only — no business-module rewrites.

Capability Local AWS (Phase 10)
Runtime Docker Compose ECS Fargate
Database PostgreSQL container RDS PostgreSQL
Queues LocalStack SQS Amazon SQS
Objects MinIO Amazon S3
Cache Valkey container ElastiCache (Valkey)
Scheduling Scheduler process EventBridge Scheduler
Secrets .env Secrets Manager

Quickstart

Prerequisites: Node 20+ (22 recommended), pnpm 9, Docker Desktop.

pnpm install
pnpm dev

pnpm dev starts the infrastructure containers, applies migrations, seeds an empty database, then runs web (3000), API (3001), worker and scheduler with hot reload — and prints the development accounts:

Account Password Role
admin@bastion.local admin-dev-password Administrator
manager@bastion.local manager-dev-password Manager
salesperson1@bastion.local sales1-dev-password Salesperson
salesperson2@bastion.local sales2-dev-password Salesperson

These accounts exist only in dev-like profiles — never in staging/production.

Commands

Command Purpose
pnpm dev Local development mode with hot reload
pnpm local:up / local:down Start/stop infrastructure (down never deletes data)
pnpm local:reset Delete all local data (asks for confirmation)
pnpm local:integration Real provider APIs (HubSpot etc.) with local infra
pnpm local:host Laptop-hosted pilot: production images + optional tunnel
pnpm local:logs Tail container logs
pnpm local:backup / local:restore --file <backup> Protected backups, tested restore
pnpm test / test:integration / test:e2e Unit / containerised integration / Playwright
pnpm lint / typecheck / build Static checks and builds
pnpm db:migrate / db:seed / db:studio Prisma workflows
pnpm openapi:generate Write docs/api/openapi.json
pnpm deploy --stage staging|production AWS deploy (gated until Phase 10)

Repository layout

apps/        web (Next.js), api (NestJS/Fastify), worker, scheduler, infra (CDK, Phase 10)
packages/    contracts, configuration, database, logger, observability,
             api-client, ui, test-utils,
             infrastructure-ports / -local / -aws   ← the ports-and-adapters seam
prisma/      schema.prisma, migrations, seed.ts
scripts/     local-start/host/reset, backup/restore, deploy
infrastructure/  docker (app image), local (LocalStack init)
docs/        architecture, ADRs, operations, security, api

Operating modes

  • developmentpnpm dev; zero-config defaults, mock CRM/AI providers.
  • local-integration — real HubSpot/Stripe against local infra; HTTPS tunnel for webhooks via PUBLIC_WEBHOOK_BASE_URL (polling covers the no-tunnel case).
  • local-hostedpnpm local:host; production containers, secure tunnel, backups. Only web/API are exposed — never PostgreSQL/MinIO/Valkey/LocalStack.
  • staging / production — same images on ECS Fargate (Phase 10; deploy is gated until local acceptance passes).

HubSpot sync model

Three layers (all provider-neutral through packages/contracts CRM contracts):

  1. WebhooksPOST /api/v1/webhooks/crm/hubspot: verify signature v3, store, dedupe, enqueue, respond fast; worker re-fetches the full record.
  2. Incremental sync — every 10 min, per-object cursors with 15-min overlap.
  3. Reconciliation — nightly (48h window) and weekly/broad, plus on-demand from the admin Integrations screen.

A mock provider ships for fully offline development and provider contract tests.

Payments and commission

Revenue ingestion is payment-source agnostic: upload Stripe, QuickBooks, bank-transfer or generic CSVs at Admin → Payment Imports — each provider has a parser adapter mapping to the same canonical payment row, so validation, dedupe (organisation + source account + transaction id), attribution and commit are identical for every rail.

Commission realises on invoiced amounts actually paid — never booked ACV. The engine in packages/contracts/src/commission.ts implements the sales commission plan: base rate × accelerator on accumulated paid-vs-quota (1.0/1.1/1.2/1.5/1.6 tiers, payments split exactly at boundaries), partner-rate deduction, Public Plan exclusion, excluded-product 5% cap, multiyear 5% of subsequent-year payments (no quota credit), guaranteed-commission advances, £250 minimum payout with carry-over, and quarterly/bi-annual/annual attainment gates. Deal type, partner rate, plan flags and contract year are read from optional (metadata) CSV columns. Statements live at /commission (GET /api/v1/me/commission); plan configuration at Admin → Commission Plans.

Money

Integer minor units everywhere. £1,000,000.00 = 100000000. Default currency GBP.

Health

GET /health/live, /health/ready, /health/dependencies (Postgres, queue, object storage, cache, worker/scheduler heartbeats — no secrets exposed).

Docs

  • docs/architecture/overview.md — module map and data flows
  • docs/adr/0001-local-first-ports-and-adapters.md
  • docs/operations/local-development.md, docs/operations/laptop-hosting.md
  • docs/security/security-model.md

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages