Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2f53512e4d | ||
|
|
497ab84031 |
@@ -118,15 +118,6 @@ ritrovamento di una card tramite un collegamento non ne implica l'approvazione.
|
|||||||
espliciti, che contribuisce alla consultazione di contenuti pertinenti. La sua
|
espliciti, che contribuisce alla consultazione di contenuti pertinenti. La sua
|
||||||
rimozione non comporta la cancellazione delle card collegate.
|
rimozione non comporta la cancellazione delle card collegate.
|
||||||
|
|
||||||
## Esempi didattici
|
|
||||||
|
|
||||||
**Example workspace** — Un workspace destinato alla pratica con ThothII, associato
|
|
||||||
a dati di esempio, schema descritto ed Evidence curate, pronto per iniziare una sessione.
|
|
||||||
|
|
||||||
**Practice question** — Una domanda di accompagnamento a un Example workspace,
|
|
||||||
proposta come spunto per il percorso human in the loop e priva di soluzione attesa.
|
|
||||||
_Avoid_: Solved Question, caso di valutazione del benchmark.
|
|
||||||
|
|
||||||
## Evidence
|
## Evidence
|
||||||
|
|
||||||
**Context specialist** — La persona competente sul dominio che redige e cura il
|
**Context specialist** — La persona competente sul dominio che redige e cura il
|
||||||
|
|||||||
+7
-1
@@ -1,6 +1,6 @@
|
|||||||
# Project state
|
# Project state
|
||||||
|
|
||||||
Updated: 2026-09-15. This is a current snapshot, not a release diary. Stable commands
|
Updated: 2026-09-27. This is a current snapshot, not a release diary. Stable commands
|
||||||
and invariants are in [AGENTS.md](AGENTS.md); prior snapshots remain in Git.
|
and invariants are in [AGENTS.md](AGENTS.md); prior snapshots remain in Git.
|
||||||
|
|
||||||
## Current contracts
|
## Current contracts
|
||||||
@@ -56,6 +56,12 @@ embedded/upstream identity, not another ThothII OIDC login. Read
|
|||||||
|
|
||||||
Last recorded application deliveries (not a fresh runtime attestation):
|
Last recorded application deliveries (not a fresh runtime attestation):
|
||||||
|
|
||||||
|
- [Coordinated ThothII/Omics release](docs/reports/2026-09-26-server-release-execution.md):
|
||||||
|
core/frontend `497ab840-preflight`, Omics proxy fix `928f7e9f` with existing web
|
||||||
|
image retained. Automated acceptance passed; on September 27 the operator confirmed
|
||||||
|
browser access, UI controls and session start/stop/resume. Functional browser
|
||||||
|
acceptance passed; remaining extended checks are handed off in the
|
||||||
|
[server acceptance follow-up](docs/reports/2026-09-27-server-acceptance-handoff.md).
|
||||||
- [Session dialogs](docs/reports/2026-09-14-session-dialogs-release.md):
|
- [Session dialogs](docs/reports/2026-09-14-session-dialogs-release.md):
|
||||||
`b1723c34-session-dialogs-20260914`, frontend-only.
|
`b1723c34-session-dialogs-20260914`, frontend-only.
|
||||||
- [Session layout/Memory fix](docs/reports/2026-09-14-session-layout-memory-fix.md):
|
- [Session layout/Memory fix](docs/reports/2026-09-14-session-layout-memory-fix.md):
|
||||||
|
|||||||
@@ -34,12 +34,11 @@ for the executed consolidation and the inventory of historical sources retained
|
|||||||
|
|
||||||
## Docker Compose and installation
|
## Docker Compose and installation
|
||||||
|
|
||||||
For a fresh installation, follow the guided terminal procedure in
|
For a fresh installation, follow the complete manual procedure in
|
||||||
[Italian](docs/install/standalone-manual-it.md) or
|
[Italian](docs/install/standalone-manual-it.md) or
|
||||||
[English](docs/install/standalone-manual-en.md). The single
|
[English](docs/install/standalone-manual-en.md). Configure protected files first;
|
||||||
`tht setup --complete` command validates protected files, builds the images, runs
|
then run the documented build, explicit migrations and startup commands with the
|
||||||
Catalog migration, starts the stack and imports the configured workspace repository.
|
same installation descriptor and Compose project. There is no installer or launcher.
|
||||||
There is no graphical installer or native launcher.
|
|
||||||
|
|
||||||
The mandatory stack includes frontend, core, PostgreSQL catalog, Qdrant, Ollama
|
The mandatory stack includes frontend, core, PostgreSQL catalog, Qdrant, Ollama
|
||||||
and the embedding initializer. DWH and LLM endpoints remain external dependencies.
|
and the embedding initializer. DWH and LLM endpoints remain external dependencies.
|
||||||
|
|||||||
@@ -16,16 +16,12 @@ import { loadSettings } from "./settings/settings-store.js";
|
|||||||
import { ThtRunner, type SessionRow } from "./tht/tht-runner.js";
|
import { ThtRunner, type SessionRow } from "./tht/tht-runner.js";
|
||||||
import { WorkspaceRegistry } from "./workspaces/registry.js";
|
import { WorkspaceRegistry } from "./workspaces/registry.js";
|
||||||
import { WorkspaceSecretStore } from "./workspaces/secret-store.js";
|
import { WorkspaceSecretStore } from "./workspaces/secret-store.js";
|
||||||
import { createProductionWorkspaceDiagnoser } from "./workspaces/diagnostics.js";
|
|
||||||
import { resolveCatalogRuntimeBinding } from "./catalog/runtime-binding.js";
|
|
||||||
import { CatalogService } from "./catalog/service.js";
|
|
||||||
import { validateOperationalWorkspace } from "./workspaces/schema.js";
|
|
||||||
import { createCatalogRepository } from "./catalog/repository.js";
|
import { createCatalogRepository } from "./catalog/repository.js";
|
||||||
import type { CatalogRepository } from "./catalog/types.js";
|
import type { CatalogRepository } from "./catalog/types.js";
|
||||||
|
|
||||||
type OperatorAction = "maintenance-activate" | "maintenance-deactivate" | "maintenance-status"
|
type OperatorAction = "maintenance-activate" | "maintenance-deactivate" | "maintenance-status"
|
||||||
| "session-inventory" | "workflow-doctor" | "workspace-integrity"
|
| "session-inventory" | "workflow-doctor" | "workspace-integrity"
|
||||||
| "workspace-pull" | "workspace-test" | "pi-test" | "effective-settings";
|
| "pi-test" | "effective-settings";
|
||||||
|
|
||||||
const lifecyclePrincipal: PrincipalContext = {
|
const lifecyclePrincipal: PrincipalContext = {
|
||||||
issuer: "tht-operator-command",
|
issuer: "tht-operator-command",
|
||||||
@@ -123,119 +119,6 @@ async function workspaceIntegrity(config: AppConfig): Promise<{
|
|||||||
return { ready: true, ...integrity };
|
return { ready: true, ...integrity };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function workspacePull(config: AppConfig): Promise<{
|
|
||||||
ready: boolean;
|
|
||||||
status: "succeeded" | "degraded";
|
|
||||||
branch: string;
|
|
||||||
head?: string;
|
|
||||||
degraded: boolean;
|
|
||||||
}> {
|
|
||||||
const status = await new WorkspaceRegistry(config.workspaceRegistry).pull();
|
|
||||||
return {
|
|
||||||
ready: !status.degraded,
|
|
||||||
status: status.degraded ? "degraded" : "succeeded",
|
|
||||||
branch: status.branch,
|
|
||||||
...(status.head ? { head: status.head } : {}),
|
|
||||||
degraded: status.degraded,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface WorkspaceTestReport {
|
|
||||||
id: string;
|
|
||||||
status: "ready" | "failed";
|
|
||||||
database: "reachable" | "not_configured" | "failed";
|
|
||||||
diagnostics: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
async function workspaceTest(config: AppConfig): Promise<{
|
|
||||||
ready: boolean;
|
|
||||||
workspaces: WorkspaceTestReport[];
|
|
||||||
}> {
|
|
||||||
if (!config.catalogDatabase) throw new Error("Catalog database is not configured");
|
|
||||||
const registry = new WorkspaceRegistry(config.workspaceRegistry);
|
|
||||||
const revisions = await registry.list();
|
|
||||||
const repository = createCatalogRepository(config.catalogDatabase);
|
|
||||||
try {
|
|
||||||
const secretStore = new WorkspaceSecretStore({
|
|
||||||
root: config.workspaceSecretStoreRoot,
|
|
||||||
runtimeRoot: config.workspaceSecretRuntimeRoot,
|
|
||||||
installationId: config.workspaceRegistry.installationId,
|
|
||||||
});
|
|
||||||
const catalogService = new CatalogService(
|
|
||||||
repository,
|
|
||||||
registry,
|
|
||||||
secretStore,
|
|
||||||
config.workspaceRegistry.secretRoots,
|
|
||||||
config.workspaceDiagnosticTimeoutMs,
|
|
||||||
);
|
|
||||||
const diagnose = createProductionWorkspaceDiagnoser(config.workspaceDiagnosticTimeoutMs, undefined, {
|
|
||||||
internalQdrantUrl: config.internalQdrantUrl,
|
|
||||||
internalEmbeddingUrl: config.internalEmbeddingUrl,
|
|
||||||
internalEmbeddingId: config.internalEmbeddingId,
|
|
||||||
internalEmbeddingModel: config.internalEmbeddingModel,
|
|
||||||
internalEmbeddingDimensions: config.internalEmbeddingDimensions,
|
|
||||||
});
|
|
||||||
const databases = await repository.list();
|
|
||||||
const reports: WorkspaceTestReport[] = [];
|
|
||||||
for (const revision of revisions) {
|
|
||||||
const diagnostics: string[] = [];
|
|
||||||
let workspace: ReturnType<typeof validateOperationalWorkspace>;
|
|
||||||
try {
|
|
||||||
workspace = validateOperationalWorkspace((await registry.read(revision.id)).workspace);
|
|
||||||
} catch {
|
|
||||||
reports.push({ id: revision.id, status: "failed", database: "not_configured", diagnostics: ["workspace_invalid"] });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const database = databases.find((candidate) => candidate.workspaceId === revision.id);
|
|
||||||
if (!database) {
|
|
||||||
reports.push({ id: revision.id, status: "failed", database: "not_configured", diagnostics: ["database_binding_missing"] });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let tested;
|
|
||||||
try {
|
|
||||||
tested = await catalogService.test(database);
|
|
||||||
} catch {
|
|
||||||
reports.push({ id: revision.id, status: "failed", database: "failed", diagnostics: ["database_unreachable"] });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (!tested || tested.connectionStatus !== "reachable") {
|
|
||||||
reports.push({ id: revision.id, status: "failed", database: "failed", diagnostics: ["database_unreachable"] });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
let lease: ReturnType<typeof resolveCatalogRuntimeBinding>;
|
|
||||||
try {
|
|
||||||
lease = resolveCatalogRuntimeBinding({
|
|
||||||
workspace,
|
|
||||||
database: tested,
|
|
||||||
environment: process.env,
|
|
||||||
secretRoots: config.workspaceRegistry.secretRoots,
|
|
||||||
secretStore,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
reports.push({ id: revision.id, status: "failed", database: "reachable", diagnostics: ["binding_missing"] });
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
// CatalogService.test() above is the authoritative database probe and records its
|
|
||||||
// outcome. The remaining diagnoser pass checks Evidence and internal semantic services;
|
|
||||||
// skipping its legacy DWH probe avoids requiring a second response-shape contract for a
|
|
||||||
// REST health endpoint.
|
|
||||||
const result = await diagnose(lease.workspace, lease.bindings, { writeProbe: false, skipDwh: true });
|
|
||||||
diagnostics.push(...result.diagnostics.map((diagnostic) => diagnostic.code));
|
|
||||||
const ready = result.activatable;
|
|
||||||
reports.push({ id: revision.id, status: ready ? "ready" : "failed", database: "reachable", diagnostics });
|
|
||||||
} catch {
|
|
||||||
reports.push({ id: revision.id, status: "failed", database: "reachable", diagnostics: ["connector_unavailable"] });
|
|
||||||
} finally {
|
|
||||||
lease.release();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return { ready: reports.length > 0 && reports.every((report) => report.status === "ready"), workspaces: reports };
|
|
||||||
} finally {
|
|
||||||
await repository.close?.();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function runOperatorAction(
|
export async function runOperatorAction(
|
||||||
action: OperatorAction,
|
action: OperatorAction,
|
||||||
config: AppConfig,
|
config: AppConfig,
|
||||||
@@ -249,8 +132,6 @@ export async function runOperatorAction(
|
|||||||
if (action === "session-inventory") return await sessionInventory(config);
|
if (action === "session-inventory") return await sessionInventory(config);
|
||||||
if (action === "workflow-doctor") return await workflowDiagnostics(config);
|
if (action === "workflow-doctor") return await workflowDiagnostics(config);
|
||||||
if (action === "workspace-integrity") return await workspaceIntegrity(config);
|
if (action === "workspace-integrity") return await workspaceIntegrity(config);
|
||||||
if (action === "workspace-pull") return await workspacePull(config);
|
|
||||||
if (action === "workspace-test") return await workspaceTest(config);
|
|
||||||
const modelCatalog = loadRuntimeModelCatalog(config.modelCatalogFile);
|
const modelCatalog = loadRuntimeModelCatalog(config.modelCatalogFile);
|
||||||
if (action === "effective-settings") {
|
if (action === "effective-settings") {
|
||||||
return effectiveSettings(config, loadSettings(config), modelCatalog);
|
return effectiveSettings(config, loadSettings(config), modelCatalog);
|
||||||
@@ -265,7 +146,6 @@ async function main(): Promise<void> {
|
|||||||
if (!action || ![
|
if (!action || ![
|
||||||
"maintenance-activate", "maintenance-deactivate", "maintenance-status", "session-inventory",
|
"maintenance-activate", "maintenance-deactivate", "maintenance-status", "session-inventory",
|
||||||
"workflow-doctor", "workspace-integrity", "pi-test", "effective-settings",
|
"workflow-doctor", "workspace-integrity", "pi-test", "effective-settings",
|
||||||
"workspace-pull", "workspace-test",
|
|
||||||
].includes(action)) throw new Error("invalid operator action");
|
].includes(action)) throw new Error("invalid operator action");
|
||||||
const result = await runOperatorAction(action, loadConfig(process.env));
|
const result = await runOperatorAction(action, loadConfig(process.env));
|
||||||
process.stdout.write(`${JSON.stringify(result)}\n`);
|
process.stdout.write(`${JSON.stringify(result)}\n`);
|
||||||
|
|||||||
@@ -36,10 +36,6 @@ vi.mock("../src/tht/tht-runner.js", () => ({
|
|||||||
|
|
||||||
vi.mock("../src/workspaces/registry.js", () => ({
|
vi.mock("../src/workspaces/registry.js", () => ({
|
||||||
WorkspaceRegistry: class {
|
WorkspaceRegistry: class {
|
||||||
async pull() {
|
|
||||||
return { branch: "main", head: "a".repeat(40), ahead: 0, behind: 0, degraded: false };
|
|
||||||
}
|
|
||||||
|
|
||||||
async listRetainedSnapshots() {
|
async listRetainedSnapshots() {
|
||||||
return [{ snapshotPath: "/data/workspace-registry/snapshots/revision/workspace.yaml" }];
|
return [{ snapshotPath: "/data/workspace-registry/snapshots/revision/workspace.yaml" }];
|
||||||
}
|
}
|
||||||
@@ -102,13 +98,3 @@ test("workflow doctor gives schema-v4 runtime rendering a live Catalog repositor
|
|||||||
expect(fakes.releaseWorkspaceRuntime).toHaveBeenCalledOnce();
|
expect(fakes.releaseWorkspaceRuntime).toHaveBeenCalledOnce();
|
||||||
expect(fakes.catalogRepository.close).toHaveBeenCalledOnce();
|
expect(fakes.catalogRepository.close).toHaveBeenCalledOnce();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("workspace pull exposes only safe Git status", async () => {
|
|
||||||
await expect(runOperatorAction("workspace-pull", config)).resolves.toEqual({
|
|
||||||
ready: true,
|
|
||||||
status: "succeeded",
|
|
||||||
branch: "main",
|
|
||||||
head: "a".repeat(40),
|
|
||||||
degraded: false,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -8,11 +8,6 @@ cp deploy/secrets/thothii.secrets.example deploy/secrets/thothii.secrets
|
|||||||
chmod 600 deploy/secrets/thothii.secrets
|
chmod 600 deploy/secrets/thothii.secrets
|
||||||
```
|
```
|
||||||
|
|
||||||
For a normal local installation, `tht setup --complete` creates the active bundle at
|
|
||||||
`deploy/local/secrets/thothii.secrets` and creates the two Catalog password files beside it. The
|
|
||||||
generated `deploy/local/operator.env` contains only absolute paths to those files; never copy
|
|
||||||
secret values into `operator.env`.
|
|
||||||
|
|
||||||
The file uses strict `KEY=VALUE` lines (comments and blank lines are allowed). The supported
|
The file uses strict `KEY=VALUE` lines (comments and blank lines are allowed). The supported
|
||||||
installation keys are `THT_MODEL_API_KEY`, `THT_DWH_API_KEY`, `THT_CA`, `THT_SSL_CA`,
|
installation keys are `THT_MODEL_API_KEY`, `THT_DWH_API_KEY`, `THT_CA`, `THT_SSL_CA`,
|
||||||
`THT_OIDC_CLIENT_SECRET`, and `THT_AUTHENTIK_API_TOKEN`. Installation Model Catalog providers may
|
`THT_OIDC_CLIENT_SECRET`, and `THT_AUTHENTIK_API_TOKEN`. Installation Model Catalog providers may
|
||||||
@@ -34,11 +29,6 @@ Session and metadata-generation runtimes read only the provider key named by
|
|||||||
credential reference, not their execution lifecycle. Pi-owned authentication remains available only
|
credential reference, not their execution lifecycle. Pi-owned authentication remains available only
|
||||||
to session-only built-in providers through `authentication.mode: pi_auth`.
|
to session-only built-in providers through `authentication.mode: pi_auth`.
|
||||||
|
|
||||||
Workspace database credentials are intentionally not part of this global bundle. Configure each
|
|
||||||
workspace's database binding, password/token, tunnel key and CA in Database Management; the
|
|
||||||
installation stores those values in its encrypted workspace secret store. The workspace Git
|
|
||||||
repository may declare database identity and Evidence, but must never contain these credentials.
|
|
||||||
|
|
||||||
Do not add vector or embedding endpoint credentials to the bundle. Active operator manuals use
|
Do not add vector or embedding endpoint credentials to the bundle. Active operator manuals use
|
||||||
internal Qdrant and Ollama services, so vector/embedding runtime endpoint secrets are not part of
|
internal Qdrant and Ollama services, so vector/embedding runtime endpoint secrets are not part of
|
||||||
the supported installation contract.
|
the supported installation contract.
|
||||||
|
|||||||
+42
-41
@@ -1,63 +1,64 @@
|
|||||||
# Install and first start
|
# Install and first start
|
||||||
|
|
||||||
Use the guided procedure for a fresh installation:
|
Use one complete procedure for a fresh installation:
|
||||||
|
|
||||||
- [Italian guided installation](standalone-manual-it.md)
|
- [Italian manual installation](standalone-manual-it.md)
|
||||||
- [English guided installation](standalone-manual-en.md)
|
- [English manual installation](standalone-manual-en.md)
|
||||||
|
|
||||||
The procedure covers Windows through Ubuntu WSL2, macOS, and Linux including an Omarchy/Arch-like
|
Both cover macOS, Windows through Ubuntu WSL2, and Linux. They use a Gitea clone,
|
||||||
host. It uses the application clone, one installation secret bundle, protected repository
|
protected local configuration and manual terminal commands, without an application
|
||||||
credentials when needed, and a terminal command. No host Node.js, Python or Pi installation is
|
installer or launcher. See their verification matrix for tests still pending.
|
||||||
required.
|
|
||||||
|
|
||||||
## What must be ready
|
## What must be ready
|
||||||
|
|
||||||
You need Docker with Compose v2, Git, Bash, curl, OpenSSL and shasum. You also need access to the
|
You need Docker with Compose, the host operator command `tht`, access to the workspace
|
||||||
workspace repository and the values supplied by its owner: repository URL/branch, DWH endpoint,
|
repository, and the credentials and network routes for the configured DWH and model
|
||||||
database/schema, transport, credentials or certificates, Evidence credentials when applicable,
|
providers. Pi runs inside the application runtime; no host Pi installation is needed.
|
||||||
and LLM provider/API-key information.
|
|
||||||
|
|
||||||
The workspace repository and the THothII application repository are different. A workspace
|
The stack includes `frontend`, `core`, `catalog-db`, `qdrant`, `embedding`, plus the
|
||||||
descriptor may declare Evidence, but database passwords and installation bindings are stored in
|
one-shot `embedding-model-init` and `catalog-migrate` services. DWH and generative-model
|
||||||
the installation Catalog, not in Git.
|
endpoints remain separate installation settings.
|
||||||
|
|
||||||
## One guided command
|
Secrets, certificates, Pi authentication and endpoint bindings are protected local files.
|
||||||
|
Do not commit them or copy the configuration of another machine unchanged.
|
||||||
|
|
||||||
After cloning THothII, checking prerequisites and installing tht, run:
|
## Follow the ordered procedure
|
||||||
|
|
||||||
~~~
|
The bilingual guides provide the exact commands for:
|
||||||
tht setup --complete --profile local --shell-mode full --shell-default-locale en
|
|
||||||
~~~
|
|
||||||
|
|
||||||
The first run creates protected placeholders under deploy/local/secrets/. Fill the required
|
1. Cloning the selected revision and checking prerequisites.
|
||||||
credential files and rerun the same command. The command validates the local files and paths,
|
2. Bootstrapping the native host command.
|
||||||
renders Compose, builds the images, starts catalog-db, runs catalog-migrate, starts the full
|
3. Preparing catalog passwords and using
|
||||||
stack, and pulls/activates the workspace repository. Evidence source files declared by the
|
`tht setup --profile local --shell-mode full --shell-default-locale en --configure-only`.
|
||||||
workspace are imported during activation.
|
4. Completing model, authentication and workspace credentials.
|
||||||
|
5. Generating configuration, building images and explicitly running `catalog-migrate`.
|
||||||
|
6. Starting the installation and checking health and readiness.
|
||||||
|
|
||||||
|
Do not run setup alone as a substitute for that sequence. Migrations are not an
|
||||||
|
implicit effect of backend startup or `tht start`. Do not mix this installation's
|
||||||
|
descriptor/project with a different low-level Compose environment.
|
||||||
|
|
||||||
For an already configured installation:
|
For an already configured installation:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
tht --installation /absolute/path/thothii-installation.yaml status
|
tht --installation /absolute/path/thothii-installation.yaml status
|
||||||
tht --installation /absolute/path/thothii-installation.yaml doctor --json
|
tht --installation /absolute/path/thothii-installation.yaml doctor --json
|
||||||
tht --installation /absolute/path/thothii-installation.yaml workspace test --json
|
```
|
||||||
~~~
|
|
||||||
|
|
||||||
doctor --json is the non-destructive general core test. workspace test also probes the configured
|
`/health` checks application-process readiness. Doctor also checks configuration,
|
||||||
database, Evidence, Qdrant and embedding service for every active workspace. It requires the
|
workspace, workflow and Pi prerequisites; a healthy web page alone does not prove
|
||||||
workspace database to have been configured in Database Management first.
|
that a real database question can complete.
|
||||||
|
|
||||||
## Installer-only completion
|
## After startup
|
||||||
|
|
||||||
The installer must still decide which LLMs and API keys are approved, configure and test each
|
Prepare [workspaces](../operations/workspaces.md), configure a database in
|
||||||
workspace database, synchronize its schema, generate and consolidate descriptions, create Qdrant
|
[Database Management](../operations/database-management.md), and complete the functional
|
||||||
entries, review naming-based FK suggestions alongside schema FKs, and load the approved
|
checks in the installation guide before using real data.
|
||||||
relationships. The final declaration of completeness requires green doctor and workspace test
|
|
||||||
results plus one real natural-language question completed through final SQL.
|
|
||||||
|
|
||||||
Migrations are part of setup --complete. Do not mix this installation’s descriptor or volumes with
|
See [display mode and language](shell-and-language.md), [local authentication](authentication-local.md),
|
||||||
a different Compose environment. Preserve the descriptor, credentials, Catalog and persistent
|
[OIDC](authentication-oidc.md) and [model configuration](../general/pi-configuration.md)
|
||||||
volumes; do not use docker compose down --volumes as a routine stop.
|
for later changes. Embedded portal integration is separate from a fresh standalone setup.
|
||||||
|
|
||||||
See the guides for the Windows/macOS/Linux prerequisite matrix, workspace repository explanation,
|
Use the installation's normal `tht start`, `tht stop` and diagnostic commands.
|
||||||
secret layout and Gate A/Gate B acceptance checks.
|
Preserve its descriptor, credentials, database and persistent volumes; do not use
|
||||||
|
`down --volumes` as a routine stop or upgrade.
|
||||||
|
|||||||
@@ -1,256 +1,324 @@
|
|||||||
# Guided standalone installation
|
# Manual standalone installation
|
||||||
|
|
||||||
[Versione italiana](standalone-manual-it.md)
|
[Versione italiana](standalone-manual-it.md)
|
||||||
|
|
||||||
This is the fresh-machine installation procedure for THothII. THothII receives a natural-language
|
This is the verification procedure for preparing THothII as a standalone application in `full`
|
||||||
question, queries an enterprise database read-only, and guides the user through SQL review. The
|
mode on macOS, Windows, and Linux.
|
||||||
core, PostgreSQL catalog, Qdrant, embedding service, and Pi run in Docker; Node.js, Python, and Pi
|
|
||||||
are not required on the host.
|
|
||||||
|
|
||||||
## Before you start: the two repositories
|
In this document, “standalone” means that the user does not need to install Node.js, Python or Pi
|
||||||
|
on the host: the application services and local semantic
|
||||||
|
services run through Docker. DWH and LLM providers remain external endpoints configured by the
|
||||||
|
installation; this is not an offline package.
|
||||||
|
|
||||||
There are two separate repositories:
|
This path uses no graphical installer, native launcher, or Docker Hub image. It starts from a Gitea
|
||||||
|
clone and uses explicit terminal commands. Publishing pre-built images is a later step.
|
||||||
|
|
||||||
1. the application repository cloned by the user:
|
## Verification matrix
|
||||||
https://git.tylconsulting.it/mptyl/ThothII.git;
|
|
||||||
2. the workspace repository supplied by the curator/installer. It is not the THothII repository
|
|
||||||
and must not be cloned inside the application directory.
|
|
||||||
|
|
||||||
The workspace repository normally contains:
|
| System | Recommended terminal | Runtime | Test architecture |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| macOS supported by the installed Docker Desktop version | Bash in Terminal | Docker Desktop | Apple Silicon (`arm64`) |
|
||||||
|
| Windows 11 | Ubuntu inside WSL2 | Docker Desktop with WSL2 integration | x64 (`amd64`) |
|
||||||
|
| Ubuntu Linux 22.04 or 24.04 | Bash | Docker Engine + Compose v2 | x64 (`amd64`) |
|
||||||
|
|
||||||
~~~
|
Intel macOS is excluded from the first verification campaign. ARM Linux may be tested when the
|
||||||
thoth-workspaces.yaml
|
machine’s Docker runtime reports `arm64`, but it is not part of the minimum matrix.
|
||||||
<workspace-id>/workspace.yaml
|
|
||||||
<workspace-id>/evidence/** # when Evidence is declared
|
|
||||||
~~~
|
|
||||||
|
|
||||||
workspace.yaml contains workspace identity, language and optional Evidence source. By design it does
|
Documentation and Mac prerequisite checks have passed. Complete fresh installations on all three
|
||||||
not contain database passwords. Database identity, transport (PostgreSQL, REST, or tunnel), user,
|
systems remain pending; this matrix describes the tests to perform, not completed certification.
|
||||||
password, token and certificates are installation-local settings stored encrypted by the Catalog.
|
|
||||||
This prevents credentials from being committed to the workspace repository.
|
|
||||||
|
|
||||||
## 0. Machine prerequisites
|
## Before you start
|
||||||
|
|
||||||
### Windows
|
You need:
|
||||||
|
|
||||||
- Windows 10/11 with Docker Desktop running and the WSL2 backend enabled.
|
- access to the THothII Gitea repository and the workspace Git repository;
|
||||||
- Ubuntu in WSL2, with Docker Desktop integration enabled for that distribution.
|
- Git;
|
||||||
- Git, Bash, curl, OpenSSL and shasum inside WSL2.
|
- Docker Desktop on macOS and Windows, or Docker Engine with the Compose v2 plugin on Linux;
|
||||||
- Do not install Node.js, Python or Pi on the host for this procedure.
|
- Bash, `curl`, OpenSSL and `shasum` (Ubuntu package: `libdigest-sha-perl`);
|
||||||
|
- enough disk space to build the images and download the embedding model;
|
||||||
|
- the DWH and LLM endpoints, plus the credentials required by the installation.
|
||||||
|
|
||||||
If WSL2 is not installed, use the company procedure or, in PowerShell:
|
On Linux, the current user must be able to run Docker. If the system requires `sudo`, add the user
|
||||||
|
to the Docker group according to local policy and open a new session before continuing.
|
||||||
|
|
||||||
~~~
|
On Windows, run every command in this guide from Ubuntu under WSL2. In Docker Desktop, enable WSL2
|
||||||
wsl --install -d Ubuntu
|
integration for that distribution. Clone the project inside the WSL2 Linux filesystem, for example
|
||||||
~~~
|
under `~/src`, rather than under `/mnt/c`: this avoids slow builds and path/line-ending issues. Pi
|
||||||
|
does not need to be installed on the host.
|
||||||
|
|
||||||
Run all commands inside Ubuntu WSL2, in a Linux directory such as $HOME/src, not under /mnt/c.
|
Check the runtime before or immediately after cloning:
|
||||||
scripts/install-tht.ps1 exists for advanced native PowerShell scenarios; use WSL2 for the
|
|
||||||
reproducible test.
|
|
||||||
|
|
||||||
### macOS
|
```sh
|
||||||
|
docker version
|
||||||
- Docker Desktop installed and running, with several GB free for images and the embedding model.
|
|
||||||
- Git, Bash, curl, OpenSSL and shasum.
|
|
||||||
- Intel and Apple Silicon Macs are supported when Docker Desktop supports the architecture
|
|
||||||
reported by the Docker server.
|
|
||||||
- Do not install Node.js, Python or Pi on the host for this procedure.
|
|
||||||
|
|
||||||
### Linux, including Omarchy
|
|
||||||
|
|
||||||
- Git, Bash, curl, OpenSSL and shasum.
|
|
||||||
- Docker Engine and the Docker Compose v2 plugin. On Omarchy, check first:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
command -v docker
|
|
||||||
docker compose version
|
docker compose version
|
||||||
docker info
|
|
||||||
~~~
|
|
||||||
|
|
||||||
If Docker is missing, install Docker and Compose using the distribution-approved package procedure,
|
|
||||||
then start the service. On an Arch-like distribution the typical route is:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
sudo pacman -S docker docker-compose
|
|
||||||
sudo systemctl enable --now docker
|
|
||||||
sudo usermod -aG docker "$USER"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
After adding the group, open a new session and repeat docker info. Node.js, Python and Pi are not
|
|
||||||
needed on the host: they are in the Docker images.
|
|
||||||
|
|
||||||
On every system run:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
bash scripts/check-standalone-prerequisites.sh
|
|
||||||
docker version --format '{{.Server.Arch}}'
|
docker version --format '{{.Server.Arch}}'
|
||||||
~~~
|
```
|
||||||
|
|
||||||
The architecture must be amd64, x86_64, arm64, or aarch64. You also need access to the
|
The last command must return `amd64`, `x86_64`, `arm64`, or `aarch64`.
|
||||||
application Gitea repository, the workspace repository URL/branch and credentials, container
|
|
||||||
reachability to DWH/LLM endpoints, and the credentials, tokens or certificates associated with
|
|
||||||
the databases.
|
|
||||||
|
|
||||||
## 1. What to clone
|
## 1. Clone a project revision
|
||||||
|
|
||||||
Clone only the application:
|
Use the project repository on Gitea:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
mkdir -p "$HOME/src"
|
mkdir -p "$HOME/src"
|
||||||
cd "$HOME/src"
|
cd "$HOME/src"
|
||||||
git clone https://git.tylconsulting.it/mptyl/ThothII.git
|
git clone https://git.tylconsulting.it/mptyl/ThothII.git
|
||||||
cd ThothII
|
cd ThothII
|
||||||
git rev-parse --short HEAD
|
git rev-parse --short HEAD
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Record the revision. tht setup --complete downloads the workspace repository into a persistent
|
For an SSH clone, when the key is already authorized on Gitea:
|
||||||
Docker volume using the URL, branch and transport supplied during setup.
|
|
||||||
|
|
||||||
## 2. Install the terminal command
|
```sh
|
||||||
|
git clone git@git.tylconsulting.it:mptyl/ThothII.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Record the hash printed by `git rev-parse` for a repeatable test. In a later campaign, use the
|
||||||
|
maintainer-approved revision/tag rather than implicitly following a mutable `main` branch.
|
||||||
|
|
||||||
|
## 2. Check prerequisites and install the operator command
|
||||||
|
|
||||||
From the clone root:
|
From the clone root:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
bash scripts/check-standalone-prerequisites.sh
|
bash scripts/check-standalone-prerequisites.sh
|
||||||
mkdir -p "$HOME/.local/bin"
|
|
||||||
THT_INSTALL_DIRECTORY="$HOME/.local/bin" bash scripts/install-tht.sh
|
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
THT_INSTALL_DIRECTORY="$HOME/.local/bin" bash scripts/install-tht.sh
|
||||||
tht version
|
tht version
|
||||||
~~~
|
```
|
||||||
|
|
||||||
tht is the only native component to install. It builds the binary with Docker and orchestrates
|
`install-tht.sh` bootstraps only the native `tht` operator command; it does not install a desktop
|
||||||
Compose; it is not a second application runtime.
|
version of THothII. It uses the repository’s Docker builder, installs the binary for the current
|
||||||
|
terminal environment, and installs it in the user directory. Persist `$HOME/.local/bin` in your
|
||||||
|
shell PATH for new terminals too. An existing `tht` in this directory will be updated.
|
||||||
|
|
||||||
## 3. Prepare a few secrets and run complete setup
|
On Windows, run these commands inside WSL2. The installed `tht` binary is the Linux binary inside
|
||||||
|
WSL2; the application runtime remains Docker Desktop. Do not use `scripts/install-tht.ps1` as the
|
||||||
|
primary path for this test.
|
||||||
|
|
||||||
The first execution creates protected placeholders under deploy/local/secrets/ and stops if a
|
## 3. Configure and start the local installation
|
||||||
required credential is missing. Fill in the requested files and rerun the same command; compatible
|
|
||||||
configuration files are reused.
|
|
||||||
|
|
||||||
~~~
|
Run the remaining blocks in one Bash session from the physical clone root (`pwd -P`).
|
||||||
tht setup --complete --profile local --shell-mode full --shell-default-locale en
|
First create two distinct catalog passwords, preserving any existing files:
|
||||||
~~~
|
|
||||||
|
|
||||||
The setup asks only for information the computer cannot know:
|
```bash
|
||||||
|
umask 077
|
||||||
|
mkdir -p deploy/local/secrets
|
||||||
|
for name in catalog-runtime-password catalog-migrator-password; do
|
||||||
|
target="deploy/local/secrets/$name"
|
||||||
|
if [ ! -e "$target" ]; then
|
||||||
|
(set -C; openssl rand -hex 32 > "$target") || exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
export THT_CATALOG_RUNTIME_PASSWORD_SOURCE="$(pwd -P)/deploy/local/secrets/catalog-runtime-password"
|
||||||
|
export THT_CATALOG_MIGRATOR_PASSWORD_SOURCE="$(pwd -P)/deploy/local/secrets/catalog-migrator-password"
|
||||||
|
```
|
||||||
|
|
||||||
| Request | What to provide |
|
Do not regenerate passwords for an initialized catalog. Configure without starting services:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tht setup --profile local --shell-mode full --shell-default-locale en --configure-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Answer the prompts as follows:
|
||||||
|
|
||||||
|
| Prompt | Value or rule |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Workspace repository | Data/configuration repository URL, not ThothII.git |
|
| Installation ID | `local`, unless one clone hosts multiple installations |
|
||||||
| Branch | normally main |
|
| Deployment profile | `local` |
|
||||||
| Access | ssh with key and known_hosts, or https with credential file and CA |
|
| DWH API endpoint | An `http(s)` URL without user, password, query, or fragment; may be empty for a smoke-only test |
|
||||||
| DWH/LLM URL | endpoint without a token in the URL |
|
| LLM API endpoint | An `http(s)` URL without credentials; may be empty for a smoke-only test |
|
||||||
| Local login | initial user and password requested by the prompt |
|
| Workspace repository URL | The workspace repository URL, not the THothII source clone |
|
||||||
|
| Workspace branch | Normally `main` |
|
||||||
|
| Workspace access | `ssh` with a deploy key, or `https` with a protected credential file |
|
||||||
|
| File paths | Accept the default paths under `deploy/local/secrets/` for the first test |
|
||||||
|
| Secret templates | Answer `yes` when protected files do not exist yet |
|
||||||
|
| Authentication | Configure the local login required by the installation; never put passwords on a command line |
|
||||||
|
|
||||||
The setup generates random Catalog passwords and writes their paths, never their values, to
|
The generated configuration is local and ignored by Git:
|
||||||
operator.env. It runs docker compose config, builds images, starts the Catalog, runs
|
|
||||||
catalog-migrate, starts the stack, and pulls the workspace repository. The pull also activates
|
|
||||||
declared Evidence; at minimum source files present in the workspace are materialized locally.
|
|
||||||
|
|
||||||
### The file the user fills in
|
```text
|
||||||
|
deploy/local/thothii-installation.yaml
|
||||||
|
deploy/local/operator.env
|
||||||
|
deploy/local/auth/
|
||||||
|
deploy/local/secrets/
|
||||||
|
```
|
||||||
|
|
||||||
The main file is:
|
Edit secrets only in protected local files; never commit them. `deploy/env/local.env.example` is a tracked reference; the
|
||||||
|
generated path `deploy/local/operator.env` is the active path for this installation.
|
||||||
|
|
||||||
~~~
|
### Complete protected files
|
||||||
deploy/local/secrets/thothii.secrets
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Add only NAME=VALUE lines needed by modelCatalog and installation adapters, such as an LLM API key
|
If setup created blank templates, enter the values with a local editor:
|
||||||
(DEEPSEEK_API_KEY, OPENAI_API_KEY, or the key declared by the catalog) and, when applicable,
|
|
||||||
THT_DWH_API_KEY. Allowed names are documented in deploy/secrets/README.md. Never put tokens in
|
|
||||||
URLs, the repository, or copied shell commands.
|
|
||||||
|
|
||||||
Two distinctions prevent common errors:
|
```sh
|
||||||
|
chmod 600 deploy/local/secrets/*
|
||||||
|
"${EDITOR:-vi}" deploy/local/secrets/thothii.secrets
|
||||||
|
```
|
||||||
|
|
||||||
- when the catalog uses pi_auth, the LLM token belongs in the Pi pi-auth.json file created by
|
The bundle must contain only `KEY=VALUE` lines for credentials actually used by `modelCatalog`. The
|
||||||
setup; {} is only a placeholder and does not enable a model;
|
allowed names and credential boundary are documented in the local file
|
||||||
- workspace database credentials (PostgreSQL password, REST API token, tunnel SSH key,
|
`deploy/secrets/README.md`. Do not put tokens in URLs, the YAML
|
||||||
known_hosts, CA) do not belong in the workspace repository. Enter them per workspace in
|
descriptor, the Git repository, or commands copied into the shell.
|
||||||
Database Management, which stores them encrypted in the Catalog. The workspace declares
|
|
||||||
database/schema and transport; the installer must obtain the actual values from the database owner.
|
|
||||||
|
|
||||||
A private workspace repository also needs the Git files required by its transport: an SSH key and
|
For SSH workspace access, also provide the private key and `known_hosts` file requested by setup.
|
||||||
known_hosts, or an HTTPS credential file and CA. These are transport files, not a second bundle to
|
For HTTPS access, provide the Git credential file and any required CA. Both must remain protected
|
||||||
commit. To minimize manual files, use SSH with an already-authorized deploy key.
|
and outside version control.
|
||||||
|
|
||||||
## 4. Automatic checks and terminal tests
|
Before starting, complete these additional configuration steps:
|
||||||
|
|
||||||
Setup verifies files, permissions, descriptor, Compose, Docker, authentication, services, Pi and
|
1. Add `THT_CATALOG_RUNTIME_PASSWORD_SOURCE` and `THT_CATALOG_MIGRATOR_PASSWORD_SOURCE` to
|
||||||
the workspace. After startup, run these commands at any time:
|
`deploy/local/operator.env`, with the same absolute paths exported above. Setup does not persist
|
||||||
|
these two variables. Store paths, not passwords.
|
||||||
|
2. Replace the descriptor's generic `modelCatalog` with the approved provider/model configuration.
|
||||||
|
The generated defaults do not replicate the existing Mac. See [Pi/model configuration](../general/pi-configuration.md)
|
||||||
|
and the local example `deploy/psd/thothii-installation.yaml.example`.
|
||||||
|
3. Populate the keys referenced by `authentication.apiKeyEnv` in `thothii.secrets`. Providers using
|
||||||
|
`pi_auth` need valid credentials at `PI_AUTH_FILE`; the `{}` template is not authentication.
|
||||||
|
4. Complete the workspace Git files. SSH requires an authorized deploy key and verified known-hosts;
|
||||||
|
HTTPS requires the credential file and CA bundle expected by the overlay. Blank templates cannot
|
||||||
|
provide repository access.
|
||||||
|
|
||||||
~~~
|
After editing generated configuration, do not rerun setup: it rejects different existing content.
|
||||||
INSTALLATION="$PWD/deploy/local/thothii-installation.yaml"
|
Generate the projections and run the explicit migration below. Use `THT_GIT_ACCESS=https` if that
|
||||||
tht --installation "$INSTALLATION" doctor --json
|
was selected during setup. This block targets the fresh `local` descriptor with only the Git overlay;
|
||||||
tht --installation "$INSTALLATION" workspace pull --json
|
custom installations must include their extra descriptor overlays in the same order.
|
||||||
tht --installation "$INSTALLATION" workspace test --json
|
|
||||||
~~~
|
|
||||||
|
|
||||||
workspace test checks, for every active workspace, database binding and credentials, Evidence,
|
```bash
|
||||||
Qdrant, and the embedding service. It exits non-zero when the database binding is missing or a
|
INSTALLATION="$(pwd -P)/deploy/local/thothii-installation.yaml"
|
||||||
connection is unusable. Before running it, the installer must configure the database in Database
|
tht --installation "$INSTALLATION" installation generate
|
||||||
Management: the workspace repository cannot contain the password by itself.
|
THT_PROJECT="thothii-$(printf '%s' "$INSTALLATION" | shasum -a 256 | cut -c 1-12)"
|
||||||
|
THT_GIT_ACCESS=ssh
|
||||||
|
compose=(
|
||||||
|
docker compose --project-name "$THT_PROJECT" --project-directory "$(pwd -P)"
|
||||||
|
--env-file "$(pwd -P)/deploy/local/operator.env"
|
||||||
|
-f compose.yaml -f deploy/compose.local.yaml
|
||||||
|
-f "deploy/compose.git-$THT_GIT_ACCESS.yaml"
|
||||||
|
-f deploy/local/generated/compose.models.yaml
|
||||||
|
)
|
||||||
|
"${compose[@]}" config --quiet
|
||||||
|
"${compose[@]}" build core frontend
|
||||||
|
"${compose[@]}" up -d catalog-db
|
||||||
|
"${compose[@]}" run --rm catalog-migrate
|
||||||
|
tht --installation "$INSTALLATION" start
|
||||||
|
```
|
||||||
|
|
||||||
doctor --json is the repeatable, non-destructive core verification. The final functional test must
|
Stop if a command fails. The project name matches the hash used by `tht`, preserving volume
|
||||||
also open http://127.0.0.1:8080, sign in, and complete a real question through final SQL.
|
identity. `catalog-migrate` applies Catalog and Memory migrations; `tht start` does not run it
|
||||||
|
automatically. Initial embedding-model download may take time. Use this installation-specific
|
||||||
|
sequence, not `run-stack.sh` with a different environment/project name.
|
||||||
|
|
||||||
## Activities only the installer can complete
|
## 4. Verify the installation
|
||||||
|
|
||||||
The procedure automates bootstrap, but it cannot invent enterprise decisions or authorizations.
|
The descriptor generated for the default ID is:
|
||||||
The installer must complete and record:
|
|
||||||
|
|
||||||
1. usable LLMs, the modelCatalog, and linked API keys; then run tht pi test and tht doctor;
|
```sh
|
||||||
2. database configuration, connection test, schema synchronization, and description generation;
|
INSTALLATION="$(pwd -P)/deploy/local/thothii-installation.yaml"
|
||||||
3. human consolidation of generated descriptions;
|
test -f "$INSTALLATION"
|
||||||
4. Qdrant semantic entries through workspace preprocess run;
|
bash scripts/verify-standalone-install.sh "$INSTALLATION"
|
||||||
5. naming-based FK suggestions as a complement to schema FKs, human review, and loading approved
|
```
|
||||||
relationships into Qdrant;
|
|
||||||
6. recurring tht doctor --json and tht workspace test --json checks;
|
|
||||||
7. one real question completed successfully without connection or model errors.
|
|
||||||
|
|
||||||
Configuration is complete only when all applicable activities are done, decisions are recorded, and
|
The verifier is read-only: it runs `tht doctor --json` and `tht status` without restarting the
|
||||||
the two terminal tests are green. The core is usable only after the real question, not merely
|
stack, regenerating configuration, or printing secret contents.
|
||||||
because the frontend answers /health.
|
|
||||||
|
|
||||||
## Gate A and Gate B
|
### Gate A — platform smoke test on all three computers
|
||||||
|
|
||||||
### Gate A — platform
|
Record the following for each machine:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
uname -a
|
uname -a
|
||||||
docker version --format '{{.Server.Version}} {{.Server.Arch}}'
|
docker version --format '{{.Server.Version}} {{.Server.Arch}}'
|
||||||
tht version
|
tht version
|
||||||
bash scripts/check-standalone-prerequisites.sh
|
bash scripts/check-standalone-prerequisites.sh
|
||||||
bash scripts/verify-standalone-install.sh "$INSTALLATION"
|
bash scripts/verify-standalone-install.sh "$INSTALLATION"
|
||||||
~~~
|
```
|
||||||
|
|
||||||
### Gate B — usability
|
The gate passes when the clone is intact, Docker and Compose are reachable, `tht doctor` is OK, the
|
||||||
|
stack is running, and the frontend responds at the default local URL `http://127.0.0.1:8080`.
|
||||||
|
Doctor also checks workspace and Pi: record their failures separately rather than labeling every
|
||||||
|
failure as a platform problem. Check HTTP readiness with:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
tht --installation "$INSTALLATION" doctor --json
|
|
||||||
tht --installation "$INSTALLATION" workspace test --json
|
|
||||||
curl --fail --silent --show-error http://127.0.0.1:8080/health
|
curl --fail --silent --show-error http://127.0.0.1:8080/health
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Then run a real question and stop/restart with tht stop and tht start. Do not use docker compose
|
### Gate B — functional verification
|
||||||
down --volumes: it deletes the Catalog, sessions, Qdrant data and the embedding model.
|
|
||||||
|
Run this on at least one machine with available endpoints and credentials:
|
||||||
|
|
||||||
|
First follow [Workspace operations](../operations/workspaces.md) to import/prepare the workspace
|
||||||
|
and configure the Database and local binding. The source clone does not transfer catalog data,
|
||||||
|
secrets or sessions from the Mac. Connect any VPN required by DWH/model endpoints and verify
|
||||||
|
that their names are reachable from containers too.
|
||||||
|
|
||||||
|
1. open `http://127.0.0.1:8080`;
|
||||||
|
2. sign in with the configured local account;
|
||||||
|
3. verify that the configured workspace is readable;
|
||||||
|
4. start a real question and complete the review gates through final SQL;
|
||||||
|
5. stop and restart the installation, then run `verify-standalone-install.sh` again.
|
||||||
|
|
||||||
|
A Gate B failure involving DWH, the LLM provider, workspace Git, or credentials does not by itself
|
||||||
|
prove a Docker portability problem: record the failed endpoint or component separately.
|
||||||
|
|
||||||
|
## Daily lifecycle
|
||||||
|
|
||||||
|
Use the explicit descriptor when more than one installation may be discoverable:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
INSTALLATION="$PWD/deploy/local/thothii-installation.yaml"
|
||||||
|
|
||||||
|
tht --installation "$INSTALLATION" status
|
||||||
|
tht --installation "$INSTALLATION" start
|
||||||
|
tht --installation "$INSTALLATION" start --build
|
||||||
|
tht --installation "$INSTALLATION" logs
|
||||||
|
tht --installation "$INSTALLATION" doctor --json
|
||||||
|
tht --installation "$INSTALLATION" stop
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `start --build` after source changes or to rebuild images from the current checkout. `stop`
|
||||||
|
preserves volumes, sessions, the catalog, Pi state, Qdrant data, and the embedding model. Do not
|
||||||
|
use `docker compose down --volumes` during a normal test: it is destructive and removes local data.
|
||||||
|
For upgrades requiring migrations, follow the release runbook before starting the new application.
|
||||||
|
|
||||||
## Quick diagnosis
|
## Quick diagnosis
|
||||||
|
|
||||||
| Symptom | Action |
|
| Symptom | Check |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Docker Engine is not reachable | start Docker Desktop or systemctl and repeat docker info |
|
| `Docker Engine is not reachable` | start Docker Desktop or the Docker service and rerun `docker info` |
|
||||||
| Omarchy cannot find docker | install Docker/Compose, enable the service and open a new session |
|
| Windows sees Docker but Bash fails | run the guide inside Ubuntu WSL2 and enable that distribution in Docker Desktop |
|
||||||
| Windows sees Docker but Bash fails | use Ubuntu WSL2 and enable its Docker Desktop integration |
|
| `tht: command not found` | open a new shell and check `command -v tht`; rerun the bootstrap if needed |
|
||||||
| workspace pull fails | check URL, branch, key/credential file and known_hosts from the container |
|
| line-ending or executable-script errors | use a clone in the WSL2/Linux filesystem and rerun `bash scripts/...` |
|
||||||
| workspace test reports a missing binding | configure database, token/password and CA in Database Management |
|
| unsupported architecture | check `docker version --format '{{.Server.Arch}}'`; the test requires `amd64` or `arm64` |
|
||||||
| Pi is not ready | fill pi-auth.json or the key declared by modelCatalog, then run tht pi test |
|
| missing descriptor or env file | use `deploy/local/...` generated by `tht setup`, not an arbitrary copied file |
|
||||||
|
| healthy stack but workflow failure | check external URLs, the credential bundle, workspace Git, and authentication separately |
|
||||||
|
| data appears missing | check that `down --volumes` was not used; `stop` does not remove volumes |
|
||||||
|
|
||||||
|
## Acceptance checklist
|
||||||
|
|
||||||
|
- [ ] The clone comes from the expected Gitea repository and the revision is recorded.
|
||||||
|
- [ ] Docker Desktop/Engine and Compose v2 are available.
|
||||||
|
- [ ] The runtime reports an allowed architecture.
|
||||||
|
- [ ] `tht` was built from the repository and responds to `tht version`.
|
||||||
|
- [ ] Setup uses `profile: local`, `shell.mode: full`, and `shell.defaultLocale: en`.
|
||||||
|
- [ ] The descriptor, `operator.env`, authentication, and secrets exist only under `deploy/local/`.
|
||||||
|
- [ ] No secret appears in Git, URLs, public YAML, or recorded commands.
|
||||||
|
- [ ] Gate A passes on Apple Silicon macOS, x64 Windows WSL2, and x64 Linux.
|
||||||
|
- [ ] Gate B runs on at least one machine with DWH and LLM available.
|
||||||
|
- [ ] Stop/start and final verification complete without deleting volumes.
|
||||||
|
|
||||||
|
## Out of scope for this release
|
||||||
|
|
||||||
|
The following remain future work:
|
||||||
|
|
||||||
|
- publishing pre-built images on Docker Hub;
|
||||||
|
- reducing prompts through a dedicated non-interactive configuration;
|
||||||
|
- creating DMG, MSI/EXE, AppImage, or other native installers;
|
||||||
|
- providing an offline runtime or bundling a local DWH/LLM into the application.
|
||||||
|
|
||||||
## Related documents
|
## Related documents
|
||||||
|
|
||||||
- [Install and first start](first-start.md)
|
- [Install and first start](first-start.md)
|
||||||
|
- [Shell and localization](shell-and-language.md)
|
||||||
- [Workspace operations](../operations/workspaces.md)
|
- [Workspace operations](../operations/workspaces.md)
|
||||||
- [Database Management](../operations/database-management.md)
|
- `deploy/secrets/README.md` (runtime secrets)
|
||||||
- [Model configuration](../general/pi-configuration.md)
|
|
||||||
- deploy/secrets/README.md
|
|
||||||
|
|
||||||
Publishing images on Docker Hub and native DMG/MSI/AppImage installers remain later work: this
|
|
||||||
procedure starts from the Gitea clone and does not require pre-published Docker Hub images.
|
|
||||||
|
|||||||
@@ -1,262 +1,329 @@
|
|||||||
# Installazione standalone guidata
|
# Installazione manuale standalone
|
||||||
|
|
||||||
[English version](standalone-manual-en.md)
|
[English version](standalone-manual-en.md)
|
||||||
|
|
||||||
Questa è la procedura per installare THothII da zero. THothII riceve una domanda in linguaggio
|
Questa è la procedura di prova per predisporre THothII come applicazione autonoma in modalità
|
||||||
naturale, interroga in sola lettura un database aziendale e accompagna l’utente nella revisione
|
`full` su macOS, Windows e Linux.
|
||||||
della SQL risultante. Il core, il catalogo PostgreSQL, Qdrant, il servizio di embedding e Pi vengono
|
|
||||||
eseguiti in Docker; sul computer non servono Node.js, Python o Pi.
|
|
||||||
|
|
||||||
## Prima di iniziare: i due repository
|
In questo documento “autonoma” significa che l’utente non deve installare Node.js, Python o Pi
|
||||||
|
sull'host: i servizi applicativi e i servizi semantici
|
||||||
|
locali vengono eseguiti con Docker. DWH e provider LLM restano endpoint esterni configurati
|
||||||
|
dall’installazione; questa procedura non è un pacchetto offline.
|
||||||
|
|
||||||
Servono due repository distinti:
|
Il percorso non usa installer grafici, launcher nativi o immagini Docker Hub. Si parte da un clone
|
||||||
|
Gitea e si usano comandi espliciti da terminale. La pubblicazione di immagini pre-costruite è una
|
||||||
|
fase successiva.
|
||||||
|
|
||||||
1. il repository dell’applicazione, che l’utente clona:
|
## Matrice di verifica
|
||||||
https://git.tylconsulting.it/mptyl/ThothII.git;
|
|
||||||
2. il repository dei workspace, indicato dal curatore/installatore. Non è il repository di
|
|
||||||
THothII e non va clonato manualmente nella directory dell’applicazione.
|
|
||||||
|
|
||||||
Il repository workspace contiene il catalogo e una directory per ogni workspace, normalmente:
|
| Sistema | Terminale raccomandato | Runtime | Architettura della prova |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| macOS supportato dalla versione Docker Desktop installata | Bash nel Terminale | Docker Desktop | Apple Silicon (`arm64`) |
|
||||||
|
| Windows 11 | Ubuntu dentro WSL2 | Docker Desktop con integrazione WSL2 | x64 (`amd64`) |
|
||||||
|
| Linux Ubuntu 22.04 o 24.04 | Bash | Docker Engine + Compose v2 | x64 (`amd64`) |
|
||||||
|
|
||||||
~~~
|
Intel macOS non fa parte della prima campagna di verifica. ARM Linux può essere provato quando il
|
||||||
thoth-workspaces.yaml
|
runtime Docker della macchina restituisce `arm64`, ma non è un requisito della matrice minima.
|
||||||
<workspace-id>/workspace.yaml
|
|
||||||
<workspace-id>/evidence/** # se il workspace dichiara Evidence
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Il file workspace.yaml descrive identità, lingua e, opzionalmente, la sorgente Evidence. Per scelta
|
Le verifiche documentali e dei prerequisiti Mac sono passate. Le installazioni complete da zero
|
||||||
architetturale non contiene password del database. L’identità del database, il trasporto
|
sui tre sistemi restano da eseguire: la matrice indica le prove previste, non una certificazione.
|
||||||
(PostgreSQL, REST o tunnel), username, password, token e certificati sono configurazione locale
|
|
||||||
dell’installazione, conservata cifrata dal Catalog. Questo evita di committare credenziali nel
|
|
||||||
repository workspace.
|
|
||||||
|
|
||||||
## 0. Prerequisiti della macchina
|
## Cosa serve prima di iniziare
|
||||||
|
|
||||||
### Windows
|
Servono:
|
||||||
|
|
||||||
- Windows 10/11 con Docker Desktop avviato e backend WSL2 abilitato.
|
- accesso al repository Gitea di THothII e al repository Git dei workspace;
|
||||||
- Ubuntu in WSL2, con integrazione Docker Desktop abilitata per quella distribuzione.
|
- Git;
|
||||||
- Git, Bash, curl, OpenSSL e shasum nella distribuzione WSL2.
|
- Docker Desktop su macOS e Windows, oppure Docker Engine con il plugin Compose v2 su Linux;
|
||||||
- Non installare Node.js, Python o Pi sull’host per questa procedura.
|
- Bash, `curl`, OpenSSL e `shasum` (su Ubuntu, pacchetto `libdigest-sha-perl`);
|
||||||
|
- spazio disco sufficiente per compilare le immagini e scaricare il modello di embedding;
|
||||||
|
- gli endpoint DWH e LLM, più le credenziali che l’installazione deve usare.
|
||||||
|
|
||||||
In PowerShell, se WSL2 non esiste ancora, usare la procedura aziendale oppure:
|
Su Linux l’utente corrente deve poter eseguire Docker. Se il sistema richiede `sudo`, aggiungere
|
||||||
|
l’utente al gruppo Docker secondo la policy locale e aprire una nuova sessione prima di continuare.
|
||||||
|
|
||||||
~~~
|
Su Windows usare Ubuntu in WSL2 per tutti i comandi di questa guida. In Docker Desktop attivare
|
||||||
wsl --install -d Ubuntu
|
l’integrazione WSL2 per quella distribuzione. Clonare il progetto nel filesystem Linux di WSL2,
|
||||||
~~~
|
per esempio sotto `~/src`, e non sotto `/mnt/c`: si evitano rallentamenti e problemi di permessi o
|
||||||
|
line ending. Non è necessario installare Pi sull’host.
|
||||||
|
|
||||||
Eseguire poi tutti i comandi dentro Ubuntu WSL2, in una directory Linux come $HOME/src, non sotto
|
Verificare il runtime prima del clone o subito dopo:
|
||||||
/mnt/c. Il percorso nativo scripts/install-tht.ps1 esiste per scenari PowerShell avanzati; per la
|
|
||||||
prova riproducibile usare WSL2.
|
|
||||||
|
|
||||||
### macOS
|
```sh
|
||||||
|
docker version
|
||||||
- Docker Desktop installato, avviato e con alcuni GB liberi per immagini e modello di embedding.
|
|
||||||
- Git, Bash, curl, OpenSSL e shasum.
|
|
||||||
- Sono supportati Mac Intel e Apple Silicon se Docker Desktop supporta l’architettura restituita
|
|
||||||
dal Docker server.
|
|
||||||
- Non installare Node.js, Python o Pi sull’host per questa procedura.
|
|
||||||
|
|
||||||
### Linux, incluso Omarchy
|
|
||||||
|
|
||||||
- Git, Bash, curl, OpenSSL e shasum.
|
|
||||||
- Docker Engine e il plugin Docker Compose v2. Su Omarchy verificare prima:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
command -v docker
|
|
||||||
docker compose version
|
docker compose version
|
||||||
docker info
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Se Docker manca, installare Docker e Compose con il gestore pacchetti/procedura approvata dalla
|
|
||||||
distribuzione, poi avviare il servizio. Su una distribuzione Arch-like il percorso tipico è:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
sudo pacman -S docker docker-compose
|
|
||||||
sudo systemctl enable --now docker
|
|
||||||
sudo usermod -aG docker "$USER"
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Dopo l’aggiunta al gruppo aprire una nuova sessione e ripetere docker info. Non installare Node.js,
|
|
||||||
Python o Pi sull’host: sono dentro le immagini Docker.
|
|
||||||
|
|
||||||
Su tutti i sistemi il controllo finale è:
|
|
||||||
|
|
||||||
~~~
|
|
||||||
bash scripts/check-standalone-prerequisites.sh
|
|
||||||
docker version --format '{{.Server.Arch}}'
|
docker version --format '{{.Server.Arch}}'
|
||||||
~~~
|
```
|
||||||
|
|
||||||
L’architettura deve essere amd64, x86_64, arm64 o aarch64. Servono inoltre accesso al repository
|
L’ultima istruzione deve restituire `amd64`, `x86_64`, `arm64` o `aarch64`.
|
||||||
Gitea dell’applicazione, URL/branch e credenziali del repository workspace, raggiungibilità dal
|
|
||||||
container degli endpoint DWH/LLM e le credenziali, token o certificati associati ai database.
|
|
||||||
|
|
||||||
## 1. Cosa clonare
|
## 1. Clonare una revisione del progetto
|
||||||
|
|
||||||
Clonare solo l’applicazione:
|
Usare il repository di progetto su Gitea:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
mkdir -p "$HOME/src"
|
mkdir -p "$HOME/src"
|
||||||
cd "$HOME/src"
|
cd "$HOME/src"
|
||||||
git clone https://git.tylconsulting.it/mptyl/ThothII.git
|
git clone https://git.tylconsulting.it/mptyl/ThothII.git
|
||||||
cd ThothII
|
cd ThothII
|
||||||
git rev-parse --short HEAD
|
git rev-parse --short HEAD
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Annotare la revisione. Il repository workspace verrà scaricato da tht setup --complete dentro un
|
Per un clone SSH usare, se la chiave è già autorizzata su Gitea:
|
||||||
volume Docker persistente, usando URL, branch e trasporto indicati durante il setup.
|
|
||||||
|
|
||||||
## 2. Installare il comando terminale
|
```sh
|
||||||
|
git clone git@git.tylconsulting.it:mptyl/ThothII.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Per una prova ripetibile annotare l’hash stampato da `git rev-parse`. In una campagna successiva
|
||||||
|
usare la revisione/tag approvata dal maintainer invece di seguire implicitamente una `main` che
|
||||||
|
può cambiare.
|
||||||
|
|
||||||
|
## 2. Verificare i prerequisiti e installare il comando operatore
|
||||||
|
|
||||||
Dal root del clone:
|
Dal root del clone:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
bash scripts/check-standalone-prerequisites.sh
|
bash scripts/check-standalone-prerequisites.sh
|
||||||
mkdir -p "$HOME/.local/bin"
|
|
||||||
THT_INSTALL_DIRECTORY="$HOME/.local/bin" bash scripts/install-tht.sh
|
|
||||||
export PATH="$HOME/.local/bin:$PATH"
|
export PATH="$HOME/.local/bin:$PATH"
|
||||||
|
THT_INSTALL_DIRECTORY="$HOME/.local/bin" bash scripts/install-tht.sh
|
||||||
tht version
|
tht version
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Il comando tht è l’unico componente nativo da installare. Costruisce il binario con Docker e
|
`install-tht.sh` è un bootstrap del solo comando operatore nativo `tht`; non installa una versione
|
||||||
orchestra Compose; non è un secondo runtime dell’applicazione.
|
desktop di THothII. Usa il builder Docker del repository, installa il binario adatto all’ambiente
|
||||||
|
del terminale e lo installa nella directory utente. Aggiungere `$HOME/.local/bin` al PATH della
|
||||||
|
shell anche per i terminali successivi. Un `tht` già presente in quella directory viene aggiornato.
|
||||||
|
|
||||||
## 3. Preparare pochi segreti e avviare il setup completo
|
Su Windows, eseguire questi comandi dentro WSL2. Il binario `tht` installato è quello Linux di WSL2;
|
||||||
|
il runtime dell’applicazione rimane Docker Desktop. Non usare `scripts/install-tht.ps1` come percorso
|
||||||
|
principale di questa prova.
|
||||||
|
|
||||||
La prima esecuzione crea i placeholder protetti sotto deploy/local/secrets/ e si ferma se manca
|
## 3. Configurare e avviare l’installazione locale
|
||||||
una credenziale necessaria. Compilare i file indicati e rilanciare lo stesso comando: i file di
|
|
||||||
configurazione già compatibili vengono riutilizzati.
|
|
||||||
|
|
||||||
~~~
|
Eseguire i blocchi successivi nella stessa sessione Bash dal root fisico del clone (`pwd -P`).
|
||||||
tht setup --complete --profile local --shell-mode full --shell-default-locale en
|
Creare prima le due password distinte del catalogo, conservando eventuali file già esistenti:
|
||||||
~~~
|
|
||||||
|
|
||||||
Durante il setup servono solo le informazioni operative che il computer non può conoscere:
|
```bash
|
||||||
|
umask 077
|
||||||
|
mkdir -p deploy/local/secrets
|
||||||
|
for name in catalog-runtime-password catalog-migrator-password; do
|
||||||
|
target="deploy/local/secrets/$name"
|
||||||
|
if [ ! -e "$target" ]; then
|
||||||
|
(set -C; openssl rand -hex 32 > "$target") || exit 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
export THT_CATALOG_RUNTIME_PASSWORD_SOURCE="$(pwd -P)/deploy/local/secrets/catalog-runtime-password"
|
||||||
|
export THT_CATALOG_MIGRATOR_PASSWORD_SOURCE="$(pwd -P)/deploy/local/secrets/catalog-migrator-password"
|
||||||
|
```
|
||||||
|
|
||||||
| Richiesta | Cosa inserire |
|
Non rigenerare le password di un catalogo già inizializzato. Configurare senza avviare i servizi:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
tht setup --profile local --shell-mode full --shell-default-locale en --configure-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Rispondere ai prompt nel seguente modo:
|
||||||
|
|
||||||
|
| Prompt | Valore o regola |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Repository workspace | URL del repository dati/configurazione, non ThothII.git |
|
| Installation ID | `local`, salvo necessità di più installazioni nello stesso clone |
|
||||||
| Branch | normalmente main |
|
| Deployment profile | `local` |
|
||||||
| Accesso | ssh con chiave e known_hosts, oppure https con credential file e CA |
|
| DWH API endpoint | URL `http(s)` senza user, password, query o fragment; può restare vuoto per il solo smoke test |
|
||||||
| DWH/LLM URL | endpoint senza token nella URL |
|
| LLM API endpoint | URL `http(s)` senza credenziali; può restare vuoto per il solo smoke test |
|
||||||
| Login locale | utente e password iniziale richiesti dal prompt |
|
| Workspace repository URL | URL del repository dei workspace, non il clone sorgente di THothII |
|
||||||
|
| Workspace branch | normalmente `main` |
|
||||||
|
| Workspace access | `ssh` se si usa una chiave deploy; altrimenti `https` con credential file protetto |
|
||||||
|
| Percorsi dei file | accettare i percorsi predefiniti sotto `deploy/local/secrets/` nella prima prova |
|
||||||
|
| Secret templates | rispondere `yes` quando i file protetti non esistono ancora |
|
||||||
|
| Autenticazione | configurare il login locale richiesto dall’installazione; non inserire password in una riga di comando |
|
||||||
|
|
||||||
Il setup crea automaticamente le password casuali del Catalog e le scrive in operator.env come
|
La configurazione generata è locale e ignorata da Git:
|
||||||
percorsi, non come valori. Esegue docker compose config, costruisce le immagini, avvia il Catalog,
|
|
||||||
esegue catalog-migrate, avvia lo stack e importa il repository workspace. L’import attiva anche
|
|
||||||
l’Evidence dichiarata: almeno i file source presenti nel workspace vengono materializzati nel
|
|
||||||
registro locale.
|
|
||||||
|
|
||||||
### Il file da compilare
|
```text
|
||||||
|
deploy/local/thothii-installation.yaml
|
||||||
|
deploy/local/operator.env
|
||||||
|
deploy/local/auth/
|
||||||
|
deploy/local/secrets/
|
||||||
|
```
|
||||||
|
|
||||||
Il file principale è:
|
Modificare i segreti solo nei file locali protetti; non committarli. Il file `deploy/env/local.env.example` è un riferimento
|
||||||
|
tracciato; il percorso generato da `tht setup`, `deploy/local/operator.env`, è quello da usare per
|
||||||
|
questa installazione.
|
||||||
|
|
||||||
~~~
|
### Completare i file protetti
|
||||||
deploy/local/secrets/thothii.secrets
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Inserire solo righe NOME=VALORE necessarie al modelCatalog e agli adapter, per esempio una API key
|
Se il setup ha creato template vuoti, inserire i valori con un editor locale:
|
||||||
LLM (DEEPSEEK_API_KEY, OPENAI_API_KEY o quella dichiarata dal catalogo) ed eventualmente
|
|
||||||
THT_DWH_API_KEY. I nomi ammessi sono documentati in deploy/secrets/README.md. Non mettere token
|
|
||||||
nelle URL, nel repository o nei comandi.
|
|
||||||
|
|
||||||
Due precisazioni evitano gli errori più comuni:
|
```sh
|
||||||
|
chmod 600 deploy/local/secrets/*
|
||||||
|
"${EDITOR:-vi}" deploy/local/secrets/thothii.secrets
|
||||||
|
```
|
||||||
|
|
||||||
- se il catalogo usa pi_auth, il token LLM va nel file Pi pi-auth.json creato dal setup; {} è solo
|
Il bundle deve contenere solo righe `KEY=VALUE` per le credenziali effettivamente usate dal
|
||||||
un placeholder e non abilita alcun modello;
|
`modelCatalog`. I nomi ammessi e il confine delle credenziali sono descritti nel file locale
|
||||||
- le credenziali specifiche di un database workspace (password PostgreSQL, API token REST, chiave
|
`deploy/secrets/README.md`. Non mettere token nelle URL, nel
|
||||||
SSH del tunnel, known_hosts, CA) non vanno nel repository workspace: si inseriscono per workspace
|
descriptor YAML, nel repository Git o nei comandi copiati nella shell.
|
||||||
in Database Management, che le conserva nel Catalog cifrato. Il workspace indica database/schema
|
|
||||||
e trasporto; l’installatore deve ottenere dal proprietario il valore corretto.
|
|
||||||
|
|
||||||
Per un repository workspace privato sono inoltre indispensabili i file Git richiesti dal trasporto:
|
Per accesso workspace SSH, predisporre anche la chiave privata e il file `known_hosts` indicati dal
|
||||||
una chiave SSH e known_hosts, oppure credential file HTTPS e CA. Sono file di trasporto, non un
|
setup. Per accesso HTTPS, predisporre il credential file Git e l’eventuale CA. Entrambi devono
|
||||||
secondo bundle da committare. Per ridurre i file da compilare, usare SSH con una deploy key già
|
restare protetti e fuori dal controllo versione.
|
||||||
autorizzata.
|
|
||||||
|
|
||||||
## 4. Controlli automatici e test da terminale
|
Prima dell'avvio completare anche questi passaggi:
|
||||||
|
|
||||||
Il setup verifica file, permessi, descriptor, Compose, Docker, autenticazione, servizi, Pi e
|
1. Aggiungere `THT_CATALOG_RUNTIME_PASSWORD_SOURCE` e `THT_CATALOG_MIGRATOR_PASSWORD_SOURCE` a
|
||||||
workspace. Dopo l’avvio usare questi comandi in qualunque momento:
|
`deploy/local/operator.env`, con gli stessi percorsi assoluti esportati sopra. Il setup non salva
|
||||||
|
queste due variabili. Inserire i percorsi, non le password.
|
||||||
|
2. Sostituire il `modelCatalog` generico nel descriptor con la configurazione provider/modelli
|
||||||
|
approvata. I default generati non replicano il Mac esistente. Vedere [configurazione Pi/modelli](../general/pi-configuration.md)
|
||||||
|
e l'esempio locale `deploy/psd/thothii-installation.yaml.example`.
|
||||||
|
3. Inserire in `thothii.secrets` le chiavi referenziate da `authentication.apiKeyEnv`. I provider
|
||||||
|
`pi_auth` richiedono credenziali valide nel file `PI_AUTH_FILE`; il template `{}` non autentica.
|
||||||
|
4. Completare i file Git del workspace. SSH richiede una chiave deploy autorizzata e known-hosts
|
||||||
|
verificato; HTTPS richiede il credential file e il bundle CA previsti dall'overlay. I template
|
||||||
|
vuoti non consentono l'accesso al repository.
|
||||||
|
|
||||||
~~~
|
Dopo aver modificato la configurazione generata, non rilanciare setup: rifiuta file esistenti con
|
||||||
INSTALLATION="$PWD/deploy/local/thothii-installation.yaml"
|
contenuti diversi. Generare le proiezioni ed eseguire la migrazione esplicita indicata sotto.
|
||||||
tht --installation "$INSTALLATION" doctor --json
|
Impostare `THT_GIT_ACCESS=https` se scelto nel setup. Il blocco usa il nuovo descriptor `local`
|
||||||
tht --installation "$INSTALLATION" workspace pull --json
|
con il solo overlay Git; per installazioni personalizzate includere gli overlay aggiuntivi
|
||||||
tht --installation "$INSTALLATION" workspace test --json
|
nello stesso ordine del descriptor.
|
||||||
~~~
|
|
||||||
|
|
||||||
workspace test prova, per ogni workspace attivo, il binding del database e le credenziali, Evidence,
|
```bash
|
||||||
Qdrant e il servizio embedding. Restituisce exit code diverso da zero se manca il binding del
|
INSTALLATION="$(pwd -P)/deploy/local/thothii-installation.yaml"
|
||||||
database o una connessione non è utilizzabile. Prima di eseguirlo l’installatore deve aver
|
tht --installation "$INSTALLATION" installation generate
|
||||||
configurato il database in Database Management: il workspace repository da solo non può contenere
|
THT_PROJECT="thothii-$(printf '%s' "$INSTALLATION" | shasum -a 256 | cut -c 1-12)"
|
||||||
la password.
|
THT_GIT_ACCESS=ssh
|
||||||
|
compose=(
|
||||||
|
docker compose --project-name "$THT_PROJECT" --project-directory "$(pwd -P)"
|
||||||
|
--env-file "$(pwd -P)/deploy/local/operator.env"
|
||||||
|
-f compose.yaml -f deploy/compose.local.yaml
|
||||||
|
-f "deploy/compose.git-$THT_GIT_ACCESS.yaml"
|
||||||
|
-f deploy/local/generated/compose.models.yaml
|
||||||
|
)
|
||||||
|
"${compose[@]}" config --quiet
|
||||||
|
"${compose[@]}" build core frontend
|
||||||
|
"${compose[@]}" up -d catalog-db
|
||||||
|
"${compose[@]}" run --rm catalog-migrate
|
||||||
|
tht --installation "$INSTALLATION" start
|
||||||
|
```
|
||||||
|
|
||||||
Per una verifica generale del core, doctor --json è il test ripetibile e non distruttivo. Il test
|
Fermarsi se un comando fallisce. Il nome progetto coincide con l'hash usato da `tht`, preservando
|
||||||
funzionale finale deve inoltre aprire http://127.0.0.1:8080, autenticarsi e completare una domanda
|
l'identità dei volumi. `catalog-migrate` applica le migrazioni Catalog e Memory; `tht start` non
|
||||||
reale fino alla SQL finale.
|
lo esegue automaticamente. Il primo download del modello embedding può richiedere tempo.
|
||||||
|
Usare questa sequenza legata all'installazione, non `run-stack.sh` con env/progetto diversi.
|
||||||
|
|
||||||
## Attività che può svolgere solo l’installatore
|
## 4. Verificare l’installazione
|
||||||
|
|
||||||
La procedura automatizza il bootstrap, non può inventare decisioni o autorizzazioni aziendali.
|
Il descriptor generato per l’ID predefinito è:
|
||||||
L’installatore deve completare e registrare:
|
|
||||||
|
|
||||||
1. quali LLM sono utilizzabili, il relativo modelCatalog e le API key collegate; poi eseguire
|
```sh
|
||||||
tht pi test e tht doctor;
|
INSTALLATION="$(pwd -P)/deploy/local/thothii-installation.yaml"
|
||||||
2. per ogni database: configurazione, test connessione, sincronizzazione dello schema e
|
test -f "$INSTALLATION"
|
||||||
generazione delle descrizioni;
|
bash scripts/verify-standalone-install.sh "$INSTALLATION"
|
||||||
3. consolidamento umano delle descrizioni generate;
|
```
|
||||||
4. generazione delle entry semantiche in Qdrant tramite workspace preprocess run;
|
|
||||||
5. generazione delle FK suggerite dal naming, come complemento alle FK lette dallo schema, revisione
|
|
||||||
umana delle proposte e caricamento delle relazioni approvate in Qdrant;
|
|
||||||
6. verifica periodica con tht doctor --json e tht workspace test --json;
|
|
||||||
7. una domanda reale completata con successo, senza errori di connessione o modello.
|
|
||||||
|
|
||||||
La configurazione è dichiarata completa solo quando tutti i punti applicabili sono stati eseguiti,
|
Il verificatore è read-only: esegue `tht doctor --json` e `tht status`, senza ristartare lo stack,
|
||||||
le decisioni sono state registrate e i due test terminali sono verdi. Il core è dichiarato usabile
|
rigenerare la configurazione o stampare il contenuto dei segreti.
|
||||||
solo dopo la domanda reale, non perché il frontend risponde a /health.
|
|
||||||
|
|
||||||
## Gate A e Gate B
|
### Gate A — smoke di piattaforma, su tutti e tre i computer
|
||||||
|
|
||||||
### Gate A — piattaforma
|
Registrare per ogni macchina:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
uname -a
|
uname -a
|
||||||
docker version --format '{{.Server.Version}} {{.Server.Arch}}'
|
docker version --format '{{.Server.Version}} {{.Server.Arch}}'
|
||||||
tht version
|
tht version
|
||||||
bash scripts/check-standalone-prerequisites.sh
|
bash scripts/check-standalone-prerequisites.sh
|
||||||
bash scripts/verify-standalone-install.sh "$INSTALLATION"
|
bash scripts/verify-standalone-install.sh "$INSTALLATION"
|
||||||
~~~
|
```
|
||||||
|
|
||||||
### Gate B — usabilità
|
Il gate passa quando il clone è integro, Docker e Compose sono raggiungibili, `tht doctor` è OK,
|
||||||
|
lo stack è avviato e il frontend risponde sulla porta locale predefinita `http://127.0.0.1:8080`.
|
||||||
|
Il doctor controlla anche workspace e Pi: registrare separatamente i loro errori senza attribuire
|
||||||
|
ogni fallimento alla piattaforma. Verificare la disponibilità HTTP con:
|
||||||
|
|
||||||
~~~
|
```sh
|
||||||
tht --installation "$INSTALLATION" doctor --json
|
|
||||||
tht --installation "$INSTALLATION" workspace test --json
|
|
||||||
curl --fail --silent --show-error http://127.0.0.1:8080/health
|
curl --fail --silent --show-error http://127.0.0.1:8080/health
|
||||||
~~~
|
```
|
||||||
|
|
||||||
Poi eseguire una domanda reale e fermare/riavviare con tht stop e tht start. Non usare docker
|
### Gate B — verifica funzionale
|
||||||
compose down --volumes: cancella Catalog, sessioni, Qdrant e il modello embedding.
|
|
||||||
|
Eseguire almeno su una macchina con endpoint e credenziali disponibili:
|
||||||
|
|
||||||
|
Seguire prima [Workspace operations](../operations/workspaces.md) per importare/preparare il
|
||||||
|
workspace e configurare Database e binding locale. Il clone sorgente non trasferisce catalogo,
|
||||||
|
segreti o sessioni del Mac. Connettere l'eventuale VPN richiesta da DWH/modelli e verificare
|
||||||
|
che i relativi nomi siano raggiungibili anche dai container.
|
||||||
|
|
||||||
|
1. aprire `http://127.0.0.1:8080`;
|
||||||
|
2. autenticarsi con l’account locale configurato;
|
||||||
|
3. verificare che il workspace configurato sia leggibile;
|
||||||
|
4. avviare una domanda reale e completare i gate di revisione fino alla SQL finale;
|
||||||
|
5. fermare e riavviare l’installazione, poi ripetere `verify-standalone-install.sh`.
|
||||||
|
|
||||||
|
Un fallimento del Gate B per DWH, provider LLM, Git workspace o credenziali non dimostra da solo un
|
||||||
|
problema di portabilità Docker: registrare separatamente l’endpoint o il componente fallito.
|
||||||
|
|
||||||
|
## Ciclo di vita quotidiano
|
||||||
|
|
||||||
|
Usare il descriptor esplicito quando più installazioni possono essere scoperte:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
INSTALLATION="$PWD/deploy/local/thothii-installation.yaml"
|
||||||
|
|
||||||
|
tht --installation "$INSTALLATION" status
|
||||||
|
tht --installation "$INSTALLATION" start
|
||||||
|
tht --installation "$INSTALLATION" start --build
|
||||||
|
tht --installation "$INSTALLATION" logs
|
||||||
|
tht --installation "$INSTALLATION" doctor --json
|
||||||
|
tht --installation "$INSTALLATION" stop
|
||||||
|
```
|
||||||
|
|
||||||
|
`start --build` è necessario dopo una modifica al codice o per ricostruire le immagini dal clone
|
||||||
|
corrente. `stop` conserva volumi, sessioni, catalogo, stato Pi, dati Qdrant e modello embedding.
|
||||||
|
Non usare `docker compose down --volumes` durante una prova normale: è un’operazione distruttiva
|
||||||
|
che cancella i dati locali.
|
||||||
|
Per aggiornamenti che richiedono migrazioni, seguire il runbook della release prima dell'avvio.
|
||||||
|
|
||||||
## Diagnosi rapida
|
## Diagnosi rapida
|
||||||
|
|
||||||
| Sintomo | Azione |
|
| Sintomo | Controllo |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| Docker Engine is not reachable | avviare Docker Desktop o systemctl e ripetere docker info |
|
| `Docker Engine is not reachable` | avviare Docker Desktop oppure il servizio Docker e ripetere `docker info` |
|
||||||
| Omarchy non trova docker | installare Docker/Compose, abilitare il servizio e riaprire la sessione |
|
| Windows vede Docker ma Bash fallisce | eseguire la guida dentro Ubuntu WSL2 e abilitare l’integrazione della distribuzione in Docker Desktop |
|
||||||
| Windows vede Docker ma Bash fallisce | usare Ubuntu WSL2 e abilitarne l’integrazione in Docker Desktop |
|
| `tht: command not found` | aprire una nuova shell e verificare `command -v tht`; se necessario ripetere il bootstrap |
|
||||||
| pull workspace fallisce | controllare URL, branch, chiave/credential file e known_hosts dal container |
|
| line ending o script non eseguibile | usare un clone nel filesystem WSL2/Linux e rieseguire `bash scripts/...` |
|
||||||
| workspace test segnala binding mancante | configurare database, token/password e CA in Database Management |
|
| architettura non supportata | verificare `docker version --format '{{.Server.Arch}}'`; la prova richiede `amd64` o `arm64` |
|
||||||
| Pi non è pronto | compilare pi-auth.json o la chiave dichiarata dal modelCatalog, poi eseguire tht pi test |
|
| descriptor o env file mancanti | usare il percorso `deploy/local/...` generato da `tht setup`, non un file copiato casualmente |
|
||||||
|
| stack sano ma workflow fallisce | controllare separatamente URL, credential bundle, workspace Git e autenticazione |
|
||||||
|
| dati apparentemente persi | verificare che non sia stato usato `down --volumes`; `stop` non rimuove i volumi |
|
||||||
|
|
||||||
|
## Checklist di accettazione
|
||||||
|
|
||||||
|
- [ ] Il clone proviene dal repository Gitea atteso e la revisione è stata annotata.
|
||||||
|
- [ ] Docker Desktop/Engine e Compose v2 sono disponibili.
|
||||||
|
- [ ] Il runtime restituisce un’architettura ammessa.
|
||||||
|
- [ ] `tht` è stato costruito dal repository e risponde a `tht version`.
|
||||||
|
- [ ] Il setup usa `profile: local`, `shell.mode: full` e `shell.defaultLocale: en`.
|
||||||
|
- [ ] Descriptor, `operator.env`, autenticazione e segreti sono presenti solo in `deploy/local/`.
|
||||||
|
- [ ] Nessun segreto compare in Git, URL, YAML pubblico o comandi registrati.
|
||||||
|
- [ ] Gate A superato su macOS Apple Silicon, Windows WSL2/x64 e Linux x64.
|
||||||
|
- [ ] Gate B eseguito almeno su una macchina con DWH e LLM disponibili.
|
||||||
|
- [ ] Stop/start e verifica finale completati senza cancellare i volumi.
|
||||||
|
|
||||||
|
## Fuori perimetro di questa release
|
||||||
|
|
||||||
|
Restano attività successive:
|
||||||
|
|
||||||
|
- pubblicare immagini pre-costruite su Docker Hub;
|
||||||
|
- ridurre ulteriormente i prompt tramite una configurazione non interattiva dedicata;
|
||||||
|
- creare pacchetti DMG, MSI/EXE, AppImage o altri installer nativi;
|
||||||
|
- fornire un runtime offline o un DWH/LLM locale incluso nell’applicazione.
|
||||||
|
|
||||||
## Documenti collegati
|
## Documenti collegati
|
||||||
|
|
||||||
- [Installazione e primo avvio](first-start.md)
|
- [Install and first start](first-start.md)
|
||||||
- [Operazioni sui workspace](../operations/workspaces.md)
|
- [Shell and localization](shell-and-language.md)
|
||||||
- [Database Management](../operations/database-management.md)
|
- [Workspace operations](../operations/workspaces.md)
|
||||||
- [Configurazione dei modelli](../general/pi-configuration.md)
|
- `deploy/secrets/README.md` (runtime secrets)
|
||||||
- deploy/secrets/README.md
|
|
||||||
|
|
||||||
La pubblicazione di immagini su Docker Hub e gli installer nativi DMG/MSI/AppImage restano attività
|
|
||||||
successive: questa procedura parte dal clone Gitea e non richiede immagini Docker Hub pre-pubblicate.
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Consegna a Codex sul server: ThothII e Omics Portal
|
# Consegna a Codex sul server: ThothII e Omics Portal
|
||||||
|
|
||||||
Revisione: **14 settembre 2026**. Destinazione: Datamart Builder nel portale
|
Revisione: **26 settembre 2026**. Destinazione: Datamart Builder nel portale
|
||||||
Omics esistente, non un nuovo sito standalone. Questo documento è la procedura
|
Omics esistente, non un nuovo sito standalone. Questo documento è la procedura
|
||||||
di riferimento per questa consegna e sostituisce le precedenti istruzioni di
|
di riferimento per questa consegna e sostituisce le precedenti istruzioni di
|
||||||
trasporto/pubblicazione del codice Omics. La distribuzione parte dai sorgenti
|
trasporto/pubblicazione del codice Omics. La distribuzione parte dai sorgenti
|
||||||
@@ -57,20 +57,27 @@ conservati in un percorso operativo stabile sul server.
|
|||||||
|
|
||||||
### ThothII
|
### ThothII
|
||||||
|
|
||||||
Il checkout aggiornato deve essere su `main` e includere almeno
|
Il checkout aggiornato deve essere sulla `main` di Gitea (`origin`) e includere almeno
|
||||||
`bdcd8fcd28f3011471d77224db9c3f5baf227995` e questo documento. Registra anche lo
|
`0d2e573e` (correzione della vista sessione del 26 settembre) e questo documento.
|
||||||
SHA effettivo di `main`, che include il commit di consegna e il merge successivi:
|
Il branch `codex/guided-standalone-install` contiene un processo di nuova installazione
|
||||||
|
ancora in lavorazione: non usarlo per questo aggiornamento e non eseguire
|
||||||
|
`tht setup --complete` sull'installazione server esistente. Registra lo SHA effettivo e
|
||||||
|
confrontalo con `origin/main` senza modificare il checkout operativo:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
git fetch origin main
|
||||||
git status --short --branch
|
git status --short --branch
|
||||||
git rev-parse HEAD
|
git rev-parse HEAD
|
||||||
git merge-base --is-ancestor bdcd8fcd28f3011471d77224db9c3f5baf227995 HEAD
|
git rev-parse origin/main
|
||||||
|
git rev-list --left-right --count HEAD...origin/main
|
||||||
|
git merge-base --is-ancestor 0d2e573e HEAD
|
||||||
```
|
```
|
||||||
|
|
||||||
Se il controllo fallisce, completa l'acquisizione della revisione approvata
|
La divergenza ideale è `0 0` e la working tree è pulita. Se il controllo dell'antenato
|
||||||
prima di toccare l'installazione. Non ricostruire a mano le singole modifiche UI:
|
fallisce, o se il server ha commit o modifiche locali, prepara e verifica la revisione
|
||||||
questa revisione contiene shell, autenticazione, i18n, workflow bilingue,
|
approvata prima di toccare l'installazione; non usare reset o force push. Non ricostruire
|
||||||
amministrazione, typography e navigazione aggiornate.
|
a mano le singole modifiche UI: la revisione di `main` contiene shell, autenticazione,
|
||||||
|
i18n, workflow bilingue, amministrazione, typography e navigazione aggiornate.
|
||||||
|
|
||||||
### Omics Portal
|
### Omics Portal
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ Omics. Le preferenze non modificano il descrittore installato.
|
|||||||
Per una nuova installazione autonoma, selezionare esplicitamente full:
|
Per una nuova installazione autonoma, selezionare esplicitamente full:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
tht setup --complete --profile local --shell-mode full --shell-default-locale en
|
tht setup --profile local --shell-mode full --shell-default-locale en
|
||||||
```
|
```
|
||||||
|
|
||||||
Il setup senza opzioni shell conserva per compatibilità il default embedded.
|
Il setup senza opzioni shell conserva per compatibilità il default embedded.
|
||||||
|
|||||||
@@ -1,175 +0,0 @@
|
|||||||
# Tre esempi locali per l'installazione guidata
|
|
||||||
|
|
||||||
Stato: nota esplorativa conservata; requisiti definiti nel PRD e implementazione
|
|
||||||
rinviata su richiesta dell'utente.
|
|
||||||
Requisiti correnti e decisioni aperte sono ora raccolti nel
|
|
||||||
[PRD dei database di esempio](2026-09-27-example-databases-prd.md), che prevale
|
|
||||||
su questa nota esplorativa in caso di divergenza.
|
|
||||||
Branch: `codex/benchmark-examples`, derivato da `codex/guided-standalone-install`
|
|
||||||
al commit `67ee5262`. Collegamento al progetto installazione:
|
|
||||||
`docs/plans/2026-09-27-guided-installation-resumption.md` sul branch di origine.
|
|
||||||
|
|
||||||
## Requisiti dell'utente
|
|
||||||
|
|
||||||
- Tre database pubblicamente scaricabili da BIRD o altro benchmark, con evidence.
|
|
||||||
- Tre livelli di complessità crescente; preferenza per dati in CSV.
|
|
||||||
- Esempi da implementare in locale.
|
|
||||||
- Caricamento opzionale tramite CLI dal repository dei workspace: selezione di
|
|
||||||
uno, due o tutti e tre i database, dopo il setup; integrazione nel setup da valutare.
|
|
||||||
- Dati, schema PostgreSQL commentato ed Evidence disponibili per ogni esempio.
|
|
||||||
- Domande in un documento di accompagnamento per esercitarsi, senza SQL target.
|
|
||||||
- Collaudo in tre tappe: Windows, Linux Omarchy, macOS.
|
|
||||||
|
|
||||||
### Criterio chiarito dall'utente
|
|
||||||
|
|
||||||
ThothII viene usato con human in the loop: questo progetto non serve a misurarlo
|
|
||||||
contro un benchmark. I benchmark sono soltanto fonti di database e documentazione.
|
|
||||||
Numero di domande, gold SQL, percentuali di correttezza e copertura delle annotazioni
|
|
||||||
per domanda non sono criteri di selezione o di accettazione.
|
|
||||||
Le domande sono invece utili come materiale didattico: il prodotto le include in
|
|
||||||
un documento separato dalle Evidence, senza soluzioni SQL o valutazione automatica.
|
|
||||||
|
|
||||||
Si cercano complessità relazionale e semantica e documentazione sostanziale da
|
|
||||||
curare come Source Evidence: significati, regole aziendali, formule, codifiche,
|
|
||||||
granularità e relazioni. Documenti non collegati ai quesiti del benchmark contano
|
|
||||||
quanto quelli collegati. DDL, righe di esempio e numero di file da soli non
|
|
||||||
dimostrano una buona documentazione di dominio. Dopo il confronto delle alternative,
|
|
||||||
il trio per cui l'utente richiede ora la procedura è Financial, European Football e F1.
|
|
||||||
|
|
||||||
## Dataset proposti
|
|
||||||
|
|
||||||
California Schools è escluso per richiesta dell'utente. European Football è richiesto;
|
|
||||||
l'utente ha inoltre chiesto di valutare Spider 2.0 e la disponibilità di evidence.
|
|
||||||
La proposta corrente comprende Financial e European Football da BIRD e F1 da
|
|
||||||
Spider 2.0-Lite. Shopify, QuickBooks e Workday restano alternative documentate.
|
|
||||||
I livelli sono una progressione didattica proposta per ThothII.
|
|
||||||
|
|
||||||
| Livello | Database | Motivo | Fonti per le Evidence |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| Primo percorso | BIRD `financial` | Conti, clienti, prestiti e movimenti | Codifiche di dominio e regole nelle annotazioni BIRD |
|
|
||||||
| Intermedio | BIRD `european_football_2` | Campionati, squadre, giocatori e partite | Stagioni, significato degli indicatori e aggregazioni nelle annotazioni BIRD |
|
|
||||||
| Avanzato | Spider 2.0-Lite `f1` | Stagioni, gare, piloti, giri, pit stop e cambi di posizione; 29 tabelle dichiarate | Documenti di dominio sui sorpassi e sui tipi di giro, da curare e integrare dove insufficienti |
|
|
||||||
|
|
||||||
Revisione Hugging Face BIRD osservata:
|
|
||||||
`f65faf4ae3b638c1fa6df1d3370c8d92c8366301`.
|
|
||||||
|
|
||||||
Le evidence BIRD comprendono spiegazioni di codici, significati di colonne e regole di
|
|
||||||
calcolo. Sono annotazioni legate alle domande; richiedono adattamento e revisione
|
|
||||||
per diventare Source Evidence di ThothII. Non sono già un archivio ThothII pronto.
|
|
||||||
|
|
||||||
Le definizioni dbt sono fonti da curare, non Evidence Unit già importate in ThothII.
|
|
||||||
Non contare ogni descrizione di colonna come un'evidence distinta. I file tecnici
|
|
||||||
delle librerie dbt non rientrano nel materiale semantico del database.
|
|
||||||
Revisione Spider2 osservata: `cafb867313aab4e674652054198f383cf4018943`.
|
|
||||||
|
|
||||||
Le ricerche motivate e le alternative sono in
|
|
||||||
`docs/research/2026-09-27-spider2-lite-evidence-candidates.md` e
|
|
||||||
`docs/research/2026-09-27-spider2-dbt-evidence-candidates.md`.
|
|
||||||
|
|
||||||
## Fonti e formati
|
|
||||||
|
|
||||||
- [Dataset ufficiale e licenza dichiarata CC BY-SA 4.0](https://huggingface.co/datasets/birdsql/bird_mini_dev).
|
|
||||||
- [Domande PostgreSQL, evidence e SQL di riferimento](https://huggingface.co/datasets/birdsql/bird_mini_dev/blob/f65faf4ae3b638c1fa6df1d3370c8d92c8366301/data/mini_dev_pg-00000-of-00001.json).
|
|
||||||
- [Istruzioni ufficiali e pacchetto database](https://github.com/bird-bench/mini_dev).
|
|
||||||
- [Pacchetto completo indicato dalla dataset card](https://drive.google.com/file/d/13VLWIwpw5E3d5DUkMvzw7hvHE67a4XkG/view?usp=sharing).
|
|
||||||
- [Archivio ZIP collegato dal repository ufficiale](https://bird-bench.oss-cn-beijing.aliyuncs.com/minidev.zip):
|
|
||||||
risposta HEAD 200, 800943648 byte al controllo; contenuto non ancora scaricato né
|
|
||||||
confrontato con il pacchetto aggiornato della dataset card.
|
|
||||||
|
|
||||||
I CSV `database_description` descrivono schema e valori, non contengono le righe
|
|
||||||
delle tabelle. I dati sono forniti come database SQLite e materiale per PostgreSQL/
|
|
||||||
MySQL. Proposta: mantenere PostgreSQL come destinazione locale e, se utile, produrre
|
|
||||||
CSV riproducibili insieme a DDL, tipi e vincoli. Non usare CSV senza schema come
|
|
||||||
unica rappresentazione del database. Conservare provenienza, versione, attribuzione
|
|
||||||
e licenza con gli artefatti derivati.
|
|
||||||
|
|
||||||
Fonti Spider 2.0-Lite per F1:
|
|
||||||
|
|
||||||
- [Istruzioni per scaricare i database SQLite locali](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/README.md).
|
|
||||||
- [Schema e metadati F1](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite/resource/databases/sqlite/f1).
|
|
||||||
- [Classificazione dei sorpassi](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/f1_overtake.md).
|
|
||||||
- [Tipi di giro](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/lap_type.md).
|
|
||||||
|
|
||||||
I tre database sorgente sono SQLite. Esportazione CSV e caricamento PostgreSQL
|
|
||||||
dovranno preservare tipi, relazioni, granularità e contenuto dei dati selezionati.
|
|
||||||
I file sono stati individuati negli archivi; i dati completi non sono stati scaricati
|
|
||||||
né convertiti durante la progettazione.
|
|
||||||
|
|
||||||
## Proposta di download e caricamento PostgreSQL
|
|
||||||
|
|
||||||
Questa sezione risponde alla richiesta di fattibilità e non autorizza né attesta
|
|
||||||
un'implementazione già eseguita.
|
|
||||||
|
|
||||||
### Destinazione
|
|
||||||
|
|
||||||
Il Compose include `catalog-db`, PostgreSQL 17.6, con volume `catalog-data` e database
|
|
||||||
`thothii_catalog`. Quest'ultimo ospita le informazioni applicative del Catalog e
|
|
||||||
la persistenza Memory. Proposta per le installazioni dimostrative: riutilizzare lo
|
|
||||||
stesso servizio PostgreSQL, creando tre database separati, con nomi da finalizzare:
|
|
||||||
`example_financial`, `example_football`, `example_f1`. Ogni database avrà un solo
|
|
||||||
schema applicativo, un workspace associato e un ruolo di interrogazione in sola
|
|
||||||
lettura. L'importazione userà un ruolo distinto con permessi di scrittura.
|
|
||||||
|
|
||||||
La creazione degli esempi deve essere una manutenzione esplicita rieseguibile, non
|
|
||||||
un'aggiunta affidata unicamente agli script di inizializzazione del volume PostgreSQL.
|
|
||||||
Le migrazioni Catalog e i suoi ruoli runtime rimangono separati dal caricatore.
|
|
||||||
La condivisione del servizio implica condivisione di risorse, volume e gestione
|
|
||||||
backup; non equivale a isolamento fra istanze PostgreSQL indipendenti.
|
|
||||||
|
|
||||||
### Sequenza prevista
|
|
||||||
|
|
||||||
1. Selezione esplicita di uno, due o tre esempi, anche dopo il primo setup.
|
|
||||||
2. Manifest versionato per ciascun esempio: URL ufficiali, revisione/checksum,
|
|
||||||
file nell'archivio, fonti documentali, licenze e versione della conversione.
|
|
||||||
Cache dei pacchetti comuni per evitare download duplicati.
|
|
||||||
3. Download ed estrazione dei SQLite e della documentazione. BIRD: descrizioni CSV
|
|
||||||
e annotazioni evidence, conservando il contesto necessario a interpretarle.
|
|
||||||
F1: metadati dello schema e documenti di dominio. Nessuna generazione automatica
|
|
||||||
di nuove regole presentate come se fossero evidence originali.
|
|
||||||
4. Ispezione dello schema e dei dati effettivi; conversione SQLite verso DDL
|
|
||||||
PostgreSQL e CSV, con mapping espliciti per tipi, date, booleani, valori null,
|
|
||||||
identificatori e colonne prive di tipo. Rilevare PK/FK presenti e distinguere
|
|
||||||
relazioni documentate o proposte da quelle effettivamente vincolate nella sorgente.
|
|
||||||
5. Caricamento in database di preparazione dedicati; creazione degli indici e
|
|
||||||
vincoli verificati, confronto delle righe e dei valori e controlli relazionali.
|
|
||||||
Un fallimento lascia l'esempio non pronto senza sostituire una versione funzionante.
|
|
||||||
6. Pubblicazione dei database validati e registrazione dei binding nel Catalog;
|
|
||||||
creazione dei workspace e sincronizzazione degli schemi via servizi esistenti.
|
|
||||||
7. Importazione separata: descrizioni nel Catalog; documenti e regole nelle Source
|
|
||||||
Evidence del workspace, con provenienza. Le Evidence restano artefatti del
|
|
||||||
modulo Evidence; la proiezione ricercabile appartiene a Qdrant.
|
|
||||||
8. Revisione umana/consolidamento delle Evidence e delle relazioni proposte,
|
|
||||||
preprocessing e controlli di utilizzabilità. La disponibilità dei file scaricati
|
|
||||||
non equivale a un workspace pronto.
|
|
||||||
|
|
||||||
Il processo conserva stato e versioni per riprendere dopo errori, evita duplicazioni
|
|
||||||
e non sovrascrive Evidence curate o dati esistenti durante una normale riesecuzione.
|
|
||||||
Download ed elaborazione devono usare componenti containerizzati, mantenendo il
|
|
||||||
percorso Windows/WSL2 senza richiedere Python o Node aggiuntivi sull'host.
|
|
||||||
|
|
||||||
## Decisione architetturale aperta
|
|
||||||
|
|
||||||
Gli ADR 0001 e 0003 e il glossario corrente prevedono un database per workspace.
|
|
||||||
La richiesta di un workspace con tre database richiede quindi una scelta esplicita.
|
|
||||||
Proposta: un pacchetto/repository di esempi con tre workspace indipendenti, ognuno
|
|
||||||
associato al proprio database. Nessuna modifica multi-database è approvata finora.
|
|
||||||
|
|
||||||
## Lavoro previsto dopo la definizione
|
|
||||||
|
|
||||||
1. Fissare versione e checksum dei dati, ispezionare schema, tipi, chiavi e
|
|
||||||
documentazione di dominio; definire percorsi dimostrativi di complessità crescente.
|
|
||||||
2. Preparare il caricamento locale selettivo dei tre dataset, con dati e ruoli
|
|
||||||
distinti dal Catalog applicativo, ripresa e riesecuzione senza duplicazioni.
|
|
||||||
3. Preparare descriptor e Source Evidence con provenienza per ogni esempio;
|
|
||||||
esplicitare ciò che è documentato e ciò che richiede una decisione del curatore.
|
|
||||||
4. Registrare binding nel Catalog, sincronizzare schema e predisporre il percorso
|
|
||||||
di revisione/consolidamento e preprocessing dei workspace selezionati.
|
|
||||||
5. Integrare nel setup la scelta opzionale dei dataset e mostrare per ciascuno
|
|
||||||
caricamento, configurazione, Evidence e stato di utilizzabilità.
|
|
||||||
6. Verificare tutte le sette selezioni non vuote dei tre esempi, la riesecuzione e
|
|
||||||
gli errori di download/importazione. Collaudare una domanda reale per ciascun
|
|
||||||
esempio installato, poi arresto e riavvio, prima su Windows.
|
|
||||||
|
|
||||||
La selezione opzionale comprende anche la possibilità di installare ThothII senza
|
|
||||||
esempi. Nessun download massivo, caricamento database o implementazione del setup
|
|
||||||
è stato eseguito durante questa proposta.
|
|
||||||
@@ -1,402 +0,0 @@
|
|||||||
# PRD — Database di esempio per ThothII
|
|
||||||
|
|
||||||
Data: 2026-09-27. Stato: requisiti D1–D8 approvati tramite `grill-with-docs`;
|
|
||||||
implementazione rinviata su richiesta dell'utente; non iniziata.
|
|
||||||
Branch di progettazione: `codex/benchmark-examples`.
|
|
||||||
|
|
||||||
Il branch conserva la progettazione per una ripresa successiva. La definizione
|
|
||||||
della procedura di installazione prosegue separatamente su
|
|
||||||
`codex/guided-standalone-install`; non deve presumere che la CLI o i database di
|
|
||||||
esempio descritti qui siano già disponibili.
|
|
||||||
|
|
||||||
Questo PRD raccoglie i requisiti correnti e sostituisce, in caso di divergenza,
|
|
||||||
le proposte nella [nota esplorativa](2026-09-27-benchmark-examples.md).
|
|
||||||
Gli aspetti tecnici da verificare prima del rilascio sono distinti dalle decisioni
|
|
||||||
di prodotto approvate e non attestano funzionalità già implementate.
|
|
||||||
|
|
||||||
## Problema e risultato desiderato
|
|
||||||
|
|
||||||
Chi installa ThothII deve poter scegliere e caricare uno, due o tre database di
|
|
||||||
esempio, ottenendo dati reali, schema commentato, Evidence disponibili e un documento
|
|
||||||
di domande per esercitarsi. Il percorso deve funzionare anche dopo l'installazione,
|
|
||||||
senza obbligare a reinstallare ThothII o a conoscere la sua architettura interna.
|
|
||||||
|
|
||||||
La distribuzione avviene dal repository dei workspace: oltre alle definizioni dei
|
|
||||||
workspace, il repository ospita una cartella `examples/` con la CLI e quanto serve
|
|
||||||
a scaricare e predisporre gli esempi su richiesta. Il normale aggiornamento del
|
|
||||||
repository non deve eseguire importazioni.
|
|
||||||
|
|
||||||
Il repository pubblico ThothII su `git.tylconsulting.it` deve rimandare al repository
|
|
||||||
pubblico dedicato agli esempi, ospitato su Gitea e gestito da TYL Consulting.
|
|
||||||
L'URL esatto di destinazione resta da definire; non si presume che debba coincidere
|
|
||||||
con l'istanza Gitea del repository ThothII. README e documentazione di installazione
|
|
||||||
devono rendere reperibili CLI, workspace e istruzioni dal repository principale.
|
|
||||||
|
|
||||||
ThothII ha un processo human in the loop. Le domande sono spunti didattici, senza
|
|
||||||
risposte SQL da riprodurre, punteggi, classifiche o confronto automatico col benchmark.
|
|
||||||
|
|
||||||
## Requisiti confermati
|
|
||||||
|
|
||||||
| ID | Requisito |
|
|
||||||
| --- | --- |
|
|
||||||
| R1 | Tre esempi: BIRD Financial, BIRD European Football, Spider 2.0-Lite F1. |
|
|
||||||
| R2 | Selezione di uno, due o tutti e tre; gli esempi sono facoltativi. |
|
|
||||||
| R3 | Caricare dati e schema PostgreSQL, inclusi commenti di tabelle e colonne. |
|
|
||||||
| R4 | Accompagnare ogni esempio con le Evidence disponibili e la loro provenienza, curate prima del rilascio e indicizzate durante il caricamento. |
|
|
||||||
| R5 | Fornire le domande disponibili in un documento leggibile per esercitarsi. |
|
|
||||||
| R6 | Escludere gli SQL target dei benchmark dal prodotto distribuito agli utenti. |
|
|
||||||
| R7 | Verificare esplicitamente la conversione dei tipi e dei valori verso PostgreSQL. |
|
|
||||||
| R8 | Distribuire una CLI attraverso il repository dei workspace, nella cartella degli esempi. |
|
|
||||||
| R9 | Consentire il caricamento tramite CLI autonoma dopo l'installazione e richiamare la stessa procedura come ultimo passo facoltativo del setup. |
|
|
||||||
| R10 | Collaudare Windows, poi Omarchy, infine macOS, in tre passaggi separati. |
|
|
||||||
| R11 | Distribuire pacchetti PostgreSQL già convertiti e verificati, con ricetta di conversione riproducibile. Valutare conversione locale solo per fonti non redistribuibili. |
|
|
||||||
| R12 | Concludere con workspace subito utilizzabili: dati, commenti, Evidence curate, metadati sincronizzati e indicizzazione completata. |
|
|
||||||
| R13 | La procedura deve prevedere una copia indipendente del repository degli esempi, senza memoria Git dell'originale, oppure uno scaricamento con accesso al repository pubblico in sola lettura. Workspace ed Evidence locali restano modificabili; nessuna credenziale o operazione di scrittura verso l'originale. |
|
|
||||||
|
|
||||||
DDL, comandi di importazione e controlli tecnici SQL fanno parte del caricatore;
|
|
||||||
R6 riguarda le soluzioni alle domande dei benchmark.
|
|
||||||
|
|
||||||
## Perimetro dei tre esempi
|
|
||||||
|
|
||||||
| Esempio | Percorso didattico | Materiale semantico disponibile |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Financial | Iniziale | Descrizioni BIRD, codifiche, annotazioni Evidence associate ai quesiti. |
|
|
||||||
| European Football | Intermedio | Descrizioni BIRD, significato degli indicatori e annotazioni Evidence. |
|
|
||||||
| F1 | Avanzato | Metadati Spider 2.0-Lite e documenti di dominio, fra cui sorpassi e tipi di giro. |
|
|
||||||
|
|
||||||
Questa progressione è didattica, non una misura delle prestazioni di ThothII.
|
|
||||||
La maggiore complessità di F1 non implica una copertura semantica completa:
|
|
||||||
le lacune vanno dichiarate nel materiale di accompagnamento.
|
|
||||||
|
|
||||||
Le fonti sono SQLite e documentazione separata. I CSV BIRD delle descrizioni non
|
|
||||||
sono i dati delle tabelle. La dimensione PostgreSQL, inclusi indici e spazio
|
|
||||||
temporaneo di caricamento, deve essere misurata durante la preparazione; non si
|
|
||||||
deduce dalla sola dimensione SQLite. Le misure sorgente sono nella
|
|
||||||
[ricerca sulle dimensioni](../research/2026-09-27-example-database-sizes.md).
|
|
||||||
|
|
||||||
## Architettura di riferimento
|
|
||||||
|
|
||||||
ThothII include già il servizio PostgreSQL `catalog-db`; il database applicativo
|
|
||||||
è `thothii_catalog`. Il progetto propone di usare la stessa istanza per tre database
|
|
||||||
di esempio distinti, senza mescolare le loro tabelle con quelle applicative.
|
|
||||||
|
|
||||||
Il contratto corrente associa un database a un workspace: il pacchetto contiene
|
|
||||||
quindi tre workspace, ciascuno con il proprio database e un singolo schema
|
|
||||||
applicativo. Non è previsto un cambiamento verso workspace multi-database.
|
|
||||||
|
|
||||||
La CLI di importazione usa credenziali di caricamento separate dalle credenziali
|
|
||||||
in sola lettura con cui ThothII interroga gli esempi. Non riutilizza il ruolo runtime
|
|
||||||
del Metadata Catalog per creare o caricare database. I segreti restano locali,
|
|
||||||
fuori dal repository, dai manifest pubblici e dai log.
|
|
||||||
|
|
||||||
Il PostgreSQL interno non richiede l'esposizione di una porta sull'host: il
|
|
||||||
caricatore deve poter operare nella rete dello stack. Una connessione a un server
|
|
||||||
PostgreSQL alternativo è un'eventuale estensione, non un requisito iniziale.
|
|
||||||
|
|
||||||
## Distribuzione e contenuti
|
|
||||||
|
|
||||||
Struttura illustrativa, da adattare alle convenzioni del repository prescelto:
|
|
||||||
|
|
||||||
```text
|
|
||||||
thoth-workspaces.yaml
|
|
||||||
examples/
|
|
||||||
README.md
|
|
||||||
cli/
|
|
||||||
manifests/
|
|
||||||
financial.yaml
|
|
||||||
european-football.yaml
|
|
||||||
f1.yaml
|
|
||||||
docs/
|
|
||||||
financial-practice.md
|
|
||||||
european-football-practice.md
|
|
||||||
f1-practice.md
|
|
||||||
example-financial/
|
|
||||||
workspace.yaml
|
|
||||||
evidence/
|
|
||||||
source/
|
|
||||||
curated/
|
|
||||||
example-football/...
|
|
||||||
example-f1/...
|
|
||||||
```
|
|
||||||
|
|
||||||
La Source Evidence rimane nel percorso canonico `<workspace-id>/evidence`;
|
|
||||||
il documento di esercitazione è esterno al corpus delle Evidence. Il solo fatto
|
|
||||||
di trovarsi nel repository non deve rendere le domande regole di dominio ricercabili.
|
|
||||||
|
|
||||||
**Adeguamento necessario in ThothII:** il lettore attuale considera workspace tutte
|
|
||||||
le directory alla radice, eccetto `workspace-docs`, e ne verifica la corrispondenza
|
|
||||||
con il catalogo. Una nuova `examples/` non è quindi accettata automaticamente.
|
|
||||||
Il sottoprogetto deve estendere esplicitamente questo contratto per riconoscerla
|
|
||||||
come directory ausiliaria, preservando la validazione dei veri workspace;
|
|
||||||
non deve registrarla come workspace fittizio. Riferimenti:
|
|
||||||
`backend/src/workspaces/git-repository.ts:212` e
|
|
||||||
`backend/src/workspaces/registry.ts:515`.
|
|
||||||
|
|
||||||
Nel repository Git risiedono CLI, manifest, documentazione e definizioni dei
|
|
||||||
workspace. Gli archivi voluminosi dei dati sono scaricati su richiesta da URL
|
|
||||||
versionati, con checksum, cache e attribuzioni. Il luogo di pubblicazione dei
|
|
||||||
pacchetti derivati dipende dalla decisione sulla modalità di conversione e dai
|
|
||||||
diritti di redistribuzione delle singole fonti: la licenza del codice di un
|
|
||||||
benchmark non prova da sola la licenza di tutti i dati inclusi.
|
|
||||||
|
|
||||||
Ogni manifest identifica almeno: esempio e workspace, versione del pacchetto,
|
|
||||||
revisioni e URL delle fonti, file da estrarre, checksum, licenze/attribuzioni,
|
|
||||||
versione della conversione, compatibilità PostgreSQL/ThothII, inventario degli
|
|
||||||
artefatti e risultati attesi dei controlli. Versioni e nomi non sono ricavati
|
|
||||||
silenziosamente da un riferimento mobile come `main`.
|
|
||||||
|
|
||||||
La verifica delle fonti del 2026-09-27 ha rilevato CC BY-SA 4.0 nella dataset card
|
|
||||||
BIRD e MIT per software/documentazione nel repository Spider2. Questo non chiarisce
|
|
||||||
da solo la redistribuibilità di ciascun database fornito negli archivi esterni:
|
|
||||||
per i tre dump PostgreSQL lo stato è ancora da verificare, non un divieto accertato.
|
|
||||||
Registrare licenza dichiarata, fonte e stato della verifica separatamente per dati,
|
|
||||||
descrizioni, Evidence, domande e codice. La verifica sulla versione esatta è una
|
|
||||||
condizione di pubblicazione dei pacchetti; la conversione locale rimane l'eccezione
|
|
||||||
prevista da D2. Fonti: [card BIRD](https://huggingface.co/datasets/birdsql/bird_mini_dev),
|
|
||||||
[repository BIRD](https://github.com/bird-bench/mini_dev),
|
|
||||||
[licenza Spider2](https://github.com/xlang-ai/Spider2/blob/main/LICENSE) e
|
|
||||||
[download Spider2-Lite](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/README.md).
|
|
||||||
|
|
||||||
## Schema commentato e conversione
|
|
||||||
|
|
||||||
Per ogni database si prepara un contratto di conversione per tabella e colonna,
|
|
||||||
fondato sull'ispezione sia dello schema sia dei valori effettivi. Non basta
|
|
||||||
tradurre il tipo dichiarato da SQLite, che può contenere valori eterogenei.
|
|
||||||
|
|
||||||
| Area | Regola di accettazione |
|
|
||||||
| --- | --- |
|
|
||||||
| Interi e identificatori | Range compatibili, nessun overflow; i codici con zeri iniziali restano codici. |
|
|
||||||
| Decimali e floating point | Precisione e scala dichiarate; nessun arrotondamento silenzioso. |
|
|
||||||
| Date e orari | Formato, granularità e timezone documentati; non inventare una timezone. |
|
|
||||||
| Durate | Non confonderle con orari del giorno; rappresentazione e unità esplicite. |
|
|
||||||
| Booleani e categorie | Conversione solo con codifiche verificate; distinguere sconosciuto e falso. |
|
|
||||||
| Null e testo | Distinguere NULL, stringa vuota e sentinelle; preservare Unicode, virgole e newline. |
|
|
||||||
| Colonne senza tipo o miste | Profilazione completa e decisione esplicita; errore comprensibile se non conformi. |
|
|
||||||
| Identificatori SQL | Mapping stabile e quoting coerente per maiuscole, parole riservate e caratteri speciali. |
|
|
||||||
| PK, FK e indici | Separare vincoli presenti, relazioni documentate e relazioni inferite; verificare prima di imporre. |
|
|
||||||
| Contenuti strutturati | Conservare il significato di XML/JSON/testi complessi senza trasformazioni non documentate. |
|
|
||||||
|
|
||||||
Ogni cambiamento rispetto alla sorgente compare in un rapporto di conversione.
|
|
||||||
Per casi anomali non sono ammessi scarto di righe o sostituzione con NULL senza
|
|
||||||
una regola esplicita e verificata. I controlli confrontano conteggi e valori
|
|
||||||
normalizzati per tabella; un solo confronto dei conteggi non basta.
|
|
||||||
|
|
||||||
Le descrizioni disponibili diventano veri `COMMENT ON TABLE` e
|
|
||||||
`COMMENT ON COLUMN` nel database PostgreSQL, mantenendo provenienza e segnalando
|
|
||||||
le descrizioni mancanti. Eventuali integrazioni redazionali sono distinte dalle
|
|
||||||
descrizioni originali. Questi commenti devono essere visibili anche nel Metadata
|
|
||||||
Catalog usato da ThothII; la sola presenza dei commenti in PostgreSQL non soddisfa
|
|
||||||
il requisito se la sincronizzazione del Catalog li ignora.
|
|
||||||
|
|
||||||
Il percorso esiste già: `backend/src/catalog/schema-introspector.ts:84` e `:106`
|
|
||||||
leggono `pg_description`; `metadata-snapshot.ts:52` applica la precedenza
|
|
||||||
descrizione curata, descrizione generata, commento sorgente. Il collaudo deve
|
|
||||||
considerare questa precedenza: non cancellare una descrizione curata per far
|
|
||||||
apparire un commento importato.
|
|
||||||
|
|
||||||
## Evidence e documento di esercitazione
|
|
||||||
|
|
||||||
Le fonti documentali e le annotazioni Evidence sono raccolte senza introdurre
|
|
||||||
regole inventate. Un'annotazione specifica di una domanda conserva il contesto
|
|
||||||
necessario: non diventa automaticamente una regola valida per tutto il database.
|
|
||||||
Duplicati e conflitti vengono riconciliati conservando i riferimenti originali.
|
|
||||||
|
|
||||||
L'archivio distingue Source Evidence e Curated Evidence nel formato supportato
|
|
||||||
da ThothII. La curation avviene prima del rilascio: il pacchetto contiene le fonti
|
|
||||||
e le unità curate, con riferimenti verificabili e lacune dichiarate. I file originali
|
|
||||||
non vengono presentati come Evidence già revisionate. Qdrant contiene la proiezione
|
|
||||||
ricercabile, non sostituisce l'archivio delle Evidence. L'utente finale può modificare
|
|
||||||
e arricchire la curation, ma non deve completarla per iniziare a usare l'esempio.
|
|
||||||
|
|
||||||
Il documento di esercitazione contiene domande disponibili, fonte e identificativo,
|
|
||||||
raggruppamento tematico, eventuali note sui limiti dei dati e riferimenti utili.
|
|
||||||
Non contiene soluzioni SQL né risposte attese per il confronto automatico.
|
|
||||||
Se necessario, si adattano i riferimenti ai nomi PostgreSQL, rendendo riconoscibile
|
|
||||||
la modifica. Guide, domande e contenuti semantici curati sono disponibili in italiano
|
|
||||||
e inglese, conservando gli originali e rendendo riconoscibili le traduzioni;
|
|
||||||
gli identificatori SQL restano invariati. Le rappresentazioni linguistiche di una
|
|
||||||
stessa Evidence non devono duplicarne il risultato nella ricerca.
|
|
||||||
|
|
||||||
Gli archivi originali possono includere SQL target. L'estrazione per il prodotto
|
|
||||||
ammette solo i campi necessari a schema, documentazione, Evidence e domande;
|
|
||||||
gli SQL target non entrano nei workspace, negli indici o nei documenti didattici.
|
|
||||||
|
|
||||||
## Comportamento della CLI
|
|
||||||
|
|
||||||
L'interfaccia esatta sarà definita dopo le decisioni di questo PRD. Le capacità
|
|
||||||
richieste sono: elencare gli esempi e i prerequisiti, scegliere un sottoinsieme,
|
|
||||||
scaricare/verificare, caricare, collegare i workspace e mostrare lo stato per esempio.
|
|
||||||
|
|
||||||
1. Individuare l'installazione e verificare compatibilità, servizi e spazio.
|
|
||||||
2. Risolvere i manifest e mostrare cosa verrà caricato per gli esempi scelti.
|
|
||||||
3. Scaricare solo i pacchetti necessari; riutilizzare gli archivi condivisi in cache.
|
|
||||||
4. Verificare ed estrarre il pacchetto PostgreSQL già convertito; l'eventuale
|
|
||||||
conversione locale eccezionale deve essere dichiarata dal manifest.
|
|
||||||
5. Caricare in un database di preparazione e verificarne dati, tipi, vincoli e commenti.
|
|
||||||
6. Rendere disponibile il database verificato e registrare il binding nel Catalog.
|
|
||||||
7. Sincronizzare metadati, importare le Evidence già curate ed eseguire
|
|
||||||
consolidamento/preprocessing per rendere il workspace subito utilizzabile.
|
|
||||||
8. Fornire un riepilogo per esempio, il documento con le domande e il prossimo passo.
|
|
||||||
|
|
||||||
Lo stato deve distinguere almeno dati caricati, metadati sincronizzati, Evidence
|
|
||||||
disponibili, indicizzazione completata e workspace pronto. Un download concluso
|
|
||||||
non equivale a un esempio utilizzabile. Se gli esempi hanno esiti diversi, il
|
|
||||||
riepilogo deve mostrare successi e fallimenti separatamente.
|
|
||||||
|
|
||||||
La riesecuzione della stessa versione non duplica dati e non sovrascrive le
|
|
||||||
Evidence modificate dall'utente. Un errore non sostituisce un database funzionante;
|
|
||||||
lo stato permette di riprendere dalle fasi completate. Il preprocessing corrente
|
|
||||||
non è internamente resumable: in caso di errore quella fase viene rieseguita.
|
|
||||||
Aggiornamento di versione, ripristino e rimozione distruttiva richiedono operazioni
|
|
||||||
esplicite distinte dalla normale installazione e sono esclusi dalla prima versione
|
|
||||||
della CLI, che comprende elenco/selezione, installazione, verifica e ripresa dopo errore.
|
|
||||||
|
|
||||||
L'integrazione deve usare le API esistenti per creazione del database nel Catalog,
|
|
||||||
binding e secret store (`backend/src/routes/catalog-databases.ts`), con
|
|
||||||
autenticazione e permessi appropriati. La sincronizzazione dello schema è un
|
|
||||||
run distinto, con conferma esplicita (`backend/src/routes/catalog-schema.ts:189`
|
|
||||||
e `:223`): il progetto deve definire come presentare o gestire quella conferma
|
|
||||||
senza aggirarne il contratto. `workspace preprocess run` ed Evidence consolidate
|
|
||||||
sono già disponibili come CLI, ma non creano binding o credenziali per conto del
|
|
||||||
caricatore. Si veda [il contratto preprocessing](../contracts/workspace-preprocessing-cli.md).
|
|
||||||
|
|
||||||
## Collaudo e condizioni di completamento
|
|
||||||
|
|
||||||
- Ogni esempio ha un inventario verificato di schema, dati, commenti, Evidence e domande.
|
|
||||||
- Il repository con `examples/` supera la validazione e mantiene i controlli
|
|
||||||
sulle directory dei workspace; nessun file della CLI viene eseguito dal pull.
|
|
||||||
- Tutte le sette selezioni non vuote producono esclusivamente gli esempi scelti.
|
|
||||||
- La selezione di nessun esempio non ostacola l'installazione di ThothII.
|
|
||||||
- Si verificano conversione dei valori, vincoli, commenti e propagazione al Catalog.
|
|
||||||
- Il ruolo di interrogazione può leggere i dati e non può modificarli.
|
|
||||||
- Interruzione del download, checksum errato, errore d'importazione e spazio
|
|
||||||
insufficiente producono uno stato recuperabile e non danneggiano esempi esistenti.
|
|
||||||
- Ripetere un'installazione completata non altera dati né curation locale.
|
|
||||||
- La copia indipendente non contiene storia Git o relazione di fork dell'originale,
|
|
||||||
né remote verso di esso; mantiene versione, checksum, licenze e attribuzioni.
|
|
||||||
- Il percorso di download non richiede credenziali di scrittura verso il repository
|
|
||||||
pubblico e non esegue push. In entrambe le modalità l'utente può modificare
|
|
||||||
workspace ed Evidence locali e continuare a usarli dopo il riavvio.
|
|
||||||
- Una sessione reale può interrogare ciascun esempio, con Evidence reperibili;
|
|
||||||
non è richiesto riprodurre l'SQL di un benchmark.
|
|
||||||
- Ogni workspace risulta subito utilizzabile anche dopo riavvio; le Evidence
|
|
||||||
curate sono effettivamente reperibili e non solo presenti sul filesystem.
|
|
||||||
- Primo rilascio verificato su Windows/WSL2 e Docker Desktop; secondo su Omarchy;
|
|
||||||
terzo su macOS. Nessuna dichiarazione di supporto a una tappa non ancora verificata.
|
|
||||||
|
|
||||||
La proposta è eseguire conversione/caricamento in container, senza introdurre
|
|
||||||
Python o Node obbligatori sull'host dell'utente. Il metodo di avvio/download della
|
|
||||||
CLI resta da precisare in base alla scelta dei pacchetti.
|
|
||||||
|
|
||||||
## Decisioni approvate con grill-with-docs
|
|
||||||
|
|
||||||
Approvazione dell'utente del 2026-09-27: «ok a tutto», riferita a D1, D2 e D3.
|
|
||||||
Nel round successivo l'utente approva D4 con precisazione della distribuzione Gitea,
|
|
||||||
D5 e D7. Dopo il chiarimento approva anche D6, ribadendo che chi installa deve
|
|
||||||
trovare tutto pronto, e aggiunge D8 sulla copia autonoma o sul download in sola lettura.
|
|
||||||
|
|
||||||
| ID | Decisione | Esito approvato |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| D1 | Quando proporre il caricamento? | CLI autonoma dopo il setup, richiamabile anche come ultimo passo facoltativo dello stesso setup. |
|
|
||||||
| D2 | Dove convertire le sorgenti verso PostgreSQL? | Preparare e verificare pacchetti PostgreSQL versionati nella fase di rilascio; la CLI dell'utente scarica e carica. Conservare la ricetta di conversione riproducibile. Se una fonte non è redistribuibile, valutarne la conversione locale. |
|
|
||||||
| D3 | Quanto deve essere pronto l'esempio dopo il caricamento? | Dati, commenti e Evidence curate in anticipo, già sincronizzate e indicizzate, per consentire subito una sessione; curation successiva resta disponibile all'utente. |
|
|
||||||
| D4 | Repository di distribuzione | Il repository pubblico ThothII su git.tylconsulting.it rimanda a un repository pubblico dedicato agli esempi su Gitea gestito da TYL Consulting. Per installazioni con un repository proprio, il curatore integra i contenuti degli esempi in quel repository. Nessun nuovo supporto multi-repository in questo sottoprogetto. |
|
|
||||||
| D5 | Lingua dei contenuti | Guide, domande e contenuti semantici curati in italiano e inglese; originali conservati, traduzioni riconoscibili e identificatori SQL invariati. Nessuna duplicazione della stessa Evidence nella ricerca. |
|
|
||||||
| D6 | Preparazione e verifica delle Evidence | Il progetto prepara e controlla i contenuti; all'utente vengono sottoposte solo ambiguità o conflitti non risolvibili dalle fonti, con una proposta concreta. Chi installa riceve tutto pronto e non deve revisionare le Evidence per iniziare. |
|
|
||||||
| D7 | Prima versione della CLI | Elenco/selezione, installazione, verifica e ripresa dopo errore. Aggiornamento di versione, reset e disinstallazione rimandati; nessuna sostituzione automatica di esempi modificati. |
|
|
||||||
| D8 | Copia autonoma e sola lettura | Copia indipendente senza storia/remote/relazione di fork dell'originale, oppure scaricamento dal repository pubblico in sola lettura. Il limite riguarda la scrittura sul repository originale: workspace ed Evidence locali rimangono modificabili. Versioni, licenze e attribuzioni sono conservate. |
|
|
||||||
|
|
||||||
La risposta «1» dell'utente conferma per D8 la sola lettura remota e la modificabilità locale.
|
|
||||||
Nome e URL del repository destinazione saranno definiti prima della pubblicazione.
|
|
||||||
Interfaccia CLI, autenticazione e custodia dei segreti saranno definite nella
|
|
||||||
specifica tecnica coerentemente con i contratti esistenti. Le verifiche tecniche
|
|
||||||
e dei diritti sulle fonti sono lavoro del progetto e non domande demandate all'utente.
|
|
||||||
|
|
||||||
## Contesto del secondo round e chiarimento D6
|
|
||||||
|
|
||||||
La verifica locale ha individuato il repository PSD privato, mentre i template
|
|
||||||
generici riportano un URL esemplificativo. Non è stato individuato un repository
|
|
||||||
concreto già destinato agli esempi. L'installazione supporta una sola sorgente Git:
|
|
||||||
la scelta di un repository per gli esempi non deve sostituire implicitamente il
|
|
||||||
repository già configurato in un'installazione esistente.
|
|
||||||
|
|
||||||
D6 riguarda la verifica del significato delle Evidence adattate dalle fonti:
|
|
||||||
per esempio, un'annotazione riferita a una singola domanda non può diventare una
|
|
||||||
regola generale senza supporto documentale. Non riguarda la scrittura da zero delle
|
|
||||||
Evidence da parte dell'utente o una revisione a ogni installazione.
|
|
||||||
|
|
||||||
Chiarimento approvato per D6: il progetto prepara i contenuti, ne
|
|
||||||
controlla provenienza, coerenza e adattamento a PostgreSQL; all'utente vengono
|
|
||||||
sottoposte solo ambiguità o conflitti non risolvibili dalle fonti, con una proposta
|
|
||||||
concreta. I punti irrisolti restano segnalati ed esclusi dalle regole pubblicate
|
|
||||||
come verificate. L'utilizzatore finale riceve il materiale già curato.
|
|
||||||
|
|
||||||
## D8 — Copia del repository e permessi
|
|
||||||
|
|
||||||
Richiesta dell'utente: «fork del repository senza memoria dell'originale, o lo
|
|
||||||
scarico in locale ma senza diritti di scrittura». Il risultato deve restare pronto
|
|
||||||
all'uso e non richiedere un lavoro di curation a chi installa.
|
|
||||||
|
|
||||||
La proposta tecnica per la copia indipendente è estrarre un rilascio verificato
|
|
||||||
senza la directory `.git` originaria; se il runtime richiede Git, inizializzare
|
|
||||||
una nuova storia locale, senza remote verso l'originale né associazione di fork
|
|
||||||
sulla piattaforma. Un fork ordinario che conserva storia e relazione col repository
|
|
||||||
originario non soddisfa questo significato di indipendenza. L'eventuale pubblicazione
|
|
||||||
in un repository personale è un'operazione separata, non implicita nell'installazione.
|
|
||||||
|
|
||||||
Versione del pacchetto, checksum, licenze e attribuzioni rimangono nel manifest e
|
|
||||||
nella documentazione: l'assenza di memoria Git non elimina la provenienza dei dati
|
|
||||||
e delle Evidence. Nessun aggiornamento automatico deve sovrascrivere una copia
|
|
||||||
personalizzata.
|
|
||||||
|
|
||||||
Per il percorso di download, la scelta approvata è accesso anonimo in sola
|
|
||||||
lettura al repository pubblico, senza credenziali di scrittura e senza operazioni
|
|
||||||
di push. File e archivio locale delle Evidence restano modificabili dall'utente.
|
|
||||||
Il filesystem locale non è reso globalmente in sola lettura.
|
|
||||||
|
|
||||||
**Adeguamento necessario nel runtime:** la copia senza `.git` non è oggi una sorgente
|
|
||||||
completa per ThothII. Il lettore richiede `HEAD` e file committati
|
|
||||||
(`backend/src/workspaces/git-repository.ts:198`); il refresh esegue fetch del branch
|
|
||||||
da `origin` e rifiuta checkout sporchi o divergenze (`:467–485`). Il solo `git init`
|
|
||||||
senza remote non completa quindi il percorso corrente.
|
|
||||||
|
|
||||||
La specifica deve prevedere una sorgente locale autonoma, oppure una nuova copia
|
|
||||||
Git locale usata come sorgente del checkout gestito: eventuali riferimenti Git
|
|
||||||
interni all'installazione non devono puntare al repository pubblico originale.
|
|
||||||
Il backend già accetta percorsi Git locali assoluti/file URL (`:60–64`), ma setup,
|
|
||||||
configurazione e aggiornamento devono supportare coerentemente il percorso scelto.
|
|
||||||
Le due modalità devono funzionare senza chiedere all'utente di configurare Git.
|
|
||||||
|
|
||||||
Il download HTTPS anonimo è compatibile con il consumo remoto del backend; va
|
|
||||||
verificato anche nel bootstrap dell'installazione. Il checkout gestito non è la
|
|
||||||
cartella da sporcare con modifiche manuali: la procedura deve rendere esplicita una
|
|
||||||
copia locale modificabile dei workspace e gestirne l'attivazione senza push verso
|
|
||||||
l'originale. L'archivio locale delle Evidence è già separato e modificabile.
|
|
||||||
Riferimenti: `docs/contracts/workspace-evidence-v3.md:218` e il contratto delle
|
|
||||||
Evidence curate. I controlli di integrità del checkout non vanno disabilitati per
|
|
||||||
ottenere la modificabilità richiesta.
|
|
||||||
|
|
||||||
## Passaggio alla specifica tecnica
|
|
||||||
|
|
||||||
La definizione dei requisiti è conclusa con D1–D8. La specifica dovrà tradurli in
|
|
||||||
questi blocchi verificabili, prima dell'implementazione:
|
|
||||||
|
|
||||||
1. Contratto del repository: cartella `examples/`, distribuzione pubblica e copia
|
|
||||||
autonoma o accesso remoto in sola lettura, con personalizzazioni locali persistenti.
|
|
||||||
2. Preparazione dei tre pacchetti: fonti e diritti verificati, conversione di
|
|
||||||
schema/dati/tipi, commenti, Evidence curate e materiale didattico bilingue.
|
|
||||||
3. CLI: download, verifica, importazione isolata, binding, sincronizzazione e
|
|
||||||
indicizzazione, stato e ripresa dopo errore, senza push verso l'originale.
|
|
||||||
4. Integrazione facoltativa nel setup, collegamenti fra repository e documentazione.
|
|
||||||
5. Collaudo Windows, successivamente Omarchy, infine macOS.
|
|
||||||
|
|
||||||
## Riferimenti
|
|
||||||
|
|
||||||
- [BIRD mini-dev: dati e documentazione](https://github.com/bird-bench/mini_dev).
|
|
||||||
- [Dataset card BIRD](https://huggingface.co/datasets/birdsql/bird_mini_dev).
|
|
||||||
- [Spider 2.0-Lite: download e formati](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite).
|
|
||||||
- [Ricerca sui candidati e sulle Evidence](../research/2026-09-27-spider2-lite-evidence-candidates.md).
|
|
||||||
- [Contratto workspace/Evidence](../contracts/workspace-evidence-v3.md),
|
|
||||||
[modulo Evidence](../evidence.md), [glossario](../../CONTEXT.md),
|
|
||||||
[ADR 0001 — Metadata Catalog](../adr/0001-postgres-metadata-catalog.md),
|
|
||||||
[ADR 0003 — binding locali](../adr/0003-installation-local-database-bindings.md).
|
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
# Rilascio server ThothII embedded in Omics — 2026-09-14
|
||||||
|
|
||||||
|
## Esito
|
||||||
|
|
||||||
|
Il rilascio tecnico è stato eseguito il 2026-09-14 e i controlli automatici e
|
||||||
|
server-side descritti sotto sono superati. L'accettazione funzionale non è ancora
|
||||||
|
chiusa: lingua, tema, fullscreen, logout, ruoli e continuità SSE devono essere
|
||||||
|
provati da browser con account Omics autorizzati.
|
||||||
|
|
||||||
|
Finestra autorizzata dall'operatore e conclusa alle 16:17 CEST. Le ammissioni
|
||||||
|
ThothII sono state riaperte dopo il collaudo (`active: false`, `admissions: 0`).
|
||||||
|
|
||||||
|
## Revisioni e immagini distribuite
|
||||||
|
|
||||||
|
- ThothII, checkout operativo `/srv/thothii-v2/source/ThothII`:
|
||||||
|
`49333a2d35664b7237c3ddc2a9f10a605dcc84ce`, branch `main`, pulito e allineato
|
||||||
|
a `origin/main`.
|
||||||
|
- Omics Portal, checkout `/home/chirone/omics_portal`:
|
||||||
|
`fca10901a73666ca257d8f4cc4b77066295c400a`, branch `master`, pulito e due
|
||||||
|
commit avanti a `origin/master`. Include la consegna funzionale
|
||||||
|
`95154e179144e2453b37ef2a63a65d6f377e4cf8`.
|
||||||
|
- CLI nativo `/usr/local/bin/tht`: commit
|
||||||
|
`49333a2d35664b7237c3ddc2a9f10a605dcc84ce`, build
|
||||||
|
`2026-09-14T15:08:47+02:00`, `linux/amd64`.
|
||||||
|
- Core: `thothii-v2-core:49333a2d`, image ID
|
||||||
|
`sha256:d62bf17dd1345e6a459edabe4b559333b396ef30c523dedf1b842506c147efbd`.
|
||||||
|
- Frontend: `thothii-v2-frontend:49333a2d`, image ID
|
||||||
|
`sha256:dd57745143fc282562ec6d4c2cd8fc493eb2078494eeb17099d49bea8eae218b`.
|
||||||
|
- Omics web: `omics_portal-web`, image ID
|
||||||
|
`sha256:11e99905c41b38cd68d0e726f25a4174b8eb65db27fb1d887238a7bd255074da`.
|
||||||
|
- Nginx: image invariata `sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14`.
|
||||||
|
|
||||||
|
## Configurazioni modificate
|
||||||
|
|
||||||
|
- `deploy/psd-server-v2/thothii-installation.yaml`: Installation Model Catalog
|
||||||
|
schema v2; shell `embedded`, locale predefinito `en`, adapter `omics-portal`;
|
||||||
|
provider DeepSeek unificato e default interaction `zai/glm-5.3`. Percorsi,
|
||||||
|
profilo server, workspace, DWH e provider reali del server sono stati
|
||||||
|
preservati.
|
||||||
|
- `/srv/thothii-v2/operator/compose.portal-upstream.yaml`: `AUTH_MODE=upstream`,
|
||||||
|
alias `thothii-core` e `thothii-frontend` sulla rete Omics; eliminato il mount
|
||||||
|
della copia manuale di `config.js`. Nessun `auth.yaml` e nessuna runtime auth
|
||||||
|
projection.
|
||||||
|
- `/srv/thothii-v2/operator/operator.env`: tag applicativo aggiornato a
|
||||||
|
`49333a2d`; nessun valore segreto copiato dal Mac o riportato in questo report.
|
||||||
|
- `deploy/psd-server-v2/generated/`: proiezioni rigenerate dal descriptor. Il
|
||||||
|
frontend riceve in sola lettura `generated/frontend/config.js`, che espone
|
||||||
|
soltanto `backendBaseUrl: /api` e il contratto shell embedded.
|
||||||
|
- Omics: integrati template embedded, lingua Django, topbar/fullscreen, adapter
|
||||||
|
JavaScript, traduzioni e test della consegna GitHub.
|
||||||
|
- `nginx/nginx.conf`: non modificato. La configurazione già presente conteneva
|
||||||
|
l'`auth_request` Django, derivazione server-side degli header `X-Thoth-*`,
|
||||||
|
rimozione di cookie/Authorization/header client, origin esatta e SSE senza
|
||||||
|
buffering.
|
||||||
|
|
||||||
|
Configurazione risolta verificata:
|
||||||
|
|
||||||
|
- core e frontend usano le immagini `49333a2d`;
|
||||||
|
- `AUTH_MODE=upstream`;
|
||||||
|
- core senza porta host pubblicata;
|
||||||
|
- frontend pubblicato soltanto su `127.0.0.1:18020`;
|
||||||
|
- alias Omics risolti rispettivamente a `thothii-core` e `thothii-frontend`;
|
||||||
|
- `config.js` generated montato read-only;
|
||||||
|
- `THOTH_PUBLIC_EXPOSURE=false` e storage sessioni locale, preservando la
|
||||||
|
topologia server già approvata.
|
||||||
|
|
||||||
|
## Backup e rollback
|
||||||
|
|
||||||
|
Backup protetto:
|
||||||
|
`/srv/thothii-v2/backups/20260914-pre-embedded-release`, directory `0700`, tutti
|
||||||
|
i file `0600` e owner `root:root`.
|
||||||
|
|
||||||
|
Contiene:
|
||||||
|
|
||||||
|
- immagini applicative precedenti core/frontend/Omics;
|
||||||
|
- binario CLI precedente;
|
||||||
|
- descriptor, override, config manuale e proiezioni precedenti;
|
||||||
|
- bind `data`, `workspace-registry`, `pi-state`, `operator` e `secrets`;
|
||||||
|
- snapshot raw dei volumi catalogo, Qdrant ed embedding;
|
||||||
|
- dump logico PostgreSQL del catalogo ThothII;
|
||||||
|
- dump logico PostgreSQL del database usato da Omics;
|
||||||
|
- snapshot dei volumi statici e media Omics;
|
||||||
|
- `SHA256SUMS`.
|
||||||
|
|
||||||
|
Tutti i checksum sono risultati validi. Gli archivi tar sono stati elencati
|
||||||
|
integralmente senza errori e i due dump sono stati validati con
|
||||||
|
`pg_restore --list`. Le vecchie immagini restano disponibili; Omics precedente
|
||||||
|
è inoltre etichettata `omics_portal-web:pre-fca1090-aff75817`.
|
||||||
|
|
||||||
|
Non sono state eseguite migrazioni ThothII: tra `82e2c91f` e `49333a2d` non
|
||||||
|
esistono nuove migrazioni catalogo, Memory o sessioni. L'entrypoint Omics ha
|
||||||
|
eseguito `migrate` con risultato `No migrations to apply`. Il rollback normale
|
||||||
|
è quindi applicativo e non richiede ripristino dati; dump e snapshot raw sono
|
||||||
|
conservati per un recupero separato solo in presenza di corruzione accertata.
|
||||||
|
|
||||||
|
## Verifiche superate
|
||||||
|
|
||||||
|
### Prima del rilascio
|
||||||
|
|
||||||
|
- frontend ThothII: 768/768 test;
|
||||||
|
- backend auth/config/session/model: 205/205 test mirati;
|
||||||
|
- estensione Pi, lingua e ripresa: 7/7;
|
||||||
|
- harness lingua sessione e repository PostgreSQL: 24/24;
|
||||||
|
- CLI Go: tutte le package superate;
|
||||||
|
- Omics embedded shell isolata: 15/15;
|
||||||
|
- build delle tre immagini candidate completata;
|
||||||
|
- generazione delle proiezioni validata prima in staging isolato;
|
||||||
|
- build documentale strict completata dopo la scrittura di questo report.
|
||||||
|
|
||||||
|
### Sul server distribuito
|
||||||
|
|
||||||
|
- `tht status`: exit 0;
|
||||||
|
- `tht doctor --json`: `ok: true`, 13/13 controlli superati, inclusi descriptor,
|
||||||
|
proiezioni, permessi, Docker/Compose, autenticazione, health, HTTP, registry,
|
||||||
|
workflow e Pi;
|
||||||
|
- core, frontend, catalog-db, Qdrant, embedding e Omics web in stato healthy;
|
||||||
|
- `nginx -t` superato prima e dopo la ricreazione;
|
||||||
|
- catalogo Superset Omics valido: 32 dashboard;
|
||||||
|
- `migrate --check` post-rilascio: exit 0;
|
||||||
|
- nessun traceback, fatal, panic, HTTP 500 o errore nginx nei log recenti;
|
||||||
|
- pagina senza sessione: `302` verso `/accounts/login/`;
|
||||||
|
- `/datamart-builder/api/me` senza sessione: `403`;
|
||||||
|
- richiesta pubblica con header principal/admin falsificati: ancora `403`;
|
||||||
|
- `config.js`: `200`, `Cache-Control: no-store`, contenuto embedded corretto;
|
||||||
|
- manifest Vite risolto da Django: 368 entry; entrypoint corrente
|
||||||
|
`index-ktEFlKPi.js` e stylesheet `index-BtNkA4QL.css`;
|
||||||
|
- asset JavaScript attraverso `/datamart-builder/assets/`: `200` e cache
|
||||||
|
`public, immutable`;
|
||||||
|
- il core non ascolta sulla porta host 8787; dalla rete interna senza principal
|
||||||
|
risponde `401`;
|
||||||
|
- nginx risolve i nuovi indirizzi degli alias, senza dipendere dai precedenti IP
|
||||||
|
Docker.
|
||||||
|
|
||||||
|
Il probe HTTPS verso l'hostname pubblico, eseguito dal server stesso, è andato
|
||||||
|
in timeout prima della connessione (`HTTP 000`): è un limite di raggiungibilità
|
||||||
|
hairpin/rete e non viene contato come verifica superata. I probe equivalenti
|
||||||
|
attraverso nginx locale con Host e forwarded protocol reali sono invece passati.
|
||||||
|
|
||||||
|
È rimasto intenzionalmente intatto il container orphan storico
|
||||||
|
`omics_portal-web-run-a0bc36025e52`, creato circa tre mesi prima del rilascio ed
|
||||||
|
exited da due settimane; non è stato rimosso perché estraneo alla consegna.
|
||||||
|
|
||||||
|
## Prove manuali ancora necessarie
|
||||||
|
|
||||||
|
Usare account di prova autorizzati e dati non operativi:
|
||||||
|
|
||||||
|
1. utente Omics autorizzato apre Datamart Builder senza secondo login e vede un
|
||||||
|
solo header, quello Omics;
|
||||||
|
2. `/datamart-builder/api/me` restituisce issuer `portal`, subject Django stabile,
|
||||||
|
ruoli corretti e `session`/`csrfToken` null;
|
||||||
|
3. confronto utente normale/amministratore e rifiuto utente senza capability;
|
||||||
|
4. IT/EN prima dell'apertura e cambio tramite form Omics, senza tradurre SQL o
|
||||||
|
contenuti authored;
|
||||||
|
5. light/dark con popup, menu e griglia aperti;
|
||||||
|
6. ingresso/uscita fullscreen, compresa uscita con Esc e rifiuto browser;
|
||||||
|
7. logout Omics, seconda scheda e nuova verifica `/me`;
|
||||||
|
8. nuova sessione, flusso SSE, riconnessione dopo scadenza, reload senza avvio
|
||||||
|
automatico e ripresa con `interaction_language` invariata;
|
||||||
|
9. richiesta cross-origin autenticata su operazione fittizia e comportamento
|
||||||
|
distinto di un singolo `403` operativo;
|
||||||
|
10. accesso HTTPS reale da una postazione client, perché il server non raggiunge
|
||||||
|
l'hostname pubblico in hairpin.
|
||||||
|
|
||||||
|
L'installazione non va dichiarata funzionalmente accettata finché questa matrice
|
||||||
|
manuale non è stata eseguita e registrata.
|
||||||
@@ -0,0 +1,142 @@
|
|||||||
|
# Rilascio coordinato ThothII / Omics — 26 settembre 2026
|
||||||
|
|
||||||
|
**Distribuito; accettazione automatica superata. Collaudo browser positivo per accesso, interfaccia e avvio/interruzione/ripresa sessione; prove estese residue sotto.**
|
||||||
|
Finestra esplicitamente confermata dall’utente in chat («confermo»), avvio alle
|
||||||
|
19:28 Europe/Rome. Riferimento: [piano approvato](2026-09-26-server-release-plan.md).
|
||||||
|
Maintenance disattivata alle **19:35:27** dopo tutti i controlli automatici.
|
||||||
|
|
||||||
|
## Versioni e stato finale
|
||||||
|
|
||||||
|
| Componente | Risultato |
|
||||||
|
| --- | --- |
|
||||||
|
| ThothII sorgente | Main `497ab84031e285464fdbb73e6e0ce9252687e3ab`, checkout pulito in `/srv/thothii-v2/releases/497ab84031e285464fdbb73e6e0ce9252687e3ab` |
|
||||||
|
| Core | `thothii-v2-core:497ab840-preflight`, ID `sha256:182f4e0d63404cb7ed6a0e272441e9c55ed27e2bb16fdbf4d7162f892ac76dc7`, healthy |
|
||||||
|
| Frontend | `thothii-v2-frontend:497ab840-preflight`, ID `sha256:5f5a4f81139432d0ac41025c3006edaf1258b623ce388242700b1b20fcce6421`, healthy |
|
||||||
|
| Omics checkout | Fast-forward a `928f7e9fff2aba895416776fecf5668ee957d237`; nessuna modifica tracciata, file locali preservati |
|
||||||
|
| Omics web | Stesso container e immagine `sha256:27aa100690b110bf596322b1b0a31acc178ca9d1c709bc10382cbeecbfb5aeca`, riavviato e healthy; risposta HTTP Django verificata |
|
||||||
|
| Omics nginx | Ricreato col fix asset e immagine precedente fissata `sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14`; `nginx -t` positivo |
|
||||||
|
| Supporti | Catalogo PostgreSQL, Qdrant e Ollama healthy; immagini e volumi invariati |
|
||||||
|
| CLI host | `/usr/local/bin/tht` aggiornato; SHA256 `0d39a93fb0a3b2147541a746c75832db20302f3a604bf6510da69d3731bcd783` |
|
||||||
|
| Maintenance / Pi | Maintenance inattiva, zero processi Pi RPC al controllo finale delle 19:36 |
|
||||||
|
|
||||||
|
Descrittore mantenuto nel percorso originale:
|
||||||
|
`/srv/thothii-v2/source/ThothII/deploy/psd-server-v2/thothii-installation.yaml`.
|
||||||
|
Project Compose sempre `thothii-7f901b48fe35`; shell embedded/en/omics-portal,
|
||||||
|
auth upstream e storage locale invariati. Cambiati solo projectDirectory e
|
||||||
|
percorso dell’overlay git-ssh nel descrittore, tag immagini in env/overlay.
|
||||||
|
Proiezioni rigenerate col nuovo CLI e UID 10001. Descriptor/env 10001:10001 0600;
|
||||||
|
overlay 1013:1014 0640; CLI root:root 0755.
|
||||||
|
|
||||||
|
Il vecchio checkout ThothII dirty resta al suo posto per rollback. Nessun reset,
|
||||||
|
force push, eliminazione di volumi, cambio identità, credenziali, DWH o Authentik.
|
||||||
|
Nessun push Omics eseguito. Nessuna nuova migrazione applicata; i controlli Django
|
||||||
|
prima e dopo il riavvio non rilevano migrazioni o modifiche dei modelli pendenti.
|
||||||
|
L’entrypoint web ha rieseguito i normali comandi di startup, statici e traduzioni.
|
||||||
|
|
||||||
|
## Backup ed esecuzione
|
||||||
|
|
||||||
|
Backup protetto root 0700:
|
||||||
|
`/srv/thothii-v2/backups/20260926-coordinated-release`.
|
||||||
|
Completato e **VERIFIED alle 19:31:57**, circa **2,89 GiB**, **23 checksum**,
|
||||||
|
archivi tar leggibili e indici dei dump verificati. Non è una prova di restore.
|
||||||
|
|
||||||
|
Include configurazioni/CLI/generated, sorgenti e Git con file locali,
|
||||||
|
immagini precedenti, bind data/registry/Evidence/Pi/segreti, volumi
|
||||||
|
catalogo/Qdrant/Ollama/static/media, dump catalogo e dump PostgreSQL condiviso.
|
||||||
|
Il DB condiviso è rimasto operativo: il suo dump è una snapshot transazionale,
|
||||||
|
non un backup raw del database fermo. Il volume raw del catalogo ThothII è stato
|
||||||
|
archiviato a servizio fermo. Nessun restore dati eseguito.
|
||||||
|
|
||||||
|
Cronologia Europe/Rome:
|
||||||
|
|
||||||
|
- 19:28: controllo del piano approvato positivo; riserva 20,9 GiB, liberi 27,8 GiB.
|
||||||
|
- 19:29:21: configurazione di rollback salvata e verificata prima delle mutazioni.
|
||||||
|
- 19:29:42: maintenance e chiusura nginx Omics; due controlli Pi negativi.
|
||||||
|
- 19:30:03: applicazioni ferme; dump, fermo supporti e archiviazione dati.
|
||||||
|
- 19:31:57: backup verificato.
|
||||||
|
- 19:32:10: deploy avviato; core 19:32:17, frontend 19:32:23,
|
||||||
|
web Omics 19:32:29, nginx 19:32:36.
|
||||||
|
- 19:35:27: accettazione automatica completata e maintenance disattivata.
|
||||||
|
|
||||||
|
Il periodo tra chiusura e riavvio nginx è stato circa tre minuti; le nuove
|
||||||
|
ammissioni sessione sono rimaste bloccate fino al completamento dei controlli.
|
||||||
|
|
||||||
|
## Correzione del controllo durante il rilascio
|
||||||
|
|
||||||
|
L’accettazione iniziale si è fermata su un falso negativo nello script:
|
||||||
|
`config.js` invia due header `Cache-Control`, `no-cache` e `no-store`; il controllo
|
||||||
|
leggeva solo il primo. Configurazione e risposta HTTP erano corrette.
|
||||||
|
|
||||||
|
Riproduzione isolata rossa, correzione di una riga con `get_all`, **16 test verdi**,
|
||||||
|
compreso il rifiuto quando `no-store` manca davvero. Nessuna modifica applicativa
|
||||||
|
necessaria. Maintenance mantenuta attiva fino alla ripetizione completa
|
||||||
|
dell’accettazione. Non sono stati ripetuti backup, fast-forward o ricreazione.
|
||||||
|
|
||||||
|
Directory script/evidenze:
|
||||||
|
`/srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/`.
|
||||||
|
|
||||||
|
- Script inizialmente approvato conservato in `release.approved.py`, SHA256
|
||||||
|
`eb2c677c8adbee0c9febf919001f654c8535e71f064d9fb7c7883afd02383a41`.
|
||||||
|
- Script corretto `release.py`, SHA256
|
||||||
|
`20314e68a6a42701456d454d2a0881652cfdbe5e00e9a912a22df9e78129aa00`.
|
||||||
|
- Test di regressione: `test_release_reviewed.py`, `reviewed-tests-cache-fix.log`.
|
||||||
|
- Stato finale filtrato: `deployed-evidence.json`; avanzamento nel
|
||||||
|
`journal.jsonl` del backup. Manifest degli artefatti aggiornato, originale conservato.
|
||||||
|
|
||||||
|
## Accettazione automatica
|
||||||
|
|
||||||
|
| Verifica | Esito |
|
||||||
|
| --- | --- |
|
||||||
|
| Digest reali dei container, readiness, doctor | Positivi |
|
||||||
|
| Alias Docker | Univoci e risolti ai container attuali; manifest raggiungibile da Omics |
|
||||||
|
| API senza cookie e con principal falsificati | 403 su HTTP e HTTPS locale verificato |
|
||||||
|
| Bypass asset e traversal codificati | Negati; `/datamart-builder/assets/api/me` restituisce 404 |
|
||||||
|
| Config | 200, embedded e no-store su entrambi i percorsi |
|
||||||
|
| Asset | Tutti i file elencati dal manifest disponibili su HTTP/HTTPS |
|
||||||
|
| Esposizione core | Nessuna porta pubblicata sull’host |
|
||||||
|
| Modelli, Pi e credenziali | Hash invariati rispetto alla baseline |
|
||||||
|
| Documenti persistiti | 2 manifest sessione, 51 file sessione/artifact e 221 file workspace/Evidence confrontati col backup: nessuna differenza |
|
||||||
|
| Migrazioni e catalogo Omics | Nessuna migrazione pendente; catalogo Superset valido |
|
||||||
|
| Log startup | Zero occorrenze nelle categorie fatal/config/auth/permessi controllate; nessun contenuto sensibile riportato |
|
||||||
|
|
||||||
|
Le prove HTTPS usano la CA interna e risoluzione locale del nome pubblico;
|
||||||
|
non sostituiscono il collaudo dalla postazione esterna. Il controllo degli hash
|
||||||
|
riguarda i file elencati, non certifica da solo l’intera semantica degli archivi.
|
||||||
|
|
||||||
|
## Rollback disponibile
|
||||||
|
|
||||||
|
Usare lo script corretto, dopo controllo di eventuali sessioni Pi attive:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -n python3 /srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py rollback --window-confirmed
|
||||||
|
```
|
||||||
|
|
||||||
|
Il rollback previsto dalla finestra approvata ripristina CLI/config/proiezioni e
|
||||||
|
immagini ThothII precedenti, mantiene il fix proxy Omics, riavvia e verifica le
|
||||||
|
applicazioni. Conserva dati e volumi; nessun restore del DB condiviso, reset Git
|
||||||
|
o ritorno al nginx vulnerabile. Se l’utente ha avviato sessioni, prima salvarle e
|
||||||
|
fermarle. Il rollback non è stato necessario né eseguito durante questo rilascio.
|
||||||
|
|
||||||
|
## Collaudo browser — aggiornamento 27 settembre 2026
|
||||||
|
|
||||||
|
Conferme dell’utente:
|
||||||
|
|
||||||
|
- Omics → Datamart Builder si carica senza problemi, in risposta alla prova di
|
||||||
|
apertura senza secondo login.
|
||||||
|
- Il 27 settembre: «tutto bene, compreso l’avvio e l’interruzione di una sessione».
|
||||||
|
Nel contesto dei controlli richiesti, registrato esito positivo per IT/EN,
|
||||||
|
tema, fullscreen/Esc e per avvio/interruzione di una sessione.
|
||||||
|
- Successivamente, sempre il 27 settembre: «ho anche ripreso una sessione interrotta.
|
||||||
|
tutto ok». Confermata anche la ripresa riuscita; il ciclo funzionale
|
||||||
|
avvio → interruzione → ripresa è collaudato dall’utente.
|
||||||
|
|
||||||
|
Il collaudo funzionale richiesto ha esito positivo. Su richiesta dell’utente,
|
||||||
|
le verifiche estese sono trasferite a un’attività successiva nel
|
||||||
|
[handoff del 27 settembre](2026-09-27-server-acceptance-handoff.md): lingua
|
||||||
|
persistita, identità/ruoli, logout, origine delle scritture, amministrazione,
|
||||||
|
reload e HTTPS esterno. Il documento contiene passi, responsabili, risultati
|
||||||
|
attesi e registro delle prove; nessuno di questi casi è dichiarato già superato.
|
||||||
|
|
||||||
|
La [matrice di accettazione](../testing/authentication-manual-acceptance.md)
|
||||||
|
resta il riferimento. Nessuna ulteriore modifica ai servizi è stata eseguita
|
||||||
|
per registrare il collaudo o preparare l’handoff del 27 settembre.
|
||||||
@@ -0,0 +1,246 @@
|
|||||||
|
# Handoff — rilascio coordinato ThothII / Omics
|
||||||
|
|
||||||
|
**Rilasciato il 26 settembre 2026; accettazione automatica superata alle 19:35 Europe/Rome.**
|
||||||
|
Per riprendere, leggere il [report di esecuzione](2026-09-26-server-release-execution.md):
|
||||||
|
servizi avviati, maintenance inattiva, backup verificato e rollback disponibile.
|
||||||
|
La finestra era stata confermata esplicitamente dall’utente; non richiederla di
|
||||||
|
nuovo per completare il collaudo già autorizzato. Il 27 settembre l’utente ha
|
||||||
|
confermato accesso, controlli dell’interfaccia e avvio/interruzione/ripresa di una
|
||||||
|
sessione: collaudo funzionale positivo. Per le verifiche residue usare il
|
||||||
|
[nuovo handoff del 27 settembre](2026-09-27-server-acceptance-handoff.md), con
|
||||||
|
passi e registro delle prove. L’utente le ha affidate a un’attività successiva.
|
||||||
|
|
||||||
|
Usare lo script corretto documentato nel report: durante il rilascio è stata
|
||||||
|
corretta soltanto la lettura degli header Cache-Control ripetuti nel controllo.
|
||||||
|
Non rieseguire le fasi pre-deploy sullo stato già rilasciato.
|
||||||
|
|
||||||
|
## Snapshot storico della sospensione delle 17:40
|
||||||
|
|
||||||
|
Il resto di questo file conserva lo stato precedente alla ripresa e al rilascio.
|
||||||
|
Il report di esecuzione sostituisce le indicazioni operative e le attività residue
|
||||||
|
qui sotto; il [piano approvato](2026-09-26-server-release-plan.md) descrive le scelte.
|
||||||
|
|
||||||
|
## Prima azione alla ripresa
|
||||||
|
|
||||||
|
Leggere questo handoff, quindi `AGENTS.md`, `PROJECT_STATE.md`,
|
||||||
|
`docs/operations/server-codex-handoff.md`, `docs/install/authentication-upstream.md`
|
||||||
|
e `docs/testing/authentication-manual-acceptance.md`. Per l'inventario completo
|
||||||
|
e i digest delle immagini operative, leggere
|
||||||
|
`docs/reports/2026-09-26-server-release-preflight.md`.
|
||||||
|
Quel preflight è storico: la correzione proxy allora mancante è ora preparata e
|
||||||
|
testata **soltanto in isolamento**, come descritto sotto.
|
||||||
|
|
||||||
|
La prossima attività è **revisionare e completare lo script di rilascio in bozza**,
|
||||||
|
validare il piano senza mutazioni operative e presentarlo all'utente con backup
|
||||||
|
e rollback. Solo dopo la sua conferma eseguire le fasi operative e il collaudo.
|
||||||
|
|
||||||
|
## Richiesta dell'utente e confini
|
||||||
|
|
||||||
|
- Aggiornare ThothII e Omics secondo il runbook, preservando dati, workspace,
|
||||||
|
Pi, provider, modelli e credenziali già presenti sul server.
|
||||||
|
- Usare main ThothII includente `497ab84031e285464fdbb73e6e0ce9252687e3ab`;
|
||||||
|
conservare i progressi server Omics successivi alla consegna GitHub `fca10901…`.
|
||||||
|
- Conservare checkout sporchi e file locali. Nessun reset, force push, rimozione
|
||||||
|
volumi o `tht setup --complete`; non usare `codex/guided-standalone-install`.
|
||||||
|
- L'utente ha autorizzato preparazione, correzione e test isolati. Prima del
|
||||||
|
fermo/proxy/migrazioni/recreate operativi vuole vedere il piano risolto e
|
||||||
|
confermare la finestra. Il suo «procediamo, fai la tua parte» ha avviato la
|
||||||
|
preparazione, non approvato uno script ancora inesistente/incompleto.
|
||||||
|
- L'utente può fare il collaudo da browser: avvisarlo quando sarà il momento
|
||||||
|
e fornire prove precise. Non chiedergli password in chat.
|
||||||
|
- Ha autorizzato a cercare credenziali di `akadmin` / `mpancotti`: trovata solo
|
||||||
|
la presenza di `AUTHENTIK_BOOTSTRAP_PASSWORD` in
|
||||||
|
`/home/chirone/chirone-authentik/docker/.env`. Valore non mostrato, non copiato,
|
||||||
|
**nessun login tentato e validità attuale non verificata**. Nessuna password
|
||||||
|
mpancotti trovata. I due utenti sono locali Authentik, non LDAP.
|
||||||
|
|
||||||
|
## Stato operativo, invariato
|
||||||
|
|
||||||
|
- Checkout di lavoro `/home/chirone/Thoth`: main `497ab840…`, allineata Gitea;
|
||||||
|
il report `2026-09-14-server-embedded-omics-release.md` era già non tracciato.
|
||||||
|
Sono stati aggiunti solo i report locali di questa attività.
|
||||||
|
- Checkout ThothII operativo `/srv/thothii-v2/source/ThothII`: main
|
||||||
|
`b1723c34c467980d007094af078d966d460cde2b`, 30 file modificati + due non tracciati,
|
||||||
|
preservato integralmente. Le modifiche sono già recepite dalla nuova main,
|
||||||
|
che contiene anche le correzioni successive.
|
||||||
|
- Omics operativo `/home/chirone/omics_portal`: master pulito
|
||||||
|
`1cf7ea90a669a26bf3bc51749eab4d07981da472`. Comprende la consegna shell GitHub
|
||||||
|
`fca10901a73666ca257d8f4cc4b77066295c400a` e la correzione Superset successiva.
|
||||||
|
**Non ripetere l'integrazione e non tornare a fca10901.**
|
||||||
|
- Core ancora `thothii-v2-core:49333a2d-session-memory-fix`; frontend ancora
|
||||||
|
`thothii-v2-frontend:b1723c34-session-dialogs-20260914`; Omics web ancora
|
||||||
|
`omics_portal-web` image ID `sha256:27aa100690b110bf596322b1b0a31acc178ca9d1c709bc10382cbeecbfb5aeca`.
|
||||||
|
- Ultimo controllo: zero processi Pi RPC, maintenance `active=false`, admissions 0.
|
||||||
|
Ricontrollare alla ripresa e prima del fermo.
|
||||||
|
- Backup nuovo `/srv/thothii-v2/backups/20260926-coordinated-release` **non esiste**.
|
||||||
|
Backup storico 14 settembre verificato (14 checksum, tar e indici dump), non
|
||||||
|
un backup dello stato odierno, nessuna prova di restore eseguita.
|
||||||
|
|
||||||
|
## Installazione e preservazione comprovata
|
||||||
|
|
||||||
|
Descrittore effettivo, il cui **percorso va mantenuto** per preservare project identity:
|
||||||
|
`/srv/thothii-v2/source/ThothII/deploy/psd-server-v2/thothii-installation.yaml`.
|
||||||
|
Project `thothii-7f901b48fe35`, schema 2, profile server, embedded/en/omics-portal,
|
||||||
|
upstream, session storage local, `THOTH_PUBLIC_EXPOSURE=false` già preesistente.
|
||||||
|
Non cambiare modalità auth o disattivare controlli per far partire l'app.
|
||||||
|
|
||||||
|
Preservati e confrontati:
|
||||||
|
|
||||||
|
- default interaction `zai/glm-5.3`;
|
||||||
|
- `deepseek/deepseek-v4-pro`, `deepseek/deepseek-v4-flash`;
|
||||||
|
- `local-qwen/qwen3.6-35b-a3b`;
|
||||||
|
- embedding `ollama/qwen3-embedding:0.6b`, dimensione 1024;
|
||||||
|
- `catalog.json`, `pi/models.json`, `pi/settings.json`, `frontend/config.js`:
|
||||||
|
proiezioni nuove **identiche byte per byte** a quelle operative;
|
||||||
|
- Compose candidato: environment, reti, porte, secret/config mount e mount
|
||||||
|
persistenti uguali. Solo due bind di script versionati identici cambiano
|
||||||
|
percorso seguendo il nuovo checkout (`catalog-db-init.sql`, `embedding-model-init.sh`).
|
||||||
|
|
||||||
|
Il CLI rifiuta correttamente i segreti se eseguito da UID diverso da 10001.
|
||||||
|
Per diagnostica usare UID 10001 con gruppi operator/Docker e DOCKER_CONFIG
|
||||||
|
leggibile; non cambiare ownership dei segreti. Esempio verificato:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -n setpriv --reuid=10001 --regid=10001 --groups=1014,988 \
|
||||||
|
env DOCKER_CONFIG=/srv/thothii-v2/operator/releases/20260926-coordinated/docker-config \
|
||||||
|
/usr/local/bin/tht \
|
||||||
|
--installation /srv/thothii-v2/source/ThothII/deploy/psd-server-v2/thothii-installation.yaml \
|
||||||
|
doctor --json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Correzione proxy pronta, non applicata
|
||||||
|
|
||||||
|
Il proxy operativo è ancora vulnerabile: senza cookie,
|
||||||
|
`/datamart-builder/assets/api/me` con header `X-Thoth-Trusted-*` inventati
|
||||||
|
restituisce 200 e principal sintetico. API canonica restituisce 403.
|
||||||
|
Confermato anche via nginx HTTPS host con CA verificata e DNS locale.
|
||||||
|
Il test ha usato un soggetto inesistente, nessun dato reale o scrittura.
|
||||||
|
|
||||||
|
Causa: il prefisso pubblico degli asset inoltra alla radice del frontend,
|
||||||
|
che espone `/api/` e converte gli header Trusted in principal del core.
|
||||||
|
|
||||||
|
Correzione candidata Omics:
|
||||||
|
|
||||||
|
- branch `codex/thothii-assets-proxy-isolation`;
|
||||||
|
- commit locale **`928f7e9fff2aba895416776fecf5668ee957d237`**;
|
||||||
|
- parte da `1cf7ea90…`, nessun push eseguito;
|
||||||
|
- checkout stabile pulito:
|
||||||
|
`/srv/thothii-v2/releases/omics-928f7e9fff2aba895416776fecf5668ee957d237`;
|
||||||
|
- clone di lavoro: `/tmp/thothii-release-20260926/omics-source`;
|
||||||
|
- sei file cambiati: nginx, test statico, tre file di test dinamico, docs integrazione.
|
||||||
|
|
||||||
|
Il filtro accetta solo file Vite con hash ed estensioni previste, alla radice
|
||||||
|
o sotto `assets/` per compatibilità. Le route pubbliche config/asset rimuovono
|
||||||
|
Cookie, Authorization e tutte le famiglie di header identità; solo GET/HEAD.
|
||||||
|
Il frontend attuale emette file alla **radice**, non tutti in `assets/`:
|
||||||
|
il primo filtro eccessivamente stretto è stato corretto grazie al test reale.
|
||||||
|
|
||||||
|
Test completati:
|
||||||
|
|
||||||
|
- test dinamico nuovo riproduceva il difetto prima della correzione;
|
||||||
|
- **6/6** test della catena nginx Omics → nginx frontend reale → core/Django
|
||||||
|
sintetici, rete Docker interna, senza porte host o volumi operativi;
|
||||||
|
- verificati traversal codificati, canonical auth, Origin esatta, config,
|
||||||
|
tutti i file del manifest reale, diniego scritture alle route statiche;
|
||||||
|
- gli stessi **6/6** passano anche con l'immagine frontend precedente:
|
||||||
|
il rollback può e deve mantenere la correzione del proxy;
|
||||||
|
- suite Omics shell/auth/nginx/Superset **28/28** dopo la modifica;
|
||||||
|
- nessun container/rete `omics-proxy-check-*` rimasto al momento della sospensione.
|
||||||
|
|
||||||
|
Esecuzione test ripetibile, solo se necessaria per nuove modifiche:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /srv/thothii-v2/releases/omics-928f7e9fff2aba895416776fecf5668ee957d237
|
||||||
|
THOTHII_TEST_FRONTEND_IMAGE=thothii-v2-frontend:497ab840-preflight \
|
||||||
|
OMICS_TEST_IMAGE=omics-portal:proxy-isolation-tests \
|
||||||
|
OMICS_TEST_NGINX_IMAGE=sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14 \
|
||||||
|
python3 test_support/thothii/run_proxy_integration.py
|
||||||
|
```
|
||||||
|
|
||||||
|
## Artefatti pronti e bozza da revisionare
|
||||||
|
|
||||||
|
Directory stabile: `/srv/thothii-v2/operator/releases/20260926-coordinated`.
|
||||||
|
Contiene:
|
||||||
|
|
||||||
|
- `descriptor.next.yaml`: cambia soltanto projectDirectory verso la nuova main
|
||||||
|
e il percorso del suo overlay git-ssh; modelCatalog/auth/shell/workspace invariati.
|
||||||
|
- `operator.next.env`: cambia soltanto tag immagini in `497ab840-preflight`.
|
||||||
|
- `compose.portal-upstream.next.yaml`: aggiorna anche il tag frontend letterale,
|
||||||
|
che non seguiva la variabile del core.
|
||||||
|
- `baseline.json`: hash protetti dei file operativi per rilevare drift prima
|
||||||
|
della finestra; non contiene valori segreti.
|
||||||
|
- `compose-preservation.json`: esito positivo del confronto Compose candidato.
|
||||||
|
- `tht.next`: nuovo binario non installato; SHA256
|
||||||
|
`0d39a93fb0a3b2147541a746c75832db20302f3a604bf6510da69d3731bcd783`.
|
||||||
|
- `nginx.safe.conf`: copia della configurazione candidata testata.
|
||||||
|
- `proxy-green.log`, `proxy-rollback-test.log`, `omics-proxy-tests.log`.
|
||||||
|
- **`release.DRAFT.py`**: bozza appena scritta, **non revisionata, non compilata,
|
||||||
|
non eseguita neppure in modalità check**. Non lanciarla prima di una revisione
|
||||||
|
completa e della conferma della finestra per le fasi mutanti.
|
||||||
|
|
||||||
|
Originale della bozza: `/tmp/thothii-release-20260926/release.py`.
|
||||||
|
Non trattare il flag `--window-confirmed` come un'approvazione dell'utente.
|
||||||
|
|
||||||
|
Sorgenti ThothII pronti, main pulita e fetch Gitea con divergenza 0/0:
|
||||||
|
`/srv/thothii-v2/releases/497ab84031e285464fdbb73e6e0ce9252687e3ab`.
|
||||||
|
Vecchio checkout dirty lasciato al suo posto per rollback.
|
||||||
|
|
||||||
|
Immagini candidate già costruite, non distribuite:
|
||||||
|
|
||||||
|
- core `thothii-v2-core:497ab840-preflight`,
|
||||||
|
`sha256:182f4e0d63404cb7ed6a0e272441e9c55ed27e2bb16fdbf4d7162f892ac76dc7`;
|
||||||
|
- frontend `thothii-v2-frontend:497ab840-preflight`,
|
||||||
|
`sha256:5f5a4f81139432d0ac41025c3006edaf1258b623ce388242700b1b20fcce6421`.
|
||||||
|
|
||||||
|
Test ThothII già superati: 782 frontend, 152 backend su Node 24.16, 31 browser,
|
||||||
|
build/typecheck core/frontend, build CLI e generazione isolata, doctor attuale 13/13.
|
||||||
|
Log in `/tmp/thothii-release-20260926`. La sottodirectory `generation` contiene
|
||||||
|
copie sensibili protette root:root 0600 sotto directory 0700: non pubblicarla.
|
||||||
|
|
||||||
|
## Lavoro residuo e criteri per avanzare
|
||||||
|
|
||||||
|
1. **Revalidare solo ciò che può essere cambiato** durante la pausa: immagini,
|
||||||
|
SHA/stato checkout operativo, configurazioni contro baseline, processi Pi,
|
||||||
|
migrazioni Omics pendenti e raggiungibilità. Se c'è drift, preservarlo e
|
||||||
|
aggiornare il piano prima di proseguire.
|
||||||
|
2. **Revisionare lo script DRAFT**, inclusi escaping del controllo processi Pi,
|
||||||
|
gestione errori/parzialità backup, health/readiness reale Omics (il suo
|
||||||
|
healthcheck verifica solo catalogo, non Gunicorn), generazione con UID corretto,
|
||||||
|
digest image vs container, conservazione proprietari e dati, rollout/rollback
|
||||||
|
della correzione proxy. Validare sintassi e fase read-only solo dopo revisione.
|
||||||
|
Aggiungere prove HTTPS locali, risoluzione alias dopo recreate e controllo
|
||||||
|
log redatto: la bozza non copre ancora integralmente il runbook.
|
||||||
|
3. **Finalizzare scelta lifecycle Omics.** La bozza mantiene l'esatta immagine
|
||||||
|
web operativa perché l'unica modifica applicabile è nginx (shell/Superset
|
||||||
|
già presenti); fa fast-forward del checkout al fix, stop/start web per backup
|
||||||
|
consistente e recreate nginx. Lo start riesegue il suo entrypoint, compresi
|
||||||
|
migrate/compilemessages/collectstatic. Spiegare questa scelta nel piano finale.
|
||||||
|
Se si decide di ricostruire web, il suo `.dockerignore` è minimale: creare un
|
||||||
|
contesto pulito, aggiungere il catalogo Superset reale valido, escludere segreti.
|
||||||
|
4. **Finalizzare backup odierno.** La bozza salva immagini/code/config, ferma
|
||||||
|
ingressi e applicativi dopo maintenance e controllo Pi, crea dump catalogo
|
||||||
|
e PostgreSQL Omics condiviso, ferma supporti ThothII per snapshot raw coerenti,
|
||||||
|
archivia bind/volumi e verifica checksum/tar/indici dump. Valutare spazio e
|
||||||
|
interruzioni; il vecchio backup verificato non basta. Il DB Omics è condiviso
|
||||||
|
(`postgres` su `supabase-db`, app in `kokoro`, metadata in `chirone_meta`):
|
||||||
|
un restore dell'intero DB non fa parte del rollback ordinario.
|
||||||
|
5. **Presentare piano risolto, comandi, backup e rollback all'utente**, chiedendo
|
||||||
|
conferma della finestra. Solo allora installare CLI/config, generare proiezioni,
|
||||||
|
ricreare le app e applicare nginx. Nessuna migrazione nuova rilevata finora.
|
||||||
|
6. **Collaudare e poi coinvolgere l'utente.** Login unico, `/me` e ruoli,
|
||||||
|
IT/EN, tema/fullscreen, logout/seconda scheda, sessione fittizia con Pi/SSE,
|
||||||
|
stop/save/ripresa e lingua immutabile, diniego cross-origin autenticato,
|
||||||
|
Database/Memory/Evidence e accesso HTTPS da postazione esterna.
|
||||||
|
|
||||||
|
Rollback: ripristinare immagini ThothII, CLI, descriptor/env/override e
|
||||||
|
proiezioni salvati; preservare dati e **mantenere il fix proxy**, già testato
|
||||||
|
col frontend precedente. Ripristinare il vecchio nginx riaprirebbe il bypass.
|
||||||
|
Nessun restore dati automatico, reset Git o eliminazione volumi.
|
||||||
|
|
||||||
|
## Ambiente strumenti
|
||||||
|
|
||||||
|
La sandbox exec fallisce prima dell'avvio (`bwrap: loopback … Operation not
|
||||||
|
permitted`): i comandi sono stati eseguiti con `require_escalated` e motivazione.
|
||||||
|
Auto-review li ha consentiti; nessun rifiuto pendente. Non sono stati usati
|
||||||
|
subagenti. Skill applicate: `diagnosing-bugs`, `writing-for-agents` per questo handoff.
|
||||||
|
Nessun goal formale attivo. Per lo stato successivo alla ripresa, usare il piano revisionato collegato in apertura.
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# Piano eseguibile — rilascio coordinato ThothII / Omics
|
||||||
|
|
||||||
|
Data: 26 settembre 2026. Ripresa del [passaggio di consegne](2026-09-26-server-release-handoff.md).
|
||||||
|
**Piano approvato dall’utente; esecuzione avviata il 26 settembre 2026 alle 19:28 Europe/Rome.**
|
||||||
|
Stato operativo e risultati successivi nel [report di esecuzione](2026-09-26-server-release-execution.md).
|
||||||
|
Il testo seguente registra la preparazione precedente alla conferma.
|
||||||
|
Nessun fermo, modifica di configurazione operativa, migrazione, ricreazione,
|
||||||
|
login di prova o cambio credenziali eseguito durante questa ripresa.
|
||||||
|
|
||||||
|
## Risultato proposto
|
||||||
|
|
||||||
|
- ThothII: distribuire core/frontend già costruiti dalla main
|
||||||
|
`497ab84031e285464fdbb73e6e0ce9252687e3ab`, conservando percorso del descrittore,
|
||||||
|
project identity, dati e configurazione server.
|
||||||
|
- Omics: fast-forward da `1cf7ea90a669a26bf3bc51749eab4d07981da472` al commit locale
|
||||||
|
`928f7e9fff2aba895416776fecf5668ee957d237`, che aggiunge il filtro proxy degli asset.
|
||||||
|
Conservare la stessa immagine e lo stesso container web: shell embedded e fix
|
||||||
|
Superset sono già operativi. Riavviare web dopo il backup e ricreare soltanto
|
||||||
|
nginx Omics, fissandone l'immagine all'ID esistente.
|
||||||
|
- Mantenere il fix proxy anche nel rollback: la configurazione precedente consente
|
||||||
|
il bypass documentato nell'handoff e non deve essere ripristinata.
|
||||||
|
|
||||||
|
L'entrypoint web rieseguirà `makemigrations`, `migrate`, controllo superuser,
|
||||||
|
`compilemessages` e `collectstatic`. Verificati `makemigrations --check --dry-run`
|
||||||
|
e `migrate --check`: nessuna modifica o migrazione pendente. L'utente che lo
|
||||||
|
script creerebbe automaticamente esiste già. Questi controlli saranno ripetuti
|
||||||
|
prima del fermo. Nessuna nuova migrazione di catalogo, Memory o sessioni emerge
|
||||||
|
anche dal confronto ThothII `49333a2d..497ab840`; nessun job di migrazione è previsto.
|
||||||
|
|
||||||
|
## Rivalidazione alla ripresa
|
||||||
|
|
||||||
|
| Controllo | Esito |
|
||||||
|
| --- | --- |
|
||||||
|
| Immagini/container operativi | Stessi ID e date di avvio registrati nell'handoff |
|
||||||
|
| Baseline descriptor/env/override/Pi/modelli/segreti | Tutti gli hash invariati |
|
||||||
|
| Checkout ThothII candidato e Omics candidato | SHA attesi, puliti |
|
||||||
|
| Checkout ThothII operativo | Sempre dirty; preservato, 30 modifiche e due file non tracciati |
|
||||||
|
| Checkout Omics operativo | Tracciati invariati; nuovi file locali sotto `docs/prd/.claude/`, preservati |
|
||||||
|
| Checkout di lavoro ThothII | Nuova directory locale `.claude/`, estranea al rilascio e preservata |
|
||||||
|
| Pi RPC | Zero processi, rilevamento effettivo in `/proc` |
|
||||||
|
| Maintenance | Inattiva; il contatore `admissions` del CLI è locale a quel processo e non certifica il drenaggio del server |
|
||||||
|
| Doctor | Positivo con UID 10001 e gruppi operator/Docker |
|
||||||
|
| Omics | Gunicorn/Django rispondono; catalogo Superset valido; nessuna migrazione pendente |
|
||||||
|
| HTTPS locale | Certificato verificato con CA interna e risoluzione del nome a 127.0.0.1; config 200, API anonima 403 |
|
||||||
|
| Alias Docker | Univoci; nginx risolve core/frontend/web; Omics legge il manifest |
|
||||||
|
| Compose candidato | Environment, reti, porte, mount persistenti/segreti invariati; cambiano immagini, contesti build e due script con contenuto identico |
|
||||||
|
| Descrittore candidato | Cambiano solo `projectDirectory` e il percorso dell'overlay git-ssh |
|
||||||
|
| Spazio | 27,8 GiB liberi; stima non compressa 12,6 GiB; riserva richiesta 20,9 GiB |
|
||||||
|
|
||||||
|
Il bypass asset operativo non è stato ritestato in questa ripresa: resta quello
|
||||||
|
accertato nell'handoff; il fix resta non distribuito. Le prove HTTPS locali non
|
||||||
|
sostituiscono l'accesso da una postazione esterna o un login reale.
|
||||||
|
|
||||||
|
## Script revisionato e verifiche
|
||||||
|
|
||||||
|
Percorso definitivo di preparazione:
|
||||||
|
`/srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py`.
|
||||||
|
SHA256: `eb2c677c8adbee0c9febf919001f654c8535e71f064d9fb7c7883afd02383a41`.
|
||||||
|
La precedente `release.DRAFT.py` resta conservata e non va eseguita.
|
||||||
|
|
||||||
|
Correzioni principali:
|
||||||
|
|
||||||
|
- Parsing NUL degli argomenti Pi, rilevamento `--mode rpc` e `--mode=rpc`, esclusione
|
||||||
|
del processo di controllo; test reale in container isolato.
|
||||||
|
- Gate espliciti anche con Python ottimizzato; lock tra esecuzioni; controllo
|
||||||
|
dei digest dei tag, dei container e degli artefatti preparati.
|
||||||
|
- Baseline estesa a CLI, configurazione Omics, CA/proxy host e file locali.
|
||||||
|
- Checksum dedicati della configurazione di rollback, creati prima delle mutazioni;
|
||||||
|
journal delle fasi, file parziali conservati e nessun marker VERIFIED su errore.
|
||||||
|
- Preservazione proprietari/permessi, `.git`, file ignorati/non tracciati, ACL/xattr
|
||||||
|
negli archivi. Solo cache dipendenze ricostruibili escluse.
|
||||||
|
- Readiness HTTP di Omics, alias dopo ricreazione, controlli HTTPS con CA,
|
||||||
|
tutti gli asset del manifest e riepilogo log per categorie senza contenuti sensibili.
|
||||||
|
- Recupero `reopen` per rendere nuovamente raggiungibile una sessione Pi comparsa
|
||||||
|
durante il drenaggio: riapre solo nginx con il fix, senza fermare web/core/Pi.
|
||||||
|
|
||||||
|
Validazione: sintassi Python, **14 test isolati**, fase `check` read-only positiva.
|
||||||
|
I test coprono anche conferma mancante, backup parziale/corrotto, checksum con
|
||||||
|
path traversal, ownership, readiness HTTP e recupero senza stop di Pi.
|
||||||
|
Le fasi mutanti non sono state eseguite né rappresentano un restore provato.
|
||||||
|
|
||||||
|
Evidenze in `/srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/`:
|
||||||
|
`reviewed-tests.log`, `reviewed-check.log`, script e test; manifest protetti
|
||||||
|
`artifacts.json`, `baseline-extra.json`, `source-state.json`.
|
||||||
|
Restano valide le prove precedenti: 6/6 proxy con ciascun frontend nuovo/vecchio,
|
||||||
|
28/28 Omics, 782 frontend, 152 backend e 31 browser; nessuna modifica a quelle
|
||||||
|
implementazioni durante questa ripresa.
|
||||||
|
|
||||||
|
## Comandi risolti per la finestra
|
||||||
|
|
||||||
|
Riservare indicativamente **30–45 minuti**, da confermare dall'operatore: la durata
|
||||||
|
reale dipende soprattutto dal dump del database condiviso. L'interruzione interessa
|
||||||
|
Omics e ThothII; non vengono fermati Authentik, il database condiviso o il DWH.
|
||||||
|
La prima parte del backup (codice/config/immagini) avviene con le app ancora attive.
|
||||||
|
|
||||||
|
Eseguire ciascun comando solo dopo exit 0 del precedente, nella finestra approvata:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -n python3 /srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py check
|
||||||
|
sudo -n python3 /srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py backup --window-confirmed
|
||||||
|
sudo -n python3 /srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py deploy --window-confirmed
|
||||||
|
```
|
||||||
|
|
||||||
|
`--window-confirmed` registra l'intenzione del comando, **non sostituisce il consenso**.
|
||||||
|
Lo script contiene tutti i percorsi/ID e l'ordine Compose risolti; non usa pull,
|
||||||
|
build implicite, setup completo, reset o cancellazione volumi.
|
||||||
|
|
||||||
|
Sequenza concreta:
|
||||||
|
|
||||||
|
1. Rivalidare baseline, assenza Pi e spazio. Salvare e verificare configurazioni,
|
||||||
|
CLI, sorgenti e immagini correnti.
|
||||||
|
2. Attivare maintenance, chiudere nginx Omics, attendere e controllare due volte
|
||||||
|
Pi. In caso di sessioni attive fermare la procedura senza ucciderle.
|
||||||
|
3. Fermare Omics web/core/frontend, creare i dump, fermare i soli supporti ThothII,
|
||||||
|
archiviare bind e volumi. Verificare checksum, lettura tar e indici dump.
|
||||||
|
4. Solo con backup VERIFIED: fast-forward Omics; aggiornare descriptor/env/overlay;
|
||||||
|
installare CLI verificato e generare proiezioni con UID 10001. Controllare che
|
||||||
|
modelli, Pi, shell e credenziali restino identici.
|
||||||
|
5. Riavviare supporti; ricreare core/frontend con stesso progetto
|
||||||
|
`thothii-7f901b48fe35`; avviare lo stesso web Omics; ricreare nginx col fix e
|
||||||
|
immagine fissata. `--no-build --pull never --no-deps` limita il lifecycle.
|
||||||
|
6. Verificare health/HTTP, DNS, `nginx -t`, attendere 31 secondi, eseguire prove
|
||||||
|
automatiche HTTP/HTTPS e log. Disattivare maintenance solo dopo esito positivo.
|
||||||
|
|
||||||
|
## Backup e gestione delle interruzioni
|
||||||
|
|
||||||
|
Destinazione nuova, protetta root 0700:
|
||||||
|
`/srv/thothii-v2/backups/20260926-coordinated-release`.
|
||||||
|
**Non esiste ancora**: verrà creata nella finestra. Se esiste già, lo script si
|
||||||
|
ferma senza riutilizzare o cancellare il contenuto.
|
||||||
|
|
||||||
|
Contiene CLI/descriptor/env/override/generated, sorgenti e Git, configurazioni
|
||||||
|
Omics e proxy, immagini per ID, bind data/registry/Evidence/Pi/segreti,
|
||||||
|
volumi catalogo/Qdrant/Ollama/static/media, dump catalogo e dump PostgreSQL condiviso.
|
||||||
|
Il dump condiviso è una snapshot transazionale coerente mentre gli altri servizi
|
||||||
|
che usano quel DB continuano a operare; non è un backup raw a database fermo.
|
||||||
|
Il volume raw del catalogo ThothII viene copiato solo dopo averlo fermato.
|
||||||
|
|
||||||
|
Su errore: niente retry cieco né prosecuzione verso deploy. Leggere journal e stato
|
||||||
|
container. Prima di una mutazione ai servizi, questi restano operativi; dopo la
|
||||||
|
quiescenza possono rimanere fermi. Il manifest `rollback-config.json` permette
|
||||||
|
il rollback applicativo anche quando il backup dati è incompleto. Nessun restore
|
||||||
|
automatico dei dati; nessuna prova di restore dichiarata.
|
||||||
|
|
||||||
|
Se Pi compare dopo chiusura ingressi e prima del fermo applicativo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -n python3 /srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py reopen --window-confirmed
|
||||||
|
```
|
||||||
|
|
||||||
|
Questo applica il solo proxy sicuro, mantiene le applicazioni e Pi accesi e lascia
|
||||||
|
maintenance attiva: l'utente può salvare/fermare la sessione. La procedura si arresta
|
||||||
|
poi per rivalutare backup parziale e baseline; non tenta automaticamente un nuovo
|
||||||
|
backup o deploy.
|
||||||
|
|
||||||
|
## Rollback applicativo
|
||||||
|
|
||||||
|
Se la nuova applicazione o i controlli falliscono, e non ci sono Pi da salvare:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo -n python3 /srv/thothii-v2/operator/releases/20260926-coordinated/reviewed/release.py rollback --window-confirmed
|
||||||
|
```
|
||||||
|
|
||||||
|
Ripristina configurazioni/CLI/generated e immagini core/frontend precedenti,
|
||||||
|
riavvia lo stesso web Omics, mantiene il commit e il proxy corretto, quindi ripete
|
||||||
|
il collaudo automatico. Ripristina UID/GID/mode originali. Non sovrascrive dati,
|
||||||
|
non ripristina l'intero DB condiviso e non torna al nginx vulnerabile. Non fa reset
|
||||||
|
Git. Rifiuta di interrompere Pi attivi. Dopo un backup parziale conserva gli
|
||||||
|
artefatti per analisi: non li presenta come backup completo.
|
||||||
|
|
||||||
|
## Collaudo dell'operatore dopo il rilascio
|
||||||
|
|
||||||
|
Avvisare l'utente quando i controlli automatici saranno verdi, poi verificare
|
||||||
|
con account autorizzati e dati fittizi:
|
||||||
|
|
||||||
|
1. Login unico Omics → Datamart Builder, `/me` con identità/ruoli corretti,
|
||||||
|
nessun secondo login; utente normale e admin coerenti.
|
||||||
|
2. IT/EN, tema, fullscreen/Esc e persistenza dopo reload.
|
||||||
|
3. Sessione di prova, eventi SSE, stop/save/ripresa e lingua immutabile.
|
||||||
|
4. Logout e seconda scheda; diniego cross-origin autenticato su risorse di prova.
|
||||||
|
5. Database/Memory/Evidence leggibili, layout previsto, HTTPS da client esterno.
|
||||||
|
|
||||||
|
Queste prove restano aperte e sono necessarie prima di dichiarare concluso il
|
||||||
|
rilascio, secondo la [matrice di accettazione](../testing/authentication-manual-acceptance.md).
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
# ThothII / Omics — preflight server del 26 settembre 2026
|
||||||
|
|
||||||
|
Stato: **rilascio fermo al gate di isolamento del proxy**. Nessuna finestra
|
||||||
|
richiesta o autorizzata; nessun servizio fermato, ricreato o aggiornato, nessuna
|
||||||
|
migrazione e nessuna modifica di proxy, descrittore, credenziali, DWH o IdP.
|
||||||
|
Questo documento è un inventario e piano parziale, **non un piano eseguibile
|
||||||
|
di rilascio approvato**. Applicare il runbook `docs/operations/server-codex-handoff.md`.
|
||||||
|
|
||||||
|
## Blocco verificato
|
||||||
|
|
||||||
|
Senza cookie/sessione Omics:
|
||||||
|
|
||||||
|
| Ingresso | Richiesta | Risultato |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| Nginx Omics, localhost:8080 con Host pubblico | `/datamart-builder/api/me` | 403 |
|
||||||
|
| Stesso ingresso, principal normalizzato inventato | `/datamart-builder/api/me` | 403 |
|
||||||
|
| Stesso ingresso, header `X-Thoth-Trusted-*` sintetici | `/datamart-builder/assets/api/me` | **200, JSON `/me` con identità sintetica e permesso** |
|
||||||
|
| Nginx TLS host, HTTPS con CA verificata e DNS locale | API canonica / percorso alternativo | 403 / **200** |
|
||||||
|
|
||||||
|
Il soggetto di prova era `release-probe-nonexistent`, con flag admin falso;
|
||||||
|
non sono stati usati utenti reali o richieste di scrittura. La risposta alternativa
|
||||||
|
conteneva issuer/subject, ruoli, permessi e session/CSRF null: non era il fallback HTML.
|
||||||
|
|
||||||
|
Causa circoscritta: la location pubblica `/datamart-builder/assets/` inoltra
|
||||||
|
qualsiasi suffisso alla radice del frontend. Il suffisso `api/me` raggiunge quindi
|
||||||
|
`/api/me` del frontend, che converte gli header Trusted in principal del core.
|
||||||
|
Quel percorso non attraversa `auth_request`. La configurazione Omics operativa e
|
||||||
|
quella della consegna mantengono questo percorso; la nuova immagine frontend
|
||||||
|
conserva l'endpoint `/api/`. Un aggiornamento di ThothII da solo non corregge il difetto.
|
||||||
|
|
||||||
|
Riproduzione non mutante, exit 1 sul difetto:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python3 /tmp/thothii-release-20260926/evidence/check-proxy.py
|
||||||
|
```
|
||||||
|
|
||||||
|
Serve una revisione candidata Omics del proxy che impedisca l'accesso alle API
|
||||||
|
attraverso gli asset e rimuova gli header di fiducia dai percorsi pubblici.
|
||||||
|
Va preparata dal codice server `1cf7ea90…`, collaudata in isolamento includendo
|
||||||
|
varianti dei percorsi, asset/manifest/config e dinieghi, quindi inclusa nel piano
|
||||||
|
da approvare **prima** del reload operativo. Nessuna correzione è stata applicata.
|
||||||
|
Non indebolire auth o Origin, né cambiare le identità degli utenti.
|
||||||
|
|
||||||
|
L'origine pubblica via DNS, dal server, va in timeout (HTTP 000, curl exit 28).
|
||||||
|
Il probe TLS con `--resolve …:443:127.0.0.1` è invece riuscito. Resta da verificare
|
||||||
|
il percorso completo dal client esterno/bilanciatore; non è attestato dal probe locale.
|
||||||
|
|
||||||
|
## Revisioni e conservazione delle modifiche
|
||||||
|
|
||||||
|
- Checkout di consegna `/home/chirone/Thoth`: branch `main`, HEAD e `origin/main`
|
||||||
|
`497ab84031e285464fdbb73e6e0ce9252687e3ab`, fetch Gitea eseguito, divergenza `0 0`;
|
||||||
|
entrambi gli ancestor richiesti (`497ab840…`, `0d2e573e`) presenti.
|
||||||
|
- All'inizio non era pulito: solo `docs/reports/2026-09-14-server-embedded-omics-release.md`
|
||||||
|
non tracciato. Quel file è stato conservato. Questo report è un ulteriore output locale.
|
||||||
|
- Copia pulita per test `/tmp/thothii-release-20260926/source`, branch `main`, stesso SHA;
|
||||||
|
clone locale senza hardlink e senza importare il report non tracciato.
|
||||||
|
- Checkout ThothII operativo `/srv/thothii-v2/source/ThothII`: branch `main`,
|
||||||
|
HEAD `b1723c34c467980d007094af078d966d460cde2b`, 30 file modificati e due file
|
||||||
|
non tracciati. Nessun aggiornamento/reset/stash eseguito in questo checkout.
|
||||||
|
Dei 32 file locali, 29 sono identici alla main approvata; le differenze negli
|
||||||
|
altri tre sono le nuove correzioni di main a `AppShell.tsx`, al suo test di
|
||||||
|
gestione sessioni e al test visuale dello scroll. Non occorre ricostruirle a mano.
|
||||||
|
- Omics `/home/chirone/omics_portal`: `master`, pulito e coincidente col riferimento
|
||||||
|
locale `origin/master`, HEAD `1cf7ea90a669a26bf3bc51749eab4d07981da472`.
|
||||||
|
Non è stato eseguito fetch di master: questa coincidenza non attesta il master remoto attuale.
|
||||||
|
- Fetch esplicito del branch GitHub `codex/thothii-embedded-shell`: esattamente
|
||||||
|
`fca10901a73666ca257d8f4cc4b77066295c400a`; contiene `95154e179144e2453b37ef2a63a65d6f377e4cf8`
|
||||||
|
ed è già antenato di HEAD Omics. **Non ripetere il merge e non tornare a fca10901.**
|
||||||
|
Il commit successivo corregge la risoluzione delle dashboard Superset rispetto
|
||||||
|
alla lingua. Gli 11 file verificati nel container (shell/auth e correzione
|
||||||
|
Superset) hanno hash uguali al checkout operativo.
|
||||||
|
- Il branch incompleto `codex/guided-standalone-install` non è stato usato;
|
||||||
|
`tht setup --complete` non è stato eseguito.
|
||||||
|
|
||||||
|
## Immagini effettivamente operative, non candidate
|
||||||
|
|
||||||
|
| Servizio | Tag | Image ID |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| core | `thothii-v2-core:49333a2d-session-memory-fix` | `sha256:ff4c435abd67c57e1e91e6e560dae73e67350ca499a5aedca3ffa517b9f59ee0` |
|
||||||
|
| frontend | `thothii-v2-frontend:b1723c34-session-dialogs-20260914` | `sha256:d2ed3dec42f8a56536ebbc8d74f13892d4c42c9a7f2fb67c476ff39f43fe7af9` |
|
||||||
|
| Omics web | `omics_portal-web` | `sha256:27aa100690b110bf596322b1b0a31acc178ca9d1c709bc10382cbeecbfb5aeca` |
|
||||||
|
| Omics nginx | `nginx:alpine` | `sha256:b3c656d55d7ad751196f21b7fd2e8d4da9cb430e32f646adcf92441b72f82b14` |
|
||||||
|
| catalog-db | PostgreSQL 17.6 bookworm | `sha256:f3bd19c606e442c3d7bdfa8002e03fe260a1023351e0ea4598032022b68dd6e3` |
|
||||||
|
| qdrant | v1.18.2 | `sha256:75eab8c4ba42096724fdcfde8b4de0b5713d529dde32f285a1f86fdcb2c9e50c` |
|
||||||
|
| embedding | Ollama 0.32.0 | `sha256:57f573b47f1f71ebb445789f279fe3e596a8beab182f7cf486db9205bad87c5a` |
|
||||||
|
|
||||||
|
Il frontend dichiara revision `b1723c34-working-tree`; core e Omics non hanno
|
||||||
|
label OCI revision. Perciò lo SHA esatto del sorgente baked del core non può
|
||||||
|
essere certificato dalla sola immagine: tag, ID e checkout sono evidenze distinte.
|
||||||
|
CLI operativo `/usr/local/bin/tht`, binario root:root 0755; non sostituito.
|
||||||
|
|
||||||
|
## Installazione, Compose e persistenza
|
||||||
|
|
||||||
|
Descrittore invariato:
|
||||||
|
`/srv/thothii-v2/source/ThothII/deploy/psd-server-v2/thothii-installation.yaml`.
|
||||||
|
Schema 2, profile server, file 0600 owner UID/GID 10001, projectDirectory
|
||||||
|
`/srv/thothii-v2/source/ThothII`, envFile `/srv/thothii-v2/operator/operator.env`.
|
||||||
|
Shell già `embedded/en/omics-portal`. Project Compose `thothii-7f901b48fe35`.
|
||||||
|
Ordine dei file applicativi, ricavato dalle label dei container:
|
||||||
|
|
||||||
|
1. `/srv/thothii-v2/source/ThothII/compose.yaml`
|
||||||
|
2. `/srv/thothii-v2/source/ThothII/deploy/compose.server.yaml`
|
||||||
|
3. `/srv/thothii-v2/source/ThothII/deploy/compose.git-ssh.yaml`
|
||||||
|
4. `/srv/thothii-v2/operator/compose.portal-upstream.yaml`
|
||||||
|
5. `/srv/thothii-v2/source/ThothII/deploy/psd-server-v2/generated/compose.models.yaml`
|
||||||
|
|
||||||
|
I supporti sono stati creati con i primi quattro file. Il percorso del descrittore
|
||||||
|
determina l'identità Compose nel CLI: mantenerlo anche usando in futuro una
|
||||||
|
directory sorgente pulita distinta. Non spostare il descrittore in un nuovo checkout.
|
||||||
|
L'override contiene un tag frontend letterale: il solo cambio di
|
||||||
|
`THTII_RELEASE_IMAGE_TAG` non aggiorna entrambe le immagini.
|
||||||
|
|
||||||
|
Core: `AUTH_MODE=upstream`, `THT_AUTH_CONFIG_FILE=/run/thothii-auth/upstream-disabled.yaml`,
|
||||||
|
nessuno dei due file auth (`auth.yaml`, `upstream-disabled.yaml`) presente;
|
||||||
|
directory host `/srv/thothii-v2/operator/auth`, nessuna runtime auth projection.
|
||||||
|
`THOTH_PUBLIC_EXPOSURE=false`, `THT_SESSION_STORAGE=local`: configurazione
|
||||||
|
preesistente, non modificata. Non è una prova di isolamento: il gate proxy è fallito.
|
||||||
|
Se si decide di impostare public exposure true, serve prima un piano separato
|
||||||
|
per storage sessioni PostgreSQL; non attivare l'overlay come falsa migrazione automatica.
|
||||||
|
|
||||||
|
Bind e archivi:
|
||||||
|
|
||||||
|
- `/srv/thothii-v2/data` → `/data`: settings, sessioni, artifact, indici e workspace secrets.
|
||||||
|
- Sessioni PSD: `/data/sessions/psd-clinical/{sessions,artifacts,indexes,memory}`;
|
||||||
|
snapshot catalogo `/data/sessions/psd-clinical/preprocessing/catalog-metadata.json`.
|
||||||
|
- `/srv/thothii-v2/workspace-registry` → `/data/workspace-registry`; workspace
|
||||||
|
`psd-clinical`, installation ID `psd-server-v2`. Evidence local archive
|
||||||
|
`/data/workspace-registry/repo/psd-clinical`.
|
||||||
|
- `/srv/thothii-v2/pi-state` → `/home/thoth/.pi`; auth provider read-only
|
||||||
|
`/srv/thothii-v2/secrets/pi-auth.json` → `/home/thoth/.pi/agent/auth.json`.
|
||||||
|
- Bundle `/srv/thothii-v2/secrets/thothii.secrets`; chiavi workspace SSH,
|
||||||
|
known-hosts e password catalogo in `/srv/thothii-v2/secrets/`, valori mai riportati.
|
||||||
|
- Generated catalog/Pi/frontend sotto il descrittore; `config.js` montato read-only.
|
||||||
|
- Catalogo e Memory autorevoli PostgreSQL nel volume
|
||||||
|
`thothii-7f901b48fe35_catalog-data`; indici derivati
|
||||||
|
`thothii-7f901b48fe35_qdrant-data`; modelli `thothii-7f901b48fe35_embedding-models`.
|
||||||
|
- Binding DWH diretto già operativo verso `host.docker.internal:5438`, utente
|
||||||
|
read-only `thoth_dwh_reader`. Nessuna query DWH o sincronizzazione avviata.
|
||||||
|
|
||||||
|
Omics: project `omics_portal`, file ordinati
|
||||||
|
`/home/chirone/omics_portal/docker-compose.yml`,
|
||||||
|
`/home/chirone/omics_portal/docker-compose.override.yml`, env `.env.docker`.
|
||||||
|
Volumi `omics_portal_static_volume` e `omics_portal_media_volume`; mount CA
|
||||||
|
`/etc/nginx/ssl/policlinicosandonato.it.fullchain.crt` read-only.
|
||||||
|
Database portale: `supabase-db`, database `postgres`, search_path `kokoro,public`,
|
||||||
|
endpoint host 5438. Non confonderlo con il DWH o col catalogo ThothII.
|
||||||
|
Il server PostgreSQL è condiviso: un eventuale restore dell'intero database
|
||||||
|
non è un rollback ordinario di Omics e richiede un piano separato.
|
||||||
|
|
||||||
|
Reti: core su `thothii-7f901b48fe35_thothii`, `omics_portal_omics_network`
|
||||||
|
(alias `thothii-core`) e `localllm_default`; frontend su prime due reti (alias
|
||||||
|
`thothii-frontend`). Nessuna porta host core; frontend `127.0.0.1:18020`.
|
||||||
|
Omics web solo porta interna 8000; nginx `0.0.0.0:8080`. TLS host nginx su 443
|
||||||
|
per `https://aritmolab.policlinicosandonato.it`, poi localhost:8080.
|
||||||
|
File host `/etc/nginx/sites-available/policlinicosandonato`, collegato in sites-enabled;
|
||||||
|
SSE canonico con buffering disabilitato e timeout 86400 su entrambi gli nginx.
|
||||||
|
La mappa Origin esatta HTTPS→HTTP è presente. Il tratto esterno non è verificato.
|
||||||
|
|
||||||
|
Inventario JSON filtrato completo (label, mount, reti, porte):
|
||||||
|
`/tmp/thothii-release-20260926/inventory.json`.
|
||||||
|
|
||||||
|
## Verifiche eseguite e candidati
|
||||||
|
|
||||||
|
- ThothII frontend: **782/782** test, build/typecheck riusciti.
|
||||||
|
- Browser isolato: **31/31** scenari visuali Playwright riusciti. Il primo
|
||||||
|
tentativo non aveva il binario Chromium; installato soltanto nello staging
|
||||||
|
`/tmp/thothii-release-20260926/browsers`, quindi suite rieseguita con successo.
|
||||||
|
- Backend: build/typecheck riusciti; **152/152** test mirati su Node 24.16 in
|
||||||
|
container senza rete o dati operativi. I tentativi host Node 23 fallivano
|
||||||
|
per Argon2 non disponibile; i primi container di test avevano UID/mount
|
||||||
|
incompleti. Il risultato valido è `backend-node24-tests.log`.
|
||||||
|
- Omics shell/auth/nginx isolati: **15/15**; regressioni Superset: **12/12**,
|
||||||
|
entrambe le esecuzioni con `--network none`, SQLite in-memory, nessun volume operativo.
|
||||||
|
- Omics operativo: `migrate --check` exit 0, catalogo Superset valido (32 dashboard),
|
||||||
|
`nginx -t` exit 0. Warning allauth deprecati presenti.
|
||||||
|
- CLI corrente: status exit 0, doctor **13/13**, maintenance `active=false`, admissions 0.
|
||||||
|
Il primo tentativo con sudo/root era rifiutato dal controllo ownership dei segreti.
|
||||||
|
Con UID 10001 e gruppi 1014,988, più DOCKER_CONFIG leggibile, nessun errore:
|
||||||
|
non mancavano credenziali e non sono stati cambiati permessi.
|
||||||
|
- CLI aggiornato costruito in `/tmp/thothii-release-20260926/cli/tht-linux-amd64`;
|
||||||
|
generazione riuscita su copie root:root 0600 in directory 0700
|
||||||
|
`/tmp/thothii-release-20260926/generation` (contiene copie sensibili, non pubblicare).
|
||||||
|
Proiezione frontend `/api`, shell embedded/en/omics-portal corretta.
|
||||||
|
- Immagine core candidata `thothii-v2-core:497ab840-preflight`:
|
||||||
|
`sha256:182f4e0d63404cb7ed6a0e272441e9c55ed27e2bb16fdbf4d7162f892ac76dc7`.
|
||||||
|
- Immagine frontend candidata `thothii-v2-frontend:497ab840-preflight`:
|
||||||
|
`sha256:5f5a4f81139432d0ac41025c3006edaf1258b623ce388242700b1b20fcce6421`.
|
||||||
|
Entrambe portano la revision OCI `497ab84031e285464fdbb73e6e0ce9252687e3ab`.
|
||||||
|
**Costruite, non distribuite**. Non è stata costruita una nuova immagine Omics operativa.
|
||||||
|
|
||||||
|
Log dei test e build in `/tmp/thothii-release-20260926/`; log Omics
|
||||||
|
`/tmp/omics-release-tests-20260926.log` e `/tmp/omics-release-superset-tests-20260926.log`.
|
||||||
|
Log browser: `/tmp/thothii-release-20260926/browser-tests.log`.
|
||||||
|
|
||||||
|
## Backup e rollback: stato e vincoli
|
||||||
|
|
||||||
|
Backup storico `/srv/thothii-v2/backups/20260914-pre-embedded-release`:
|
||||||
|
directory root:root 0700, file 0600. Verificati **14 checksum**, leggibilità di
|
||||||
|
sette archivi tar.gz e indice dei due dump con `pg_restore --list`: tutto exit 0.
|
||||||
|
**Non è stata eseguita una prova di restore e non è un backup dello stato odierno.**
|
||||||
|
Contiene anche dati condivisi/sensibili: accesso protetto, nessun contenuto mostrato.
|
||||||
|
Altri backup presenti: `20260914-session-memory-fix`, `20260914-session-dialogs`,
|
||||||
|
`memory-evidence-20260910`; non attestati dai controlli del primo backup.
|
||||||
|
|
||||||
|
Il nuovo punto di rollback andrà creato nella finestra, dopo gestione delle
|
||||||
|
sessioni in corso e quiescenza delle scritture dei due applicativi. Percorso
|
||||||
|
previsto `/srv/thothii-v2/backups/20260926-coordinated-release` (non creato).
|
||||||
|
Deve includere:
|
||||||
|
|
||||||
|
1. Binario CLI, descriptor/env/override/generated, checkout operativo dirty
|
||||||
|
completo o bundle Git + patch + file non tracciati, configurazioni Omics,
|
||||||
|
catalogo Superset runtime e configurazione nginx host; proprietari/permessi preservati.
|
||||||
|
2. Immagini attuali core/frontend/web/nginx per ID e checksum dell'archivio.
|
||||||
|
3. Bind data, registry, Evidence, Pi, secrets/settings e volumi static/media Omics.
|
||||||
|
4. Dump coerente del catalogo e backup portale con ambito esplicito rispetto
|
||||||
|
al database PostgreSQL condiviso; snapshot Qdrant/Ollama e, se richiesto,
|
||||||
|
snapshot raw catalogo **solo a database fermo**. Non archiviare un PGDATA live
|
||||||
|
come se fosse un backup consistente.
|
||||||
|
5. SHA256SUMS, elenco integrale archivi senza errori, `pg_restore --list` e
|
||||||
|
restore isolato prima di eventuali migrazioni non reversibili.
|
||||||
|
|
||||||
|
Fra il riferimento operativo core `49333a2d` e la main approvata non risultano
|
||||||
|
nuove migrazioni catalogo/sessioni; Omics `migrate --check` non segnala pendenti.
|
||||||
|
Rivalutare dopo l'eventuale nuova revisione proxy: nessuna migrazione autorizzata ora.
|
||||||
|
L'entrypoint Omics esegue anche `makemigrations`, `migrate`, creazione superuser,
|
||||||
|
`compilemessages`, `collectstatic`: non usarlo come test preliminare su dati operativi.
|
||||||
|
Il `.dockerignore` Omics è minimale: preparare un contesto di build pulito che
|
||||||
|
includa il catalogo valido ed escluda env/backup/segreti prima della build operativa.
|
||||||
|
|
||||||
|
Rollback applicativo previsto: ripristino della coppia core/frontend e Omics
|
||||||
|
sopra registrata, del CLI e dei file di configurazione/proiezione salvati,
|
||||||
|
con gli stessi project name, bind e volumi; ricreazione mirata delle sole app,
|
||||||
|
`nginx -t`, aggiornamento DNS/reload del proxy e collaudo accesso/manifest/SSE.
|
||||||
|
Non fare downgrade dati, restore dell'intero Supabase o cancellazioni di volumi.
|
||||||
|
**Il ritorno alla vecchia configurazione proxy ripristinerebbe il bypass noto:**
|
||||||
|
il rollback approvato deve conservare una chiusura di sicurezza verificata,
|
||||||
|
oppure mantenere indisponibile Datamart Builder fino alla correzione.
|
||||||
|
|
||||||
|
## Comandi ricostruiti e piano da completare
|
||||||
|
|
||||||
|
Queste funzioni ricostruiscono il lifecycle corrente; non sono state usate per mutazioni:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
thoth_compose() {
|
||||||
|
sudo -n docker compose --project-name thothii-7f901b48fe35 \
|
||||||
|
--project-directory /srv/thothii-v2/source/ThothII \
|
||||||
|
--env-file /srv/thothii-v2/operator/operator.env \
|
||||||
|
-f /srv/thothii-v2/source/ThothII/compose.yaml \
|
||||||
|
-f /srv/thothii-v2/source/ThothII/deploy/compose.server.yaml \
|
||||||
|
-f /srv/thothii-v2/source/ThothII/deploy/compose.git-ssh.yaml \
|
||||||
|
-f /srv/thothii-v2/operator/compose.portal-upstream.yaml \
|
||||||
|
-f /srv/thothii-v2/source/ThothII/deploy/psd-server-v2/generated/compose.models.yaml "$@"
|
||||||
|
}
|
||||||
|
omics_compose() {
|
||||||
|
docker compose --project-name omics_portal \
|
||||||
|
--project-directory /home/chirone/omics_portal \
|
||||||
|
-f /home/chirone/omics_portal/docker-compose.yml \
|
||||||
|
-f /home/chirone/omics_portal/docker-compose.override.yml "$@"
|
||||||
|
}
|
||||||
|
# Sola diagnostica, con identità del proprietario dei file protetti:
|
||||||
|
sudo -n setpriv --reuid=10001 --regid=10001 --groups=1014,988 \
|
||||||
|
env DOCKER_CONFIG=/tmp/thothii-release-20260926/docker-config \
|
||||||
|
/usr/local/bin/tht \
|
||||||
|
--installation /srv/thothii-v2/source/ThothII/deploy/psd-server-v2/thothii-installation.yaml \
|
||||||
|
doctor --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Prima di chiedere la finestra occorre risolvere il gate proxy, selezionare la
|
||||||
|
nuova revisione Omics, completare il contesto di build e il backup odierno,
|
||||||
|
e verificare il rollback che non riapra il bypass. La revisione ThothII pulita
|
||||||
|
può essere collocata in `/srv/thothii-v2/releases/497ab84031e285464fdbb73e6e0ce9252687e3ab`
|
||||||
|
senza modificare il checkout dirty; mantenendo invariato il percorso del
|
||||||
|
descrittore, il project name CLI resta uguale. Questo trasferimento e gli
|
||||||
|
aggiornamenti del descriptor/override non sono stati eseguiti.
|
||||||
|
|
||||||
|
Solo dopo questi prerequisiti presentare comandi finali risolti (nuovo CLI,
|
||||||
|
generazione, build/up mirati, proxy, verifiche e rollback) e chiedere conferma
|
||||||
|
della finestra. La sospensione attuale deriva dall'istruzione dell'operatore
|
||||||
|
e dal runbook: «Ferma il passaggio interessato se manca … un prerequisito;
|
||||||
|
non aggirare i controlli» e «Nessuna route diretta aggira il proxy».
|
||||||
|
|
||||||
|
Restano aperti tutti i gate reali con account Omics autorizzati: login unico,
|
||||||
|
ruoli/capability, tema/IT-EN/fullscreen, logout e seconda scheda, sessione di
|
||||||
|
prova e SSE/ripresa, rifiuto cross-origin autenticato, lettura amministrazione
|
||||||
|
e accesso HTTPS da client esterno. I test isolati non li sostituiscono.
|
||||||
@@ -0,0 +1,90 @@
|
|||||||
|
# Handoff — verifiche estese ThothII / Omics
|
||||||
|
|
||||||
|
Aggiornato il 27 settembre 2026. L’utente ha chiesto di affidare a un’attività
|
||||||
|
successiva le verifiche residue e di pubblicare la documentazione del rilascio.
|
||||||
|
**Aggiornamento e collaudo funzionale conclusi con successo; matrice estesa aperta.**
|
||||||
|
Questo documento è il punto di ripresa per le sole prove ancora da registrare.
|
||||||
|
|
||||||
|
## Stato acquisito e confini
|
||||||
|
|
||||||
|
Leggere [PROJECT_STATE.md](../../PROJECT_STATE.md), il
|
||||||
|
[report del rilascio](2026-09-26-server-release-execution.md), la
|
||||||
|
[matrice di accettazione](../testing/authentication-manual-acceptance.md) e il
|
||||||
|
[contratto upstream](../install/authentication-upstream.md).
|
||||||
|
|
||||||
|
Il 26 settembre sono stati distribuiti ThothII `497ab840` e il fix proxy Omics
|
||||||
|
`928f7e9f`, conservando l’immagine web Omics. Backup verificato e rollback sono
|
||||||
|
registrati nel report. L’utente ha confermato accesso senza secondo login,
|
||||||
|
controlli IT/EN, tema, fullscreen/Esc e avvio → interruzione → ripresa di una
|
||||||
|
sessione. Le prove automatiche di health, proxy anonimo/header falsificati,
|
||||||
|
asset, TLS locale e preservazione dati/configurazioni sono passate.
|
||||||
|
|
||||||
|
Queste sono evidenze del rilascio, non una nuova attestazione dello stato live.
|
||||||
|
Non ripetere backup/deploy né attivare maintenance per questo collaudo. Usare
|
||||||
|
account autorizzati e sessioni fittizie; DWH read-only. Non modificare ruoli,
|
||||||
|
Authentik, credenziali, modelli, archivi o configurazioni per far passare una prova.
|
||||||
|
Un problema che richieda un nuovo rilascio va prima diagnosticato e pianificato.
|
||||||
|
|
||||||
|
## Prima azione alla ripresa
|
||||||
|
|
||||||
|
1. Rileggere le conferme nel report: non chiedere all’utente di ripetere il ciclo
|
||||||
|
funzionale già riuscito, salvo regressioni o cambio di versione.
|
||||||
|
2. Verificare in sola lettura revisioni/container e stato dell’installazione.
|
||||||
|
Distinguere eventuale drift dalla baseline pubblicata; preservare il lavoro
|
||||||
|
e le sessioni in corso. Il `check` dello script di rilascio si aspetta lo stato
|
||||||
|
**precedente** al deploy: non usarlo come controllo corrente.
|
||||||
|
3. Concordare con l’operatore browser e account già disponibili: autorizzato,
|
||||||
|
normale, amministratore e, se disponibile, senza capability Datamart Builder.
|
||||||
|
Accedere dal normale login Omics; non chiedere password/cookie/token in chat.
|
||||||
|
Se manca un profilo, registrare quel caso come non eseguito senza crearne uno.
|
||||||
|
|
||||||
|
**Completato quando:** sono registrati data, revisioni effettive, modalità
|
||||||
|
embedded/upstream, browser e disponibilità dei profili, senza dati personali.
|
||||||
|
L’agente può proseguire con le letture tecniche mentre attende l’operatore.
|
||||||
|
|
||||||
|
## Prove residue
|
||||||
|
|
||||||
|
Tutti i casi sotto partono da **non eseguito**. La colonna “chi” indica chi compie
|
||||||
|
la parte principale; l’agente prepara i controlli tecnici e registra i risultati.
|
||||||
|
|
||||||
|
| ID | Chi | Azione concreta | Risultato necessario |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| V1 — lingua persistita | Operatore + agente | Creare una sessione fittizia con UI italiana, annotarne `interaction_language` tramite il normale stato sessione, interromperla, cambiare UI in inglese e riprendere **la stessa** sessione. | UI inglese, lingua della sessione ancora italiana; domande/scelte nella lingua persistita, SQL e contenuti authored invariati. La ripresa generica già provata non chiude questo caso. |
|
||||||
|
| V2 — identità e ruoli | Operatore + agente | Aprire `/datamart-builder/api/me` dalla sessione Omics autenticata; confrontare profilo normale e admin con le capability attese. Provare una richiesta amministrativa di sola lettura con il profilo normale. Se disponibile, provare pagina/API con un account senza capability. | Issuer `portal`, subject Django stabile, ruoli coerenti, `session` e `csrfToken` null. Profilo normale senza accesso amministrativo anche lato server; account senza capability rifiutato. Registrare solo esiti e codici, non identità o payload completi. |
|
||||||
|
| V3 — logout e riconnessione | Operatore | Aprire due schede Omics/Datamart Builder con una sessione fittizia; fare logout in una, tornare nell’altra e provocare un ricontrollo con reload/riconnessione. Rientrare attraverso Omics. | La nuova richiesta `/me` e le nuove aperture SSE non riusano l’accesso scaduto; UI protetta rimossa al ricontrollo. Non richiedere la chiusura istantanea di uno stream già aperto: non è il contratto. |
|
||||||
|
| V4 — origine delle scritture | Agente, con login dell’operatore | Preparare una coppia di richieste autenticate equivalenti su una risorsa fittizia autorizzata: prima same-origin, poi con origine estranea, attraversando il proxy pubblico. Confrontare lo stato della risorsa prima/dopo. Usare un harness HTTP locale con credenziali solo in memoria o file protetto; non affidarsi a `fetch` per impostare manualmente `Origin`. | La scrittura same-origin riesce e quella cross-origin è negata senza mutazioni. Dimostrare che la seconda richiesta è autenticata: un 403 dovuto alla sola assenza di cookie non prova la difesa Origin. I test isolati già verdi sono evidenza complementare, non sostituiscono questo caso. |
|
||||||
|
| V5 — lettura amministrazione | Operatore autorizzato | Aprire Database, Memory ed Evidence e controllare disponibilità dei dati preesistenti, selezione, pannelli e scroll. | Viste leggibili, nessun errore e nessuna scrittura/sincronizzazione necessaria per aprirle. Annotare quale area è stata verificata senza copiare contenuti clinici. |
|
||||||
|
| V6 — reload e preferenze | Operatore | Con sessione selezionata e Pi fermo, scegliere lingua e tema dal portale e ricaricare. | Preferenze e selezione coerenti; i documenti si riaprono senza avviare automaticamente Pi o una nuova generazione. La lingua persistita della sessione resta quella originale. |
|
||||||
|
| V7 — HTTPS esterno | Operatore | Confermare se le prove precedenti sono state svolte da una postazione esterna al server. Se non attestato, aprire il portale dal client abituale attraverso il nome pubblico e verificare config, asset e connessione eventi. | Accesso HTTPS senza avvisi di certificato, mixed content o errori di rete. Annotare browser e tipo di accesso, senza IP personali. Il curl locale con CA e risoluzione a 127.0.0.1 non chiude questo caso. |
|
||||||
|
|
||||||
|
Per V4 preparare e rendere verificabile il probe prima di eseguirlo: deve agire
|
||||||
|
solo sulla risorsa di prova concordata e controllare l’assenza di mutazioni nel
|
||||||
|
caso negato. In assenza di credenziali utilizzabili localmente, lasciare il caso
|
||||||
|
non eseguito; non estrarre sessioni di altri utenti o cambiare le regole Origin.
|
||||||
|
I comandi e gli endpoint concreti vanno derivati dalla versione effettivamente
|
||||||
|
installata, non inventati a partire da questo elenco.
|
||||||
|
|
||||||
|
## Registrazione e criterio di chiusura
|
||||||
|
|
||||||
|
Aggiornare questa tabella dopo ogni prova, collegando evidenze redatte o una
|
||||||
|
conferma esplicita dell’operatore. Un caso parziale resta aperto per i profili o
|
||||||
|
scenari mancanti. In caso di difetto, annotare riproduzione, atteso/ottenuto e
|
||||||
|
revisione; correggere e riprovare il caso interessato prima di dichiararlo superato.
|
||||||
|
|
||||||
|
| Caso | Stato iniziale | Data / versione / evidenza |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| V1 | Non eseguito | — |
|
||||||
|
| V2 | Non eseguito | — |
|
||||||
|
| V3 | Non eseguito | — |
|
||||||
|
| V4 | Non eseguito | — |
|
||||||
|
| V5 | Non eseguito | — |
|
||||||
|
| V6 | Non eseguito | — |
|
||||||
|
| V7 | Non eseguito | — |
|
||||||
|
|
||||||
|
**Chiusura delle verifiche residue:** ogni caso V1–V7 ha esito e prova registrati;
|
||||||
|
per dichiarare la matrice estesa superata devono essere tutti verdi. Un rinvio
|
||||||
|
esplicito o un prerequisito mancante va riportato come tale, non come successo.
|
||||||
|
Aggiornare quindi report di rilascio, questo handoff e PROJECT_STATE.md.
|
||||||
|
|
||||||
|
L’aggiornamento applicativo e il collaudo funzionale già confermati restano conclusi;
|
||||||
|
questo follow-up non richiede di reinstallare né di ripetere il rilascio.
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
# Dimensioni dei sei database candidati
|
|
||||||
|
|
||||||
Verifica del 27 settembre 2026 tramite lettura HTTP Range della directory centrale
|
|
||||||
degli archivi ZIP ufficiali. I valori sono le dimensioni non compresse dichiarate
|
|
||||||
per i singoli file, non il consumo misurato dopo importazione in PostgreSQL.
|
|
||||||
GB e MB sono decimali: 1 GB = 1.000.000.000 byte.
|
|
||||||
|
|
||||||
| Database | Formato | Byte | GB | MB |
|
|
||||||
| --- | --- | ---: | ---: | ---: |
|
|
||||||
| Financial, BIRD Mini-Dev | SQLite | 71.294.976 | 0,071295 | 71,295 |
|
|
||||||
| European Football, BIRD Mini-Dev | SQLite | 597.754.880 | 0,597755 | 597,755 |
|
|
||||||
| F1, Spider 2.0-Lite | SQLite | 74.940.416 | 0,074940 | 74,940 |
|
|
||||||
| Shopify, Spider 2.0-DBT, shopify001 | DuckDB iniziale | 19.935.232 | 0,019935 | 19,935 |
|
|
||||||
| QuickBooks, Spider 2.0-DBT, quickbooks001 | DuckDB iniziale | 50.606.080 | 0,050606 | 50,606 |
|
|
||||||
| Workday, Spider 2.0-DBT, workday001 | DuckDB iniziale | 28.323.840 | 0,028324 | 28,324 |
|
|
||||||
| Totale | | 842.855.424 | 0,842855 | 842,855 |
|
|
||||||
|
|
||||||
## Provenienza
|
|
||||||
|
|
||||||
- [BIRD Mini-Dev ZIP](https://bird-bench.oss-cn-beijing.aliyuncs.com/minidev.zip),
|
|
||||||
collegato dal [repository ufficiale](https://github.com/bird-bench/mini_dev).
|
|
||||||
Archivio: 800.943.648 byte; Last-Modified 20 giugno 2024.
|
|
||||||
Entry: `minidev/MINIDEV/dev_databases/financial/financial.sqlite` e
|
|
||||||
`minidev/MINIDEV/dev_databases/european_football_2/european_football_2.sqlite`.
|
|
||||||
- [Spider database locali](https://drive.google.com/file/d/1coEVsCZq-Xvj9p2TnhBFoFTsY-UoYGmG/view),
|
|
||||||
collegati dal [README Lite](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/README.md).
|
|
||||||
Archivio: 456.643.204 byte; entry `f1.sqlite`.
|
|
||||||
- [DBT_start_db.zip](https://drive.google.com/file/d/1N3f7BSWC4foj-V-1C9n8M2XmgV7FOcqL/view),
|
|
||||||
collegato dal [README DBT](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/README.md).
|
|
||||||
Archivio: 377.819.033 byte; Last-Modified 19 dicembre 2024.
|
|
||||||
Entry: `shopify001/shopify.duckdb`, `quickbooks001/quickbooks.duckdb`,
|
|
||||||
`workday001/workday.duckdb`.
|
|
||||||
|
|
||||||
I pesi degli archivi completi non sono quelli dei soli database selezionati:
|
|
||||||
contengono anche altri esempi. Non sommarli alla tabella salvo voler conservare
|
|
||||||
localmente tutti i pacchetti originali.
|
|
||||||
|
|
||||||
Per confronto, l'archivio ufficiale `dbt_gold.zip` contiene file corrispondenti di
|
|
||||||
22.032.384 byte (Shopify), 54.013.952 byte (QuickBooks) e 28.848.128 byte (Workday).
|
|
||||||
Sono versioni di risultato del benchmark, non la base scelta per la tabella e non
|
|
||||||
una previsione del consumo finale di ThothII.
|
|
||||||
|
|
||||||
## Limiti
|
|
||||||
|
|
||||||
Il totale esclude descrizioni, Evidence, CSV esportati, indici aggiuntivi, log,
|
|
||||||
PostgreSQL, Qdrant, immagini Docker e modelli locali. La conversione può modificare
|
|
||||||
sensibilmente l'occupazione. Non sono state estratte tutte le tabelle né contate
|
|
||||||
le righe: il peso del file non prova che tutte le tabelle documentate siano popolate.
|
|
||||||
La complessità di schema e dominio non implica grandi volumi nei dati dimostrativi.
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
# Candidati Spider 2.0-DBT con documentazione di dominio
|
|
||||||
|
|
||||||
Ricerca del 27 settembre 2026. Obiettivo: scegliere un database locale complesso,
|
|
||||||
con materiale da curare come Source Evidence di ThothII. Non vengono usate
|
|
||||||
domande del benchmark, SQL attesi o punteggi come criterio di selezione.
|
|
||||||
|
|
||||||
## Raccomandazione
|
|
||||||
|
|
||||||
**Shopify è il candidato da verificare per primo**, perché combina commercio,
|
|
||||||
pagamenti, rimborsi, inventario e ordini con documentazione dei significati e
|
|
||||||
delle misure. Offre inoltre un dominio diverso dal Financial BIRD già proposto.
|
|
||||||
QuickBooks è una valida alternativa se si preferisce la contabilità; Workday
|
|
||||||
se si preferiscono personale e storia organizzativa. Questa priorità è una
|
|
||||||
valutazione per il progetto, non una classificazione ufficiale Spider.
|
|
||||||
|
|
||||||
| Progetto Spider 2.0-DBT | Tabelle sorgente dichiarate | Coppie tabella/colonna descritte e distinte | Database locale indicato dal profilo |
|
|
||||||
| --- | ---: | ---: | --- |
|
|
||||||
| Shopify, `shopify001` | 34 | 578 | `shopify.duckdb` |
|
|
||||||
| QuickBooks, `quickbooks001` | 40 | 426 | `quickbooks.duckdb` |
|
|
||||||
| Workday, `workday001` | 21 | 436 | `workday.duckdb` |
|
|
||||||
|
|
||||||
Conteggi ricavati analizzando i rispettivi YAML `sources[].tables[]` e le
|
|
||||||
descrizioni delle colonne; **non sono un'ispezione delle tabelle materializzate
|
|
||||||
nei file DuckDB**. Alcune tabelle possono essere opzionali. Shopify ha 581
|
|
||||||
dichiarazioni di colonna, ma tre sono duplicate: `order.total_shipping_price_set`,
|
|
||||||
`order_line.tax_code`, `order_line_refund.subtotal_set`. I conteggi comprendono
|
|
||||||
anche metadati tecnici e riferimenti `doc(...)`: **non equivalgono a un numero
|
|
||||||
di Evidence Unit**. Sono esclusi i pacchetti di utilità generica dbt.
|
|
||||||
Fonti: [Shopify schema](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/shopify001/dbt_packages/shopify_source/models/src_shopify.yml),
|
|
||||||
[QuickBooks schema](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/quickbooks001/dbt_packages/quickbooks_source/models/src_quickbooks.yml),
|
|
||||||
[Workday schema](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/workday001/models/staging/src_workday.yml).
|
|
||||||
|
|
||||||
## Shopify: commercio e operazioni
|
|
||||||
|
|
||||||
Lo schema documenta ordini e righe d'ordine, clienti, prodotti e varianti,
|
|
||||||
transazioni, rimborsi, rettifiche, spedizioni, imposte, sconti, inventario,
|
|
||||||
sedi e checkout abbandonati. Le descrizioni specificano sia la granularità
|
|
||||||
delle entità sia il significato dei campi. Esempi di materiale semanticamente
|
|
||||||
utile: il subtotale è dopo gli sconti e prima di spedizione, imposte e mance;
|
|
||||||
`processed_at` è la data usata nei report analitici; l'ID API dell'ordine è
|
|
||||||
distinto dal numero mostrato al cliente; valuta del negozio e valuta presentata
|
|
||||||
al cliente hanno ruoli distinti. Le tre dichiarazioni duplicate richiedono
|
|
||||||
normalizzazione prima dell'importazione documentale.
|
|
||||||
[Dizionario sorgente](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/shopify001/dbt_packages/shopify_source/models/src_shopify.yml).
|
|
||||||
|
|
||||||
Il progetto aggiunge definizioni di modelli analitici, inclusi ordini, coorti
|
|
||||||
clienti e aggregazioni giornaliere del negozio; il solo `models/shopify.yml`
|
|
||||||
ne dichiara 10. Sono modelli dbt, da tenere distinti dalle 34 sorgenti e dalle
|
|
||||||
tabelle fisiche effettivamente disponibili. Queste definizioni sono un secondo
|
|
||||||
livello di materiale per Evidence su granularità e metriche.
|
|
||||||
[Modelli analitici](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/shopify001/models/shopify.yml).
|
|
||||||
|
|
||||||
Il profilo indica esplicitamente DuckDB, percorso `./shopify.duckdb`, schema
|
|
||||||
`main`. Non è necessario collegare un negozio Shopify reale per leggere il
|
|
||||||
database distribuito dal progetto.
|
|
||||||
[Profilo](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/shopify001/profiles.yml).
|
|
||||||
|
|
||||||
## QuickBooks: contabilità e documenti commerciali
|
|
||||||
|
|
||||||
Le 40 sorgenti dichiarate coprono conti, clienti, fornitori, fatture e righe,
|
|
||||||
pagamenti, depositi, acquisti, ordini, note di credito, trasferimenti e
|
|
||||||
registrazioni contabili. Il dizionario definisce classificazioni dei conti e
|
|
||||||
tipi delle righe fattura, distinguendo elementi di vendita, descrizione,
|
|
||||||
sconto e subtotale.
|
|
||||||
[Dizionario sorgente](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/quickbooks001/dbt_packages/quickbooks_source/models/src_quickbooks.yml).
|
|
||||||
|
|
||||||
La documentazione del libro mastro contiene una regola esplicita utile come
|
|
||||||
Evidence: l'importo aumenta il conto quando il tipo di movimento corrisponde
|
|
||||||
al lato di incremento del conto, e lo diminuisce altrimenti. Definisce inoltre
|
|
||||||
importi convertiti e saldi progressivi. `models/quickbooks.yml` dichiara 29
|
|
||||||
modelli tra intermedi e analitici: non sono 29 ulteriori tabelle sorgente
|
|
||||||
garantite. I due file di documentazione contengono complessivamente 120 blocchi
|
|
||||||
`docs` (68 nel progetto, 52 nel pacchetto sorgente); anche qui sono definizioni
|
|
||||||
da selezionare e curare, non 120 Evidence Unit già validate.
|
|
||||||
[Modelli e regole contabili](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/quickbooks001/models/quickbooks.yml),
|
|
||||||
[glossario progetto](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/quickbooks001/models/docs.md),
|
|
||||||
[glossario sorgente](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/quickbooks001/dbt_packages/quickbooks_source/models/docs.md).
|
|
||||||
|
|
||||||
Il profilo usa `./quickbooks.duckdb`.
|
|
||||||
[Profilo](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/quickbooks001/profiles.yml).
|
|
||||||
|
|
||||||
## Workday: personale, ruoli e storia organizzativa
|
|
||||||
|
|
||||||
Le sorgenti documentate comprendono lavoratori, posizioni, famiglie
|
|
||||||
professionali, organizzazioni, assegnazioni e diverse tabelle storiche.
|
|
||||||
Il glossario contiene 409 blocchi `docs`; molti sono definizioni brevi di
|
|
||||||
attributi, non regole articolate. Fra i concetti documentati figurano FTE
|
|
||||||
retribuito e lavorato, stato attivo/cessato, compensi, date di assunzione e
|
|
||||||
appartenenze organizzative. La complessità temporale e organizzativa è
|
|
||||||
interessante, ma il glossario da solo non giustifica chiamarlo il candidato
|
|
||||||
con più Evidence di qualità.
|
|
||||||
[Sorgenti](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/workday001/models/staging/src_workday.yml),
|
|
||||||
[glossario](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/workday001/models/docs.md).
|
|
||||||
|
|
||||||
Il profilo usa `./workday.duckdb`.
|
|
||||||
[Profilo](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/examples/workday001/profiles.yml).
|
|
||||||
|
|
||||||
## Download e prossimo controllo prima della scelta definitiva
|
|
||||||
|
|
||||||
Il README ufficiale fornisce due download Google Drive. Lo script di setup
|
|
||||||
attende `DBT_start_db.zip` e `dbt_gold.zip`, estrae i file DuckDB e li distribuisce
|
|
||||||
nei progetti e nella suite di riferimento. Per ThothII va scelto consapevolmente
|
|
||||||
il contenuto da usare come esempio: non occorre importare il meccanismo di
|
|
||||||
valutazione del benchmark. Questa ricerca verifica la pubblicazione del
|
|
||||||
percorso di download e la configurazione locale; **non verifica il download
|
|
||||||
integrale, dimensioni, righe, licenza dei singoli dati o schema fisico**.
|
|
||||||
[README](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/README.md),
|
|
||||||
[setup ufficiale](https://github.com/xlang-ai/Spider2/blob/main/spider2-dbt/setup.py).
|
|
||||||
|
|
||||||
Prima di promettere il pacchetto di installazione occorre scaricare il
|
|
||||||
candidato, confrontare tabelle e colonne reali con la documentazione,
|
|
||||||
verificare copertura delle entità e consistenza dei dati, e scegliere quali
|
|
||||||
definizioni diventino Source Evidence. Per PostgreSQL la conversione proposta
|
|
||||||
è schema esplicito più dati esportati; CSV sarebbe un formato derivato.
|
|
||||||
Vanno preservati tipi numerici, date, valute, valori nulli e contenuti
|
|
||||||
strutturati eventualmente presenti, adattando le sole trasformazioni
|
|
||||||
necessarie. Non è ancora stato implementato o testato alcun convertitore.
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
# Alternative Spider 2.0-Lite per database dimostrativi con Evidence
|
|
||||||
|
|
||||||
Verifica del 27 settembre 2026. Il criterio è complessità del database e qualità
|
|
||||||
della documentazione di dominio da curare in ThothII, non prestazioni sul benchmark
|
|
||||||
né numero di domande pubblicate. Nessun database è stato installato.
|
|
||||||
|
|
||||||
## Metodo e limiti
|
|
||||||
|
|
||||||
Ispezionati DDL, metadati per tabella e documenti ufficiali in
|
|
||||||
[Spider2](https://github.com/xlang-ai/Spider2), revisione osservata
|
|
||||||
`cafb867313aab4e674652054198f383cf4018943`. I conteggi sotto sono delle tabelle
|
|
||||||
dichiarate nei DDL e delle colonne nei JSON, non un'ispezione dei file SQLite.
|
|
||||||
La [procedura ufficiale](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/README.md)
|
|
||||||
offre un archivio dei database locali. I database cloud seguono un percorso diverso.
|
|
||||||
|
|
||||||
## Candidati locali
|
|
||||||
|
|
||||||
| Database | Tabelle / colonne nei metadati | Materiale semantico riscontrato | Valutazione |
|
|
||||||
| --- | --- | --- | --- |
|
|
||||||
| `E_commerce` | 11 / 70 | Documento RFM; documentazione originale Olist da integrare | Il più coerente dei candidati Lite esaminati per una demo aziendale, ma complessità media |
|
|
||||||
| `complex_oracle` | 10 / 140 | Proiezione vendite e conversioni valutarie; dizionario originale Oracle SH da confrontare | Buon caso analitico, meno esteso relazionalmente |
|
|
||||||
| `oracle_sql` | 38 / 124 | Documento sul rapporto vendite/media mobile e finestre temporali | Molte tabelle, documentazione semantica allegata troppo parziale |
|
|
||||||
| `AdventureWorks` | 13 / 120 | Documentazione originale Microsoft, da riallineare al sottoinsieme Spider | Non confondere questo estratto con l'intero AdventureWorks |
|
|
||||||
|
|
||||||
Conteggi ricavati dai DDL e JSON ufficiali: [E_commerce](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite/resource/databases/sqlite/E_commerce),
|
|
||||||
[complex_oracle](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite/resource/databases/sqlite/complex_oracle),
|
|
||||||
[oracle_sql](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite/resource/databases/sqlite/oracle_sql),
|
|
||||||
[AdventureWorks](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite/resource/databases/sqlite/AdventureWorks).
|
|
||||||
In tutti i JSON di questi quattro candidati, gli array `description` controllati
|
|
||||||
sono vuoti: tipi e righe di esempio non costituiscono da soli un dizionario di dominio.
|
|
||||||
|
|
||||||
### E_commerce
|
|
||||||
|
|
||||||
Comprende ordini, righe d'ordine, pagamenti, recensioni, prodotti, clienti, venditori,
|
|
||||||
geolocalizzazione e lead. Il [documento RFM](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/RFM.md)
|
|
||||||
definisce recency, frequency, monetary e undici segmenti con regole di assegnazione.
|
|
||||||
Sono fonti concrete di formule e regole, da rivedere e collegare allo schema.
|
|
||||||
|
|
||||||
La [fonte originale Olist](https://www.kaggle.com/olistbr/brazilian-ecommerce/metadata)
|
|
||||||
fornisce CSV e spiega una distinzione utile: `customer_id` identifica il cliente
|
|
||||||
nel contesto dell'ordine, mentre `customer_unique_id` permette di riconoscere acquisti
|
|
||||||
ripetuti della stessa persona. La distribuzione Olist di base contiene nove file;
|
|
||||||
non equivale automaticamente alle undici tabelle Spider, che includono i lead.
|
|
||||||
|
|
||||||
### complex_oracle
|
|
||||||
|
|
||||||
Il [documento allegato](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/projection_calculation.md)
|
|
||||||
descrive proiezione mensile delle vendite, crescita rispetto all'anno precedente,
|
|
||||||
conversione in USD e gestione di cambi mancanti. Lo schema ha vendite e costi con
|
|
||||||
dimensioni prodotto, cliente, calendario, canale, promozione e geografia.
|
|
||||||
|
|
||||||
Nomi e struttura sono riconducibili al [Sales History di Oracle](https://github.com/oracle-samples/db-sample-schemas/tree/main/sales_history).
|
|
||||||
Il suo script `sh_create.sql` contiene 88 commenti `COMMENT ON TABLE/COLUMN` e la
|
|
||||||
distribuzione comprende CSV. È materiale aggiuntivo utile, ma ogni corrispondenza
|
|
||||||
con lo schema Spider, incluse estensioni come `currency`, va verificata: non si
|
|
||||||
deve importare la documentazione dell'originale come se descrivesse automaticamente
|
|
||||||
ogni adattamento Spider.
|
|
||||||
|
|
||||||
### oracle_sql
|
|
||||||
|
|
||||||
Le tabelle coprono magazzino, ordini, confezioni annidate, vendite mensili e altri
|
|
||||||
sottodomini eterogenei. Il [documento di calcolo](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/calculation_method.md)
|
|
||||||
tratta tre aspetti: rapporto fra vendite e media mobile centrata, finestre di dodici
|
|
||||||
mesi e limiti temporali per evitare effetti ai bordi. Questo non documenta in modo
|
|
||||||
completo le altre parti del database: sconsigliato come scelta basata sulla sola
|
|
||||||
abbondanza di tabelle.
|
|
||||||
|
|
||||||
## Alternativa cloud con documentazione più ricca
|
|
||||||
|
|
||||||
`ga4` offre tre documenti complementari: [dizionario degli eventi](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/ga4_obfuscated_sample_ecommerce.events.md),
|
|
||||||
[dimensioni e metriche](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/ga4_dimensions_and_metrics.md)
|
|
||||||
e [categorie delle pagine](https://github.com/xlang-ai/Spider2/blob/main/spider2-lite/resource/documents/ga4_page_category.md).
|
|
||||||
Coprono campi annidati, classificazione dei canali e regole di interpretazione;
|
|
||||||
sono più vicini al requisito semantico. Tuttavia la
|
|
||||||
[distribuzione Spider è BigQuery](https://github.com/xlang-ai/Spider2/tree/main/spider2-lite/resource/databases/bigquery/ga4):
|
|
||||||
molte tabelle sono partizioni giornaliere dello stesso schema logico. Il conteggio
|
|
||||||
fisico non è una misura utile di complessità relazionale. Esportazione locale e
|
|
||||||
adattamento PostgreSQL sarebbero lavoro aggiuntivo, non un semplice import SQLite.
|
|
||||||
|
|
||||||
## Esito
|
|
||||||
|
|
||||||
Nessuno dei quattro candidati SQLite esaminati combina da solo schema molto esteso
|
|
||||||
e documentazione di dominio completa già pronta. Per cercare una scelta più forte,
|
|
||||||
confrontare con i progetti Spider 2.0-DBT nella ricerca separata
|
|
||||||
`2026-09-27-spider2-dbt-evidence-candidates.md`. I modelli documentati di dbt non
|
|
||||||
vanno confusi con tabelle fisiche già presenti, né le librerie di utility con Evidence.
|
|
||||||
@@ -79,7 +79,7 @@ verify_standalone_installation_guides() {
|
|||||||
'git clone https://git.tylconsulting.it/mptyl/ThothII.git' \
|
'git clone https://git.tylconsulting.it/mptyl/ThothII.git' \
|
||||||
'scripts/check-standalone-prerequisites.sh' \
|
'scripts/check-standalone-prerequisites.sh' \
|
||||||
'scripts/install-tht.sh' \
|
'scripts/install-tht.sh' \
|
||||||
'tht setup --complete --profile local --shell-mode full --shell-default-locale en' \
|
'tht setup --profile local --shell-mode full --shell-default-locale en' \
|
||||||
'scripts/verify-standalone-install.sh' \
|
'scripts/verify-standalone-install.sh' \
|
||||||
'Docker Hub' \
|
'Docker Hub' \
|
||||||
'Gate A' \
|
'Gate A' \
|
||||||
@@ -99,7 +99,8 @@ verify_install_and_workspace_guides() {
|
|||||||
require_file "$workspace"
|
require_file "$workspace"
|
||||||
|
|
||||||
for text in \
|
for text in \
|
||||||
'tht setup --complete --profile local' \
|
'tht setup --profile local' \
|
||||||
|
'--configure-only' \
|
||||||
'catalog-migrate' \
|
'catalog-migrate' \
|
||||||
'tht --installation /absolute/path/thothii-installation.yaml doctor --json'; do
|
'tht --installation /absolute/path/thothii-installation.yaml doctor --json'; do
|
||||||
require_text "$install" "$text"
|
require_text "$install" "$text"
|
||||||
|
|||||||
@@ -40,9 +40,9 @@ When --installation is omitted, tht uses THOTHII_INSTALLATION or discovers one v
|
|||||||
descriptor in the current project tree.
|
descriptor in the current project tree.
|
||||||
|
|
||||||
Commands:
|
Commands:
|
||||||
setup [--complete|--configure-only] [--installation-id ID] [--profile local|server]
|
setup [--configure-only] [--installation-id ID] [--profile local|server]
|
||||||
[--shell-mode full|embedded] [--shell-default-locale BCP47-TAG] [--shell-adapter omics-portal]
|
[--shell-mode full|embedded] [--shell-default-locale BCP47-TAG] [--shell-adapter omics-portal]
|
||||||
Create, validate, and optionally complete the local installation.
|
Create or validate the local non-secret installation configuration.
|
||||||
installation migrate --output PATH --session-default PROVIDER/MODEL
|
installation migrate --output PATH --session-default PROVIDER/MODEL
|
||||||
--embedding-id PROVIDER/MODEL --embedding-dimensions N
|
--embedding-id PROVIDER/MODEL --embedding-dimensions N
|
||||||
Create a review-only schema-v2 candidate from all three legacy model sources.
|
Create a review-only schema-v2 candidate from all three legacy model sources.
|
||||||
@@ -86,10 +86,6 @@ Commands:
|
|||||||
Verify a terminal installation, remove stale lifecycle files, and clear maintenance.
|
Verify a terminal installation, remove stale lifecycle files, and clear maintenance.
|
||||||
pi logs Show the latest 200 sanitized core log lines (bounded; no follow mode).
|
pi logs Show the latest 200 sanitized core log lines (bounded; no follow mode).
|
||||||
workspace inspect --workspace ID [--json]
|
workspace inspect --workspace ID [--json]
|
||||||
workspace pull [--json]
|
|
||||||
Pull and activate the configured workspace repository.
|
|
||||||
workspace test [--json]
|
|
||||||
Test configured database, Evidence, Qdrant, and embedding connectivity.
|
|
||||||
workspace evidence consolidate --workspace ID [--json]
|
workspace evidence consolidate --workspace ID [--json]
|
||||||
workspace evidence refresh --workspace ID [--json]
|
workspace evidence refresh --workspace ID [--json]
|
||||||
workspace evidence decide --workspace ID --source-id SHA --revision SHA --decision keep|replace [--json]
|
workspace evidence decide --workspace ID --source-id SHA --revision SHA --decision keep|replace [--json]
|
||||||
@@ -404,11 +400,6 @@ func parseSetupArgs(args []string) (setup.Request, error) {
|
|||||||
flag := args[0]
|
flag := args[0]
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
switch flag {
|
switch flag {
|
||||||
case "--complete":
|
|
||||||
if request.Complete {
|
|
||||||
return setup.Request{}, errors.New("--complete may be supplied once")
|
|
||||||
}
|
|
||||||
request.Complete = true
|
|
||||||
case "--configure-only":
|
case "--configure-only":
|
||||||
if request.ConfigureOnly {
|
if request.ConfigureOnly {
|
||||||
return setup.Request{}, errors.New("--configure-only may be supplied once")
|
return setup.Request{}, errors.New("--configure-only may be supplied once")
|
||||||
@@ -493,9 +484,6 @@ func parseSetupArgs(args []string) (setup.Request, error) {
|
|||||||
*target = value
|
*target = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if request.Complete && request.ConfigureOnly {
|
|
||||||
return setup.Request{}, errors.New("--complete and --configure-only cannot be combined")
|
|
||||||
}
|
|
||||||
return request, nil
|
return request, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -511,9 +499,6 @@ func writeRemovalTargets(outputWriter io.Writer, project string, targets []serve
|
|||||||
}
|
}
|
||||||
|
|
||||||
func workspaceCommand(ctx context.Context, installation config.Installation, runner compose.Runner, args []string, secretValues []string, stdout, stderr io.Writer) int {
|
func workspaceCommand(ctx context.Context, installation config.Installation, runner compose.Runner, args []string, secretValues []string, stdout, stderr io.Writer) int {
|
||||||
if len(args) > 0 && (args[0] == "pull" || args[0] == "test") {
|
|
||||||
return workspaceOperatorCommand(ctx, installation, runner, args, secretValues, stdout, stderr)
|
|
||||||
}
|
|
||||||
request, err := workspaceops.Parse(args)
|
request, err := workspaceops.Parse(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return commandUsageError(stderr, err.Error())
|
return commandUsageError(stderr, err.Error())
|
||||||
@@ -542,51 +527,6 @@ func workspaceCommand(ctx context.Context, installation config.Installation, run
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func workspaceOperatorCommand(ctx context.Context, installation config.Installation, runner compose.Runner, args []string, secretValues []string, stdout, stderr io.Writer) int {
|
|
||||||
action := "workspace-" + args[0]
|
|
||||||
jsonMode := false
|
|
||||||
for _, arg := range args[1:] {
|
|
||||||
if arg != "--json" || jsonMode {
|
|
||||||
return commandUsageError(stderr, "workspace pull/test accepts only --json")
|
|
||||||
}
|
|
||||||
jsonMode = true
|
|
||||||
}
|
|
||||||
result, err := runner.Run(ctx, installation.ComposeArgs("exec", "-T", "core", "node", "dist/operator-command.js", action), nil)
|
|
||||||
if err != nil {
|
|
||||||
return writeResult(result, err, secretValues, stdout, stderr)
|
|
||||||
}
|
|
||||||
var payload struct {
|
|
||||||
Ready bool `json:"ready"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal([]byte(result.Stdout), &payload); err != nil {
|
|
||||||
fmt.Fprintln(stderr, "tht: workspace operator returned invalid JSON")
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
if jsonMode {
|
|
||||||
fmt.Fprintln(stdout, output.Sanitize(result.Stdout, secretValues))
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(stdout, "workspace %s: %s\n", args[0], output.Sanitize(workspaceOperatorSummary(payload), secretValues))
|
|
||||||
}
|
|
||||||
if !payload.Ready {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func workspaceOperatorSummary(payload struct {
|
|
||||||
Ready bool `json:"ready"`
|
|
||||||
Status string `json:"status"`
|
|
||||||
}) string {
|
|
||||||
if payload.Status != "" {
|
|
||||||
return payload.Status
|
|
||||||
}
|
|
||||||
if payload.Ready {
|
|
||||||
return "ready"
|
|
||||||
}
|
|
||||||
return "failed"
|
|
||||||
}
|
|
||||||
|
|
||||||
func workspaceFailure(stderr io.Writer, err error, secretValues []string) int {
|
func workspaceFailure(stderr io.Writer, err error, secretValues []string) int {
|
||||||
message := output.Sanitize(err.Error(), secretValues)
|
message := output.Sanitize(err.Error(), secretValues)
|
||||||
var operationErr *workspaceops.OperationError
|
var operationErr *workspaceops.OperationError
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package setup
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"crypto/rand"
|
|
||||||
"encoding/hex"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -15,7 +13,6 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/aritmolab/thothii/tools/tht/internal/config"
|
"github.com/aritmolab/thothii/tools/tht/internal/config"
|
||||||
"github.com/aritmolab/thothii/tools/tht/internal/safeio"
|
"github.com/aritmolab/thothii/tools/tht/internal/safeio"
|
||||||
@@ -29,7 +26,6 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var installationIDPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_-]*$`)
|
var installationIDPattern = regexp.MustCompile(`^[A-Za-z0-9][A-Za-z0-9_-]*$`)
|
||||||
var secretBundleKeyPattern = regexp.MustCompile(`^[A-Z][A-Z0-9_]{0,127}$`)
|
|
||||||
|
|
||||||
// atomicWriteNewFile is a seam for failure testing. Its implementation never replaces an existing
|
// atomicWriteNewFile is a seam for failure testing. Its implementation never replaces an existing
|
||||||
// file and leaves no final target until all content is synced.
|
// file and leaves no final target until all content is synced.
|
||||||
@@ -48,7 +44,6 @@ type answers struct {
|
|||||||
secretsFile, piAuthFile string
|
secretsFile, piAuthFile string
|
||||||
gitCredentialsFile, gitCAFile string
|
gitCredentialsFile, gitCAFile string
|
||||||
gitSSHKeyFile, gitKnownHostsFile string
|
gitSSHKeyFile, gitKnownHostsFile string
|
||||||
complete bool
|
|
||||||
createSecretTemplates bool
|
createSecretTemplates bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,11 +116,6 @@ func EnsureFiles(request Request, input io.Reader, output io.Writer) (FilesResul
|
|||||||
if err := validateOrCreateSecretFiles(values, output); err != nil {
|
if err := validateOrCreateSecretFiles(values, output); err != nil {
|
||||||
return FilesResult{}, err
|
return FilesResult{}, err
|
||||||
}
|
}
|
||||||
if values.complete {
|
|
||||||
if err := validateCompleteProtectedFiles(values); err != nil {
|
|
||||||
return FilesResult{}, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
created := make([]string, 0, 2)
|
created := make([]string, 0, 2)
|
||||||
cleanup := func() {
|
cleanup := func() {
|
||||||
@@ -173,27 +163,6 @@ func collectAnswers(request Request, input io.Reader, output io.Writer, root str
|
|||||||
value := answersFromRequest(request)
|
value := answersFromRequest(request)
|
||||||
value.installationID = firstNonEmpty(request.InstallationID, os.Getenv("THT_SETUP_INSTALLATION_ID"), "local")
|
value.installationID = firstNonEmpty(request.InstallationID, os.Getenv("THT_SETUP_INSTALLATION_ID"), "local")
|
||||||
value.profile = firstNonEmpty(request.Profile, os.Getenv("THT_SETUP_PROFILE"), "local")
|
value.profile = firstNonEmpty(request.Profile, os.Getenv("THT_SETUP_PROFILE"), "local")
|
||||||
value.complete = request.Complete
|
|
||||||
if request.Complete {
|
|
||||||
// The complete path has one predictable protected directory. The user only fills the
|
|
||||||
// bundle and any repository credential that is genuinely required; catalog passwords
|
|
||||||
// are generated below and never appear in the questionnaire.
|
|
||||||
directory := filepath.Join(root, "deploy", value.installationID, "secrets")
|
|
||||||
value.workspaceBranch = firstNonEmpty(value.workspaceBranch, "main")
|
|
||||||
value.secretsFile = firstNonEmpty(value.secretsFile, filepath.Join(directory, "thothii.secrets"))
|
|
||||||
value.piAuthFile = firstNonEmpty(value.piAuthFile, filepath.Join(directory, "pi-auth.json"))
|
|
||||||
if request.NonInteractive {
|
|
||||||
value.workspaceAccess = firstNonEmpty(value.workspaceAccess, accessForRemote(value.workspaceRemote))
|
|
||||||
if value.workspaceAccess == "ssh" {
|
|
||||||
value.gitSSHKeyFile = firstNonEmpty(value.gitSSHKeyFile, filepath.Join(directory, "workspace-git-key"))
|
|
||||||
value.gitKnownHostsFile = firstNonEmpty(value.gitKnownHostsFile, filepath.Join(directory, "workspace-git-known-hosts"))
|
|
||||||
} else {
|
|
||||||
value.gitCredentialsFile = firstNonEmpty(value.gitCredentialsFile, filepath.Join(directory, "workspace-git-credentials"))
|
|
||||||
value.gitCAFile = firstNonEmpty(value.gitCAFile, filepath.Join(directory, "workspace-git-ca.pem"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
value.createSecretTemplates = true
|
|
||||||
}
|
|
||||||
if request.NonInteractive {
|
if request.NonInteractive {
|
||||||
return requireNonInteractiveAnswers(value)
|
return requireNonInteractiveAnswers(value)
|
||||||
}
|
}
|
||||||
@@ -221,18 +190,6 @@ func collectAnswers(request Request, input io.Reader, output io.Writer, root str
|
|||||||
return answers{}, err
|
return answers{}, err
|
||||||
}
|
}
|
||||||
directory := filepath.Join(root, "deploy", value.installationID, "secrets")
|
directory := filepath.Join(root, "deploy", value.installationID, "secrets")
|
||||||
if request.Complete {
|
|
||||||
value.secretsFile = firstNonEmpty(value.secretsFile, filepath.Join(directory, "thothii.secrets"))
|
|
||||||
value.piAuthFile = firstNonEmpty(value.piAuthFile, filepath.Join(directory, "pi-auth.json"))
|
|
||||||
if value.workspaceAccess == "ssh" {
|
|
||||||
value.gitSSHKeyFile = firstNonEmpty(value.gitSSHKeyFile, filepath.Join(directory, "workspace-git-key"))
|
|
||||||
value.gitKnownHostsFile = firstNonEmpty(value.gitKnownHostsFile, filepath.Join(directory, "workspace-git-known-hosts"))
|
|
||||||
} else {
|
|
||||||
value.gitCredentialsFile = firstNonEmpty(value.gitCredentialsFile, filepath.Join(directory, "workspace-git-credentials"))
|
|
||||||
value.gitCAFile = firstNonEmpty(value.gitCAFile, filepath.Join(directory, "workspace-git-ca.pem"))
|
|
||||||
}
|
|
||||||
return value, nil
|
|
||||||
}
|
|
||||||
if value.secretsFile, err = prompt(scanner, output, "Secret file location", firstNonEmpty(value.secretsFile, filepath.Join(directory, "thothii.secrets"))); err != nil {
|
if value.secretsFile, err = prompt(scanner, output, "Secret file location", firstNonEmpty(value.secretsFile, filepath.Join(directory, "thothii.secrets"))); err != nil {
|
||||||
return answers{}, err
|
return answers{}, err
|
||||||
}
|
}
|
||||||
@@ -259,16 +216,12 @@ func collectAnswers(request Request, input io.Reader, output io.Writer, root str
|
|||||||
return answers{}, missingErr
|
return answers{}, missingErr
|
||||||
}
|
}
|
||||||
if len(missing) > 0 {
|
if len(missing) > 0 {
|
||||||
if request.Complete {
|
|
||||||
value.createSecretTemplates = true
|
|
||||||
} else {
|
|
||||||
answer, promptErr := prompt(scanner, output, "Create blank secret-file templates for the missing locations? Type yes to confirm", "no")
|
answer, promptErr := prompt(scanner, output, "Create blank secret-file templates for the missing locations? Type yes to confirm", "no")
|
||||||
if promptErr != nil {
|
if promptErr != nil {
|
||||||
return answers{}, promptErr
|
return answers{}, promptErr
|
||||||
}
|
}
|
||||||
value.createSecretTemplates = strings.EqualFold(answer, "yes")
|
value.createSecretTemplates = strings.EqualFold(answer, "yes")
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return value, nil
|
return value, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -426,13 +379,6 @@ func render(root, descriptorPath string, value answers) ([]byte, []byte, error)
|
|||||||
if value.llmURL != "" {
|
if value.llmURL != "" {
|
||||||
lines = append(lines, "THT_LLM_URL="+dotenvValue(value.llmURL))
|
lines = append(lines, "THT_LLM_URL="+dotenvValue(value.llmURL))
|
||||||
}
|
}
|
||||||
if value.complete {
|
|
||||||
passwordDirectory := filepath.Dir(value.secretsFile)
|
|
||||||
lines = append(lines,
|
|
||||||
"THT_CATALOG_RUNTIME_PASSWORD_SOURCE="+dotenvValue(filepath.Join(passwordDirectory, "catalog-runtime-password")),
|
|
||||||
"THT_CATALOG_MIGRATOR_PASSWORD_SOURCE="+dotenvValue(filepath.Join(passwordDirectory, "catalog-migrator-password")),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if value.profile == "server" {
|
if value.profile == "server" {
|
||||||
installationDirectory := filepath.Dir(descriptorPath)
|
installationDirectory := filepath.Dir(descriptorPath)
|
||||||
lines = append(lines,
|
lines = append(lines,
|
||||||
@@ -528,7 +474,10 @@ func validateOrCreateSecretFiles(value answers, output io.Writer) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(missing) > 0 && !value.createSecretTemplates {
|
if len(missing) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !value.createSecretTemplates {
|
||||||
return fmt.Errorf("secret files are missing: %s; create them yourself or explicitly confirm blank secret-file templates", strings.Join(missing, ", "))
|
return fmt.Errorf("secret files are missing: %s; create them yourself or explicitly confirm blank secret-file templates", strings.Join(missing, ", "))
|
||||||
}
|
}
|
||||||
for _, path := range missing {
|
for _, path := range missing {
|
||||||
@@ -540,104 +489,6 @@ func validateOrCreateSecretFiles(value answers, output io.Writer) error {
|
|||||||
}
|
}
|
||||||
fmt.Fprintf(output, "Created blank secret-file template: %s\n", path)
|
fmt.Fprintf(output, "Created blank secret-file template: %s\n", path)
|
||||||
}
|
}
|
||||||
if value.complete {
|
|
||||||
for _, path := range catalogPasswordPaths(value) {
|
|
||||||
exists, err := inspectExistingSecretFile(path)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if exists {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
contents, err := generatedCatalogPassword()
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("generate catalog password: %w", err)
|
|
||||||
}
|
|
||||||
if err := atomicWriteNewFile(path, contents, 0o600); err != nil {
|
|
||||||
return fmt.Errorf("create catalog password %s: %w", path, err)
|
|
||||||
}
|
|
||||||
fmt.Fprintf(output, "Created generated catalog password file: %s\n", path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func catalogPasswordPaths(value answers) []string {
|
|
||||||
directory := filepath.Dir(value.secretsFile)
|
|
||||||
return []string{
|
|
||||||
filepath.Join(directory, "catalog-runtime-password"),
|
|
||||||
filepath.Join(directory, "catalog-migrator-password"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func generatedCatalogPassword() ([]byte, error) {
|
|
||||||
value := make([]byte, 32)
|
|
||||||
if _, err := rand.Read(value); err != nil {
|
|
||||||
return nil, errors.New("secure random source is unavailable")
|
|
||||||
}
|
|
||||||
return []byte(hex.EncodeToString(value) + "\n"), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateCompleteProtectedFiles(value answers) error {
|
|
||||||
if err := validateSecretBundle(value.secretsFile); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// The generated catalog deliberately uses Pi's built-in provider. A syntactically empty
|
|
||||||
// auth store would let Docker start only to fail at the first provider check, so catch it
|
|
||||||
// before any image is built. Other model providers can be selected later in the descriptor.
|
|
||||||
contents, err := safeio.ReadCanonicalRegular(value.piAuthFile, maxSecretBytes)
|
|
||||||
if err != nil || strings.TrimSpace(string(contents)) == "" || strings.TrimSpace(string(contents)) == "{}" {
|
|
||||||
return fmt.Errorf("complete setup requires usable Pi credentials in %s", value.piAuthFile)
|
|
||||||
}
|
|
||||||
if value.workspaceAccess == "ssh" {
|
|
||||||
for name, path := range map[string]string{
|
|
||||||
"workspace Git SSH key": value.gitSSHKeyFile,
|
|
||||||
"workspace Git known-hosts": value.gitKnownHostsFile,
|
|
||||||
} {
|
|
||||||
contents, readErr := safeio.ReadCanonicalRegular(path, maxSecretBytes)
|
|
||||||
if readErr != nil || strings.TrimSpace(string(contents)) == "" {
|
|
||||||
return fmt.Errorf("complete setup requires usable %s in %s", name, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for name, path := range map[string]string{
|
|
||||||
"workspace Git credentials": value.gitCredentialsFile,
|
|
||||||
"workspace Git CA": value.gitCAFile,
|
|
||||||
} {
|
|
||||||
contents, readErr := safeio.ReadCanonicalRegular(path, maxSecretBytes)
|
|
||||||
if readErr != nil || strings.TrimSpace(string(contents)) == "" {
|
|
||||||
return fmt.Errorf("complete setup requires usable %s in %s", name, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateSecretBundle(path string) error {
|
|
||||||
contents, err := safeio.ReadCanonicalRegular(path, maxSecretBytes)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("complete setup cannot read the secret bundle %s", path)
|
|
||||||
}
|
|
||||||
seen := make(map[string]struct{})
|
|
||||||
for lineNumber, raw := range strings.Split(string(contents), "\n") {
|
|
||||||
line := strings.TrimSuffix(raw, "\r")
|
|
||||||
trimmed := strings.TrimSpace(line)
|
|
||||||
if trimmed == "" || strings.HasPrefix(trimmed, "#") {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
key, secret, found := strings.Cut(line, "=")
|
|
||||||
invalid := !found || !secretBundleKeyPattern.MatchString(key) || strings.TrimSpace(key) != key ||
|
|
||||||
secret == "" || strings.TrimSpace(secret) != secret ||
|
|
||||||
strings.Contains(strings.ToLower(secret), "replace-me") ||
|
|
||||||
strings.IndexFunc(secret, unicode.IsSpace) >= 0
|
|
||||||
if invalid {
|
|
||||||
return fmt.Errorf("complete setup found an invalid secret bundle entry at line %d", lineNumber+1)
|
|
||||||
}
|
|
||||||
if _, duplicate := seen[key]; duplicate {
|
|
||||||
return fmt.Errorf("complete setup found a duplicate secret bundle key %s", key)
|
|
||||||
}
|
|
||||||
seen[key] = struct{}{}
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,50 +207,6 @@ func TestEnsureFilesRequiresExplicitNonInteractiveAnswers(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCompleteSetupCreatesProtectedPlaceholdersThenRequiresUsableCredentials(t *testing.T) {
|
|
||||||
root := newProject(t, "complete setup")
|
|
||||||
for name, value := range map[string]string{
|
|
||||||
"THT_SETUP_WORKSPACE_REMOTE": "git@git.example.invalid:team/workspaces.git",
|
|
||||||
"THT_SETUP_WORKSPACE_BRANCH": "main",
|
|
||||||
"THT_SETUP_WORKSPACE_ACCESS": "ssh",
|
|
||||||
} {
|
|
||||||
t.Setenv(name, value)
|
|
||||||
}
|
|
||||||
request := Request{ProjectRoot: root, InstallationID: "local", Profile: "local", Complete: true, NonInteractive: true}
|
|
||||||
if _, err := EnsureFiles(request, strings.NewReader(""), ioDiscard{}); err == nil || !strings.Contains(err.Error(), "usable Pi credentials") {
|
|
||||||
t.Fatalf("first complete setup error = %v, want the placeholder guidance", err)
|
|
||||||
}
|
|
||||||
secretRoot := filepath.Join(root, "deploy", "local", "secrets")
|
|
||||||
for path, contents := range map[string]string{
|
|
||||||
filepath.Join(secretRoot, "pi-auth.json"): "{\"deepseek\":{\"apiKey\":\"configured\"}}\n",
|
|
||||||
filepath.Join(secretRoot, "workspace-git-key"): "private-key\n",
|
|
||||||
filepath.Join(secretRoot, "workspace-git-known-hosts"): "git.example.invalid ssh-ed25519 AAAA\n",
|
|
||||||
} {
|
|
||||||
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result, err := EnsureFiles(request, strings.NewReader(""), ioDiscard{})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
environment, err := os.ReadFile(result.EnvironmentPath)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
for _, name := range []string{"THT_CATALOG_RUNTIME_PASSWORD_SOURCE", "THT_CATALOG_MIGRATOR_PASSWORD_SOURCE"} {
|
|
||||||
if !strings.Contains(string(environment), name+"=") {
|
|
||||||
t.Fatalf("complete environment misses %s: %s", name, environment)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, name := range []string{"catalog-runtime-password", "catalog-migrator-password"} {
|
|
||||||
contents, readErr := os.ReadFile(filepath.Join(secretRoot, name))
|
|
||||||
if readErr != nil || len(strings.TrimSpace(string(contents))) < 32 {
|
|
||||||
t.Fatalf("generated catalog password %s is unavailable or too short", name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEnsureFilesIncludesServerStorageLocations(t *testing.T) {
|
func TestEnsureFilesIncludesServerStorageLocations(t *testing.T) {
|
||||||
requireProjectedServerTestHost(t)
|
requireProjectedServerTestHost(t)
|
||||||
root := newProject(t, "server profile")
|
root := newProject(t, "server profile")
|
||||||
|
|||||||
@@ -1,15 +1,12 @@
|
|||||||
// Package setup creates the local, non-secret configuration selected by tht setup.
|
// Package setup creates the local, non-secret configuration selected by tht setup.
|
||||||
package setup
|
package setup
|
||||||
|
|
||||||
// Request contains the stable setup-file inputs.
|
// Request contains the stable setup-file inputs. Task 5 will use ConfigureOnly when it adds
|
||||||
|
// Compose validation and lifecycle orchestration.
|
||||||
type Request struct {
|
type Request struct {
|
||||||
ProjectRoot string
|
ProjectRoot string
|
||||||
InstallationID string
|
InstallationID string
|
||||||
Profile string
|
Profile string
|
||||||
// Complete runs the installation-only steps that are safe to automate: catalog migration,
|
|
||||||
// stack startup, and the initial workspace pull. It intentionally does not invent database
|
|
||||||
// bindings or credentials that belong to the installation operator.
|
|
||||||
Complete bool
|
|
||||||
ConfigureOnly bool
|
ConfigureOnly bool
|
||||||
NonInteractive bool
|
NonInteractive bool
|
||||||
Answers Answers
|
Answers Answers
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package setup
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -36,8 +35,7 @@ type Result struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Run validates the host, creates or validates non-secret configuration, and by default builds,
|
// Run validates the host, creates or validates non-secret configuration, and by default builds,
|
||||||
// starts, and verifies the current checkout. Complete additionally migrates the Catalog and
|
// starts, and verifies the current checkout. ConfigureOnly stops after Compose rendering.
|
||||||
// imports the configured workspace repository. ConfigureOnly stops after Compose rendering.
|
|
||||||
func Run(ctx context.Context, runner compose.Runner, request Request, input io.Reader, output io.Writer) (Result, error) {
|
func Run(ctx context.Context, runner compose.Runner, request Request, input io.Reader, output io.Writer) (Result, error) {
|
||||||
if runner == nil {
|
if runner == nil {
|
||||||
return Result{}, errors.New("setup requires a Docker command runner")
|
return Result{}, errors.New("setup requires a Docker command runner")
|
||||||
@@ -73,33 +71,13 @@ func Run(ctx context.Context, runner compose.Runner, request Request, input io.R
|
|||||||
fmt.Fprintf(output, "Configuration is ready: %s\n", result.DescriptorPath)
|
fmt.Fprintf(output, "Configuration is ready: %s\n", result.DescriptorPath)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
if request.Complete {
|
if err := service.Start(ctx, installation, runner, true); err != nil {
|
||||||
if err := runCompose(ctx, runner, installation, "build"); err != nil {
|
|
||||||
return Result{}, fmt.Errorf("setup image build: %w", err)
|
|
||||||
}
|
|
||||||
if err := runCompose(ctx, runner, installation, "up", "--detach", "catalog-db"); err != nil {
|
|
||||||
return Result{}, fmt.Errorf("setup Catalog database start: %w", err)
|
|
||||||
}
|
|
||||||
if err := runCompose(ctx, runner, installation,
|
|
||||||
"--profile", "catalog-maintenance", "run", "--rm", "catalog-migrate"); err != nil {
|
|
||||||
return Result{}, fmt.Errorf("setup Catalog migration: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := service.Start(ctx, installation, runner, !request.Complete); err != nil {
|
|
||||||
if strings.Contains(err.Error(), "image build") {
|
if strings.Contains(err.Error(), "image build") {
|
||||||
return Result{}, fmt.Errorf("setup %w", err)
|
return Result{}, fmt.Errorf("setup %w", err)
|
||||||
}
|
}
|
||||||
return Result{}, withStartupRecovery(fmt.Errorf("setup %w", err), recoveryService(err))
|
return Result{}, withStartupRecovery(fmt.Errorf("setup %w", err), recoveryService(err))
|
||||||
}
|
}
|
||||||
result.Built, result.Started, result.Healthy = true, true, true
|
result.Built, result.Started, result.Healthy = true, true, true
|
||||||
if request.Complete {
|
|
||||||
if err := runOperator(ctx, runner, installation, "workspace-pull"); err != nil {
|
|
||||||
return Result{}, withStartupRecovery(fmt.Errorf("setup workspace import: %w", err), "core")
|
|
||||||
}
|
|
||||||
if err := runOperator(ctx, runner, installation, "pi-test"); err != nil {
|
|
||||||
return Result{}, withStartupRecovery(fmt.Errorf("setup LLM credential test: %w", err), "core")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
report, err := doctor.Run(ctx, installation, runner)
|
report, err := doctor.Run(ctx, installation, runner)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Result{}, withStartupRecovery(fmt.Errorf("setup doctor: %w", err), "core")
|
return Result{}, withStartupRecovery(fmt.Errorf("setup doctor: %w", err), "core")
|
||||||
@@ -107,9 +85,6 @@ func Run(ctx context.Context, runner compose.Runner, request Request, input io.R
|
|||||||
if !report.OK {
|
if !report.OK {
|
||||||
return Result{}, withStartupRecovery(errors.New("setup doctor reported failed checks"), "core")
|
return Result{}, withStartupRecovery(errors.New("setup doctor reported failed checks"), "core")
|
||||||
}
|
}
|
||||||
if request.Complete {
|
|
||||||
fmt.Fprintln(output, "Workspace repository pulled and activated; run 'tht workspace test' after configuring each workspace database.")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(output, "ThothII is ready at %s\nInstallation descriptor: %s\nNext: tht status\n", frontendURL(installation), result.DescriptorPath)
|
fmt.Fprintf(output, "ThothII is ready at %s\nInstallation descriptor: %s\nNext: tht status\n", frontendURL(installation), result.DescriptorPath)
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
@@ -244,25 +219,6 @@ func runCompose(ctx context.Context, runner compose.Runner, installation config.
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func runOperator(ctx context.Context, runner compose.Runner, installation config.Installation, action string) error {
|
|
||||||
result, err := runner.Run(ctx, installation.ComposeArgs(
|
|
||||||
"exec", "-T", "core", "node", "dist/operator-command.js", action,
|
|
||||||
), nil)
|
|
||||||
if err != nil {
|
|
||||||
if result.ExitCode != 0 {
|
|
||||||
return fmt.Errorf("Docker exited with status %d", result.ExitCode)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var payload struct {
|
|
||||||
Ready *bool `json:"ready"`
|
|
||||||
}
|
|
||||||
if err := json.Unmarshal([]byte(result.Stdout), &payload); err != nil || payload.Ready == nil || !*payload.Ready {
|
|
||||||
return fmt.Errorf("operator action %s reported failure", action)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func composeFailure(result compose.Result, cause error) error {
|
func composeFailure(result compose.Result, cause error) error {
|
||||||
if result.ExitCode != 0 {
|
if result.ExitCode != 0 {
|
||||||
return fmt.Errorf("Docker exited with status %d", result.ExitCode)
|
return fmt.Errorf("Docker exited with status %d", result.ExitCode)
|
||||||
|
|||||||
@@ -68,34 +68,6 @@ func TestRunConfigureOnlyStopsAfterRenderedConfiguration(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRunCompleteMigratesCatalogPullsWorkspaceAndTestsLLM(t *testing.T) {
|
|
||||||
root, request := setupRunFixture(t, false)
|
|
||||||
request.Complete = true
|
|
||||||
secretRoot := filepath.Join(root, "deploy", "ci", "secrets")
|
|
||||||
for path, contents := range map[string]string{
|
|
||||||
filepath.Join(secretRoot, "pi-auth.json"): "{\"deepseek\":{\"apiKey\":\"configured\"}}\n",
|
|
||||||
filepath.Join(secretRoot, "workspace-git-key"): "private-key\n",
|
|
||||||
filepath.Join(secretRoot, "workspace-git-known-hosts"): "git.example.invalid ssh-ed25519 AAAA\n",
|
|
||||||
} {
|
|
||||||
if err := os.WriteFile(path, []byte(contents), 0o600); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
runner := &setupRunner{health: []string{healthyServicesJSON}}
|
|
||||||
if _, err := Run(context.Background(), runner, request, strings.NewReader(""), io.Discard); err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
want := []string{
|
|
||||||
"docker engine", "docker compose", "architecture", "compose config", "compose build",
|
|
||||||
"catalog db", "catalog migrate", "compose up", "health", "workspace pull", "pi doctor",
|
|
||||||
"doctor docker", "doctor compose", "compose config", "doctor config", "health",
|
|
||||||
"authentication", "core HTTP", "frontend HTTP", "workspace registry", "workflow doctor", "pi doctor",
|
|
||||||
}
|
|
||||||
if got := collapseStages(runner.stages); strings.Join(got, " | ") != strings.Join(want, " | ") {
|
|
||||||
t.Fatalf("complete setup stages = %v, want %v", got, want)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestRunConfiguresAndStaticallyValidatesLocalAuthBeforeComposeRender(t *testing.T) {
|
func TestRunConfiguresAndStaticallyValidatesLocalAuthBeforeComposeRender(t *testing.T) {
|
||||||
projectRoot, request := setupRunFixture(t, true)
|
projectRoot, request := setupRunFixture(t, true)
|
||||||
passwordFile := filepath.Join(projectRoot, "initial-admin-password")
|
passwordFile := filepath.Join(projectRoot, "initial-admin-password")
|
||||||
@@ -449,10 +421,6 @@ func setupStage(args []string) (string, compose.Result) {
|
|||||||
return "architecture", compose.Result{Stdout: "arm64\n"}
|
return "architecture", compose.Result{Stdout: "arm64\n"}
|
||||||
case strings.HasSuffix(joined, " config --quiet"):
|
case strings.HasSuffix(joined, " config --quiet"):
|
||||||
return "compose config", compose.Result{}
|
return "compose config", compose.Result{}
|
||||||
case strings.HasSuffix(joined, " up --detach catalog-db"):
|
|
||||||
return "catalog db", compose.Result{}
|
|
||||||
case strings.HasSuffix(joined, " --profile catalog-maintenance run --rm catalog-migrate"):
|
|
||||||
return "catalog migrate", compose.Result{}
|
|
||||||
case strings.HasSuffix(joined, " build"):
|
case strings.HasSuffix(joined, " build"):
|
||||||
return "compose build", compose.Result{}
|
return "compose build", compose.Result{}
|
||||||
case strings.HasSuffix(joined, " up --detach --remove-orphans"):
|
case strings.HasSuffix(joined, " up --detach --remove-orphans"):
|
||||||
@@ -465,8 +433,6 @@ func setupStage(args []string) (string, compose.Result) {
|
|||||||
return "authentication", compose.Result{Stdout: `{"ready":true,"mode":"oidc","checks":[{"level":"info","code":"auth_ready","message":"Authentication is ready."}]}`}
|
return "authentication", compose.Result{Stdout: `{"ready":true,"mode":"oidc","checks":[{"level":"info","code":"auth_ready","message":"Authentication is ready."}]}`}
|
||||||
case strings.Contains(joined, "exec -T core node dist/operator-command.js workflow-doctor"):
|
case strings.Contains(joined, "exec -T core node dist/operator-command.js workflow-doctor"):
|
||||||
return "workflow doctor", compose.Result{Stdout: `{"ready":true,"workspaces":1}`}
|
return "workflow doctor", compose.Result{Stdout: `{"ready":true,"workspaces":1}`}
|
||||||
case strings.Contains(joined, "operator-command.js workspace-pull"):
|
|
||||||
return "workspace pull", compose.Result{Stdout: `{"ready":true,"status":"succeeded"}`}
|
|
||||||
case strings.Contains(joined, "exec -T core curl -fsS --max-time 5 http://127.0.0.1:8787/health"):
|
case strings.Contains(joined, "exec -T core curl -fsS --max-time 5 http://127.0.0.1:8787/health"):
|
||||||
return "core HTTP", compose.Result{}
|
return "core HTTP", compose.Result{}
|
||||||
case strings.Contains(joined, "exec -T frontend wget -q -T 5 -O /dev/null http://127.0.0.1:8080/"):
|
case strings.Contains(joined, "exec -T frontend wget -q -T 5 -O /dev/null http://127.0.0.1:8080/"):
|
||||||
|
|||||||
Reference in New Issue
Block a user