16499 Commits
Author SHA1 Message Date
zeekayandHanzo Dev 9ebe7b6ef7 LLM.md is the one committed guide; CLAUDE.md, AGENTS.md and GEMINI.md are local links to it
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-24 15:42:15 -07:00
zeekay e576da4b26 Delete upstream workflows
This fork does not ship upstream's releases, and its hosted-runner jobs
never start here.

Claude-Session: https://claude.ai/code/session_01HuMDfgFssPUptYUzgZ6Cp8
2026-09-24 09:53:59 -07:00
zeekayandHanzo Dev 40d53cfac3 fix: call the pipeline at the address it actually lives
hanzoai/ci keeps the reusable at .github/workflows/build.yml — the one path
both planes resolve, since github.com reads a reusable only from there and the
forge reads it too. The v1 tag moved with it, so a caller still naming
.hanzo/workflows/build.yml asks for a blob that is not in the tree:

  InsertRun: read hanzoai/ci@v1:.hanzo/workflows/build.yml: object does not exist

The caller itself stays at .hanzo/workflows/cicd.yml on purpose: github.com has
no runner for these labels, so a caller placed there could never be scheduled.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-08 01:14:21 -07:00
zeekayandHanzo Dev 046df137a2 Drop Railway one-click deploy links and guide page
README and the docs site listed a rival PaaS's deploy badge and a
Postgres-hosting link alongside AWS/Azure/Northflank/Render/Vercel/
Elestio; remove that one option (and its dedicated deployments/
railway.mdx page + nav entry), keep the rest. The WEBAPP_URL
RAILWAY_STATIC_URL fallback and its turbo.json cache-key entry are
real env-var integration and stay untouched.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-04 02:08:46 -07:00
zeekayandHanzo Dev 8d6c57b3d8 chore: symlink AGENTS.md + GEMINI.md + CLAUDE.md -> LLM.md
Co-authored-by: Hanzo Dev <[email protected]>
2026-09-02 00:56:03 -07:00
zeekay 5d96e4d016 fix(license): the shipped Zen carries the notice the OFL requires
All ten vendored Zen binaries had name ID 0 rewritten to 'Copyright 2026
Hanzo AI, Inc.' alone, dropping 'Copyright 2024 The Geist Project
Authors' — and Zen is drawn from Geist, so OFL section 2 binds that line
to every copy. Name ID 13 still pointed at the OFL while the notice it
governs was gone.

Replaced with the authored bytes from @hanzo/font 1.9.2. Every other
name record, every table and all 974 glyphs were already identical, so
nothing renders differently; only the copyright record changes.
2026-08-28 11:49:55 -07:00
zeekay 7e4d8eca23 fix(type): the logos name a face the app never loads
The three Hanzo wordmark SVGs asked for Inter, which the app has not
shipped since it moved to Zen, so every one of them silently fell
through to the system UI face and rendered the mark in whatever the
viewer's OS supplies. They now name Zen.

The atoms package also carried seven Inter woff2 subsets left behind by
an old next/font build. Nothing in the tree referenced them and they
went out in the npm tarball as dead weight.
2026-08-28 11:09:04 -07:00
zeekay b95e61fc6e fix(font): bind the family the package actually exports
@hanzo/font 1.9.1 exports Zen. The name table, zen.css and every stylesheet
call the family Zen, so ZenSans named a family that does not exist; twenty
files imported it and would not resolve against the version they depend on.
The SDK examples bound it to `inter` and `poppins` — index.tsx held two
names for one Zen — so a customer copying them read the sans as Inter. The
atoms theme set --font-sans from --font-inter, which nothing defines, while
--font-zen-sans is the property the package publishes.
2026-08-28 08:30:21 -07:00
zeekay 72d4b86c25 fix(type): the two references that were left pointing at files that are gone
The OG route still fetched /fonts/cal.ttf for its display weight after that
file was deleted, so every share card would have rendered with one of its three
faces missing — a break the previous commit introduced. Zen SemiBold.

