Přeskočit obsah

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):

  1. Iterace přes _BOOTSTRAP_MODULES (vendored seznam — avax-legal atd.)
  2. Iterace přes DB dynamic_backend_mounts WHERE enabled=true
  3. Pro každý: importlib.import_module(module_path) + app.include_router(mod.router) (+ optional admin_router, sync_router)

Bezpečné — pokud import selže, jen warning v logu, ostatní moduly se mountnou.

main.py finální:

from .dynamic_mounts import mount_all
mount_all(app)

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 StoreScreenBackupPlansScreen (pro zálohy)
  • Nový AppStoreScreen v 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-key se 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

Verze tohoto spec

v1.0-draft — 2026-05-13 — F1 implementováno, F2-F4 ke schválení a kódování.