Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
430a1d7
Implement tenant activity log API
rbjornstad Jun 25, 2026
0fd0aae
Regenerate activity log code
rbjornstad Jun 25, 2026
2eddb9a
Fix service account team validation
rbjornstad Jun 25, 2026
958d382
Refine tenant activity log access
rbjornstad Jun 25, 2026
128638a
Handle legacy vulnerability activity log rows
rbjornstad Jun 25, 2026
67cc5ac
Upgrade bbolt to v1.5.0 to fix vulnerability
rbjornstad Jun 25, 2026
90b6911
Rename tenantActivityLog to activityLog
rbjornstad Jun 25, 2026
fe8d26c
Fix team facet pollution by filtering empty slugs
rbjornstad Jun 25, 2026
55436df
Remove dead activity log authorization code
rbjornstad Jun 25, 2026
9bb8fa1
Fix service account race condition and remove unused Tenant scope field
rbjornstad Jun 25, 2026
dafaa20
Remove empty data fallback from vulnerability transformer
rbjornstad Jun 26, 2026
124fcf7
Address review feedback: comment on FilterFrom/FilterTo intent, remov…
rbjornstad Jun 26, 2026
4df521e
go mod tidy
rbjornstad Jun 26, 2026
f192e30
fmt
rbjornstad Jun 26, 2026
e768a0b
Split Facets query to avoid cardinality explosion with many teams
rbjornstad Jun 26, 2026
5803435
Add created_at index for tenant-level activity log time range queries
rbjornstad Jun 26, 2026
524a41b
Remove redundant migration 0072 - created_at indexes already exist fr…
rbjornstad Jun 26, 2026
208c3bf
Fix conflicting semconv schema URLs and bump go directive to 1.26.4
rbjornstad Jun 26, 2026
364136b
Remove team facets from activity log
rbjornstad Jun 26, 2026
a19d551
Fix team.Get dataloader usage in service account create transaction
rbjornstad Jun 26, 2026
1de4ee5
Remove redundant comments in ComputeFacets function for clarity
rbjornstad Jun 26, 2026
a5cc832
Remove redundant newline in ActivityLogFacets type definition
rbjornstad Jun 26, 2026
7da22bc
Mark static service account functions for removal
rbjornstad Jun 26, 2026
09ea7aa
Remove redundant newline in ActivityLogFacets type definition
rbjornstad Jun 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/nais/api

go 1.26.3
go 1.26.4

