Onboarding and Host Configuration

Overview

v1.0.5 is an onboarding and host-configuration release on top of v1.0.4. Every ./ztd command now loads an owner-only repo-root .env holding user secrets and user-specific endpoints, make up-public and make gw-public start a Gateway reachable from other hosts, ztd gw start refuses to report success against a running Gateway whose startup configuration differs from the request, and an outbound Operator refuses to open a Gateway's runtime tree. The governance pipeline, protocol contracts, and storage layout are unchanged from v1.0.4.

Added

  • Repo-root .env — Every ./ztd command loads .env from the working directory at startup through config.LoadEnvFile (internal/cli/config/env_file.go). Only the secret and user_endpoint keys in protocol/constants/env_vars.json are accepted; an unknown key or a line that is not KEY=VALUE stops the command (ErrEnvFileUnknownKey, ErrEnvFileMalformed). A variable already exported in the shell wins over the file, and an explicit flag wins over both. On Linux and macOS the file is opened without following symlinks or blocking on a FIFO, and must be a regular file owned by the user or root with mode 0600 or 0400 (ErrEnvFileInvalid). A missing .env loads nothing. See Configure .env.
  • Setup creates .env — scripts/linux-setup.sh, scripts/macos-setup.sh, and scripts/windows-setup.ps1 copy .env.example to .env after building ./ztd (mode 0600 on Linux and macOS) and keep an existing .env. Every template entry is commented, so the default flow loads no keys.
  • ZTD_OLLAMA_ENDPOINT — A new user_endpoint registry key that supplies --inference-ollama-endpoint for ztd gw start, ztd operator start, and ztd operator model commands when the flag is blank. Set it in .env when the approved Ollama provider is not on the Gateway or Operator host.
  • make up-public and make gw-public — Run make up and make gw with --listen-host 0.0.0.0 so Operators on other hosts can enroll. make up and make gw stay loopback-only.
  • One-command onboarding — curl -fsSL https://zerotrustdata.io/start.sh | sh (website/static/start.sh) installs the checksum-verified release binary into ~/ztd through ztd.sh, then starts or reuses a Gateway, signs the CLI in or reuses its identity, and runs a first governed action, the same steps as make quickstart. ZTD_DIR, ZTD_VERSION, ZTD_OVERWRITE, and ZTD_MASTER_KEY_FILE are honored; a missing OS key store or a busy Gateway port prints its remedy. It never uses sudo.
  • Releases pages — https://zerotrustdata.io/releases/ lists every published version, and /releases/v<version>/ shows its binaries, sizes, SHA-256 digests, .sha256 and Sigstore bundles, pinned install commands, sha256sum and cosign verify-blob steps, and the release notes. The Worker renders them from the ztd-releases R2 bucket (website/src/releases.js); release notes are rendered at build time from docs/release_notes/ (website/src/release-notes.js).

