docs(phase-16): record 16.2 absorption + 16.3 anonId landing

PLAN/COMPLETED mark 16.2 absorbed into 16.1 and 16.3 landed (no migration). Folder CLAUDE.md files reflect anonId now accepted/persisted + the distinct-listener queries.
This commit is contained in:
daniel-c-harvey
2026-06-19 14:57:23 -04:00
parent 297805b5a8
commit 4317a2f9e7
5 changed files with 49 additions and 10 deletions
+4 -4
View File
@@ -313,9 +313,9 @@ Both endpoints are unauthenticated and rate-limited by the `"events"` fixed-wind
### POST api/event/play (unauthenticated, rate-limited)
Records an anonymous play event. Client sends only the track `EntryKey` and a completion bucket; server-side release resolution joins track→release at write time (D4). Wave 16.1 drops any `anonId` the client sends — that field is wired in wave 16.3.
Records an anonymous play event. Client sends the track `EntryKey`, a completion bucket, and an optional `anonId` (wave 16.3); server-side release resolution joins track→release at write time (D4). The `anonId` is length-clamped server-side: whitespace-only / empty / null collapses to null (valid anonId-less event); a token longer than 64 chars returns `400` rather than being truncated (truncation would collide distinct listeners).
- **Body** (`PlayEventDto`): `{ "trackEntryKey": "...", "bucket": "partial"|"sampled"|"complete" }`.
- **Body** (`PlayEventDto`): `{ "trackEntryKey": "...", "bucket": "partial"|"sampled"|"complete", "anonId": "..." }` (`anonId` optional — omitted when null).
- Validates: non-empty `trackEntryKey`; `bucket` must be a defined `PlayBucket` enum value.
- Delegates to `IEventService.RecordPlay`, which appends to `play_event` and bumps `play_counter`.
- Returns 202 on success. Returns 400 for missing/invalid fields. Returns 429 when the rate limit is exceeded. Returns 500 on a write failure (logged; beacon ignores it).
@@ -324,8 +324,8 @@ Records an anonymous play event. Client sends only the track `EntryKey` and a co
Records an anonymous share event (a clipboard write from `SharePopover`).
- **Body** (`ShareEventDto`): `{ "targetKey": "...", "targetType": "track"|"release", "channel": "link"|"embed" }`.
- Validates: non-empty `targetKey`; defined `ShareTargetType` and `ShareChannel` enum values.
- **Body** (`ShareEventDto`): `{ "targetKey": "...", "targetType": "track"|"release", "channel": "link"|"embed", "anonId": "..." }` (`anonId` optional — omitted when null; same length-clamp as the play endpoint).
- Validates: non-empty `targetKey`; defined `ShareTargetType` and `ShareChannel` enum values; `anonId` ≤ 64 chars (reject-not-truncate).
- Delegates to `IEventService.RecordShare`, which appends to `share_event`.
- Returns 202 on success. Returns 400 for missing/invalid fields. Returns 429 on rate limit. Returns 500 on write failure.