feat(contract): support "at least one of" material choke groups
Merged
JI
4mo ago+491+491+012345678901234567890123456789-56-56-01234567890123456789
Add new group field to contract materials to denote oneOf behaviour and validation
Ungrouped materials (group == ""): unchanged — required unless optional.
Grouped materials: partition by group value. For each group, at least one member
must be present in the crafted materials; otherwise the group is reported missing
(e.g. at least one material from group "sbom-source" is required: cyclonedx-sbom, spdx-sbom).
A member’s individual optional flag is ignored for grouped materials (the group rule governs).
Closes https://github.com/chainloop-dev/chainloop/issues/3234
Example:
apiVersion: chainloop.dev/v1
kind: Contract
metadata:
name: $C
spec:
materials:
- name: build-ref
type: STRING
- name: sbom-cyclonedx
type: SBOM_CYCLONEDX_JSON
group: sbom
- name: sbom-spdx
type: SBOM_SPDX_JSON
group: sbom
EOF
> go run app/cli/main.go --insecure attestation status 2>&1
...
┌────────────────────────────────────────┐
│ Materials │
├───────────┬────────────────────────────┤
│ Name │ build-ref │
│ Type │ STRING │
│ Set │ No │
│ Required │ Yes │
├───────────┼────────────────────────────┤
│ Group │ sbom │
│ Rule │ at least one of 2 required │
│ Satisfied │ No │
├───────────┼────────────────────────────┤
│ Name │ ↳ sbom-cyclonedx │
│ Type │ SBOM_CYCLONEDX_JSON │
│ Set │ No │
├───────────┼────────────────────────────┤
│ Name │ ↳ sbom-spdx │
│ Type │ SBOM_SPDX_JSON │
│ Set │ No │
└───────────┴────────────────────────────┘
AI assistance: this contribution was produced with assistance from Claude Code (disclosed via the Assisted-by trailer on the commits).