Commit Graph
2005 Commits
Author SHA1 Message Date
Livio SpringandGitHub a0c3ccecf7 fix: use a single translator for middleware (#10633)
# Which Problems Are Solved

Comparing the v3 and v4 deployments we noticed an increase in memory
usage. A first analysis revealed that it might be related to the
(multiple) initialization of the `i18n.Translator`, partially related

# How the Problems Are Solved

Initialize the tranlator once (apart from the translator interceptor,
which uses context / request specific information) and pass it to all
necessary middleware.

# Additional Changes

Removed unnecessary error return parameter from the translator
initialization.

# Additional Context

- noticed internally
- backport to v4.x
2025-09-09 06:34:59 +00:00
Livio SpringandGitHub 79809d0199 fix(actions v2): send event_payload on event executions again (#10651)
# Which Problems Are Solved

It was noticed that on actions v2 when subscribing to events, the
webhook would always receive an empty `event_payload`:
```
{
    "aggregateID": "336494809936035843",
    "aggregateType": "user",
    "resourceOwner": "336392597046099971",
    "instanceID": "336392597046034435",
    "version": "v2",
    "sequence": 1,
    "event_type": "user.human.added",
    "created_at": "2025-09-05T08:55:36.156333Z",
    "userID": "336392597046755331",
    "event_payload":
    {}
}
```

The problem was due to using `json.Marshal` on the `Event` interface,
where the underlying `BaseEvent` prevents the data to be marshalled:

https://github.com/zitadel/zitadel/blob/131f70db3423b80da1b038a822da59c908e4ffa6/internal/eventstore/event_base.go#L38

# How the Problems Are Solved

The `Event`s `Unmarshal` function is used with a `json.RawMessage`.

# Additional Changes

none

# Additional Context

- closes https://github.com/zitadel/zitadel/issues/10650
- requires backport to v4.x
2025-09-09 05:28:29 +00:00
Livio SpringandGitHub 2dbe21fb30 feat(service ping): add additional resource counts (#10621)
# Which Problems Are Solved

Using the service ping, we want to have some additional insights to how
zitadel is configured. The current resource count report contains
already some amount of configured policies, such as the login_policy.
But we do not know if for example MFA is enforced.

# How the Problems Are Solved

- Added the following counts to the report:
  - service users per organization
  - MFA enforcements (though login policy)
  - Notification policies with password change option enabled
  - SCIM provisioned users (using user metadata)
- Since all of the above are conditional based on at least a column
inside a projection, a new `migration.CountTriggerConditional` has been
added, where a condition (column values) and an option to track updates
on that column should be considered for the count.
- For this to be possible, the following changes had to be made to the
existing sql resources:
- the `resource_name` has been added to unique constraint on the
`projection.resource_counts` table
- triggers have been added / changed to individually track `INSERT`,
`UPDATE`(s) and `DELETE` and be able to handle conditions
- an optional argument has been added to the
`projections.count_resource()` function to allow providing the
information to `UP` or `DOWN` count the resource on an update.

# Additional Changes

None

# Additional Context

- partially solves #10244 (reporting audit log retention limit will be
handled in #10245 directly)
- backport to v4.x
2025-09-08 16:30:03 +00:00
ef058c8de6 fix: org remove taken into account during username changes (#10617)
# Which Problems Are Solved

For instance settings related to username changes, already removed
organizations were still processed.

# How the Problems Are Solved

Do no process already removed organizations.

# Additional Changes

None

# Additional Context

None

---------

Co-authored-by: Marco A. <[email protected]>
2025-09-08 13:58:14 +00:00
75774eb64c chore: fix org v2beta integration tests (#10655)
# Which Problems Are Solved

Flakiness in integration tests for organization v2beta service.

# How the Problems Are Solved

Fix eventual consistent handling of integration tests.

# Additional Changes

None

# Additional Context

None

---------

Co-authored-by: Marco A. <[email protected]>
2025-09-08 11:43:16 +00:00
8909b9a2a6 feat: http provider signing key addition (#10641)
# Which Problems Are Solved

HTTP Request to HTTP providers for Email or SMS are not signed.

# How the Problems Are Solved

Add a Signing Key to the HTTP Provider resources, which is then used to
generate a header to sign the payload.

# Additional Changes

Additional tests for query side of the SMTP provider.

# Additional Context

Closes #10067

---------

Co-authored-by: Marco A. <[email protected]>
2025-09-08 11:00:04 +00:00
51e12e224d feat(actionsv2): Propagate request headers in actions v2 (#10632)
# Which Problems Are Solved

This PR adds functionality to propagate request headers in actions v2. 

# How the Problems Are Solved
The new functionality is added to the`ExecutionHandler` interceptors,
where the incoming request headers (from a list of allowed headers to be
forwarded) are set in the payload of the request before calling the
target.

# Additional Changes
This PR also contains minor fixes to the Actions V2 example docs. 

# Additional Context
- Closes #9941

---------

Co-authored-by: Marco A. <[email protected]>
2025-09-08 08:50:52 +00:00
Tim MöhlmannandGitHub a06ae2c835 perf(cache): use redis unlink for key deletion (#10658)
# Which Problems Are Solved

The usage of the Redis `DEL` command showed blocking and slowdowns
during load-tests.

# How the Problems Are Solved

Use [`UNLINK`](https://redis.io/docs/latest/commands/UNLINK/) instead.

# Additional Changes

- none

# Additional Context

- closes https://github.com/zitadel/zitadel/issues/8930
2025-09-08 08:21:32 +00:00
SilvanandGitHub 869282ca49 fix(repo): correct mapping for domains (#10653)
This pull request fixes an issue where the repository would fail to scan
organization or instance structs if the `domains` column was `NULL`.

## Which problems are solved

If the `domains` column of `orgs` or `instances` was `NULL`, the
repository failed scanning into the structs. This happened because the
scanning mechanism did not correctly handle `NULL` JSONB columns.

## How the problems are solved

A new generic type `JSONArray[T]` is introduced, which implements the
`sql.Scanner` interface. This type can correctly scan JSON arrays from
the database, including handling `NULL` values gracefully.

The repositories for instances and organizations have been updated to
use this new type for the domains field. The SQL queries have also been
improved to use `FILTER` with `jsonb_agg` for better readability and
performance when aggregating domains.

## Additional changes
* An unnecessary cleanup step in the organization domain tests for
already removed domains has been removed.
* The `pgxscan` library has been replaced with `sqlscan` for scanning
`database/sql`.Rows.
* Minor cleanups in integration tests.
2025-09-08 09:35:31 +02:00
61cab8878e feat(backend): state persisted objects (#9870)
This PR initiates the rework of Zitadel's backend to state-persisted
objects. This change is a step towards a more scalable and maintainable
architecture.

## Changes

* **New `/backend/v3` package**: A new package structure has been
introduced to house the reworked backend logic. This includes:
* `domain`: Contains the core business logic, commands, and repository
interfaces.
* `storage`: Implements the repository interfaces for database
interactions with new transactional tables.
  * `telemetry`: Provides logging and tracing capabilities.
* **Transactional Tables**: New database tables have been defined for
`instances`, `instance_domains`, `organizations`, and `org_domains`.
* **Projections**: New projections have been created to populate the new
relational tables from the existing event store, ensuring data
consistency during the migration.
* **Repositories**: New repositories provide an abstraction layer for
accessing and manipulating the data in the new tables.
* **Setup**: A new setup step for `TransactionalTables` has been added
to manage the database migrations for the new tables.

This PR lays the foundation for future work to fully transition to
state-persisted objects for these components, which will improve
performance and simplify data access patterns.

This PR initiates the rework of ZITADEL's backend to state-persisted
objects. This is a foundational step towards a new architecture that
will improve performance and maintainability.

The following objects are migrated from event-sourced aggregates to
state-persisted objects:

* Instances
  * incl. Domains
* Orgs
  * incl. Domains

The structure of the new backend implementation follows the software
architecture defined in this [wiki
page](https://github.com/zitadel/zitadel/wiki/Software-Architecturel).

This PR includes:

* The initial implementation of the new transactional repositories for
the objects listed above.
* Projections to populate the new relational tables from the existing
event store.
* Adjustments to the build and test process to accommodate the new
backend structure.

This is a work in progress and further changes will be made to complete
the migration.

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Iraq Jaber <[email protected]>
Co-authored-by: Iraq <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
2025-09-05 09:54:34 +01:00
0575f67e94 fix(projections): overhaul the event projection system (#10560)
This PR overhauls our event projection system to make it more robust and
prevent skipped events under high load. The core change replaces our
custom, transaction-based locking with standard PostgreSQL advisory
locks. We also introduce a worker pool to manage concurrency and prevent
database connection exhaustion.

### Key Changes

* **Advisory Locks for Projections:** Replaces exclusive row locks and
inspection of `pg_stat_activity` with PostgreSQL advisory locks for
managing projection state. This is a more reliable and standard approach
to distributed locking.
* **Simplified Await Logic:** Removes the complex logic for awaiting
open transactions, simplifying it to a more straightforward time-based
filtering of events.
* **Projection Worker Pool:** Implements a worker pool to limit
concurrent projection triggers, preventing connection exhaustion and
improving stability under load. A new `MaxParallelTriggers`
configuration option is introduced.

### Problem Solved

Under high throughput, a race condition could cause projections to miss
events from the eventstore. This led to inconsistent data in projection
tables (e.g., a user grant might be missing). This PR fixes the
underlying locking and concurrency issues to ensure all events are
processed reliably.

### How it Works

1. **Event Writing:** When writing events, a *shared* advisory lock is
taken. This signals that a write is in progress.
2.  **Event Handling (Projections):**
* A projection worker attempts to acquire an *exclusive* advisory lock
for that specific projection. If the lock is already held, it means
another worker is on the job, so the current one backs off.
* Once the lock is acquired, the worker briefly acquires and releases
the same *shared* lock used by event writers. This acts as a barrier,
ensuring it waits for any in-flight writes to complete.
* Finally, it processes all events that occurred before its transaction
began.

### Additional Information

* ZITADEL no longer modifies the `application_name` PostgreSQL variable
during event writes.
*   The lock on the `current_states` table is now `FOR NO KEY UPDATE`.
*   Fixes https://github.com/zitadel/zitadel/issues/8509

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
2025-09-03 15:29:00 +00:00
bdefd9147f fix: permission check for actions v1 post creation user grants (#10638)
# Which Problems Are Solved

Unnecessary default permission check in creating an authorization fails
even if the functionality was called internally.

# How the Problems Are Solved

Move permission check to the proper implementation, so that necessary
permission checks are provided by the responsible API.

# Additional Changes

None

# Additional Context

Closes #10624

Co-authored-by: Livio Spring <[email protected]>
2025-09-03 14:39:18 +00:00
Livio SpringandGitHub a1ad87387d fix: cleanup information in logs (#10634)
# Which Problems Are Solved

I noticed some outdated / misleading logs when starting zitadel:
- The `init-projections` were no longer in beta for a long time.
- The LRU auth request cache is disabled by default, which results in
the following message, which has caused confusion by customers:
```level=info msg="auth request cache disabled" error="must provide a positive size"```

# How the Problems Are Solved

- Removed the beta info
- Disable cache initialization if possible

# Additional Changes

None

# Additional Context

- noticed internally
- backport to v4.x
2025-09-03 09:18:54 +00:00
75a67be669 feat: Feature flag for relational tables (#10599)
# Which Problems Are Solved

This PR introduces a new feature flag `EnableRelationalTables` that will
be used in following implementations to decide whether Zitadel should
use the relational model or the event sourcing one.

# TODO

  - [x] Implement flag at system level
- [x] Display the flag on console:
https://github.com/zitadel/zitadel/pull/10615

# How the Problems Are Solved

  - Implement loading the flag from config
- Add persistence of the flag through gRPC endpoint
(SetInstanceFeatures)
- Implement reading of the flag through gRPC endpoint
(GetInstanceFeatures)

# Additional Changes

Some minor refactoring to remove un-needed generics annotations

# Additional Context

- Closes #10574

---------

Co-authored-by: Silvan <[email protected]>
2025-09-02 09:48:46 +00:00
8df402fb4f feat: List users by metadata (#10415)
# Which Problems Are Solved

Some users have reported the need of retrieving users given a metadata
key, metadata value or both. This change introduces metadata search
filter on the `ListUsers()` endpoint to allow Zitadel users to search
for user records by metadata.

The changes affect only v2 APIs.

# How the Problems Are Solved

- Add new search filter to `ListUserRequest`: `MetaKey` and `MetaValue`
  - Add SQL indices on metadata key and metadata value
  - Update query to left join `user_metadata` table

# Additional Context

  - Closes #9053 
  - Depends on https://github.com/zitadel/zitadel/pull/10567

---------

Co-authored-by: Silvan <[email protected]>
Co-authored-by: Stefan Benz <[email protected]>
2025-09-01 16:12:36 +00:00
fcdc598320 fix: correct river otel metrics units (#10425)
# Which Problems Are Solved

The
[otelriver](https://github.com/riverqueue/rivercontrib/tree/master/otelriver)
package uses default otel histogram buckets that are designed for
millisecond measurements. OTEL docs also suggest standardizing on using
seconds as the measurement unit. However, the default buckets from
opentelemetry-go are more or less useless when used with seconds as the
smallest measurement is 5 seconds and the largest is nearly 3 hours.
Example:
```
river_work_duration_histogram_seconds_bucket{attempt="1",kind="notification_request",otel_scope_name="github.com/riverqueue/rivercontrib/otelriver",otel_scope_version="",priority="1",queue="notification",status="ok",tag="[]",le="0"} 0
river_work_duration_histogram_seconds_bucket{attempt="1",kind="notification_request",otel_scope_name="github.com/riverqueue/rivercontrib/otelriver",otel_scope_version="",priority="1",queue="notification",status="ok",tag="[]",le="5"} 1144
river_work_duration_histogram_seconds_bucket{attempt="1",kind="notification_request",otel_scope_name="github.com/riverqueue/rivercontrib/otelriver",otel_scope_version="",priority="1",queue="notification",status="ok",tag="[]",le="10"} 1144
<...more buckets here...>
river_work_duration_histogram_seconds_bucket{attempt="1",kind="notification_request",otel_scope_name="github.com/riverqueue/rivercontrib/otelriver",otel_scope_version="",priority="1",queue="notification",status="ok",tag="[]",le="7500"} 1144
river_work_duration_histogram_seconds_bucket{attempt="1",kind="notification_request",otel_scope_name="github.com/riverqueue/rivercontrib/otelriver",otel_scope_version="",priority="1",queue="notification",status="ok",tag="[]",le="10000"} 1144
river_work_duration_histogram_seconds_bucket{attempt="1",kind="notification_request",otel_scope_name="github.com/riverqueue/rivercontrib/otelriver",otel_scope_version="",priority="1",queue="notification",status="ok",tag="[]",le="+Inf"} 1144
```

# How the Problems Are Solved

Change the default unit to "ms" from "s" as supported by the middleware
API:
https://riverqueue.com/docs/open-telemetry#list-of-middleware-options

# Additional Changes

None

# Additional Context

None

Co-authored-by: Tim Möhlmann <[email protected]>
2025-09-01 10:31:18 +00:00
Livio SpringandGitHub 8574d6fbab chore(integration test): prevent eventual consistency issue in TestServer_Limits_AuditLogRetention (#10608)
# Which Problems Are Solved

The TestServer_Limits_AuditLogRetention is too reliant on time
constraints when checking that a limit is correctly applied. IN case it
takes to long to do all the preparation, there won't be any events to
read and the test will fail.

# How the Problems Are Solved

Don't require any events to be returned.

# Additional Changes

None

# Additional Context

- Noted a lot of pipeline to fail on this step.
- requires backport to at least v4.x
2025-09-01 12:22:09 +03:00
a9ebc06c77 perf(actionsv2): execution target router (#10564)
# Which Problems Are Solved

The event execution system currently uses a projection handler that
subscribes to and processes all events for all instances. This creates a
high static cost because the system over-fetches event data, handling
many events that are not needed by most instances. This inefficiency is
also reflected in high "rows returned" metrics in the database.

# How the Problems Are Solved

Eliminate the use of a project handler. Instead, events for which
"execution targets" are defined, are directly pushed to the queue by the
eventstore. A Router is populated in the Instance object in the authz
middleware.

- By joining the execution targets to the instance, no additional
queries are needed anymore.
- As part of the instance object, execution targets are now cached as
well.
- Events are queued within the same transaction, giving transactional
guarantees on delivery.
- Uses the "insert many fast` variant of River. Multiple jobs are queued
in a single round-trip to the database.
- Fix compatibility with PostgreSQL 15

# Additional Changes

- The signing key was stored as plain-text in the river job payload in
the DB. This violated our [Secrets
Storage](https://zitadel.com/docs/concepts/architecture/secrets#secrets-storage)
principle. This change removed the field and only uses the encrypted
version of the signing key.
- Fixed the target ordering from descending to ascending.
- Some minor linter warnings on the use of `io.WriteString()`.

# Additional Context

- Introduced in https://github.com/zitadel/zitadel/pull/9249
- Closes https://github.com/zitadel/zitadel/issues/10553
- Closes https://github.com/zitadel/zitadel/issues/9832
- Closes https://github.com/zitadel/zitadel/issues/10372
- Closes https://github.com/zitadel/zitadel/issues/10492

---------

Co-authored-by: Stefan Benz <[email protected]>
2025-09-01 07:21:10 +02:00
5721b63bcb chore: use integration package for name generation (#10591)
# Which Problems Are Solved

Integration test failed sometimes with `organization already
exists`-errors.

# How the Problems Are Solved

Use a consistent function to generate name used for organization
creation.

# Additional Changes

Correct a eventual consistent test for username around organization
domain changes with eventual consistent loop.

# Additional Context

None

---------

Co-authored-by: Livio Spring <[email protected]>
2025-08-29 14:56:16 +02:00
832e78f9bc feat(typescript): add i18n for input labels in Login V2 (#10233)
# Which Problems Are Solved

- Most inputs have hardcoded label

# How the Problems Are Solved

- add usage of i18n library for every label
- add labels to i18n translation files

# Additional Changes

- fixed key used in `device-code-form.tsx` by submit button
- `v2-default.json` was update and contains all values from login app
not only newly added key for labels.

# Additional Context

N.A

---------

Co-authored-by: David Skewis <[email protected]>
Co-authored-by: Max Peintner <[email protected]>
2025-08-29 05:12:12 +00:00
6d0b7ed2aa chore(i18n): Completion Chinese translation (#10109)
# Which Problems Are Solved

- Inconsistencies in the terminology used for "身份认证提供商" (identity
provider) and "身份认证提供者" (identity supplier) in the Chinese translation
files could lead to confusion among users.
- Missing translations for terminology related to identity providers
could hinder user experience and understanding.

# How the Problems Are Solved

- Unified the terms "身份认证提供商" and "身份认证提供者" to consistently use
"身份认证提供者" across all Chinese translation files.
- Added necessary translations to ensure that all relevant terms related
to identity providers are accurately represented in the Chinese
localization.

# Additional Changes

- Improved overall readability and clarity in the Chinese translations
by ensuring consistent terminology for identity-related phrases
throughout the application.
- Complete the missing translations.

# Additional Context

If I have missed any translations, please point them out, and I would be
happy to complete them.

---------

Co-authored-by: Florian Forster <[email protected]>
2025-08-28 14:56:26 +00:00
8e60cce20d fix: correctly handle user grants on project grant to same organization (#10568)
# Which Problems Are Solved

Authorizations (aka user grants) could not be managed correctly if they
were created on a project grant, which itself was based on a project
granted to the own organization. The error persisted if the
corresponding (potentially unintended) project grant was removed again.

# How the Problems Are Solved

Fixed checks for managing user grants: Roles from projects and project
grants get handled individually to ensure cases like project grants on
the own organization.

# Additional Changes

Additional tests for the 3 failing scenarios.

# Additional Context

Closes #10556

---------

Co-authored-by: Livio Spring <[email protected]>
2025-08-28 12:09:52 +00:00
Marco A.andGitHub b604615cab chore: move converter methods users v2 to separate converter package + add tests (#10567)
# Which Problems Are Solved

As requested by @adlerhurst in
https://github.com/zitadel/zitadel/pull/10415#discussion_r2298087711 , I
am moving the refactoring of v2 user converter methods to a separate PR

# How the Problems Are Solved

Cherry-pick 648c234caf618e9b1cf9f093826d94e79883a73a

# Additional Context

Parent of https://github.com/zitadel/zitadel/pull/10415
2025-08-27 13:08:13 +02:00
255d42da65 feat(saml): add SignatureMethod config for SAML IDP (#10520)
# Which Problems Are Solved
When a SAML IDP is created, the signing algorithm defaults to
`RSA-SHA1`.
This PR adds the functionality to configure the signing algorithm while
creating or updating a SAML IDP. When nothing is specified, `RSA-SHA1`
is the default.

Available options:
* RSA_SHA1
* RSA_SHA256
* RSA_SHA512


# How the Problems Are Solved

By introducing a new optional config to specify the Signing Algorithm. 

# Additional Changes
N/A

# Additional Context
- Closes #9842 

An existing bug in the UpdateSAMLProvider API will be fixed as a
followup in a different
[PR](https://github.com/zitadel/zitadel/pull/10557).

---------

Co-authored-by: Stefan Benz <[email protected]>
2025-08-27 09:07:13 +00:00
Stefan BenzandGitHub 2a78fdfe1f fix: define base uri for login v2 feature as string to make it config… (#10533)
…urable

# Which Problems Are Solved

BaseURI defined in environment variables or configuration files was
ignored for Login v2 feature flag.

# How the Problems Are Solved

Define BaseURI as string so that the environment variables and
configuration files can be parsed into it.

# Additional Changes

None

# Additional Context

Closes #10405
2025-08-26 12:18:13 +00:00
0a14c01412 fix: configure default url templates (#10416)
# Which Problems Are Solved

Emails are still send only with URLs to login v1.

# How the Problems Are Solved

Add configuration for URLs as URL templates, so that links can point at
Login v2.

# Additional Changes

None

# Additional Context

Closes #10236

---------

Co-authored-by: Marco A. <[email protected]>
2025-08-26 10:14:41 +00:00
IraqandGitHub 2718d345b8 chore(docker-integration-postgres): adding volume to internal/integration/config/docker-compose.yaml (#10079)
# Which Problems Are Solved

This change makes it easier to delete the integration database

# How the Problems Are Solved

Gives the integration database a volume you can address via name

`docker volume rm config_zitadel_integration_db`
2025-08-26 07:55:30 +00:00
Livio SpringandGitHub 9621d357c0 fix(service ping): improve systemID search query to use index (#10566)
# Which Problems Are Solved

We noticed that the startup for v4 was way slower than v3. A query
without an instanceID filter could be traced back to the systemID query
of the service ping.

# How the Problems Are Solved

A an empty instanceID to the query to ensure it used an appropriate
index.

# Additional Changes

None

# Additional Context

- Closes https://github.com/zitadel/zitadel/issues/10390
- backport to v4.x
2025-08-25 15:07:00 +00:00
IraqandGitHub 24a7d3ceb1 fix(project_roles): fixed bad permission check in command layer for project roles add/update/delete (#10531)
# Which Problems Are Solved

Project Admins would get permission errors when trying to add project
roles

# How the Problems Are Solved

Fixed wrong parameters were being passed into the permission check


- Closes https://github.com/zitadel/zitadel/issues/10505
2025-08-22 06:08:53 +00:00
93ea30ba2e fix: correct unmarshall of EntraID userinfo when retrieving intent information (#10507)
# Which Problems Are Solved

EntraID userinfo gets incorrectly unmarshalled again in the
`RetrieveIdentityProviderIntent` endpoint.

# How the Problems Are Solved

Correctly use the already available information and not try to marshall
it into a `RawInformation` struct again.

# Additional Changes

None

# Additional Context

Closes https://github.com/zitadel/typescript/issues/578

---------

Co-authored-by: Livio Spring <[email protected]>
2025-08-22 05:35:58 +00:00
Livio SpringandGitHub 7abe759c95 Merge commit from fork 2025-08-21 09:02:32 +02:00
Livio SpringandGitHub 6c8d027e72 fix: correctly escape backslash in queries (#10522)
# Which Problems Are Solved

While investigating a support ticket, it was discovered that some
queries using equals or not equals without case matching were not
correctly escaping the value to compare. If a value contained a
backslash (`\`) the row would not match.

# How the Problems Are Solved

- Fixed the escaping for backslash for `like` operations.
- Changed equals and not equals comparison without case matching to `=`
instead of `like`.

# Additional Changes

None

# Additional Context

- related to a support request
- requires backport to v.3 and v4.x
2025-08-21 05:25:23 +00:00
a28950661c perf(oidc): introspection endpoint query optimization (#10392)
The `/introspect` endpoint showed poor performance during v4 load
testing due to an inefficient database query in
`internal/query/introspection_client_by_id.sql`. This PR optimizes the
query structure to significantly improve performance.

## Query Optimizations

**UNION → UNION ALL**: Changed expensive `UNION` to `UNION ALL` since
`client_id` is unique across both API and OIDC config tables,
eliminating unnecessary deduplication overhead (30-50% improvement
expected).

**Simplified Keys CTE**: Optimized the keys lookup logic by using
`$2::text as client_id` instead of `identifier as client_id` with `group
by`, and added explicit `$3 = true` condition to the LEFT JOIN for
better query planning.

**Enhanced Readability**: Added consistent table aliases (c, a, p, o, k)
for better maintainability.

## Benefits

- **Zero-downtime deployment**: Uses existing database indexes, no
schema changes required
- **Secondary performance gains**: Other similar queries
(`oidc_client_by_id.sql`, `userinfo_client_by_id.sql`) will also benefit
from the optimizations
- **Minimal code changes**: Only 13 lines added, 9 lines removed in the
SQL query
- **Backward compatible**: Same result set and API behavior

The optimized query maintains the same functionality while providing
significant performance improvements for the introspection endpoint
under high concurrent load.

Fixes #10389.

<!-- START COPILOT CODING AGENT TIPS -->
---

💬 Share your feedback on Copilot coding agent for the chance to win a
$200 gift card! Click
[here](https://survey.alchemer.com/s3/8343779/Copilot-Coding-agent) to
start the survey.

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: muhlemmer <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
2025-08-20 12:37:00 +00:00
Marco A.andGitHub e8a9cd6964 fix: remove legacy events (#10464)
# Which Problems Are Solved

Some events that are now unused are clogging the event queue from time
to time.

# How the Problems Are Solved

Remove the events described in #10458

# Additional Changes

- Updated `stringer` and `enumer` in Makefile target `core_generate_all`
to resolve generated files compilation issues

# Notes
It looks like there are a lot of changes, but most of it is fixing
translation files. I suggest doing a review per-commit

# Additional Context

- Closes #10458
- Depends on https://github.com/zitadel/zitadel/pull/10513
2025-08-19 15:22:34 +02:00
a637ae5aa5 fix(api): fix for ListAppKeys() not returning app keys (#10465)
# Which Problems Are Solved

`ListAppKeys()` does not work properly, in that it does not return any
app keys.


# How the Problems Are Solved

The issue stems from a mistake SQL query not joining the
`projections.authn_keys2` table to `projections.projects4` instead of
joining to `projections.apps7`

# Additional Changes

`ListAppKeys()` returns the app key IDs in order of their creation

- Closes https://github.com/zitadel/zitadel/issues/10420
- backport to v4.x

---------

Co-authored-by: Livio Spring <[email protected]>
2025-08-15 12:51:43 +00:00
Gayathri VijayanandGitHub 0929c4d235 fix: create project with the right permission (#10485)
# Which Problems Are Solved

When a user with an `ORG_PROJECT_CREATOR` role tries to create a
project, the request fails with `No matching permissions found
(AUTH-AWfge)` error. This is because `project.write` was set as the
required permission instead of `project.create` during project creation.

# How the Problems Are Solved
By setting the right required permission (`project.create`) while
creating new projects.

# Additional Changes
N/A

# Additional Context
- Closes #10399
2025-08-15 11:35:43 +02:00
532932ef94 fix: drop default otel scope info from metrics (#10306)
# Which Problems Are Solved

Currently, the prometheus endpoint metrics contain otel specific labels
that increase the overall metric size to the point that the exemplar
implementation in the underlying prom exporter library throws an error,
see https://github.com/zitadel/zitadel/issues/10047. The MaxRuneSize for
metric refs in exemplars is 128 and many of metrics cross this because
of `otel_scope_name`.

# How the Problems Are Solved

This change drops those otel specific labels on the prometheus exporter:
`otel_scope_name` and `otel_scope_version`

Current metrics example: 
```
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_version="0.53.0",le="0"} 0
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_version="0.53.0",le="5"} 100
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",otel_scope_name="go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp",otel_scope_version="0.53.0",le="10"} 100
...
grpc_server_grpc_status_code_total{grpc_method="/zitadel.admin.v1.AdminService/ListIAMMemberRoles",otel_scope_name="",otel_scope_version="",return_code="200"} 3
grpc_server_grpc_status_code_total{grpc_method="/zitadel.admin.v1.AdminService/ListIAMMembers",otel_scope_name="",otel_scope_version="",return_code="200"} 3
grpc_server_grpc_status_code_total{grpc_method="/zitadel.admin.v1.AdminService/ListMilestones",otel_scope_name="",otel_scope_version="",return_code="200"} 1
```

New example: 
```
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",le="10"} 8
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",le="25"} 8
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",le="50"} 9
http_server_duration_milliseconds_bucket{http_method="GET",http_status_code="200",le="75"} 9
...
grpc_server_grpc_status_code_total{grpc_method="/zitadel.admin.v1.AdminService/GetSupportedLanguages",return_code="200"} 1
grpc_server_grpc_status_code_total{grpc_method="/zitadel.admin.v1.AdminService/ListMilestones",return_code="200"} 1
grpc_server_grpc_status_code_total{grpc_method="/zitadel.auth.v1.AuthService/GetMyLabelPolicy",return_code="200"} 3
```

# Additional Changes

None

# Additional Context

From my understanding, this change is fully spec compliant with
Prometheus and Otel:
*
https://opentelemetry.io/docs/specs/otel/compatibility/prometheus_and_openmetrics/#instrumentation-scope

However, these tags were originally added as optional labels to
disambiguate metrics. But I'm not sure we need to care about that right
now? My gut feeling is that exemplar support (the ability for traces to
reference metrics) would be a preferable tradeoff to this label
standard.

Co-authored-by: Silvan <[email protected]>
2025-08-14 12:44:37 +00:00
10bd747105 fix(projections): added check to make sure there cannot be 2 projections for the same table (#10439)
# Which Problems Are Solved

It should not be possible to start 2 projections with the same name.

If this happens, it can cause issues with the event store such as events
being skipped/unprocessed and can be very hard/time-consuming to
diagnose.

# How the Problems Are Solved

A check was added to make sure no 2 projections have the same table


Closes https://github.com/zitadel/zitadel/issues/10453

---------

Co-authored-by: Silvan <[email protected]>
2025-08-13 13:51:30 +00:00
Livio SpringandGitHub 4630b53313 fix(idp): make external id check case insensitive (#10460)
# Which Problems Are Solved

When searching for an existing external userID from an IdP response, the
comparison is case sensitive. This can lead to issues esp. when using
SAML, since the `NameID`'s value case could change. The existing user
would not be found and the login would try to create a new one, but fail
since the uniqueness check of IdP ID and external userID is not case
insensitive.

# How the Problems Are Solved

Search case insensitive for external useriDs.

# Additional Changes

None

# Additional Context

- closes #10457, #10387
- backport to v3.x
2025-08-13 07:44:39 +00:00
Gayathri VijayanandGitHub 45cc6e9bb1 fix: use correct the userID column name in permissions v2 check (#10467)
# Which Problems Are Solved

When `Permission Check V2` is enabled, calls to the `ListPasskeys` and
`ListAuthenticationFactors` APIs fail with the following error:
```
ERROR:  missing FROM-clause entry for table "users14"
```

# How the Problems Are Solved
By using the right UserID column
(`projections.user_auth_methods5.user_id`) in the permission clause in
the `userAuthMethod` query

# Additional Changes
N/A

# Additional Context
- Closes #10386
2025-08-12 17:17:39 +02:00
427cbe06f3 fix: query organization directly from event store (#10463)
Querying an organization by id allowed to trigger the org projection.
This could lead to performance impacts if the projection gets triggered
too often.

Instead of executing the trigger the organization by id query is now
always executed on the eventstore and reduces all event types required
of the organization requested.

---------

Co-authored-by: Livio Spring <[email protected]>
2025-08-12 09:37:08 +00:00
SilvanandGitHub 7fff529777 fix(actionsV1): disable projection trigger when querying org metadata in the action (#10462)
Disables the trigger of the org metadata projection when using `api.v1.getOrgMetadata()`.
2025-08-12 10:53:36 +02:00
1579bbc8db fix: add user info to context for set metadata in actions (#10426)
# Which Problems Are Solved

User information in the context is necessary through the addition of the
resource based API endpoints for user metadata, for the permission
check.

# How the Problems Are Solved

Add user information to the action execution to add metadata to users.

# Additional Changes

None

# Additional Context

Needs to be added to v4 releases, to provide the functionality to add
metadata through actions v1 and actions v2 functions.

Co-authored-by: Marco A. <[email protected]>
2025-08-11 16:43:52 +02:00
Livio SpringandGitHub 67efddcbc6 fix: allow disabling projections for specific instances (#10421)
# Which Problems Are Solved

The current handling of event subscriptions for actions is bad, esp. on
instances with a lot of events
(https://github.com/zitadel/zitadel/issues/9832#issuecomment-2866236414).
This led to severe problems on zitadel.cloud for such instances.

# How the Problems Are Solved

As a workaround until the handling can be improved, we introduce an
option for projections to be disabled completely for specific instances:
`SkipInstanceIDs`

# Additional Changes

None

# Additional Context

- relates to https://github.com/zitadel/zitadel/issues/9832
2025-08-08 16:42:14 +03:00
Stefan BenzandGitHub cc2ef939c5 fix: remove fields entry with instance domain remove (#10406)
# Which Problems Are Solved

Fields table entry is not removed when removing instance domain.

# How the Problems Are Solved

Remove the fields entry, instead of setting it.

# Additional Changes

None

# Additional Context

Needs to be backported to v3.x
2025-08-07 14:16:02 +00:00
6e8aa9a7d1 chore: fix flakiness in gofakeit usage with additional random string (#10385)
# Which Problems Are Solved

Flakiness in integration tests regarding gofakeit functions, which
provided the same names on 2 different occasions.

# How the Problems Are Solved

Attach a random string to the provided names, so that they are not
dependent on the gofakeit code.

# Additional Changes

None

# Additional Context

None

---------

Co-authored-by: Marco A. <[email protected]>
2025-08-07 13:27:01 +00:00
a96f4708cb fix(sessions): add an expiration date filter to list sessions api (#10384)
# Which Problems Are Solved

The deletion of expired sessions does not go through even though a
success response is returned to the user. These expired and supposedly
deleted (to the user) sessions are then returned when the `ListSessions`
API is called.

This PR fixes this issue by:
1. Allowing deletion of expired sessions
2. Providing an `expiration_date` filter in `ListSession` API to filter
sessions by expiration date

# How the Problems Are Solved

1. Remove expired session check during deletion
2. Add an `expiration_date` filter to the  `ListSession` API

# Additional Changes
N/A

# Additional Context
- Closes #10045

---------

Co-authored-by: Marco A. <[email protected]>
2025-08-07 14:58:59 +02:00
d4222d6fd6 fix: don't trigger session projection on notification handling (#10298)
# Which Problems Are Solved

There is an outstanding bug wherein a session projection can fail to
complete and an session OTP challenge is blocked because the projection
doesn't exist. Not sure why the session projection can fail to persist -
I can't find any error logs or failed events to crosscheck. However, I
can clearly see the session events persisted with user/password checks
and the OTP challenged added on the session - but no session projection
on sessions8 table.

This only seems to come up under somewhat higher loads - about 5
logins/s and only for about 1% of cases. (where a "login" is:
authRequest, createSession, getAuthCodeWithSession, tokenExchange, and
finally, otpSmsChallenge...💥).

# How the Problems Are Solved

This is only half a fix, but an important one as it can block login for
affected users. Instead of triggering and checking the session
projection on notification enqueuing, build a write model directly from
the ES.

# Additional Changes

# Additional Context

This doesn't touch the "legacy" notification handler as to limit the
blast radius of this change. But might be worth adding there too.

The test is difficult to update correctly so is somewhat incomplete. Any
suggestions for refactoring or test helpers I'm missing would be
welcome.

Co-authored-by: Silvan <[email protected]>
2025-08-04 13:33:01 +00:00
Gayathri VijayanandGitHub 00b0af4368 fix(saml): use transient mapping attribute when nameID is missing in saml response (#10353)
# Which Problems Are Solved

In the SAML responses from some IDPs (e.g. ADFS and Shibboleth), the
`<NameID>` part could be missing in `<Subject>`, and in some cases, the
`<Subject>` part might be missing as well. This causes Zitadel to fail
the SAML login with the following error message:

```
ID=SAML-EFG32 Message=Errors.Intent.ResponseInvalid
```

# How the Problems Are Solved

This is solved by adding a workaround to accept a transient mapping
attribute when the `NameID` or the `Subject` is missing in the SAML
response. This requires setting the custom transient mapping attribute
in the SAML IDP config in Zitadel, and it should be present in the SAML
response as well.

<img width="639" height="173" alt="image"
src="https://github.com/user-attachments/assets/cbb792f1-aa6c-4b16-ad31-bd126d164eae"
/>


# Additional Changes
N/A

# Additional Context
- Closes #10251
2025-07-31 15:12:26 +00:00
Stefan BenzandGitHub 4046dd31b4 feat: actions v2 api GA (#10364)
# Which Problems Are Solved

The Actions v2beta API is not yet promoted to GA.

# How the Problems Are Solved

Promote Actions v2Beta API to Actions v2 API.

# Additional Changes

None

# Additional Context

None
2025-07-31 13:09:09 +00:00