Commit Graph
25 Commits
Author SHA1 Message Date
500821ce0c fix: prevent possible nil pointer panics (#11728)
# 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]>
2026-03-16 14:30:17 +00:00
SilvanandGitHub 90faf440f4 refactor: relational identity provider table and projection (#11739) 2026-03-05 09:43:14 +00:00
Marco A.andGitHub 3ebeb61b80 feat: test event reduction to relational tables (#11718)
# Which Problems Are Solved

This PR provides an example for testing DB reduction to relational
tables without exploiting integration tests.

# How the Problems Are Solved

- Set up a disposable embedded Postgres DB used to store the results of
the calls to the reducers and verify such results
- Add utility method to return transactions from the existing DB pool.
These transactions can be used by the single test cases to insert and
read data from DB
- Add a test to verify that the handler contains the expected reducers
(checking also that they are on the right aggregate type)
- Add tests to verify the single reduce functions. A parent test creates
the required objects to satisfy the foreign key constraints.

# Additional Changes

  - Typo fixed in `postgres.DecodeConfig()`
  - Discard unneeded `projectionName` parameter for `Executor` function
 
# Additional Context

- Closes #11430
2026-03-02 16:44:51 +00:00
5df8a97f9d feat(repository): implement user repository (#10967)
## Summary

This PR introduces the relational user repository for backend v3,
including schema, repository APIs, reducers/projections, and tests for
both human and machine users.

## What changed

* Added user-focused relational migrations (users, verifications,
metadata, PATs, machine keys, passkeys, identity provider links) and
related FK wiring.
* Implemented/expanded repository domain contracts and storage
implementations for human and machine user flows.
* Added support for machine secret handling and aligned access token
type modeling.
* Extended user domain models (verifications, password/email/phone/TOTP
state, passkeys, metadata, invite handling, identity provider links).
* Updated projection/reduction coverage and integration tests for key
user lifecycle events.
* Regenerated and updated mocks/enums plus supporting database
change/column utilities.

## Notes for reviewers

* This PR is large because it establishes the foundational relational
user storage layer and related test scaffolding. Sorry for that.

## Closes

Closes #10218
Closes #10224
Closes #10225
Closes #10209
Closes #10802

---------

Co-authored-by: Iraq Jaber <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
2026-02-23 16:03:47 +01:00
Gayathri VijayanandGitHub 1494f91f80 fix: session termination after user deletion/deactivation (#11644)
# Which Problems Are Solved

After a user is deactivated, their sessions are still valid. When the
user is redirected to login page, they're stuck in a loop on a blank
page on the `users/me` endpoint as the user's session is still valid.

# How the Problems Are Solved

By terminating a deactivated user's session. This is done by:
- Adding a new reducer in session projection to delete sessions for
`UserDeactivatedEvent`, `UserLockedEvent` and `UserRemovedEvent` events
- Adding a new reducer in the relation session projection to delete
sessions based on `UserDeactivatedEvent`, `UserLockedEvent` events

# Additional Changes
N/A

# Additional Context
- Closes https://github.com/zitadel/zitadel/issues/10307
- todo: add integration test cases for relational session reducers based
on user deactivated, locked, deleted events
2026-02-20 10:21:01 +00:00
5a2181bcec chore: rename IAM to instance (#11351)
# Which Problems Are Solved

In many cases IAM was used where instance was meant. 

# How the Problems Are Solved

- Rename wrong usage of IAM to instance all over the code base.
- Add an agents.md which explains the terms used in Zitadel's
architecture.

# Additional Context

- closes #11280

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: muhlemmer <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
2026-02-10 20:25:39 +01:00
4936bdf2c9 feat(rt): IDP Intents Relational Table (#11374)
# Which Problems Are Solved

In the context of moving our datastore to relational tables, Identity
Provider Intents have no definition of a relational table nor any DB API
that can be used to store the IDP intents as relational objects.

# How the Problems Are Solved

The PR follows the guidelines left in #11190

- A table `zitadel.identity_provider_intents` is created: it defines its
relational constraints (foreign keys) with the other tables, as well as
an ENUM to represent the state of the intent.
- An IDP Intent repository has been created, which offers CRUD
operations implemented as `Create`, `Get`, `Update` and `Delete` methods
for the IDP intent.
- The repository also defines all columns and conditions useful for
performing DB operations on the IDP intents.
- DB mocks have been added as well to ease testing on the `domain`
package.
- Reduction functions have been implemented for the existing IDP events
so to keep the relational table in sync with the event store.

# Additional Changes

To allow testing LDAP intent flow, the `Session.FetchUser()` method has
been extracted to a separate file. A corresponding mock has been created
as well in `fetch_user_mock.go`. The files are mutually excluded and
added at build time through go build tags: the mock is added when the
`integration` tag is specified, while the real implementation is added
when the same tag IS NOT added to the build tags.

# Additional Context

- Closes #11190

---------

Co-authored-by: Livio Spring <[email protected]>
Co-authored-by: Silvan <[email protected]>
2026-02-05 03:44:07 +00:00
11dbb1b277 feat(logging): add streams (#11435)
# Which Problems Are Solved

Streams allow differentiating logs produced by different components of
Zitadel.

# How the Problems Are Solved

The `backend/v3/instrumentation/logging` package now exposes convenience
function for setting and getting a logger from the context. As well as
high-level functions to emit log records at various levels. When
constructing a new logger a "stream" needs to be specified:

- **runtime**: General runtime logs, such as startup and shutdown
messages. Default for logs that do not belong to the other categories.
- **request**: Logs for incoming API and HTTP requests.
- **event_handler**: Logs for event handling in projections.
- **queue**: Logs for the job queue processing.
- **event_pusher**: Logs for event pushing to the database. Disabled by
default, contains sensitive information.

Each line from the returned logger contains a `stream` field as well as
a `version` field with the current Zitadel version.

## Runtime config

Streams can be enabled by passing an array of stream names in the
runtime config. Because some log streams may contain sensitive data
(especially events), it is now also possible to mask values by their
key.

# Additional Changes

- Wrap `slogctx` in the `logging` package. (Except API error converter
packages, because of import cycle)
- Add some docs to `logging` package so other devs understand how to add
logging to Zitadel
- Add `logging.OnError` and `logging.WithError` helper functions with
`Panic()` and `Fatal()` methods, to preserve current calls in the `cmd`
packages.
- Add instance context extractor.
- Only output request details in the request info log. Request ID
remains propagated through context.
- Moved middleware functionality into protocol specific packages. 
- Removed setting of URI to context in metric middleware. There were ony
setters and no getters. (Unused value)
- Reuse a single statusWriter in the middleware package for middlewares
that need to know the response status.

# Additional Context

- Closes #11333
- Closes #11331 
- Partly #11330

---------

Co-authored-by: Silvan <[email protected]>
2026-02-04 11:51:43 +01:00
3fc0ef2506 feat: added xoauth for smtp (#11239)
# Which Problems Are Solved

- Some mail providers (e.g.: MS Exchange) have deprecated plain auth

# How the Problems Are Solved

Adds XOauth2 auth option to SMPT
- SMTP config now can contain XOAuth2 auth config
- Proto files are updated to have a oneof for configuration selection.
Old fields for configuring plain auth are still available not to create
a breaking change. These can be removed in the future.
- Columns are added to the database to persist the config

# Additional Changes

none

# Additional Context

Replace this example with links to related issues, discussions, discord
threads, or other sources with more context.
Use the Closing #issue syntax for issues that are resolved with this PR.
- Closes #8042

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
2026-01-27 15:11:56 +01:00
Livio SpringandGitHub 4e6f68c511 feat(relational): implement session repository (#11109)
# Which Problems Are Solved

As part of going to a relation storage model, we need to implement the
repository for handling sessions and their events.

# How the Problems Are Solved

- Adds a migration step to create the necessary tables and types in the
database.
- Adds the repository implementation for sessions.
- Implements a projection handler for session events to handle the
events written by the old command handlers.
- Updates the `Session` type and `SessionRepository` interface:
  - added `CreatorID`
  - Adjusted `Delete` method to return amount of affected columns
  - Removed sub-repository clumns from the main interface
- Added `CreatorIDCondition`, `ExpirationCondition`, `ExistsFactor` and
`ExistsMetadata`
  - Removed `SetUserAgent`
- Methods of `SessionFactor` and `SessionChallenge` have been made
public
- fixed enumer on `SessionFactorType`
- Adds a `JSON` type to the repository package to easy can JSON columns,
resp. jsonb object inside a property of a `JSONArray` object.
- Adds a `NoChange` interface, which can be implemented to signal that a
`Change` interface implementation is not writing any changes to the
statement builder, e.g. `CTEChange`

# Additional Changes

- Fixes the operators enums. `TextOperations` had wrong comments and
`NumberOperations` additionally also had from comparisons.
- Fixes downgrade of migration step 008.

# Additional Context

- closes https://github.com/zitadel/zitadel/issues/10212
2026-01-06 08:08:11 +01:00
Gayathri VijayanandGitHub af8deb1145 fix(authorizations): flaky integration tests (#11215)
# Which Problems Are Solved

Flaky integration tests related to authorizations RT.

# How the Problems Are Solved

By setting the `created_at` and `updated_at` timestamps based on event
timestamps while creating an authorization.

# Additional Changes
N/A
# Additional Context

https://cloud.nx.app/runs/ICj84SxEf0/task/%40zitadel%2Fapi%3Atest-integration
2025-12-22 09:41:01 +01:00
Gayathri VijayanandGitHub 7c01deb8ed fix(authorizations): comment out timestamp assertions (#11214)
# Which Problems Are Solved

Comment out timestamp assertions to temporarily unblock CI pipeline

# How the Problems Are Solved

Comment out timestamp assertions to temporarily unblock CI pipeline

# Additional Changes

N/A

# Additional Context
2025-12-19 15:37:44 +01:00
8472c7683d feat(rt): authorizations (#11066)
# Which Problems Are Solved

This PR implements relational table and repository interface for the
authorizations feature as described in
https://github.com/zitadel/zitadel/issues/10767

# How the Problems Are Solved

By
* adding new `zitadel.authorizations` and `zitadel.authorization_roles`
tables
* implementing the `AuthorizationRepository` interface to create,
update, query, and delete user authorizations and roles
* implementing `authorization_relational.go` projection to update
`zitadel.authorizations` and `zitadel.authorization_roles` tables based
on events

# Additional Changes
N/A

# Additional Context
- Closes #10767

---------

Co-authored-by: Livio Spring <[email protected]>
2025-12-19 07:03:27 +01:00
3903355d18 feat(settings): add secret generator type to settings RT implementation (#11152)
# Which Problems Are Solved

The `SecretGenerators` setting is missing among the instance settings in
the new relational model.

# How the Problems Are Solved

This PR adds:
* `SettingTypeSecretGenerator` type to the settings model
* `SecretGeneratorSettingsRepository` and
`secretGeneratorSettingsJSONChanges` interfaces to set, retrieve, and
delete `secret_generator` settings, and corresponding unit tests.
* projection reducers to reduce the following events:
  * `SecretGeneratorAddedEvent`
  * `SecretGeneratorChangedEvent`
  * `SecretGeneratorRemovedEvent`
* integration tests to test that the events get reduced correctly 

# Additional Changes
N/A

# Additional Context
- Part of https://github.com/zitadel/zitadel/issues/10207

---------

Co-authored-by: Copilot <[email protected]>
Co-authored-by: Marco A. <[email protected]>
2025-12-11 12:33:19 +01:00
b4732579cb fix(RT): correct restricting null columns (#11123)
# Which Problems Are Solved

`IS NULL` and `IS NOT NULL` conditions were incorrectly marked as
restricting columns,
and currently fails unit tests. The restricting columns are mostly used
to ensure single row selection during DELETE and UPDATE . When a `IS NOT
NULL` condition is passed, the filter may (unintentionally) apply to all
rows, while still allowing the query to execute.

Settings and other repositories (still to be done) have unified tables
for instance-level settings and organization-level settings. In those
cases the organization ID may be null or have a value. The unique
condition is a compound of multiple columns, in which case `IS NULL` is
valid as part of the other restricting columns.

# How the Problems Are Solved

In order to prevent unsafe usage of null related filters and not break
settings:

- null conditions are no longer considered restricting columns
- A function to force the restricting column state on a condition is
provided
- The settings unique condition function forces restricting column state
on the returned condition.

# Additional Changes

- add `backend/v3` to the NX build.

# Additional Context

- [pipeline
failures](https://github.com/zitadel/zitadel/actions/runs/19852295780/job/56881654340?pr=11115#step:13:3197)

---------

Co-authored-by: Elio Bischof <[email protected]>
2025-12-03 16:15:49 +00:00
911967c865 feat(settings_relational): adding settings table for relational db (#10769)
# Which Problems Are Solved

As part of https://github.com/zitadel/zitadel/issues/9599 to push to
move to a relational db table model, this is the migration of the
settings

# Additional Changes

I had to add 2 non source code files
`backend/v3/storage/database/events_testing/font.otf` and
`backend/v3/storage/database/events_testing/picture.png`, these are used
as part of the reduce tests, hence why they're sourced inside
`backend/v3/storage/database/events_testing/settings_instance_test.go`

- Closes https://github.com/zitadel/zitadel/issues/10207

---------

Co-authored-by: adlerhurst <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Stefan Benz <[email protected]>
2025-12-02 08:16:21 +01:00
9274e008fe feat(rt): project grants (#10951)
This pull request introduces a new feature that allows adding, updating,
and querying project grants The changes are primarily in the backend and
include new database tables, repositories, and domain logic to support
project grants.

## Changes

* New `project_grants` table: A new table `zitadel.project_grants` is
introduced to store project grants It includes columns for
`instance_id`, `id`, `state`, `project_id`, `granted_org_id` and
`granting_org_id`.
* New `ProjectGrantRepository`: A new repository
`ProjectGrantRepository` is created to handle all database operations
for project grants. It provides methods to `Get`, `List`, `Create`,
`Update`, and `Delete`.
* New `project_grant_roles` table: A new table
`zitadel.project_grant_roles` is introduced to store project grant roles
It includes columns for `instance_id`, `grant_id`, `key`, `project_id`
and `project_org_id`.
* New `ProjectGrantRoleRepository`: A new repository
`ProjectGrantRoleRepository` is created to handle all database
operations for project grant roles. It provides methods to `Get`,
`List`, `Add`, and `Delete`.
* New `project_grant_relational_projection`: A new projection
`project_grant_relational_projection` is added to update the
`zitadel.project_grants` and `zitadel.project_grant_roles` tables based
on events. It handles all project grant events.
* Updated `ProjectRepository`: The `ProjectRepository` is updated to
list granted projects.

# Additional Context

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

---------

Co-authored-by: Stefan Benz <[email protected]>
Co-authored-by: Marco A. <[email protected]>
Co-authored-by: Silvan <[email protected]>
2025-11-14 11:04:16 +00:00
c4221a9c0f refactor: invoker implementations and clean up code (#10962)
This pull request refactors the command execution and transaction
handling logic within the `domain` package. The primary goal is to
simplify the invoker chain, clarify transaction management, and improve
the overall structure for better maintainability and readability.

### Key Changes:

- **Simplified Invoker Chain**: The previous chain of invokers has been
refactored. A new `transactionInvoker` is introduced to explicitly
manage database transactions for commands that require them. This
responsibility is no longer spread across different parts of the
invocation flow.
- **`Transactional` Interface**: A new `Transactional` interface has
been introduced. Commands that need to run within a database transaction
now implement this interface. This provides a clear and explicit
contract for transactional operations.
- **Consolidated Transaction Logic**: The logic for starting,
committing, and rolling back transactions is now centralized within the
`transactionInvoker` and the `eventStoreInvoker`. The `EnsureTx` method
on `InvokeOpts` has been removed, and transaction handling is now
managed automatically by the invocation framework.
- **Improved Event Handling**: The `eventStoreInvoker` and its
`eventCollector` have been rewritten to be more robust and to correctly
handle nested and batched commands, ensuring that all events are
collected and published within the same transaction.
- **Code Cleanup**: A significant amount of now-unused code, including
the old `invoker_test.go`, has been removed. Various comments and
variable declarations have also been cleaned up.
- **Updated Command Implementations**: All commands in the `domain`
package (e.g., `ActivateOrgCommand`, `DeactivateOrgCommand`,
`DeleteOrgCommand`, `UpdateOrgCommand`) have been updated to use the new
`Transactional` interface where appropriate, removing manual transaction
management.
- **Enhanced Testing**: Tests have been added and updated to cover the
new transaction and event handling logic, ensuring the refactoring is
sound.
- **Use `PrimaryKeyCondition`**: Use the
`repository.PrimaryKeyCondition(...)` method instead of using
`database.And(...)` where possible.

These changes lead to a cleaner, more decoupled architecture for command
handling in ZITADEL.

---------

Co-authored-by: Marco A. <[email protected]>
2025-10-27 14:04:06 +00:00
SilvanandGitHub 6686c3b16b feat(relational): org metadata (#10761)
This pull request introduces a new feature that allows adding, updating,
and querying metadata for organizations. The changes are primarily in
the backend and include new database tables, repositories, and domain
logic to support organization metadata.

## Changes

* New `org_metadata` table: A new table `zitadel.org_metadata` is
introduced to store metadata for organizations. It includes columns for
`instance_id`, `org_id`, `key`, and `value`. The `value` is stored as a
`BYTEA` type to allow for flexible data storage.
* New `OrganizationMetadataRepository`: A new repository
`OrganizationMetadataRepository` is created to handle all database
operations for organization metadata. It provides methods to `Get`,
`List`, `Set`, and `Remove` metadata.
* New `org_metadata_relational_projection`: A new projection
`org_metadata_relational_projection` is added to update the
`zitadel.org_metadata` table based on events. It handles `MetadataSet`,
`MetadataRemoved`, and `MetadataRemovedAll` events.
* Updated `OrganizationRepository`: The `OrganizationRepository` is
updated to support loading organization metadata. A new method
`LoadMetadata` is added to enable joining the `org_metadata` table when
querying for organizations.
* Updated Organization domain: The Organization domain model is updated
to include a new field `Metadata` of type `[]*OrganizationMetadata`.

## Additional Info

* Extensible Design: The new metadata feature is designed to be
extensible, allowing for future enhancements such as indexing on
specific JSON fields within the `value` column.
* closes https://github.com/zitadel/zitadel/issues/10206
* closes https://github.com/zitadel/zitadel/issues/10214
2025-10-14 10:15:16 +01:00
f69a6ed4f3 chore: rehaul DevX (#10571)
# Which Problems Are Solved

Replaces Turbo by Nx and lays the foundation for the next CI
improvements. It enables using Nx Cloud to speed the up the pipelines
that affect any node package.
It streamlines the dev experience for frontend and backend developers by
providing the following commands:

| Task | Command | Notes |
|------|---------|--------|
| **Production** | `nx run PROJECT:prod` | Production server |
| **Develop** | `nx run PROJECT:dev` | Hot reloading development server
|
| **Test** | `nx run PROJECT:test` | Run all tests |
| **Lint** | `nx run PROJECT:lint` | Check code style |
| **Lint Fix** | `nx run PROJECT:lint-fix` | Auto-fix style issues |

The following values can be used for PROJECT:

- @zitadel/zitadel (root commands)
- @zitadel/api,
- @zitadel/login,
- @zitadel/console,
- @zitadel/docs,
- @zitadel/client
- @zitadel/proto

The project names and folders are streamlined:

| Old Folder | New Folder |
| --- | --- |
| ./e2e | ./tests/functional-ui |
| ./load-test | ./benchmark |
| ./build/zitadel | ./apps/api |
| ./console | ./apps/console (postponed so the PR is reviewable) |  

Also, all references to the TypeScript repo are removed so we can
archive it.

# How the Problems Are Solved

- Ran `npx nx@latest init`
- Replaced all turbo.json by project.json and fixed the target configs
- Removed Turbo dependency
- All JavaScript related code affected by a PRs changes is
quality-checked using the `nx affected` command
- We move PR checks that are runnable using Nx into the `check`
workflow. For workflows where we don't use Nx, yet, we restore
previously built dependency artifacts from Nx.
- We only use a single and easy to understand dev container
- The CONTRIBUTING.md is streamlined
- The setup with a generated client pat is orchestrated with Nx
- Everything related to the TypeScript repo is updated or removed. A
**Deploy with Vercel** button is added to the docs and the
CONTRIBUTING.md.

# Additional Changes

- NPM package names have a consistent pattern.
- Docker bake is removed. The login container is built and released like
the core container.
- The integration tests build the login container before running, so
they don't rely on the login container action anymore. This fixes
consistently failing checks on PRs from forks.
- The docs build in GitHub actions is removed, as we already build on
Vercel.

# Additional Context

- Internal discussion:
https://zitadel.slack.com/archives/C087ADF8LRX/p1756277884928169
- Workflow dispatch test:
https://github.com/zitadel/zitadel/actions/runs/17760122959

---------

Co-authored-by: Florian Forster <[email protected]>
Co-authored-by: Tim Möhlmann <[email protected]>
Co-authored-by: Copilot <[email protected]>
2025-10-08 10:27:02 +02:00
Tim MöhlmannandGitHub a45908b364 feat(rt): project repository (#10789)
# Which Problems Are Solved

Add projects to the relational tables

# How the Problems Are Solved

- Define table migrations
- Define and implement Project and Project Role repositories.
- Provide projection handlers to populate the relational tables.

# Additional Changes

- Statement Builder now has a constructor which allows setting of a base
query with arguments.
- Certain operations, like Get, Update and Delete require the Primary
Key to be set as conditions. However, this requires knowledge of the
implementation and table definition. This PR proposes an additional
condition for repositories: `PrimaryKeyCondition`. This gives clarity on
the required IDs for these operations.
- Added couple of helpers to the repository package, to allow more DRY
code.
- getOne / getMany: generic functions for query execution and scanning.
- checkRestrictingColumns, checkPkCondition: simplify condition
checking, instead of using ladders of conditionals.
- Added a couple of helpers to the repository test package:
  - Transaction, savepoint and rollback helpers.
- Create instance and organization helpers for objects that depend on
them (like projects).

# Additional Context

- after https://github.com/zitadel/zitadel/pull/10809
- closes #10765
2025-10-01 09:47:04 +00:00
IraqandGitHub 08f41e034e feat(idp_table_relational): adding inital idp tables for relational repository (#10334) 2025-09-24 13:19:09 +00:00
SilvanandGitHub cccfc816f6 refactor: database interaction and error handling (#10762)
This pull request introduces a significant refactoring of the database
interaction layer, focusing on improving explicitness, transactional
control, and error handling. The core change is the removal of the
stateful `QueryExecutor` from repository instances. Instead, it is now
passed as an argument to each method that interacts with the database.

This change makes transaction management more explicit and flexible, as
the same repository instance can be used with a database pool or a
specific transaction without needing to be re-instantiated.

### Key Changes

- **Explicit `QueryExecutor` Passing:**
- All repository methods (`Get`, `List`, `Create`, `Update`, `Delete`,
etc.) in `InstanceRepository`, `OrganizationRepository`,
`UserRepository`, and their sub-repositories now require a
`database.QueryExecutor` (e.g., a `*pgxpool.Pool` or `pgx.Tx`) as the
first argument.
- Repository constructors no longer accept a `QueryExecutor`. For
example, `repository.InstanceRepository(pool)` is now
`repository.InstanceRepository()`.

- **Enhanced Error Handling:**
- A new `database.MissingConditionError` is introduced to enforce
required query conditions, such as ensuring an `instance_id` is always
present in `UPDATE` and `DELETE` operations.
- The database error wrapper in the `postgres` package now correctly
identifies and wraps `pgx.ErrTooManyRows` and similar errors from the
`scany` library into a `database.MultipleRowsFoundError`.

- **Improved Database Conditions:**
- The `database.Condition` interface now includes a
`ContainsColumn(Column) bool` method. This allows for runtime checks to
ensure that critical filters (like `instance_id`) are included in a
query, preventing accidental cross-tenant data modification.
- A new `database.Exists()` condition has been added to support `EXISTS`
subqueries, enabling more complex filtering logic, such as finding an
organization that has a specific domain.

- **Repository and Interface Refactoring:**
- The method for loading related entities (e.g., domains for an
organization) has been changed from a boolean flag (`Domains(true)`) to
a more explicit, chainable method (`LoadDomains()`). This returns a new
repository instance configured to load the sub-resource, promoting
immutability.
- The custom `OrgIdentifierCondition` has been removed in favor of using
the standard `database.Condition` interface, simplifying the API.

- **Code Cleanup and Test Updates:**
  - Unnecessary struct embeddings and metadata have been removed.
- All integration and repository tests have been updated to reflect the
new method signatures, passing the database pool or transaction object
explicitly.
- New tests have been added to cover the new `ExistsDomain`
functionality and other enhancements.

These changes make the data access layer more robust, predictable, and
easier to work with, especially in the context of database transactions.
2025-09-24 10:12:31 +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