Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
6b7cbf1
docs(changelog): backfill the 6.37.0 release commit reference (#1681)
rpgmem Oct 12, 2026
a986ca7
fix(identity): fold a person's duplicate candidacy when consolidating…
rpgmem Oct 12, 2026
8344cfe
fix(recruitment): the CSV import honours the RF check digit setting (…
rpgmem Oct 12, 2026
6592438
feat(identity): name each number on the shared-address panel (#1687)
rpgmem Oct 12, 2026
8c6526e
docs: a standard for issues, pull requests and the merge queue (#1689)
rpgmem Oct 12, 2026
82042ba
docs(claude): a PR carries the labels of the issue it closes (#1691)
rpgmem Oct 12, 2026
e8b356e
chore(deps)(deps-dev): bump phpstan/phpstan from 2.2.16 to 2.3.1 (#1692)
dependabot[bot] Oct 12, 2026
49068a4
chore(deps)(deps-dev): bump eslint from 10.11.0 to 10.12.0 (#1693)
dependabot[bot] Oct 12, 2026
53b8ab7
chore(deps)(deps-dev): bump jsdom from 30.1.1 to 30.1.2 (#1694)
dependabot[bot] Oct 12, 2026
27db535
chore(license): add LICENSE, move to AGPLv3 or later and hold the dec…
rpgmem Oct 12, 2026
e470c82
test(audience): cover audience, recruitment and reregistration error …
rpgmem Oct 12, 2026
bdb8e44
test(certificates): cover certificate templates, form editor and sett…
rpgmem Oct 12, 2026
b617e2e
test(identity): cover identity resolution, migrations and encryption …
rpgmem Oct 12, 2026
1acd6ba
fix(ci): run the CI, lint, PHPCS and assets workflows with a read-onl…
rpgmem Oct 12, 2026
fe96a8a
chore(ci): raise the PHP coverage floor to 90% (#1705)
rpgmem Oct 12, 2026
feff1b2
fix(reregistration): open the screen to a manage-only role (#1706)
rpgmem Oct 12, 2026
984a496
refactor(certificates): drop the unreachable empty-link branch in the…
rpgmem Oct 12, 2026
6a60a19
test: make twelve "never called" checks verify something (#1708)
rpgmem Oct 12, 2026
10e7090
release: 6.38.0 — bump + finalize CHANGELOG (#1709)
rpgmem Oct 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,25 @@ body:
validations:
required: true

- type: dropdown
id: area
attributes:
label: Area
description: The part of the plugin the problem is in. The maintainer applies the matching `area:` label.
options:
- Certificates
- Scheduling
- Reregistration
- Recruitment
- Short URLs
- Date Messages
- Settings
- Identity resolution
- Infrastructure (CI, build, release)
- Not sure
validations:
required: true

- type: textarea
id: reproduction
attributes:
Expand All @@ -42,7 +61,7 @@ body:
id: plugin-version
attributes:
label: Plugin version
placeholder: "5.1.0"
placeholder: "6.37.0"
validations:
required: true

Expand All @@ -58,7 +77,7 @@ body:
id: php-version
attributes:
label: PHP version
placeholder: "8.1"
placeholder: "8.3"
validations:
required: true

Expand Down
19 changes: 19 additions & 0 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,25 @@ body:
validations:
required: true

- type: dropdown
id: area
attributes:
label: Area
description: The part of the plugin the problem is in. The maintainer applies the matching `area:` label.
options:
- Certificates
- Scheduling
- Reregistration
- Recruitment
- Short URLs
- Date Messages
- Settings
- Identity resolution
- Infrastructure (CI, build, release)
- Not sure
validations:
required: true

- type: textarea
id: proposal
attributes:
Expand Down
79 changes: 79 additions & 0 deletions .github/ISSUE_TEMPLATE/task.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: Task
description: Internal work — a defect found by measurement, tech debt, an audit, maintenance
title: "<Area>: <the problem in one sentence>"
labels: ["task"]
body:
- type: markdown
attributes:
value: |
For work the maintainer or an agent will pick up. Write it in English, and
state what was **measured**, not what is suspected: a number, a query, a
failing test, a screenshot. The acceptance criteria are ticked, or named
as deferred, when the issue closes — `CLAUDE.md` → "Closing an issue".

- type: dropdown
id: area
attributes:
label: Area
description: The part of the plugin the work is in. The maintainer applies the matching `area:` label.
options:
- Certificates
- Scheduling
- Reregistration
- Recruitment
- Short URLs
- Date Messages
- Settings
- Identity resolution
- Infrastructure (CI, build, release)
- Not sure
validations:
required: true

- type: textarea
id: problem
attributes:
label: Problem
description: What is wrong or missing, and why it matters to an operator or to the code.
validations:
required: true

- type: textarea
id: evidence
attributes:
label: Evidence
description: What was measured — counts, file:line references, a reproduction, the failing check.
validations:
required: true

- type: textarea
id: scope
attributes:
label: Scope
description: What the change will do, and what it deliberately will not (out of scope).
value: |
**In scope**
-

**Out of scope**
-
validations:
required: true

- type: textarea
id: acceptance
attributes:
label: Acceptance criteria
description: Checkboxes the closing PR must satisfy.
value: |
- [ ]
validations:
required: true

- type: textarea
id: related
attributes:
label: Related
description: Issues, PRs or precedents this builds on.
validations:
required: false
55 changes: 34 additions & 21 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,31 +1,44 @@
<!-- Thanks for the contribution! Please fill in the sections below. -->
<!--
Title: `type(scope): summary` — type is feat, fix, docs, test, refactor or chore;
scope is the area (identity, recruitment, scheduling, …). It becomes the squash
subject on `develop`. Base branch: `develop`. Write in English.
Release PRs use the release template: append `?template=release.md` to the
compare URL.
-->

## Summary
Closes #

<!-- 1-3 bullets describing the change and motivation. -->
<!-- Every PR names its issue. Exempt: trivial docs or chore, Dependabot, the
`release: X.Y.Z` bump and the CHANGELOG SHA backfill. `Closes` does not
auto-close on `develop`: the issue is closed by hand after the merge. -->

## Type of change
## Problem

- [ ] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would alter existing behavior)
- [ ] Refactor / chore (no functional change)
- [ ] Documentation only
<!-- What was wrong or missing, as measured. -->

## Test plan
## Change

<!-- Bulleted checklist of tests performed (manual + automated). -->
<!-- What the diff does, and what it deliberately leaves alone. -->

- [ ] `composer test` passes locally
- [ ] `composer lint` (PHPStan) passes locally
- [ ] Manual smoke test in WordPress admin / frontend
- [ ] Updated or added unit tests where relevant
## Tests

<!-- What proves it: the tests added, and the evidence they bite — e.g.
"reverting X makes test Y fail". Name any gate that was run only in CI. -->

## Risk

<!-- Data, migrations, capabilities, anything an install upgrades into. Delete
if none. -->

## Screenshots

<!-- For a change an operator sees: before / after. Delete if none. -->

## Checklist

- [ ] Source CSS/JS changes were re-minified (`npm run build`) and the
resulting `*.min.*` files are committed
- [ ] `CHANGELOG.md` updated (and `readme.txt` `== Changelog ==` section if
this is a release-bound change)
- [ ] No new PHPStan baseline entries unless explicitly justified
- [ ] No secrets, tokens, or personally identifiable information in the diff
- [ ] Base is `develop`; no version bump
- [ ] `CHANGELOG.md` — one bullet at the end of its heading under `[Unreleased]`, citing the issue, ≤300 characters
- [ ] Documentation topic under `includes/settings/views/documentation/` updated, if an operator sees or configures the change
- [ ] Strings in the `.pot` and `.po`, catalogues recompiled with `php .github/scripts/ffc-compile-translations.php`
- [ ] Minified assets rebuilt (`npm run build`) if JS or CSS changed
- [ ] Fast checks run locally: PHPUnit for the touched tests, PHPStan, PHPCS; the full suite when the change can reach another file
26 changes: 26 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE/release.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!--
Title: `release: X.Y.Z — bump + finalize CHANGELOG` (to `develop`), or
`X.Y.Z — <summary of the batch>` (the `develop → main` PR, which stays draft
until the maintainer confirms the production deploy).
See CLAUDE.md → "Release PR (develop → main)".
-->

## Release X.Y.Z

<!-- One paragraph: what the batch delivers, by story. -->

## Checklist

- [ ] Version bumped in the three sites (`ffcertificate.php` header, `FFC_VERSION`, `readme.txt` `Stable tag`)
- [ ] `[Unreleased]` renamed to `[X.Y.Z] (YYYY-MM-DD)`, fresh empty `[Unreleased]` above, section condensed by story
- [ ] `readme.txt` `== Upgrade Notice ==` rewritten for this version, ≤300 characters
- [ ] `@since` tags written mid-batch corrected to `X.Y.Z`
- [ ] Documentation cross-checked against every `Added` / `Changed` bullet
- [ ] Minified assets current

## After merge (maintainer / agent)

1. Maintainer pushes the tag with the guarded recipe in `CLAUDE.md`.
2. Agent resets `develop` to `main` (`--force-with-lease`).
3. Agent opens the SHA-backfill PR for the CHANGELOG heading.
4. Agent lists any branch left behind; maintainer deletes it.
4 changes: 4 additions & 0 deletions .github/workflows/assets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ on:
# and leave PRs in mergeable_state: blocked. With npm cache + npm ci
# the job finishes in well under a minute.

# Every job only reads the repository; nothing here writes to it.
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
14 changes: 13 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ on:
# same gates per PR — develop must stay deployable to the testes site.
branches: [main, develop, "release/**"]

# Every job only reads the repository; nothing here writes to it. The
# Coveralls upload below passes the token to identify the repository only.
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down Expand Up @@ -250,8 +255,15 @@ jobs:
# isolated coverage per-shard on CI but not in a mixed single-process run), so
# the true (CI, sharded) figure sits above the ~89% baseline — 86 stays well
# clear while still ratcheting the pending #910 gain.
#
# 86 → 90 — error-path coverage push (#1690, #1697 / #1700 / #1701): the
# audience/recruitment/reregistration, certificate/form-editor/settings and
# identity/migration/encryption modules. This job measured 93.64% on #1701's
# head (sharded phpcov merge). The floor follows the rule shared by the four
# plugins — the highest of 90%, the measured figure minus 5 points (88.64)
# and the current value — so 90, a 3.6pp buffer.
env:
COVERAGE_FLOOR_LINES: '86'
COVERAGE_FLOOR_LINES: '90'
steps:
- name: Fail if any coverage shard did not succeed
if: needs.coverage-shard.result != 'success'
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
pull_request:
branches: [main, develop, "release/**"]

# Every job only reads the repository; nothing here writes to it.
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/phpcs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ on:
pull_request:
branches: [main, develop, "release/**"]

# Every job only reads the repository; nothing here writes to it.
permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
Expand Down
23 changes: 22 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,28 @@ The format follows [Keep a Changelog] (https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [6.37.0] (2026-10-12)
## [6.38.0] (2026-10-12)

The licence moves to AGPLv3 or later. Identity resolution names each number in "One address, several people" and can consolidate a candidate imported twice, the recruitment CSV import honours the RF check digit, and a manage-only role reaches the Reregistration screen. Behind the screens, tests now cover error paths across the plugin and the PHP coverage floor rises to 90%.

### Changed

- ⚠ **The licence is now AGPLv3 or later** (#1695). Reuse and forks stay free; a modified copy offered as a network service must publish its source too. The repository now ships the AGPL text in `LICENSE`, a test holds every declaration together, and releases already published stay GPLv3.
- **"One address, several people" names each number** (#1684). Each Move / Split group shows the names recorded beside the number, now also read from the submission answers, so a number can be taken to HR by name rather than by hash.
- **Tests cover error paths across the plugin, and the PHP coverage floor rises from 86% to 90%** (#1690). About 2,650 more statements in 51 classes, from audience, recruitment and reregistration to certificates, settings, identity, migrations and `Encryption`: refusals, `WP_Error` returns and database failures. CI measured 93.64%; the floor follows the rule the four plugins share.
- **Twelve "never called" test checks now verify something** (#1699). An `expect()->never()` on a function `setUp()` had already stubbed was never consulted; those tests now count calls, and a guard refuses the shape. The magic-link QR code also drops a check that could never fail (#1702).

### Fixed

- **Consolidating a person imported twice as a candidate no longer dead-ends** (#1682). The mistyped candidacy is folded into the sound one: classifications move unchanged, an identical never-called one is deduplicated, and a differing or called one is still refused.
- **The recruitment CSV import honours the RF check digit setting** (#1683). With Settings → General → RF check digit on, a row whose RF fails the digit is refused by line, as the forms already did.
- **A role holding only `ffc_manage_reregistration` opens the Reregistration screen** (#1698). The menu and the page admitted the view capability alone; the shipped presets grant both and were not affected.

### Security

- **CI jobs run with a read-only token** (#1703). `ci.yml`, `lint.yml`, `phpcs.yml` and `assets.yml` declare `contents: read`.

## [6.37.0] (2026-10-12) — `5823fad`

### Added

Expand Down
Loading
Loading