Add active status field to access entries

Track whether an account is active (enabled) or disabled at the
source system. The field is nullable so existing entries without
this data remain valid.

- DB migration adds active BOOLEAN column to access_entries
- Coredata read/write/upsert/filter wiring for the new column
- Review engine propagates Active from source accounts
- GraphQL schema exposes active on AccessEntry and AccessEntryFilter
- MCP spec, types, and resolvers expose active and fix missing
  account_type filter that was wired in GraphQL but not MCP
- CLI list command adds --active filter flag and ACTIVE output column
- Console campaign detail table shows Active/Disabled status badge
- E2e and unit tests updated to cover the new field

Signed-off-by: Bryan Frimin <bryan@probo.com>
This commit is contained in:
Bryan Frimin
2026-06-11 08:40:49 +02:00
parent 95a12d338b
commit c913e97c35
13 changed files with 171 additions and 3 deletions

View File

@@ -162,6 +162,7 @@ export const campaignDetailPageQuery = graphql`
fullName fullName
role role
isAdmin isAdmin
active
mfaStatus mfaStatus
accountType accountType
lastLogin lastLogin
@@ -670,6 +671,7 @@ function ScopeSourceCard({ source, isPendingActions }: { source: ScopeSource; is
<Th>{__("Email")}</Th> <Th>{__("Email")}</Th>
<Th>{__("Role")}</Th> <Th>{__("Role")}</Th>
<Th>{__("Admin")}</Th> <Th>{__("Admin")}</Th>
<Th>{__("Status")}</Th>
<Th>{__("MFA")}</Th> <Th>{__("MFA")}</Th>
<Th>{__("Last login")}</Th> <Th>{__("Last login")}</Th>
<Th>{__("Flag")}</Th> <Th>{__("Flag")}</Th>
@@ -698,6 +700,15 @@ function ScopeSourceCard({ source, isPendingActions }: { source: ScopeSource; is
<Td>{edge.node.email || <NotAvailable />}</Td> <Td>{edge.node.email || <NotAvailable />}</Td>
<Td>{edge.node.role || <NotAvailable />}</Td> <Td>{edge.node.role || <NotAvailable />}</Td>
<Td>{edge.node.isAdmin ? __("Yes") : __("No")}</Td> <Td>{edge.node.isAdmin ? __("Yes") : __("No")}</Td>
<Td>
{edge.node.active == null
? <NotAvailable />
: (
<Badge variant={edge.node.active ? "success" : "danger"}>
{edge.node.active ? __("Active") : __("Disabled")}
</Badge>
)}
</Td>
<Td> <Td>
{edge.node.mfaStatus === "UNKNOWN" {edge.node.mfaStatus === "UNKNOWN"
? <NotAvailable /> ? <NotAvailable />

View File

@@ -24,7 +24,7 @@ import (
"go.probo.inc/probo/e2e/internal/testutil" "go.probo.inc/probo/e2e/internal/testutil"
) )
const testCsvData = "email,full_name,role,job_title,is_admin,mfa_status,auth_method,last_login,account_created_at,external_id\njane@example.com,Jane Smith,admin,CTO,true,ENABLED,SSO,2026-01-15T00:00:00Z,2024-06-01T00:00:00Z,ext-jane" const testCsvData = "email,full_name,role,job_title,is_admin,active,mfa_status,auth_method,last_login,account_created_at,external_id\njane@example.com,Jane Smith,admin,CTO,true,true,ENABLED,SSO,2026-01-15T00:00:00Z,2024-06-01T00:00:00Z,ext-jane"
func TestAccessSource_Create(t *testing.T) { func TestAccessSource_Create(t *testing.T) {
t.Parallel() t.Parallel()
@@ -1073,6 +1073,7 @@ func TestAccessReviewCampaign_FullLifecycle(t *testing.T) {
id id
email email
fullName fullName
active
decision decision
} }
} }
@@ -1100,6 +1101,7 @@ func TestAccessReviewCampaign_FullLifecycle(t *testing.T) {
ID string `json:"id"` ID string `json:"id"`
Email string `json:"email"` Email string `json:"email"`
FullName string `json:"fullName"` FullName string `json:"fullName"`
Active *bool `json:"active"`
Decision string `json:"decision"` Decision string `json:"decision"`
} `json:"node"` } `json:"node"`
} `json:"edges"` } `json:"edges"`
@@ -1133,6 +1135,10 @@ func TestAccessReviewCampaign_FullLifecycle(t *testing.T) {
// All entries should be PENDING // All entries should be PENDING
for _, edge := range campaignResult.Node.Entries.Edges { for _, edge := range campaignResult.Node.Entries.Edges {
assert.Equal(t, "PENDING", edge.Node.Decision) assert.Equal(t, "PENDING", edge.Node.Decision)
if edge.Node.Email == "jane@example.com" {
require.NotNil(t, edge.Node.Active)
assert.True(t, *edge.Node.Active)
}
} }
// Step 5: Record decisions on all entries // Step 5: Record decisions on all entries

View File

@@ -161,6 +161,7 @@ func (e *ReviewEngine) FetchSource(
MFAStatus: account.MFAStatus, MFAStatus: account.MFAStatus,
AuthMethod: account.AuthMethod, AuthMethod: account.AuthMethod,
AccountType: account.AccountType, AccountType: account.AccountType,
Active: account.Active,
LastLogin: account.LastLogin, LastLogin: account.LastLogin,
AccountCreatedAt: account.CreatedAt, AccountCreatedAt: account.CreatedAt,
ExternalID: account.ExternalID, ExternalID: account.ExternalID,

View File

@@ -52,6 +52,7 @@ query(
role role
jobTitle jobTitle
isAdmin isAdmin
active
mfaStatus mfaStatus
authMethod authMethod
accountType accountType
@@ -86,6 +87,7 @@ type entryNode struct {
Role string `json:"role"` Role string `json:"role"`
JobTitle string `json:"jobTitle"` JobTitle string `json:"jobTitle"`
IsAdmin bool `json:"isAdmin"` IsAdmin bool `json:"isAdmin"`
Active *bool `json:"active"`
MfaStatus string `json:"mfaStatus"` MfaStatus string `json:"mfaStatus"`
AuthMethod string `json:"authMethod"` AuthMethod string `json:"authMethod"`
AccountType string `json:"accountType"` AccountType string `json:"accountType"`
@@ -113,6 +115,7 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
flagFlag string flagFlag string
flagIncTag string flagIncTag string
flagIsAdmin *bool flagIsAdmin *bool
flagActive *bool
flagAuthMethod string flagAuthMethod string
flagAccountType string flagAccountType string
flagOutput *string flagOutput *string
@@ -226,6 +229,10 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
filter["isAdmin"] = *flagIsAdmin filter["isAdmin"] = *flagIsAdmin
} }
if cmd.Flags().Changed("active") {
filter["active"] = *flagActive
}
if flagAuthMethod != "" { if flagAuthMethod != "" {
if err := cmdutil.ValidateEnum( if err := cmdutil.ValidateEnum(
"auth-method", "auth-method",
@@ -305,6 +312,15 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
admin = "yes" admin = "yes"
} }
active := "unknown"
if e.Active != nil {
if *e.Active {
active = "active"
} else {
active = "disabled"
}
}
rows = append(rows, []string{ rows = append(rows, []string{
e.ID, e.ID,
e.Email, e.Email,
@@ -313,10 +329,11 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
e.Decision, e.Decision,
strings.Join(e.Flags, ","), strings.Join(e.Flags, ","),
admin, admin,
active,
}) })
} }
t := cmdutil.NewTable("ID", "EMAIL", "NAME", "SOURCE", "DECISION", "FLAGS", "ADMIN").Rows(rows...) t := cmdutil.NewTable("ID", "EMAIL", "NAME", "SOURCE", "DECISION", "FLAGS", "ADMIN", "ACTIVE").Rows(rows...)
_, _ = fmt.Fprintln(f.IOStreams.Out, t) _, _ = fmt.Fprintln(f.IOStreams.Out, t)
@@ -341,6 +358,7 @@ func NewCmdList(f *cmdutil.Factory) *cobra.Command {
cmd.Flags().StringVar(&flagFlag, "flag", "", "Filter by flag (NONE, ORPHANED, INACTIVE, EXCESSIVE, ROLE_MISMATCH, NEW)") cmd.Flags().StringVar(&flagFlag, "flag", "", "Filter by flag (NONE, ORPHANED, INACTIVE, EXCESSIVE, ROLE_MISMATCH, NEW)")
cmd.Flags().StringVar(&flagIncTag, "incremental-tag", "", "Filter by incremental tag (NEW, REMOVED, UNCHANGED)") cmd.Flags().StringVar(&flagIncTag, "incremental-tag", "", "Filter by incremental tag (NEW, REMOVED, UNCHANGED)")
flagIsAdmin = cmd.Flags().Bool("is-admin", false, "Filter by admin status") flagIsAdmin = cmd.Flags().Bool("is-admin", false, "Filter by admin status")
flagActive = cmd.Flags().Bool("active", false, "Filter by active status at the source")
cmd.Flags().StringVar(&flagAuthMethod, "auth-method", "", "Filter by auth method (SSO, PASSWORD, API_KEY, SERVICE_ACCOUNT, UNKNOWN)") cmd.Flags().StringVar(&flagAuthMethod, "auth-method", "", "Filter by auth method (SSO, PASSWORD, API_KEY, SERVICE_ACCOUNT, UNKNOWN)")
cmd.Flags().StringVar(&flagAccountType, "account-type", "", "Filter by account type (USER, SERVICE_ACCOUNT)") cmd.Flags().StringVar(&flagAccountType, "account-type", "", "Filter by account type (USER, SERVICE_ACCOUNT)")
flagOutput = cmdutil.AddOutputFlag(cmd) flagOutput = cmdutil.AddOutputFlag(cmd)

View File

@@ -43,6 +43,7 @@ type (
MFAStatus MFAStatus `db:"mfa_status"` MFAStatus MFAStatus `db:"mfa_status"`
AuthMethod AccessEntryAuthMethod `db:"auth_method"` AuthMethod AccessEntryAuthMethod `db:"auth_method"`
AccountType AccessEntryAccountType `db:"account_type"` AccountType AccessEntryAccountType `db:"account_type"`
Active *bool `db:"active"`
LastLogin *time.Time `db:"last_login"` LastLogin *time.Time `db:"last_login"`
AccountCreatedAt *time.Time `db:"account_created_at"` AccountCreatedAt *time.Time `db:"account_created_at"`
ExternalID string `db:"external_id"` ExternalID string `db:"external_id"`
@@ -130,6 +131,7 @@ SELECT
mfa_status, mfa_status,
auth_method, auth_method,
account_type, account_type,
active,
last_login, last_login,
account_created_at, account_created_at,
external_id, external_id,
@@ -196,6 +198,7 @@ INSERT INTO
mfa_status, mfa_status,
auth_method, auth_method,
account_type, account_type,
active,
last_login, last_login,
account_created_at, account_created_at,
external_id, external_id,
@@ -225,6 +228,7 @@ VALUES (
@mfa_status, @mfa_status,
@auth_method, @auth_method,
@account_type, @account_type,
@active,
@last_login, @last_login,
@account_created_at, @account_created_at,
@external_id, @external_id,
@@ -256,6 +260,7 @@ VALUES (
"mfa_status": e.MFAStatus, "mfa_status": e.MFAStatus,
"auth_method": e.AuthMethod, "auth_method": e.AuthMethod,
"account_type": e.AccountType, "account_type": e.AccountType,
"active": e.Active,
"last_login": e.LastLogin, "last_login": e.LastLogin,
"account_created_at": e.AccountCreatedAt, "account_created_at": e.AccountCreatedAt,
"external_id": e.ExternalID, "external_id": e.ExternalID,
@@ -347,6 +352,7 @@ SELECT
mfa_status, mfa_status,
auth_method, auth_method,
account_type, account_type,
active,
last_login, last_login,
account_created_at, account_created_at,
external_id, external_id,
@@ -414,6 +420,7 @@ SELECT
mfa_status, mfa_status,
auth_method, auth_method,
account_type, account_type,
active,
last_login, last_login,
account_created_at, account_created_at,
external_id, external_id,
@@ -629,6 +636,7 @@ INSERT INTO access_entries (
mfa_status, mfa_status,
auth_method, auth_method,
account_type, account_type,
active,
last_login, last_login,
account_created_at, account_created_at,
external_id, external_id,
@@ -657,6 +665,7 @@ INSERT INTO access_entries (
@mfa_status, @mfa_status,
@auth_method, @auth_method,
@account_type, @account_type,
@active,
@last_login, @last_login,
@account_created_at, @account_created_at,
@external_id, @external_id,
@@ -680,6 +689,7 @@ ON CONFLICT (access_review_campaign_id, access_source_id, account_key) DO UPDATE
mfa_status = EXCLUDED.mfa_status, mfa_status = EXCLUDED.mfa_status,
auth_method = EXCLUDED.auth_method, auth_method = EXCLUDED.auth_method,
account_type = EXCLUDED.account_type, account_type = EXCLUDED.account_type,
active = EXCLUDED.active,
last_login = EXCLUDED.last_login, last_login = EXCLUDED.last_login,
account_created_at = EXCLUDED.account_created_at, account_created_at = EXCLUDED.account_created_at,
external_id = EXCLUDED.external_id, external_id = EXCLUDED.external_id,
@@ -702,6 +712,7 @@ ON CONFLICT (access_review_campaign_id, access_source_id, account_key) DO UPDATE
"mfa_status": e.MFAStatus, "mfa_status": e.MFAStatus,
"auth_method": e.AuthMethod, "auth_method": e.AuthMethod,
"account_type": e.AccountType, "account_type": e.AccountType,
"active": e.Active,
"last_login": e.LastLogin, "last_login": e.LastLogin,
"account_created_at": e.AccountCreatedAt, "account_created_at": e.AccountCreatedAt,
"external_id": e.ExternalID, "external_id": e.ExternalID,

View File

@@ -23,6 +23,7 @@ type AccessEntryFilter struct {
Flag *AccessEntryFlag Flag *AccessEntryFlag
IncrementalTag *AccessEntryIncrementalTag IncrementalTag *AccessEntryIncrementalTag
IsAdmin *bool IsAdmin *bool
Active *bool
AuthMethod *AccessEntryAuthMethod AuthMethod *AccessEntryAuthMethod
AccountType *AccessEntryAccountType AccountType *AccessEntryAccountType
} }
@@ -58,6 +59,12 @@ func (f *AccessEntryFilter) SQLFragment() string {
ELSE TRUE ELSE TRUE
END END
AND AND
CASE
WHEN @filter_active::boolean IS NOT NULL THEN
active = @filter_active::boolean
ELSE TRUE
END
AND
CASE CASE
WHEN @filter_auth_method::text IS NOT NULL THEN WHEN @filter_auth_method::text IS NOT NULL THEN
auth_method = @filter_auth_method::text auth_method = @filter_auth_method::text
@@ -82,6 +89,7 @@ func (f *AccessEntryFilter) SQLArguments() pgx.StrictNamedArgs {
"filter_flag": nil, "filter_flag": nil,
"filter_incremental_tag": nil, "filter_incremental_tag": nil,
"filter_is_admin": nil, "filter_is_admin": nil,
"filter_active": nil,
"filter_auth_method": nil, "filter_auth_method": nil,
"filter_account_type": nil, "filter_account_type": nil,
} }
@@ -102,6 +110,10 @@ func (f *AccessEntryFilter) SQLArguments() pgx.StrictNamedArgs {
args["filter_is_admin"] = *f.IsAdmin args["filter_is_admin"] = *f.IsAdmin
} }
if f.Active != nil {
args["filter_active"] = *f.Active
}
if f.AuthMethod != nil { if f.AuthMethod != nil {
args["filter_auth_method"] = string(*f.AuthMethod) args["filter_auth_method"] = string(*f.AuthMethod)
} }

View File

@@ -350,6 +350,82 @@ func TestAccessEntry_Upsert_RefreshesSourceTrackingFields(t *testing.T) {
assert.Nil(t, loaded.DecidedAt) assert.Nil(t, loaded.DecidedAt)
} }
func TestAccessEntry_Upsert_RefreshesActiveStatus(t *testing.T) {
t.Parallel()
client := test.PGClient(t)
ctx := context.Background()
fx := seedAccessEntryFixture(t, ctx, client)
tenantID := fx.scope.GetTenantID()
t0 := time.Now().UTC().Truncate(time.Microsecond)
activeTrue := true
activeFalse := false
entryID := gid.New(tenantID, coredata.AccessEntryEntityType)
first := &coredata.AccessEntry{
ID: entryID,
OrganizationID: fx.organizationID,
AccessReviewCampaignID: fx.campaignID,
AccessSourceID: fx.sourceID,
Email: "user@example.com",
FullName: "User",
Role: "member",
MFAStatus: coredata.MFAStatusUnknown,
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
AccountType: coredata.AccessEntryAccountTypeUser,
Active: &activeTrue,
ExternalID: "ext-active",
AccountKey: fx.accountKey,
IncrementalTag: coredata.AccessEntryIncrementalTagNew,
Flags: []coredata.AccessEntryFlag{},
FlagReasons: []string{},
Decision: coredata.AccessEntryDecisionPending,
CreatedAt: t0,
UpdatedAt: t0,
}
require.NoError(t, client.WithTx(ctx, func(ctx context.Context, tx pg.Tx) error {
return first.Upsert(ctx, tx, fx.scope)
}))
t1 := t0.Add(1 * time.Hour)
second := &coredata.AccessEntry{
ID: gid.New(tenantID, coredata.AccessEntryEntityType),
OrganizationID: fx.organizationID,
AccessReviewCampaignID: fx.campaignID,
AccessSourceID: fx.sourceID,
Email: "user@example.com",
FullName: "User",
Role: "member",
MFAStatus: coredata.MFAStatusUnknown,
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
AccountType: coredata.AccessEntryAccountTypeUser,
Active: &activeFalse,
ExternalID: "ext-active",
AccountKey: fx.accountKey,
IncrementalTag: coredata.AccessEntryIncrementalTagUnchanged,
Flags: []coredata.AccessEntryFlag{},
FlagReasons: []string{},
Decision: coredata.AccessEntryDecisionPending,
CreatedAt: t1,
UpdatedAt: t1,
}
require.NoError(t, client.WithTx(ctx, func(ctx context.Context, tx pg.Tx) error {
return second.Upsert(ctx, tx, fx.scope)
}))
loaded := &coredata.AccessEntry{}
require.NoError(t, client.WithConn(ctx, func(ctx context.Context, conn pg.Querier) error {
return loaded.LoadByID(ctx, conn, fx.scope, entryID)
}))
require.NotNil(t, loaded.Active)
assert.False(t, *loaded.Active)
}
// TestAccessEntry_Upsert_InsertsActiveAccount covers the shape FetchSource // TestAccessEntry_Upsert_InsertsActiveAccount covers the shape FetchSource
// builds for an active account: a PENDING decision and explicit empty // builds for an active account: a PENDING decision and explicit empty
// flags / flag_reasons slices. The access_entries.flags and flag_reasons // flags / flag_reasons slices. The access_entries.flags and flag_reasons
@@ -377,6 +453,7 @@ func TestAccessEntry_Upsert_InsertsActiveAccount(t *testing.T) {
MFAStatus: coredata.MFAStatusUnknown, MFAStatus: coredata.MFAStatusUnknown,
AuthMethod: coredata.AccessEntryAuthMethodUnknown, AuthMethod: coredata.AccessEntryAuthMethodUnknown,
AccountType: coredata.AccessEntryAccountTypeUser, AccountType: coredata.AccessEntryAccountTypeUser,
Active: new(true),
ExternalID: "ext-active", ExternalID: "ext-active",
AccountKey: fx.accountKey, AccountKey: fx.accountKey,
IncrementalTag: coredata.AccessEntryIncrementalTagNew, IncrementalTag: coredata.AccessEntryIncrementalTagNew,
@@ -397,6 +474,8 @@ func TestAccessEntry_Upsert_InsertsActiveAccount(t *testing.T) {
return loaded.LoadByID(ctx, conn, fx.scope, entryID) return loaded.LoadByID(ctx, conn, fx.scope, entryID)
})) }))
require.NotNil(t, loaded.Active)
assert.True(t, *loaded.Active)
assert.Equal(t, coredata.AccessEntryDecisionPending, loaded.Decision) assert.Equal(t, coredata.AccessEntryDecisionPending, loaded.Decision)
assert.Equal(t, []coredata.AccessEntryFlag{}, loaded.Flags) assert.Equal(t, []coredata.AccessEntryFlag{}, loaded.Flags)
assert.Equal(t, []string{}, loaded.FlagReasons) assert.Equal(t, []string{}, loaded.FlagReasons)

View File

@@ -0,0 +1,16 @@
-- Copyright (c) 2026 Probo Inc <hello@probo.com>.
--
-- Permission to use, copy, modify, and/or distribute this software for any
-- purpose with or without fee is hereby granted, provided that the above
-- copyright notice and this permission notice appear in all copies.
--
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-- PERFORMANCE OF THIS SOFTWARE.
ALTER TABLE access_entries
ADD COLUMN active BOOLEAN;

View File

@@ -280,6 +280,7 @@ input AccessEntryFilter
flag: AccessEntryFlag flag: AccessEntryFlag
incrementalTag: AccessEntryIncrementalTag incrementalTag: AccessEntryIncrementalTag
isAdmin: Boolean isAdmin: Boolean
active: Boolean
authMethod: AccessEntryAuthMethod authMethod: AccessEntryAuthMethod
accountType: AccessEntryAccountType accountType: AccessEntryAccountType
} }
@@ -372,6 +373,7 @@ type AccessEntry implements Node {
role: String! role: String!
jobTitle: String! jobTitle: String!
isAdmin: Boolean! isAdmin: Boolean!
active: Boolean
mfaStatus: MfaStatus! mfaStatus: MfaStatus!
authMethod: AccessEntryAuthMethod! authMethod: AccessEntryAuthMethod!
accountType: AccessEntryAccountType! accountType: AccessEntryAccountType!

View File

@@ -249,6 +249,7 @@ func NewAccessEntry(e *coredata.AccessEntry) *AccessEntry {
Role: e.Role, Role: e.Role,
JobTitle: e.JobTitle, JobTitle: e.JobTitle,
IsAdmin: e.IsAdmin, IsAdmin: e.IsAdmin,
Active: e.Active,
MfaStatus: e.MFAStatus, MfaStatus: e.MFAStatus,
AuthMethod: e.AuthMethod, AuthMethod: e.AuthMethod,
AccountType: e.AccountType, AccountType: e.AccountType,

View File

@@ -3438,7 +3438,9 @@ func (r *Resolver) ListAccessEntriesTool(ctx context.Context, req *mcp.CallToolR
Flag: input.Filter.Flag, Flag: input.Filter.Flag,
IncrementalTag: input.Filter.IncrementalTag, IncrementalTag: input.Filter.IncrementalTag,
IsAdmin: input.Filter.IsAdmin, IsAdmin: input.Filter.IsAdmin,
Active: input.Filter.Active,
AuthMethod: input.Filter.AuthMethod, AuthMethod: input.Filter.AuthMethod,
AccountType: input.Filter.AccountType,
} }
} }

View File

@@ -7721,6 +7721,11 @@ components:
is_admin: is_admin:
type: boolean type: boolean
description: Whether the user has admin privileges description: Whether the user has admin privileges
active:
type:
- boolean
- "null"
description: Whether the account is active at the source (null when unknown)
mfa_status: mfa_status:
$ref: "#/components/schemas/MFAStatus" $ref: "#/components/schemas/MFAStatus"
description: MFA status description: MFA status
@@ -7879,6 +7884,9 @@ components:
is_admin: is_admin:
type: boolean type: boolean
description: Filter by admin status description: Filter by admin status
active:
type: boolean
description: Filter by active status at the source
auth_method: auth_method:
$ref: "#/components/schemas/AccessEntryAuthMethod" $ref: "#/components/schemas/AccessEntryAuthMethod"
description: Filter by auth method description: Filter by auth method
@@ -13277,7 +13285,7 @@ tools:
outputSchema: outputSchema:
$ref: "#/components/schemas/ListAccessReviewCampaignsOutput" $ref: "#/components/schemas/ListAccessReviewCampaignsOutput"
- name: listAccessEntries - name: listAccessEntries
description: List access entries for a campaign with optional filters (decision, flag, incremental_tag, is_admin, auth_method, account_type) description: List access entries for a campaign with optional filters (decision, flag, incremental_tag, is_admin, active, auth_method, account_type)
hints: hints:
readonly: true readonly: true
idempotent: true idempotent: true

View File

@@ -77,6 +77,7 @@ func NewAccessEntry(e *coredata.AccessEntry) *AccessEntry {
Role: e.Role, Role: e.Role,
JobTitle: e.JobTitle, JobTitle: e.JobTitle,
IsAdmin: e.IsAdmin, IsAdmin: e.IsAdmin,
Active: e.Active,
MfaStatus: e.MFAStatus, MfaStatus: e.MFAStatus,
AuthMethod: e.AuthMethod, AuthMethod: e.AuthMethod,
AccountType: e.AccountType, AccountType: e.AccountType,