Appearance
Handoff: SVC-011-storage-media-browser-proof
Scope
- Dispatch ID:
SVC-011 - Service:
file-servicedomain alias, implemented bydocument-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.mddocs/agents/handoffs/SVC-011-object-delete-archive-lifecycle.mddocs/agents/service-agent-next-slice-queue.jsondocs/agents/service-agent-next-slice-closeout-ledger.jsondocs/qa/storage-media-parity-smoke.mddocs/qa/storage-media-browser-proof.mddocs/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.mddocs/agents/handoffs/SVC-011-storage-media-browser-proof.mddocs/agents/service-agent-next-slice-closeout-ledger.jsondocs/agents/service-agent-next-slice-closeout-ledger.mddocs/agents/service-agent-accepted-handoffs.mddocs/agents/service-tasks/file-service.mddocs/api/document-service.mddocs/index.mddocs/.vitepress/config.tsdocs/qa/service-agent-goal-completion-audit.mddocs/qa/service-agent-readiness-smoke.mdservices/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-Tokenis read-only: a token-onlyDELETE /v1/storage/objectsrequest is forbidden and leaves the object readable under its organization scope. - Extended archive HTTP proof to assert both
publishedAtandfeaturedAtare cleared when a teaching document becomesARCHIVED. - Added a service-local route boundary test proving
/api/storage/*and/api/documents/*are not served by document-service's/v1handler. - 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=1STORAGE_PARITY_SELF_TEST=1 make test-storage-media-paritycmp -s services/document-service/api/openapi.yaml contracts/openapi/services/document-service.yamlruby -e 'require "yaml"; ARGV.each { |f| YAML.load_file(f) }' services/document-service/api/openapi.yaml contracts/openapi/services/document-service.yamlGOTOOLCHAIN=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.