Tables in Schema.php — us_policies, us_policy_versions, us_policy_acceptances
PolicyService orchestrates the multi-table publish flow: archive the prior current version, stamp published_at, and repoint current_version_id
Admin — a Policies menu (gated on manage_policies): create a policy, add/publish draft versions, see which version is current
Wiring — Plugin, RestRegistrar, AdminMenu
REST API
Method
Endpoint
Permission
GET
/policies
public (current published versions)
POST
/policies
manage_policies
POST
/policies/{id}/versions
manage_policies
PATCH
/policies/{id}/versions/{vid}
manage_policies (draft only)
POST
/policies/{id}/versions/{vid}/publish
manage_policies
Versioning & acceptance
Acceptance is bound to policy_version_id, so publishing a new version leaves it unaccepted — students must re-accept at their next booking. AcceptanceRepository is built here and consumed by the booking/enrolment gate in #3/#4.
Also
Bumped PHPStan to --memory-limit=1G in the composer lint script — the default 128M now crashes analysis as the codebase has grown (would otherwise fail the static-analysis CI job).
Tests
tests/Unit/Policy/ — value objects, three repositories, and the PolicyService publish orchestration (25 new tests)
composer test (90 total), composer cs, and PHPStan level 6 all pass
Implements **#6 (Policies)** — the second registration gate (standalone, no payment dependency).
## What's included
- **`src/Policy/` domain** — `Policy`, `PolicyVersion` (draft/published/archived), `PolicyAcceptance` value objects; `PolicyRepository`, `PolicyVersionRepository`, `AcceptanceRepository`; `PolicyService`; `PolicyEndpoint`; `PolicyController` + `templates/admin/policies.php`
- **Tables** in `Schema.php` — `us_policies`, `us_policy_versions`, `us_policy_acceptances`
- **`PolicyService`** orchestrates the multi-table publish flow: archive the prior current version, stamp `published_at`, and repoint `current_version_id`
- **Admin** — a **Policies** menu (gated on `manage_policies`): create a policy, add/publish draft versions, see which version is current
- **Wiring** — Plugin, RestRegistrar, AdminMenu
## REST API
| Method | Endpoint | Permission |
|---|---|---|
| GET | `/policies` | public (current published versions) |
| POST | `/policies` | `manage_policies` |
| POST | `/policies/{id}/versions` | `manage_policies` |
| PATCH | `/policies/{id}/versions/{vid}` | `manage_policies` (draft only) |
| POST | `/policies/{id}/versions/{vid}/publish` | `manage_policies` |
## Versioning & acceptance
Acceptance is bound to `policy_version_id`, so publishing a new version leaves it unaccepted — students must re-accept at their next booking. `AcceptanceRepository` is built here and consumed by the booking/enrolment gate in #3/#4.
## Also
Bumped PHPStan to `--memory-limit=1G` in the `composer lint` script — the default 128M now crashes analysis as the codebase has grown (would otherwise fail the `static-analysis` CI job).
## Tests
- `tests/Unit/Policy/` — value objects, three repositories, and the `PolicyService` publish orchestration (25 new tests)
- `composer test` (90 total), `composer cs`, and PHPStan level 6 all pass
Refs #6
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Implements #6: studio admins draft, version, and publish policies; the
public registration gate reads the current published version of each, and
acceptance is recorded against the exact version so a new version must be
re-accepted at the next booking.
- src/Policy/: Policy, PolicyVersion, PolicyAcceptance value objects;
PolicyRepository, PolicyVersionRepository, AcceptanceRepository;
PolicyService (orchestrates create/add-draft/publish across the policies
and versions tables); PolicyEndpoint (REST); PolicyController +
templates/admin/policies.php (Policies admin menu, manage_policies)
- us_policies, us_policy_versions, us_policy_acceptances tables in Schema
- REST: public GET /policies (current published versions); manage_policies
for create, add version, edit draft, and publish
- Wiring in Plugin, RestRegistrar, AdminMenu
AcceptanceRepository is built now and consumed by the booking/enrolment
gate in #3/#4.
Also bump PHPStan to --memory-limit=1G in the composer lint script; the
default 128M now crashes the analysis as the codebase has grown.
Tests: tests/Unit/Policy/ (value objects, repositories, service).
composer test (90 total), cs, and PHPStan level 6 all pass.
Refs #6
Co-Authored-By: Claude Opus 4.8 <[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.
Implements #6 (Policies) — the second registration gate (standalone, no payment dependency).
What's included
src/Policy/domain —Policy,PolicyVersion(draft/published/archived),PolicyAcceptancevalue objects;PolicyRepository,PolicyVersionRepository,AcceptanceRepository;PolicyService;PolicyEndpoint;PolicyController+templates/admin/policies.phpSchema.php—us_policies,us_policy_versions,us_policy_acceptancesPolicyServiceorchestrates the multi-table publish flow: archive the prior current version, stamppublished_at, and repointcurrent_version_idmanage_policies): create a policy, add/publish draft versions, see which version is currentREST API
/policies/policiesmanage_policies/policies/{id}/versionsmanage_policies/policies/{id}/versions/{vid}manage_policies(draft only)/policies/{id}/versions/{vid}/publishmanage_policiesVersioning & acceptance
Acceptance is bound to
policy_version_id, so publishing a new version leaves it unaccepted — students must re-accept at their next booking.AcceptanceRepositoryis built here and consumed by the booking/enrolment gate in #3/#4.Also
Bumped PHPStan to
--memory-limit=1Gin thecomposer lintscript — the default 128M now crashes analysis as the codebase has grown (would otherwise fail thestatic-analysisCI job).Tests
tests/Unit/Policy/— value objects, three repositories, and thePolicyServicepublish orchestration (25 new tests)composer test(90 total),composer cs, and PHPStan level 6 all passRefs #6
🤖 Generated with Claude Code