Skip to content

sync: upstream v0.30.6 - #215

Open
AminDhouib wants to merge 124 commits into
canaryfrom
sync/upstream-v0.30.6
Open

AminDhouib wants to merge 124 commits into
canaryfrom
sync/upstream-v0.30.6

Conversation

@AminDhouib

Copy link
Copy Markdown
Member

Syncs the fork to upstream release tag v0.30.6 (121 upstream commits since v0.30.5). Version set to v0.30.6-community.1.

Merge commit, never a rebase, per docs/UPSTREAM_SYNC.md. Do not merge this yet — merge, release and deploy are the maintainer's call.

Summary

Headline upstream features in this release:

  • Infomaniak and OVH DNS providers (DnsProviderType += infomaniak, ovh)
  • AWS Parameter Store vault provider (VaultProviderType += aws-parameter-store)
  • Infisical secret-reference expansion + folder paths
  • Whitelabeling security fixes</style> tag XSS breakout scrub (including </style/> and whitespace variants), SVG sanitising on upload — plus OG metadata (ogImageUrl, absolute fallback OG image for social scrapers)
  • Organization logo drag-and-drop upload with resize-to-WebP, and org-name truncation polish in the sidebar
  • SSO enforcement on the server-side sign-in endpoints: blocks password, social and passkey sign-in and email signup when enforceSSO is on; SSO account-linking trust
  • DNS upsert content-matching fixes
  • Domain validation now includes the server's interface addresses (not just its public IP), and resolves both A and AAAA records
  • Server-health address-pool detection now reads docker info over the socket instead of /etc/docker/daemon.json (which isn't mounted into the container)
  • nanoid bump; trial 14 → 7 days (cloud-only, no effect self-hosted)

Also notable: v0.30.6 (8c9e473b4) reverts the v0.30.5 default Docker build-context break. getDockerContextPath returns null again when unset and builders/docker-file.ts restores the fallback to the Dockerfile's own directory. That break only ever shipped in v0.30.5-community.1. Users who set dockerContextPath explicitly to work around it are unaffected — an explicit context is still honoured — and do not need to revert their config.

Conflicts and resolutions (16 files)

File Resolution
.claude/skills/fix-issue/SKILL.md modify/delete → kept deleted. The fork removes upstream's .claude skill files on purpose. Verified .claude/settings.json was not resurrected either.
drizzle/meta/0191..0195_snapshot.json (add/add ×5) ours. See Migrations below.
apps/dokploy/package.json version → v0.30.6-community.1. Kept the fork's #213 security pins (next 16.3.3 > upstream's 16.3.0, plus the sharp@<0.35.4 and js-yaml@4 overrides); took upstream's other dependency changes.
pages/_document.tsx theirs (same-change collision, see below).
server/api/routers/proprietary/whitelabeling.ts theirs (same-change collision).
components/dashboard/organization/handle-organization.tsx theirs, then re-applied the fork's organization-description feature on top.
pages/index.tsx upstream's structure, fork behaviours re-applied.
pages/register.tsx upstream's structure + self-hosted social login.
pages/invitation.tsx upstream's structure + await router.push(...).
pages/send-reset-password.tsx upstream's structure, minus the !IS_CLOUD redirect (self-hosted password reset).
components/dashboard/application/domains/handle-domain.tsx ours, with upstream's small 0f28775a1 diff applied onto it.
packages/server/src/lib/auth.ts both sides kept.

Same-change collisions

The fork had already ported two upstream PRs before they merged upstream — Dokploy#4769 (whitelabeling FOUC, fork commit 2035eed43) and Dokploy#4765 (org logo drag-and-drop, 625b42dff), both by Yash Kumar. Upstream's further-developed versions now win. Taken wholesale: upstream's extracted utils/image-processing.ts, utils/sanitize-svg.ts, utils/create-server-helpers.ts, components/shared/truncate-tooltip.tsx, and the removal of whitelabeling-provider.tsx (confirmed zero remaining references). Upstream also adopted the fork's classNameContent prop on components/ui/dropzone.tsx verbatim, so that file is now byte-identical to upstream and both fork callers still work.

