feat: Unraid deploy, dealer-flow heatmap, confluence zones, 13F capture
CI / Test (push) Canceled after 0s
CI / Build and push (push) Canceled after 0s

Ship Node production images, Unraid compose, and Gitea CI/CD (test then
push registry images; cron script if no runner). Rebuild dealer flow as a
heatmap-first map with integrity gates and chart helpers. Add confluence
zone rules, session clock, capture evidence, and tighter 13F/queue/options
paths, plus the matching UI and tests.
This commit is contained in:
Investor Flow Build
2026-08-18 14:10:02 -04:00
parent f7efea2178
commit 90e1829d39
113 changed files with 7606 additions and 1947 deletions
+34
View File
@@ -0,0 +1,34 @@
# Copy to the compose working directory as `.env`.
# Generate secrets: openssl rand -hex 32
# Required
IFLOW_SESSION_SECRET=
# 64 hex chars. Required if you copy an existing DB that has encrypted X/FRED keys.
# If you never set this locally, leave blank only for a fresh Unraid DB.
IFLOW_CRYPTO_KEY=
# SQLite + harvest files. Use a cache (or single-disk) path, not /mnt/user.
IFLOW_DATA_DIR=/mnt/cache/appdata/investor-flow/data
# Host ports
IFLOW_WEB_PORT=3000
IFLOW_BACKEND_PORT=3001
# Images: local tags when building on Unraid; Gitea registry after CD is live.
IFLOW_IMAGE_BACKEND=investor-flow-backend:local
IFLOW_IMAGE_FRONTEND=investor-flow-frontend:local
# After the Gitea runner + CD workflow exist:
# IFLOW_IMAGE_BACKEND=unraid.local:3003/transnet/investor-flow-backend:latest
# IFLOW_IMAGE_FRONTEND=unraid.local:3003/transnet/investor-flow-frontend:latest
IFLOW_TAG=latest
# SEC / Yahoo user-agent identity (required by fair-use)
SEC_OPERATOR_EMAIL=you@example.com
YF_OPERATOR_EMAIL=you@example.com
# Optional vendor keys
FRED_API_KEY=
# Ornith on the LAN (not localhost — that is inside the container)
LLM_PROVIDER_URL=http://10.37.0.165:30081/v1
ORNITH_LLM_URL=http://10.37.0.165:30081/v1
+27
View File
@@ -0,0 +1,27 @@
# Gitea Actions runner for Unraid. One-time setup so CI/CD actually executes.
# Current Gitea (unraid.local:3003) has Actions enabled but zero runners —
# every workflow run is cancelled until this container is registered.
#
# 1. In Gitea: Site Administration → Actions → Runners → Create new runner
# Copy the registration token.
# 2. Put the token in .env next to this file:
# GITEA_INSTANCE_URL=http://10.37.0.86:3003
# GITEA_RUNNER_REGISTRATION_TOKEN=...
# 3. docker compose -f act-runner-compose.yml up -d
# 4. Confirm the runner is Idle on the Gitea runners page.
name: gitea-act-runner
services:
runner:
image: gitea/act_runner:0.2.13
restart: unless-stopped
environment:
CONFIG_FILE: /config.yaml
GITEA_INSTANCE_URL: ${GITEA_INSTANCE_URL:-http://10.37.0.86:3003}
GITEA_RUNNER_REGISTRATION_TOKEN: ${GITEA_RUNNER_REGISTRATION_TOKEN:?set registration token}
GITEA_RUNNER_NAME: ${GITEA_RUNNER_NAME:-unraid-investor-flow}
GITEA_RUNNER_LABELS: ubuntu-latest:docker://gitea/runner-images:ubuntu-22.04
volumes:
- ${GITEA_RUNNER_DATA:-/mnt/cache/appdata/gitea-runner}:/data
- /var/run/docker.sock:/var/run/docker.sock
+55
View File
@@ -0,0 +1,55 @@
# Unraid stack that *pulls* prebuilt images from the Gitea registry.
# Use this after CI/CD has pushed at least one tag.
#
# Place next to a `.env` (see .env.example) and run:
# docker compose -f compose.pull.yml pull
# docker compose -f compose.pull.yml up -d
name: investor-flow
services:
backend:
image: ${GITEA_REGISTRY:-unraid.local:3003}/transnet/investor-flow-backend:${IFLOW_TAG:-latest}
restart: unless-stopped
ports:
- "${IFLOW_BACKEND_PORT:-3001}:3001"
environment:
NODE_ENV: production
HOST: 0.0.0.0
PORT: 3001
IFLOW_DB_PATH: /app/data/investor-flow.db
IFLOW_SESSION_SECRET: ${IFLOW_SESSION_SECRET:?set IFLOW_SESSION_SECRET}
IFLOW_CRYPTO_KEY: ${IFLOW_CRYPTO_KEY:-}
SEC_OPERATOR_EMAIL: ${SEC_OPERATOR_EMAIL:-operator@example.com}
YF_OPERATOR_EMAIL: ${YF_OPERATOR_EMAIL:-${SEC_OPERATOR_EMAIL:-operator@example.com}}
FRED_API_KEY: ${FRED_API_KEY:-}
LLM_PROVIDER_URL: ${LLM_PROVIDER_URL:-}
ORNITH_LLM_URL: ${ORNITH_LLM_URL:-${LLM_PROVIDER_URL:-}}
volumes:
- ${IFLOW_DATA_DIR}:/app/data
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3001/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
frontend:
image: ${GITEA_REGISTRY:-unraid.local:3003}/transnet/investor-flow-frontend:${IFLOW_TAG:-latest}
restart: unless-stopped
depends_on:
backend:
condition: service_healthy
ports:
- "${IFLOW_WEB_PORT:-3000}:3000"
environment:
NODE_ENV: production
HOSTNAME: 0.0.0.0
PORT: 3000
IFLOW_BACKEND_URL: http://backend:3001
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 40s
+60
View File
@@ -0,0 +1,60 @@
#!/bin/bash
# Unraid User Scripts → "Run in background" on a 5–15 min cron.
# Pulls main from Gitea and rebuilds the stack when HEAD moved.
#
# First-time:
# mkdir -p /mnt/cache/appdata/investor-flow
# git clone http://unraid.local:3003/transnet/investor-flow.git \
# /mnt/cache/appdata/investor-flow/repo
# cp /mnt/cache/appdata/investor-flow/repo/deploy/unraid/.env.example \
# /mnt/cache/appdata/investor-flow/.env
# # edit .env
# Then point this script at those paths (or set the env vars below).
set -euo pipefail
REPO_DIR="${IFLOW_REPO_DIR:-/mnt/cache/appdata/investor-flow/repo}"
ENV_FILE="${IFLOW_ENV_FILE:-/mnt/cache/appdata/investor-flow/.env}"
COMPOSE="docker compose --project-directory ${REPO_DIR} --env-file ${ENV_FILE}"
LOG_TAG="investor-flow-cd"
log() { echo "[${LOG_TAG}] $*"; }
if [[ ! -d "${REPO_DIR}/.git" ]]; then
log "ERROR: ${REPO_DIR} is not a git checkout"
exit 1
fi
if [[ ! -f "${ENV_FILE}" ]]; then
log "ERROR: missing ${ENV_FILE}"
exit 1
fi
cd "${REPO_DIR}"
git fetch --prune origin main
LOCAL=$(git rev-parse HEAD)
REMOTE=$(git rev-parse origin/main)
if [[ "${LOCAL}" == "${REMOTE}" ]]; then
log "already at ${LOCAL:0:12} — no deploy"
# still ensure the stack is up
${COMPOSE} up -d --remove-orphans
exit 0
fi
log "updating ${LOCAL:0:12} → ${REMOTE:0:12}"
git merge --ff-only origin/main
${COMPOSE} up -d --build --remove-orphans
# Wait for health
for i in 1 2 3 4 5 6 7 8 9 10; do
if curl -fsS "http://127.0.0.1:${IFLOW_WEB_PORT:-3000}/health" >/dev/null \
&& curl -fsS "http://127.0.0.1:${IFLOW_BACKEND_PORT:-3001}/health" >/dev/null; then
log "healthy after deploy"
exit 0
fi
sleep 3
done
log "WARNING: containers started but health checks did not pass in 30s"
${COMPOSE} ps
exit 1