Skip to content

ADR 0006: License policy

  • Status: accepted
  • Date: 2026-09-26

The project is MIT. It links many C libraries and may ship ML models. GPL/AGPL components would force the combined work’s license or create distribution obligations incompatible with the project’s goals.

  • Allowed in shipped artefacts: MIT, BSD-2/3, Apache-2.0, ISC, Zlib, libpng, IJG, OFL (fonts), MPL-2.0 (file-level), LGPL-2.1+/LGPL-3 dynamically linked only with source offer and license text shipped. LibRaw used under LGPL-2.1 (or CDDL-1.0).
  • Forbidden (in slim, full and every Go module; the opt-in gpl image flavor is the single exception, see the 2026-09-27 amendment below): GPL, AGPL, SSPL, non-commercial or “research only” licenses, including model weights. Concretely excluded: x265 (use kvazaar), poppler (use PDFium), exiv2, GPL FFmpeg builds (--enable-gpl, libx264, libx265), libimagequant ≥ 2.12 (GPL-3; use quantizr), Ultralytics YOLO weights (AGPL), Ghostscript (except the separate gs program in the gpl flavor, WP-99 amendment below), dssim CLI (AGPL; own SSIM implementation instead).
  • Base image extras (WP-66), all dynamically linked from /opt/xtandard/lib with their licence texts in share/licenses/ and exact sources in SOURCES.md:
  • full flavor (WP-70), dynamically linked or loaded, licence texts in share/licenses/{ffmpeg,libvpx,onnxruntime,models}/, sources in SOURCES.md (section “full flavor”), pins in docker/base/versions-full.sh:
  • Go dependencies follow the same list; checked with go-licenses in CI.
  • golang.org/x/image v0.46.0 (BSD-3-Clause, released 2026-09-08), added by WP-36: WebP/BMP/TIFF decoders for the golden harness (internal/testutil/golden) and font/basicfont for the fixture generator (testdata/gen). Decode-only, test support; the service decodes through libvips.
  • github.com/caarlos0/env/v11 v11.4.1 (MIT, released 2026-05-01) and github.com/goccy/go-yaml v1.19.2 (MIT, released 2026-01-08), added by WP-04: the XI_* environment parser and the strict YAML config file decoder chosen in go-standards §7. Both have no transitive dependencies and are imported only by internal/config.
  • github.com/ebitengine/purego v0.11.1 (Apache-2.0, released 2026-09-18, no dependencies), added by WP-71: loads ONNX Runtime with dlopen in internal/detect/ort without cgo (ADR 0010); credited in NOTICE.
  • Source code ported or adapted from other projects keeps its licence obligations. imgproxy is Apache-2.0 (not MIT; only imgproxy-docker-base and imagor-base are MIT): every file derived from it (for example the BMP/ICO codecs) keeps the upstream copyright header plus a modification notice, and the repository NOTICE file credits imgproxy and reproduces any upstream NOTICE text that applies. MIT-licensed build scripts (imgproxy-docker-base) keep their copyright notice in docker/base/.
  • build-deps.sh runs a license gate that fails on any forbidden license; every image contains /opt/xtandard/share/licenses/ and SOURCES.md with exact source URLs and versions.
  • Test fixtures must be redistributable; licenses recorded in testdata/LICENSES.md.
  • External tools that are only run, never linked, vendored or shipped, may carry any licence, like MinIO in compose.test.yml. The benchmark (WP-38, bench/) runs k6 (AGPL-3.0) from its unmodified grafana/k6 image as the load generator, and Caddy (Apache-2.0) and darthsim/imgproxy (Apache-2.0) as services; its fixtures are generated from testdata/gen (CC0) at run time.
  • Patent-encumbered codecs (HEVC decode/encode, H.264 encode) are a separate question from copyright licenses. Resolved 2026-09-27 (ROADMAP open questions 1 and 2): H.264 and HEVC video encoding (libx264, libx265) exist only in the gpl flavor, and their patent review is the deployer’s responsibility; slim and full keep H.264/HEVC decode (FFmpeg h264/hevc, libde265) and HEIC still-image encoding through kvazaar (BSD) behind XI_HEIC_ENCODE (default off).
  • Some capabilities cost more work (own BMP/ICO loaders, own SSIM, PDFium integration) or are unavailable in slim and full (H.264/HEVC video encoding, which only the gpl flavor has; x265-quality HEIC encoding).
  • GPL components are available only through the opt-in gpl flavor (amendment below). Other GPL builds users make themselves are unsupported and must not be published under the project name.
  • Status: accepted (owner decision, 2026-09-27, final).
  • Reasoning: the owner does not sell this project and does not want licence purity to limit features. The GPL exclusions cost real capability (H.264 MP4 output, the format every browser and phone plays; HEVC video), while nobody is forced to take GPL code if it lives in a separate, clearly labelled image.
  • Decision: add a third base image flavor (the app image built on it with BASE_BUILDER/BASE_RUNTIME inherits it), gpl = full + FFmpeg rebuilt with --enable-gpl + x264 (GPL-2.0-or-later, H.264 encode) + x265 (GPL-2.0-or-later, HEVC encode). It keeps everything full has (dav1d, libvpx, libaom, ONNX Runtime, models). Tags ghcr.io/xantiagoma/xtandard-image-base:<vips>-r<G>-gpl[-builder], pins in docker/base/versions-gpl.sh. As distributed, its FFmpeg libraries and CLIs are one GPL-2.0-or-later work; the image label is org.opencontainers.image.licenses="GPL-2.0-or-later AND MIT" and /opt/xtandard/share/licenses/LICENSE-GPL.md states it, lists every component with its SPDX licence, and points to the corresponding source (SOURCES.md + docker/base/).
  • What stays permissive: the Go source (MIT, and Go modules keep the MIT/BSD/Apache/ISC allowlist), and the slim and full images, which contain no GPL code, keep the MIT label and keep the strict licence gate with unchanged results. The gpl stages start from full-deps, so they never change slim or full.
  • Scope: only x264, x265 and GPL FFmpeg are allowed, through an explicit allowlist (XI_GPL_COMPONENTS in versions-gpl.sh) that the licence gate reads in its gpl mode (check-licenses.sh --allow-gpl); AGPL, SSPL, nonfree, --enable-version3 for a GPL-2.0 entry, unknown licences and any other GPL component still fail. poppler, exiv2 and GPL dssim are not added back: they were replaced (PDFium, own metadata handling, own SSIM), so there is nothing to gain. libheif is not rebuilt against x265; HEIC encoding stays on kvazaar.
  • Patents: H.264 and HEVC are covered by patent pools. Neither the image nor the project grants a patent licence; whoever deploys or distributes the gpl image reviews the licences and patents that apply to them. The docs (README, docker/base/README.md, LICENSE-GPL.md) say so plainly.
  • Runtime: the app picks the video encoder at startup by probing avcodec_find_encoder_by_name (docs/FORMATS.md “Video output”), so one binary serves full and gpl.

