Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
5b5ed13
Merge branch 'dev' into main
JOY Aug 22, 2026
1a23a85
feat(tenant): implement multi-tenant organizations with JIT and webho…
JOY Aug 23, 2026
18d7370
ci: add GitHub Actions CI and automated GHCR Docker build workflows f…
JOY Aug 23, 2026
35f7032
fix(spa): support Next.js html page resolution when directory exists
JOY Aug 23, 2026
6f854eb
fix(auth): log and surface oauth error parameters on oidc callback
JOY Aug 23, 2026
e870f2a
feat(auth): add PKCE S256 code challenge and verifier support for OID…
JOY Aug 23, 2026
97b8568
feat(auth): add PKCE S256 code challenge and verifier support for OID…
JOY Aug 23, 2026
12bb354
feat(auth): add passwordLoginEnabled setting to disable username/pass…
JOY Aug 23, 2026
56e5393
feat(config): add .env file support and standard environment variable…
JOY Aug 23, 2026
5739846
feat(config): add .env file support and standard environment variable…
JOY Aug 23, 2026
a0ab3f9
feat(tenant): add organization CRUD dialogs, member management, and C…
JOY Aug 23, 2026
453744c
feat(tenant): add organization CRUD dialogs, member management, and C…
JOY Aug 23, 2026
1ab6565
fix(ui): redirect to /dashboard upon creating or switching organization
JOY Aug 23, 2026
9c8d200
fix(ui): redirect to /dashboard upon creating or switching organization
JOY Aug 23, 2026
0160433
feat(sync): add outbound organization webhook sync dispatcher
JOY Aug 24, 2026
5cc46b0
feat(sync): add outbound organization webhook sync dispatcher
JOY Aug 24, 2026
0e3b82d
style(ui): fix font-sans resolution by loading Inter font and setting…
JOY Aug 24, 2026
341dddc
style(ui): fix font-sans resolution by loading Inter font and setting…
JOY Aug 24, 2026
4e04a2e
feat(auth): support active_org_id and organization slug claims in OID…
JOY Aug 24, 2026
0fd874a
feat(auth): support active_org_id and organization slug claims in OID…
JOY Aug 24, 2026
243b133
feat(ai): support OpenAI-compatible API config via environment variab…
JOY Aug 25, 2026
cc4116c
feat(config): add DOS.AI environment variable aliases and update .env…
JOY Aug 25, 2026
9893259
test(ai): add unit test for DOS.AI model configuration initialization
JOY Aug 25, 2026
0bf480f
test(ai): add live integration test for DOS.AI API and recursive .env…
JOY Aug 25, 2026
60e0840
feat(migration): add migration 000010 to sync support and organizatio…
JOY Aug 25, 2026
6c367c8
feat(kb): add default Crove Desk Knowledge Base & FAQs seeding and fi…
JOY Aug 25, 2026
25bcc29
feat(i18n): add Vietnamese language support, LanguageToggle component…
JOY Aug 25, 2026
9a071ad
fix(ui): fix font-sans fallback to prevent Times New Roman and bind p…
JOY Aug 26, 2026
70dc246
feat(mcp): support Twenty CRM MCP configuration and add comprehensive…
JOY Aug 26, 2026
c67449b
feat(ui): refine sidebar font size to compact 13.5px and support DOS-…
JOY Aug 26, 2026
f9d6217
feat(i18n): localize hardcoded UI strings in AI Workflows and Support…
JOY Aug 26, 2026
4c65650
feat(i18n): comprehensively translate AI execution traces, agent runs…
JOY Aug 26, 2026
3ed41ce
feat(sync): implement 2-tier hybrid sync for Company and Customer ent…
JOY Aug 26, 2026
f3088e4
docs: add CHANGELOG.md documenting versions and features
JOY Aug 26, 2026
bedd366
feat(sync): add outbound event dispatching for company and customer c…
JOY Aug 26, 2026
9711beb
feat(channel): implement native Telegram channel integration and auto…
JOY Aug 26, 2026
b4fc306
chore(config): replace live credentials with placeholders in docker s…
JOY Aug 26, 2026
443a6f9
feat(channel): implement Zalo OA channel adapter and automated Telegr…
JOY Aug 27, 2026
40d5f6c
feat(webhook): register /api/webhooks/ecosystem route alias for Crove…
JOY Aug 27, 2026
cd95ff1
fix(oidc): use client_secret_basic auth style in token exchange and s…
JOY Aug 27, 2026
1ada550
feat(branding): add custom companyFaviconUrl, high-res Crove SVG asse…
JOY Aug 27, 2026
2750302
fix(ai-agent): resolve MCP catalog failure blocking AI configs load a…
JOY Aug 28, 2026
43c07aa
fix(i18n): add common.cancel and common.status translation keys
JOY Aug 28, 2026
b71fbb7
test(web): fix paths and assertions in node unit tests across web com…
JOY Aug 28, 2026
d471f78
ci(workflow): add automated upstream release sync and dual-image buil…
JOY Aug 28, 2026
f6c0cdd
fix(ci): handle existing tag ref gracefully and push fetched upstream…
JOY Aug 28, 2026
7e95658
chore(config): update internal crm mcp endpoint in example config
JOY Aug 28, 2026
3817f4d
feat(channel): add native email channel support with brevo and smtp i…
JOY Aug 28, 2026
63c0853
feat(email): complete multi-provider inbound and outbound email suppo…
JOY Aug 31, 2026
df375ad
docs(config): add comprehensive email provider environment variables …
JOY Aug 31, 2026
e905267
fix(email): support universal field mapping and heterogeneous headers…
JOY Aug 31, 2026
00fa48a
feat(scripts): add Cloudflare Email Routing inbound forwarder worker …
JOY Sep 1, 2026
1ab53d0
Merge remote-tracking branch 'upstream/main' into main
JOY Sep 1, 2026
8b6b90b
Merge branch 'main' into dev
JOY Sep 1, 2026
7b013b8
fix(ci): lowercase repository name for GHCR docker tags to prevent up…
JOY Sep 1, 2026
e3843f1
docs(rules): add SaaS multi-tenant architecture and product guidelines
JOY Sep 2, 2026
8a53f8e
feat(email): add multi-tenant forwarding address resolution help@<slu…
JOY Sep 2, 2026
b2994a1
feat(conversation): add private internal notes support with tab toggl…
JOY Sep 2, 2026
54be4a8
fix(models): normalize CommentReport CreatedAt column tag for Postgre…
JOY Sep 2, 2026
793abd7
feat(email-worker): configure account id and lockfile for cloudflare …
JOY Sep 2, 2026
a9b481f
fix(ai): add robust ChatWithTools fallback in einoAgentLoop to preven…
JOY Sep 2, 2026
69107bc
chore(deps): upgrade eino to v0.9.19 and typescript to v7.0.2
JOY Sep 2, 2026
0e199f0
chore(flowgram): update pnpm-lock.yaml for typescript 7 in flowgram-e…
JOY Sep 2, 2026
b65cfca
chore(deps): update TypeScript to stable 5.9.3, migrate next.config t…
JOY Sep 2, 2026
9c4ab5e
chore(deps): upgrade TypeScript to v6.0.3 across web, flowgram-editor…
JOY Sep 2, 2026
470595d
Merge remote-tracking branch 'upstream/main'
JOY Sep 7, 2026
d1c24e0
Merge remote-tracking branch 'upstream/main' into feat/email-channel-…
JOY Sep 22, 2026
c35873d
chore: regenerate pnpm-lock.yaml with pnpm 10 to match CI
JOY Sep 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .cursor/rules/saas-multitenant-architecture.mdc
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
description: Mandatory rule defining Crove OS and Crove Desk as a Multi-Tenant B2B SaaS platform (not internal-only)
alwaysApply: true
---

