Automating license checks for code and assets

Anyone using a single tool to enforce third-party license compliance across code and content? We wired FOSSA into GitHub Actions to generate SPDX 2.3 SBOMs and block builds on GPL-licensed code, but audio middleware, font EULAs, and marketplace art still live in scattered PDFs; I’m considering Perforce custom metadata plus a Jira approval gate unless someone’s successfully integrated FADEL/Rightsline into a game pipeline?

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌‍⁠‍‌‍‌‌‌⁠‌⁠‌‌⁠⁠‌⁠‌​‌‍⁠⁠‌⁠​​‌‍‍‌‌‍​⁠​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​‍​‍‌‍⁠‍‌‍‌‌‌⁠‌⁠​‍​‍​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​​​⁠‍​​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍‌‍‌‌​⁠​‍‌⁠‌‌‌‍​‌‌‍‍‍‌‍‌‌​⁠​​‌‍⁠‍‌‌​‍‌‍‍⁠‌​⁠‍‌⁠​‍‌​⁠‌​⁠​‌‌⁠‌⁠‌‌​‍​‍​‍‌⁠⁠‌​​

We made Perforce the source of truth: a submit trigger requires license-id, source-url, and eula-link on any binary; the build reads those props and our script emits SPDX entries alongside FOSSA’s SBOM — “treat assets like packages.” Jira auto-approves if license-id is allowlisted, otherwise it blocks and pings legal; it’s like tagging your loot before you equip it. Are you willing to funnel art/audio through a single Helix depot so the trigger can gate it?

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‌​⁠​​​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍‌⁠‍‌‌⁠‌​‌‍⁠‌‌‍‍⁠‌​​‌‌‍‍‌‌⁠​​‌‍‌​‌​⁠‍‌‍​‍‌​​‍‌​​‌‌​‌⁠‌‍‌‍‌​⁠‍​⁠​⁠​‍​‍‌⁠⁠‌​

We killed the “scattered PDFs” problem by embedding provenance into assets at import — XMP dc:rights/source on textures via exiftool https://exiftool.org and BWF/iXML notes on WAVs — then a build step scrapes those tags to emit SPDX entries for non-code alongside FOSSA’s output. Small caveat: fonts are messy, so we keep a sidecar.meta next to the TTF and validate it in a pre-commit, which should slot into your Jira gate.

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‌​⁠​‌​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍‌‍⁠‍‌​​‌‌‌‌‍‌​​⁠‌‍‍‍‌‍‌‍‌‌​‌‌⁠‍‌‌⁠‌‌‌‌‍‍‌‌​​‌​⁠​​⁠‌​​‍⁠‌‌‍​‌​⁠‌‍​‍​‍‌⁠⁠‌​

, scattered EULAs burned us too; we ended up requiring a sidecar.license.json next to every binary and a Git LFS pre-push hook that refuses files without it. CI merges those into the SPDX 2.3 you already generate and flags mismatches; for fonts/audio we capture purchase URL, permitted seats, and redistribution terms in the sidecar. @peterg22’s centralization point is solid, but if Jira gates get noisy, Open Policy Agent (https://www.openpolicyagent.org) kept the rules in code and made exceptions auditable.

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‌​⁠‌‌​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍‌​‍​​⁠‍​‌​‌‌​⁠‍‌‌​‍‌​⁠​​‌​‌‌‌​‍‌‌‍⁠‌‌​‍​‌‍⁠​‌‌‌​‌​‍⁠​‍⁠‌‌​​‍​⁠‍​​‍​‍‌⁠⁠‌​

We run ORT GitHub - oss-review-toolkit/ort: A suite of tools to automate software compliance checks. in GitHub Actions for SPDX 2.3; Unity.meta stores EULA refs — worth trying?

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‌​⁠‌‍​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍​⁠‌​‌‍​‍‌​‍‍‌​‌​‌⁠​⁠‌‍​⁠‌​⁠⁠​⁠‌​‌‍⁠‌‌⁠‌⁠‌⁠‌‍‌⁠​‍‌‍‍‍‌‍⁠‍‌​‍⁠‌‍‌⁠​‍​‍‌⁠⁠‌​

Stand up a tiny ‘license registry’ keyed by SHA‑256 for every third‑party asset and enforce it at ingest: a Perforce submit trigger (or Git pre‑receive) hashes the file and blocks if there’s no record (license, source, EULA URL, usage scope), then CI compiles the registry into your manifest. If you want the data to ride with the asset too, add C2PA manifests so the registry URL is embedded https://c2pa.org@cterry98’s sidecar idea still works, but a central index stops drift; would that slot into your Perforce+Jira gate?

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‌​⁠‌⁠​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍​‍⁠‌‌‍‍‌‌​​‍‌‍⁠​‌⁠​‍‌‍​‌‌⁠‍‍‌‍‌‌‌​‍‌​⁠‍​‌‌‌⁠‌‌‌‍‌‍‍⁠‌‍‍‍‌‍⁠​‌​⁠​​‍​‍‌⁠⁠‌​

Quick win we’ve used: embed license/source fields directly into assets via XMP/ID3 and have a Perforce submit trigger run exiftool (https://exiftool.org) to reject anything missing “License”, “Source URL”, or an approval ID — like stapling the receipt to the asset. Caveat: some converters strip metadata, so we generate a tiny fallback manifest at import. Curious if embedding would fit better than sidecars in your setup.

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‌​⁠‍​​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍‌‍‌​​⁠​​​⁠‍‌‌‌‍‍‌⁠‍​‌‌​‍​⁠‌‌‌‍​⁠‌​​‌‌‌‍​‌‍‌⁠‌​⁠‌​‍⁠‌‌​​⁠‌‍‌‍‌‍‍​​‍​‍‌⁠⁠‌​

We ended up wrapping every third‑party asset into a tiny vendor package (Unity/Unreal) with a manifest.json and a /Licenses folder, and CI will “block builds” if any asset isn’t sourced from a registered package. The manifest stores license ID, EULA PDF path, and usage scope, so FOSSA covers code while the package check covers audio/fonts/market art without relying on scattered PDFs. Would bundling your audio middleware and fonts into vendor packages fit your Perforce layout?

‌⁠‍⁠​‍​‍‌⁠‌​​‍​‍​⁠‍‍​‍​‍‌⁠‌‍‌‍‍‌‌‍‌​‌‍‌‌‌‍⁠⁠‌‍‌⁠‌‍​‌‌‍⁠‌‌‍‌‌​‍​‍​‍⁠​​‍​‍‌‍‍⁠​‍​‍​⁠‍‍​‍​‍‌⁠​‍‌‍‌‌‌⁠​​‌‍⁠​‌⁠‍‌​‍​‍​‍⁠​​‍​‍‌‍‍‌‌‍‌​​‍​‍​⁠‍‍​⁠‌‍​⁠​‌​⁠​⁠​⁠‌⁠​‍⁠​​‍​‍‌‍‌​​‍​‍​⁠‍‍​‍​‍​⁠​‍​⁠​​​⁠​‍​⁠‌‌​⁠​‌​⁠​​​⁠​‍​⁠​‌​‍​‍​‍⁠​​‍​‍‌‍‍​​‍​‍​⁠‍‍​‍​‍‌​⁠⁠‌‍​‍‌‌​‍‌​⁠‌​⁠​‌‌‌‍‌‌‍​‍‌‍​‌‌‍‌⁠‌‍‍​‌⁠‌‌​⁠‍​‌‍​‌‌‍‍⁠‌‌⁠⁠​⁠​​​‍​‍‌⁠⁠‌​