## Summary
Return a specific, safe error when a project reaches its plan's
asset-count limit instead of reporting an internal Assets API failure.
## Root cause
The uploader enforced `maxAssetsPerProject` by throwing a plain `Error`.
The REST boundary correctly treated unknown errors as internal failures,
returned HTTP 500, and redacted the useful limit explanation. The
Builder then displayed that generic response.
## Technical choices
- Represent the expected quota condition with
`AssetUploadCountLimitError`.
- Map that domain error to HTTP 409 while preserving its existing
message.
- Keep the generic HTTP 500 response and server logging for unexpected
failures.
- Reuse the Builder's existing API-error handling; it already displays
the returned `errors` value in the upload toast.
## Checklist
- [x] Reproduce the generic uploader and REST error behavior
- [x] Add regressions and verify they fail before the behavior change
- [x] Throw a typed error when the asset-count limit is reached
- [x] Return the safe limit explanation through the Assets API
- [x] Verify unexpected internal errors remain redacted
- [x] Review documentation impact — no documentation change is needed
for this error-message correction
- [x] Review fixture impact — no fixture inputs or generated outputs are
affected
- [x] Review the final diff for unrelated changes and duplicated logic
## Verification
- `pnpm --filter @webstudio-is/asset-uploader test` — 196 tests passed
- Asset uploader typecheck passed
- Targeted Builder Assets API and upload client tests — 37 tests passed
- Builder typecheck passed
- `pnpm lint`
Closes#6148