Two behavioural deltas accepted under theirs-wins, both documented in the playbook:

  1. The fork's port inlined the favicon as a base64 data URI so it was present in the first HTML response; upstream emits the raw faviconUrl. Upstream's version is otherwise a superset (OG metadata + the XSS/SVG fixes).
  2. whitelabelingConfig.metaTitle is gone — upstream drives the document title from appName and adds ogImageUrl.

Fork behaviours re-applied on top of upstream's files

  • index.tsxgetPostLoginDestination(router.query) replaces every /dashboard/home literal (4 client redirects + 2 getServerSideProps redirects) so the validated post-login target survives password, passkey, 2FA, backup-code, social and SSO sign-in. This is the MCP consent return path (ec4e90253, 4af3e723d) — losing it would break the remote-MCP OAuth flow. Plus SocialLoginButtons on self-hosted when GitHub/Google env vars are configured (9e63ae180), callbackURL threaded into both <SignInWithSSO> branches, and the per-branch setIsLoading(false) calls that keep the button spinning across the awaited redirect (94be4ca34).
  • register.tsx — self-hosted social login (9e63ae180).
  • send-reset-password.tsx — password reset allowed on self-hosted (03d51628c).
  • invitation.tsxawait router.push(...) (94be4ca34).
  • handle-organization.tsx — organization descriptions (d8ff0a7a7), stored in better-auth's opaque metadata JSON. The fork's {!isControlled && <DialogTrigger>} guard was deliberately not re-applied: upstream ships the same controlled open/onOpenChange props and renders the trigger unconditionally, and no caller uses controlled mode.
  • handle-domain.tsx — every fork domain feature kept (wildcard domains + Traefik v3 HostRegexp, user-owned wildcard base, wildcard domain restriction, Cloudflare Tunnel publishing + Cloudflare Access, custom certificate provider display). Upstream's diff — defer the AddDomain queries until the dialog opens — was applied onto ours; the resulting diff vs canary is exactly upstream's five enabled: changes and nothing else.
  • auth.ts — both sides survive. Upstream's SSO enforcement runs first in hooks.before (a hard deny for the whole request), then the fork's MCP OAuth gates (/mcp/register DCR policy, /mcp/authorize consent proof); the fork's hooks.after refresh-rotation clamp, buildMemberSession, 30-day sliding sessions and session-rejection logging are untouched. The two path sets are disjoint, so ordering is readability, not behaviour.

Migrations

Fourth application of the playbook's Drizzle rule 4. Upstream added 0191_cool_christian_walker, 0192_light_lake, 0193_chemical_the_liberteens, 0194_acoustic_prima and 0195_classy_whirlwind — but the fork has released migrations at all five of those numbers, so instances have already run the fork's copies and taking upstream's would strand production. Upstream's five .sql files, five snapshots and five _journal.json entries were dropped, and the schema delta regenerated into the fork's next free slot as 0201_steep_sage:

-- Re-issue of upstream v0.30.6 migrations 0191_cool_christian_walker,
-- 0192_light_lake, 0193_chemical_the_liberteens, 0194_acoustic_prima and
-- 0195_classy_whirlwind in a fork slot: the fork had already released
-- migrations at 0191-0195, so upstream's copies were dropped and their schema
-- delta regenerated here. Guarded with IF NOT EXISTS so instances that somehow
-- already have these objects are a no-op.
ALTER TYPE "public"."DnsProviderType" ADD VALUE IF NOT EXISTS 'infomaniak';--> statement-breakpoint
ALTER TYPE "public"."DnsProviderType" ADD VALUE IF NOT EXISTS 'ovh';--> statement-breakpoint
ALTER TYPE "public"."VaultProviderType" ADD VALUE IF NOT EXISTS 'aws-parameter-store' BEFORE 'doppler';--> statement-breakpoint
ALTER TABLE "webServerSettings" ALTER COLUMN "whitelabelingConfig" SET DEFAULT '{"appName":null,"appDescription":null,"logoUrl":null,"faviconUrl":null,"customCss":null,"loginLogoUrl":null,"supportUrl":null,"docsUrl":null,"errorPageTitle":null,"errorPageDescription":null,"footerText":null,"ogImageUrl":null}'::jsonb;--> statement-breakpoint
ALTER TABLE "sso_provider" ADD COLUMN IF NOT EXISTS "domain_verified" boolean DEFAULT true NOT NULL;

