# kunalpandey1/usernaut architecture

> Architecture diagram of the GitHub repository kunalpandey1/usernaut, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-30). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/kunalpandey1/usernaut
- Repository: https://github.com/kunalpandey1/usernaut

## Overview

1. **Overall shape**
Usernaut is a Kubernetes Operator-style service that continuously reconciles a custom `Group` resource into external identity/team systems. The core runtime is a single Go manager process, packaged as a container and deployed with Kustomize manifests.

2. **Primary control plane boundary**
The Kubernetes API is the main source of truth. The `api/v1alpha1` package defines the `Group` CRD schema, and `config/crd` contains the generated CRD manifest. Cluster operators create/update `Group` objects; Usernaut watches them and drives reconciliation from there.

3. **Controller layer**
The main reconciliation logic lives in `internal/controller/group_controller.go`. This controller is responsible for reading group definitions, resolving membership, and syncing the desired state to downstream systems. A second controller, `periodic_tasks_controller.go`, exists to run scheduled maintenance work rather than direct CR reconciliation.

4. **Membership resolution pipeline**
Group membership is not limited to static users. The README and file layout show three member sources: direct users, nested groups, and LDAP-query-based membership. That means the controller must expand a group graph and also consult LDAP to resolve dynamic members before syncing.

5. **Backend synchronization**
The `pkg/clients` tree is the integration boundary to external SaaS platforms:
- `ldap` for directory lookups
- `fivetran`, `gitlab`, `snowflake`, and `redhat_rover` for target systems
Each backend has its own client package plus resource-specific operations like users, teams, and team membership. This is the main outbound data flow from the operator.

6. **State and caching**
Usernaut has a separate cache abstraction in `pkg/cache` with both in-memory and Redis implementations. Redis manifests live under `config/redis`, which implies cache-backed persistence is part of the deployed architecture, not just a library detail. The cache likely stores reconciliation state, lookup results, or derived membership data to reduce repeated API calls.

7. **Store layer**
The `pkg/store` package sits between controllers and cached/derived data. There are dedicated stores for groups, teams, users, and user-group relationships, indicating the operator normalizes CRD and backend data into internal domain models before acting on them. This helps keep reconciliation logic separate from raw client APIs.

8. **Periodic offboarding**
`internal/controller/periodicjobs/job_usernaut_offboarding.go` and related tests indicate a scheduled offboarding job. The README confirms this is a daily task that removes users no longer present in LDAP from the managed backends. This is a distinct flow from normal reconcile: it is time-driven and cross-cutting across all systems.

9. **HTTP API surface**
The `internal/httpapi` package provides a separate REST server for querying memberships programmatically. It has its own handlers, server wrapper, and middleware for basic auth and CORS. This API is an auxiliary read-facing interface, not the primary control mechanism.

10. **Configuration and runtime wiring**
`pkg/config` and `appconfig` provide environment/file-based configuration for backend credentials, feature flags, and deployment-specific settings. The presence of `config/default`, `config/manifests`, `config/manual-rbac`, and environment overlays (`rhprod`, `rhplatformtest`) shows the same binary is deployed into multiple Kubernetes environments with different RBAC and env patches.

11. **RBAC and platform integration**
The repo includes explicit RBAC manifests for the operator, leader election, metrics access, and service accounts. There are also separate manifests for manual RBAC and admin service accounts, suggesting some deployment modes require additional permissions outside the default operator role set.

12. **Operational and packaging boundaries**
The repo is built and validated with Go tooling, GitHub Actions, Docker, and Kubernetes manifests. Metrics are exposed via the manager/service manifests, and `config/prometheus` plus `config/scorecard` indicate standard operator observability and operator-framework validation support.

13. **Testing boundaries**
Unit tests cover clients, cache, stores, controller behavior, and the HTTP layer. End-to-end tests live under `test/e2e`, which suggests the project validates not just local logic but also the reconciliation path against Kubernetes resources and externalized behavior.

14. **Diagram-friendly data flow**
A useful architecture diagram should show: Kubernetes `Group` CRs in the center; the controller reading CRs and config; LDAP as a read dependency for user resolution; Redis/in-memory cache as an internal accelerator/state layer; outbound writes to Fivetran, GitLab, Snowflake, and Rover; a separate periodic offboarding path; and a read-only REST API alongside the operator for membership queries.

