Skip to content

Media Workflow And Validation

Use this page when deciding how much media proof a change needs. The architecture page explains the model; this page chooses the day-to-day loop: mocked storage, local emulators, real deployed dev, media smoke, browser media smoke, and discrepancy reporting.

The default posture is simple: use the cheapest lane that proves the risk, and keep real cloud media validation explicit.

Change ShapeRecommended LaneWhy
UI layout, form mapping, media draft state, validation messages, or non-media feature workMocked storageProves app behavior without object-store startup or cloud state.
Upload/delete path construction, S3 adapter behavior, public URL resolution, or local cleanup behaviorS3 emulator through LocalStackExercises AWS-shaped storage without touching deployed dev.
Azure-specific continuity checksAzure emulator through AzuriteKeeps the older Azure path smokeable without making Azure the roadmap driver.
IAM, bucket policy, S3/CloudFront delivery, same-origin /media/*, or deployed runtime configDeployed dev media validationOnly real AWS dev proves cloud permissions and edge delivery.
Browser rendering of deployed mediaBrowser media smokeProves the actual user-visible media path after seeded media is available.
DB/S3 drift after reset, media smoke, manual media testing, or bucket investigationMedia discrepancy reportRead-only comparison of deployed DB rows and S3 objects.

Do not use real AWS dev storage for ordinary local iteration. Real-cloud checks should be intentional because local database resets, upload experiments, and cleanup scripts can otherwise leave durable objects without matching rows and introduce persistent hidden costs as stored objects accumulate.

Local media behavior is selected by the following backend env values:

  • MEDIA_STORAGE_PROVIDER
  • MEDIA_STORAGE_EXECUTION_TARGET
  • MEDIA_STORAGE_APPLICATION_ENVIRONMENT

Mocked storage is the default app-logic lane. It is the right place for most frontend and backend feature work where the storage provider itself is not under investigation.

Use S3 emulator mode when the provider behavior matters:

  • Uploading, deleting, and resolving stored objects.
  • Verifying object key construction.
  • Exercising provider-specific adapter code.
  • Checking local cleanup and reset behavior.

pnpm dev:docker:up reads the selected local media mode and adds the S3 or Azure emulator compose layer only when that mode requires it. The LocalStack S3 path has a reset hook; Azure emulator reset remains a continuity-path gap until/if platform development seriously explores Azure as a cloud provider.

Keep these distinctions intact:

  • LocalStack and Azurite are execution targets, not persisted media providers.
  • Mocked storage is a deliberate provider double for development and tests.
  • AWS_PROFILE is a cloud credential selector, not a media-mode selector.
  • Generic local reset commands must not target real cloud storage.

Use deployed dev when the change needs cloud proof:

  • Runtime media config from SSM and host-side env rendering.
  • Runtime host IAM access to the private media bucket.
  • S3 object writes and reads through the deployed backend.
  • Browser-facing delivery through same-origin CloudFront /media/*.
  • Media behavior after runtime deploy, reset, or rollback.

Choose the narrowest proof:

ProofUse WhenNotes
Endpoint smokeMedia code changed but the risk is ordinary app readiness.No media-specific proof by itself.
Seeded smokeA reset or seeded route is needed before media/browser checks.Destructive database reset must be deliberate.
Media smokeYou need a temporary DB/S3 media write/read proof in deployed dev.Mutates app media state and should stay profile-scoped.
Browser media smokeYou need user-visible proof that seeded media renders through the deployed frontend and edge path.Read-only once seeded prerequisites exist; uses browser evidence on failure.
Media discrepancy reportYou need to inspect drift between deployed DB rows and S3 objects.Read-only telemetry; cleanup remains a separate approval-gated mutation.
Media bucket replacement pathA Pulumi preview changes or destroys deployed-dev media storage.Use the media bucket replacement runbook before applying infrastructure changes.

Keep deploy-media and lifecycle proofs separate unless the combined signal is deliberate. Media proof mutates app media; lifecycle proof can stop the shared runtime host.

Media proof should leave enough evidence for the next operator or developer to understand what happened:

  • Selected target, profile, commit, and app URL.
  • Whether the proof was mocked, emulator-backed, or deployed dev.
  • For deployed media smoke, the SSM command ID or workflow job summary when live SSM execution ran.
  • For browser media smoke failures, the browser artifact bundle and the rendered media URL or currentSrc when available.
  • For discrepancy reports, inspected row/object counts and discrepancy-kind summary.
  • Any explicit cleanup decision or follow-up command that remains outside the proof.

Do not publish raw logs, live identifiers, signed URLs, provider object keys, or workflow artifacts into the public docs site. Reduce live proof to the reusable lesson before promoting it.

Database reset does not delete deployed-dev S3 media. That can leave orphaned objects. Media bucket changes can also leave database rows pointing at missing objects.

Current rule:

  • Use the media discrepancy report for read-only inspection.
  • Treat discrepancy counts as telemetry, not automatic failure or cleanup.
  • Require a separate approval-gated cleanup command before deleting DB rows or provider objects.
  • Print the exact rows or object keys before any future cleanup mutation.

For local emulator work, reset local emulator media when the goal is a clean app/media state. Preserve emulator media only when creating intentional orphan or reconciliation fixtures.

Keep active media implementation sequencing in roadmap notes while it is moving quickly. Promote material into curated docs when it becomes a repeated decision. Example scenarios may include:

  • A new media-bearing entity adopts the artist-first pattern.
  • Direct-to-storage upload sessions become real.
  • Scheduled discrepancy reporting or cleanup becomes justified.
  • Cross-entity media management leaves the roadmap.
  • Browser media smoke becomes routine enough to change deploy profiles.
  • Staging or production adds different media durability, privacy, or CDN requirements.