Guards follow the 0199_complex_mantis pattern (ADD VALUE IF NOT EXISTS / ADD COLUMN IF NOT EXISTS); the SET DEFAULT is naturally idempotent. None of the five upstream migrations is a data backfill, so nothing had to be hand-carried this time.

Verified:

  • The generated SQL contains no DROP and touches no fork object — the proof that the schema merge preserved every fork column and table.
  • Snapshot 0201 still has organization.wildcard_domain, project.wildcardDomain, project.useOrganizationWildcard, webServerSettings.domainRestrictionConfig, the three oauth_* MCP tables and the three build_policy_* tables from feat(build-policy): enforced remote builds, registry push, deploy-by-digest, queue coalescing, required checks #209's 0200.
  • _journal.json is monotonic in when, carries no upstream 01910195 entries, and 0201 (1789444271863) sorts after 0200_handy_lifeguard (1789011785969).
  • Drizzle files kept LF (.gitattributes enforces it).

Silent hazards found

  • webServerSettings.domainRestrictionConfig was missing from the fork-columns ledger in the playbook, even though it is a fork column on an upstream-owned table — exactly the class of drift the ledger exists to prevent. It survived this merge, but it was surviving by luck rather than by check. Added to the ledger.
  • The v0.30.5 BREAKING build-context section was stale: upstream reverted that change at v0.30.6. The playbook now says so, since it changes the release notes for this release.
  • generateTraefikMeDomain (the v0.30.5 trap): both call sites still pass the fork's 4th projectId argument and read .domain. No new upstream call sites in this release.
  • Only two upstream routers changed (organization.ts, whitelabeling.ts) and neither adds a procedure, so the fork's MCP scope map needed no new entries — confirmed by the tool→scope snapshot test passing unchanged. No scope was loosened.
  • organization.ts auto-merged correctly: upstream's name: z.string().min(1) landed on both create and update while the fork's description input survived on both.

