Replaces the static /enterprise-hero.png on the /enterprise page with a live
React component (LandingEnterpriseHero) that renders the same dashboard as an
interactive leaderboard with three tabs.
- Departments: flat list (no technical/business split). Adoption-trend
sparkline per team, colored green/gray/red by direction. Engineering now
absorbs former Data Science (48/82, \$330K, JC+LT+AL+5). Customer Support
trending up, Legal falling to zero.
- Power users: 7 famous scientists/programmers/businesspeople with cumulative
weekday trend sparklines whose shape encodes personality (Carmack's bursts,
Turing's scheduled-automation linearity, Hopper removed, Lovelace's early-
adopter flattening, Carnegie's late ramp, etc.). Tools: Zed (Carmack),
Omarchy (Linus), Hugging Face (Lovelace), Claude Code (Turing).
- AI tools: tool, penetration, top department, and power-user avatars
colored by each person's home department so viewers see cross-functional
adoption at a glance.
Interactivity kept minimal: row hover background for scan, tab color
transitions, native title-attribute tooltips on avatars/tool glyphs/
sparklines. No fake animations.
Header consolidated into a single row: OpenWork logo + Q2 pill + breadcrumb
on the left, Search/Bell/AG on the right. Old wordmark and dead whitespace
removed. Total hero height ~705px (down from 1018px).
Screenshots under ee/apps/landing/screenshots/.
* feat(landing): add enterprise hero image
Add a hero screenshot below the enterprise page headline showing the
OpenWork AI-adoption dashboard. Frames the image with the same
rounded-[2rem] + border treatment used by the compliance and deployment
cards further down the page so the hero matches the rest of the layout.
* feat(landing): use rounded-xl on hero card to match stack cards
Return from GitHub install completion as soon as the connector account exists
instead of eagerly scanning every visible repo, and use explicit browser
navigations for the post-install and start-discovery transitions. Also keep the
add-repo screen in a loading state until the connector account query settles so
it no longer flashes a false not-found state.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(plugin-system): add GitHub connector, discovery, marketplaces, and access UX
End-to-end GitHub App connector flow and UI:
- GitHub App connect: install start/callback/complete endpoints, connector account upsert from installation, selection state, and a dedicated Den Web setup page.
- Repo discovery: GitHub tree + manifest inspection, Claude-compatible classification (marketplace/plugin-manifest), marketplace plugin metadata/component path parsing, discovery API + snapshot.
- Apply pipeline: materialize plugins, connector mappings, config objects (with frontmatter-aware skill/agent parsing), memberships, and source bindings; create marketplaces with name/description from marketplace.json.
- Auto-import on push: persist flag on connector instance, webhook-driven re-apply for new discoveries.
- Cleanup: cascading disconnect on connector account removal and remove on connector instance.
- Integrations UI: cleaner connected-account card, GitHub avatar, hover trash + confirm dialog, inline "Add new repo" action, per-account repo picker, manifest badges, configured/unconfigured sorting.
- Discovery UI: cleaner loader, plugin cards with component chips, inline apply action, auto-import toggle default on.
- Manage UI: instance configuration endpoint, auto-import toggle, remove repo danger zone with cascade confirmation.
- Plugins & Marketplaces pages: dashboard nav entries, list + detail screens, per-plugin component counts, marketplace resolved endpoint with source + plugins, marketplace access section (org-wide/team/member grants).
- Bitbucket card marked "Coming soon".
- PRDs, GitHub setup instructions, and learnings docs added.
* chore(docs): move GitHub-instructions.md into prds/new-plugin-arch/github-connection
* fix(den-web): wrap github integration page in Suspense for useSearchParams
* refactor(den-web): redirect GitHub post-install flow into the clean account selection phase
After completing the GitHub App install, previously we rendered a separate
GithubRepositorySelectionPhase with different styling. Now we call the install
completion endpoint, then router.replace to ?connectorAccountId=... so the
existing GithubConnectedAccountSelectionPhase renders the repo list. Removes
the duplicate selection phase and its unused helpers/imports.
* fix(den-web): drop Requires-scopes body and show GitHub description in integrations card
Removes the empty-state Requires scopes: <code>… block from both provider
cards and restores the provider description on the GitHub card so the empty
state is consistent with Bitbucket. Drops the header's bottom border when no
body follows.
* fix(den-web): only show integration provider description in empty state
Once a provider has connections, hide the description in the header so the
card focuses on the connected accounts + repos list.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(app): gate desktop updates by org config
Return allowed desktop versions through the signed-in desktop config endpoint and only surface Tauri updates when both the server and active org explicitly allow them, logging failures silently for debugging.
* fix(app): trace den-gated update checks
Wait for Den auth hydration before the startup update check and add debug logging around auth restoration and update gating so local-vs-cloud version decisions are visible while testing.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
Users were confused when adding or editing an LLM provider because the
display name was derived automatically from the catalog or pasted
config. This made it impossible to tell two keys for the same provider
apart (e.g. 'OpenAI personal' vs 'OpenAI prod').
- Add an explicit 'Name' field to the add + edit LLM provider forms in
ee/apps/den-web with a 'Give this key a name' prompt, preload the
current name when editing, and require a non-empty value before save.
- Require 'name' on the llm-provider write schema in ee/apps/den-api and
persist it verbatim instead of falling back to provider.name from the
models.dev catalog or the custom config JSON.
Verified end-to-end via Chrome DevTools MCP on the Den Docker stack;
screenshots captured under ee/apps/den-web/docs/screenshots/.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(den): let orgs restrict supported desktop versions
Give org settings a desktop version allowlist derived from the server-supported range so admins can block specific releases without exposing stale metadata.
* fix(den): simplify desktop version settings copy
Reduce the prominence of the supported-version helper text and remove the redundant summary box so the allowlist stays focused on the actual version choices.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(app): enforce desktop restriction policies
Keep org desktop restrictions consistent in the desktop client by hiding blocked provider/model paths and syncing workspace config when Zen access is disabled.
* fix(app): persist provider disconnects in workspace config
Keep config-backed providers disabled through the same opencode.jsonc flow used by desktop restrictions so disconnecting OpenCode writes the workspace disabled_providers state reliably.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
Treat legacy '/v1/orgs/:orgId/*' forwarding differently from API-key scoping so proxied requests can still hydrate a missing session active organization. This keeps older clients working across moved endpoints while preserving API-key behavior.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* fix(den): support legacy org invitation routes
Restore the old org-scoped invitation paths and rehydrate sessions to a user's first organization when activeOrg is missing so older clients keep working. Include the shared types workspace in Den Docker images so the local verification stack can still build.
* fix(den): proxy legacy org-scoped routes
Route legacy '/v1/orgs/:orgId/*' requests into the new unscoped '/v1/*' handlers while preserving the current '/v1/orgs/...' endpoints. Pass the org id through middleware so old clients keep the intended workspace context and add coverage for the generic proxy behavior.
* refactor(den): trim invitation route churn
Drop the leftover invitation-specific handler extraction now that legacy org-scoped forwarding is handled generically in the org router. Keep the proxy behavior intact while returning the invitation routes closer to their original shape.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(landing): SEO metadata, JSON-LD, H1 fixes, manifest
Raises the site's traditional SEO to match its strong agent-readiness
foundations (llms.txt, api-catalog, markdown negotiation).
Metadata:
- Root layout: canonical, og:type/siteName/locale, explicit robots
- Per-page canonical + openGraph.url on every route
- Rewritten titles/descriptions for /pricing, /enterprise, /den, /download
(previously 14-21 char titles and 51-73 char descriptions)
- /feedback and /starter-success marked noindex,follow
- /feedback removed from sitemap; /privacy and /terms demoted to 0.3
- Title dash normalized to em-dash site-wide
Headings:
- /den gains a real <h1> (was <h2> only — a11y + SEO bug)
- /enterprise H1 rewritten to be enterprise-specific (was a dup of home)
- /pricing H1 enriched; tier names promoted to <h2> in pricing-grid
- /download nav-card duplicate H2s demoted to spans
- lib/agent-markdown.ts H1s realigned with HTML for agent parity
Structured data:
- New components/structured-data.tsx helper
- Organization on every page (root)
- SoftwareApplication on / and /download
- Product with three Offers on /pricing
Manifest & perf:
- New app/manifest.ts
- Enterprise hero: 12MB PNG -> 1.1MB JPEG (1600px q70)
Old PNG left in public/ for a follow-up cleanup commit
* chore(landing): remove unused /den marketing page
Deletes the /den route and its components (LandingDen, DenHero) along
with every internal reference. The cloud product is still linked from
nav + footer, pointing at https://app.openworklabs.com.
- Removed from sitemap.ts, middleware.ts matcher, and agent-markdown
(both the markdown twin and the "Den (team workspace)" home mention)
- Removed from llms.txt routing list and site map
- Footer "Cloud" link now points to the external app (matches nav)
- Nav internal key renamed from "den" to "cloud" and type union updated
- WebMCP navigate_to destinations no longer advertise "den"
api-catalog still references "OpenWork Den API" since that's the API
product name, not the marketing page — untouched.
* fix(landing): point nav + footer Cloud link at /cloud redirect
Previous removal of /den hardcoded the external app URL into the nav
and footer. Switch to the /cloud internal path so the existing cloud
redirect is the single source of truth (and works consistently with
the rest of the internal links).
* docs(landing): restore Cloud mentions in llms.txt and agent-markdown
The previous /den removal also stripped every Cloud mention from the
agent-facing text. Restore them pointing at /cloud (which redirects to
https://app.openworklabs.com) so agents can still route users to the
hosted workspace.
* fix(landing): link Cloud directly to app.openworklabs.com, not /cloud
There's no /cloud route on the marketing site — the hosted app lives
at https://app.openworklabs.com. Point every Cloud link (nav, footer,
llms.txt, agent-markdown, WebMCP) at the real URL.
* feat(landing): replace Trust details link with Security Review CTA
The old small Trust details text link under the Book a call button got
lost. Surface it as a proper secondary CTA next to Book a call, and
rename to Security Review to set expectations for enterprise buyers.
Also updates the enterprise markdown twin to mirror the label.
* fix(landing): preserve og:type/siteName/locale/images on pages overriding openGraph
Next.js replaces (not merges) the openGraph object across layout/page
boundaries. Earlier per-page metadata added only og:url, which silently
wiped og:type, og:siteName, og:locale, and og:image off every page that
did so — exactly the fields the root layout relied on for defaults.
Introduce lib/seo.ts with a baseOpenGraph constant and spread it into
every per-page openGraph override. Caught by running the PR's test plan
against the dev server: 12 failing checks → 0 after this fix.
* feat(landing): rasterize SVG into favicon.ico + PNG icon set
Adds proper raster icons for browsers/OSes that don't render SVG
favicons (older Safari, Android home-screen, Windows taskbar):
- app/favicon.ico — 32×32, PNG-in-ICO container
- app/icon.png — 192×192
- app/apple-icon.png — 180×180
Uses Next.js App Router icon-file convention — Next auto-generates the
<link rel="icon"> / <link rel="apple-touch-icon"> tags, so the
manual icons: metadata block in app/layout.tsx is removed.
Manifest updated to advertise the 192×192 PNG (the Android PWA pick)
alongside the 180 apple-icon and the SVG mark.
All three PNGs generated from public/openwork-mark.svg with sharp,
centered on a white square canvas with ~10% padding so the mark
doesn't bleed to the edges at any size. Generator script at
/tmp/generate-favicons.mjs (not committed) — re-run any time the
source SVG changes.
* fix(landing): match /enterprise H1 styling + copy to /
The /enterprise hero H1 used slightly different Tailwind classes (mb-6,
leading-[1.05]) than the homepage H1 (mb-5, leading-[1.1]), giving a
visibly different type rhythm. Align to the home page classes.
Copy updated to 'A privacy-first alternative to Claude Cowork for your
org' — clearer positioning than 'OpenWork for the enterprise'. Mirrored
in the agent-markdown enterprise twin for parity.
* fix(landing): use 'organization' not 'org' in /enterprise H1
* fix(landing): restore original /enterprise hero subhead copy
* fix(landing): open Docs in a new tab from the main nav
Footer's Docs link already opens in a new tab; the top nav didn't. Add
an explicit newTab flag to the nav items array and honor it in both
the desktop and mobile menus so visitors keep the marketing tab open
while reading docs.
Adds three agent-readiness features on openworklabs.com:
- Markdown content negotiation: middleware serves hand-authored
markdown twins for /, /pricing, /enterprise, /den, /download, and
/trust when Accept: text/markdown outranks text/html. Sets
Content-Type: text/markdown; charset=utf-8, Vary: Accept, and an
X-Markdown-Tokens estimate. Browsers still get HTML by default.
- API catalog (RFC 9727): /.well-known/api-catalog returns an
application/linkset+json document pointing at api.openworklabs.com's
openapi.json, /docs/api-reference, /health, and llms.txt. Advertised
from the home page via the Link header.
- WebMCP: a client component calls navigator.modelContext.provideContext
on mount with four tools — navigate_to, open_enterprise_contact,
get_pricing_summary, and get_download_links. Submit-style mutations
are intentionally excluded; agents navigate users to forms instead of
posting on their behalf.
* feat(landing): make site agents-ready
Adds robots.txt with AI crawler rules and Content-Signal (ai-train=no,
search=yes, ai-input=yes), an RFC-compliant sitemap.xml, Link headers
pointing agents to /docs and the agent-skills index, and exposes the
workspace-guide skill at /.well-known/agent-skills/ with a sha256-verified
index.json.
* feat(landing): permit AI training in Content-Signal
* feat(landing): simplify robots.txt and add llms.txt navigation guide
Collapse robots.txt to a single User-agent: * Allow: / block (matching
the Huggingface pattern) — all per-bot entries had identical rules, so
the wildcard already covers them and future bots without maintenance.
Content-Signal remains permissive (ai-train=yes, search=yes, ai-input=yes).
Add llms.txt per the llmstxt.org spec — the main gap Cloudflare's
agent-readiness checklist identifies for this site. It tells agents how
to route users based on intent (download, pricing, enterprise, den),
what agents can do once OpenWork is installed, and how the cloud plan
differs from the desktop app.
* docs(landing): neutral llms.txt tone, drop feedback routing
Drop the routing entry that sends agents to /feedback — feedback should
come from humans, not agent-mediated submissions. Rephrase the agents
note from 'we want usage' to a neutral statement of what agents may do.
Introduce org-scoped marketplaces so teams can curate and share groups of plugins with consistent access rules. This adds the schema, admin routes, RBAC updates, and PRD coverage needed for marketplace-backed plugin catalogs.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* fix(den-api): surface invitation email send failures instead of swallowing
Loops failures in sendDenOrganizationInvitationEmail and
sendDenVerificationEmail were being caught and logged at warn level,
so the HTTP handlers still returned 201 'Invitation created' even when
no email ever left the process. Ben observed this with two live
invitations: the DB row was pending, the UI showed it, but one of two
recipients never received the email and clicking resend re-ran the same
silent-failure path.
Root cause (from an explore audit):
- email.ts:129,132 swallowed non-2xx Loops responses and fetch throws.
- invitations.ts awaited the send and unconditionally returned 2xx.
- There is no 'skip email if user already exists' branch anywhere;
the Slack hypothesis was wrong. The failure mode is provider-side and
was invisible because of the swallow.
Changes:
- Introduce DenEmailSendError with a stable reason tagged union
(loops_not_configured | loops_rejected | loops_network).
- sendDenOrganizationInvitationEmail and sendDenVerificationEmail now
throw DenEmailSendError on failure. Dev-mode short-circuit is
preserved (still logs the payload and returns cleanly).
- POST /v1/orgs/:orgId/invitations catches DenEmailSendError, logs via
console.error with a stable [auth][invite_email_failed] prefix
(greppable across deployments), and returns 502
invitation_email_failed with a human-readable message and the
invitationId so the UI can correlate and offer a retry. The row is
left pending intentionally so the next submit becomes a real resend.
- Document the 502 response in the OpenAPI describeRoute.
Operator note: if LOOPS_TRANSACTIONAL_ID_DEN_VERIFY_EMAIL is unset the
signup OTP endpoint will now return a real error instead of silently
stranding the user at the OTP screen forever. This is intentional; the
previous behavior was a latent signup-breaking bug.
* fix(den-api): tolerate missing apps/desktop/package.json in Docker build
PR #1476 introduced a build step that reads apps/desktop/package.json to
bake in a default latest-app-version, but packaging/docker/Dockerfile.den
does not ship the Tauri desktop sources. As a result, the den-dev Docker
stack fails to build after the PR landed. Gracefully fall back to 0.0.0
(matching the runtime default) when the file is absent, and allow a
DEN_API_LATEST_APP_VERSION env override so deployers can still pin a
real value.
* test(den-api): add smoke script for invite email failure paths
scripts/smoke-email-failures.mjs exercises the DenEmailSendError paths
against the built dist/ of den-api. Ships with instructions so a
reviewer can rerun it inside the docker-compose den-dev container with
a single command.
Also parameterises OPENWORK_DEV_MODE in the den compose service so the
failure paths can be reached from outside the container when needed
(defaults to 1; override with OPENWORK_DEV_MODE=0 at compose time).
* feat(den-api): add PATCH /v1/orgs/:orgId to rename organization
- Owners can update the display name (2-120 chars) via a new PATCH route.
- Slug stays immutable to keep dashboard URLs stable.
- Adds updateOrganizationName helper in orgs.ts.
* feat(den-web): rename organization from Members page
- Adds an 'Organization' settings card above the Members tabs with inline
rename for workspace owners.
- Non-owners see a read-only summary explaining who can rename.
- Wires a new updateOrganizationName mutation through OrgDashboardProvider
that calls PATCH /v1/orgs/:orgId.
* fix(den-api): tolerate missing apps/desktop/package.json in Docker build
PR #1476 introduced a build step that reads apps/desktop/package.json to
bake in a default latest-app-version, but packaging/docker/Dockerfile.den
does not ship the Tauri desktop sources. As a result, the den-dev Docker
stack fails to build after the PR landed. Gracefully fall back to 0.0.0
(matching the runtime default) when the file is absent, and allow a
DEN_API_LATEST_APP_VERSION env override so deployers can still pin a
real value.
* docs(den-web): add rename organization screenshots
Captured via Chrome MCP against packaging/docker/den-dev-up.sh:
- before: Members page shows Organization card with Rename button.
- editing: inline form with the current name pre-filled.
- after: new name shown with success state, sidebar also updated.
* refactor(den-web): extract DenCard primitive and drop drop shadows
The dashboard has been inlining the same card style (rounded-[30px] + p-6
+ shadow-[0_18px_48px_-34px_rgba(15,23,42,0.22)]) on every form surface.
Per Den visual language we do not use drop shadows, so the repeated
shadow class is both incorrect and a copy-paste risk.
- Add ee/apps/den-web/app/(den)/_components/ui/card.tsx exporting DenCard
with two size presets (comfortable + spacious). Shadows are explicitly
omitted and the component is designed so they cannot be re-introduced
via className (no tokens ever emit shadow utilities).
- Replace all five inline cards in manage-members-screen.tsx with DenCard.
- Replace the reused sibling card in api-keys-screen.tsx with DenCard.
- Re-capture members-rename screenshots against the refactored UI.
Introduce a new /integrations route under the org dashboard where users
can simulate connecting GitHub or Bitbucket through a realistic OAuth-
style wizard. The Plugins page now only shows its catalog once at least
one integration is connected; connecting more providers unlocks more
plugins.
- Integrations list card per provider (GitHub, Bitbucket) with connect /
disconnect actions, connected account chips, and repo pills.
- Multi-step connect dialog: authorize -> select account -> select repos
-> connecting -> connected. Dismissable, fully keyboard accessible,
matches the existing OrgLimitDialog scrim/card frame.
- Data layer uses TanStack Query mutations; connections live only in the
React Query cache (in-memory, per user's request). Mutations
invalidate both ['integrations', 'list'] and ['plugins'], so the
Plugins page updates in place when you connect or disconnect.
- plugin-data: each plugin now declares requiresProvider ('any' |
'github' | 'bitbucket'). The plugins queryFn reads the integration
cache and filters accordingly; the catalog stays empty with zero
connections.
- plugins-screen: new 'Connect an integration' empty state with a CTA
that deep-links to /integrations.
- No sidebar entry added (hidden page per request). Header title is
mapped to 'Integrations' so navigating manually still feels coherent.
All data is mocked; the same hook surface (useIntegrations / useConnect
Integration / useDisconnectIntegration / usePlugins) will back a real
API with a one-line queryFn swap later.
Introduce a new /plugins route under the org dashboard that lists plugins
(bundles of skills, hooks, MCP servers, agents, and commands) with a
list view, per-plugin detail view, and tabbed cross-cutting views for
all skills/hooks/MCPs.
- Reuses existing dashboard primitives: DashboardPageTemplate,
UnderlineTabs, DenInput, PaperMeshGradient cards.
- Mirrors the skill-hubs list/detail patterns 1:1 for visual coherence.
- Introduces @tanstack/react-query (scoped to the dashboard subtree)
with a mock queryFn so the data layer can swap to a real API later
with a one-line change.
- Hidden by design: no sidebar nav entry. Reachable only via direct URL
/o/<slug>/dashboard/plugins. Header title is mapped to 'Plugins' so
navigating manually still feels coherent.
Bring back Windows desktop artifacts in release workflows and remove the paid landing flow so Windows users can download public installers again.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
Pass the enterprise stack demo state setter through LandingAppDemoPanel's onSelectFlow prop so the landing build typechecks and compiles.
Made-with: Cursor
Update enterprise hero copy and remove shell/backdrop/shadow styling from enterprise content blocks and contact form so the page matches the current flat visual system.
Made-with: Cursor
Replace the enterprise stack cards with updated messaging, larger media areas, and real Cloud/Skill Hub/Onboarding screenshots plus a live OpenWork demo shell so the section reflects the actual product experience.
Made-with: Cursor
Remove the home-page pricing tagline and LLM provider showcase, and update the middle pricing card to Team starter with revised price and feature copy for team access.
Made-with: Cursor
Replace the old commercial EE terms with the new Functional Source License so the enterprise licensing model is explicit and time-bounded. Clarify the root license reference to the EE directory so readers can find the governing terms quickly.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* fix(den): make desktop signin state update immediately
* fix(den): support local auth verification and handoff
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
Reduce redundant helper copy and tighten the Den management layouts so the important controls are easier to scan. Update button content alignment so icon and text actions render consistently across the refreshed screens.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* fix(den): validate TypeIDs in API schemas
Use the shared TypeID utility in den-api request and response schemas so invalid IDs are rejected consistently and Swagger documents the expected prefixes. Keep the API docs aligned with the live validation rules used by the app.
* docs(den): refine OpenAPI route visibility
Hide internal and sensitive Den routes from Swagger so the published docs stay focused on public workflows. Clarify route tags and permission descriptions so ownership and workspace-admin requirements are easier to understand.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
Generate an OpenAPI spec and Swagger UI from den-api's existing Hono and zod validators so the API stays self-describing. Add route metadata, typed responses, and hide API key creation endpoints from production docs.
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(den): add org API key auth and management
Let org owners and admins manage named API keys while keeping keys scoped to the issuing member and org. Reuse existing org middleware so API-key-backed requests behave like normal user actions across Den routes.
* fix(den): polish API key creation flow
Avoid duplicating the visible key prefix in the table preview and make key creation an explicit one-time reveal flow. Show the create form only after the user asks for a new key, then replace it with the copyable secret after issuance.
* fix(den): simplify API key table UI
Remove rate-limit details from the Den web API keys screen and keep the page focused on naming, reveal, and deletion. Leave the generated next-env types file out of the commit.
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* feat(den): add org-managed llm provider library
Let Den admins curate shared providers and models with encrypted credentials, then let the app connect through the existing add-provider flow. This keeps org-wide model access consistent without requiring per-user OAuth setup.
* docs(den): prefer longer db encryption keys
* fix(den): pass db encryption key through local dev
---------
Co-authored-by: src-opn <src-opn@users.noreply.github.com>
* docs(landing): add privacy policy and terms of use pages
- Add comprehensive privacy policy covering Desktop App (no tracking),
Cloud Service (operational telemetry only), and Website (PostHog analytics)
- Add terms of use with AI output disclaimer, export controls, beta features,
feedback, publicity rights, and JAMS arbitration
- Create reusable LegalPage component and shared parser for .txt legal docs
- Add Privacy and Terms links to site footer
- Both pages render with consistent styling, bold definition terms,
subheadings for tracking technology categories, and clickable email links
* chore: add .turbo to .gitignore
* fix(landing): improve legal page parser for terms readability
- Detect definition blocks ("Term" means ...) and render as bulleted
list with bold terms
- Bold ALL CAPS text (warranty disclaimers, arbitration notices, etc.)
- Make URLs clickable links alongside emails
- Distinguish h2 headings (questions, longer titles) from h3 subheadings
(short section names like "Our IP", "Billing", "Usage Data")
* fix(landing): improve subscription termination wording and URL parsing
- Clarify recurring billing cancellation: users can cancel via account
settings first, contact email as fallback at our discretion
- Fix URL regex to avoid capturing trailing periods/punctuation
* fix(landing): clarify subscription cancellation — email always accepted, late refunds at our discretion
* docs(landing): convert privacy policy and terms of use to markdown
- Add proper heading hierarchy (# h1, ## h2, ### h3)
- Bold definition terms, ALL CAPS legal clauses, and sub-processor names
- Convert restriction items into bullet points
- Make all URLs and emails clickable markdown links
- Use blockquote for the API key disclaimer note
- Structure tracking technologies as proper subheadings
* refactor(landing): use markdown for legal pages, no new dependencies
- Rename .txt to .md with proper markdown formatting
- Replace txt parser with lean render-markdown.tsx (zero deps, ~120 lines)
- LegalPage handles full page shell — page.tsx files are now 8 lines each
- Add legal-prose CSS for consistent typography
- Delete parse-legal-doc.tsx