Skip to content

v0.2.69

Choose a tag to compare

@larryro larryro released this 06 May 04:22
81f5a5c

v0.2.69 — Marketing site, optional SOPS, version-pinned installs

This release ships the public marketing site at services/web (with a shared @tale/ui library and plop scaffolding), makes SOPS encryption optional for provider secrets, and adds version-pinned CLI installs and downgrades. It also closes a thread-access regression on deleted-org and ex-member states, and stops the failover loop when no provider is configured.

🔒 Security

  • Closed access bypass and Convex subscription leaks on deleted-org / ex-member threads. canAccessThread no longer waves owners through unconditionally — current org membership is required, with expectedOrgId letting hot-path callers parallelize the membership read. Layout chrome and child routes now bail out cleanly when memberContext is invalid, tearing down org-scoped observers, and isPersonalizationActiveForChat returns false on miss instead of throwing (#1671).

💥 Breaking Changes

  • The guardrails secret_box now derives its HKDF input from ENCRYPTION_SECRET_HEX instead of SOPS_AGE_KEY. Operators with an existing moderation-provider auth header must re-save it once after upgrade — see the Migration Guide below (#1672).

🚀 Features

  • Marketing site launched at services/web (TanStack Start + Vite + Tailwind v4) with home / pricing / hardware-pricing / request-demo / contact pages and full en/de/fr i18n (plus de-AT / de-CH / fr-CH overrides). Shared UI primitives extracted into @tale/ui so platform and web consume one source of truth, and a new tools/plop/ directory provides generators for react-service, react-package, python-service, python-package, typescript-package, and docker-service (#1667).
  • Marketing site polish: 16 SVG illustrations replace raster mockups across feature-secure / feature-sectors / compliance-trust / feature-grid; sticky-only-on-tier-cards comparison header on /pricing and /hardware-pricing; new TierCard / CompareTable / ProgressBar shared components; locale-aware footer language switcher with country flags. PII-redaction added to the comparison table; hardware buy prices corrected to 31.7k / 32.9k / 35.3k CHF (#1673).
  • SOPS provider-secret encryption is now optional. Hybrid read path detects SOPS-shaped JSON and shells out to sops -d; otherwise returns plaintext as-is. Write path encrypts when an age key is configured and writes 0600 plaintext otherwise. SOPS_AGE_KEY_FILE is now honored on write (Vault / K8s Secret / systemd LoadCredential workflows). Wrong/rotated/missing keys no longer silently overwrite existing files — refusal surfaces as a destructive ConfirmDialog with a force-override path. en/de/fr docs updated for the two-mode model (#1672).
  • Version-pinned CLI installs: scripts/install-cli.{sh,ps1} honor a VERSION env var (downgrades included) with a friendly 404 message and pre-flight HEAD probe; tale upgrade --version <tag> migrates or downgrades to an exact release with a warning when downgrading that newer-version schema changes persist in the database (#1664).

🛠 Improvements

  • New Docker Desktop quickstart at docs/self-hosted/install/quickstart.md (~10 min), new docs/develop/integrations.md covering config.json / connector.ts / sandbox API, Member-role orientation reframe of platform/member/overview.md, and reworked platform/integrations/overview.md around the connector model. Translated to en/de/fr; footer "Getting started" link points at the new quickstart (#1664).
  • New web front-page designs added under designs/web/frontpages.pen (hero, contact, request-demo) with shared design-system components and image assets (#1666).
  • .env.example now explicitly marks SOPS_AGE_KEY, INSTANCE_SECRET, and the database section as REQUIRED — both keys are auto-generated by tale init but now surface as required to operators reading the file (#1668).

🐛 Fixes

  • NoProviderAvailableError is now treated as terminal in the failover chain — chat surfaces the friendly "Open Settings → AI providers" message instead of cycling through fallback models that would all hit the same empty provider list. Cross-action serialization (Convex's Uncaught NoProviderAvailableError: prefix) is matched in addition to instanceof (#1670).
  • Org owners can delete their own organizations again. The owner role is now distinct from admin and spreads ownerAc.statements (organization: ["update", "delete"]) — regressed when creatorRole was switched to owner and aliased to admin (#1669).
  • Added an explicit slug to the French operation-shape heading in docs/fr/develop/integrations.md (3f0e757).

📝 Other

  • Removed orphan operator-service code (browser_operate.ts, get_operator_service_url.ts, WebBrowserOperateResult types, thinking.browsing translations, /metrics/operator Caddyfile entry) — the operator service was already gone from the deployment (#1668).
  • Dropped orphan convex/lib/crypto/generate_secure_state.ts whose node:crypto import occasionally caused InvalidModules flakes during convex deploy. Husky pre-commit hook now passes --no-error-on-unmatched-pattern to oxfmt so commits touching only oxfmt-ignored files don't fail (#1665).
  • Renovate dependency pin pass: @types/validator, defu, libphonenumber-js, lodash-es, safe-regex2, validator, github/codeql-action, useblacksmith/setup-docker-builder (#1660).
  • Tightened Renovate config: internalChecksFilter=strict, prCreation=not-pending, rebaseWhen=conflicted, and migrated deprecated matchPackagePatterns to matchPackageNames regex form (806124a).

Upgrade

Run tale upgrade to update the CLI, then tale deploy to apply the new version.

Migration Guide

Re-save moderation provider secrets (only if you configured one). The guardrails secret_box HKDF input moved from SOPS_AGE_KEY to ENCRYPTION_SECRET_HEX, so existing encrypted moderation-provider auth headers can no longer be decrypted with the old key.

  1. After tale deploy completes, open Settings → Governance in the platform UI.
  2. Any provider with a configured auth header will display •••• (key rotated — re-save).
  3. Re-enter the auth header value and save. Chat with failBehavior.output='closed' is hard-blocked on those providers until this is done.

If you never configured a moderation-provider auth header, no action is required.

Contributors

@larryro, @yannickmonney, @AdeolaAdekoya, @renovate


Full Changelog: v0.2.68...v0.2.69