Files
ThothII/tools/tht

Native installation CLI

Offline workspace documents (issue #43)

tht workspace prepare --directory NEW_PATH --id ID --name NAME [--language en|it] creates an ad hoc workspace repository template. tht workspace validate --directory PATH [--json] checks the working documents without an installation descriptor or services. Both commands invoke the packaged sibling tht-workspace-documents, which compiles the canonical backend YAML/Zod parsers with its runtime. Neither Node nor Bun is required on the user's computer. Validation never writes documents or Git configuration. See the IT and EN guides for the correction loop and explicit runtime checks that local validation cannot satisfy.

Maintainer build (Go from go.mod, Node/npm for build only):

cd backend
npm ci
npm run build:workspace-tools
# Cross-compile the complete platform pairs:
npm run build:workspace-tools -- --all

The output is dist/workspace-tools/<os>-<arch>/ containing tht[.exe], tht-workspace-documents[.exe], SHA256SUMS and build.json. Individual targets: windows-amd64, linux-amd64, linux-arm64, darwin-amd64, darwin-arm64. Bun is pinned in backend/package-lock.json; compilation embeds the runtime, and cross-compilation may download the selected Bun target. Deliver the complete pair from one build, verify checksums and keep the executables together. The previous build-tht.sh / install-tht.sh single-binary path remains for existing operator commands; it does not package this helper. Release publication is tracked separately in issue #46; building a Windows/Linux artifact does not establish acceptance there.

Run the same public CLI fixture corpus against the native pair, with subprocess PATH deliberately empty:

cd backend
THT_WORKSPACE_TEST_CLI=/absolute/path/dist/workspace-tools/darwin-arm64/tht \
  npx vitest run test/workspace-documents-cli.test.ts

Application document preparation (issue #44)

Before installation, use tht installation prepare --directory NEW_PATH, then tht installation credentials --directory PATH to explicitly create technical credentials in the default protected layout. The latter preserves existing files. Edit the documents and external credentials, then repeat:

tht --installation /absolute/path/thothii-installation.yaml \
  installation validate --workspaces /absolute/path/workspaces --json

database-bootstrap.yaml beside the descriptor is a schemaVersion-1 bootstrap input, not a runtime Catalog. Its database entries use the exact Catalog API configuration schema plus private secretFiles and optional evidenceSecretFiles references. --bootstrap selects another document. The helper validates workspace membership, uniqueness, supported transports and required credential references; Go checks protected files, the canonical Installation Model Catalog, environment and local administrator. No process contacts a service or creates projections. Only missing standard release Compose assets are deferred by config.LoadPrepared; normal runtime config.Load retains all existing checks. Custom overrides must exist.

The native integration test is opt-in because it requires the built pair:

THT_INSTALLATION_TEST_CLI=/absolute/path/dist/workspace-tools/darwin-arm64/tht \
  npx vitest run test/installation-documents-cli.test.ts

Run it from backend/, following the bundle build above. It supplies prepared fixtures and removes host tools from the subprocess PATH. Platform acceptance and real external credentials remain separate gates. See the IT/EN guides for the complete parameter collection procedure, default admin account and local-auth scope.

Shell configuration

The schema-v2 thothii-installation.yaml accepts this optional section:

shell:
  mode: full
  defaultLocale: en

Omitted shell settings resolve to mode: embedded, defaultLocale: en, and adapter: omics-portal. Supported modes are full and embedded. The default locale accepts well-formed BCP47 language tags, including tags without a UI catalog (for example fr-CA or sr-Latn-RS). Syntax follows RFC 5646, including private use and grandfathered tags; duplicate variants and extension singletons are rejected. The installation preserves the supplied tag; the frontend resolves available translations and falls back to English. No catalog or language-registry allowlist is imposed by the installer. The only supported adapter is omics-portal. Invalid values and unknown descriptor fields are rejected. In full mode, a known adapter setting is ignored and omitted from the resolved public configuration. Shell selection is independent of profile and authentication.

Operational guide: shell configuration and deployment. For Omics server identity, use upstream integration: the CLI's auth configure configures local/OIDC, not an upstream login. A mounted auth.yaml/runtime projection cannot coexist with core AUTH_MODE=upstream.

New installations can select these values with tht setup --shell-mode full --shell-default-locale en. The optional --shell-adapter omics-portal selects the embedded adapter explicitly. Corresponding environment answers are THT_SETUP_SHELL_MODE, THT_SETUP_SHELL_DEFAULT_LOCALE, and THT_SETUP_SHELL_ADAPTER; explicit flags take precedence. Omitting all three preserves the existing setup descriptor format and uses the defaults at load time. Setup does not overwrite an existing descriptor with different settings.

Public runtime projection

The installation generation workflow (modelprojection.Generate, used by setup, lifecycle operations, and installation generate) publishes generated/frontend/config.js next to the model artifacts, relative to the descriptor directory. It contains only:

window.__THOTHII_CONFIG__ = {
  "backendBaseUrl": "/api",
  "shell": {
    "mode": "embedded",
    "defaultLocale": "en",
    "adapter": "omics-portal"
  }
};

For full mode, shell.adapter is absent. No secret values, model configuration, authentication configuration, or host filesystem paths enter this JavaScript. The standalone browser API address remains same-origin /api; it never uses the private nginx upstream http://core:8787. The Omics document must continue to supply its same-origin /datamart-builder/api override when mounting the application under that prefix; selecting an adapter does not infer API routing.

The automatically included generated/compose.models.yaml adds a read-only file bind from generated/frontend/config.js to /usr/share/nginx/html/config.js on the frontend service. Missing sources fail instead of becoming directories (bind.create_host_path: false). The frontend receives THT_FRONTEND_CONFIG_REVISION=sha256:<hash-of-config.js-bytes> so Compose recreates it when public settings change. Shell changes do not revise core's model settings. Only the public file is mounted into the frontend, not the generated directory.

Publication retains the existing whole-generation replacement and rollback behavior. Identical outputs keep file identities; projection drift checks include the public file, Compose definition, and POSIX read permissions. Candidate directories are explicitly set to 0755 and files to 0644, independent of the host umask, so nginx and core can read their file mounts under different UIDs. The enclosing private installation directory is not made public. Existing permission drift is repaired by publishing a new complete generation, using the same rollback path as content changes. A running container requires the normal Compose lifecycle step to pick up a changed file bind. No image rebuild is needed. The generic image retains its empty fallback config, and nginx already serves /config.js with no-store, no-cache, must-revalidate.

docker/smoke/frontend-smoke.sh checks both the generic image fallback and the installed public projection. Its optional file argument permits the same check against generated output in targeted host tests.

To generate files before rebuilding or launching containers, use the upgraded CLI:

/usr/local/bin/tht --installation /Users/mp/projects/ThothII/deploy/psd/thothii-installation.yaml installation generate

This command validates the installation and publishes the common runtime generation. It invokes no Docker commands and does not modify the descriptor, authored model catalog, environment, or authentication configuration. A shell-only descriptor change preserves model projection contents, while the common generation may replace their file identities. It is not a shell-only writer: model projections are always derived from the current descriptor. Run the existing preview rebuild after this command to replace containers with the upgraded images and updated projection mounts.