Skip to content

Handoff: SVC-011-storage-media-browser-proof

Scope

  • Dispatch ID: SVC-011
  • Service: file-service domain alias, implemented by document-service
  • Task pack: docs/agents/service-tasks/file-service.md
  • Next task: SVC-011-storage-media-browser-proof
  • Goal: prove storage/media parity and the browser evidence gate before public storage/document route promotion.
  • Status: accepted bounded contract slice, not service completion.

Docs Read

  • docs/agents/service-tasks/file-service.md
  • docs/agents/handoffs/SVC-011-object-delete-archive-lifecycle.md
  • docs/agents/service-agent-next-slice-queue.json
  • docs/agents/service-agent-next-slice-closeout-ledger.json
  • docs/qa/storage-media-parity-smoke.md
  • docs/qa/storage-media-browser-proof.md
  • docs/api/document-service.md

Legacy Evidence Read

  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/storage/storage.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/documents/documents.controller.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/documents/documents.service.ts
  • /Users/velikho/Desktop/WORKING/HOCTAPAZ/node-platform/apps/api/src/modules/admin/content-admin.service.ts
  • Legacy source was read-only evidence. No legacy file was changed.

Files Changed

  • docs/qa/storage-media-browser-proof.md
  • docs/agents/handoffs/SVC-011-storage-media-browser-proof.md
  • docs/agents/service-agent-next-slice-closeout-ledger.json
  • docs/agents/service-agent-next-slice-closeout-ledger.md
  • docs/agents/service-agent-accepted-handoffs.md
  • docs/agents/service-tasks/file-service.md
  • docs/api/document-service.md
  • docs/index.md
  • docs/.vitepress/config.ts
  • docs/qa/service-agent-goal-completion-audit.md
  • docs/qa/service-agent-readiness-smoke.md
  • services/document-service/internal/http/server_test.go

Behavior Implemented

  • Existing document-service tests prove upload URL generation, media metadata, object content reads, image variants, organization-scoped delete, archive ownership, and search-projection exclusion of archived documents.
  • The storage parity self-test and non-default route definitions provide a bounded HTTP/rehearsal contract without changing default gateway traffic.
  • Required evidence: storage/media parity proof, upload/read browser evidence, and rollback notes. The first and third are bounded/passed; real browser upload/read evidence remains open.

Audit Update 2026-07-10

  • Added HTTP proof that X-Document-Object-Read-Token is read-only: a token-only DELETE /v1/storage/objects request is forbidden and leaves the object readable under its organization scope.
  • Extended archive HTTP proof to assert both publishedAt and featuredAt are cleared when a teaching document becomes ARCHIVED.
  • Added a service-local route boundary test proving /api/storage/* and /api/documents/* are not served by document-service's /v1 handler.
  • No implementation bug was reproduced in the bounded memory-backed path; the concrete change is missing focused HTTP coverage. Default gateway routes and legacy source remain unchanged.

Tests And Verification

  • GOTOOLCHAIN=go1.25.11 go test ./services/document-service/... -count=1
  • STORAGE_PARITY_SELF_TEST=1 make test-storage-media-parity
  • cmp -s services/document-service/api/openapi.yaml contracts/openapi/services/document-service.yaml
  • ruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f) }' services/document-service/api/openapi.yaml contracts/openapi/services/document-service.yaml
  • GOTOOLCHAIN=go1.25.11 go test -race ./services/document-service/internal/http ./services/document-service/internal/usecase ./services/document-service/internal/media -count=1

All bounded commands passed. Self-test and memory object-store coverage do not claim a real browser or production object-store run.

Current Disposable Runtime Recheck (2026-07-13)

A disposable in-memory document-service accepted a token-gated POST /v1/internal/media-assets PNG fixture. Direct native content and the same content through the non-default routes.storage-native-localhost-example.json had identical SHA-256 bytes. The Gateway response included X-Hoctapaz-Gateway-Route: storage and X-Hoctapaz-Gateway-Route-State: native_write; Playwright rendered the PNG without a blank frame. Restarting the Gateway with active deploy/gateway/routes.json returned storage/legacy_proxy and the expected 502 against an intentionally unavailable legacy target.

Artifacts are in output/qa/storage-media-browser-proof-20260713/ and output/playwright/storage-media-browser-proof-20260713/. The temporary processes on 8097 and 18086 were stopped after capture. This is direct browser media rendering and Gateway evidence only, not a frontend import, question, or document workflow proof.

Route State

  • Default storage/media/document routes remain legacy-proxied.
  • Native document-service storage routes remain non-default rehearsals.
  • Route state: storage/media promotion requires parity proof plus browser evidence for touched upload/read flows.
  • Rollback is GATEWAY_ROUTE_TABLE=deploy/gateway/routes.json; remove the rehearsal route and rerun storage route coverage and smoke checks.

Risks / Blockers

  • Real legacy-media byte parity and frontend import/question/document workflow rendering remain open. The disposable browser rendering and rollback artifacts do not replace those promotion gates.
  • S3/MinIO provider deletion was not live-tested in this bounded slice.
  • Purchase, entitlement, wallet, billing, usage/quota, share, and hard purge behavior remain outside file-service ownership.

Next Step

Run the non-default storage gateway/browser smoke with a seeded legacy media asset, shared object store, frontend, bearer token, and organization; capture output/playwright/ artifacts and rollback to the default route table.

Go-platform documentation is generated from repository Markdown.