A delta audit (fork's diff-vs-upstream before the merge vs after) flagged only 13 files as having lost fork lines, and every one is accounted for: the 5 discarded upstream drizzle snapshots, the 4 same-change collision files (delta correctly → 0), and the 4 login pages + handle-organization.tsx where upstream absorbed boilerplate and only the genuine fork behaviours remain. No fork code was lost anywhere else.

Verification

Check Result
pnpm install clean, exit 0
pnpm --filter=dokploy run typecheck pass (app + packages/server, no output)
pnpm --filter=dokploy run build-server pass
pnpm --filter=dokploy test -- run 2366 passed / 11 failed / 13 skipped (218 files)
__test__/mcp/ (scopes + tool→scope snapshot) 112/112 pass
lockfile resolves the #213 security pins next@16.3.3, sharp@0.35.4, js-yaml@4.3.2

The 11 local failures are in 5 files, all of which the merge does not touch — neither the test files nor their subjects — and are the known Windows/Docker environment class the playbook documents:

  • __test__/deploy/application.real.test.ts (5) — needs Docker, git and nixpacks
  • __test__/server/server-setup.test.ts (3) — command -v awk (no POSIX shell)
  • __test__/backups/restore-use-statement.test.ts (1) — execSync of a sed/awk pipeline
  • __test__/compose/compose-project-directory.test.ts (1) — POSIX path assertions
  • __test__/wss/readValidDirectory.test.ts (1) — POSIX path assertions

CI on Linux is the authority for these.

Release notes input

  • The v0.30.5 Docker build-context break is fixed. Upstream reverted it; the default context is the Dockerfile's own directory again. If you set dockerContextPath to work around the v0.30.5 regression you can leave it as-is — explicit contexts are still honoured.
  • New DNS providers: Infomaniak and OVH.
  • New vault provider: AWS Parameter Store. Infisical gains secret-reference expansion and folder paths.
  • Whitelabeling security: custom CSS can no longer break out of the <style> tag, and uploaded SVG logos are sanitised. New Open Graph metadata (custom OG image, description) so shared links render your branding.
  • Organization logos can now be drag-and-dropped; raster images are resized to 256×256 WebP. Long organization names truncate with a tooltip in the sidebar.
  • SSO enforcement is now enforced server-side — with enforceSSO on, password, social and passkey sign-in and email signup are rejected at the auth layer, not just hidden in the UI. Note this also disables the fork's self-hosted social login buttons when enabled.
  • Domain validation now checks the server's own interface addresses and AAAA records, so validation stops failing on hosts behind NAT or on IPv6-only records.
  • Server health address-pool detection works again inside the container.
  • Security: the fork's patched next 16.3.3 (two critical RCE advisories), sharp and js-yaml pins are carried forward over upstream's older next 16.3.0.
  • Fork features preserved and worth re-testing after deploy: MCP OAuth consent redirect, self-hosted social login, self-hosted password reset, organization descriptions, and the whole wildcard-domain / Cloudflare Tunnel domain dialog.

imrja8 and others added 30 commits July 8, 2026 10:17
- Integrated Dropzone component into handle-organization.tsx.
- Resolved dialog auto-close bug by decoupling Dialog from DropdownMenu trigger.
- Added DOMPurify to sanitize uploaded SVG logos preventing XSS.
- Implemented client-side compression via canvas to resize raster images to 256x256 WebP.
- Enhanced UX with instant logo preview, masked base64 input strings, and a quick-clear button.
- Updated Dropzone to accept classNameContent for local height overrides.
# Conflicts:
#	apps/dokploy/components/proprietary/whitelabeling/whitelabeling-provider.tsx
#	apps/dokploy/pages/_app.tsx
Adds Infomaniak alongside Cloudflare, AWS Route53 and Porkbun, following the
existing DnsClient interface in packages/server/src/utils/dns/.

- infomaniak.ts implements listZones, listRecords, upsertRecord, updateRecord,
  deleteRecord and testConnection against the Infomaniak API. Zones come from
  /1/product?service_name=domain and records from the v2 /2/zones/{zone}/records
  endpoints, which are keyed by zone name rather than by product id.
- A new `infomaniak` value was added to the DnsProviderType enum along with an
  infomaniakDnsConfigSchema (apiToken) in the discriminated union, plus the
  Drizzle migration for the enum change.
- The token is masked/merged like the other providers in services/dns-provider.ts.
- UI: Infomaniak icon and API Token field in the DNS provider dialog, plus
  registration in the provider selector.

Infomaniak's `source` is relative to the zone (empty for the apex), so record
names are translated between Dokploy's fully-qualified format and Infomaniak's
subdomain-only format internally, with the trailing dot handled. TXT targets are
stored quoted by the API and are unquoted on read / quoted on write so that
editing a record does not stack quotes on every save.

Also fills in the missing Porkbun label in show-dns-providers.tsx, which fell
back to displaying the raw enum value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adds OVHcloud alongside Cloudflare, AWS Route53 and Porkbun, following the
existing DnsClient interface in packages/server/src/utils/dns/.

- ovh.ts implements listZones, listRecords, upsertRecord, updateRecord,
  deleteRecord and testConnection against the /domain/zone endpoints of the
  OVHcloud API, on any of its seven regional endpoints (ovh-eu/ca/us, kimsufi
  and soyoustart).
- A new `ovh` value was added to the DnsProviderType enum along with an
  ovhDnsConfigSchema (endpoint, applicationKey, applicationSecret, consumerKey)
  in the discriminated union, plus the Drizzle migration for the enum change.
- The application secret and the consumer key are masked/merged like the other
  providers' secrets in services/dns-provider.ts.
- UI: OVHcloud icon, an endpoint selector and the three credential fields in the
  DNS provider dialog, plus registration in the provider selector.

Three OVH-specific behaviours are handled explicitly:

- Requests are signed with `$1$` + sha1(applicationSecret+consumerKey+method+
  url+body+timestamp). The timestamp comes from the API's own clock via an
  unauthenticated GET /auth/time, since a host clock a few seconds off would get
  every call rejected; the measured drift is cached per endpoint for an hour.
- OVH only applies zone changes once the zone is explicitly refreshed, so every
  successful create, update and delete is followed by POST /domain/zone/{zone}
  /refresh.
- The record update payload carries no fieldType, so changing a record's type
  replaces the record (DELETE then POST) and returns the new id.

The record listing endpoint returns ids only, so each record is fetched
individually with the fan-out capped at 8 concurrent requests.

Also fills in the missing Porkbun label in show-dns-providers.tsx, which fell
back to displaying the raw enum value.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Verified against a live Infomaniak account: the API returns `source: "."` for
apex records, not "" as assumed.

Reading them back produced a doubled dot ("..example.com"), and writing "" meant
an apex upsert never matched the existing record, so it would have created a
duplicate apex record instead of updating it.

toSource now emits "." for the apex and toFqdn accepts ".", "" and "@" so a
hand-written record still round-trips.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
toSource always writes the apex as ".", but listRecords already accepted "" and
"@" as apex spellings on read. The upsert lookup compared sources strictly, so a
record stored under one of the other spellings would not have matched and the
upsert would have created a duplicate apex record instead of updating it.

Normalize the candidate's source before comparing, so read and match agree.

Reported by Greptile on Dokploy#5257.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Changing a record's type deletes the record then recreates it with the new type,
because OVH's update payload carries no fieldType. If the creation failed the
name was left with nothing and no rollback.

The delete still has to come first, since OVH rejects a CNAME that would sit
alongside other data on the same name. So on a failed creation the original
record is put back from the copy already fetched before the delete, and the
original error is rethrown. If the restore fails too, the error names the record
that has to be recreated by hand.

Reported by Greptile on Dokploy#5258.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
listZones used /1/product, which lego uses but the API docs don't: it is the
legacy singular route, it returns no pagination metadata, and it 401s for at
least some tokens. The documented /1/products returns `total`, `pages`,
`items_per_page` and `page`, and defaults to 15 domains per page, so an account
with more domains than that would silently lose zones.

Switch to the plural endpoint and walk every page. Verified against a live
account: forcing per_page=2 collects all 5 domains across 3 pages with no
duplicates.

Also inline the single-use createdId helper.

Both reported by @narcisonunez on Dokploy#5257.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
OVH matches access rules per exact path: a `GET /domain/zone/*` rule grants the
subtree but not the bare `GET /domain/zone` that listZones and testConnection
call. Verified against a live account with a consumer key carrying that single
wildcard rule:

    GET /domain/zone                     -> 403 This call has not been granted
    GET /domain/zone/                    -> 200
    GET /domain/zone/{zone}/record       -> 200

The form only asked for rights on `/domain/zone/*`, so a token created by
following it could not list zones at all, and the failure surfaced as a bare
"This call has not been granted" that points nowhere.

The hint now lists the five rights verbatim, and a token missing the root one
gets an error that names it instead of echoing OVH's message.

Reported by @narcisonunez on Dokploy#5258.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- Sanitize customCss in _document.tsx to prevent XSS breakouts by stripping </style> tags.
- Remove SSR favicon fetching to prevent SSRF and internal network scanning, falling back to client-side fetching.
canary landed its own 0190 (0190_nappy_anita_blake), which collides with this
branch's 0190_perpetual_red_skull. Renaming would not have been enough: drizzle
applies migrations by comparing timestamps against the last applied one, so this
branch's older `when` would have been silently skipped on any deployment that
had already run canary's 0190, leaving the enum without its new value.

Regenerated as 0191_cool_christian_walker with a current timestamp.
canary landed its own 0190 (0190_nappy_anita_blake), which collides with this
branch's 0190_even_mastermind. Renaming would not have been enough: drizzle
applies migrations by comparing timestamps against the last applied one, so this
branch's older `when` would have been silently skipped on any deployment that
had already run canary's 0190, leaving the enum without its new value.

Regenerated as 0191_elite_ultragirl with a current timestamp.
Siumauricio and others added 30 commits September 8, 2026 00:25
Reduce trial duration from 14 to 7 days
…gnment

fix(ui): align close button in web server update modal
Fixes Dokploy#5279. The Domains table (and grid) view mounts one AddDomain
instance per row for the edit action. Its 4 queries (domain.one,
application.one/compose.one, domain.canGenerateTraefikMeDomains,
compose.loadServices) ran unconditionally on mount instead of only
when the edit dialog is open, so any table interaction that causes a
re-render (typing in the host filter, sorting, toggling columns) fired
all 4 queries for every domain row again.
…-and-misc-bugs

fix(domains): stop AddDomain queries flooding the API in table view
better-auth's account-linking guard requires either the IdP asserting
email_verified or the sso_provider row being domainVerified before it
will link an SSO login to an existing local user with the same email.
Entra ID never asserts email_verified (neither via its OIDC userinfo
endpoint nor via SAML attributes), and Dokploy never persisted
domainVerified at all, so linking was permanently impossible for any
Entra-backed provider (OIDC or SAML) regardless of the local user's
own emailVerified state.

Add the domainVerified column, defaulting to true — Dokploy already
scopes providers to an admin-configured domain and gates registration
behind enterprise/admin permissions, so that domain match (still
enforced by better-auth's validateEmailDomain check) is trust enough.

Fixes Dokploy#5099
…ed-trust

fix(sso): trust admin-configured SSO providers for account linking
… existing records

Previously, upsertRecord matched only by type and name, silently
overwriting any existing record of the same type/name with different
content. This caused data loss when users had multiple records of the
same type (e.g. multiple TXT records for SPF + site verification).

Now upsertRecord also checks the record content/target before deciding
to update. If the content differs, a new record is created alongside
the existing one instead of replacing it.

Affected providers: Cloudflare, Porkbun, Infomaniak, OVH.
Tests updated accordingly.
Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com>
* feat: add dynamic open graph metadata for enterprise whitelabeling
…d-filter

perf(dns): filter Infomaniak records server-side when upserting
…eserve-existing-records

# Conflicts:
#	packages/server/src/utils/dns/infomaniak.ts
…xisting-records

fix(dns): match record content in upsertRecord to prevent overwriting existing records
…cret-references

fix(vault): expand Infisical secret references when listing secrets
An Infisical provider is pinned to one non-recursive `secretPath`, so reading
two folders means two providers, two machine identities and two sets of
credentials to rotate. This lets a reference name the folder instead:

    ${{vault.my-provider.external/sentry:SENTRY_DSN}}

`<path>:<KEY>` mirrors the HashiCorp client in this directory, which already
documents that exact format. A relative path resolves against the provider's
`secretPath`, a leading slash is absolute, and a ref without a colon keeps its
current meaning — the whole ref is the secret name at the provider's own path.

A dot cannot be the separator here: Infisical accepts dots inside secret names
(`A.B.C` is a valid key), so `provider.a.b.C` cannot be split unambiguously
and would silently break anyone using such a name.

Refs are grouped by resolved path so each path is listed once, and the login
happens once per batch rather than once per path.

Tests cover the bare ref, relative and absolute paths, a provider at `/`,
grouping with a single login, the error naming the path, and a malformed ref.
…reference

feat(vault): address an Infisical folder from the reference
/etc/docker/daemon.json isn't mounted into the dokploy container, only
docker.sock is, so cat-ing it always failed silently. Read the effective
config over the already-mounted socket instead.

Fixes Dokploy#5383
…s-pools

fix(server-health): detect custom default-address-pools via docker info
121 upstream commits since v0.30.5. Version set to v0.30.6-community.1.

Conflict resolutions (16 files):

- .claude/skills/fix-issue/SKILL.md: modify/delete. The fork deleted
  upstream's .claude skill files on purpose; kept deleted.
- apps/dokploy/drizzle/meta/0191..0195_snapshot.json (add/add): kept ours.
  Upstream's colliding 0191-0195 .sql files and journal entries were dropped
  and their schema delta re-issued as the fork's 0201 (playbook Drizzle rule 4,
  as at v0.30.3 and v0.30.5).
- apps/dokploy/package.json: version v0.30.6-community.1. Kept the fork's
  patched next/sharp/js-yaml pins from #213 (next 16.3.3 > upstream 16.3.0);
  took upstream's other dependency changes.
- Same-change collisions - the fork had already ported upstream Dokploy#4769
  (whitelabeling FOUC, 2035eed) and Dokploy#4765 (org logo drag-and-drop,
  625b42d) before they merged upstream. Upstream's final versions win in
  pages/_document.tsx, server/api/routers/proprietary/whitelabeling.ts,
  components/ui/dropzone.tsx and components/dashboard/organization/
  handle-organization.tsx, including upstream's extracted utils/
  image-processing.ts, utils/sanitize-svg.ts, utils/create-server-helpers.ts
  and components/shared/truncate-tooltip.tsx, and the removal of
  whitelabeling-provider.tsx. The fork's organization-description feature was
  re-applied on top of upstream's handle-organization.tsx.