Main entry points: [`internal/controller/group_controller.go`](https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/group_controller.go) (Group Controller), [`pkg/store/store.go`](https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/store.go) (Membership Store), [`internal/controller/periodicjobs/job_usernaut_offboarding.go`](https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/periodicjobs/job_usernaut_offboarding.go) (Offboarding Job), [`cmd/main.go`](https://github.com/kunalpandey1/usernaut/blob/main/cmd/main.go) (Manager Binary)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_control_plane["Kubernetes Control Plane"]
  node_group_crd["Group CRD<br/>api/v1alpha1 schema<br/>[group_types.go]"]
  node_crd_manifest["CRD Manifest<br/>generated YAML"]
  node_group_controller["Group Controller<br/>reconciler"]
  node_periodic_controller["Periodic Controller<br/>scheduler"]
  node_manager_bin{{"Manager Binary<br/>operator entrypoint<br/>[main.go]"}}
end

subgraph group_integration["External Integrations"]
  node_ldap_client["LDAP Client<br/>directory client<br/>[client.go]"]
  node_fivetran_client["Fivetran Client<br/>target client<br/>[client.go]"]
  node_gitlab_client["GitLab Client<br/>target client<br/>[client.go]"]
  node_snowflake_client["Snowflake Client<br/>target client<br/>[client.go]"]
  node_rover_client["Rover Client<br/>target client<br/>[client.go]"]
end

subgraph group_state["Internal State"]
  node_membership_store["Membership Store<br/>domain store<br/>[store.go]"]
  node_group_store["Group Store<br/>[group_store.go]"]
  node_team_store["Team Store<br/>[team_store.go]"]
  node_user_store["User Store<br/>[user_store.go]"]
  node_user_groups_store["User-Group Store<br/>relationship store"]
  node_cache_layer["Cache Layer<br/>cache abstraction<br/>[cache.go]"]
  node_redis_cache[("Redis Cache<br/>cache backend<br/>[cache.go]")]
  node_memory_cache[("In-Memory Cache<br/>cache backend<br/>[cache.go]")]
end

subgraph group_interfaces["Auxiliary Interfaces"]
  node_offboarding_job["Offboarding Job<br/>daily job"]
  node_http_api["HTTP API<br/>read API<br/>[server.go]"]
end

subgraph group_deployment["Packaging"]
  node_config_pkg["Config Loader<br/>runtime config<br/>[config.go]"]
end

node_crd_manifest -->|"installs"| node_group_crd
node_manager_bin -->|"loads"| node_config_pkg
node_manager_bin -->|"runs"| node_group_controller
node_manager_bin -->|"runs"| node_periodic_controller
node_manager_bin -->|"serves"| node_http_api
node_group_controller -->|"watches"| node_group_crd
node_group_controller -->|"uses"| node_membership_store
node_membership_store -->|"contains"| node_group_store
node_membership_store -->|"contains"| node_team_store
node_membership_store -->|"contains"| node_user_store
node_membership_store -->|"contains"| node_user_groups_store
node_membership_store -->|"accelerates"| node_cache_layer
node_cache_layer -->|"implements"| node_memory_cache
node_cache_layer -->|"implements"| node_redis_cache
node_group_controller -->|"resolves"| node_ldap_client
node_group_controller -->|"syncs"| node_fivetran_client
node_group_controller -->|"syncs"| node_gitlab_client
node_group_controller -->|"syncs"| node_snowflake_client
node_group_controller -->|"syncs"| node_rover_client
node_periodic_controller -->|"triggers"| node_offboarding_job
node_offboarding_job -->|"checks"| node_ldap_client
node_offboarding_job -->|"removes"| node_fivetran_client
node_offboarding_job -->|"removes"| node_gitlab_client
node_offboarding_job -->|"removes"| node_snowflake_client
node_offboarding_job -->|"removes"| node_rover_client
node_http_api -->|"queries"| node_membership_store

click node_group_crd "https://github.com/kunalpandey1/usernaut/blob/main/api/v1alpha1/group_types.go"
click node_crd_manifest "https://github.com/kunalpandey1/usernaut/blob/main/config/crd/bases/operator.dataverse.redhat.com_groups.yaml"
click node_group_controller "https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/group_controller.go"
click node_periodic_controller "https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/periodic_tasks_controller.go"
click node_offboarding_job "https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/periodicjobs/job_usernaut_offboarding.go"
click node_membership_store "https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/store.go"
click node_group_store "https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/group_store.go"
click node_team_store "https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/team_store.go"
click node_user_store "https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/user_store.go"
click node_user_groups_store "https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/user_groups_store.go"
click node_cache_layer "https://github.com/kunalpandey1/usernaut/blob/main/pkg/cache/cache.go"
click node_redis_cache "https://github.com/kunalpandey1/usernaut/blob/main/pkg/cache/redis/cache.go"
click node_memory_cache "https://github.com/kunalpandey1/usernaut/blob/main/pkg/cache/inmemory/cache.go"
click node_ldap_client "https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/ldap/client.go"
click node_fivetran_client "https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/fivetran/client.go"
click node_gitlab_client "https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/gitlab/client.go"
click node_snowflake_client "https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/snowflake/client.go"
click node_rover_client "https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/redhat_rover/client.go"
click node_http_api "https://github.com/kunalpandey1/usernaut/blob/main/internal/httpapi/server/server.go"
click node_config_pkg "https://github.com/kunalpandey1/usernaut/blob/main/pkg/config/config.go"
click node_manager_bin "https://github.com/kunalpandey1/usernaut/blob/main/cmd/main.go"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_group_crd,node_crd_manifest,node_group_controller,node_periodic_controller,node_manager_bin toneBlue
class node_ldap_client,node_fivetran_client,node_gitlab_client,node_snowflake_client,node_rover_client toneAmber
class node_membership_store,node_group_store,node_team_store,node_user_store,node_user_groups_store,node_cache_layer,node_redis_cache,node_memory_cache toneMint
class node_offboarding_job,node_http_api toneRose
class node_config_pkg toneIndigo
```

## Components

### Kubernetes Control Plane

CRDs, controller runtime, and deployment manifests that define the operator's main reconciliation path.

- [Group CRD](https://github.com/kunalpandey1/usernaut/blob/main/api/v1alpha1/group_types.go): api/v1alpha1 schema · Custom resource definition for managed groups. · `api/v1alpha1/group_types.go`
- [CRD Manifest](https://github.com/kunalpandey1/usernaut/blob/main/config/crd/bases/operator.dataverse.redhat.com_groups.yaml): generated YAML · Cluster manifest that installs the Group custom resource. · `config/crd/bases/operator.dataverse.redhat.com_groups.yaml`
- [Group Controller](https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/group_controller.go): reconciler · Main reconciliation loop for syncing Group resources to external systems. · `internal/controller/group_controller.go`
- [Periodic Controller](https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/periodic_tasks_controller.go): scheduler · Controller that triggers scheduled maintenance work. · `internal/controller/periodic_tasks_controller.go`
- [Manager Binary](https://github.com/kunalpandey1/usernaut/blob/main/cmd/main.go): operator entrypoint · Single Go process that wires controllers, clients, cache, and API server. · `cmd/main.go`

### External Integrations

Outbound systems the operator reads from or syncs into.

- [LDAP Client](https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/ldap/client.go): directory client · Reads directory data and dynamic membership queries. · `pkg/clients/ldap/client.go`
- [Fivetran Client](https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/fivetran/client.go): target client · Syncs users, teams, and memberships to Fivetran. · `pkg/clients/fivetran/client.go`
- [GitLab Client](https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/gitlab/client.go): target client · Syncs users, teams, and memberships to GitLab. · `pkg/clients/gitlab/client.go`
- [Snowflake Client](https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/snowflake/client.go): target client · Syncs users, teams, and memberships to Snowflake. · `pkg/clients/snowflake/client.go`
- [Rover Client](https://github.com/kunalpandey1/usernaut/blob/main/pkg/clients/redhat_rover/client.go): target client · Syncs users, teams, and memberships to Red Hat Rover. · `pkg/clients/redhat_rover/client.go`

### Internal State

Caching, stores, and domain models used to normalize and accelerate reconciliation.

- [Membership Store](https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/store.go): domain store · Normalized store for groups, teams, users, and user-group relationships. · `pkg/store/store.go`
- [Group Store](https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/group_store.go): group store · Group-centric storage and lookup logic. · `pkg/store/group_store.go`
- [Team Store](https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/team_store.go): team store · Team-centric storage and lookup logic. · `pkg/store/team_store.go`
- [User Store](https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/user_store.go): user store · User-centric storage and lookup logic. · `pkg/store/user_store.go`
- [User-Group Store](https://github.com/kunalpandey1/usernaut/blob/main/pkg/store/user_groups_store.go): relationship store · Tracks membership relationships between users and groups. · `pkg/store/user_groups_store.go`
- [Cache Layer](https://github.com/kunalpandey1/usernaut/blob/main/pkg/cache/cache.go): cache abstraction · Shared cache interface used to reduce repeated lookups and preserve derived state. · `pkg/cache/cache.go`
- [Redis Cache](https://github.com/kunalpandey1/usernaut/blob/main/pkg/cache/redis/cache.go): cache backend · Redis-backed cache implementation used in deployment. · `pkg/cache/redis/cache.go`
- [In-Memory Cache](https://github.com/kunalpandey1/usernaut/blob/main/pkg/cache/inmemory/cache.go): cache backend · Local in-process cache implementation. · `pkg/cache/inmemory/cache.go`

### Auxiliary Interfaces

Read-facing API and scheduled jobs that complement the main reconcile loop.

- [Offboarding Job](https://github.com/kunalpandey1/usernaut/blob/main/internal/controller/periodicjobs/job_usernaut_offboarding.go): daily job · Scheduled flow that removes users no longer present in LDAP. · `internal/controller/periodicjobs/job_usernaut_offboarding.go`
- [HTTP API](https://github.com/kunalpandey1/usernaut/blob/main/internal/httpapi/server/server.go): read API · Auxiliary REST surface for membership queries. · `internal/httpapi/server/server.go`

### Packaging

Kustomize overlays and runtime configuration used to ship the same binary into different environments.

- [Config Loader](https://github.com/kunalpandey1/usernaut/blob/main/pkg/config/config.go): runtime config · Loads environment/file configuration for credentials, flags, and deployment settings. · `pkg/config/config.go`

## Connections

- CRD Manifest → Group CRD: installs · Cluster manifest defines the Group resource.
- Manager Binary → Config Loader: loads · Entry point reads runtime configuration.
- Manager Binary → Group Controller: runs · Manager starts the primary reconciler.
- Manager Binary → Periodic Controller: runs · Manager starts scheduled maintenance controller.
- Manager Binary → HTTP API: serves · Manager also hosts the read-only API.
- Group Controller → Group CRD: watches · Controller reconciles Group custom resources.
- Group Controller → Membership Store: uses · Controller reads and writes normalized domain state.
- Membership Store → Group Store: contains · Group-specific store component.
- Membership Store → Team Store: contains · Team-specific store component.
- Membership Store → User Store: contains · User-specific store component.
- Membership Store → User-Group Store: contains · Relationship store for membership edges.
- Membership Store → Cache Layer: accelerates · Stores use cache for derived state and lookups.
- Cache Layer → In-Memory Cache: implements · In-memory backend.
- Cache Layer → Redis Cache: implements · Redis-backed backend.
- Group Controller → LDAP Client: resolves · Reads directory data for direct and query-based members.
- Group Controller → Fivetran Client: syncs · Writes desired membership state.
- Group Controller → GitLab Client: syncs · Writes desired membership state.
- Group Controller → Snowflake Client: syncs · Writes desired membership state.
- Group Controller → Rover Client: syncs · Writes desired membership state.
- Periodic Controller → Offboarding Job: triggers · Runs the daily offboarding workflow.
- Offboarding Job → LDAP Client: checks · Verifies current LDAP presence before removal.
- Offboarding Job → Fivetran Client: removes · Cleans up managed users where needed.
- Offboarding Job → GitLab Client: removes · Cleans up managed users where needed.
- Offboarding Job → Snowflake Client: removes · Cleans up managed users where needed.
- Offboarding Job → Rover Client: removes · Cleans up managed users where needed.
- HTTP API → Membership Store: queries · API reads normalized membership data.