Changed

  • ztd gw start against a running Gateway — The running-process check now precedes network identity detection. Every startup flag the caller set explicitly (--capabilities, --posture, --listen-host, --http-port, --https-port, --model-storage-root, --inference-ollama-endpoint, --public-base-url, --cors-origin, and the passkey relying-party flags) is compared with the running launch profile. A match reuses the running Gateway; a difference prints the current and requested values and fails with ErrGatewayAlreadyRunning. A ZTD_OLLAMA_ENDPOINT value (exported or from .env) counts as requesting --inference-ollama-endpoint, so editing it and rerunning make gw reports the difference instead of silently keeping the old endpoint. A bare gw start with no such value still reuses whatever Gateway is running. Previously the command reported "already running" and exited 0 while the old configuration stayed active.
  • Gateway startup output — gw start, gw restart, and gw connect print the detected network identity only when the listeners bind a routable interface. The post-start guidance is a single Console origin and a short command list (login / login web ordered by posture, a same-host or remote operator start with its own --working-dir, auth enroll pending, gw status). gw restart prints the same guidance as gw start.
  • Copy-paste-safe command output — Every command the CLI prints for the user to run sits alone on its own line, flush-left, with no quotes, prose, or indentation around it. This covers the loopback notice (gw stop, then gw start --listen-host 0.0.0.0), the gw start next steps (a purpose line, then the bare command), tunnel and swagger hints, --help text and error messages that name a command (for example Enroll first with: followed by ./ztd auth enroll user), the eval and vault hints, and the TUI status lines, where the command is unquoted at the end of the line. Stray duplicate and misspelled output, such as ztd.operator stream --help, is fixed.
  • Enrollment approval hint — Application and Operator enrollment requests print Approve on the Gateway host with: followed by ztd auth enroll approve <id> on its own line.
  • make status — make status runs ztd gw status only, which already includes the Operator inventory and pending enrollments.
  • .env.example — Lists every secret and user_endpoint registry key, including CLOUDFLARE_API_TOKEN; the make constants-check exemption for that key is removed.
  • TLS bundle logging — Per-certificate [TLS-DEBUG] bundle lines log at debug level instead of info.
  • Website reduced motion — With prefers-reduced-motion: reduce, the homepage (website/src/index.html) drops shake, jitter, and slide offsets and slows the background grid and ticker instead of disabling every animation and transition. Reveal and trace rows still fade in, and the grid stops drawing while the page is hidden.
  • Install scripts run from main — website/static/ztd.sh runs entirely from a main function called on the last line, so a truncated curl | sh download executes nothing.
  • Release set upload order — scripts/release-r2.sh upload writes ztd-binaries.json last and refuses a set without it, so the manifest's presence marks a complete set for the Releases pages.
  • Deterministic OpenAPI — .swaggo overrides webauthncose.COSEAlgorithmIdentifier to an integer so make swagger-generate output no longer depends on map order, and swag errors are reported (--quiet) instead of discarded.

Removed

  • public_feed_outbox collection constant — CollectionPublicFeedOutbox had no readers or writers and is removed from internal/constants/collections.go.
  • make up follow-up hints — The status and sign-in lines make up printed after gw start are removed; gw start prints the guidance itself.

Fixed

  • Operator in a Gateway runtime tree — ztd operator start refuses a runtime tree that holds the Gateway root CA (GatewayRuntimeMarker, pki/root/root_ca.crt) and exits with a configuration error naming --working-dir (ErrOperatorGatewayRuntime, INV-OP-STOR-03). An Operator launched from the Gateway directory without --working-dir previously opened the Gateway's audit database and vault. ztd operator reset-identity uses the same marker.
  • Local receipt reads in tests — storage.ReadLocalActionReceipt is the single reader of a runtime's sealed local receipt. Release smoke and the deploy lifecycle E2E use it; the E2E previously parsed the encrypted receipt_json as protojson. The lifecycle cancellation case omits --approve so only the worker dials the stalled HTTPS port.
  • Test isolation from .env — ztd test runners (unit, integration, E2E, coverage, release smoke, scale) start their child processes without the secret and user_endpoint keys (config.WithoutUserEnv). Because every ./ztd command loads .env, test processes previously inherited the developer's CLOUDFLARE_API_TOKEN and ZTD_OLLAMA_ENDPOINT, and the release smoke Gateway and worker inherited the developer's Ollama endpoint.
  • auth enroll user help — Named a nonexistent auth enroll operator command; it now points to operator start and auth enroll approve.
  • operator start --endpoint host:port — The global --endpoint help accepts host:port, but operator start appended its own port, so the pub/sub URL became wss://[host:port]:8443 and the Operator could not connect. The endpoint port now sets the Gateway HTTP discovery port; a port that differs from an explicit --gateway-http-port, a URL scheme, or an invalid port fails at startup with ErrGatewayEndpointInvalid. Workers deployed by operator deploy with a host:port endpoint had the same failure.
  • E2E environment keys — ztd test scale and the E2E suite exchanged twelve ZTD_E2E_* keys (ZTD_E2E_RUNTIME_ROOT, ZTD_E2E_GATEWAY_HTTP_PORT, ZTD_E2E_GATEWAY_HTTPS_PORT, ZTD_E2E_MASTER_KEY_FILE, and the ZTD_E2E_FLEET_* keys) through local string constants outside env_vars.json (INV-ENV-04). They are now test registry keys read through constants.EnvVar, and TestProductionGoEnvReads_UseRegistryKeys also rejects local string constants and covers test/.
  • Collections registry — protocol/constants/collections.json omitted ten CollectionName constants (consensus, enrollment_tokens, cli_recovery_requests, six observe_* projections, and eval_campaign_publication_state). They are listed, and TestCollectionsRegistryMatchesGoConstants fails on drift in either direction.

