Skip to content

S61 — phlix-server CLI user:* commands with --json + last-admin guard - #742

Merged
detain merged 2 commits into
masterfrom
s61srv-s61-cli-commands
Sep 9, 2026
Merged

S61 — phlix-server CLI user:* commands with --json + last-admin guard#742
detain merged 2 commits into
masterfrom
s61srv-s61-cli-commands

Conversation

@detain

@detain detain commented Sep 9, 2026

Copy link
Copy Markdown
Owner

S61 — phlix-server: CLI user:* commands with --json + last-admin guard

Step S61 (lane s61srv). Adds operator-facing console commands for user
management with a machine-readable --json contract, and the in-repository
last-admin guard consumed by the destructive/revoke paths.

What ships

  • src/Console/Commands/Concerns/JsonOutput.php — per-repo --json helper.
    Success renders {"ok":true,"data":[...]}, failure {"ok":false,"error":"..."}.
    This is the server-side copy; the hub ships an identical helper as its own
    second copy (deliberately not pushed into detain/phlix-shared, per ruling
    R6).
  • src/Auth/UserRepository.phpcountAdmins() and isLastAdmin()
    (SELECT-only; no writes, no migration).
  • Seven commands registered in bin/phlix via a lazy UserRepository factory:
    user:list (--status filter, sensitive columns redacted),
    user:create, user:promote (--revoke), user:delete (--force),
    user:approve, user:disable, user:reject.
  • Per-command CommandTester tests with and without --json, plus
    UserRepositoryAdminTest additions (count predicate, isLastAdmin true/false,
    non-admin short-circuit asserting query is never called).

Last-admin guard (absolute)

The destructive/revoke paths refuse to strip the final admin:
--force bypasses the confirmation step, never the guard. Tests prove both
the plain rejection and that --force is still rejected for the last admin.

Scope guards (rulings honoured)

  • CLI only — zero HTTP route changes (R1). No controller/route/middleware
    edits; the AdminUserController endpoints are untouched.
  • No migrations in this repo (R2).
  • Census re-pinned to the post-change PHP file count in the same commit.

Verification (local, CI-faithful venue)

  • Full Unit test suite: OK (10566 tests, 73888 assertions, 5 skipped) — the
    5 skips are all environment-dependent (Workerman timer ×3, mysqldump, FFI).
  • phpstan analyze src/ --level=9 → no errors; phpstan -c phpstan-tests.neon → no errors.
  • phpcs --standard=PSR12 src/ → 0; per-command test files add 0 errors/0 warnings.
  • assertion-escape-check.php → no escapes; assertion-escape-audit.php --probe → exit 0, undecided set matches baseline.
  • security-audit-check.php → no advisories; composer validate --strict → valid.
  • Survival marker asserted code-resident via the tokenized (php_strip_whitespace) corpus scan and absent from every *.md.

Adds seven user console commands (list, create, promote, delete,
approve, disable, reject) each honouring a shared --json contract, and
the in-repository last-admin guard consumed by the destructive/revoke
paths.

- src/Console/Commands/Concerns/JsonOutput.php: per-repo --json helper
  (success {"ok":true,"data":[...]}, failure {"ok":false,"error":...}).
- src/Auth/UserRepository.php: countAdmins() + isLastAdmin() (SELECT-only).
- bin/phlix: register the seven commands via the UserRepository factory.
- tests/Unit/Console/Commands/*: per-command CommandTester coverage,
  with/without --json, and guard proofs (rejection AND --force-still-rejected).
- Census re-pinned to the post-change PHP file count.

CLI-only: no HTTP route changes, no migrations.
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@codacy-production

codacy-production Bot commented Sep 9, 2026

Copy link
Copy Markdown

Not up to standards ⛔

🔴 Issues 12 medium · 88 minor

Alerts:
⚠ 100 issues (≤ 0 issues of at least minor severity)

Results:
100 new issues

Category Results
Documentation 15 minor
ErrorProne 7 medium
Comprehensibility 7 minor
CodeStyle 66 minor
Complexity 5 medium

View in Codacy

🟢 Metrics 193 complexity · 6 duplication

Metric Results
Complexity 193
Duplication 6

View in Codacy

🟢 Coverage 91.87% diff coverage · +0.12% coverage variation

Metric Results
Coverage variation +0.12% coverage variation (-1.00%)
Diff coverage 91.87% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (798adc4) 66835 47960 71.76%
Head commit (159ca71) 67204 (+369) 48307 (+347) 71.88% (+0.12%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#742) 369 339 91.87%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codecov

codecov Bot commented Sep 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.09524% with 29 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.72%. Comparing base (798adc4) to head (159ca71).

Files with missing lines Patch % Lines
src/Console/Commands/UserListCommand.php 91.78% 6 Missing ⚠️
src/Console/Commands/UserCreateCommand.php 93.82% 5 Missing ⚠️
src/Console/Commands/UserApproveCommand.php 90.69% 4 Missing ⚠️
src/Console/Commands/UserDisableCommand.php 91.11% 4 Missing ⚠️
src/Console/Commands/UserRejectCommand.php 92.15% 4 Missing ⚠️
src/Console/Commands/UserDeleteCommand.php 94.73% 3 Missing ⚠️
src/Console/Commands/UserPromoteCommand.php 93.75% 3 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master     #742      +/-   ##
============================================
+ Coverage     72.59%   72.72%   +0.13%     
- Complexity    22863    23008     +145     
============================================
  Files           711      719       +8     
  Lines         71267    71687     +420     
============================================
+ Hits          51738    52137     +399     
- Misses        19529    19550      +21     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@detain detain added the needs-coordinator PARKED lane: blocked, not failed — coordinator decides next action label Sep 9, 2026
Line 225 carried a 5-space indent from the re-pin; the sibling census
consts use 4. Aligning it clears the sole PHP CodeSniffer error (0 errors,
warnings unchanged). CI-faithful: verified with the vendored phpcs 3.13.6.
@detain
detain merged commit ff8cac9 into master Sep 9, 2026
21 of 22 checks passed
@detain
detain deleted the s61srv-s61-cli-commands branch September 9, 2026 04:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-coordinator PARKED lane: blocked, not failed — coordinator decides next action

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant