Add spdx_expression to pm_licenses

Add a nullable spdx_expression text column so a license row can hold an expression instead of a single spdx_identifier. One row = one identifier OR one expression; multiplicity is handled at the package tuple level (a list of row ids).

  • Migration via the Rails generator
  • Add the spdx_expression column (text, max 1024 chars, unique index)
  • Relax spdx_identifier to nullable so expression-only rows need no identifier; the column is deprecated but not dropped, with the drop deferred to post-#606525
  • Update PackageMetadata::License: valid with spdx_identifier OR spdx_expression; presence validation requires at least one to be non-null
  • spdx_expression gets its own length cap (1024 chars) separate from the identifier cap
  • Make uniqueness cover expressions (unique index on spdx_expression)
  • Regenerate structure.sql + dictionary

The write path (routing, data object, upsert) is in !250674 (merged), which closes #611126 (closed), #606523 (closed), and #606524 (closed). The read path is in #606525 (closed).

Refs: ee/app/models/package_metadata/license.rb, db/migrate/, db/structure.sql

Edited by Igor Frenkel