# SaaS Multi-Tenant Product Mindset & Architecture

## 1. Core Principle: Multi-Tenant B2B SaaS
- **Crove OS** (Crove Desk, Crove CRM, Crove Post, Crove Sign, Crove Cal) is a **commercial, multi-tenant B2B SaaS ecosystem**, NOT an internal single-company tool or single-user product.
- Every feature, channel, data model, API, and workflow MUST be architected to serve multiple independent organizations/tenants (`org_id`, `org_slug`) in a fully automated, self-service manner.
- **NEVER** hardcode single-tenant assumptions, single company emails (e.g. assuming only `help@crove.com`), or manual database edits for a single user in architecture proposals or production logic.

## 2. Channel & Inbound Routing Architecture (Multi-Tenant)
- **Tenant Isolation**: Each organization manages their own channels (Web Widget, Telegram Bot, Zalo OA, Email, etc.) via the Dashboard self-service UI.
- **Dynamic Inbound Ingestion**:
- Global gateways (Cloudflare Email Routing, Inbound Webhooks) act as universal dispatchers.
- Inbound messages/emails are dynamically resolved to the correct Organization and Channel via recipient address format (e.g. `support@<org_slug>.crove.io`, `help+<org_slug>@crove.com`), channel ID, or verified custom domain routing.
- **Outbound Delivery**:
- Tenants can use default SaaS delivery infrastructure or bring their own custom SMTP / ESP API keys (Brevo, SendGrid, Postmark, Resend, Mailgun) configured securely within their organization settings.