Tests

Evidence: this section records the commands run from the final release commit and their results, and lists any command not run. The required commands are ./ztd test lint, ./ztd test unit, make console-lint console-test console-embed-check, make constants-check, make swagger-generate, and make doctrines-validate. The record is entered before tagging.

New coverage in this release: internal/cli/config/env_file_test.go (registry keys, comments, shell precedence, missing file, unknown and host keys, malformed lines, mode, and symlinks), TestUserEndpointEnvVars_MatchRegistryUserEndpoints, TestCollectionsRegistryMatchesGoConstants, TestResolveOperatorGateway, internal/cli/cmd/gw/gateway_start_running_test.go (running-Gateway reuse and conflict), TestRefuseGatewayRuntime, test_create_env_file_owner_only_and_kept in scripts/test-onboarding.sh, website/test/start.test.js (start.sh piped into sh, dash, busybox sh, and bash --posix against a stub release host and a fake ztd: reuse, environment variables, failure remedies, truncated downloads, stdin isolation, and shellcheck), website/test/releases.test.js, and the /releases/ cases in website/test/worker.test.js. website/smoke/live.sh runs after each website deploy against production.

Documentation

  • Homepage (website/src/index.html) quick start leads with the start.sh one-command install and matches the README (INV-DOC-GEN-04), the navigation and footer link to /releases/, and the First Run Report form lists the current entry points.
  • Website Runbook — Releases pages, the listing rule, release-note fragments, onboarding scripts, and their tests.
  • README.md and .github/CONTRIBUTING.md — .env creation, ZTD_OLLAMA_ENDPOINT, make up-public/make gw-public, the running-Gateway conflict behavior, runnable protocol examples, and current setup anchors.
  • Getting Started — New "Configure .env" section and public-listener targets.
  • Unified Stack, Connect an Operator, Build an Operator, Build a Gateway, Reset Workload Identity, and Cloudflare Tunnel — Separate Operator working directories, public-listener targets, .env keys, and the ztd login re-enrollment flow.
  • Operator Architecture — INV-OP-STOR-03 and registry-based environment scrubbing. Gateway Architecture — running-Gateway startup comparison. Scripts — public-listener targets and the complete internal/tools/ catalog, which Code Map now links to instead of repeating. Operator Architecture owners name internal/services/ztdo.go and internal/services/operatorcapability/ in place of the nonexistent internal/services/operator/; Gateway Architecture describes ztd mcp agent list and show as implemented.
  • Developer Guidelines INV-ENV-04, Testing Guide INV-TEST-ISO-06 (test child processes run without .env keys), Troubleshooting vault key, audit receipt, and protocol prerequisite paths, and Constants user endpoints, test-harness keys, and the complete collections registry.

Compliance Evidence

Evidence: this section records the signed operational evidence bundle for the Gateway build assessed at release. The bundle requires a running Gateway built from the final release HEAD, governed activity from that build in the assessment window, and the release owner's report-signing key. It is generated by running ./ztd compliance release-prepare on the release commit. This section then records the bundle path, verification result, checksum root, assessment window, and source revision. The generated v1.0.5-compliance-evidence.md and v1.0.5-compliance-evidence.csv files are committed beside these notes (INV-REL-COMP-01).

Deferred

  • On Windows, .env ownership and mode are not checked, and setup copies the template without restricting its ACL.