Skip to content

feat(user): add name and status fields per ADR 006 (#45, #83)#86

Open
martinydeAI wants to merge 5 commits into
developfrom
feature/issue-45-user-entity-extension
Open

feat(user): add name and status fields per ADR 006 (#45, #83)#86
martinydeAI wants to merge 5 commits into
developfrom
feature/issue-45-user-entity-extension

Conversation

@martinydeAI

@martinydeAI martinydeAI commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Links to issues

Closes #45.
Closes #83.

Description

Adds the User-entity work of ADR 006:

  • New App\Enum\UserStatus (pending | approved | blocked).
  • New columns on App\Entity\User: name: string (display name)
    and status: UserStatus.
  • UserManager::createUser() now requires a name argument and
    accepts an optional status (defaults to Approved for the
    console + fixture path; the registration flow in feat: anonymous self-signup with email-domain allow-list #62 will pass
    Pending explicitly).
  • app:user:create console command grows a third name
    positional argument.
  • UserFixtures seeds Alice + Bob with display names.
  • Single Doctrine migration adds both columns with SQL defaults
    (name = '', status = 'approved') so existing rows in
    long-running environments backfill cleanly.

Combines two issues (#45 User.name + #83 UserStatus enum + status
field) in one PR since the migration is most coherent as a single
ALTER TABLE and the entity tests would fight if either landed
without the other.

Screenshot of the result

n/a — schema + service-signature change, no UI.

Checklist

  • My code is covered by test cases.
  • My code passes our test (all our tests).
  • My code passes our static analysis suite.
  • My code passes our continuous integration process.

Verified locally:

  • task coding-standards-check — PHP CS Fixer, Twig CS Fixer,
    Prettier (YAML / JS / CSS), markdownlint, composer validate +
    normalize — all green.
  • task test-coverage — 51 tests, 186 assertions, 100 %
    coverage
    .

Additional comments or questions

The migration uses column-level SQL defaults so that environments
already carrying user rows backfill without a separate UPDATE step.
The ORM metadata does not declare those defaults (so new rows go
through the constructor / setters as before); the discrepancy is
intentional and only visible to doctrine:schema:validate — not
enforced in CI.

UserManager::createUser()'s name argument is required
rather than nullable-with-default. The alternative (empty-string
default) was considered and rejected: a blank display name would
bleed into the admin user list (PR 5, #64+#85) as empty cells with
no way to tell apart a deliberately-empty row from an
incorrectly-created one. Required-with-empty-allowed is the
strictest contract that still keeps the call sites ergonomic.


Details - AI specificities

Lands the User-entity work of ADR 006 — a `UserStatus` PHP enum
(`pending | approved | blocked`) and a matching `status` column on
the entity, plus the long-pending `name` display column. The
`UserManager::createUser()` service grows a required `name` argument
and an optional `status` (defaults to `Approved` for the console /
fixture path; the registration flow in #62 will pass `Pending`).
The `app:user:create` console command grows a third `name`
argument; fixtures seed Alice + Bob with display names.

A single migration adds both columns with a default value so
existing rows in long-running environments backfill cleanly:
`name = ''` and `status = 'approved'` (historic rows are assumed
already-trusted accounts).

Combines #45 (User.name) and #83 (UserStatus enum + status field)
in one PR, since the migration is most coherent as a single ALTER
TABLE and the entity tests fight if either field lands without the
other. Sequenced as PR 1 of the User management milestone plan
(`docs/plans/user-management-milestone.md`, written locally) —
PR 3 (UserChecker, #63) and PR 4 (Registration, #62) stack on top
of this branch with `do-not-merge` labels until it merges.

Closes #45.
Closes #83.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
{
$user = $schema->getTable('user');
$user->addColumn('name', Types::STRING, ['length' => 255, 'notnull' => true, 'default' => '']);
$user->addColumn('status', Types::STRING, ['length' => 32, 'notnull' => true, 'default' => 'approved']);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should default be "approved" in db context?
@tuj ?

Comment thread CHANGELOG.md Outdated
martinyde and others added 2 commits June 19, 2026 11:04
Updated migration comment to remove ADR reference.
Per review on PR #86 - keep the CHANGELOG entry to what was added
and the issue references; details belong in the PR description.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread tests/Integration/Repository/UserRepositoryTest.php
Comment thread tests/Integration/Security/UserManagerTest.php
Comment thread tests/Unit/Entity/UserTest.php
Per review on PR #86 - apply the test-comment convention to every
test method in UserTest, UserManagerTest, and UserRepositoryTest.
Each method now opens with a single-line "Tests ...", "Ensures ...",
or "Verifies ..." comment naming what it asserts.

Pure documentation change - no test logic touched.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@martinyde martinyde requested review from martinyde and tuj June 19, 2026 10:52
@martinyde martinyde removed their request for review June 19, 2026 10:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: UserStatus enum and User.status field feat: add User.name field (rescoped per ADR 006)

2 participants