## 3. Implementation Checklist for New Features
- [ ] Multi-tenant scoping: Data, settings, and permissions are partitioned by `org_id` / `org_slug`.
- [ ] Self-service UX: Any tenant admin can configure and activate the feature directly from the UI without developer intervention.
- [ ] Scalable routing: Inbound webhooks/events dynamically look up target tenant and channel in real-time.
- [ ] Clean upstream compatibility: Generic code stays compatible with open-source upstream while SaaS multi-tenant extensions follow clean architectural boundaries.
57 changes: 53 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
# Copy this file to .env and adjust the configuration values as needed.
# ==============================================================================

# Server Configuration
# Server & Branding Configuration
PORT=8083
COMPANY_NAME=
COMPANY_LOGO_URL=
# COMPANY_NAME="AgentDesk"
# COMPANY_LOGO_URL="/images/logo.svg"
# AGENT_DESK_SERVER_CORS_ALLOWEDORIGINS="http://localhost:3000,http://127.0.0.1:8083"

# Client IP resolution.
Expand Down Expand Up @@ -52,7 +52,24 @@ QDRANT_HOST=127.0.0.1
QDRANT_GRPC_PORT=6334
# QDRANT_API_KEY=

# Single Sign-On (OIDC / OAuth 2.0)
# AI Models & OpenAI-Compatible Providers (OpenAI, DOS.AI, DeepSeek, OpenRouter, Azure, Ollama, LiteLLM, vLLM, etc.)
# OPENAI_API_KEY=sk-your-api-key
# OPENAI_BASE_URL=https://api.openai.com/v1
# OPENAI_LLM_MODEL=gpt-4o-mini
# OPENAI_EMBEDDING_MODEL=text-embedding-3-small
# OPENAI_EMBEDDING_DIMENSION=1536
#
# DOS.AI Example:
# OPENAI_API_KEY=dos_sk_your_key
# OPENAI_BASE_URL=https://api.dos.ai/v1
# OPENAI_LLM_MODEL=dos-ai
# OPENAI_EMBEDDING_MODEL=qwen3-embedding-4b
# OPENAI_EMBEDDING_DIMENSION=2560
#
# AI_TIMEOUT_MS=30000
# AI_MAX_RETRY_COUNT=1

# Single Sign-On (OIDC / OAuth 2.1 with PKCE)
# OIDC_ENABLED=true
# OIDC_ISSUER=https://auth.example.com
# OIDC_CLIENT_ID=your-client-id
Expand All @@ -62,6 +79,38 @@ QDRANT_GRPC_PORT=6334
# Webhook & Organization Sync
# ORG_SYNC_SECRET=your-webhook-hmac-secret

