From 9cadae305f02bc07f511b29116bae4d6542cec48 Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 18:18:34 +0700 Subject: [PATCH 1/7] ci: run verification on the fork and gate the docker deploy The upstream All checks workflow only fires on merge_group and is guarded to calcom/cal.diy, so nothing verified pushes or PRs on DOS/Crove-Cal (audit finding HI-09). fork-ci.yml runs type-check, lint and unit tests on pull_request and push to dev/main, reusing the existing reusable workflows. deploy-docker.yml now requires a type-check job to pass before publishing :latest to GHCR. The caller grants actions:write explicitly: lint.yml asks for it and a called workflow requesting more than the default GITHUB_TOKEN grant makes every run die as a startup_failure before any job is created. --- .github/workflows/deploy-docker.yml | 8 ++++++ .github/workflows/fork-ci.yml | 39 +++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) create mode 100644 .github/workflows/fork-ci.yml diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml index 0a0b38b50aa..f082d345db3 100644 --- a/.github/workflows/deploy-docker.yml +++ b/.github/workflows/deploy-docker.yml @@ -12,7 +12,15 @@ permissions: packages: write jobs: + # Why: this workflow publishes :latest on every push. Without a gate the image + # ships untested code straight to the registry (audit finding HI-09). + ci-gate: + name: CI gate (type check) + uses: ./.github/workflows/check-types.yml + secrets: inherit + build-and-push: + needs: ci-gate runs-on: ubuntu-latest steps: - name: Checkout repository diff --git a/.github/workflows/fork-ci.yml b/.github/workflows/fork-ci.yml new file mode 100644 index 00000000000..846c2d34d44 --- /dev/null +++ b/.github/workflows/fork-ci.yml @@ -0,0 +1,39 @@ +name: Fork CI + +# Crove-Cal's own verification pipeline. The upstream "All checks" workflow only +# fires on merge_group and is guarded to calcom/cal.diy, so without this file +# nothing verifies pushes/PRs on DOS/Crove-Cal (audit finding HI-09). +# +# Why explicit permissions: lint.yml (called below) requires "actions: write"; +# without this block the called workflow asks for more than the default +# GITHUB_TOKEN grant and every run dies as a startup_failure with no jobs. +permissions: + actions: write + contents: read + +on: + pull_request: + branches: + - dev + - main + push: + branches: + - dev + - main + workflow_dispatch: + +jobs: + type-check: + name: Type check + uses: ./.github/workflows/check-types.yml + secrets: inherit + + lint: + name: Linters + uses: ./.github/workflows/lint.yml + secrets: inherit + + unit-test: + name: Unit tests + uses: ./.github/workflows/unit-tests.yml + secrets: inherit From c35f3af923d14cf68831e759b3e5ee6dfe296d63 Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 18:18:41 +0700 Subject: [PATCH 2/7] fix(api-v2): replace shipped secrets with placeholders in example files apps/api/v2/.env.example carried real NEXTAUTH_SECRET, JWT_SECRET, CALENDSO_ENCRYPTION_KEY and CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY values and README-PLATFORM.md embedded a fully-signed example JWT (audit findings CR-08 and LO-13). Anyone copying the example would run with publicly-known keys. Replaced with placeholders. --- apps/api/v2/.env.example | 8 ++++---- apps/api/v2/README-PLATFORM.md | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/apps/api/v2/.env.example b/apps/api/v2/.env.example index fd53a2e3570..cd7d02f7c33 100644 --- a/apps/api/v2/.env.example +++ b/apps/api/v2/.env.example @@ -11,11 +11,11 @@ DATABASE_WRITE_URL="postgresql://postgres:@localhost:5450/calendso" LOG_LEVEL=DEBUG # the same value as in the root .env - it is used by api-auth.strategy.ts to validate requests authenticated with next token. If you already have a value # in the root .env then you can paste it here. It is important that they are the same. -NEXTAUTH_SECRET="RbyBOfiZFt/IsBL2E2Zy2idcKRH+WclnHEiu1FmRdf0=" +NEXTAUTH_SECRET="change-me-generate-a-random-base64-value" DATABASE_URL="postgresql://postgres:@localhost:5450/calendso" DATABASE_DIRECT_URL="postgresql://postgres:@localhost:5450/calendso" # used by JwtService to sign and decode tokens -JWT_SECRET="asjdijI1JIO12I3O89198jojioSAJDU" +JWT_SECRET="change-me-generate-a-random-string" SENTRY_DSN= # mailhog setup. Make sure its running - see instructions in apps/api/v2/README.md @@ -23,9 +23,9 @@ EMAIL_SERVER_HOST='localhost' EMAIL_SERVER_PORT=1025 # used to manage encrypt and decrypt third party tokens -CALENDSO_ENCRYPTION_KEY="Lmqy57DlHKPvwwrtkwjL/8QtxJWxC/OV" +CALENDSO_ENCRYPTION_KEY="change-me-generate-a-random-base64-value" # Service Account Encryption Key for encrypting/decrypting service account keys -CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY="LDBFYLEVICRZBYQZUZCSTZRJFZUKZMEI" +CALCOM_SERVICE_ACCOUNT_ENCRYPTION_KEY="change-me-generate-a-random-base64-value" # url to redis instance running in Docker and used to cache data. Redis is setup in apps/api/v2/docker-compose.yaml REDIS_URL="redis://localhost:6379" diff --git a/apps/api/v2/README-PLATFORM.md b/apps/api/v2/README-PLATFORM.md index 68136255a5a..6e78eb60ce1 100644 --- a/apps/api/v2/README-PLATFORM.md +++ b/apps/api/v2/README-PLATFORM.md @@ -47,7 +47,7 @@ Then in the `packages/platform/examples/base/.env` set the `NEXT_PUBLIC_OAUTH2_C { "id": "clxyyy21o0003sbk7yw5z6tzg", "name": "Acme", - "secret": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiQWNtZSAiLCJwZXJtaXNzaW9ucyI6MTAyMywicmVkaXJlY3RVcmlzIjpbImh0dHA6Ly9sb2NhbGhvc3Q6NDMyMSJdLCJib29raW5nUmVkaXJlY3RVcmkiOiIiLCJib29raW5nQ2FuY2VsUmVkaXJlY3RVcmkiOiIiLCJib29raW5nUmVzY2hlZHVsZVJlZGlyZWN0VXJpIjoiIiwiYXJlRW1haWxzRW5hYmxlZCI6dHJ1ZSwiaWF0IjoxNzE5NTk1ODA4fQ.L5_jSS14fcKLCD_9_DAOgtGd6lUSZlU5CEpCPaPt41I", + "secret": "", "permissions": 1023, "logo": null, "redirectUris": "{http://localhost:4321}", From 8dd12efbf1b4705a8cb01eeaece82505b9d0a271 Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 18:18:48 +0700 Subject: [PATCH 3/7] docs(audit): update fix status to Round 4 and add Cal.com feature gap report Round 4 status (2026-09-16, verified in code): MD-03, MD-05/06, LO-02, LO-03, MD-29 were already fixed by commits after the last report update and are now recorded; HI-09 (fork CI + deploy gate) and CR-08 (env example placeholders) close in this PR. Every finding now carries a status badge (fixed / partial / decision / open) with per-finding notes. Also adds a dark-theme Vietnamese report comparing Cal.com features (v6.2-v6.9, post closed-source) against the fork, with per-item repo verification evidence and a recommended order. The audit report is switched to a native dark theme to match the docs standard. --- docs/audit/2026-09-08-audit-report.html | 316 ++++++++++-------- .../2026-09-16-calcom-vs-crove-cal-gap.html | 257 ++++++++++++++ 2 files changed, 438 insertions(+), 135 deletions(-) create mode 100644 docs/audit/2026-09-16-calcom-vs-crove-cal-gap.html diff --git a/docs/audit/2026-09-08-audit-report.html b/docs/audit/2026-09-08-audit-report.html index 9d08f7ecbee..e486e936069 100644 --- a/docs/audit/2026-09-08-audit-report.html +++ b/docs/audit/2026-09-08-audit-report.html @@ -3,17 +3,18 @@ -Crove-Cal — Báo cáo Audit toàn bộ Repo — 2026-09-08 + +Crove-Cal - Báo cáo Audit toàn bộ Repo - 2026-09-08 (cập nhật 2026-09-16)
-