tool (
github.com/99designs/gqlgen
Expand Down Expand Up @@ -406,7 +406,7 @@ require (
github.com/zeebo/xxh3 v1.1.0 // indirect
github.com/zitadel/logging v0.6.1 // indirect
github.com/zitadel/schema v1.3.0 // indirect
go.etcd.io/bbolt v1.4.3 // indirect
go.etcd.io/bbolt v1.5.0 // indirect
go.etcd.io/etcd/api/v3 v3.6.7 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.6.7 // indirect
go.etcd.io/etcd/client/v3 v3.6.7 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1119,8 +1119,8 @@ github.com/zitadel/zitadel-go/v3 v3.4.3 h1:Ph+5wkXmxOpykCBjiUSjbhXidbDGgkeZF2/B9
github.com/zitadel/zitadel-go/v3 v3.4.3/go.mod h1:hylnXtN3ARxTDRO7OzgQTyRyGXFQ8gAIwTC3NAniRds=
go.einride.tech/aip v0.79.0 h1:19zdPlZzlUvxOA8syAFw4LkdJdXepzyTl6gt9XEeqdU=
go.einride.tech/aip v0.79.0/go.mod h1:E8+wdTApA70odnpFzJgsGogHozC2JCIhFJBKPr8bVig=
go.etcd.io/bbolt v1.4.3 h1:dEadXpI6G79deX5prL3QRNP6JB8UxVkqo4UPnHaNXJo=
go.etcd.io/bbolt v1.4.3/go.mod h1:tKQlpPaYCVFctUIgFKFnAlvbmB3tpy1vkTnDWohtc0E=
go.etcd.io/bbolt v1.5.0 h1:S7GAl7Fxv12yohbwFfIbQCGDWbQbtDGPET4P/bD4lxU=
go.etcd.io/bbolt v1.5.0/go.mod h1:mkltfYE5aUHQxUct9N9V+Kp7aSjFqjgrhcXIS70Lrdk=
go.etcd.io/etcd/api/v3 v3.6.7 h1:7BNJ2gQmc3DNM+9cRkv7KkGQDayElg8x3X+tFDYS+E0=
go.etcd.io/etcd/api/v3 v3.6.7/go.mod h1:xJ81TLj9hxrYYEDmXTeKURMeY3qEDN24hqe+q7KhbnI=
go.etcd.io/etcd/client/pkg/v3 v3.6.7 h1:vvzgyozz46q+TyeGBuFzVuI53/yd133CHceNb/AhBVs=
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/serviceaccounts_queries.lua
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ Test.gql("Create service account with non-existent team slug", function(t)
errors = {
{
locations = NotNull(),
message = Contains("database encountered an error"),
message = Contains("The specified team was not found."),
path = {
"createServiceAccount",
},
Expand Down
152 changes: 152 additions & 0 deletions integration_tests/tenant_activitylog.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
local admin = User.new()
admin:admin(true)
local teamOne = Team.new("slug-1", "purpose", "#channel")
local teamTwo = Team.new("slug-2", "purpose", "#channel")

Test.gql("Create repository event for team one", function(t)
t.addHeader("x-user-email", admin:email())

t.query [[
mutation {
addRepositoryToTeam(input: {teamSlug: "slug-1", repositoryName: "nais/api-team-one"}) {
repository {
name
}
}
}
]]

t.check {
data = {
addRepositoryToTeam = {
repository = {
name = "nais/api-team-one",
},
},
},
}
end)

Test.gql("Create repository event for team two", function(t)
t.addHeader("x-user-email", admin:email())

t.query [[
mutation {
addRepositoryToTeam(input: {teamSlug: "slug-2", repositoryName: "nais/api-team-two"}) {
repository {
name
}
}
}
]]

t.check {
data = {
addRepositoryToTeam = {
repository = {
name = "nais/api-team-two",
},
},
},
}
end)

Test.gql("Tenant activity log returns facets and pagination metadata", function(t)
t.addHeader("x-user-email", admin:email())

t.query [[
query {
activityLog(first: 10, filter: { activityTypes: [REPOSITORY_ADDED] }) {
nodes {
resourceName
teamSlug
}
pageInfo {
totalCount
hasNextPage
}
facets {
activityTypes {
activityType
count
}
resourceTypes {
resourceType
count
}
environments {
value
count
}
}
}
}
]]

t.check {
data = {
activityLog = {
nodes = {
{
resourceName = "nais/api-team-two",
teamSlug = "slug-2",
},
{
resourceName = "nais/api-team-one",
teamSlug = "slug-1",
},
},
pageInfo = {
totalCount = 2,
hasNextPage = false,
},
facets = {
activityTypes = {
{
activityType = "REPOSITORY_ADDED",
count = 2,
},
},
resourceTypes = {
{
resourceType = "REPOSITORY",
count = 2,
},
},
environments = {},
},
},
},
}
end)

Test.gql("Tenant activity log supports time filtering", function(t)
t.addHeader("x-user-email", admin:email())

t.query [[
query {
activityLog(
first: 10
filter: { activityTypes: [REPOSITORY_ADDED], from: "9999-01-01T00:00:00Z" }
) {
nodes {
resourceName
}
pageInfo {
totalCount
}
}
}
]]

t.check {
data = {
activityLog = {
nodes = {},
pageInfo = {
totalCount = 0,
},
},
},
}
end)
Loading
Loading