# Email Channel & Delivery (help@crove.com / Inbound & Outbound)
# Provider options: smtp, brevo, sendgrid, resend, postmark, mailgun
EMAIL_PROVIDER=brevo
EMAIL_FROM=help@crove.com
EMAIL_FROM_NAME="Crove Desk Support"
# Inbound Webhook Authentication Secret (Header: X-Webhook-Secret)
EMAIL_INBOUND_SECRET=crove_email_secret_token_123

# ESP Provider API Keys (Fill the one corresponding to your EMAIL_PROVIDER):
# Brevo (Sendinblue):
BREVO_API_KEY=xkeysib-your-brevo-api-key
# SendGrid:
# SENDGRID_API_KEY=SG.your-sendgrid-api-key
# Resend:
# RESEND_API_KEY=re_your-resend-api-key
# Postmark:
# POSTMARK_API_KEY=your-postmark-server-token
# Mailgun:
# MAILGUN_API_KEY=your-mailgun-api-key

# Custom SMTP Server (when EMAIL_PROVIDER=smtp):
# SMTP_HOST=email-smtp.ap-southeast-1.amazonaws.com
# SMTP_PORT=587
# SMTP_USER=your-smtp-username
# SMTP_PASSWORD=your-smtp-password
# SMTP_USE_TLS=false

# MCP (Model Context Protocol) Integration
# MCP_ENABLED=true
# MCP_CRM_ENDPOINT=https://crm.crove.com/api/mcp
# MCP_CRM_API_KEY=your-twenty-crm-api-key

# Discord Bot Channel
# Deployment-wide bot token, used when a Discord channel does not carry its own.
# DISCORD_BOT_TOKEN=your-discord-bot-token
Expand Down
9 changes: 7 additions & 2 deletions .github/workflows/deploy-beta.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ concurrency:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
Expand All @@ -31,6 +30,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Set lowercase image name
run: |
echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand All @@ -51,6 +54,8 @@ jobs:
target: app
platforms: linux/amd64
push: true
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:beta
cache-from: type=gha
cache-to: type=gha,mode=max
5 changes: 4 additions & 1 deletion .github/workflows/deploy-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ concurrency:

env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
build-and-push:
Expand All @@ -28,6 +27,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v4

- name: Set lowercase image name
run: |
echo "IMAGE_NAME=${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

Expand Down
180 changes: 180 additions & 0 deletions .github/workflows/sync-upstream.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
name: Sync Upstream & Build Images

on:
schedule:
# Check for upstream releases every 6 hours
- cron: "0 */6 * * *"
workflow_dispatch:
inputs:
upstream_tag:
description: "Specific upstream tag/release to sync (e.g. v0.3.0). Leave empty for latest release."
required: false
default: ""
force_build:
description: "Force sync and image build even if tag exists"
required: false
type: boolean
default: false

concurrency:
group: sync-upstream
cancel-in-progress: false

env:
UPSTREAM_REPO: "huabeitech/agent-desk"
REGISTRY: ghcr.io
IMAGE_NAME: dos/crove-desk

jobs:
check-and-sync:
name: Check & Sync Upstream Release
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
outputs:
has_new_release: ${{ steps.sync.outputs.has_new_release }}
synced_tag: ${{ steps.sync.outputs.synced_tag }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: dev
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}

- name: Check Upstream & Merge
id: sync
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
INPUT_TAG: ${{ github.event.inputs.upstream_tag }}
FORCE_BUILD: ${{ github.event.inputs.force_build }}
run: |
set -e

# 1. Determine target tag from upstream
if [ -n "$INPUT_TAG" ]; then
TARGET_TAG="$INPUT_TAG"
echo "Using specified target tag: $TARGET_TAG"
else
echo "Fetching latest release from upstream ($UPSTREAM_REPO)..."
LATEST_JSON=$(gh api repos/$UPSTREAM_REPO/releases/latest || echo "{}")
TARGET_TAG=$(echo "$LATEST_JSON" | jq -r '.tag_name // empty')
if [ -z "$TARGET_TAG" ]; then
echo "No releases found via releases API, checking tags..."
TARGET_TAG=$(gh api repos/$UPSTREAM_REPO/tags --jq '.[0].name // empty')
fi
fi