Amendment 2026-09-27 (WP-97): long-tail inputs, Ghostscript stays out

Section titled “Amendment 2026-09-27 (WP-97): long-tail inputs, Ghostscript stays out”
  • Status: accepted (WP-97; owner asked for the widest input support and delegated the AGPL judgement: “if you judge AGPL in a network service too risky, stop at documenting it”).
  • Added, all permissive and all in slim (so in every flavor): jxrlib (Microsoft, BSD-2-Clause) for JPEG XR, built from the 4creators commit Debian packages with Debian’s and our patches (docker/base/patches/jxrlib), linked by the Go shim only (internal/vips/jxr.c), listed in XI_COMPONENT_LICENSES (jxrlib is unmaintained C code run on untrusted input in-process: it is fuzzed and patched, see FORMATS §1.6, and that residual risk is accepted for the format); and more ImageMagick coders (same ImageMagick licence, no new library). WBMP and ICNS are decoded by our own Go code (MIT).
  • Not added: Ghostscript (AGPL-3.0), which EPS/PS/AI input needs, not even in the gpl flavor, whose allowlist stays x264, x265 and GPL FFmpeg. Reasons: (1) linked into the server (ImageMagick --with-gslib), AGPL-3.0 §13 would extend to the whole gpl image and oblige every deployer to offer the corresponding source to every network user; (2) the alternative, ImageMagick’s gs delegate, is a program the policy forbids for every coder, and allowing it means running a full PostScript interpreter on untrusted uploads whose -dSAFER sandbox has a long record of bypasses (file read/write and command execution); (3) either way a crash or exploit sits inside the request-serving process. The licence gate keeps refusing ghostscript, libgs.so and gsapi_new_instance everywhere. If EPS is ever needed, the documented route is an external converter (Ghostscript in its own sandboxed container, called over the network), which keeps AGPL code out of this image and its licence.

