App Management v2 — specifikace¶
Status: F1 (foundation) hotová, F2-F4 v dalších sezeních. Cíl: sjednotit workflow vytváření a správy AVAX aplikací do jedné UI sekce. Nahradit ad-hoc SQL inserty + ruční git clone + ruční pip install + ruční main.py edity.
Motivace¶
Současný flow (dnes 2026-05-13) pro novou AVAX app vyžadoval:
- Ruční SQL insert do apps, app_versions, app_assignments,
company_subscriptions, company_channel_assignments, app_version_files
- Manuální clone repa na dev s qwen tokenem
- Manuální pip install -e pro backend balíček (+ jeho deps)
- Manuální CREATE SCHEMA legal + alembic upgrade
- Manuální editace main.py (mount routerů)
- Manuální release.bat pro publish 0.0.1
- Manuální fix-ups (visibility, slug propagation, presigned bucket)
Cíl v2: 1 dialog v AVAX Admin → 5 minut → app je v Knihovně Avaxis.
Rozhodnutí (z user diskuse 2026-05-13)¶
| Aspekt | Rozhodnutí |
|---|---|
| Lokace projektu | Windows admin PC C:\Avaxis\apps\{slug}\ (no WSL) |
| Gitea organizace | claudAI/{slug}-app |
| S3 credentials | Výběr z existující AVAX Admin S3 klíče sekce |
| Backend modul | Opt-in checkbox při create |
| Backend mount | Auto-generated z DB tabulky dynamic_backend_mounts |
| Initial verze | Auto-publish 0.0.1 placeholder stub |
| Verze management | Per-channel current dropdown (rollback enabled) |
| Visibility | is_public flag + Obchod self-service + admin "Přidat všem" |
| Pull/Deploy | 3 separate tlačítka (Pull / Migrate / Restart) |
| UI | AvaxAdminScreen → "Aplikace & Verze" tab enhance s detail view |
DB změny (migrace 016)¶
apps:
- is_public BOOL — viditelnost v Obchodě (self-service)
- backend_mount BOOL — má FastAPI router
- gitea_repo_url VARCHAR(500) — https://git.avaxis.cz/claudAI/{slug}-app
- local_path VARCHAR(500) — C:\Avaxis\apps\{slug} (admin PC reference)
- backend_module VARCHAR(200) — Python import path (např. avax_legal_backend.legal)
- s3_key_id UUID — FK na admin S3 klíče tabulku
dynamic_backend_mounts (nová):
- id UUID PK
- app_id FK → apps
- module_path VARCHAR(200) — pro importlib.import_module
- mount_prefix VARCHAR(50)
- enabled BOOL
- created_at, updated_at TIMESTAMPTZ
Backend endpointy (/admin/app-management/*)¶
Všechny vyžadují system_role = super_admin.
| Method | Path | Akce |
|---|---|---|
| POST | /create |
Vytvoří app: DB row + (F2) gitea repo + S3 + clone + publish stub |
| GET | /list |
Všechny apps s metadaty |
| GET | /{slug} |
Detail jedné app |
| PUT | /{slug}/public?is_public=true |
Toggle visibility |
| POST | /{slug}/pull |
git pull na dev (jen backend) |
| POST | /{slug}/migrate |
alembic upgrade head |
| POST | /{slug}/restart |
systemctl restart avax-backend-bare |
| PUT | /{slug}/channel-active |
Set is_current per channel/version |
| POST | /{slug}/assign-all-companies |
Bulk subscriptions všem firmám |
Dynamic mount infrastructure¶
app/dynamic_mounts.py.mount_all(app):
- Iterace přes
_BOOTSTRAP_MODULES(vendored seznam — avax-legal atd.) - Iterace přes DB
dynamic_backend_mounts WHERE enabled=true - Pro každý:
importlib.import_module(module_path)+app.include_router(mod.router)(+ optionaladmin_router,sync_router)
Bezpečné — pokud import selže, jen warning v logu, ostatní moduly se mountnou.
main.py finální:
Po git pull + systemctl restart jsou nové moduly aktivní (mount probíhá
při startu FastAPI).
Klient (launcher) UI — F3 (next session)¶
AvaxAdminScreen → "Aplikace & Verze" tab:
┌─ Aplikace & Verze ─────────────────────────────────────────────────────┐
│ [+ Vytvořit novou aplikaci] [↺] [Filtr: všechny] │
│ │
│ ┌─ avax-legal-client ────────────────────────── public · backend ✓ ──┐ │
│ │ Časová osa zákonů │ │
│ │ Bucket: app-avax-legal-client Gitea: claudAI/avax-legal-client-app│
│ │ │ │
│ │ Verze v kanálech: │ │
│ │ alpha: [v0.0.2 ▼] ← dropdown: v0.0.1, v0.0.2 │ │
│ │ beta: [v0.0.1 ▼] │ │
│ │ stable: (žádná) │ │
│ │ │ │
│ │ Backend deploy: [⬇ Pull] [⚙ Migrate] [↻ Restart] │ │
│ │ Subscriptions: [➕ Přidat všem firmám] [👁 Public ☑] │ │
│ │ Test: [⚡ Stáhnout a spustit current] │ │
│ └────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─ avax-mzdy (next vytvořená) ... │
│ ... │
└─────────────────────────────────────────────────────────────────────────┘
Dialog "Vytvořit novou aplikaci":
┌─ Nová aplikace ──────────────────────────────────────┐
│ Slug: [_______________] ← [a-z0-9-]+ │
│ Název: [_______________] │
│ Popis: [_______________] │
│ Kategorie: [▼ ekonomika ] │
│ │
│ ☐ Má backend modul │
│ Modul import path: [____________] │
│ │
│ S3 klíč: [▼ avax-legal-key (existující) ] │
│ Publisher: [▼ AVAXIS.CZ ] │
│ │
│ ☑ Auto-publish 0.0.1 placeholder │
│ │
│ [ Zrušit ] [ Vytvořit ] │
└──────────────────────────────────────────────────────┘
F2 — Gitea + S3 + SSH integrace (next session)¶
Gitea API:
- POST /api/v1/orgs/claudAI/repos (token: existující claudAI)
- Push initial commit s template (clone avax-app-template → force push)
- Vyžaduje: gitea token v env / config
S3 výběr:
- Při create app dropdown s existujícími admin_s3_keys
- Vybraný klíč se uloží do apps.s3_key_id
- Při publish.py + při runtime aplikace se vrátí jeho creds
SSH self-deploy (backend volá samotný server):
- subprocess.run(["ssh", "...", "git clone ...", "..."])
- Vyžaduje SSH key v ~/.ssh/ backendu na avaxdev
- Output streamován do response (pro UI log)
F3 — UI v launcheru (next session)¶
- Enhance
AvaxAdminScreen._tab_apps()→ app list s detail view - Nový dialog
_CreateAppV2Dialog - Per-app detail s tabs: Verze / Backend / S3 / Subscriptions
F4 — Obchod aplikací screen (next session)¶
- Rename current
StoreScreen→BackupPlansScreen(pro zálohy) - Nový
AppStoreScreenv menu (Software → Obchod): - List všech apps s
is_public=true - Self-service "Přidat do mojí firmy" → vytvoří subscription
- V Knihovně → "Aplikace dostupné navíc" link → vede do Obchodu
Migrace dat (best-effort)¶
Existující apps (jako avax-legal-client) se po migraci 016 najdou s
is_public=false, backend_mount=false, ostatní nové sloupce NULL.
Manuální update pro avax-legal:
UPDATE apps SET
backend_mount = true,
backend_module = 'avax_legal_backend.legal',
gitea_repo_url = 'https://git.avaxis.cz/qwen/avax-legal',
local_path = 'C:\Users\plave\AIsoftware\avax-legal',
is_public = true
WHERE slug = 'avax-legal-client';
A registr dynamic mount (zatim přes _BOOTSTRAP_MODULES, F2 přesune do tabulky):
INSERT INTO dynamic_backend_mounts (app_id, module_path, mount_prefix, enabled)
SELECT id, 'avax_legal_backend.legal', '/legal', true FROM apps
WHERE slug='avax-legal-client';
Bezpečnost¶
- Endpointy
/admin/app-management/*vyžadujísystem_role = super_admin - Pull/Migrate/Restart vyžadují SSH access z backend procesu (F2):
zařídí se SSH key
/home/avax/.ssh/avax-admin-keyse sudo rights - Gitea API: použít existující service token
claudAI - S3: per-app klíče oddělené, vendor nezíská cross-app přístup
Souvislosti¶
- Spec souvisí s docs/spec/app-distribution.md (publish flow)
- Spec souvisí s docs/spec/app-catalog.md (channels)
- F2 vyžaduje běžícího gitea (✓) a SSH access mezi backendem a sebou (TODO)
Verze tohoto spec¶
v1.0-draft — 2026-05-13 — F1 implementováno, F2-F4 ke schválení a kódování.