if [ -z "$TARGET_TAG" ]; then
echo "No upstream tag or release found to sync."
echo "has_new_release=false" >> $GITHUB_OUTPUT
exit 0
fi

echo "Target upstream tag: $TARGET_TAG"

# 2. Check if tag already exists in origin repository
TAG_EXISTS=false
if git ls-remote --tags origin "refs/tags/$TARGET_TAG" | grep -q "$TARGET_TAG"; then
TAG_EXISTS=true
fi

if [ "$TAG_EXISTS" = "true" ] && [ "$FORCE_BUILD" != "true" ]; then
echo "Tag $TARGET_TAG has already been synced to this repository. No sync needed."
echo "has_new_release=false" >> $GITHUB_OUTPUT
exit 0
fi

echo "Proceeding with sync for upstream tag $TARGET_TAG..."

# 3. Configure Git author
git config user.name "JOY"
git config user.email "5027251+JOY@users.noreply.github.com"

# 4. Fetch upstream
git remote add upstream "https://github.com/$UPSTREAM_REPO.git" || git remote set-url upstream "https://github.com/$UPSTREAM_REPO.git"
git fetch upstream --tags

# 5. Merge upstream tag into dev branch
git checkout dev
echo "Merging upstream tag $TARGET_TAG into dev..."
git merge --no-edit -m "chore(upstream): sync upstream release $TARGET_TAG into dev" "$TARGET_TAG" || {
echo "Merge conflict encountered during upstream sync."
echo "Creating a sync branch instead..."
SYNC_BRANCH="sync/upstream-$TARGET_TAG"
git merge --abort || true
git checkout -b "$SYNC_BRANCH" "$TARGET_TAG"
git push -u origin "$SYNC_BRANCH" --force
gh pr create --base dev --head "$SYNC_BRANCH" \
--title "chore(upstream): sync upstream release $TARGET_TAG" \
--body "Automated PR to sync upstream release \`$TARGET_TAG\` from \`$UPSTREAM_REPO\`. Please resolve merge conflicts."
echo "has_new_release=false" >> $GITHUB_OUTPUT
exit 0
}

# Push updated dev branch
git push origin dev

# 6. Create or update tag on our repository
if [ "$TAG_EXISTS" != "true" ]; then
git push origin "$TARGET_TAG" || true

# Create GitHub Release with release notes
UPSTREAM_BODY=$(gh api repos/$UPSTREAM_REPO/releases/tags/$TARGET_TAG --jq '.body // "Release synced from upstream."' || echo "Release synced from upstream.")
gh release create "$TARGET_TAG" \
--title "$TARGET_TAG (Upstream Sync)" \
--notes "$UPSTREAM_BODY" || true
fi

echo "has_new_release=true" >> $GITHUB_OUTPUT
echo "synced_tag=$TARGET_TAG" >> $GITHUB_OUTPUT

build-and-push-images:
name: Build & Push Beta & Production Images
needs: check-and-sync
if: needs.check-and-sync.outputs.has_new_release == 'true'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: dev

- name: Set up QEMU
uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push Docker images
uses: docker/build-push-action@v6
with:
context: .
target: app
platforms: linux/amd64
push: true
tags: |
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:beta
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-and-sync.outputs.synced_tag }}
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max

- name: Summary
run: |
echo "### 🚀 Upstream Release Sync Complete" >> $GITHUB_STEP_SUMMARY
echo "- **Synced Tag**: \`${{ needs.check-and-sync.outputs.synced_tag }}\`" >> $GITHUB_STEP_SUMMARY
echo "- **Branch Merged**: \`dev\`" >> $GITHUB_STEP_SUMMARY
echo "- **Beta Image Built**: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:beta\` (Auto-deployable to Beta)" >> $GITHUB_STEP_SUMMARY
echo "- **Production Artifacts Built**: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.check-and-sync.outputs.synced_tag }}\` & \`:latest\` (Stored on GHCR, ready for manual/staged promotion)" >> $GITHUB_STEP_SUMMARY
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
.idea
.pnpm-store