Amendment 2026-09-27 (WP-99): Ghostscript in the gpl flavor, out of process, off by default

Section titled “Amendment 2026-09-27 (WP-99): Ghostscript in the gpl flavor, out of process, off by default”
  • Status: accepted (owner decision, 2026-09-27, final, after reviewing the reasons of the WP-97 amendment above). Supersedes that amendment’s “not even in the gpl flavor” for Ghostscript; its reasoning still decides the shape.
  • Decision: the gpl flavor adds Ghostscript (AGPL-3.0-or-later) as the single program /opt/xtandard/bin/gs, never as a library, and the server runs it only when XI_FORMATS_EPS_ENABLED=true (default false), one sandboxed subprocess per page (ADR 0011). This answers reasons (1) and (3) above: nothing links AGPL code, and a crash or exploit sits in a short-lived child process with resource limits, not in the request-serving process. Reason (2), -dSAFER’s record, is why it is off by default and why ADR 0011 lists what the sandbox does not protect.
  • Licence gate: XI_GPL_COMPONENTS gains ghostscript=AGPL-3.0-or-later; check-licenses.sh --allow-gpl accepts it only with exactly that licence and only as the gs program (--ghostscript: minimal device list, libc only). AGPL for any other component, libgs in any library, and Ghostscript in slim or full still fail. The gpl image label becomes AGPL-3.0-or-later AND GPL-2.0-or-later AND MIT, and LICENSE-GPL.md states the AGPL part and where its source is.
  • slim and full are unchanged: no Ghostscript, strict gate, MIT label. Without Ghostscript an EPS is 422 (“EPS needs the gpl image with XI_FORMATS_EPS_ENABLED=true”), except a DOS EPS file with an embedded TIFF preview, which every flavour decodes from that preview (TIFF, already supported).
  • AGPL obligations: the image ships Ghostscript unmodified from its release tarball (SOURCES.md); distributing the gpl image means offering that source; modifying Ghostscript and serving EPS with it brings §13’s duty to offer the modified source to network users. Legal review of a deployment stays the deployer’s.

Amendment 2026-09-28 (WP-103): LibRaw snapshot, X3F tools, Adobe DNG SDK, GoPro GPR SDK

