New DashboardService aggregates entity counts (rules, connections, credentials, schedules, users, api keys), rolling rule-run statistics (last 24h and 7d), the 10 most recent rule runs, and per-connection health based on last_tested_utc/last_test_result. Exposed via GET /api/v1/dashboard/summary and wired through server.Dependencies + cli.RunForeground.
New SettingsService provides List/Get/Upsert/Delete over the app_settings table. SettingsHandler exposes GET /api/v1/settings, GET/PUT/DELETE /api/v1/settings/{key} and redacts sensitive values in responses. Changes are recorded as ConfigChange audit events. The service is wired into server.Dependencies and constructed in cli.RunForeground.
Add Filter-based List and GetByID methods to audit.Service backed by a shared rowScanner so both sql.Row and sql.Rows can be decoded into an Event. Add a new AuditHandler with GET /api/v1/audit and GET /api/v1/audit/{id} wired into the router. Filters accepted via query string: eventType, userId, username, resourceType, resourceId, action, success, startUtc, endUtc.
Previously the audit service was never constructed, so every emitAudit call across the handlers was a silent no-op. Build an audit.Service in RunForeground, add it to the Dependencies struct, and log a ServiceStart event on startup so the audit trail is bootstrapped.
Introduce a shared audit_helpers.emitAudit utility that extracts user identity, IP, and User-Agent from the request context and forwards events to audit.Service. Wire an auditService dependency into all management handlers (auth, credentials, connections, schedules, rules, backups, api-keys, users) and emit audit events for login, CRUD, test, preview, run, backup, restore, API key create/revoke, and user lifecycle operations. Both successful and failed paths log with appropriate event types, resource IDs, and sanitized detail maps.
- New ConnectionService.QueryPreview runs an ad-hoc LDAP search against an
existing AD connection. Caller supplies filter, optional baseDn (defaults
to the connection's rootDn), scope, attributes, and limit (capped at 500,
defaulting to 100) and gets back the matched entries as DN + attribute map
along with a truncated flag.
- Scope strings are mapped through goldap.Scope* constants so base, one,
and sub values all work.
- Wire POST /api/v1/ad-connections/{id}/query-preview to
ConnectionsHandler.QueryPreview and require a non-empty filter.
- New CredentialService.Test method that decrypts the stored secret and
performs an LDAP bind against a user-supplied host/port/TLS target.
- Persists the outcome on the credential via UpdateTestResult so the
last_tested_utc and last_test_result columns stay current.
- Wire POST /api/v1/credentials/{id}/test to CredentialsHandler.Test,
which accepts the connection parameters in the request body and maps
'credential not found' to 404.
- New BackupsHandler exposing list, create, and restore over
/api/v1/backups, backed by services.BackupService.
- Create records who triggered the backup (username from context or
'api') and defaults the backup type to 'manual'.
- Restore resolves the {id} path parameter against the list of available
backups so clients can reference backups by filename, or pass an
explicit filePath in the body.
- Inject BackupService via server.Dependencies and initialize it in
cli.RunForeground under <DataPath>/backups with retention 10.
- New APIKeysHandler exposing list, create, revoke, and delete over
/api/v1/api-keys, backed by services.APIKeyService.
- Create returns the full plaintext key once; list/get responses only
surface the prefix and metadata.
- When userId is omitted, the handler falls back to the authenticated
principal pulled from context so callers can self-service tokens.
- Inject APIKeyService via server.Dependencies and initialize it in
cli.RunForeground.
- Add UserRepository.List with pagination and non-deleted filtering.
- New UsersHandler with List/Get/Create/Update/Delete; Create hashes
passwords via crypto.HashPassword and Update re-hashes on rotation.
- Responses omit password material; username conflict returns 409.
- Inject UserRepo via server.Dependencies and wire /api/v1/users routes.
- Extend server.Dependencies with AuthService and CredService, and
initialize them in cli.RunForeground using the derived AES key.
- Replace the handleNotImplemented stubs on /auth and /credentials with
the existing AuthHandler and CredentialsHandler routes.
- Guard /auth/me behind api.AuthMiddleware so it only resolves when a
valid session token is presented.
- Add RuleRunRepository.List for paging across runs regardless of rule.
- New RuleRunsHandler with List/Get/ListByRule, returning run summaries
and per-action detail via RuleRunDetailResponse.
- Register GET /api/v1/rule-runs, GET /api/v1/rule-runs/{runId}, and
GET /api/v1/rules/{id}/runs.
- New SchedulesHandler backed by the existing ScheduleRepository, with
request/response DTOs matching the schedules model (kind, easy/cron,
timezone mode).
- Register List/Get/Create/Update/Delete routes on /api/v1/schedules.
- Extend server.Dependencies with ScheduleRepo and wire it from
cli.RunForeground.
- Add Create/Update/Delete handlers on ConnectionsHandler backed by the
existing ConnectionRepository (soft-delete preserves audit history).
- Register List/Get/Create/Update/Delete/Test routes on /ad-connections
so the resource is no longer stubbed out.
- Extend RuleRepository with List/Update/SoftDelete/UpdateEnabled and
upsert helpers for condition groups, conditions, and actions.
- Extend RuleService with Create/GetByID/List/Update/Delete/Enable/Disable.
- Add List/Get/Create/Update/Delete/Enable/Disable handlers on RulesHandler
with request/response DTOs that decouple the API from storage models.
- Register the full CRUD route set on /api/v1/rules.
- Inject RuleService into server.Dependencies from cli.RunForeground.
Covers Expander.Expand / ExpandStrict behaviour for object, rule, custom,
and now sources, including error paths and template listing. Covers engine
helpers resolveBaseDN, resolveScope, collectAttributes, buildConditionGroups,
and parentDN.
Adds RulesHandler exposing POST /api/v1/rules/{id}/preview and
POST /api/v1/rules/{id}/run. Preview returns the generated LDAP filter,
matched objects, and planned actions. Run triggers an immediate execution
via the Runner using the X-Triggered-By header (defaults to 'api').
Also adds Runner.PreviewRule so the handler can delegate without having to
load the rule, connection, and LDAP client itself.
Derives a 32-byte AES key from the configured secret via SHA-256, constructs
the ConnectionService, Runner, and Engine, and starts the Scheduler so
enabled rules fire automatically. Injects the shared services into the HTTP
server via a new Dependencies struct so API handlers can reuse them.
- Add engine.Execute() that searches AD, iterates matches, runs actions,
honors StopOnError and PreviewOnly, and supports context cancellation
- Resolve base DN and search scope from rule override then connection defaults
- Add actionExecutor covering AddToGroup, AddGroupToGroup, EnsureGroupExists,
MoveToOu, and RemoveFromGroupIfNoLongerMatched with dynamic DN expansion
- Add RuleRunRepository persisting rule_runs and rule_run_actions
- Add Runner coordinator that loads rule+connection, builds an LDAP client,
invokes the engine, and records the run + per-action outcomes
- Expose ConnectionService.BuildClient / BuildLDAPConfig for reuse
- Scheduler now accepts a RuleRunner and invokes it when a scheduled rule fires
- Next.js 14 with App Router
- TypeScript strict mode
- Tailwind CSS with dark mode support
- React Query for server state
- NextAuth.js integration ready
- Dashboard layout with sidebar navigation
- API client with error handling
- Core type definitions for all entities
- Utility functions for dates and classnames
- Rule engine with preview and condition evaluation
- LDAP filter generation from rule conditions
- Connection service with full test workflow
- Credential service with encryption/decryption
- Rule service with validation
- Backup service with retention management
- Integration between services and repositories
- API response helpers and error codes
- Authentication handlers (login, logout, me, csrf)
- Auth middleware (session validation, role checks, CSRF)
- LDAP client with TLS/StartTLS support
- LDAP filter construction from conditions
- AD operations (group membership, move, create group/OU)
- Credentials repository (CRUD, test results, usage check)
- AD connections repository (CRUD, test results)
- Schedules repository (CRUD, next run tracking)
- Rules repository with nested condition groups and actions
- go-ldap/ldap/v3 dependency added
Phase 1 foundations:
- Go backend with Chi router framework
- SQLite database with WAL mode and foreign keys
- Database migrations for users, roles, credentials, AD connections, schedules, rules, and audit
- CLI commands: init, run, install, uninstall, start, stop, migrate, backup, restore, doctor
- Configuration loading from environment variables
- Centralized logging with file rotation (lumberjack)
- Crypto package for Argon2id password hashing and AES-GCM encryption
- Auth service with session management
- Audit service for event logging
- Scheduler with 6-field cron support
- REST API routes scaffolded for all major resources
- CORS support with localhost defaults for development
- Docker support with Dockerfile and docker-compose.yml
- Multi-platform build script (PowerShell)
- Project structure per design specification
Version format: yyyy.MM.dd.HHmm
All PKs are UUIDv4, all timestamps UTC