Closes#11721
# Which Problems Are Solved
The login app now correctly handles the themeMode from branding
settings:
- Hide toggle when themeMode is LIGHT or DARK — the theme is forced,
users cannot switch
- Show 3-option toggle (light / system / dark) when themeMode is AUTO or
UNSPECIFIED
# How the Problems Are Solved
- Introduced a `BrandingContext` to pass `themeMode` from `ThemeWrapper`
down to `ThemeSwitch`
# Additional Changes
- removed the CSP from next.config.ts to prevent a precedency issue
where the CSP was actually not applied
<!--
Please inform yourself about the contribution guidelines on submitting a
PR here:
https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr.
Take note of how PR/commit titles should be written and replace the
template texts in the sections below. Don't remove any of the sections.
It is important that the commit history clearly shows what is changed
and why.
Important: By submitting a contribution you agree to the terms from our
Licensing Policy as described here:
https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions.
-->
# Which Problems Are Solved
- With Login V2 and EMAIL_VERIFICATION=true, opening the verify page
with send=true can trigger email code generation twice.
- The second code invalidates the first one, so users may receive two
emails where the first code is always invalid.
- This causes failed verification attempts and blocks onboarding for
affected users.
# How the Problems Are Solved
- Removed side-effectful email-code sending from direct server component
execution path.
- Ensured code sending is executed only once in a safe server-side flow,
so React Server Component re-fetches do not generate additional codes.
- Kept verify flow behavior intact while preventing duplicate code
invalidation.
# Additional Changes
- Added/updated logic around the verify flow to make repeated
render/re-fetch paths idempotent for email-code sending.
- Improved reliability of the Login V2 email verification step under App
Router navigation behavior.
# Additional Context
Fixes#11857
- Tested manually with Login V2 and EMAIL_VERIFICATION=true by
completing a new user registration flow to /verify?send=true.
- Verified that only one verification email is sent and the first
received code is valid (no duplicate invalidating code generated).
Related bug report with reproduction details:
[https://github.com/zitadel/zitadel/issues/11857](vscode-file://vscode-app/Applications/Visual%20Studio%20Code.app/Contents/Resources/app/out/vs/code/electron-browser/workbench/workbench.html)
---------
Co-authored-by: Max Peintner <[email protected]>
# Which Problems Are Solved
Add OTP Email challenge needed for Create/Set session in the RT model.
# How the Problems Are Solved
Introduce `OTPEmailChallengeCommand` (validate/execute/events) for
session creation checks
Add unit tests
# Additional Changes
Remove unused fields from `session_challenge_otp_sms.go`
# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11035
---------
Co-authored-by: Marco A. <[email protected]>
# Which Problems Are Solved
This fixes an issue where resending a code for invite flow did not have
the same context it was initially created for
# How the Problems Are Solved
by passing down thre requestId, the context is preserved though a resend
Closes#11923
# Which Problems Are Solved
Client-side gRPC errors (e.g. NotFound, InvalidArgument,
PermissionDenied) were being surfaced as HTTP 500 Internal Server
Errors, causing false SRE alerts and poor UI feedback.
# How the Problems Are Solved
- New transport interceptor (`error-classification.ts`): Automatically
enriches every ConnectError with httpStatus and isUserError metadata via
a `ClassifiedConnectError` wrapper
- Route handler protection (`route.ts`, `flow-initiation.ts`): Catches
classified errors from `getAuthRequest` / `getSAMLRequest` and returns
correct HTTP status codes instead of 500
- Type safety: Replaced all magic number error.code === 9 checks with
typed Code.FailedPrecondition + instanceof ConnectError across
`oidc.ts`, `saml.ts`, `password.ts`, `zitadel.ts`
- Classification-aware logging (`session.ts`): Client/user errors log at
warn level, server errors at error level
- Observability (`otel.ts`): Spans now include error.is_user_error and
http.status_code attributes for alert filtering
# Additional Changes
Gitignore `next-env.d.ts`: This file is auto-generated by Next.js on
every next dev and next build invocation. The two modes write slightly
different import paths (.next/dev/types/ vs .next/types/), which causes
git diff --exit-code to fail in CI whenever a developer runs next dev
locally before committing. Since Next.js regenerates it automatically,
there's no need to track it
---------
Co-authored-by: Ramon <[email protected]>
Co-authored-by: Copilot <[email protected]>
<!--
Please inform yourself about the contribution guidelines on submitting a
PR here:
https://github.com/zitadel/zitadel/blob/main/CONTRIBUTING.md#submit-a-pull-request-pr.
Take note of how PR/commit titles should be written and replace the
template texts in the sections below. Don't remove any of the sections.
It is important that the commit history clearly shows what is changed
and why.
Important: By submitting a contribution you agree to the terms from our
Licensing Policy as described here:
https://github.com/zitadel/zitadel/blob/main/LICENSING.md#community-contributions.
-->
# Which Problems Are Solved
- Creating an organization via `SetUpOrg` failed when a custom domain
was provided in the same request.
- The org-domain setup path checked org existence only against persisted
state, so it could not see the newly created organization before the
batch was pushed.
# How the Problems Are Solved
- Added a preparation-aware org existence check that resolves the org
through the validation filter instead of the direct persisted-state
lookup.
- Reused the transaction-aware preparation filter so later validations
can see earlier in-flight commands from the same `PrepareCommands`
batch.
fixes#11677
---------
Co-authored-by: abhishek kumar gupta <[email protected]>
Co-authored-by: Wim Van Laer <[email protected]>
# Which Problems Are Solved
https://github.com/zitadel/zitadel/pull/11390 renamed "Console" to
"Management Console". While
https://github.com/zitadel/zitadel/pull/11706 already reverted an
unintended rename of the feature key to enable the management console to
use the V2 API for user creation. It was now also discovered that the
rename of the feature itself also broke existing (default)
configurations.
# How the Problems Are Solved
Added a `mapstructure` tag on the instance feature to handle existing
configs.
# Additional Changes
Removed unused `TokenExchange` from the default configuration.
# Additional Context
- relates to #11390
- relates to #11706
- requires backport to v4.x
---------
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
# Which Problems Are Solved
Currently when setting up an instance, for example from the customer
portal through system api, an instance is created together with an
administrator. If no admin user is specified the default user from the
runtime configuration is automatically added.
For the new onboarding, we can to create instances without prompting the
user to set up a complete account right on start, but the current
behavior of the API prevents this, resp. the created account would
fallback to the default user or password.
By providing an empty `password` field in the `owner_password` in the
`AddInstanceRequest` or `huiman.password` in the
`CreateInstanceRequest`, it's already possible to create an account
without password. Until now this however ended up in an initial mail to
be sent to the user to finalize their account setup.
# How the Problems Are Solved
We simply set the `allowInitMail` to false in the `AddHumanCommand` for
setting up the admins. This will prevent an email to be sent out
immediately and gives us the possibility to use the invite flow later
on.
# Additional Changes
None
# Additional Context
- required for https://github.com/zitadel/website/issues/1611
- backport to v4.x
# Which Problems Are Solved
The documentation did not reflect the difference between login v1 and v2
for configuring a JWT-idp
# How the Problems Are Solved
Added a warning in the docs which highlight that difference.
# Additional Changes
- Restructured the docs to reflect a more generic approach.
- Fixed indentation inside the `<Callout type="warning">` block so the
content renders as formatted text instead of a code block.
- Fixed inconsistent acronym casing in the use-case section: "jwt" →
"JWT" and "idp" → "IdP" to match the rest of the page and UI terms.
# Additional Context
- Closes: #11589
<!-- START COPILOT CODING AGENT TIPS -->
---
💡 You can make Copilot smarter by setting up custom instructions,
customizing its development environment and configuring Model Context
Protocol (MCP) servers. Learn more [Copilot coding agent
tips](https://gh.io/copilot-coding-agent-tips) in the docs.
---------
Co-authored-by: Copilot <[email protected]>
Co-authored-by: copilot-swe-agent[bot] <[email protected]>
# Which Problems Are Solved
As part of #11035 , this PR implements the Passkey check logic for
session validation
# How the Problems Are Solved
- Refactor webauth FinishLogin to support new domain model
- Add webauth config to defaults
- Implement passkey check logic and tests
- Manual transaction management to avoid stalling the DB while
FinishLogin callback is executed
- Update passkey Type condition to allow passing a text operation
(equal, contains, etc..)
# Additional Context
This is a cherry-picked PR + minor changes, coming from
https://github.com/zitadel/zitadel/pull/11164
- Relates to #11035
---------
Co-authored-by: Fabienne Bühler <[email protected]>
Co-authored-by: Gayathri Vijayan <[email protected]>
# Which Problems Are Solved
- Recovery codes added via `GenerateRecoveryCodes` were never listed as
active authentication methods by `ListAuthenticationMethodTypes`. The
`user_auth_method` projection reducer (`reduceInitAuthMethod`) set the
state to `MFAStateNotReady`, expecting a subsequent verification event
to transition it to `MFAStateReady`. Unlike TOTP, U2F, and Passwordless
— which all have distinct verification events — recovery codes have no
such event, so they were permanently stuck in `NotReady`.
# How the Problems Are Solved
- Introduced a dedicated `reduceAddRecoveryCodes` reducer for
`HumanRecoveryCodesAddedEvent` that sets `MFAStateReady` immediately,
since recovery codes are usable as soon as they are generated.
- Uses `NewUpsertStatement` (instead of `NewCreateStatement`) so that
regenerating recovery codes for the same user updates the existing row
rather than failing on a duplicate key conflict.
- Removed the `HumanRecoveryCodesAddedEvent` case from
`reduceInitAuthMethod`.
# Additional Changes
- Added `UserAuthMethodTypeRecoveryCode` mapping in `authMethodTypeToPb`
unit test.
- Added integration tests for `ListAuthenticationMethodTypes` covering
both the "recovery codes present" and "recovery codes removed" cases.
# Additional Context
* https://github.com/zitadel/zitadel/issues/11317
---------
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Cursor <[email protected]>
# Which Problems Are Solved
This PR adds the OTP SMS Challenge needed for CreateSession API
https://github.com/zitadel/zitadel/issues/11035
# How the Problems Are Solved
- Introduce `OTPSMSChallengeCommand` (validate/execute/events) for
session creation checks
- Introduce `GetOTPCryptoGeneratorConfigWithDefault` to fetch
per-instance secret generator settings
- Add unit tests
# Additional Changes
Refactor tests in `session_check_recovery_code_test.go` to make the
helper functions reusable in `session_challenge_otp_sms_test.go`
# Additional Context
Related to https://github.com/zitadel/zitadel/issues/11035
Updates all dependencies to latests versions (apart from the ones where
there are already issues to solve their updates).
Some updates required minor changes.
## Problem statement
- `<Tabs>` were not rendered in docs
- Missing steps in README for local dev
## How it was solved
- Enhance the README to better describe local development setup and
clean up formatting.
- Standardize the use of tabs across various components for consistency.
## Additional info
To not cause merge conflicts with
https://github.com/zitadel/zitadel/pull/11729 changes in
`/self-hosting/manage/configure/configure.mdx` were skipped
# Which Problems Are Solved
System API users currently authenticate using raw RSA public keys
configured via Path or KeyData. This approach doesn't integrate well
with Kubernetes tooling.
# How the Problems Are Solved
Allow for the `path`/`keyData` to be an X.509 certificate.
The `NotBefore` and `NotAfter` fields of the certificate are beeing
respected when validating the JWT.
# Additional Changes
# Additional Context
- Closes#11442
---------
Co-authored-by: Livio Spring <[email protected]>
# Which Problems Are Solved
For switching v4.x releases to a corresponding maintenance branch, we
had to trick semantic release and create a `5.0.0-base` tag on main.
This now breaks the docs build, which tries to fetch all tags and build
a corresponding version.
# How the Problems Are Solved
- Ignore pre-released tags/releases for the moment.
# Additional Changes
None
# Additional Context
- requires backport to v4.x
# Which Problems Are Solved
Adding recovery code check step required for the CreateSession RT
implementation.
# How the Problems Are Solved
- Introduce `RecoveryCodeCheckCommand` (validate/execute/events) for
session creation checks
- Add unit tests
# Additional Changes
- refactor password-check code to reuse a shared lockout-policy helper
- add some missing error translations in `internal/static/i18n/en.yaml`
# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11035
---------
Co-authored-by: Silvan <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
# Which Problems Are Solved
Add pnpm overrides to resolve two security vulnerabilities in transitive
dependencies:
node-tar (CVE-2026-23745): Arbitrary file overwrite and symlink
poisoning via insufficient path sanitization — fixed by overriding to
>=7.5.3
Rollup 4 (#477): Arbitrary file write via path traversal — fixed by
overriding to >=4.59.0
# How the Problems Are Solved
applied overrides in package.json
# Which Problems Are Solved
Paragraph reorganization of `SECURITY.md` and some minor changes
# How the Problems Are Solved
- Move out of scope section under `Scope`
- Update `Supported Versions` with an up to date link
- Extend `Out of Scope`
---------
Co-authored-by: Copilot <[email protected]>
# Which Problems Are Solved
2 tests were failing on the new session checks:
- Password check (events) fails due to a race condition
- IDP intent check (events) (also password test) fails due to a flaky
time comparison
# How the Problems Are Solved
- Race condition: remove setting the password hasher in the test. It's
already globally set in `domain_test.go`
- Time comparison: use `assert.WithinRange` instead of `assert.InDelta`
and use 2 second range to make sure you don't get resolution issues
# Additional Context
- Closes#11878
# Which Problems Are Solved
API Requests in the docs, still had old naming
# How the Problems Are Solved
Updated Authorization Reuqest naming in docs with role assignments
# Which Problems Are Solved
As part of moving the session API to the relational database, this PR
adds the functionality to delete sessions through the session API v2 and
the OIDC end_session endpoint.
# How the Problems Are Solved
- added `SessionDeleteCommand` in domain package
- added possibility to pass the session token verifier to the domain
package
- use feature flag to switch API and OIDC usage from CQRS to relation
table
- added a `permissionCheck` condition to let permissions be checked
directly in the repository / sql
- part of it is still a placeholder until actual permission tables are
done
- added a `session_deleted` table to store (recently) deleted sessions
to handle necessary checks / cases like delete my own session, which
needs to be idempotent
# Additional Changes
Fixed `Matches` function of `existsCondition` (as missing an
implementation)
# Additional Context
- closes#11037
---------
Co-authored-by: Stefan Benz <[email protected]>
Added a callout to the Kubernetes deployment guide (`Deploy ZITADEL on
Kubernetes`) explicitly stating that PostgreSQL 18 is not currently
supported, ensuring users deploy with a compatible version (14-17).
# Which Problems Are Solved
In the "new" structured logging, request details were added in different
middlewares, such as request, instance and user IDs. This meant the the
upstream request logging middleware did not have access to metadata that
got added later, resulting in incomplete logs. Furthermore it was not
possible to correlate an API error response to log output.
# How the Problems Are Solved
A mutable request details object is added to the context early on. When
the api authz function run, the instance and user IDs are added to this
object as they become available. Every logline emitted after this
(time-wise) will then all contain these details under the `request` log
group.
<details>
<summary>example output in JSON</summary>
```json
{
"time": "2026-03-13T19:21:20.890428806Z",
"level": "INFO",
"source": {
"function": "github.com/zitadel/zitadel/internal/api/grpc/server/connect_middleware.LogHandler.func1.1",
"file": "/workspaces/zitadel/internal/api/grpc/server/connect_middleware/log_interceptor.go",
"line": 34
},
"msg": "request served",
"request": {
"id": "d6q67c04vtjmi77cbbpg",
"instance_host": "localhost:8080",
"instance_id": "362349751439458307",
"user_id": "362349751440048131"
},
"TraceID": "a9e0fee3522224f3583bbdcda737f4b4",
"SpanID": "a563056eee36920a",
"stream": "request",
"version": "2026-03-13T19:20:59Z",
"protocol": "connect",
"service": "zitadel.user.v2.UserService",
"http_method": "POST",
"path": "/zitadel.user.v2.UserService/ListUsers",
"code": "code_0",
"duration": 12254350
}
```
</details>
Request IDs are now also returned with a response header or metadata.
Depending on the protocol:
- HTTP calls always return the request ID as header, regardless of
status
- gRPC calls always return the request ID as header, even if there was
an error
- connect RPC calls returns the request ID as header on success, trailer
in case of error. This is because header must be set on the response
object, which is nil in case of error. When there is an error, metadata
can be added which are then sent as trailers.
# Additional Changes
- Use the existing call duration middleware for both request ID and
logging for a consistent request start timestamp in all layers.
- Upgrade sloggcp for some fixes (notably TraceID)
- Modify the NoCache middleware so it uses `SetHeaders` instead of
`SendHeaders`. The latter prevented any other handler from setting
headers, including the new request ID middleware.
# Additional Context
Follow up on demo of:
- https://github.com/zitadel/zitadel/pull/11159
- https://github.com/zitadel/zitadel/pull/11435
- backport to v4
---------
Co-authored-by: Copilot <[email protected]>
Co-authored-by: muhlemmer <[email protected]>
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
Co-authored-by: Marco A. <[email protected]>
Introduces the `administrators` relational table and repository layer
for the v3 backend, unifying instance, organization, project, and
project-grant membership into a single scoped model.
Closes#10220
## Changes
- **Domain**: `Administrator` struct, `AdministratorScope` enum,
`AdministratorRepository` interface with typed CRUD, column, condition,
and change helpers. Generated enumer and GoMock.
- **Migration** (`016`): `zitadel.administrators` table with a generated
`id`, scope-alignment check constraint, cascading foreign keys, and a
child `administrator_roles` table.
- **Repository**: CTE-based role mutations (`AddRole`, `RemoveRole`,
`SetRoles`) for atomicity. Roles aggregated via `ARRAY_AGG`.
- **Projection**: Event reducers for
`member.added/changed/removed/cascade_removed` across all four admin
scopes.
- **Fixes**: `Rows.Close()` error wrapping; `TextArray` nil-safe scan +
full `pgtype` array interface; `authorization` and `projectGrant` scan
helpers fixed for `ARRAY_AGG` under `database/sql`; removed unused `ctx`
parameter from `callReduce`.
---------
Co-authored-by: Marco Ardizzone <[email protected]>
## Problem description
- Setup currently creates/updates relational tables, but there is no
built-in way to fully reset the relational schema during iterative
development.
- Re-running setup after schema/projection changes can leave stale
relational objects and projection state behind, which makes local/dev
validation harder.
- There is no explicit, configurable switch in setup steps for
destructive schema recreation behavior.
## How the Problems Are Solved
- Adds a new setup step configuration section for relational tables with
a `ShouldRecreateSchema` flag (default `false`).
- Wires the new config flag into the transactional tables setup step.
- Extends the transactional tables execution logic to optionally:
- Drop the `zitadel` schema with `CASCADE`
- Clean related projection state entries for relational tables in
`projections.current_states`
- Recreate tables through the existing setup flow afterward
- Wraps the destructive operations in a transaction and keeps
error/rollback handling plus logging for visibility.
## Additional Changes
- Adds an explicit warning in step configuration that schema recreation
is intended for development and not production use.
- Keeps behavior fully backward-compatible by default
(`ShouldRecreateSchema: false`), so existing setups are unchanged unless
the flag is enabled.
## Additional Context
- Follow-up for relational setup/dev workflow improvements.
- PR: #11833
## How to use it
### Env `export ZITADEL_RELATIONALTABLES_SHOULDRECREATESCHEMA=true`
### Config
Add the following to your custom setup steps config:
```yaml
RelationalTables:
ShouldRecreateSchema: true
```
# Which Problems Are Solved
Updated the project to use the latest versions of Next.js and React, and
implemented a SWR caching strategy for key settings API calls to improve
performance. Adjusted configuration to ensure compatibility with Next.js
16.
# How the Problems Are Solved
- Updated next to 16.1.6, react & react-dom to 19.2.4, and next-intl to
4.8.3.
- Implemented `API_CACHE_ENABLED` and `API_CACHE_CONFIG` (replacing
deprecated unstable_cacheLife) for:
- getBrandingSettings
- getSecuritySettings
- getPasswordComplexitySettings
- getLoginSettings ...
- Updated default theme colors from blue to a more neutral black and
white
# Additional changes
- Updated login docker image to node 24
---------
Co-authored-by: Ramon <[email protected]>
# Which Problems Are Solved
All http 2 based connect-es clients caused memory leaks in our testing
using the login v2 application as the host.
# How the Problems Are Solved
Switch to connect-rpc based http 1.1 transport for the login v2
# Additional Changes
Improved the otel interceptor implementation and tests.
# Additional Context
- connect-rpc is only enabled for v2 API's so we have to make sure to
not use any v1 apis in the login but this should be the case anyways.
- Discussion #10562
---------
Co-authored-by: Max Peintner <[email protected]>
# Which Problems Are Solved
Removes the Cypress integration tests and associated configuration from
the apps/login project to streamline the build process.
# How the Problems Are Solved
- Removed cypress directory, integration directory, and
cypress.config.ts from apps/login.
- Updated project.json to remove test-integration targets and
dependencies.
- Updated package.json to remove the cypress dev dependency and clean
script reference.
- Updated tsconfig.json to remove the now-redundant integration
exclusion.
- Ensured acceptance tests are preserved and correctly excluded from
build inputs.
---------
Co-authored-by: Florian Forster <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: conblem <[email protected]>
* fix: add `Scopes` to `Request` interface so that scopes can be validated on all requests
* feat: assert org from scope exists when authorizing requests
* fix: check all scopes
* comments
* check org on callback creation
* fix tests
* clarifications
* fix scope marshaling
* fix: enfore organization for authrequest in initiation
* fix: filter sessions on the accounts page by organization scope
* add integration tests
---------
Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Max Peintner <[email protected]>
# Which Problems Are Solved
As part of #11035 , this PR implements the IDP intent check logic for
session validation
# How the Problems Are Solved
- Inject encryption algorithm for IDP intent tokens at DB initialization
- Add the IDP intent repository as an invoke option
- Rework crypto mocks using gomock
- Implement IDP intent check logic
- minor - DB: expand IDP Intent deletion testing table with a test case
where IDP intent is not found
# Noteworthy
I did not implement `domain.Transactional` given the doubts that
@adlerhurst expressed in https://github.com/zitadel/zitadel/pull/11804 .
So, there is no transaction AT ALL in here because the `Execute()`
method contains one single DB call (Delete) and `Validate()` just does
Get calls.
# Additional Context
This is a cherry-picked PR + minor changes, coming from
https://github.com/zitadel/zitadel/pull/11164
- Relates to #11035
- Depends on https://github.com/zitadel/zitadel/pull/11804
# Which Problems Are Solved
The total number of configured IDPs seemed of.
We were counting only the IDP table for non-templated IDPs.
# How the Problems Are Solved
Add a count trigger migration for the IDP template table.
Entries will be counted under the existing
`ResourceCountIdentityProvider`
# Additional Changes
- none
# Additional Context
- Reported internally
- Implemented in #9979
- Related https://github.com/zitadel/zitadel/issues/9957
Co-authored-by: Livio Spring <[email protected]>
This PR updates the "Hosted Login UI" documentation to clarify how text
customization works for the new Hosted Login V2.
**Changes:**
1. Adds a warning callout to the "Customization options" section.
2. Clarifies that Login V2 interface texts currently cannot be modified
via the ZITADEL Console UI.
3. Provides the required workaround, directing users to use the Settings
V2 API to patch translation keys using the en.json locale file as a
reference.
---------
Co-authored-by: Copilot Autofix powered by AI <[email protected]>
# Which Problems Are Solved
We found multiple cases where potentially a panic occurred or could
occur:
- when de/encrypting certain information
- returning apps without any configuration type (?)
- apple IdPs without a proper private key
# How the Problems Are Solved
- Added nil checks
- Check private key format for apple IdPs
- Added necessary helper function
# Additional Changes
Fixed i18n yaml where the IDP errors were indented under `org` instead
of directly under `errors`.
# Additional Context
- requires backport to v4.x
---------
Co-authored-by: Marco A. <[email protected]>
# Which Problems Are Solved
Instead of encoding the private key as base64 and setting it in the env
as SYSTEM_USER_PRIVATE_KEY it is sometimes easier to write it to disk
and use a file path. This is for example also possible when setting up
system users in zitadel core.
# How the Problems Are Solved
Added SYSTEM_USER_PRIVATE_KEY_FILE which is preferred over
SYSTEM_USER_PRIVATE_KEY and expects a file path to a private key in PEM
format (like SYSTEM_USER_PRIVATE_KEY but not base64 encoded). To prevent
loading the private key too often it is cached.
---------
Co-authored-by: Ramon <[email protected]>
# Which Problems Are Solved
It was possible to create a user with an imaginary org.
# How the Problems Are Solved
Check whether org exists before creating the user.
# Additional Changes
# Additional Context
- Closes#11532
# Which Problems Are Solved
For existing customers it could be hard to understand the new aligned
terms we have defined, if they are already used to the "old term"
# How the Problems Are Solved
Adding notes at the top of docs pages to state clearliy new and old
terms.
# Which Problems Are Solved
The OTEL service.name resource attribute is hardcoded to "ZITADEL" in
setupOTelSDK, so the Instrumentation.ServiceName config and the
OTEL_SERVICE_NAME environment variable are both ignored. This makes it
impossible to distinguish between multiple Zitadel instances or
co-located services in tracing dashboards and alerting rules.
# How the Problems Are Solved
The hardcoded string is replaced with cfg.ServiceName so the configured
value flows through. An explicit check for the OTEL_SERVICE_NAME
environment variable is added at the top of resourceWithService, giving
it the highest priority per the OpenTelemetry specification.
# Additional Changes
None.
# Additional Context
Closes#11455
Backport to v4
# Which Problems Are Solved
As part of #11035 , this PR implements the password check logic for
session validation
# How the Problems Are Solved
- Add system config to default configuration of `domain` package for
easy initialization. Intialize the system settings when Zitadel starts
up
- Add password hasher verify logic to the default configuration of
`domain` package. Initialize it when Zitadel starts up.
- Add settings repositories with their mocks
- Implement the logic for doing a password check
# Additional Context
This is a cherry-picked PR + minor changes, coming from
https://github.com/zitadel/zitadel/pull/11164
- Relates to #11035
- Depends on https://github.com/zitadel/zitadel/pull/11777
# Which Problems Are Solved
Adds support for returning CreateUser/UpdateUser action payloads from
RetrieveIdentityProviderIntent so Actions v2 can update user metadata
(and other fields) using the v2 user APIs, ensuring parity with user
creation using Actions v2.
# How the Problems Are Solved
By:
- deprecating `AddHumanUser` and `UpdateHumanUser` fields in
`RetrieveIdentityProviderIntentResponse`
- adding a oneof field called `UserAction` with `CreateUser` and
`UpdateUser` fields to support user creation/update
- setting `UserAction` in the `RetrieveIdentityProviderIntentResponse`
for user creation/update
# Additional Changes
N/A
# Additional Context
- Related to https://github.com/zitadel/zitadel/issues/11369
- Follow-up for PRs https://github.com/zitadel/zitadel/pull/11719,
https://github.com/zitadel/zitadel/pull/11747
- Actions V2 example docs will be updated in a follow-up PR
---------
Co-authored-by: Copilot <[email protected]>
# Which Problems Are Solved
- `@zitadel/docs:generate-proto-docs` could block while `npx` waited for
confirmation to install `@bufbuild/buf`.
- When the docs generation ran through `nx run-many --target generate`,
that interactive prompt was hidden, so the task appeared stuck without
visible output.
# How the Problems Are Solved
- Resolve Buf from the workspace root with `pnpm exec buf generate` so
the repo-pinned CLI is used non-interactively.
- Run the Buf command from the workspace context instead of the
temporary execution directory.
- Keep the existing generation arguments, template handling, and
excluded path handling intact.
# Additional Changes
- Remove the temporary directory setup that was only needed for the
previous `npx`-based invocation.
- Keep the existing `protoc-gen-connect-openapi` installation and PATH
wiring unchanged.
# Additional Context
- Follow-up for the docs generation issue discussed in Discord where
`@zitadel/docs:generate-proto-docs` prompted for `@bufbuild/buf`
installation and appeared blocked under `nx run-many --target generate`.
- Validated with `pnpm nx run @zitadel/docs:generate-proto-docs
--outputStyle=stream`.
- Validated with `pnpm nx run @zitadel/docs:generate
--outputStyle=stream`.
# Which Problems Are Solved
- Apple Sign-In uses a Form Post method to return the authorization
response, which ZITADEL handles at a specific endpoint ending in /form
for the login v1.
- The Console previously displayed the standard callback URL (without
`/form`), causing confusion and configuration errors..
# How the Problems Are Solved
- **Console**: Updated ProviderNextService to accept a suffix string .
- **Console**: Updated ProviderAppleComponent to append the suffix to
the urls.
# Additional Changes
- Updated `docs/docs/guides/integrate/identity-providers/apple.mdx` to
explicitly state that the callback URL end with `/form`
- Updated `docs/docs/guides/integrate/login-ui/external-login.mdx` to
clarify the `/form` suffix requirement for Apple Sign-In in the hosted
login documentation.
# Additional Context
- fixes#11438
---------
Co-authored-by: Ramon <[email protected]>
Co-authored-by: Florian Forster <[email protected]>
# Which Problems Are Solved
In #11239 , the helper function for matrix tests (without the relational
tables enabled) was changed, but the feature was never enabled in the
matrix. Some integration tests currently can't even succeed because of
missing implementations.
# How the Problems Are Solved
This PR correctly enables the feature where intended and returns the
state into the matrix.
This allows returning early for some tests which cannot succeed yet.
Corresponding todos have been re-added as well.
# Additional Changes
None
# Additional Context
- relates to #11239
- requires backport to v4.x
# Which Problems Are Solved
The login v2 container has no way to verify upstream Zitadel API
connectivity before accepting traffic. The existing `/healthy` endpoint
always returns 200 regardless of whether the backend is reachable. This
means Kubernetes routes user traffic to pods that cannot actually serve
login requests, causing silent failures where the root layout swallows
gRPC errors and renders pages with default settings.
# How the Problems Are Solved
A new `/ui/v2/login/ready` endpoint creates a gRPC client using the same
auth and transport path as real requests, calls
`SettingsService.getGeneralSettings()`, and returns `200 OK` on success
or `503 Service unavailable` on failure. This verifies both network
connectivity and authentication credentials to the upstream Zitadel API.
Kubernetes supports readiness probes natively, so this endpoint can be
configured as a readiness probe to gate traffic until the login
container can connect to Zitadel. Docker Compose does not have a
readiness probe concept, so the compose healthcheck and
`healthcheck.mjs` default remain unchanged and continue using
`/healthy`.
The Docker HEALTHCHECK in the Dockerfile has been updated to use
`/ready` so that the image-level health status reflects actual upstream
connectivity. This will also allow us to simplify the Helm chart by
dropping the `wait4x` init containers that currently poll the Zitadel
API before starting the login pod, since the readiness probe makes them
redundant.
# Additional Changes
The `/ready` endpoint has been added to the OTEL HTTP instrumentation
ignore list to avoid noisy probe traces. Unit tests, a wiring spec
integration test, and an OTEL span filtering test have been added for
the new endpoint. The `# TODO: Check healthy, not ready` comment has
been removed from the Dockerfile. The `/healthy` endpoint is kept as-is
for liveness probes.
# Additional Context
The Helm chart changes to use `/ready` for readiness and startup probes
and to remove the `wait-for-zitadel` init container will be done in a
follow-up PR in the `zitadel-charts` repository.