Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f708d0ea87 |
No files matched your search
@@ -49,7 +49,7 @@ import (
|
||||
|
||||
const workerPollInterval = 2 * time.Second
|
||||
|
||||
const defaultListenAddr = "127.0.0.1:9600"
|
||||
const defaultListenAddr = "127.0.0.1:8900"
|
||||
const defaultModel = "default"
|
||||
|
||||
type config struct {
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Command migrate wendet die offenen Postgres-Migrationen des AI-Moduls an.
|
||||
// Einmal gegen eine frische Datenbank ausfuehren, bevor ai-app startet.
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
|
||||
"gitea.perlbach24.de/scripte/nexarch/ai/internal/migrate"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dsn := os.Getenv("NEXARCH_AI_APP_TENANT_DSN")
|
||||
if dsn == "" {
|
||||
log.Fatal("migrate: NEXARCH_AI_APP_TENANT_DSN ist erforderlich")
|
||||
}
|
||||
dir := "migrations"
|
||||
if len(os.Args) > 1 {
|
||||
dir = os.Args[1]
|
||||
}
|
||||
ctx := context.Background()
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
log.Fatalf("migrate: datenbankverbindung: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
migrations, err := migrate.Load(dir)
|
||||
if err != nil {
|
||||
log.Fatalf("migrate: migrationen laden: %v", err)
|
||||
}
|
||||
applied, err := migrate.Up(ctx, pool, migrations)
|
||||
if err != nil {
|
||||
log.Fatalf("migrate: migrationen anwenden: %v", err)
|
||||
}
|
||||
log.Printf("migrate: %d migration(en) angewendet", len(applied))
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
# Betrieb: ai-app
|
||||
|
||||
Port-Bereich 8900 bis 8999 (`deploy/ports.tsv`), Routenpräfix `/api/ai/v1` (`deploy/routes.tsv`). Secrets gehören ausschließlich in die Umgebung (`/etc/nexarch/ai-app.env`, Rechte 600), nie in Code, Logs oder Dokumentation.
|
||||
|
||||
## Einrichten
|
||||
|
||||
1. Datenbank und Rolle anlegen (nicht Teil der Units).
|
||||
2. `/etc/nexarch/ai-app.env` mit den Variablen unten anlegen.
|
||||
3. Migrationen anwenden: `NEXARCH_AI_APP_TENANT_DSN=... ./migrate ai/migrations` (Fortschrittstabelle `ai_schema_migrations`).
|
||||
4. Unit aus `deploy/systemd/nexarch-ai-app.service.tmpl` installieren (`__INSTALL_DIR__` ersetzen), `systemctl enable --now nexarch-ai-app`.
|
||||
5. Health: `GET /healthz`.
|
||||
|
||||
Eine Datenbank, die vor ENG-10 mit den AI-Migrationen angelegt wurde, führte den Fortschritt in `connect_schema_migrations`. Ist sie ausschließlich AI-Datenbank, vor dem ersten Lauf `ALTER TABLE connect_schema_migrations RENAME TO ai_schema_migrations;`. Bei gemeinsamer Datenbank mit Connect nicht umbenennen, sondern die AI-Einträge von Hand in die neue Tabelle übertragen.
|
||||
|
||||
## Variablen
|
||||
|
||||
| Variable | Standard | Wirkung |
|
||||
|---|---|---|
|
||||
| `NEXARCH_AI_APP_TENANT_DSN` | Pflicht | Datenbank des AI-Moduls |
|
||||
| `NEXARCH_AI_APP_SERVICE_TOKEN` | Pflicht | Service-Token, das alle Aufrufer im Header `X-Service-Token` senden |
|
||||
| `NEXARCH_AI_APP_LISTEN_ADDR` | `127.0.0.1:8900` | Lauschadresse |
|
||||
| `NEXARCH_AI_APP_MODEL` | `default` | Modellname für Inferenzaufrufe |
|
||||
| `NEXARCH_AI_APP_POLICY_URL` / `_POLICY_SERVICE_TOKEN` | Pflicht, oder Übergangsschalter | Rechteprüfung der semantischen Suche; Token Pflicht, sobald URL gesetzt |
|
||||
| `NEXARCH_AI_APP_POLICY_DISABLED` | aus | `1` startet ohne Rechteprüfung (Übergang, Warnlog) |
|
||||
| `NEXARCH_AI_APP_MODULE_BASE_URLS` | leer | `modul=url,modul2=url2`, Basis-URLs für den Rückschreib-Push |
|
||||
| `NEXARCH_AI_APP_CORE_BASE_URL` / `_CORE_SERVICE_TOKEN` | leer | Core-Anbindung; ohne sie ist die Objekttyp-Registrierung (GOV-01) deaktiviert |
|
||||
@@ -0,0 +1,40 @@
|
||||
# ENG-10 – ai-app: Deployment-Anbindung – Prüfprotokoll
|
||||
|
||||
Datum: 2026-11-06. Host: Entwicklungshost 192.168.1.204 (Wegwerf-Rolle/DB `eng10_test`, nach Abschluss entfernt).
|
||||
|
||||
## Befund (Ausgangslage)
|
||||
|
||||
- `ai-app` lauschte standardmäßig auf `127.0.0.1:9600`, außerhalb des für `ai` reservierten Bereichs 8900 bis 8999 (`deploy/ports.tsv`). 9600 belegt außerdem `workflow-app` (`docs/BETRIEB-PORTAL.md`). `scripts/check-port-defaults.sh` erkennt nur `":NNNN"`-Literale und meldete den Verstoß nicht.
|
||||
- Kein systemd-Template für `ai-app` (Connect und DMS haben eines).
|
||||
- Kein Migrationswerkzeug für das AI-Modul; `ai/internal/migrate` führte den Fortschritt in der Tabelle `connect_schema_migrations` (Kopierfehler aus dem Connect-Modul).
|
||||
|
||||
## Umsetzung
|
||||
|
||||
- Standard-Lauschadresse `127.0.0.1:8900`.
|
||||
- `ai/cmd/migrate` (Muster `connect/cmd/migrate`, DSN aus `NEXARCH_AI_APP_TENANT_DSN`, Verzeichnis als Argument).
|
||||
- Fortschrittstabelle `ai_schema_migrations`.
|
||||
- `deploy/systemd/nexarch-ai-app.service.tmpl` nach dem Muster von `nexarch-connect-app` (gleiche Härtung).
|
||||
- `ai/docs/BETRIEB-UMGEBUNGSVARIABLEN.md` mit Einrichtungsschritten und Variablen.
|
||||
|
||||
## Akzeptanzkriterien
|
||||
|
||||
| # | Kriterium | Ergebnis |
|
||||
|---|---|---|
|
||||
| 1 | Standard-Port liegt im Bereich von `ai` | **Erfüllt.** 8900. `scripts/check-port-defaults.sh` meldet für `ai/cmd/ai-app` nichts (dort erkennt es allerdings das Format `127.0.0.1:NNNN` ohnehin nicht, siehe Einschränkungen). |
|
||||
| 2 | systemd-Template vorhanden und gehärtet | **Erfüllt.** `scripts/check-systemd-hardening.sh`: ok, 18 Dienste geprüft. Start der Unit selbst nicht getestet. |
|
||||
| 3 | Migrationen anwendbar, idempotent | **Erfüllt.** Frische DB: 16 Migrationen angewendet, zweiter Lauf 0; ohne DSN klare Fehlermeldung, Abbruch. |
|
||||
| 4 | Eigene Fortschrittstabelle | **Erfüllt.** `ai_schema_migrations` existiert, `connect_schema_migrations` nicht (`TestUp_UsesOwnTrackingTable`, echte DB). |
|
||||
|
||||
## Prüfungen vor der Abnahme
|
||||
|
||||
| # | Prüfung | Ergebnis |
|
||||
|---|---|---|
|
||||
| 1 | Migrationswerkzeug gegen frische Wegwerf-DB | **Bestanden** (siehe AK3). |
|
||||
| 2 | Bestehende Modultests | **Bestanden.** `./internal/migrate/`, `./cmd/ai-app/` grün, `go build ./...` und `go vet` sauber. |
|
||||
| 3 | Unit startet `ai-app` real | **Offen.** Template nicht auf einem Host installiert, `systemctl` nicht ausgeführt. |
|
||||
|
||||
## Einschränkungen
|
||||
|
||||
- Umbenennung der Fortschrittstabelle betrifft bestehende AI-Datenbanken; Hinweis in `BETRIEB-UMGEBUNGSVARIABLEN.md`. Eine automatische Übernahme gibt es nicht.
|
||||
- Nicht Teil der Kachel: Aufnahme in `deploy/rollout-131-*.sh` (Host-131-Rollout), Provisionierung von DB, Rolle und Secrets.
|
||||
- Weitere Port-Verstöße außerhalb von `ai`, die beim Prüfen auffielen und nicht behoben wurden: `workflow-app` und `tasks-a11y-fixture` auf 9600 (Bereich 8800 bis 8899), Connect-Fixtures doppelt auf 9500, mehrere Fixtures und `verapdf-sidecar` außerhalb ihrer Bereiche. `check-port-defaults.sh` erkennt `127.0.0.1:NNNN`-Literale nicht; eine Erweiterung würde diese Verstöße sichtbar machen und braucht eine eigene Entscheidung.
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
type Migration = cmigrate.Migration
|
||||
|
||||
const TrackingTable = "connect_schema_migrations"
|
||||
const TrackingTable = "ai_schema_migrations"
|
||||
|
||||
var migrator = cmigrate.MustNew(TrackingTable)
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package migrate
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"gitea.perlbach24.de/scripte/nexarch/common/testdb"
|
||||
)
|
||||
|
||||
func TestUp_UsesOwnTrackingTable(t *testing.T) {
|
||||
dsn := os.Getenv("TEST_TENANT_DSN")
|
||||
if dsn == "" {
|
||||
t.Skip("TEST_TENANT_DSN nicht gesetzt, Integrationstest uebersprungen")
|
||||
}
|
||||
pool := testdb.Pool(t, dsn)
|
||||
dir, err := filepath.Abs("../../migrations")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
migrations, err := Load(dir)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ctx := context.Background()
|
||||
if _, err := Up(ctx, pool, migrations); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
again, err := Up(ctx, pool, migrations)
|
||||
if err != nil || len(again) != 0 {
|
||||
t.Fatalf("zweiter lauf soll nichts anwenden: %v %v", again, err)
|
||||
}
|
||||
var own, foreign bool
|
||||
if err := pool.QueryRow(ctx, `SELECT to_regclass('ai_schema_migrations') IS NOT NULL, to_regclass('connect_schema_migrations') IS NOT NULL`).Scan(&own, &foreign); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !own || foreign {
|
||||
t.Fatalf("fortschrittstabelle: ai=%v connect=%v", own, foreign)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
[Unit]
|
||||
Description=NEXARCH AI - ai-app (ENG-10)
|
||||
After=network.target postgresql.service
|
||||
Wants=postgresql.service
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
User=nexarch
|
||||
Group=nexarch
|
||||
EnvironmentFile=/etc/nexarch/ai-app.env
|
||||
ExecStart=__INSTALL_DIR__/bin/ai-app
|
||||
Restart=on-failure
|
||||
RestartSec=3
|
||||
WorkingDirectory=__INSTALL_DIR__
|
||||
# QA-15 F-13/OPS-08: reiner Netzwerkdienst (HTTP + Postgres-DSN aus
|
||||
# EnvironmentFile), keine eigene Schreibarbeit im Dateisystem.
|
||||
NoNewPrivileges=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
PrivateTmp=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
Reference in new issue
Block a user