Found on a live deployment, on the studio's first real booking.
What happens
A student books a weekly recurring lesson and accepts the studio's policies as part of booking. Opening the lesson detail page for any occurrence after the first shows no policies accepted and no intake answers — as though the student had agreed to nothing.
What is actually stored
The acceptances are recorded correctly. A weekly booking creates one us_bookings row per occurrence, but the student answers the intake and ticks the policy boxes once, so BookingEndpoint::book() records both against the anchor lesson only:
The admin detail view then looks them up by whichever lesson id is being viewed, so every occurrence but the anchor finds nothing. Purely a read-path bug — no data is missing or wrong in the database.
What it should do
Every occurrence of a series should show the intake answers and the policy audit trail (policy, version, accepted-at, IP) captured when the reservation was booked. A weekly lesson row already carries series_id pointing at the anchor, so the detail view can follow it — the same way PaymentService already resolves a series lesson's payment back to the anchor's.
The intake answers have the identical bug from the same call site.
Impact
The policy audit trail is the record that a student agreed to the cancellation and payment terms for their lessons. For a recurring student it currently reads as absent on 11 of 12 lessons, which is exactly the situation where a studio would go looking for it.
Found on a live deployment, on the studio's first real booking.
## What happens
A student books a weekly recurring lesson and accepts the studio's policies as part of booking. Opening the lesson detail page for any occurrence **after the first** shows no policies accepted and no intake answers — as though the student had agreed to nothing.
## What is actually stored
The acceptances are recorded correctly. A weekly booking creates one `us_bookings` row per occurrence, but the student answers the intake and ticks the policy boxes **once**, so `BookingEndpoint::book()` records both against the anchor lesson only:
```php
$this->gate->record( PolicyAcceptance::REG_LESSON, $anchorId, ... );
```
The admin detail view then looks them up by whichever lesson id is being viewed, so every occurrence but the anchor finds nothing. Purely a read-path bug — no data is missing or wrong in the database.
## What it should do
Every occurrence of a series should show the intake answers and the policy audit trail (policy, version, accepted-at, IP) captured when the reservation was booked. A weekly lesson row already carries `series_id` pointing at the anchor, so the detail view can follow it — the same way `PaymentService` already resolves a series lesson's payment back to the anchor's.
The intake answers have the identical bug from the same call site.
## Impact
The policy audit trail is the record that a student agreed to the cancellation and payment terms for their lessons. For a recurring student it currently reads as absent on 11 of 12 lessons, which is exactly the situation where a studio would go looking for it.
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.
Found on a live deployment, on the studio's first real booking.
What happens
A student books a weekly recurring lesson and accepts the studio's policies as part of booking. Opening the lesson detail page for any occurrence after the first shows no policies accepted and no intake answers — as though the student had agreed to nothing.
What is actually stored
The acceptances are recorded correctly. A weekly booking creates one
us_bookingsrow per occurrence, but the student answers the intake and ticks the policy boxes once, soBookingEndpoint::book()records both against the anchor lesson only:The admin detail view then looks them up by whichever lesson id is being viewed, so every occurrence but the anchor finds nothing. Purely a read-path bug — no data is missing or wrong in the database.
What it should do
Every occurrence of a series should show the intake answers and the policy audit trail (policy, version, accepted-at, IP) captured when the reservation was booked. A weekly lesson row already carries
series_idpointing at the anchor, so the detail view can follow it — the same wayPaymentServicealready resolves a series lesson's payment back to the anchor's.The intake answers have the identical bug from the same call site.
Impact
The policy audit trail is the record that a student agreed to the cancellation and payment terms for their lessons. For a recurring student it currently reads as absent on 11 of 12 lessons, which is exactly the situation where a studio would go looking for it.