mirror of
https://github.com/Alkatrazz24/Funk-lab.git
synced 2026-07-08 12:44:41 +02:00
feat(finlab): console Claude Code finance in-cluster + toolkit d'analyse (#64)
* feat(finlab): console Claude Code finance in-cluster + toolkit d'analyse Intègre finlab (ex-projet Projets/Finance) au lab comme une console Claude Code web spécialisée finance — l'esprit OpenAlice, mais c'est le vrai Claude Code sur l'abonnement (login persisté, pas d'API facturée), agentique, avec la boîte à outils finlab (Yahoo Finance) branchée en MCP. - tools/finlab/ : source finlab rapatriée + Dockerfile (Python 3.12 + Node + claude-code + ttyd) + persona workspace/CLAUDE.md + branchement MCP + entrypoint (seed du workspace no-clobber sur le PVC) - .github/workflows/build-finlab.yml : build GHCR funk-finlab + bump manifest (main) - k8s/apps/finlab/ : Deployment/Service/PVC/IngressRoute (finance.lab.local) + Middleware basicAuth (shell web protégé) ; PVC = HOME (login) + workspace - k8s/apps-of-apps/apps/finlab.yaml : Application ArgoCD - .mcp.json (racine) : outils finlab dans les sessions Claude Code du lab - admin/ia/finlab.md + READMEs + CLAUDE.md : doc + enregistrement Analyse/aide à la décision uniquement — aucun ordre réel (paper trading Alpaca fictif seul exécutable). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * fix(finlab): ttyd absent des dépôts bookworm → binaire statique GitHub Le build amont échouait (`E: Package 'ttyd' has no installation candidate`) : ttyd n'est pas packagé dans Debian bookworm. On récupère le binaire statique (musl, pin TTYD_VERSION=1.7.7) depuis les releases GitHub. Build complet validé en local (podman) : ttyd 1.7.7, claude-code 2.1.195, import finlab + seed OK. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
35ad1deb64
commit
54f6f7c634
39 changed files with 2115 additions and 2 deletions
68
k8s/apps/finlab/README.md
Normal file
68
k8s/apps/finlab/README.md
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
# FinLab — console Claude Code finance (in-cluster)
|
||||
|
||||
Une **vraie session Claude Code** (sur l'**abonnement** d'Alkatrazz, login persisté) servie
|
||||
dans un **terminal web** (`ttyd`), spécialisée analyse de marché via la persona `CLAUDE.md` et
|
||||
la boîte à outils **finlab** (Yahoo Finance, exposée en **MCP**). Esprit OpenAlice, mais c'est
|
||||
Claude Code + le toolkit maison — **aucune facturation API**, **aucun broker**, analyse seule.
|
||||
|
||||
> ⚠️ La console expose un **shell web** → protégée par **basicAuth Traefik**. Analyse et aide à
|
||||
> la décision uniquement : **aucun ordre réel** (seul le paper trading Alpaca fictif existe).
|
||||
|
||||
## Image
|
||||
|
||||
Pas d'image publique : la CI (`.github/workflows/build-finlab.yml`) build depuis
|
||||
`tools/finlab/` (notre code) → `ghcr.io/alkatrazz24/funk-finlab`, tag `sha-<court>`, bump du
|
||||
manifest sur `main`.
|
||||
|
||||
## Architecture du déploiement
|
||||
|
||||
| Composant | Détail |
|
||||
|---|---|
|
||||
| Deployment | 1 réplica, `Recreate` (volume RWO), PodSecurity *restricted* (uid 1000, `fsGroup` 1000) |
|
||||
| PVC `finlab-data` | 5Gi NFS → `/home/finlab` : `~/.claude` (login abonnement) + workspace (code finlab seedé, `portfolio.yaml`/`watchlists.yaml`/`alerts.yaml` éditables, `.cache`) |
|
||||
| Service `finlab` | `web:7681` (ttyd) |
|
||||
| Middleware `finlab-auth` | basicAuth Traefik (secret `finlab-auth`, htpasswd) |
|
||||
| IngressRoute | `finance.lab.local` → 7681 (via `finlab-auth`) |
|
||||
|
||||
Le workspace est **seedé depuis l'image au 1er boot** (`cp -rn`, no-clobber) puis vit sur le
|
||||
PVC : tes edits (portefeuille, etc.) et ton login persistent ; une nouvelle image n'apporte que
|
||||
les fichiers manquants.
|
||||
|
||||
## Pré-requis manuels (une fois)
|
||||
|
||||
### 1. Secret de pull GHCR (si absent du ns `ai`)
|
||||
|
||||
```bash
|
||||
kubectl -n ai create secret docker-registry ghcr-pull \
|
||||
--docker-server=ghcr.io \
|
||||
--docker-username=Alkatrazz24 \
|
||||
--docker-password=<GHCR_PAT_read_packages>
|
||||
```
|
||||
|
||||
### 2. Secret basicAuth de la console (`finlab-auth`)
|
||||
|
||||
```bash
|
||||
# htpasswd (paquet apache2-utils). Remplace <user>/<pass>.
|
||||
htpasswd -nbB <user> '<pass>' > /tmp/finlab.htpasswd
|
||||
kubectl -n ai create secret generic finlab-auth \
|
||||
--from-file=users=/tmp/finlab.htpasswd
|
||||
rm -f /tmp/finlab.htpasswd
|
||||
```
|
||||
|
||||
### 3. Premier boot — login Claude Code (abonnement)
|
||||
|
||||
1. Ouvrir **http://finance.lab.local** (basicAuth → identifiants de l'étape 2).
|
||||
2. Dans le terminal, lancer `claude`, puis `/login` → suivre l'OAuth (ouvrir l'URL sur ta
|
||||
machine, autoriser, coller le code). Persisté dans `~/.claude` sur le PVC.
|
||||
3. À l'invite, FinLab a déjà sa persona (`CLAUDE.md`) et les outils finlab (MCP `finlab`,
|
||||
auto-activé). Essaie : *« résume mon portefeuille »*, *« plan de trade pour Micron »*.
|
||||
|
||||
> Le workspace `/home/finlab/workspace` contient `portfolio.yaml` etc. — éditables directement
|
||||
> (par toi ou par Claude à ta demande). Pour une vue rapide hors console :
|
||||
> `kubectl -n ai exec deploy/finlab -- python -m finlab.cli digest`.
|
||||
|
||||
## Accès depuis le terminal (sans navigateur)
|
||||
|
||||
```bash
|
||||
kubectl -n ai exec -it deploy/finlab -- bash -lc 'cd "$WORKSPACE" && claude'
|
||||
```
|
||||
72
k8s/apps/finlab/deployment.yaml
Normal file
72
k8s/apps/finlab/deployment.yaml
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: finlab
|
||||
namespace: ai
|
||||
spec:
|
||||
replicas: 1
|
||||
# HOME + workspace sur un volume RWO (NFS) → pas de rolling à 2 pods sur le même volume.
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: finlab
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: finlab
|
||||
spec:
|
||||
# Image privée sur GHCR → secret de pull créé manuellement dans le ns ai
|
||||
# (cf. README : kubectl create secret docker-registry ghcr-pull ...).
|
||||
imagePullSecrets:
|
||||
- name: ghcr-pull
|
||||
# Conformité PodSecurity « restricted » (namespace ai). fsGroup 1000 → le PVC NFS monté
|
||||
# en /home/finlab (HOME : ~/.claude du login abonnement + workspace) est inscriptible.
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
runAsGroup: 1000
|
||||
fsGroup: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
containers:
|
||||
- name: finlab
|
||||
# Tag bumpé par la CI (build-finlab.yml) sur main.
|
||||
image: ghcr.io/alkatrazz24/funk-finlab:latest
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop: ["ALL"]
|
||||
ports:
|
||||
- name: web
|
||||
containerPort: 7681
|
||||
env:
|
||||
- name: TZ
|
||||
value: "Europe/Paris"
|
||||
# ttyd écoute en TCP : sonde TCP (pas de endpoint HTTP de santé dédié). Démarrage
|
||||
# rapide, mais on laisse de la marge (seed du workspace au 1er boot).
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 7681
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 15
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 7681
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 30
|
||||
# Node + Claude Code peuvent consommer ; nœuds 8 Go (OOM actif) → limite raisonnable.
|
||||
resources:
|
||||
requests:
|
||||
cpu: 200m
|
||||
memory: 512Mi
|
||||
limits:
|
||||
cpu: "1"
|
||||
memory: 1536Mi
|
||||
volumeMounts:
|
||||
- name: home
|
||||
mountPath: /home/finlab
|
||||
volumes:
|
||||
- name: home
|
||||
persistentVolumeClaim:
|
||||
claimName: finlab-data
|
||||
17
k8s/apps/finlab/ingress.yaml
Normal file
17
k8s/apps/finlab/ingress.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
apiVersion: traefik.io/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: finlab
|
||||
namespace: ai
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`finance.lab.local`)
|
||||
kind: Rule
|
||||
middlewares:
|
||||
# basicAuth : un shell web ne doit pas être ouvert sans auth (cf. middleware.yaml).
|
||||
- name: finlab-auth
|
||||
services:
|
||||
- name: finlab
|
||||
port: 7681
|
||||
11
k8s/apps/finlab/middleware.yaml
Normal file
11
k8s/apps/finlab/middleware.yaml
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
apiVersion: traefik.io/v1alpha1
|
||||
kind: Middleware
|
||||
metadata:
|
||||
name: finlab-auth
|
||||
namespace: ai
|
||||
spec:
|
||||
# La console expose un SHELL web (ttyd) → on la protège par basicAuth Traefik, même en LAN.
|
||||
# Le secret `finlab-auth` (htpasswd) est créé MANUELLEMENT (hors git) — voir README.
|
||||
basicAuth:
|
||||
secret: finlab-auth
|
||||
realm: FinLab
|
||||
15
k8s/apps/finlab/pvc.yaml
Normal file
15
k8s/apps/finlab/pvc.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: finlab-data
|
||||
namespace: ai
|
||||
spec:
|
||||
# /home/finlab : login abonnement Claude Code (~/.claude), workspace finlab (code seedé +
|
||||
# configs éditables portfolio/watchlists/alerts), cache disque (.cache), sessions/historique.
|
||||
# Persiste l'onboarding (login) et les edits à travers redémarrages et rebuilds d'image.
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: nfs
|
||||
resources:
|
||||
requests:
|
||||
storage: 5Gi
|
||||
12
k8s/apps/finlab/service.yaml
Normal file
12
k8s/apps/finlab/service.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: finlab
|
||||
namespace: ai
|
||||
spec:
|
||||
selector:
|
||||
app: finlab
|
||||
ports:
|
||||
- name: web
|
||||
port: 7681
|
||||
targetPort: 7681
|
||||
Loading…
Add table
Add a link
Reference in a new issue