Add same-origin MFE artifact delivery endpoint

What does this MR do and why?

Serves baked MFE assets at /-/mfe/:name/:version/*path as public immutable artifacts, so browsers never contact the upstream registry and the CSP needs no new origins:

  • Mfe::ArtifactsController — no auth (BaseActionController), Content-Type allow-list, nosniff, immutable Cache-Control, X-Sendfile. No session, no database access on the serve path.

The dev-mode proxy for local development moved to its own MR: !245301 (closed).

How to verify

bin/rspec spec/requests/mfe/artifacts_spec.rb

End-to-end with a real application (baked Duo Chat)

Bake the real Duo Chat MFE first, exactly as described in the bake MR (!245045 (closed), "Bake a real application"): pin it in config/mfe.yml and run the bake — no configuration needed, registry reads are anonymous:

apps:
  - name: duo_chat
    project: gitlab-org/frontend/gitlab-mfe
    version: 0.2.0
    manifest_sha256: 13a8f610c44190e6cbead9e7ba2b48316677479a1e682fc894ed1c1c669eb38d
bin/rake gitlab:mfe:bake

Then enable delivery — unlike the bake, the serving endpoint is double-gated:

# gitlab.yml (GDK: gdk.yml → gitlab section, or edit config/gitlab.yml)
mfe:
  enabled: true
# rails console
Feature.enable(:mfe_enabled)

And verify the delivery behavior:

# 200 with the delivery headers: immutable public Cache-Control,
# X-Content-Type-Options: nosniff, correct Content-Type from the allow-list
curl -sI http://gdk.test:3000/-/mfe/duo_chat/0.2.0/mf-manifest.json | grep -iE "^HTTP|cache-control|content-type|nosniff"

# a real JS chunk from the 211-file tree is served the same way
curl -sI http://gdk.test:3000/-/mfe/duo_chat/0.2.0/remoteEntry.js | grep -iE "^HTTP|content-type"

# unknown version, unknown app, traversal attempts: 404
curl -s -o /dev/null -w "%{http_code}\n" http://gdk.test:3000/-/mfe/duo_chat/9.9.9/mf-manifest.json
curl -s -o /dev/null -w "%{http_code}\n" http://gdk.test:3000/-/mfe/nope/0.2.0/mf-manifest.json

# the whole endpoint disappears behind the kill switch
# (disable the feature flag or set mfe.enabled: false -> 404)

No session cookie is needed for any of these requests, and no SQL is executed on the serve path (spec/requests/mfe/artifacts_spec.rb asserts the zero-query property).

Stack

This is part of a stacked series extracted from a single 1700+ line MR for reviewability. Each part is independently verifiable and leaves master inert: nothing is user-reachable until an application is pinned.

# Scope MR
1 Config plumbing + instance kill switch !245043 (closed)
2 Sidecar manifest validation + pin-file catalog !245044 (closed)
3 Verified bake task + baked manifest !245045 (closed)
4 Same-origin delivery endpoint !245046 (closed)
5 Dev-mode proxy for local development !245301 (closed)

Merging bottom-up; when a part merges, GitLab retargets the next one to master automatically.

A separate demonstration MR shows the whole stack working end to end with the real Duo Chat MFE (production bake + dev-mode HMR): !245014.

Related to #605798.

Edited by Illya Klymov

Merge request reports

Loading