Regression from PR #83: creating a personal invite stored nothing (empty Pending Invites) while still displaying a registration link that could only dead-end as "invalid or expired."
Schema.php gained kind and expires_at on us_invites and InviteRepository::insert() started writing them — but USC_VERSION stayed at 1.0.0-rc.2. Plugin::boot() only re-runs Installer/dbDelta when the stored version differs, so upgraded sites never got the new columns and wpdb->insert failed silently on every invite.
Fix
Version bump to 1.0.0-rc.3 (header + USC_VERSION) — the next page load runs dbDelta and adds the columns. No manual action needed after deploying; the failed invites were never stored, so just re-create them.
Never show a dead link again:InviteRepository::insert() now returns 0 on failure (instead of a stale insert_id), and the Invites page shows an error notice instead of a link when the insert fails — for both the personal and group forms. Validation failures (bad email / existing account / pending invite / past expiry date) also get explicit error notices instead of silently doing nothing.
CLAUDE.md now calls out that any Schema.php change requires the version bump, so this class of bug doesn't recur.
Tests
New InviteRepositoryTest::testInsertReturnsZeroWhenDbInsertFails.
composer test — 410 tests pass; composer lint (PHPStan level 10) and composer cs clean.
Closes #87
## What happened
Regression from PR #83: creating a personal invite stored nothing (empty Pending Invites) while still displaying a registration link that could only dead-end as "invalid or expired."
`Schema.php` gained `kind` and `expires_at` on `us_invites` and `InviteRepository::insert()` started writing them — but `USC_VERSION` stayed at `1.0.0-rc.2`. `Plugin::boot()` only re-runs `Installer`/`dbDelta` when the stored version differs, so upgraded sites never got the new columns and `wpdb->insert` failed silently on every invite.
## Fix
- **Version bump** to `1.0.0-rc.3` (header + `USC_VERSION`) — the next page load runs `dbDelta` and adds the columns. No manual action needed after deploying; the failed invites were never stored, so just re-create them.
- **Never show a dead link again:** `InviteRepository::insert()` now returns 0 on failure (instead of a stale `insert_id`), and the Invites page shows an error notice instead of a link when the insert fails — for both the personal and group forms. Validation failures (bad email / existing account / pending invite / past expiry date) also get explicit error notices instead of silently doing nothing.
- `CLAUDE.md` now calls out that any `Schema.php` change requires the version bump, so this class of bug doesn't recur.
## Tests
- New `InviteRepositoryTest::testInsertReturnsZeroWhenDbInsertFails`.
- `composer test` — 410 tests pass; `composer lint` (PHPStan level 10) and `composer cs` clean.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
PR #83 added kind and expires_at to us_invites and the repository started
writing them, but USC_VERSION stayed at 1.0.0-rc.2 — Plugin::boot() only
re-runs Installer/dbDelta on a version mismatch, so upgraded sites never got
the columns. Every invite insert then failed silently: nothing appeared under
Pending Invites while the admin was still shown a registration link whose
token hash was never stored.
- Version / USC_VERSION -> 1.0.0-rc.3 (triggers dbDelta on next load).
- InviteRepository::insert() returns 0 on failure instead of a stale
insert_id, and the Invites page now shows an error notice instead of a
dead link when creation fails (personal and group forms), including
clearer validation messages.
- CLAUDE.md: schema changes must bump the version.
Closes#87
Co-Authored-By: Claude Fable 5 <[email protected]>
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Closes #87
What happened
Regression from PR #83: creating a personal invite stored nothing (empty Pending Invites) while still displaying a registration link that could only dead-end as "invalid or expired."
Schema.phpgainedkindandexpires_atonus_invitesandInviteRepository::insert()started writing them — butUSC_VERSIONstayed at1.0.0-rc.2.Plugin::boot()only re-runsInstaller/dbDeltawhen the stored version differs, so upgraded sites never got the new columns andwpdb->insertfailed silently on every invite.Fix
1.0.0-rc.3(header +USC_VERSION) — the next page load runsdbDeltaand adds the columns. No manual action needed after deploying; the failed invites were never stored, so just re-create them.InviteRepository::insert()now returns 0 on failure (instead of a staleinsert_id), and the Invites page shows an error notice instead of a link when the insert fails — for both the personal and group forms. Validation failures (bad email / existing account / pending invite / past expiry date) also get explicit error notices instead of silently doing nothing.CLAUDE.mdnow calls out that anySchema.phpchange requires the version bump, so this class of bug doesn't recur.Tests
InviteRepositoryTest::testInsertReturnsZeroWhenDbInsertFails.composer test— 410 tests pass;composer lint(PHPStan level 10) andcomposer csclean.🤖 Generated with Claude Code