# Project Coding Standards

`AGENTS.md` is intentionally stored at the repository root so Codex and future coding agents can discover project standards before modifying code.

## Project Architecture

- This is a CodeIgniter 4 PHP application. Follow CodeIgniter 4 MVC structure and conventions.
- Keep controllers thin. Controllers should orchestrate requests, validation, services/models, responses, flash messages, redirects, and views.
- Put presentation markup in Views.
- Put reusable business logic in Services or Libraries.
- Put database access and query logic in Models or focused query/service classes where practical.
- Use CodeIgniter request, response, session, validation, migration, seeder, and model conventions.
- Do not build large HTML strings in controllers.
- Do not mix unrelated responsibilities in one class or method.
- Prefer small, focused services over large controller methods.
- Preserve existing route URLs where practical when refactoring.

## PHP Formatting

### Indentation

- Use 2 spaces per indent level in all project code and documentation examples.
- Do not use tabs or 4-space indentation in project files.
- This applies to PHP, Views, HTML, CSS, JavaScript, JSON, configuration examples, and code snippets unless an external format requires otherwise.
- Preserve deliberate alignment where it improves readability, but use 2 spaces for normal nested blocks.
- When editing existing files, normalize indentation in the sections being changed. Do not create broad unrelated indentation-only churn.

- Use same-line opening braces for classes, methods, functions, conditionals, loops, and `try`/`catch` blocks.

Preferred:

```php
public function getMethod(): string {
  return 'POST';
}
```

Not preferred:

```php
public function getMethod(): string
{
  return 'POST';
}
```

- Keep methods small and readable.
- Avoid compressed one-line control structures.
- Do not place multiple unrelated statements on one line.
- Use clear variable names.
- Avoid unnecessary cleverness.
- Prefer explicit, readable code over compact code.
- Avoid broad refactors while doing targeted fixes.
- Keep comments useful; do not add noisy comments that simply repeat the code.

## CodeIgniter Controller Standards

Controllers should:

- Validate input.
- Call services and models.
- Set flash messages.
- Redirect after successful POST actions.
- Return Views or CodeIgniter Response objects.
- Use CodeIgniter request, response, and session helpers.
- Keep methods focused and readable.

Controllers should not:

- Concatenate large HTML strings.
- Output full pages with `echo` or `print`.
- Contain large repeated query blocks when a Model, Service, or focused query class is practical.
- Perform presentation formatting that belongs in a View.
- Perform unrelated business workflows in the same method.
- Access `$_GET`, `$_POST`, or `$_REQUEST` directly when CodeIgniter request helpers are available.

## CodeIgniter View Standards

### Frontend CSS

- Bootstrap 5 remains the component framework for forms, buttons, tables, modals, dropdowns, offcanvas navigation, and other established components.
- Tailwind CSS v4 utilities may be used for layout and presentation. All Tailwind utilities must use the `tw:` prefix, and Tailwind Preflight must remain disabled.
- Prefer Tailwind utilities over trivial one-off CSS, but do not convert stable Bootstrap components without a dedicated reason.
- Write complete Tailwind class names in source; do not construct class-name fragments dynamically.
- Run `npm run css:build` after changing Tailwind classes, and continue running `composer lint:views` for View changes.

- Keep every PHP View under `app/Views/` human-readable. A View that is syntactically valid but collapsed or badly formatted is not complete.
- Follow the rule: **compact individual elements, expanded structural markup**.
- Put structural elements on normally indented lines. Cards, card headers and bodies, Bootstrap rows and columns, forms, tables, table sections and rows, lists, modals, navigation, and large grouped sections must remain visually identifiable.
- Never place an entire card, form, table row, Bootstrap grid, loop, or section on one physical line. Do not minify Views merely to reduce line count.
- Put View-level `if`/`elseif`/`else`/`endif`, `foreach`/`endforeach`, and similar control structures on logical lines, indented with the HTML they control. Do not place substantial structural HTML after an opening control or before its closing control on the same line.
- Keep ordinary individual labels, inputs, buttons, badges, anchors, table cells, and short selects on one line when they fit comfortably. This compact-element rule never justifies collapsing the surrounding column, row, form, table, loop, card, or section.
- Do not format normal Bootstrap controls with one attribute per line. If an element is genuinely too complex for one readable line, split its attributes into a few logical groups.
- Section comments are encouraged for navigation, but they are not a reason to spread individual controls across excessive lines.
- Use `esc()` for rendered output.
- Use `csrf_field()` in forms.
- Prefer Bootstrap classes over inline styles.
- Avoid unnecessary inline styles. Keep small inline styles only where already necessary and justified.

Acceptable PHP in Views includes:

- `$this->extend()`
- `$this->section()`
- `$this->endSection()`
- `if` / `endif`
- `foreach` / `endforeach`
- `esc()`
- `csrf_field()`
- `old()`
- `site_url()`
- Simple date or number display formatting

The following are not acceptable in Views:

- Database queries
- Business logic
- Authentication decisions beyond rendering passed flags or data
- Large string building
- Compressed one-line forms or tables
- Controller-like workflow logic

Preferred View style:

```php
<?php if ($message = session()->getFlashdata('success')): ?>
  <div class="alert alert-success"><?= esc($message) ?></div>
<?php endif; ?>

<div class="card mb-4">
  <div class="card-header">Create local user</div>

  <div class="card-body">
    <form method="post" action="<?= site_url('dashboard/users') ?>" class="row g-3">
      <?= csrf_field() ?>

      <div class="col-md-2">
        <label class="form-label" for="username">Username</label>
        <input class="form-control" id="username" name="username" required maxlength="100">
      </div>

      <div class="col-md-1 form-check align-self-end mb-2">
        <input class="form-check-input" id="new-active" type="checkbox" name="is_active" checked>
        <label class="form-check-label" for="new-active">Active</label>
      </div>

      <div class="col-md-1 align-self-end">
        <button class="btn btn-primary" type="submit">Create</button>
      </div>
    </form>
  </div>
</div>
```

This is the required balance: readable block layout, normal short elements kept compact, no compressed structural markup, and no excessive attribute-per-line formatting.

Avoid this:

```html
<button
  class="btn btn-outline-primary"
  type="button"
  data-bs-toggle="collapse"
  data-bs-target="#companyInformationForm"
>
```

Prefer this:

```html
<button class="btn btn-outline-primary" type="button" data-bs-toggle="collapse" data-bs-target="#companyInformationForm">
```

## Services, Libraries, and Models

- Put reusable business logic in Services or Libraries.
- Put database access in Models or focused query classes where practical.
- Keep services focused on one area of responsibility.
- Avoid services that render HTML.
- Avoid models that contain presentation logic.
- Prefer testable methods with clear inputs and outputs.
- Do not duplicate important status maps, role lists, or permission rules across controllers.

## Comments and Readability

- Comment complex workflow code to explain intent, stage boundaries, and non-obvious handoffs.
- Use section comments in Views for major UI blocks, especially role-sensitive sections.
- Explain security-sensitive decisions and non-obvious file or path handling near the relevant code.
- Comments should explain why a block exists, not restate obvious syntax.
- Do not use comments to hide unclear structure; keep the underlying code focused and readable.

## Security and Authentication

- Never store plaintext passwords.
- Use `password_hash()` for local password storage.
- Use `password_verify()` for local password checks.
- Regenerate the session after a successful login.
- Do not log plaintext passwords.
- Do not expose whether a username exists in failed-login messages.
- Audit login, logout, failed login, and sensitive user-management actions.
- Include timestamp, username/user ID where known, role where known, IP address, user agent, route/method where practical, and useful context.
- Local `super_admin` users are for full administrative access.
- LDAP/AD authentication, when implemented, must query LDAP on every login.
- Locally cached LDAP users are for identity, history, reporting, and audit logs only.
- Locally cached LDAP users must not be used for LDAP password authentication.
- Centralize AD group-to-role mapping when it is implemented.

Planned role keys:

- `super_admin`
- `admin`
- `manager`
- `user`
- `dashboard`
- `customer`

## Diagnostics and Test Routes

- Public prototype or test routes must not expose customer data or trigger expensive work without protection.
- Put diagnostic routes behind `adminAuth` and an explicit feature flag where practical.
- Diagnostic Views must still follow MVC and View formatting standards.
- Do not leave CodeIgniter debug toolbar or Kint artifacts in generated PDF HTML.
- Keep useful diagnostics, but isolate them from production user flows.

## Audit Logging and Timestamps

- Timestamp sensitive actions.
- Log start, stop, delete, cancel, and retry actions where practical.
- Log authentication events.
- Log user-management events.
- Do not log secrets, passwords, LDAP credentials, private keys, or full sensitive payloads.
- Prefer structured `context_json` for additional metadata.

## Workflow and Git Standards

- Keep changes scoped to the requested task.
- Use small branches.
- Do not refactor unrelated systems.
- When a task is complete, provide validation commands, test commands, a commit command, commit message and body, push command, merge or PR title, merge or PR comment, and local merge commands.
- Run `php spark test` or `vendor/bin/phpunit` where practical.

Before completing a task that creates or changes a View:

- Review every modified file under `app/Views/` for readable nesting and control-structure placement.
- Run `composer lint:views`. Fix violations; do not weaken the lint to excuse collapsed markup.
- Confirm ordinary controls were not expanded into unnecessary one-attribute-per-line markup.

Before completing any code task, run the checks relevant to its scope. Do not weaken existing project checks:

```bash
git status
git diff --stat
git diff --check
find app tests -name "*.php" -print0 | xargs -0 -n1 php -l
composer lint:views
vendor/bin/phpunit
```

Also run `node --check` for each changed shared JavaScript file and the applicable migration commands when database migrations are in scope.

Report the commands and results. A passing PHP syntax check does not compensate for an unreadable View.

