Skip to content

Ferrum Foundry v0.3.0

Choose a tag to compare

@github-actions github-actions released this 27 Sep 14:23
· 57 commits to main since this release
b0762e6

Ferrum Foundry v0.3.0

This release pairs Foundry with Ferrum Edge v0.9.8. Like v0.2.0, it is
intended for a supervised early-access deployment: one gateway, a small
number of administrators, the documented identity-proxy topology. It tightens
static-token authentication, which is a breaking change for static-mode
deployments
(see Upgrading from v0.2.0). It also
redacts secrets from write failures and makes effective-policy analysis and
upstream and credential editing more accurate. It makes no compatibility
promise for other Edge releases. Changes since
v0.2.0:
git log v0.2.0..v0.3.0.

Supported pairing

Foundry v0.3.0 — ferrumedge/ferrum-foundry:v0.3.0, linux/amd64 and linux/arm64. Deploy it by the multi-architecture digest this release's run publishes
Ferrum Edge Ferrum Edge v0.9.8 — ferrumedge/ferrum-edge@sha256:e5b204f9448d4ec210a57dbd2badece5f4359d5d544522fa48dcdfeef033b385, commit e27f2109216352c3fe9e67a7014611f3f66daa91; linux/amd64 sha256:0e629633ad55368002c415bbf76d4c91f3741519a33dd310045531d791d9a592, linux/arm64 sha256:1e900bd537814fdc864ee1830bbd7a1e1f2785074a5da088a3d9cdd738b532f9
Tested gateway database mode on SQLite, writable and with FERRUM_ADMIN_READ_ONLY=true; admin JWT with audience and namespace-claim enforcement
Tested access trusted-proxy authentication through the starter's identity proxy; viewer, operator, and admin
Tested browser Chromium (the build bundled with Playwright 1.63.0)
CI evidence The pull request that moved the pin to v0.9.8, and this release's Pre-publication Gates, which re-run every gate against the same image before anything is published

Best-effort: PostgreSQL/MySQL database mode, cp mode, other browsers,
Kubernetes, static-token authentication (development only). Not qualified:
file/dp/mesh/node_agent modes (so the mesh, waypoint, trust, and
chargeback pages), any other Edge release, and any other Edge image, including
the 0.9.8-ebpf variants. The full envelope, including tested scale, is in
docs/compatibility.md.

