Include all accounts in access-review fetch
Drivers whose source API surfaces an account-status signal return every account (including inactive / suspended / deleted) and populate Active accordingly; drivers without such a signal no longer fabricate it. The fetch pipeline records every account with decision PENDING and no flags. Producing flags or a non-PENDING decision is reserved to human reviewers or a purpose-built agent run against the campaign -- the engine must not form an implicit verdict. Signed-off-by: Aurélien Sibiril <81782+aureliensibiril@users.noreply.github.com>
This commit is contained in:
@@ -68,7 +68,7 @@ func (d *BrexDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error)
|
||||
Email: u.Email,
|
||||
FullName: u.FirstName + " " + u.LastName,
|
||||
Role: u.Role,
|
||||
Active: u.Status == "ACTIVE",
|
||||
Active: new(u.Status == "ACTIVE"),
|
||||
IsAdmin: false,
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -184,7 +184,7 @@ func (d *CloudflareDriver) queryAllMembers(ctx context.Context, accountID string
|
||||
Email: m.User.Email,
|
||||
FullName: m.User.FirstName + " " + m.User.LastName,
|
||||
Role: role,
|
||||
Active: m.Status == "accepted",
|
||||
Active: new(m.Status == "accepted"),
|
||||
IsAdmin: isAdmin,
|
||||
ExternalID: m.ID,
|
||||
MFAStatus: mfaStatus,
|
||||
|
||||
@@ -88,7 +88,7 @@ func (d *CSVDriver) ListAccounts(_ context.Context) ([]AccountRecord, error) {
|
||||
record.IsAdmin = strings.TrimSpace(strings.ToLower(row[idx])) == "true"
|
||||
}
|
||||
if idx, ok := colIndex["active"]; ok && idx < len(row) {
|
||||
record.Active = strings.TrimSpace(strings.ToLower(row[idx])) == "true"
|
||||
record.Active = new(strings.TrimSpace(strings.ToLower(row[idx])) == "true")
|
||||
}
|
||||
if idx, ok := colIndex["external_id"]; ok && idx < len(row) {
|
||||
record.ExternalID = strings.TrimSpace(row[idx])
|
||||
|
||||
@@ -93,7 +93,7 @@ func (d *DocuSignDriver) ListAccounts(ctx context.Context) ([]AccountRecord, err
|
||||
FullName: u.UserName,
|
||||
Role: u.PermissionProfileName,
|
||||
JobTitle: u.JobTitle,
|
||||
Active: strings.EqualFold(u.UserStatus, "active"),
|
||||
Active: new(strings.EqualFold(u.UserStatus, "active")),
|
||||
IsAdmin: strings.EqualFold(u.IsAdmin, "True"),
|
||||
ExternalID: u.UserID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -23,13 +23,23 @@ import (
|
||||
)
|
||||
|
||||
// AccountRecord represents a single account from an access source or identity
|
||||
// source. All fields are best-effort; sources populate what they can.
|
||||
// source. All fields are best-effort; sources populate what they can. Drivers
|
||||
// must return ALL accounts the source exposes (including inactive / suspended
|
||||
// / deleted); classification is the job of the reviewer or of an agent run
|
||||
// against the campaign, not of the fetch pipeline.
|
||||
//
|
||||
// Active is three-valued: nil means the source API has no explicit
|
||||
// account-status signal for this account (the driver cannot tell), a non-nil
|
||||
// pointer means the driver observed an explicit signal (true = active at
|
||||
// source, false = deactivated / suspended / deleted). Drivers whose API does
|
||||
// not distinguish active from deactivated accounts must leave Active nil
|
||||
// rather than fabricate a value.
|
||||
type AccountRecord struct {
|
||||
Email string
|
||||
FullName string
|
||||
Role string // system role/permission (e.g. "Admin", "Viewer")
|
||||
JobTitle string // HR job title / department (e.g. "Software Engineer")
|
||||
Active bool
|
||||
Active *bool
|
||||
IsAdmin bool
|
||||
MFAStatus coredata.MFAStatus
|
||||
AuthMethod coredata.AccessEntryAuthMethod
|
||||
|
||||
@@ -119,7 +119,7 @@ func (d *GitHubDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error
|
||||
Email: profile.Email,
|
||||
FullName: fullName,
|
||||
Role: membership.Role,
|
||||
Active: membership.State == "active",
|
||||
Active: new(membership.State == "active"),
|
||||
IsAdmin: membership.Role == "admin",
|
||||
MFAStatus: mfaStatus,
|
||||
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
|
||||
|
||||
@@ -109,7 +109,7 @@ func (d *GoogleWorkspaceDriver) ListAccounts(ctx context.Context) ([]AccountReco
|
||||
rec := AccountRecord{
|
||||
Email: u.PrimaryEmail,
|
||||
FullName: u.Name.FullName,
|
||||
Active: !u.Suspended && !u.Archived,
|
||||
Active: new(!u.Suspended && !u.Archived),
|
||||
IsAdmin: u.IsAdmin,
|
||||
ExternalID: u.Id,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -99,7 +99,6 @@ func (d *HubSpotDriver) ListAccounts(ctx context.Context) ([]AccountRecord, erro
|
||||
Email: u.Email,
|
||||
FullName: fullName,
|
||||
Role: role,
|
||||
Active: true,
|
||||
IsAdmin: u.SuperAdmin,
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -67,7 +67,6 @@ func (d *IntercomDriver) ListAccounts(ctx context.Context) ([]AccountRecord, err
|
||||
FullName: a.Name,
|
||||
Role: intercomRole(a.HasInboxSeat),
|
||||
JobTitle: a.JobTitle,
|
||||
Active: true,
|
||||
IsAdmin: false, // Intercom API does not expose admin role information
|
||||
ExternalID: a.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -97,7 +97,7 @@ func (d *LinearDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error
|
||||
Email: u.Email,
|
||||
FullName: u.Name,
|
||||
Role: linearRole(u.Admin, u.Guest),
|
||||
Active: u.Active,
|
||||
Active: new(u.Active),
|
||||
IsAdmin: u.Admin,
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -81,7 +81,6 @@ func (d *NotionDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error
|
||||
Email: email,
|
||||
FullName: u.Name,
|
||||
Role: "Member",
|
||||
Active: true,
|
||||
IsAdmin: false,
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -93,7 +93,7 @@ func (d *OnePasswordDriver) ListAccounts(ctx context.Context) ([]AccountRecord,
|
||||
record := AccountRecord{
|
||||
Email: email,
|
||||
FullName: u.DisplayName,
|
||||
Active: u.Active,
|
||||
Active: new(u.Active),
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
|
||||
|
||||
@@ -86,7 +86,7 @@ func (d *OnePasswordUsersAPIDriver) ListAccounts(ctx context.Context) ([]Account
|
||||
record := AccountRecord{
|
||||
Email: u.Email,
|
||||
FullName: u.DisplayName,
|
||||
Active: u.State == "ACTIVE",
|
||||
Active: new(u.State == "ACTIVE"),
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
|
||||
|
||||
@@ -68,7 +68,7 @@ func (d *OpenAIDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error
|
||||
Email: u.Email,
|
||||
FullName: u.Name,
|
||||
Role: openaiRole(u.Role),
|
||||
Active: !u.Disabled,
|
||||
Active: new(!u.Disabled),
|
||||
IsAdmin: u.Role == "owner",
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -69,7 +69,7 @@ func (d *ProboMembershipsDriver) ListAccounts(ctx context.Context) ([]AccountRec
|
||||
Email: account.Email,
|
||||
FullName: account.FullName,
|
||||
Role: role,
|
||||
Active: account.State == string(coredata.ProfileStateActive),
|
||||
Active: new(account.State == string(coredata.ProfileStateActive)),
|
||||
IsAdmin: isAdmin,
|
||||
ExternalID: account.ID.String(),
|
||||
CreatedAt: &createdAt,
|
||||
|
||||
@@ -57,7 +57,6 @@ func (d *ResendDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error
|
||||
for _, k := range resp.Data {
|
||||
record := AccountRecord{
|
||||
FullName: k.Name,
|
||||
Active: true,
|
||||
IsAdmin: false,
|
||||
ExternalID: k.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
|
||||
@@ -144,7 +144,7 @@ func (d *SentryDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error
|
||||
Email: m.Email,
|
||||
FullName: fullName,
|
||||
Role: m.OrgRole,
|
||||
Active: active,
|
||||
Active: new(active),
|
||||
IsAdmin: isAdmin,
|
||||
ExternalID: m.ID,
|
||||
MFAStatus: mfaStatus,
|
||||
|
||||
@@ -101,7 +101,7 @@ func (d *SlackDriver) ListAccounts(ctx context.Context) ([]AccountRecord, error)
|
||||
FullName: m.RealName,
|
||||
JobTitle: m.Profile.Title,
|
||||
Role: slackRole(m),
|
||||
Active: !m.Deleted,
|
||||
Active: new(!m.Deleted),
|
||||
IsAdmin: m.IsAdmin || m.IsOwner || m.IsPrimaryOwner,
|
||||
ExternalID: m.ID,
|
||||
MFAStatus: slackMFAStatus(m.Has2FA),
|
||||
|
||||
@@ -65,7 +65,6 @@ func (d *SupabaseDriver) ListAccounts(ctx context.Context) ([]AccountRecord, err
|
||||
Email: m.Email,
|
||||
FullName: m.UserName,
|
||||
Role: m.RoleName,
|
||||
Active: true,
|
||||
IsAdmin: isAdmin,
|
||||
ExternalID: m.UserID,
|
||||
MFAStatus: mfaStatus,
|
||||
|
||||
@@ -115,7 +115,7 @@ func (d *TallyDriver) listUsers(ctx context.Context) ([]AccountRecord, error) {
|
||||
record := AccountRecord{
|
||||
Email: u.Email,
|
||||
FullName: u.FullName,
|
||||
Active: !u.IsDeleted,
|
||||
Active: new(!u.IsDeleted),
|
||||
ExternalID: u.ID,
|
||||
MFAStatus: mfaStatus,
|
||||
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
|
||||
@@ -169,7 +169,7 @@ func (d *TallyDriver) listInvites(ctx context.Context) ([]AccountRecord, error)
|
||||
for _, inv := range invites {
|
||||
record := AccountRecord{
|
||||
Email: inv.Email,
|
||||
Active: false,
|
||||
Active: new(false),
|
||||
ExternalID: inv.ID,
|
||||
MFAStatus: coredata.MFAStatusUnknown,
|
||||
AuthMethod: coredata.AccessEntryAuthMethodUnknown,
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
package accessreview
|
||||
|
||||
import "testing"
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNormalizeAccountKey(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
Reference in New Issue
Block a user