Section titled “Amendment 2026-09-28 (WP-103): LibRaw snapshot, X3F tools, Adobe DNG SDK, GoPro GPR SDK”
  • Status: accepted (WP-103; the owner asked for the widest RAW support: “don’t let licence purity limit features”, gpl amendment above). Owner decision 2026-09-28 (final): the Adobe DNG SDK ships only in the gpl flavor, and the GoPro GPR SDK with it (LibRaw reaches VC-5 through the DNG SDK).
  • Per flavor, compiled into libraw.so/libraw_r.so only (docker/base/build-libraw.sh), licence texts in share/licenses/, sources in SOURCES.md:
    • slim and full: the LibRaw snapshot with the X3F tools (build-libraw.sh in the deps stage). No DNG SDK, no GPR SDK: their stage (libraw-deps-src) and pins (versions-gpl.sh) are never read by a slim or full stage, and the strict gate fails if the SDK shows up (the RTTI names 12dng_negative/8dng_host in any library, or a dng-sdk/DNGSDK pin in versions.sh/versions-full.sh), and verify-image.sh fails a slim or full image that carries share/licenses/dng-sdk or gpr or whose LibRaw reports the SDK capabilities. JPEG XL DNG and GoPro GPR keep the WP-101 behaviour there: the embedded preview, or 422 naming the gpl image.
    • gpl: LibRaw rebuilt in the gpl-deps stage (build-libraw.sh --with-sdks) with the X3F tools, the Adobe DNG SDK and the GoPro GPR SDK as static, hidden-visibility archives. dng-sdk=LicenseRef-Adobe-DNG-SDK is in XI_GPL_COMPONENTS of versions-gpl.sh (the gate accepts that licence for that entry only, like the AGPL for Ghostscript), dng-sdk and gpr are in its XI_COMPONENT_LICENSES, and LICENSE-GPL.md lists both with a paragraph on the DNG SDK terms.
    • LibRaw is pinned to a snapshot of its master branch (a commit, not a release), same LGPL-2.1 terms; one snapshot per base release, camera-list diff in docker/base/README.md.
    • X3F tools (Sigma Foveon), BSD-3-Clause (Copyright (c) 2010 Roland Karlsson), shipped inside LibRaw’s tree and enabled with -DUSE_X3FTOOLS; its notice is extracted to share/licenses/libraw/LICENSE.x3f-tools and the libraw bundle entry becomes (LGPL-2.1-only OR CDDL-1.0) AND BSD-3-Clause.
    • GoPro GPR SDK (VC-5 decoder only), Apache-2.0 OR MIT, https://github.com/gopro/gpr/blob/master/LICENSE.txt .
    • Adobe DNG SDK 1.7.1 (source only, without its bundled XMP SDK, libjxl and libjpeg), under the Adobe DNG SDK License Agreement (dng_sdk_1_7_1/LICENSE.txt, shipped as share/licenses/dng-sdk/LICENSE.txt). It has no SPDX identifier; the gate knows it as LicenseRef-Adobe-DNG-SDK. Terms checked: a non-exclusive, worldwide, royalty-free licence to use, reproduce, modify, distribute and sublicense the Software for any purpose; copyright notices must be kept; Adobe’s marks may not be used to endorse the product; no warranty and a liability cap. Two terms go beyond MIT/BSD and are accepted knowingly: (1) indemnification: whoever distributes the Software “in a commercial product” agrees to defend and indemnify Adobe against claims arising from that distribution; (2) the agreement is governed by California law and terminates on material breach. It is permissive (no copyleft, no field-of-use or non-commercial restriction), so it fits the policy’s intent; still, the owner kept it out of the default images so that slim and full stay MIT/BSD/Apache/LGPL-only: whoever picks the gpl image already reviews extra terms, and a deployer that redistributes it commercially takes on the indemnity for the SDK part.
  • Risk: the three decoders are C/C++ code run in-process on untrusted input. The VC-5 decoder in particular is reference code whose checks are assert()s; fuzzing found and fixed memory errors in it (docker/base/patches/gpr), and the shim hands the DNG SDK only what LibRaw cannot decode itself (JPEG XL and VC-5 raw data). The residual risk is recorded in docs/FORMATS.md §2.
  • Size: see docker/base/README.md (Sizes).

Amendment 2026-09-28 (WP-108): scientific and legacy long tail