- pages/index.tsx, register.tsx, invitation.tsx, send-reset-password.tsx: took
  upstream's structure (createServerSideHelpers now lives in
  utils/create-server-helpers.ts), then re-applied the fork behaviours:
  validated post-login redirect carried through social/SSO sign-in for the MCP
  consent return path, social login on self-hosted when configured, password
  reset allowed on self-hosted, and the awaited-redirect login fix.
- components/dashboard/application/domains/handle-domain.tsx: applied
  upstream's small 0f28775 diff (defer the AddDomain queries until the dialog
  opens) onto the fork's version, keeping every fork domain feature.
- packages/server/src/lib/auth.ts: both sides survive. Upstream's SSO
  enforcement on the server-side sign-in/passkey/signup endpoints runs first in
  hooks.before, followed by the fork's MCP OAuth DCR and consent-proof gates;
  the fork's hooks.after refresh-rotation clamp is unchanged. The path sets are
  disjoint.

Notable upstream change: v0.30.6 (8c9e473) reverts the v0.30.5 default
Docker build-context break - getDockerContextPath returns null again when
unset and builders/docker-file.ts falls back to the Dockerfile's directory.
Upstream v0.30.6 added 0191_cool_christian_walker, 0192_light_lake,
0193_chemical_the_liberteens, 0194_acoustic_prima and 0195_classy_whirlwind.
The fork has released migrations at all five of those numbers, so instances
have already run the fork's copies. Per docs/UPSTREAM_SYNC.md Drizzle rule 4,
upstream's five .sql files, five snapshots and five journal entries were
dropped and the schema delta regenerated into the fork's next free slot.

0201 contains exactly the upstream delta and nothing else:
  DnsProviderType   += infomaniak, ovh
  VaultProviderType += aws-parameter-store (BEFORE doppler)
  webServerSettings.whitelabelingConfig default gains ogImageUrl
  sso_provider.domain_verified boolean DEFAULT true NOT NULL

Guarded with ADD VALUE IF NOT EXISTS / ADD COLUMN IF NOT EXISTS, the same
pattern 0199_complex_mantis used for porkbun and phase. The SET DEFAULT is
naturally idempotent. No DROP and no fork object in the generated SQL, so the
schema merge preserved the fork columns and tables.

Journal is monotonic in when, carries no upstream 0191-0195 entries, and
0201 (1789444271863) sorts after 0200_handy_lifeguard (1789011785969).
Four new sections and two corrections to the playbook:

- Same-change collisions on upstream Dokploy#4769 / Dokploy#4765, which the fork had already
  ported. Upstream wins in _document.tsx, whitelabeling.ts, dropzone.tsx and
  handle-organization.tsx; the two accepted behavioural deltas (favicon data-URI
  inlining, metaTitle -> appName/ogImageUrl) are written down, and the one fork
  feature that had to be re-applied on top (organization descriptions).
- The four login pages rebuilt on upstream's generateServerSideHelper, with the
  exact fork behaviours re-applied to each and the commit that introduced them.
- Upstream's SSO enforcement coexisting with the fork's MCP OAuth hooks in
  better-auth hooks.before, and the enforceSSO/social-login interaction.
- Drizzle rule 4 applied a fourth time: upstream 0191-0195 -> fork 0201.

Corrections:

- The v0.30.5 BREAKING build-context change was reverted upstream at v0.30.6,
  so that section now says so; it only ever shipped in v0.30.5-community.1.
- webServerSettings.domainRestrictionConfig was missing from the fork-columns
  ledger even though it is a fork column on an upstream table. Added.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants