Code MERGED (backend #259 — assets route + controller mirror + GLB bucket fallback). Remaining = ops via #529 (assets bucket/backfill) + the #412 note: when Trellis is repaired its worker must…
Code MERGED (backend #262). Remaining = ops via #529 (lesson-videos bucket + videos-svc key + VIDEOS_S3_SECRET_KEY — backend #264/infra #60 — backfill, phase-2 bind drop). S3-temp transcode…
Code MERGED (backend #260). Remaining = ops via #529 (blogs bucket + blogs-svc key + BLOGS_S3_SECRET_KEY secret — backend #264/infra #60 add the guard+env — backfill, phase-2 bind drop). Serving…
MERGED (backend #252): SpikerSoft.Storage project + IObjectStore/S3ObjectStore/ObjectKeys + shared registrations. Seam has since grown keyed multi-bucket stores (#526), ObjectFileCache (#527) and…
Code MERGED (backend #258 — moved-file router + dlls route). Remaining = ops via the #529 runbook (dlls bucket, backfill, phase-2 bind drop).
Code MERGED (backend #257). Remaining = ops via the #529 runbook: quarantine bucket + keys (blogs-svc write, file-movement policy widening), backfill, Storage__UseS3 flip (already true on…
Angular PRs up: #177 (SECURITY, ungated — deny the private trees the root bind exposes; see the new security ticket) and #178 (GATED — proxy blogs/ebooks/lesson-videos to MinIO with Range…
QA watch 2026-07-13 ~20:29Z — status changed since filing: /healthz now returns HTTP 200 with overall status 'Degraded' (was 503). The TileServerGL check is now classified Degraded rather than…
Cutover prep landed as two PRs: backend #264 (deploy-secret guards for blog-media/lesson-video — the only batch members missing them) + infra #60 GATED (Storage__ env for those two stacks +…
Backend PR #263: S3MediaFallbackMiddleware behind the four disk mounts — streaming proxy chosen over presigned (URLs and semantics unchanged → no Angular work; presign stays a later optimization)…
Backend PR #262: LessonVideoMoveConsumer dual-writes moved video+thumbnail to the lesson-videos bucket (same relative keys served today → #528/#531 cutover = prefix swap). Transcoder deliberately…
Backend PR #261: ObjectFileCache in SpikerSoft.Storage (local-wins → atomic bucket download → null), embeddings resolves its gguf directly, quiz-generation via a ModelPathResolver delegate so…
Backend PR #260: BlogMediaMoveConsumer dual-writes moved media to the blogs bucket (same relative keys nginx serves — #531 cutover becomes a prefix swap); file-movement routes /app/blogs.…
Correction + resolution of the CI thread (2026-07-13 ~19:57Z): the API's 'silent no-op deploy' I described was me misreading interleaved task lists — spikersoft-api.yml has NO deploy job at all…
Backend PR #259 (stacked on #258→#257): file-movement routes /app/assets moves to the assets bucket; ThreeDModelController dual-writes source images and falls back to the bucket for GLB downloads…
QA watch 2026-07-13 ~19:52Z — concrete CI impact of the dead arm runner: backend's new code is NOT live despite green-looking runs. Sequence: urgent-fix build pushed spikersoft-backend:amd64 +…
Backend PR #258 (stacked on #257): S3MovedFileMirror now routes moved files by destination tree — /app/dlls → dlls bucket via a keyed store; ebooks route unchanged. Finding: UploadCoordinator…
QA watch 2026-07-13 ~19:47Z — arm runner crash-loop root-caused: CONTAINER DNS, not gitea. Every restart logs: 'fail to invoke Declare … lookup git.spikersoft.com on 127.0.0.11:53 … i/o…