Ferrum Edge v0.9.8 leaves the admin API Foundry depends on unchanged from
v0.9.7. Conditional writes (ferrum-edge#5661: a strong ETag on resource reads
and If-Match on PUT/DELETE) keep guarded saves and detail-page deletes
atomic, and the GET /plugins/config?proxy_id= filter (ferrum-edge#5726)
still backs a proxy's Plugins tab. Edge's plugin configuration projection,
which Foundry's secret redaction follows, is the same table.

Highlights since v0.2.0

Authentication

  • Static-token mode refuses to start without FERRUM_JWT_NAMESPACES, and a
    set-but-empty value is a startup error in either mode; * alone is the
    explicit spelling for every namespace (#460, #462).
  • Runtime settings can narrow a session's namespace grants but never widen
    them, and in trusted-proxy mode an empty X-Ferrum-Namespaces header is
    refused rather than read as "every namespace" (#460, #464).
  • FERRUM_JWT_SECRET is used byte for byte, as Ferrum Edge verifies it,
    instead of being trimmed (#486).

Secrets stay out of errors

  • Every write that carries a secret — consumer create and credentials, plugin
    configurations, upstreams, TLS key material and ACME account credentials,
    batch create, backup restore, and API spec import and replacement — replaces
    each submitted secret with [REDACTED] in any refusal the gateway echoes,
    before anything is shown or kept. Plugin configurations are classified by
    Ferrum Edge's own projection table (#466, #478, #485, #487, #491, #493).

Accurate policy

  • Effective policy follows the gateway's scope merge: an attached scoped
    plugin shadows the same-name global one, a group configuration carrying
    proxy_id is excluded, and a proxy protected only by access_control reads
    as denied, not public (#469, #470, #472).
  • The Matched Proxies tab builds its plugin-attachment index once per
    collection instead of scanning per proxy (#454).

Safer editing

  • Upstream target editors are bound to the target they edit, keep their draft
    across refreshes, and are guarded against a background refresh advancing
    past the draft (#445, #448, #464).
  • Upstream subset selectors are edited as lossless key/value rows, and a
    sticky-hash cookie's unset SameSite is kept (#449, #479).
  • A consumer credential write that committed but is not yet live disarms the
    form, and a lost credential add is reported honestly and cannot be
    resubmitted blind (#451, #466).
  • A restore retires every pre-restore detail cache so reopened editors show
    what the gateway now holds (#446).
  • Guided plugin edits keep literal "null" strings (#483), and a host-only
    proxy keeps its absent listen_path (#447).

Operating Foundry

  • A runtime adminUrl change can no longer carry one gateway's cached data,
    drafts, or operations to another: the BFF refuses requests declared against
    a replaced target with 409 (#437).
  • Sessions follow the authentication lifecycle and the shared CSRF cookie
    across tabs (#435, #436).
  • Uploads refused or unread by the gateway are drained under bounded, pooled
    limits instead of resetting the connection (#453, #468).
  • Dashboard request rates are bound to the gateway they were sampled from
    (#476).
  • A UI polish pass: one page header, flush tables, consistent dates and
    labels, an accessible mobile drawer, and a lighter brand mark (#450, #455).
  • Node.js minimums are 22.22.2 and 24.15.0 (#452).

The complete list is in
CHANGELOG.md.

Known limitations

  • The cached-config fallback is not atomic. A read Ferrum Edge serves from
    its cached configuration (X-Data-Source: cached) carries no ETag, so a
    write verified against it is sent without If-Match. A stale editor still
    cannot revert a newer change, but a writer that commits within that one round
    trip is not detected.
  • One qualified gateway configuration. Modes other than database, and Edge
    releases other than v0.9.8, have not been run in CI.
  • Scale. Real-gateway testing covers tens of resources per namespace.
    Request budgets are measured at 50,000 records against a synthetic gateway;
    browser latency is not measured. List search still traverses the
    collection, because the admin API offers no server-side search, and the
    effective plugin policy of a proxy still traverses the namespace's plugin
    configurations, because global and proxy-group configurations cannot be
    filtered.
  • One browser. Only Chromium runs in the release gate.

Install

Run the pairing above, both by digest.

docker pull ferrumedge/ferrum-edge@sha256:e5b204f9448d4ec210a57dbd2badece5f4359d5d544522fa48dcdfeef033b385
docker pull ferrumedge/ferrum-foundry:v0.3.0   # then pin the digest it resolves to
  • New deployment: follow Getting started
    with the starter, then Deployment
    for the production checklist. Set FOUNDRY_IMAGE to the Foundry digest; the
    starter's default (:main) is the development channel.
  • FERRUM_JWT_SECRET must equal the gateway's FERRUM_ADMIN_JWT_SECRET, and
    FERRUM_JWT_AUDIENCE its FERRUM_ADMIN_JWT_AUDIENCE.

Upgrading from v0.2.0

Foundry keeps no persistent state of its own, so an upgrade is an image
replacement.

  1. Move the gateway to Ferrum Edge v0.9.8 first, following Ferrum Edge's own
    upgrade guide
    ("Upgrading to 0.9.8"). Its changes are to the data plane (HTTP/3 rule
    timeouts, the request_timeout X-Gateway-Error token, the
    ValidateJWTSVID claims wire type); the admin API Foundry uses is
    unchanged. Foundry v0.2.0 is not qualified against v0.9.8, so upgrade both
    together.
  2. Apply the configuration changes below before replacing the image.
  3. Replace the Foundry image with the release digest and confirm
    GET /api/health/ready reports version 0.3.0 and a reachable gateway.
  4. Reload open browser tabs so they run the new SPA bundle.

Configuration changes in this release:

  • Breaking, static authentication mode only: FERRUM_JWT_NAMESPACES is
    required. A static-mode BFF without it refuses to start, where v0.2.0 granted
    the static principal every namespace. To keep the v0.2.0 behavior, set
    FERRUM_JWT_NAMESPACES=* before replacing the image; to scope the principal,
    list exact namespace names instead. trusted-proxy deployments, including
    the deployment starter, need no change as long as they leave
    FERRUM_JWT_NAMESPACES unset.
  • Breaking, either authentication mode: a set-but-empty
    FERRUM_JWT_NAMESPACES — empty, whitespace, or commas only — is now a startup
    error, where v0.2.0 treated it as if the variable were unset and left the
    principal unrestricted. Operators who set such a value should unset it in
    trusted-proxy mode, or set * or exact namespace names in static mode.

Rolling back

  • Foundry: redeploy the previous immutable tag or digest. Nothing Foundry
    wrote needs undoing — configuration lives in Ferrum Edge — but a rollback
    does not revert configuration changes made through the newer version, and
    v0.2.0 is not qualified against Ferrum Edge v0.9.8. A FERRUM_JWT_NAMESPACES
    set for v0.3.0 is also valid for v0.2.0.
  • Ferrum Edge: follow Ferrum Edge's own rollback guidance: during Edge's
    build-out, cut traffic back to the old binary on the old, untouched
    database rather than pointing an older binary at a new one. Take a backup
    per namespace with Settings → Download Backup (GET /backup, admin role)
    before either upgrade.
  • Confirm FERRUM_JWT_SECRET and FERRUM_JWT_AUDIENCE still match the gateway
    after any rollback.

Docker

docker pull ferrumedge/ferrum-foundry:v0.3.0
docker pull ghcr.io/ferrum-edge/ferrum-foundry:v0.3.0

Production quick start

Run Foundry only behind an identity-aware reverse proxy that removes
client-supplied identity headers and injects the trusted proxy proof:

export FERRUM_JWT_SECRET=$(openssl rand -hex 32)
export FERRUM_TRUSTED_PROXY_SECRET=$(openssl rand -hex 32)

docker run \
  -e FERRUM_ADMIN_URL=https://your-gateway:9443 \
  -e FERRUM_JWT_SECRET \
  -e FERRUM_AUTH_MODE=trusted-proxy \
  -e FERRUM_TRUSTED_PROXY_SECRET \
  -p 127.0.0.1:8080:8080 \
  ferrumedge/ferrum-foundry:v0.3.0

Configure the proxy to send X-Ferrum-Auth-Secret,
X-Forwarded-User, X-Ferrum-Role, and exact
X-Ferrum-Namespaces grants. See
Production authentication.