.env
.env.*
!.env.example

data/
config/config.yaml
.env
Expand Down
50 changes: 50 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Changelog

All notable changes to the **Crove Desk** project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

---

## [0.3.0] - 2026-08-26

### Added
- **2-Tier Hybrid Architecture**: Implemented local database mirroring for `Company` and `Customer` entities alongside deep Agentic Tool Calling via MCP.
- **Bi-directional Webhook Synchronization**: Added support for event-driven synchronization (`company.created`, `company.updated`, `customer.created`, `customer.updated`, `organization.created`, `organization.member.added`) with HMAC-SHA256 signature verification.
- **Twenty CRM MCP Integration**: Added support for connecting Crove Desk AI Agent to Twenty CRM MCP server (`twenty_crm.get_subscription_status`, `twenty_crm.create_opportunity`, `twenty_crm.create_task`).
- **Vietnamese Language Support (`vi-VN`)**: Added complete Vietnamese localization files and implemented `LanguageToggle` component in navigation header and user menu.
- **AI Agent Loop Live Test Suite**: Added comprehensive live integration tests for Answerability Gate, Knowledge Base context grounding, and function calling tool loops.

### Changed
- **Typography & Font Resolution**: Replaced broken Geist/Times New Roman font fallback with Tailwind CSS v4 `@theme inline` mapping to Inter font with Latin and Vietnamese character subsets.
- **Sidebar Font Sizing**: Refined dashboard navigation sidebar font size to compact 13.5px / 13px for improved scannability and professional desktop density.
- **System Architecture Documentation**: Updated `docs/ARCHITECTURE.md` with 2-Tier Hybrid Architecture diagrams and webhook event specifications.

---

## [0.2.0] - 2026-08-25

### Added
- **OpenAI-Compatible AI Configuration**: Supported configuring LLM and Embedding models via `.env` environment variables (`OPENAI_API_KEY`, `OPENAI_BASE_URL`, `OPENAI_LLM_MODEL`, `OPENAI_EMBEDDING_MODEL`, `OPENAI_EMBEDDING_DIMENSION`).
- **DOS.AI Provider Integration**: Configured live support for DOS.AI (`dos-ai` LLM model and `qwen3-embedding-4b` 2560-dim embedding model).
- **Automated AI Bootstrap & Sync**: Implemented `InitAI` startup hook to automatically seed and synchronize default AI model configurations into PostgreSQL.
- **Default Crove Desk Knowledge Base**: Added auto-seeding of official Crove Desk Knowledge Base and 7 core FAQ entries with background vector indexing in Qdrant.
- **Dynamic Company Branding**: Added `COMPANY_NAME` and `COMPANY_LOGO_URL` configuration exposed via `/api/config` and applied to Login, Workspace Switcher, Legal document pages, and Support Center header.
- **OAuth 2.1 with PKCE S256**: Implemented secure OIDC authorization code exchange with PKCE code challenge and verifier.
- **Password Login Toggle**: Added `PASSWORD_LOGIN_ENABLED` setting to enforce SSO-only login flows.

### Fixed
- Fixed Next.js static export SPA routing for `/dashboard/` trailing slashes.
- Fixed embedded locale file path resolution on Windows environments.

---

## [0.1.0] - 2026-08-22

### Added
- **Repository Initialization**: Forked from `huabeitech/agent-desk` to `DOS/Crove-Desk`.
- **PostgreSQL Database Support**: Added PostgreSQL driver (`gorm.io/driver/postgres`) and normalized GORM model schema types for cross-database compatibility (PostgreSQL, MySQL, SQLite).
- **Supabase Integration**: Connected to Supabase `dos.me` PostgreSQL database under schema `desk` with Session Pooler.
- **Multi-tenant Organization Architecture**: Added `Organization` and `OrganizationMember` models with JIT workspace provisioning upon OIDC login.
- **Production Deployment**: Configured `docker-compose.prod.yml`, Qdrant Vector DB, and Cloudflare Tunnel routing for `desk.crove.com` on GCP VM `crove-server`.
Loading
Loading