Files
ADconsle/CLAUDE/AGENTS.md
T
kzbkowskiandClaude Sonnet 5 1126d96271
CI / PHP 8.2 (push) Failing after 2m46s
CI / PHP 8.3 (push) Failing after 59s
CI / PHP 8.4 (push) Failing after 1m7s
ADconsole v1.0.0
First public release.

- docs: document the audit log, user offboarding, CSV export and the
  "require a reason for destructive actions" setting across README, docs/
  and CLAUDE/AGENTS.md; note retention for panel_audit
- docs: fill the publishing placeholders (repo URL, security contact,
  issue-template links) and add a semantic-versioning policy
- move agent/contributor context into CLAUDE/ (AGENTS.md + a README);
  root CLAUDE.md is now a thin @-import pointer
- add a favicon (shield-lock, matching the login screen) to the login
  page and the app layout
- CHANGELOG: promote [Unreleased] to [1.0.0]; keep the earlier internal
  build as [0.1.0]

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UfuvfwexztdS7LDpGuKsuK
2026-09-08 23:14:39 +02:00

3.9 KiB

AGENTS.md — working on ADconsole

Context for AI coding agents and new contributors. Keep it accurate when you change the architecture.

What this is

A Laravel 11 + LdapRecord web panel that manages an Active Directory domain: users, computers, groups and read-only GPO, plus a dashboard and an org chart. PHP 8.2+. Interface is PL/EN.

Golden rules

  1. No SQL storage for AD objects. Every read/write of a user, computer or group goes through LdapRecord straight to a domain controller. The database (panel_settings + panel_attributes + panel_audit, plus Laravel's sessions / cache / jobs) backs the application layer only. panel_audit records what the panel did to AD — it is not a mirror of AD state.
  2. Auth is the ldap guard (LdapRecord plain-bind, no local accounts). Only members of AD_LOGIN_GROUP may sign in (App\Ldap\Rules\MemberOfLoginGroup, honours nested + primary group). Every panel route is behind auth:ldap; the admin profile lives in the session key ad_admin.
  3. i18n everywhere. User-facing strings come from lang/{pl,en}/*.php via __('namespace.key'). Never hard-code copy in Blade/PHP. Add a key to both locales. Default locale is pl; config/locales.php is the single source of the available-language list.
  4. Some lang/pl/* values are asserted verbatim by tests (e.g. tests/Feature/AttributeConfigTest). Changing an existing PL string can break a test — check before editing.
  5. Docroot is public/. Do not add .htaccess deny rules elsewhere as a substitute.

Layout

Path Role
app/Http/Controllers/Admin/* one controller per module (Users, Computers, Groups, Gpo, OrgChart, Dashboard, Audit, Config)
app/Ldap/User.php AD user model + attribute map + toPanelProfile()
app/Ldap/Rules/MemberOfLoginGroup.php login authorisation rule
app/Services/ PanelSettingsService (config, DB-backed), AttributeCipher, LdapAttributeHelper (UAC bits, FileTime), OuTreeService (cached OU tree), AuditLogger (writes panel_audit; never throws — a log failure is only report()ed)
app/Models/PanelSetting.php key→JSON row: general panel config (panel_settings)
app/Models/PanelAttribute.php one row per configured AD attribute (panel_attributes, ordered by position)
app/Models/AuditLog.php one row per audited panel action (panel_audit); written only via AuditLogger, read only by AuditController
config/ldap.php connection, auth.login_group, default OUs, attribute map
resources/views/admin/* Blade views; shared bits in components/ + partials/
public/css/style.css, public/js/main.js hand-written assets loaded directly (no Vite build needed)
routes/web.php all routes; English URL segments and route names

Configuration

  • Deployment config → .env (see .env.example for every key). Read-only at runtime; nothing writes back to it.
  • In-app config (/settings) → via PanelSettingsService:
    • general settings (password policy / generator, reset-dialog defaults, attribute-encryption key, audit.require_reason) → one JSON row in panel_settings;
    • AD attribute / column definitions → one row each in panel_attributes (columns: key, label, ldap, category, type, is_column, position). Both fall back to PanelSettingsService::defaults() / defaultAttributes() when empty.

Running things

composer install
cp .env.example .env && php artisan key:generate
php artisan migrate
php artisan test          # SQLite :memory:, ~40 tests
vendor/bin/pint           # code style

php artisan test prints a harmless PHP 8.5 PDO::MYSQL_ATTR_SSL_CA deprecation that PHPUnit flags on every test as DEPR — that is not a failure.

See docs/ for installation, AD setup, deployment, architecture and troubleshooting.