Skip to content

feat(supply-chain): SPDX and CycloneDX imports with derived SPDX export - #110

Merged
balcsida merged 2 commits into
feat/supply-chain/m3-portfoliofrom
feat/supply-chain/m4-imports
Sep 22, 2026
Merged

balcsida merged 2 commits into
feat/supply-chain/m3-portfoliofrom
feat/supply-chain/m4-imports

Conversation

@balcsida

@balcsida balcsida commented Sep 22, 2026 •

Copy link
Copy Markdown
Owner

Summary

Milestone 4. Depends on #109.

  • POST /v1/supply-chain/imports – SPDX 2.3 JSON and CycloneDX 1.6 JSON only; format detected from the document (a contradicting Content-Type is rejected), other formats/versions rejected with 415 unsupported_format. Each (subject, label) is its own import:<subject>:<label> stream, so a container SBOM never replaces the GitHub observation and an old artifact upload never becomes the current source inventory. Original bytes preserved; uploader recorded separately from the claimed producer (a Tool: ORT string grants nothing); an optional subject_revision is bound only as producer_asserted; idempotent on identical bytes; per-repository quota; non-administrators need a repository-scoped upload grant (PUT /v1/supply-chain/upload-grants). External URLs inside documents are never dereferenced.
  • CycloneDX 1.6 normalizer – nested components flattened with CONTAINS edges, dependencies → DEPENDS_ON, hashes, suppliers, purl qualifiers; license choices kept as the format carries them (a list of license objects has no AND/OR meaning and is kept as a list with a warning); component evidence and inline license text stay only in the preserved original and are flagged (evidence_not_carried, license_text_inline). Fuzzed.
  • Derived SPDX export GET /v1/supply-chain/exports/{id}/derived.spdx.json – GraphNest as creator, links the preserved original by URL + SHA-256 (externalDocumentRefs), assessments only as licenseComments, licenseConcluded always NOASSERTION, validated by GraphNest's own reader before serving. The original download is never altered.
  • Docs – producer examples for Syft (CycloneDX) and ORT (SPDX), what is and is not carried (no native ScanCode/Code Insight adapter is claimed). Migration 035.

Verification

Integration tests: real-format round trips for both formats, stream separation, uploader vs claimed producer, spoofed GitHub tool string lands only in an import stream, producer-asserted binding, idempotency, quota per repository, permission matrix (admin / granted / ungranted / reader / unknown repo), explicit rejections (old versions, mismatched claim, unknown format, malformed, bad label/subject/revision, wrong media type), derived export structure and original preservation.

Implications

  • Migration: 035 additive (imports, upload grants, uploaded_by/upload_label on snapshots).
  • Security: documented trust boundaries in the operations guide.

Part of the Dependencies & Licenses stack (native GitHub stack #114, ten layers, main ← #104 ← #105 ← #106 ← #107 ← #108 ← #109 ← #110 ← #111 ← #112 ← #113). Design: ADR-0017; living plan with the full validation table: docs/execplans/supply-chain.md. All commits are SSH-signed. Nothing here calls a live GitHub Enterprise Server or a live package registry; GitHub and registry behavior is exercised against fixtures and fake servers only.

Stack created with GitHub Stacks CLI

@balcsida
balcsida added this pull request to stack #114 September 22, 2026 21:06
@balcsida balcsida changed the title feat/supply chain/m4 imports feat(supply-chain): SPDX and CycloneDX imports with derived SPDX export Sep 22, 2026
@balcsida
balcsida force-pushed the feat/supply-chain/m4-imports branch 2 times, most recently from 566a255 to 1b896b8 Compare September 22, 2026 22:19
@balcsida
balcsida marked this pull request as ready for review September 22, 2026 22:20
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

balcsida and others added 2 commits September 23, 2026 00:30
…rived SPDX

Accept authenticated SPDX 2.3 JSON and CycloneDX 1.6 JSON uploads into
declared import streams of an authorized repository. The format is
detected from the document, unsupported versions and contradictory
content types are rejected explicitly, original bytes are preserved, the
uploader is recorded separately from the claimed producer, and a
supplied subject revision is bound only as producer_asserted. Identical
bytes are idempotent, per-repository quotas apply, and non-administrators
need a repository-scoped upload grant. The CycloneDX normalizer keeps
nested components, dependencies, hashes, and license choices as the
format carries them and warns about evidence it cannot carry. A derived
SPDX export names GraphNest as creator, links the preserved original by
URL and hash, carries assessments as comments only, and is validated by
the same reader. Migration 035 adds imports and upload grants.

Co-Authored-By: Claude <noreply@anthropic.com>
…exports

Co-Authored-By: Claude <noreply@anthropic.com>
@balcsida
balcsida force-pushed the feat/supply-chain/m4-imports branch from 1b896b8 to 26fbe20 Compare September 22, 2026 22:30
@balcsida
balcsida force-pushed the feat/supply-chain/m4-imports branch from 26fbe20 to 51a70e6 Compare September 22, 2026 22:59
@balcsida
balcsida force-pushed the feat/supply-chain/m4-imports branch from 51a70e6 to 26fbe20 Compare September 22, 2026 23:51
@balcsida
balcsida merged commit 0def80c into main Sep 22, 2026
16 of 24 checks passed
@balcsida balcsida mentioned this pull request Sep 23, 2026
@balcsida
balcsida deleted the feat/supply-chain/m4-imports branch September 23, 2026 07:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant