# Drop `programs.authorName` column; author is provenance, not a field

**Filed:** Batch 56, 2026-08-02.
**Status:** deferred to post-demo (requires migration).

## Problem

`programs.authorName varchar(191)` is a frozen name snapshot maintained
alongside `programs.created_by` (FK → `users.id`). It duplicates
information, goes stale if the creator is renamed, and is fragile:

- `ProgramController::store` writes it on INSERT only, from
  `Auth::user()->first_name ?? name ?? ''` — but `users` has neither
  `first_name` nor `name`, so for real user-created programs it always
  writes `''`. Non-empty values in the wild come from seeders that set
  the column directly.
- `ProgramController::store` never writes it on UPDATE (not in the
  validator), so edits don't corrupt it. But that's an implicit
  contract that could be broken by an unrelated form change.
- The column reads as "author on record" but is not actually the
  author of record — `created_by` is.

## Interim (Batch 56)

- `ProgramController::index` and `ProgramController::libraryMetrics`
  now derive `authorName` server-side from
  `LEFT JOIN users ON users.id = programs.created_by
   LEFT JOIN teams ON teams.id = users.staffId`
  using `teamFirstName + teamLastName`, falling back to
  `programs.authorName` (for rows whose creator was deleted or for
  seed rows with only the frozen column), finally to `users.username`.
  The FE reads the same key (`authorName`) — no FE change required.
- The frozen column stays populated for now so the fallback keeps
  working for the seeded demo program.

## Post-demo target

1. Migration removes `programs.authorName`.
2. `ProgramController::store` drops the `$authorName = ...` line and
   the `'authorName' => $authorName` INSERT key.
3. Both list endpoints drop the fallback and select
   `authorDisplayName` directly.
4. Seeder stops setting `authorName`.
5. Any dashboard/report reading `programs.authorName` gets the same
   join treatment.

## Related

- Batch 42 introduced the Tags + Author columns in the Library list.
- Batch 56 §1 fixed the empty-render bug (metrics projection was
  missing tags + authorName).
- `docs/post-demo/aba-staff-designation.md` — analogous pattern:
  replace inferred/duplicated data with an explicit source of truth.