And the embed theme's stored default was fontSrc "https://cal.com/cal.ttf",
written into every branded booking page, so a customer's own page fetched its
face from our upstream's host. It is same-origin now.
2026-08-25 12:32:27 -07:00
zeekay 74b81c2bd0 fix(type): the OG cards, the emails and the embed stop naming other people's faces
Three surfaces the earlier pass missed, and the embed is the one that matters
most: packages/embeds/embed-core runs inside a CUSTOMER's page and its
stylesheet carried @font-face src url("https://cal.com/cal.ttf") — so every
page anyone put our embed on made a request to our upstream's domain and told
that host about the visit. An embed has no business fetching a face at all; the
headings inherit the host page's stack.

The OG route fetched Inter-Regular.ttf and Inter-Medium.ttf and registered them
as "inter", so every share card was set in a face the product stopped using —
satori reads ttf, which is why the variable file could not serve it. Zen's
static cuts, carried beside them.

shared-globals declared Cal Sans and Inter var; one Zen variable file covers
both roles. The transactional emails linked and @imported fonts.googleapis.com
for Roboto and Inter.
2026-08-25 12:31:32 -07:00
zeekay c5a4964d9d fix(type): the calendar reads Zen, and nothing fetches a face from Google
Three entry points called next/font/google for Inter and bound it to
--font-sans, so the product rendered in a Google-hosted face and made the
request to fetch it before anything painted. They take @hanzo/font's ZenSans,
which is local; the --font-sans contract the app already sets from the font
object is unchanged, so nothing downstream moves.

The display face was Cal Sans — the upstream product's own, which we have no
licence to ship under our name. Both apps take Zen's matching cuts and the
seven CalSans files are gone.

The platform SDK examples are sixteen more next/font/google imports, and they
matter for the reason the docs examples do: a customer scaffolds from them, so
whatever face they open with becomes the face of somebody else's project.

`interFont` is `sansFont` — a binding named after a face it no longer holds is
the thing the next reader has to be told about.
2026-08-25 12:14:00 -07:00
zeekay 3d4be841fe fix(brand): the tab shows our mark, not the framework we built on
These favicons still shipped the upstream artwork of whatever the surface was
scaffolded from, so a customer with a few of our products open read someone
else in every tab. They are @hanzo/logo favicon.{ico,svg,png} now, one source
for the geometry.
2026-08-25 11:49:19 -07:00
zeekay 85e9b5c545 carry the github copy onto the forge
github.com held commits this host lacked, which refuses the mirror push
("fetch first") and stops github receiving anything at all. Merging rather
than overwriting, so the mirror is a fast-forward again and neither side's
work is dropped.
2026-08-20 21:52:35 -07:00
zeekay c816524d41 run on the native fleet
Adds .hanzo/workflows/cicd.yml calling the canonical pipeline and drops the
GitHub-hosted workflows it replaces. Lands here because this is where the repo
is written — git.hanzo.ai is upstream and github.com is its push mirror, so the
same change made on github.com never reaches the runner fleet.
2026-08-20 20:11:51 -07:00
zeekay 6c4fe614bf Report vulnerabilities to us, not to the upstream we forked
This repo is a fork, and its SECURITY.md still carried the upstream's contact —
so a researcher who found a hole in what WE ship was told to mail a vendor who
cannot fix it, and who would then know about a live vulnerability in our
production before we did.

Fourteen repos were in that state: datastore -> [email protected], git and
its two worktrees -> [email protected], auto -> [email protected],
calendar -> [email protected], dns -> [email protected], python-sdk ->
[email protected], plus bot, gui-gates, gui-geist, playground and
playground-oauthcb pointing at brand domains with no mailbox behind them.