Section titled “Amendment 2026-09-28 (WP-108): scientific and legacy long tail”
  • Status: accepted (WP-108; the owner asked for every long-tail item, EMF/WMF in the gpl flavor only).
  • Every flavor (permissive, strict gate unchanged):
    • Basis Universal transcoder 2.50 (Binomial LLC, Apache-2.0), compiled with the app’s MIT wrapper into libxibasisu.so in the slim deps stage (docker/base/build-basisu.sh) for KTX2. Apache-2.0 is on the allowlist; its NOTICE (attribution, trademark) is shipped in share/licenses/basisu and reproduced in the repository’s NOTICE (§4(d)); the one modified file (patches/basisu) carries a notice of the change (§4(b)). Transcoder only: no encoder, no bundled zstd (the base’s BSD-3-Clause libzstd is linked).
    • ImageMagick PICT and PCD coders: already compiled into the base’s ImageMagick (ImageMagick licence), only allowed by policy.xml; no new code.
    • FITS, DICOM, MNG/JNG and the KTX2 container are read by the app’s own Go code (MIT), not by cfitsio (the roadmap’s libvips fitsload), DCMTK/GDCM or ImageMagick’s MNG coder: less C on untrusted input and no new base dependency. JPEG and JPEG 2000 frames inside DICOM go to the base’s libjpeg-turbo and OpenJPEG through libvips.
  • gpl flavor only: WMF and EMF. No permissive WMF/EMF renderer exists (format-gap §3.2: libwmf is LGPL, libemf2svg and libUEMF are GPL-2.0, LibreOffice and Inkscape are far larger). The gpl flavor adds, in build-gpl-metafile.sh:
    • libwmf 0.2.16: LGPL-2.0-or-later, which strictly the strict gate would allow; it ships with its 13 URW Type 1 fonts (GPL; libwmf needs them for text metrics, a conversion fails without them) and it has no use without the GPL program below, so the owner’s decision keeps it with that program in gpl. Its SVG device is patched (patches/libwmf: namespaces, exact colours, escaped text).
    • libemf2svg 1.8.1 with its vendored libUEMF: GPL-2.0-only. libemf2svg=GPL-2.0-only joins XI_GPL_COMPONENTS; the strict gate (slim, full) refuses libemf2svg by name and by the content markers libemf2svg.so and emf2svg_is_emfplus, and verify-image.sh fails a slim or full image that carries the program, either library or their licences.
    • xi-metafile2svg: the app’s MIT driver (docker/base/metafile) linking both, a GPL-2.0-only work as built. It is a separate program: the server runs it as a sandboxed subprocess (the Ghostscript sandbox of ADR 0011, internal/sandbox) and never links either library, so the server binary stays MIT. LICENSE-GPL.md and SOURCES.md describe it; the image label is unchanged (AGPL-3.0-or-later AND GPL-2.0-or-later AND MIT already covers a GPL-2.0-only component under “GPL-2.0”).
  • Risk: the Basis Universal transcoder runs in-process on untrusted KTX2 files (fuzzed with libFuzzer + ASan and through FuzzBasisKTX2; aborts turned into exceptions); ImageMagick’s PICT and PCD coders run in-process behind a Go header parser and the magick limits; libwmf and libemf2svg are old C code, contained by the subprocess sandbox. Details in docs/FORMATS.md §1.8.
  • Size: see docker/base/README.md (Sizes).

Amendment 2026-10-04 (WP-120): audio and the video-transformation FFmpeg build

Section titled “Amendment 2026-10-04 (WP-120): audio and the video-transformation FFmpeg build”
  • Status: accepted (WP-120; owner decision 2026-10-04: video transformations with audio, ADR 0012).
  • full and gpl only; slim unchanged. FFmpeg gains libswresample (LGPL-2.1+), its native audio decoders (AAC, MP3, MP2, Opus, Vorbis, FLAC, ALAC, AC-3, E-AC-3, PCM) and encoders (AAC, FLAC, PCM), more demuxers and muxers (MPEG-TS, HLS, DASH, segment, M4A, MP3, Ogg, Opus, ADTS, WAV, FLAC) and filters (drawtext, loudnorm, aresample, amix, fades, …). All of it is FFmpeg’s own LGPL code; the build is still --disable-gpl --disable-nonfree without --enable-version3 in full, and the gpl flavour still rebuilds exactly full’s configuration plus x264/x265. Still only the file and pipe protocols, no network, no concat/HLS/DASH demuxer.
  • New libraries (dynamically linked, licence texts in share/licenses/{opus,lame}, sources in SOURCES.md, pins in versions-full.sh):
    • libopus 1.6.1: BSD-3-Clause (Xiph.Org and contributors), https://opus-codec.org/license/ . Opus encoder for WebM/Ogg. The Opus patent licences of the contributors (Xiph, Microsoft/Skype, Broadcom) are royalty-free and listed at the same address. Built without the optional deep-learning features (no model weights).
    • LAME 3.100: LGPL-2.0-or-later, https://lame.sourceforge.io/license.txt . libmp3lame only, without the frontend and without its mpglib decoder. MP3 patents expired in 2017.
  • Already in slim and now also linked by FFmpeg: FreeType (used under the FTL, its BSD-style licence; it is dual FTL/GPL-2.0 and the GPL option is not taken), HarfBuzz (MIT), FriBidi (LGPL-2.1+), Fontconfig (MIT-style, HPND-sell-variant), and the DejaVu fonts (Bitstream Vera licence). No new licence text is needed for them.
  • Not built: FDK-AAC (libfdk_aac, nonfree with FFmpeg; --enable-nonfree fails the gate), libshine, TwoLAME, Vorbis encoding (no need: Opus), any GPL audio filter (rubberband, frei0r stay in the gate’s refused switches).
  • Gate: no change to check-licenses.sh. The strict gate keeps refusing GPL/nonfree FFmpeg in full; opus BSD-3-Clause and lame LGPL-2.0-or-later join XI_COMPONENT_LICENSES for the gpl bundle check. verify-image.sh asserts the exact audio encoder set (aac flac libmp3lame libopus pcm_s16le), the protocol set (file pipe) and the absence of the concat/HLS/DASH/lavfi demuxers, and runs audio, filter-graph and HLS/DASH packaging round trips.
  • Patents: AAC-LC, AC-3/E-AC-3 decoding, H.264 and HEVC may be covered by patent pools in some jurisdictions; as in the 2026-09-27 amendment, the images grant no patent licence and the deployer reviews what applies.

One line per direct Go dependency (go-standards §10): module, version, licence, last release date, reason.

  • github.com/prometheus/client_golang v1.24.1 (Apache-2.0, 2026-07-24): metrics on a private registry, promhttp exposition (WP-33, internal/obs/metrics).
  • github.com/prometheus/client_model v0.6.2 (Apache-2.0, 2025-04-11): already required by client_golang; imported directly only by metrics tests to read samples without prometheus/testutil (which would add kylelemons/godebug).
  • go.opentelemetry.io/otel, /otel/sdk, /otel/trace, /otel/metric v1.46.0 (Apache-2.0, 2026-08-25): opt-in tracing, W3C propagation, resource attributes with semconv/v1.43.0 (WP-33, internal/obs/tracing). otel/metric is used only for a no-op meter provider so otelhttp does not read the global one.
  • go.opentelemetry.io/contrib/exporters/autoexport v0.71.0 (Apache-2.0, 2026-08-26): span exporter from the standard OTEL_* variables (OTLP http/grpc, console, none). It pulls gRPC and the OTLP metric/log exporters in as indirect modules (all Apache-2.0/BSD-3); they are only linked, never started, while tracing is off.
  • go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.71.0 (Apache-2.0, 2026-08-26): server span middleware, applied only when tracing is on.
  • github.com/google/go-cmp v0.7.0 (BSD-3-Clause, 2025-01-14): test diffs (go-standards §8).
  • cloud.google.com/go/storage v1.68.0 (Apache-2.0, 2026-09-17): GCS source backend (WP-14, internal/fetch/gcssrc, depguard storage-sdks keeps it there). Reads object attrs then streams the body pinned to that generation; endpoint override for emulators. Pulls in the Google auth, gRPC and GCP OpenTelemetry detector modules as indirect dependencies (Apache-2.0/BSD-3/MIT).
  • google.golang.org/api v0.293.0 (BSD-3-Clause, 2026-08-11): already required by the storage client; imported directly for option (credentials, endpoint) and googleapi.Error (status → errs.Kind) in internal/fetch/gcssrc.
  • github.com/fsouza/fake-gcs-server v1.56.1 (BSD-2-Clause, 2026-08-24): test only. In-process fakestorage server for internal/fetch/gcssrc unit tests; the same project’s container image backs the fake-gcs service in compose.test.yml for integration tests. Never imported by non-test code. Brings gorilla/mux/gorilla/handlers (BSD) and pkg/xattr (BSD-2) as indirect modules, linked only into the test binary.
  • github.com/aws/aws-sdk-go-v2 v1.47.1 with /config v1.33.6, /credentials v1.20.6, /service/s3 v1.113.4, /service/sts v1.51.1, and github.com/aws/smithy-go v1.28.2 (all Apache-2.0, released 2026-09-24 / smithy 2026-09-18): the s3 source backend (WP-13, internal/fetch/s3src, confined there by depguard). config supplies the default credential chain (env, shared files, IRSA web identity, ECS/EC2 roles), sts the optional assume-role, smithy-go the typed API/HTTP errors used for status mapping. Indirect SDK modules (imds, sso, ssooidc, signin, internal/*) are the same repository and licence. Checksums are set to when_required so R2, B2 and self-hosted stores accept requests. Integration and acceptance tests run against RustFS (rustfs/rustfs:1.0.0, Apache-2.0, pinned by digest in compose.test.yml and compose.acceptance.yml) as an external compose service only; nothing from it is linked, vendored or shipped. RustFS replaced MinIO (AGPL-3.0) in 2026-09 because MinIO stopped publishing its self-hosted community images and the suite had to pin a third-party rebuild.
  • github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.8.1 (MIT, 2026-09-09): Azure Blob Storage client for the azure source (WP-15, internal/fetch/azuresrc only, depguard storage-sdks). v1.8.1 over v1.8.0 for its CRLF-injection fix; it pulls apache/arrow-go/v18 (Apache-2.0) with google/flatbuffers (Apache-2.0), goccy/go-json (MIT), klauspost/compress (BSD-3) and klauspost/cpuid (MIT), pierrec/lz4 (BSD-3), zeebo/xxh3 (BSD-2) and golang.org/x/exp (BSD-3) as indirect modules for its optional Arrow list format. None of them is imported by our code.
  • github.com/Azure/azure-sdk-for-go/sdk/azcore v1.23.1 (MIT, 2026-08-27): azblob’s pipeline types (ClientOptions, ResponseError, ETag, policy.Transporter) used directly by azuresrc.
  • github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.14.1 (MIT, 2026-08-27): DefaultAzureCredential (environment, workload identity, managed identity, Azure CLI) when an azure source has no key, connection string or SAS. Indirect: AzureAD/microsoft-authentication-library-for-go (MIT), golang-jwt/jwt/v5 (MIT), kylelemons/godebug (Apache-2.0), pkg/browser (BSD-2), golang.org/x/crypto (BSD-3).
  • github.com/jlaffaye/ftp v0.2.4 (ISC, 2026-08-22): FTP client for internal/fetch/ftpsrc (WP-17): explicit TLS, EPSV/PASV that ignores the PASV reply’s address by default, SIZE/MDTM/RETR. Its only requirements (testify, yaml) are test-only and never linked.
  • github.com/pkg/sftp v1.13.11 (BSD-2-Clause, 2026-07-12): SFTP client for internal/fetch/sftpsrc (WP-17); its request server is used only by the package’s in-process test fake. Pulls in github.com/kr/fs v0.1.0 (BSD-3-Clause, 2018-05-06) as an indirect module.
  • github.com/redis/go-redis/v9 v9.22.0 (BSD-2-Clause, 2026-08-03): Redis-protocol client for the redis cache tier (WP-55, internal/cache/redis, depguard storage-sdks keeps it there). Pulls in go.uber.org/atomic v1.11.0 (MIT) and github.com/cespare/xxhash/v2 (MIT, already indirect) as indirect modules; its ginkgo/gomega test requirements are never linked. The integration tests run against Valkey (valkey/valkey:9.1.2-alpine, BSD-3-Clause, pinned by digest in compose.test.yml) as an external compose service only; Redis server images are not used (RSALv2/SSPL/AGPL).
  • golang.org/x/crypto v0.57.0 (BSD-3-Clause, 2026-09-08): ssh client for internal/fetch/sftpsrc (WP-17) with FixedHostKey-style pinning (no TOFU); previously an indirect module at v0.55.0.
  • github.com/pelletier/go-toml/v2 v2.4.3 (MIT, 2026-07-05): TOML config files (WP-81, ADR 0007), internal/config only (depguard toml-only-in-config). No dependencies. The TOML document is decoded to a map and handed to the same strict goccy/go-yaml decoder as YAML and JSON.
  • github.com/danielgtaylor/huma/v2 v2.39.1 (MIT, 2026-07-29): OpenAPI 3.1 document builder (ADR 0008, WP-82): its OpenAPI model, JSON Schema registry and AddOperation, in internal/apidoc only (depguard huma-only-in-apidoc). No adapter or router is used and no huma package variable is assigned (TestNoHumaGlobals). The build links only huma’s core packages (casing, negotiation, validation, yaml), which import the stdlib; the router and test modules in its go.mod (chi, gin, fiber, testify, …) appear in go.sum only.
  • github.com/santhosh-tekuri/jsonschema/v6 v6.0.3 (Apache-2.0, 2026-06-28): test only (depguard jsonschema-only-in-tests). Compiles internal/config/config.schema.json (draft 2020-12) and validates the corpus of example config files against it (WP-81, ADR 0007); also the JSON Schema 2020-12 validator for the OpenAPI contract tests (internal/apidoc, ADR 0008) and the imgproxy option catalogue schema (internal/dialect/imgproxy). Its only requirement, golang.org/x/text (BSD-3), is already in the graph; dlclark/regexp2 is listed for its own tests and not linked.