Commercial operations monorepo — public website, email intelligence pipeline, operator API with a durable commercial CRM core, and dashboard.
OrigenLab combines a public marketing site with operator tooling for commercial email intelligence, outbound safety, and commercial triage. Gmail and archive signals land in SQLite on the operator machine; Postgres holds rebuildable machine mirrors plus the durable human CRM (commercial.sales_opportunity, tasks, activities, organizations, contacts). Machine systems propose; the durable CRM records human commercial truth. The API/dashboard never send mail or mutate outreach state; durable CRM writes flow only through the allowlisted /operations/* commands. Canonical V1 architecture: docs/architecture/CURRENT_SYSTEM_TRUTH.md.
This describes V1, which is running today. A V2 architecture was accepted on 2026-09-05: one Supabase PostgreSQL 17 project with seven private schemas replaces the V1 Postgres durable core, and SQLite and the PST archives become cold evidence. Its schema foundation lives in
supabase/and its canonical documentation isdocs/README.md. What is actually built and deployed is indocs/STATUS.md— as of 2026-09-09 that is the local schema foundation only, with no hosted project.
This public repository holds code, tests, and documentation only. Mail exports, SQLite files, generated reports, and client collateral stay outside Git by design.
| Write path | Surfaces |
|---|---|
Machine: apps/email-pipeline — ingest, mart, safety, explicit --apply workflows. Human CRM: POST /operations/* on apps/api |
apps/api :8001 · apps/dashboard :5173 (reads + allowlisted CRM commands via apps/dashboard-proxy) |
Full topology: docs/PROJECT_CONTEXT.md · outbound rules: apps/email-pipeline/docs/OUTBOUND_SOURCE_OF_TRUTH.md
The active operator UI is apps/dashboard (Streamlit was retired). Sections read machine evidence and the durable CRM; the only writes are the allowlisted /operations/* CRM commands and the tender annex import.
| Section | Role |
|---|---|
| Hoy (Today) | Durable commercial work queue + daily summary, automation health, queue counts |
| Bandeja de revisión | Warm-case triage (machine evidence) |
| Negocios | Machine-proposed opportunity intake + durable CRM commands + historical deal ledger |
| Prospectos / Clientes / Catálogo / Proveedores / Pagos | Machine-evidence views (mirror) |
| Licitaciones / equipos | W1 actionable tender queue + T1 term intelligence + annex import |
| Sistema | Service status, backend/mirror context |
Handoff and freeze rules: apps/dashboard/docs/V1_FREEZE_OPERATOR_HANDOFF.md
flowchart LR
Gmail[Gmail / ChileCompra / archives] --> MailRefresh[auto-refresh-mail + tender workers]
MailRefresh --> SQLite[(SQLite operational truth)]
SQLite --> DailyCore[daily-core + read models]
DailyCore --> Reports[reports / safety state]
DailyCore --> Mirror[auto-mirror-dashboard]
Mirror --> PGM[(Postgres machine mirrors)]
PGD[(Postgres durable CRM commercial.*)] <--> API[FastAPI operator API]
PGM --> API
API --> Proxy[dashboard-proxy allowlist]
Proxy --> Dashboard[React operator dashboard]
Web[Astro public website] -. separate .- Dashboard
| Layer | Role |
|---|---|
| Gmail / ChileCompra / archives | External sources (not in Git) |
| SQLite | Machine operational truth — ingest, outbound safety, Sent memory |
| Postgres mirrors | Rebuildable machine projections (warm cases, deals, catalog, leads, PR3 opportunities) |
| Postgres durable CRM | Human commercial truth — sales opportunities, tasks, activities, organizations, contacts |
| API / proxy / dashboard | Reads + allowlisted /operations/* CRM commands; mirror data is not send approval |
apps/web |
Public marketing site (separate from operator stack) |
Two debounced cron loops keep ingest and publish separate: Gmail → SQLite (~3 min) and SQLite → Postgres/dashboard (every minute; default 60s cooldown). Runbook: apps/email-pipeline/docs/pipeline/OPERATOR_CRON.md
| App | Path | Stack | Writes? |
|---|---|---|---|
| Web | apps/web/ |
Astro, Tailwind, TypeScript | No operational data |
| Email pipeline | apps/email-pipeline/ |
Python 3.12, uv, SQLite |
Yes — local SQLite/reports/mirrors when explicitly applied |
| Operator API | apps/api/ |
FastAPI :8001 |
Durable CRM commands under /operations/* only (+ tender annex import) |
| Dashboard | apps/dashboard/ |
React, Vite :5173 |
Via allowlisted API commands only |
| Dashboard proxy | apps/dashboard-proxy/ |
Cloudflare Worker | Trust boundary — strict method+path allowlist |
Default ports: API :8001 · Dashboard :5173 · Web :4321
- SQLite — machine operational truth for ingest, outbound safety, and send decisions.
- Postgres mirrors — rebuildable machine projections published by
auto-mirror-dashboard. - Postgres durable CRM (
commercial.*durable tables) — human commercial truth; written only viaPOST /operations/*with trusted operator identity. - API / dashboard — reads plus allowlisted CRM commands; never treat mirror responses as send approval.
- Send / outreach — human-reviewed batches via email-pipeline scripts; no autonomous send path.
- Generated datasets —
reports/out, SQLite, and mail exports stay out of Git.
| Check | Command | Notes |
|---|---|---|
| Active operator stack | ./scripts/validate-active-stack.sh |
email-pipeline + API + dashboard; no send/purge |
| Public-repo hygiene | ./scripts/security/check-public-repo-hygiene.sh |
Tracked files only; no network |
| Remote response audit | apps/api/scripts/remote_response_audit.py |
Live GET contract checks behind Cloudflare Access; skips without CF credentials |
| Remote latency audit | apps/api/scripts/remote_latency_audit.py |
Warm-run latency budgets; cold probe advisory |
Per-app CI: ./scripts/validate.sh inside each app. Heavier monorepo sweep: ./scripts/check-all.sh
Before changing repo visibility: docs/PUBLIC_RELEASE_CHECKLIST.md
Website
cd apps/web && npm ci && npm run devOperator API + dashboard
cd apps/api && uv sync && uv run uvicorn origenlab_api.main:app --host 127.0.0.1 --port 8001
cd apps/dashboard && npm ci && npm run dev # expects API on :8001Email pipeline — read-only status
cd apps/email-pipeline && uv sync && uv run origenlab operator-automation-statusDo not run --apply, send, purge, or mirror workflows from this README. See app runbooks for operator procedures.
This repository is public. Do not commit .env, SQLite databases, mail archives, reports/out, keys, or client collateral.
| Control | Location |
|---|---|
| Coordinated disclosure | SECURITY.md |
| Public-repo guide | docs/SECURITY_PUBLIC_REPO.md |
| Secret scan (gitleaks) | .github/workflows/secret-scan.yml |
| Dependabot | .github/dependabot.yml |
| Topic | Doc |
|---|---|
| What is actually built and deployed | docs/STATUS.md |
| V2 — canonical documentation (accepted 2026-09-05) | docs/README.md → DOMAIN · DATA · WORKFLOWS · ARCHITECTURE · MIGRATION · OPERATIONS |
| Canonical V1 system truth | docs/architecture/CURRENT_SYSTEM_TRUTH.md |
| V1 target commercial architecture | docs/architecture/TARGET_COMMERCIAL_ARCHITECTURE.md |
| Monorepo architecture (V1 reference) | docs/PROJECT_CONTEXT.md |
| Documentation map | docs/DOCUMENTATION_MAP.md |
| Release process | docs/RELEASE_PROCESS.md |
| Email pipeline | apps/email-pipeline/docs/README.md |
| Operator API | apps/api/README.md |
| Dashboard handoff | apps/dashboard/docs/V1_FREEZE_OPERATOR_HANDOFF.md |
| Web app | apps/web/docs/README.md |
| Contributing | CONTRIBUTING.md |
MIT — see LICENSE.