Crove-Cal — Báo cáo Audit toàn bộ Repo

- Ngày: 2026-09-08  ·  Commit: 7782de6b7a (dev)  ·  Phạm vi: ~115 packages (upstream + 73 commit fork)  ·  Phương pháp: 6 hướng audit song song, chỉ đọc  ·  +

Crove-Cal - Báo cáo Audit toàn bộ Repo

+ Ngày audit: 2026-09-08  ·  Commit baseline: 7782de6b7a (dev)  ·  Phạm vi: ~115 packages (upstream + 73 commit fork)  ·  Phương pháp: 6 hướng audit song song, chỉ đọc  ·  Trạng thái cập nhật: 2026-09-16 (Round 4)  · 
- Cách đọc: mỗi phát hiện có ID (CR/HI/MD/LO-##), Priority (mức độ rủi ro), Action order (thứ tự khắc phục khuyến nghị — mục "Kế hoạch khắc phục"). Cột Verified = đã được xác minh độc lập bằng đọc code trực tiếp (không phải chỉ kết quả agent). - Không có giá trị secret nào được in trong file này — mọi secret chỉ được tham chiếu theo file:line. + Cách đọc: mỗi phát hiện có ID (CR/HI/MD/LO-##), Priority (mức độ rủi ro), Action order (thứ tự khắc phục khuyến nghị - mục "Kế hoạch khắc phục"). Cột Verified = đã được xác minh độc lập bằng đọc code trực tiếp (không phải chỉ kết quả agent). + Không có giá trị secret nào được in trong file này - mọi secret chỉ được tham chiếu theo file:line.
-

Trạng thái xử lý — cập nhật sau Round 1 + Dependabot (cùng ngày)

+

Trạng thái xử lý - cập nhật đến Round 4 (2026-09-16)

- - - - - - + + + + + + + +
Trạng tháiPhạm viGhi chú
ĐÃ FIXFork security & correctnessCR-01…CR-06, HI-01, HI-04…HI-07, HI-15, HI-17…HI-20, MD-02/04/07/08/09/13/14/15/23/24/25/26, LO-12 — các commit trên dev, verify 72/72 vitest + tsc sạch + biome lint 0 error
ĐÃ FIXDependabotCR-07 (next-auth 4.24.15), HI-11 phần resolutions + tar/websocket-driver, next 16.2.11, dependabot.yml — yarn install exit 0, tsc apps/web sạch
ĐÃ FIXHI-08, MD-01TLS mặc định verify-on (opt-out qua DATABASE_SSL_REJECT_UNAUTHORIZED=false) + sửa pool leak api/v2 + gate session/ADMIN cho /api/webhooks/health — 5/5 test pass
ĐÃ FIX (Round 3)HI-06, HI-11, HI-14, HI-02/03, HI-21, HI-22, MD-10/11/12, MD-13/14/15, MD-01Cron auth timing-safe fail-closed (7 routes); reminder re-check booking + cancel stale reminders; rate limit 6 auth mutations + HSTS/CSP headers; MCP tenant scoping + fromReschedule + conflict guard; SSRF self-hosted + opt-out; video token fail-closed; timing-safe webhook compares
CHỜ QUYẾT ĐỊNHHI-13, HI-1461 migrations cần biết DB prod dùng schema nào; wire workflows dispatcher là quyết định feature. Khi deploy: rotate secret Supabase + env mới (CRON_SECRET, OIDC_*, BREVO/CROVE/DOS_SYNC_WEBHOOK_SECRET, DATABASE_SSL_REJECT_UNAUTHORIZED=false nếu pooler cần) + prisma migrate deploy
CÒN LẠI (TAIL)Docker/CI + cosmeticCR-08, HI-09/10/12 (Docker hardening + re-enable CI/crons), HI-16 (branding), MD-03 (PBAC stub), MD-05/06 (data perf), MD-16…22 (frontend perf), MD-27…32, LO-01…11/13/15
ĐÃ FIXFork security & correctnessCR-01…CR-06, HI-01, HI-04…HI-07, HI-15, HI-17…HI-20, MD-02/04/07/08/09/13/14/15/23/24/25/26, LO-12 - các commit trên dev, verify 72/72 vitest + tsc sạch + biome lint 0 error
ĐÃ FIXDependabotCR-07 (next-auth 4.24.15), HI-11 phần resolutions + tar/websocket-driver, next 16.2.11 → 16.3.3, dependabot.yml - yarn install exit 0, tsc apps/web sạch
ĐÃ FIXHI-08, MD-01TLS mặc định verify-on (opt-out qua DATABASE_SSL_REJECT_UNAUTHORIZED=false) + sửa pool leak api/v2 + gate session/ADMIN cho /api/webhooks/health - 5/5 test pass
ĐÃ FIX (Round 3)HI-06, HI-11, HI-14 (phần hardening), HI-02/03, HI-21, HI-22, MD-10/11/12, MD-13/14/15, MD-01Cron auth timing-safe fail-closed (7 routes); reminder re-check booking + cancel stale reminders; rate limit 6 auth mutations + HSTS/CSP headers; MCP tenant scoping + fromReschedule + conflict guard; SSRF self-hosted + opt-out; video token fail-closed; timing-safe webhook compares
ĐÃ FIX (Round 4 - verify lại 2026-09-16)MD-03, MD-05/06, LO-02, LO-03, MD-29MD-03: PBAC checkPermission giờ query membership thật, throw FORBIDDEN (aa68fd3acc). MD-05/06: partial expression index trên metadata dosOrgId/dosTeamId + WebhookScheduledTriggers drain take:100 + await + deleteMany sau dispatch (efb232e52f). LO-02: 3 barrels chết đã xoá (a058d89d53). LO-03: restore membership ADMIN/OWNER check (aa68fd3acc). MD-29: fork env vars vào turbo globalEnv (ccf9b85785)
ĐÃ FIX (Round 4 - 2026-09-16)HI-09, CR-08 (hoàn tất), LO-13 (một phần)HI-09: workflow mới fork-ci.yml (type-check + lint + unit test) chạy trên PR + push dev/main của DOS/Crove-Cal; deploy-docker.yml thêm job ci-gate (type-check) mà build-and-push phải chờ. CR-08: Dockerfile/docker-compose bỏ default secret từ Round trước; Round 4 thay 4 giá trị secret thật trong apps/api/v2/.env.example bằng placeholder. LO-13: JWT example trong README-PLATFORM.md thay bằng placeholder
CHỜ QUYẾT ĐỊNHHI-13, HI-14, HI-16, HI-10HI-13: 61 migrations cần biết DB prod dùng schema nào (lưu ý: upstream đã đóng source 2026-04 nên áp lực sync giảm). HI-14: wire workflows dispatcher là quyết định feature - tham khảo Cal.com Workflows 2.0 (v6.9) trong report feature-gap cùng ngày. HI-16: branding hardcode - giờ upstream đóng source nên việc giữ branding riêng có chủ đích là phương án hợp lý, cần chốt. HI-10: bật crons cần cấu hình secrets riêng (CRON_SECRET v.v.) trước. Khi deploy: rotate secret Supabase + env mới (CRON_SECRET, OIDC_*, BREVO/CROVE/DOS_SYNC_WEBHOOK_SECRET, DATABASE_SSL_REJECT_UNAUTHORIZED=false nếu pooler cần) + prisma migrate deploy
CÒN LẠI (TAIL)Docker phần dở + perf/cosmeticHI-12 phần dở (USER non-root, .dockerignore thiếu .env/*.pem/*.key), LO-13 phần dở (prisma/.env symlink, pin trigger.dev), MD-16…22 (frontend perf), MD-27/28 (CI supply-chain hygiene), MD-30 (Stripe png), MD-31/32 (latent), LO-01/04/05/06/07 (một phần)/08/09/11/14
@@ -105,6 +112,7 @@

Tổng quan

0
Medium
0
Low
0
Đã verify độc lập
+
0
Đã xử lý xong (2026-09-16)
@@ -113,7 +121,7 @@

Tổng quan

Kế hoạch khắc phục (thứ tự khuyến nghị)

    -
  1. Rotate OIDC client secret trên Supabase dashboard NGAY — việc duy nhất thực sự khắc phục C-01; secret nằm vĩnh viễn trong git history của repo public. Xoá code / rewrite history không cứu được. +
  2. Rotate OIDC client secret trên Supabase dashboard NGAY - việc duy nhất thực sự khắc phục C-01; secret nằm vĩnh viễn trong git history của repo public. Xoá code / rewrite history không cứu được. Liên quan: CR-01
  3. Bỏ mọi secret fallback (OIDC, video-token) + fail startup khi thiếu env + gate đăng ký DosIdProvider theo cấu hình thật + đổi emailVerified ?? true. CR-01, HI-22, HI-01
  4. @@ -147,16 +155,16 @@

    Kế hoạch khắc phục (thứ tự khuyến nghị)

    Vùng đã kiểm tra và sạch (không cần re-audit)

    -
    credential.key không lộ ra client — quét toàn bộ select/tRPC/serializer; safeCredentialSelect có comment đúng mục đích. Over-fetch duy nhất trong bookingsProcedure middleware không tới response (MD-34).
    -
    Không SQL injection — 38 site $queryRaw toàn tagged-template parameterized; zero $queryRawUnsafe/$executeRawUnsafe.
    +
    credential.key không lộ ra client - quét toàn bộ select/tRPC/serializer; safeCredentialSelect có comment đúng mục đích. Over-fetch duy nhất trong bookingsProcedure middleware không tới response (MD-34).
    +
    Không SQL injection - 38 site $queryRaw toàn tagged-template parameterized; zero $queryRawUnsafe/$executeRawUnsafe.
    Không barrel-import violation trong code fork; booking flow upstream không bị fork đụng (packages/features/bookings không đổi).
    -
    OAuth client management (platform) đúng — secret SHA-256, redirect URI so exact, PKCE S256 bắt buộc cho PUBLIC client, code 40 random bytes.
    -
    authorizeCredentials + deleteMe sound — lock check, băm email rate-limit, backup codes consumed, ADMIN thiếu 2FA bị downgrade.
    -
    dos-org-sync verification logic đúng (timingSafeEqual, fail-closed, chạy trước JSON.parse) — lỗi nằm ở key selection (HI-01).
    +
    OAuth client management (platform) đúng - secret SHA-256, redirect URI so exact, PKCE S256 bắt buộc cho PUBLIC client, code 40 random bytes.
    +
    authorizeCredentials + deleteMe sound - lock check, băm email rate-limit, backup codes consumed, ADMIN thiếu 2FA bị downgrade.
    +
    dos-org-sync verification logic đúng (timingSafeEqual, fail-closed, chạy trước JSON.parse) - lỗi nằm ở key selection (HI-01).
    Generated files đúng app-store-cli output (8 thêm / 0 xoá, đúng thứ tự alphabet); api/v2 import rule sạch cho code fork.
    -
    Placement đúng chuẩn — business logic trong Service (không Repository), permission check trong page.tsx (không layout.tsx), không dayjs misuse trong code fork.
    -
    TS6 decorators an toàn — useDefineForClassFields được set đúng nơi cần; NestJS DTO emission còn nguyên.
    -
    Test breadth tốt hơn kỳ vọng — mọi feature fork đều có test; WorkflowService.test assert timestamp tính thật (không mock-only).
    +
    Placement đúng chuẩn - business logic trong Service (không Repository), permission check trong page.tsx (không layout.tsx), không dayjs misuse trong code fork.
    +
    TS6 decorators an toàn - useDefineForClassFields được set đúng nơi cần; NestJS DTO emission còn nguyên.
    +
    Test breadth tốt hơn kỳ vọng - mọi feature fork đều có test; WorkflowService.test assert timestamp tính thật (không mock-only).

    Danh sách phát hiện

    @@ -167,6 +175,7 @@

    Danh sách phát hiện

    + @@ -174,7 +183,7 @@

    Danh sách phát hiện

    - Tạo bởi 6 audit agent song song + verify độc lập thủ công · Crove-Cal (fork của calcom/cal.diy) · 2026-09-08 · Chỉ báo cáo, không thay đổi code. + Tạo bởi 6 audit agent song song + verify độc lập thủ công · Crove-Cal (fork của calcom/cal.diy) · Audit 2026-09-08 · Trạng thái xử lý cập nhật 2026-09-16 (Round 4) · Chỉ báo cáo, không thay đổi code.
    diff --git a/docs/audit/2026-09-16-calcom-vs-crove-cal-gap.html b/docs/audit/2026-09-16-calcom-vs-crove-cal-gap.html new file mode 100644 index 00000000000..f61734b00f9 --- /dev/null +++ b/docs/audit/2026-09-16-calcom-vs-crove-cal-gap.html @@ -0,0 +1,257 @@ + + + + + + +Cal.com vs Crove-Cal - Bảng so sánh tính năng còn thiếu - 2026-09-16 + + + +
    +

    Cal.com vs Crove-Cal - Tính năng Cal.com có mà fork chưa có

    +
    Ngày: 2026-09-16  ·  Nguồn: cal.com/blog/category/updates (changelog v6.2 → v6.9)  ·  Phương pháp: đọc changelog + verify trực tiếp trong repo Crove-Cal (grep từng module)  ·  Baseline fork: dev @ 6752eeb267
    +
    + +
    +
    + Bối cảnh quan trọng nhất: Cal.com đã đóng source từ 2026-04 (bài "Cal.com is going closed source. Here's why" - lý do: AI quét code public tìm lỗ hổng). Production code của họ đã chuyển sang repo private và diverged mạnh (rewrite auth + data handling). Repo công khai calcom/cal.diy - upstream của Crove-Cal - giờ là bản MIT community-driven, không cam kết vá CVE hay nhận feature mới. Hệ quả: mọi tính năng trong bảng dưới đây không bao giờ tới fork qua đường sync upstream - muốn có thì phải tự xây hoặc thay thế bằng hướng khác. +
    + +

    Tổng quan nhanh

    +
    +
    12
    Tính năng fork CHƯA có
    +
    2
    Có một phần / bản cũ
    +
    4
    Không cần cho use-case DOS
    +
    0
    Port được từ upstream (đã đóng source)
    +
    + +

    Bảng chi tiết (mới nhất lên đầu)

    +
NhómCriticalHighMediumLow
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Tính năngRa mắtCrove-CalLà gì / bằng chứng verify trong repoHướng đi đề xuấtƯu tiên
Workflows 2.0
(visual automation canvas)
v6.9
15/09/2026
BẢN CRUDCal.com: canvas kéo-thả, split theo điều kiện, filter nodes; sắp có Delays + Lead enrichment. Fork: có UI /workflows tự viết nhưng engine chưa wire - scheduleRemindersForBooking vẫn 0 production caller (audit HI-14, verify lại 2026-09-16). Nghĩa là reminder hiện KHÔNG bao giờ được gửi.Quyết định treo HI-14: hoặc wire dispatcher cho workflow đơn giản (SMS/email trước/gặp), hoặc giấu UI. Không thể tham khảo code Cal.com (đã đóng) - chỉ tham khảo mô hình.CAO
Calendar read fail-closed
(security behavior fix)
v6.9
15/09/2026
CHƯA CHECKCal.com fix: khi đọc calendar lỗi, host hiện là busy thay vì hiện slot trống (tránh double-book khi calendar unreadable). Đây là mô tả trong changelog - code đóng, không xem được. Fork chưa từng audit hành vi tương tự.Tự audit booking availability path trong fork: xác định hành vi hiện tại khi external calendar fetch fail (error bị nuốt → coi như rảnh? hay throw?). Nếu nuốt lỗi → tự fix theo hướng fail-closed.CAO
Troubleshooter 2.0v6.9
(1.0: v6.8)
CÓ 1.0Cal.com: giải thích vì sao slot biến mất, gợi ý fix. Fork đã có apps/web/modules/troubleshooter + trang /availability/troubleshoot (verify 2026-09-16).Giữ bản hiện có; nâng cấp theo nhu cầu thực tế support. Không port được.THẤP
Cal.ai trở lại app store
(AI assistant đặt lịch)
v6.9
15/09/2026
KHÔNG CÓAssistant AI hosted của Cal.com. Fork: packages/app-store/calai không tồn tại (verify 2026-09-16); đây là dịch vụ trả phí của Cal.com, self-host không chạy được kể cả khi có code.Không cần. Fork đã có hướng thay thế đúng: packages/mcp-server (MCP cho agent tự vận hành calendar) - đã được audit hardening tenant-scoping (HI-02/03 fixed). Đầu tư vào MCP hơn.KHÔNG CẦN
PBAC role overlays
(custom role per team)
v6.9
15/09/2026
NỀN ĐÃ CÓCal.com: role mặc định sửa được + overlay role riêng từng team. Fork: PBAC permission check đã thật (MD-03 fix 2026-09-10, commit aa68fd3acc) nhưng chưa có UI quản lý role tùy biến.Nếu DOS cần phân quyền mịn theo team: xây UI role editor trên nền PBAC hiện có. Không port được.TRUNG BÌNH
Cal Events
(sản phẩm tổ chức sự kiện)
v6.8
15/08/2026
KHÔNG CÓTrang đăng ký sự kiện nhiều người / marketing events. Fork không có module tương tự (verify: không tìm thấy "cal events" feature riêng - chỉ có calendar-subscription thông thường).Không phục vụ use-case hiện tại (booking nội bộ hệ sinh thái DOS). Bỏ qua.KHÔNG CẦN
AI chat trong routing formsv6.8
15/08/2026
KHÔNG CÓFork có app routing-forms (bản cũ upstream) nhưng không có AI chat (verify: không tìm thấy module chat trong packages/app-store/routing-forms).Chỉ làm nếu DOS cần chatbot tư vấn trước đặt lịch. Có thể ghép qua API AI bên ngoài.THẤP
Cal.com Notes + private event notesv6.7
15/07/2026
KHÔNG CÓGhi chú cuộc họp (meeting notes) trong hệ sinh thái Cal. Fork: không có packages/features/notes (verify 2026-09-16).Tự xây được nếu DOS mentor (Menteelogy) cần notes sau session - model đơn giản (bảng Note + quan hệ Booking). Đặt sau khi giải quyết Workflows.TRUNG BÌNH
Cal Payv6.7
15/07/2026
KHÔNG CÓHệ thống thanh toán/subscription của Cal.com cho platform. Fork: không có (verify: không tìm thấy module calpay).Không cần - Crove không bán gói qua calendar; thanh toán nằm ở hệ sinh thái DOS.KHÔNG CẦN
Design system mới + UI overhaulv6.6
15/06/2026
KHÔNG CÓCal.com làm lại toàn bộ UI/design system. Fork giữ giao diện bản cũ (trước 2026-06).Không theo - chi phí rework toàn diện quá lớn so với giá trị (calendar nội bộ). Chỉ chỉnh nhỏ khi cần.KHÔNG CẦN
Audit logs
(instance-level)
v6.6
15/06/2026
CÓ BOOKINGCal.com: audit log toàn hệ thống. Fork đã có packages/features/booking-audit (booking history viewer) - đủ cho booking, thiếu audit toàn hệ thống (ai đổi setting gì, lúc nào).Nếu cần compliance/chuẩn bị bán cho ngân hàng (DOSafe context): xây bảng AuditLog tổng + middleware ghi event. Giá trị chiến lược cao với khách tài chính.TRUNG BÌNH
Event type historyv6.5
15/05/2026
KHÔNG CÓXem lịch sử thay đổi event type. Fork: schema không có model tương tự (verify: không tìm thấy EventTypeHistory trong schema.prisma).Ghép cùng audit log tổng (mục trên) nếu làm.THẤP
Cal.com Agentsv6.3
15/03/2026
KHÔNG CÓSản phẩm AI agent của Cal.com. Fork: packages/app-store/agents không tồn tại (verify 2026-09-16).Không cần - thay bằng MCP server của fork (agent infrastructure riêng của DOS ecosystem).KHÔNG CẦN
Custom domain + SMTP admin UIv6.3
15/03/2026
KHÔNG CÓ (env)Cal.com: cấu hình custom domain + SMTP trong admin UI. Fork: cấu hình qua biến môi trường (self-host single-tenant).Không cần admin UI khi vận hành 1 tenant; env + CI hiện tại đủ và an toàn hơn.THẤP
Bookings page redesignv6.2
15/02/2026
BẢN CŨTrang /bookings làm mới. Fork giữ bản cũ.Cosmetic - bỏ qua.THẤP
Link cloaking chống URL scannersv6.2
15/02/2026
KHÔNG CÓChe link cuộc họp trước URL preview scanner (Outlook Safe Links v.v.). Fork không có cơ chế tương tự (verify: không tìm thấy module cloak).Chỉ làm khi có vấn đề thực tế (link họp bị scanner phá). Nhỏ, tự làm được.THẤP
Salesforce improvementsv6.5
15/05/2026
APP CÓ SẴNFork có app Salesforce bản cũ trong app-store; thiếu các cải thiện v6.5.Không liên quan use-case DOS. Bỏ qua.KHÔNG CẦN
+ +

Security fixes trong v6.9 đáng tự soi lại fork

+
+ Cal.com công bố các fix security trong v6.9. Code đã đóng nên không xem được - nhưng mô tả hành vi đủ để tự kiểm tra xem fork có cùng lỗ hổng hành vi hay không: +
+ + + + + + + + + + + + + + + + + + + + +
Fix của Cal.com (mô tả từ changelog)Trạng thái Crove-Cal
Availability fail closed khi calendar read lỗi (host hiện busy thay vì rảnh)CHƯA AUDIT - cần kiểm tra availability path khi external calendar fetch fail. Đề xuất đưa vào round audit kế tiếp.
Ngừng tin email claim từ Azure AD trong invite/new-user flows + siết SAML tenant lookupĐÃ FIX NHÓM TƯƠNG ĐƯƠNG - audit CR-01/HI-07 đã xử email trust (emailVerified ?? true → unverified, JWT update callback re-anchor). Fork không dùng Azure AD/SAML nên phần đó không áp dụng.
Unconfirmed bookings không còn block slot của event types khácCHƯA AUDIT - hành vi PENDING booking với availability: cần kiểm tra khi làm Workflows.
Account locks tạm thời sau failed login (backoff)ĐÃ CÓ HƯỚNG TƯƠNG ĐƯƠNG - rate limit 6 auth mutations đã thêm trong Round 3 (commit a81ee2e86c).
+ +

Kết luận và thứ tự đề xuất

+
    +
  • Không có gì phải "đuổi" theo Cal.com. Sau khi đóng source, fork và Cal.com là hai sản phẩm khác nhau. Các item "KHÔNG CẦN" (Cal.ai, Agents, Cal Pay, Cal Events, design overhaul) đều là sản phẩm thương mại của họ, không hợp use-case nội bộ DOS.
  • +
  • Hai việc đáng làm nhất từ bảng này: (1) quyết định Workflows - wire dispatcher hoặc giấu UI (đang treo từ audit HI-14, hiện trạng là UI trông hoạt động nhưng reminder không bao giờ gửi - nguy hiểm hơn là không có tính năng); (2) audit calendar-read fail-closed - hành vi đúng đắn của booking engine, ảnh hưởng trực tiếp double-book.
  • +
  • Điều kiện vận hành đã thay đổi vĩnh viễn: không còn upstream để tự vá CVE. CI của fork (bật lại 2026-09-16 qua fork-ci.yml) + dependabot.yml + quy trình tự audit định kỳ là hàng rào duy nhất. Nên giữ nhịp audit lại mỗi lần bump dependency lớn.
  • +
+
+ +
+ Nguồn: cal.com/blog (changelog v6.2-v6.9 + bài closed-source, đọc 2026-09-16) · Verify trong repo Crove-Cal (dev @ 6752eeb267) · File self-contained, không fetch ngoài. +
+ + From 34f03443c35c78d7cb9705546d4664f349845cbe Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 18:21:57 +0700 Subject: [PATCH 4/7] fix(ts): declare node types for embed-react so CI type-check passes The embed-react program pulls in embed-core sources through tsconfig paths; those files reference the node 'process' global. Locally the root-hoisted @types/node happened to be visible, but a clean CI install resolves differently and every run failed with TS2591 (Cannot find name 'process'). embed-core already declares "types": ["node"]; mirror it here so the check is deterministic instead of layout-dependent. --- packages/embeds/embed-react/tsconfig.json | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/embeds/embed-react/tsconfig.json b/packages/embeds/embed-react/tsconfig.json index 82bd6042b50..41c26c076d6 100644 --- a/packages/embeds/embed-react/tsconfig.json +++ b/packages/embeds/embed-react/tsconfig.json @@ -10,6 +10,7 @@ "declaration": true, "jsx": "preserve", "outDir": "dist", + "types": ["node"], "paths": { "@calcom/embed-core": ["../embed-core/src"], "@calcom/embed-snippet": ["../embed-snippet/src"] From b19ab7602688ea3c11d0dfb89cbf2137491711d5 Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 18:37:01 +0700 Subject: [PATCH 5/7] ci: regenerate app-store files before checks run Commit 4234549670 untracked the app-store generated files, relying on the pre-commit hook to regenerate them locally. A clean CI checkout has no such hook, so type-check and unit tests died on missing apps.schemas.generated / apps.metadata.generated imports. Run the same 'yarn app-store:build' the hook uses right after yarn install. --- .github/workflows/check-types.yml | 3 +++ .github/workflows/unit-tests.yml | 3 +++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index b10b5d71b2f..a9b788f62e8 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -16,6 +16,9 @@ jobs: sparse-checkout: .github - uses: ./.github/actions/cache-checkout - uses: ./.github/actions/yarn-install + # The fork untracks app-store generated files (audit MD-02); regenerate + # them after install or every type-check dies on missing imports. + - run: yarn app-store:build - name: Show info run: node -e "console.log(require('v8').getHeapStatistics())" - name: Configure TSC problem matcher diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 4af892454ed..0bde8787d96 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -16,6 +16,9 @@ jobs: sparse-checkout: .github - uses: ./.github/actions/cache-checkout - uses: ./.github/actions/yarn-install + # The fork untracks app-store generated files (audit MD-02); regenerate + # them after install or the test suite dies on missing imports. + - run: yarn app-store:build - run: yarn prisma generate - run: yarn test -- --no-isolate # We could add different timezones here that we need to run our tests in From eb55591bb068d7c90362b79662b642dd86dfee38 Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 18:49:35 +0700 Subject: [PATCH 6/7] fix(ts,test): node types for embed-snippet and updated health test embed-snippet pulls embed-core sources into its program and hit the same TS2591 'process' failure as embed-react; declare node types the same way. The /api/health test still asserted the pre-MD-15 behavior where the raw database error string was returned in the response body. The route no longer leaks it, so assert the error field is undefined instead. Verified locally: 3/3 tests pass. --- apps/web/app/api/health/__tests__/route.test.ts | 3 ++- packages/embeds/embed-snippet/tsconfig.json | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/apps/web/app/api/health/__tests__/route.test.ts b/apps/web/app/api/health/__tests__/route.test.ts index f5e3b5befd6..a016d4de387 100644 --- a/apps/web/app/api/health/__tests__/route.test.ts +++ b/apps/web/app/api/health/__tests__/route.test.ts @@ -36,7 +36,8 @@ describe("API /api/health Endpoint", () => { const json = await res.json(); expect(json.status).toBe("unhealthy"); expect(json.database.status).toBe("disconnected"); - expect(json.database.error).toContain("Connection refused to database pooler"); + // Raw database errors must not leak to anonymous callers (audit MD-15). + expect(json.database.error).toBeUndefined(); }); it("should support HEAD requests", async () => { diff --git a/packages/embeds/embed-snippet/tsconfig.json b/packages/embeds/embed-snippet/tsconfig.json index 91676ef28bf..7951ff049ad 100644 --- a/packages/embeds/embed-snippet/tsconfig.json +++ b/packages/embeds/embed-snippet/tsconfig.json @@ -9,6 +9,7 @@ "module": "ESNext", "declaration": true, "outDir": "dist", + "types": ["node"], "paths": { "@calcom/embed-core": ["../embed-core/src"], "@calcom/embed-react": ["../embed-react/src"] From 19d3e78deffe75ad9ade3fa5bd94bded74b59c92 Mon Sep 17 00:00:00 2001 From: JOY Date: Wed, 16 Sep 2026 19:01:27 +0700 Subject: [PATCH 7/7] build(turbo): build dependencies before type-checking Local runs pass because platform packages carry dist/ artifacts from earlier builds, and 'types' resolution plus skipLibCheck hides redeclarations in platform/types sources. A clean CI checkout has no dist, so apps/web type-checked those sources directly and failed with a wall of TS2612. Making type-check depend on ^build gives CI the same artifacts local development always has. --- turbo.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/turbo.json b/turbo.json index b70da9ee949..e70108b1552 100644 --- a/turbo.json +++ b/turbo.json @@ -567,11 +567,11 @@ }, "type-check": { "cache": false, - "dependsOn": ["@calcom/trpc#build"] + "dependsOn": ["^build", "@calcom/trpc#build"] }, "type-check:ci": { "cache": false, - "dependsOn": ["@calcom/trpc#build"] + "dependsOn": ["^build", "@calcom/trpc#build"] }, "@calcom/prisma#db-reset": { "cache": false,