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]>
This commit is contained in:
Silvan
2026-02-23 16:03:47 +01:00
committed by GitHub
co-authored by Iraq Jaber Copilot Marco A. Tim Möhlmann
parent 40c7b38ca1
commit 5df8a97f9d
73 changed files with 15914 additions and 1661 deletions
+16 -7
View File
@@ -42,23 +42,32 @@ func TestChangeWrite(t *testing.T) {
args: []any{42},
},
},
{
name: "change to NULL",
change: NewChangeToNull(NewColumn("table", "column")),
want: want{
stmt: "column = NULL",
args: nil,
},
},
{
name: "multiple changes",
change: NewChanges(
NewChange(NewColumn("table", "column1"), "value1"),
NewChangePtr[int](NewColumn("table", "column2"), nil),
NewChange(NewColumn("table", "column3"), 123),
NewChangeToNull(NewColumn("table", "column4")),
),
want: want{
stmt: "column1 = $1, column2 = NULL, column3 = $2",
stmt: "column1 = $1, column2 = NULL, column3 = $2, column4 = NULL",
args: []any{"value1", 123},
},
},
{
name: "increment change",
change: NewIncrementColumnChange(NewColumn("table", "counter")),
change: NewIncrementColumnChange(NewColumn("table", "counter"), NewColumn("table", "counter")),
want: want{
stmt: "counter = counter + 1",
stmt: "counter = table.counter + 1",
},
},
} {
@@ -111,11 +120,11 @@ func TestChangeToStatement(t *testing.T) {
name: "change to statement with existing builder args",
prefillBuilder: func(builder *StatementBuilder) {
builder.WriteString("UPDATE table SET ")
NewChanges(
assert.NoError(t, NewChanges(
NewChange(NewColumn("table", "field1"), "asdf"),
NewChangeToNull(NewColumn("table", "field2")),
NewChangeToColumn(NewColumn("table", "field3"), NewColumn("table", "field4")),
).Write(builder)
).Write(builder))
builder.WriteString(", ")
},
change: NewChangeToStatement(NewColumn("table", "column"), func(builder *StatementBuilder) {
@@ -135,7 +144,7 @@ func TestChangeToStatement(t *testing.T) {
if test.prefillBuilder != nil {
test.prefillBuilder(&builder)
}
test.change.Write(&builder)
assert.NoError(t, test.change.Write(&builder))
assert.Equal(t, test.want.stmt, builder.String())
assert.Equal(t, builder.Args(), test.want.args)
})
@@ -250,7 +259,7 @@ func TestCTEChange(t *testing.T) {
if test.afterCTE != nil {
test.afterCTE(&builder)
}
test.change.Write(&builder)
assert.NoError(t, test.change.Write(&builder))
assert.Equal(t, test.want.stmt, builder.String())
assert.Equal(t, builder.Args(), test.want.args)