ENGLISH·COURSE API
    Preparing search index...

    Driven adapter: LessonRepository backed by declared manifest rows whose content keys are resolved through a BlobStore on every read.

    Rows are stored in insertion order and hold opaque content KEYS in source and poster. Resolution happens at read time, not when the time, so repointing storage (local folder → S3/R2 bucket) is a change of BlobStore driver rather than an edit to the course manifests. It is also what makes per-request signed URLs possible: a signed URL expires and therefore cannot be baked into a committed file.

    Parsing happens after resolution — urlOrRelativePath() rejects a bare key — so a row that resolves to a malformed URL is rejected here rather than reaching a src attribute in the UI.

    Implements