All of them now carry one policy and one address, [email protected], matching
what cloud and gateway already used. The policy says out loud to report here
rather than upstream, because the next fork will inherit the same file and the
same instinct.
2026-08-13 14:35:50 -07:00
zeekayandHanzo Dev 31549c2042 ci: canonical pair — hanzo.yml + forge caller
github.com has no runner for hanzo-build-linux-amd64, so a caller under
.github/workflows is a gate that can never be scheduled. This is the ~7-line
caller on the plane that can (git.hanzo.ai git-runner fleet), pinned @v1.

Co-authored-by: Hanzo Dev <[email protected]>
2026-08-06 02:29:10 -07:00
zeekayandHanzo Dev 220733777f NOTICE: attribute the upstream this is forked from
The repo carries the upstream LICENSE but no NOTICE, so nothing states which
project the code derives from or who holds copyright on it. Added in the same
form the other forks here use.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 10:46:02 -07:00
zeekay a1662e1db2 merge(hanzo/overlay): consolidate onto main 2026-07-21 17:07:38 -07:00
zeekay 0733251184 hanzo/overlay: overlay README (deploy, white-label, MIT license note) 2026-07-21 16:16:11 -07:00
zeekay d0add2f659 hanzo/overlay: Hanzo wordmark logos + env overlay example 2026-07-21 16:13:40 -07:00
zeekay 0a15266d85 hanzo/overlay: k8s manifests + ghcr build/rollout workflow for cal.hanzo.ai 2026-07-21 16:10:38 -07:00
Anirban SinghaandGitHub f004349273 refactor: rename getEventLocationType to getLocationByType for better clarity (#28567)
* chore: rename getEventLocationType

* chore: update imports
2026-07-09 09:22:35 +00:00
shafi-VMandGitHub 761b780aa2 fix(bookings): refund all seat payments when cancelling a paid seated… (#29685)
* fix(bookings): refund all seat payments when cancelling a paid seated booking

A paid seated booking creates one Payment row per seat on the same bookingId (each seat's payment_intent.succeeded webhook flips only its own payment via handlePaymentSuccess). processPaymentRefund only refunded payment.find((p) => p.success) — the first successful payment — so fully cancelling a multi-seat paid booking with an auto-refund policy refunded a single seat and left the other attendees charged with no error surfaced.

Refund every successful, not-yet-refunded payment instead.

Tests: unit regression in processPaymentRefund.test.ts (all payments refunded, verified red before the fix); integration test in handleCancelBooking.test.ts proving a full cancel of a seated multi-payment booking hands all payments to the refund path.

* fix(bookings): make seat refunds resilient and drop dayjs in test

Address CodeRabbit review on #29685:

- processPaymentRefund now attempts every seat's refund independently and throws an aggregate error, so one provider failure no longer skips the remaining seats.
- Add a regression test for that resilience, and use native Date instead of dayjs for fixed-offset test timestamps.
2026-07-09 14:23:03 +05:30
okxintandGitHub 009f91d163 fix(CalEventParser): skip null/undefined values in getUserFieldsResponses (#29703)
When a booking question is optional and left unanswered, the field value
stored in customInputs can be null. The previous guard only checked
for empty strings, so null (and undefined) would coerce to the literal
strings "null"/"undefined" inside the template literal, polluting calendar
event descriptions.

Fixes #29688
2026-07-08 18:01:41 +00:00
SreeCharan DesuandGitHub bb7c87cae1 fix(notifications): use instance URL in push test notification (#29673)
Fixes #29567

The test push on subscribe hardcoded app.cal.com. Use WEBAPP_URL instead,
wrap JSON.parse in try/catch, and localize the title/body.
2026-07-08 17:53:34 +00:00
0968bcef01 fix(calendar): sync Cal.diy iCalUID events (#29580)
Co-authored-by: Kartik <[email protected]>
2026-07-07 21:53:03 +05:30
Anirban SinghaandGitHub ca90ca2c94 refactor(app-store): move credential query to repository pattern (#29724)
* refactor(app-store): move credential query to repository pattern

* chore: removed unused imports
2026-07-06 08:40:17 +00:00
Alana AnjosandGitHub f3284f581f docs: add windows/powershell setup troubleshooting for prisma (#29707)
Adds a note explaining how to manually push schema using PowerShell when Turbo fails to pass environment variables down to the prisma workspace.
2026-07-06 08:29:29 +00:00
Gaurav KumarandGitHub 188aaa1857 fix(emails): send METHOD:CANCEL in ICS for cancelled bookings (#29708)
Fixes an issue where cancellation emails were sending ICS files with
METHOD:REQUEST instead of METHOD:CANCEL. As per RFC 5546, calendar
clients only process cancellations correctly when METHOD:CANCEL is used,
otherwise cancelled events remain in attendee calendars with active
reminders.

- Use METHOD:CANCEL for cancelled booking ICS files
- Keep METHOD:REQUEST for non-cancelled booking invitations
- Preserve STATUS:CANCELLED and sequence handling
- Add tests to verify the generated ICS method for cancellations
2026-07-05 10:23:53 +00:00
Gaurav KumarandGitHub 032962f577 fix(ui): render markdown headings properly in event descriptions (#29648)
* fix(ui): render markdown headings properly in event descriptions

* fix(ui): Add noopener and noreferrer to external links in markdownToSafeHTML

* fix(ui): revert external link changes in markdownToSafeHTML

* fix(ui): update markdown heading styles
2026-07-03 11:52:08 +05:30
Gaurav KumarandGitHub 8f89c082e8 fix(i18n): add missing space between number and unit in Hebrew duration (#29695) 2026-07-03 06:21:43 +00:00
53e32a5bba fix: return 404 when booking does not exist (#29583)
Signed-off-by: Chayan Das <[email protected]>
Co-authored-by: Bandhan Majumder <[email protected]>
2026-07-01 01:26:48 +05:30
Anirban SinghaandGitHub 5d6d4d30cc refactor: app category metadata to use Record<AppCategories, AppCategoryEntry> for exhaustive type safety (#29558)
* refactor: derive category metadata from single Record source of truth

* test: add test for category order and entries sync

* fix: check for duplicates
2026-06-29 20:25:39 +05:30
Bandhan MajumderandGitHub b97cd6203d fix: security audit (#29657) 2026-06-27 02:01:09 +05:30
Jimmy HeandGitHub 62317bd4e1 fix: pass bookingFields and locale to handlePayment in createNewSeat (#29639) 2026-06-25 04:21:38 +00:00
Anirban SinghaandGitHub 051ae77279 chore: remove obsolete ts comment (#29638) 2026-06-24 22:30:25 +00:00
0d164da8dd fix: implement missing password validation (#27634)
* fix: validate password presence and requirements

* chore: add error code for invalid passwords

* chore: avoid trimming password

* chore: add test for password validation

* fix: update password to delete user

* fix: create user password following protocol

* test: simplify deleteMeHandler password validation tests

* fix: address coderabbit

* fix: modify login params for failing tests

* fix: failing e2e tests

---------

Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-22 10:37:09 +05:30
a46d5f8dd4 docs(claude): add path-scoped frontmatter to four agent rules (#29612)
Adds `paths:` YAML frontmatter so each rule only loads into Claude Code
context when the agent is working on relevant files, keeping context lean
in a large monorepo.

- architecture-page-level-auth: fires on page.tsx and layout.tsx
- data-prisma-migrations: fires on packages/prisma/**
- testing-playwright: fires on playwright dirs, *.e2e.ts, and api e2e dirs
- api-thin-controllers: fires on *.controller.ts files only

Co-authored-by: Claude Sonnet 4.6 <[email protected]>
2026-06-21 11:21:14 +00:00
yadavlokesh1andGitHub c0b13fb120 docs: remove dead Discussions links (#29617)
remove dead Discussions links
2026-06-21 16:50:46 +05:30
7469444aea fix: align confirmation dialog header and footer (#29588)
Signed-off-by: Chayan Das <[email protected]>
Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-19 12:11:40 +05:30
1599dfd515 fix: zero-pad username suggestion suffix consistently (#29571)
generateUsernameSuggestion built its numeric suffix with
String(rand).padStart(4 - rand.toString().length, "0"). padStart's first
argument is the target total length, not the number of pad characters, so the
expression only padded single-digit numbers: rand=1 became "001" but rand=42
became "42" and rand=999 stayed "999". Suggested usernames therefore had
inconsistent suffix widths, and the magic 4 didn't match the 3-wide output the
existing test pins ("johnny001").

Pull the suffix into a small helper that always pads to 3 digits, so collisions
and the returned value share one definition and every suggestion is uniformly
zero-padded. Add unit tests for the first-attempt path and for two- and
three-digit suffixes; the two-digit case fails on the old code.

Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-19 05:37:42 +00:00
ebf696a991 fix: remove console.log and improve type safety in tRPC routers (#29529)
- Remove two console.log statements dumping private hashed link data
  in update.handler.ts (fixes production data leakage)
- Replace console.log(e) with structured logger.error in
  getScheduleByEventTypeSlug.handler.ts
- Fix @ts-expect-error by typing reduce accumulator as
  Record<string, unknown> in update.handler.ts
- Narrow Prisma include to select in duplicate.handler.ts:
  team and webhooks now fetch only required fields

Fixes #29500

Co-authored-by: lucadapice <[email protected]>
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-19 10:53:23 +05:30
Chayan DasandGitHub 4e529cbad1 fix: user table to load on scroll (#29593)
* fix: load more users on table scroll

Signed-off-by: Chayan Das <[email protected]>

* refactor: move user listing logic to UserRepository

Add a dedicated listUsers method with search and cursor pagination support.

Add repository tests covering filtering and pagination.

Ensure user listing metadata remains consistent with the returned results.

Signed-off-by: Chayan Das <[email protected]>

---------

Signed-off-by: Chayan Das <[email protected]>
2026-06-18 18:09:12 +00:00
Bryan VarelaandGitHub 561cf889ab fix(daily-webhook): use BookingRepository instead of direct prisma call (#29541) 2026-06-16 12:34:18 +00:00
Bandhan MajumderandGitHub 70a883b191 fix(ci): retry workflow cancellation on 409 conflicts (#29584) 2026-06-16 17:46:01 +05:30
dcd0da831f refactor: use userRepository class methods for signup handlers (#29561)
* refactor: use userRepository class methods for signup handlers

* feat: add user repo modules for DI

* feat: build user repo container

* test: integration test for user repository

* fix: use DI container in selfhosted

* refactor: tests, module, container and handlers

---------

Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-14 16:11:21 +00:00
642c38582e fix: correct CLAUDE.md symlink casing to AGENTS.md (#29556)
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
2026-06-14 07:05:48 +00:00
Chayan DasandGitHub 9104545a18 fix(frontend): improve password update form UX and add translation (#29544)
- disable update button until form is valid
- add required field validation
- add translation key for password complexity message

Signed-off-by: Chayan Das <[email protected]>
2026-06-12 20:12:36 +00:00
ca03f007df fix: getUserVerifiedPhoneNumber calls phone lookup instead of email (#29458)
getUserVerifiedPhoneNumber incorrectly called getUserVerifiedEmail
on the repository, causing verified phone numbers to never be found.

Fixes #29450

Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-12 13:26:28 +05:30
4026669e68 fix(api): return 401 instead of 409 for unauthenticated /api/me requests (#29538)
* api: me: fix return 401 instead of 409 for unauthorized requests in the me API route

Signed-off-by: Chayan Das <[email protected]>

* undo import changes

Reorder imports for better organization.

---------

Signed-off-by: Chayan Das <[email protected]>
Co-authored-by: Bandhan Majumder <[email protected]>
2026-06-11 03:56:55 +00:00