This repository implements the datamodel defined in spdx-3-model.
This is just a proof of concept and probably roughtly 80% complete, but it has the following features
- a datamodel, using GADTs
- implementing “core” and “software” profile
- complete serialization to JSON
- example outputs are written to
./_testOut/
- example outputs are written to
- complete deserialization from JSON
- conversion from SPDX 2.2 or 2.3 to 3.0
- this uses spdx-tools-hs
{ "@type": "Package", "SPDXID": "urn:spdx:curl-7.50.3-1", "comment": null, "contentIdentifier": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "downloadLocation": null, "externalIdentifiers": [], "externalReferences": [], "homePage": null, "name": "curl-7.50.3-1", "originatedBy": [], "packagePurpose": [], "packageUrl": "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie", "summary": null, "verifiedUsing": [] }
This contanis all properties of Package
, Artifact
and Element
, pulled to one flat JSON object.
For parsing, the type is specified in @type
, and here all fields are filled with dummy data or their default values.
The null
and []
entries are optional.
dropping all optional fields would result in:
{ "@type": "Package", "SPDXID": "urn:spdx:curl-7.50.3-1", "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "name": "curl-7.50.3-1", "packageUrl": "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie" }
Now lets pack the package from above into a collection, a SpdxDocument
in this case.
Lets give it the name ”Tho Document
”, the SPDXID ”urn:spdx:Document
” and the same creationInfo as our Package
.
Additionally we add a rather small Annotation that just contains the text ”some Annotation
” and has our package as the subject.
The subject can either be an inline Element
or a String
which is then the SPDXID.
{ "@type": "SpdxDocument", "SPDXID": "urn:spdx:Document", "comment": null, "context": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "elements": [ { "@type": "Package", "SPDXID": "urn:spdx:curl-7.50.3-1", "comment": null, "contentIdentifier": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "downloadLocation": null, "externalIdentifiers": [], "externalReferences": [], "homePage": null, "name": "curl-7.50.3-1", "originatedBy": [], "packagePurpose": [], "packageUrl": "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie", "summary": null, "verifiedUsing": [] }, { "@type": "Annotation", "SPDXID": "urn:spdx:Annotation0", "comment": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "name": null, "statement": "some Annotation", "subject": "urn:spdx:curl-7.50.3-1", "summary": null, "verifiedUsing": [] } ], "externalIdentifiers": [], "externalReferences": [], "imports": {}, "name": "The Document", "namespaces": {}, "rootElements": [], "summary": null, "verifiedUsing": [] }
Lets create two files (with generated SPDXIDs) contained in our Package, ”urn:File:efe40ac114769e83b4d4971da76295a4
” and ”urn:File:65f2e7526fd42ae9f0893991e2473915
”.
Then add a Relationship which represents this, where one file is inlined and one is referenced and placed in the SpdxDocument
.
This defines two elements which then can be added to the document:
[...] { "@type": "Relationship", "SPDXID": "urn:Relationship:d74e9f23525b8766dc81f5ada441e4fb", "comment": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "from": "urn:spdx:curl-7.50.3-1", "name": null, "relationshipCompleteness": null, "relationshipType": "CONTAINS", "summary": null, "to": [ "urn:File:efe40ac114769e83b4d4971da76295a4", { "@type": "File", "SPDXID": "urn:File:65f2e7526fd42ae9f0893991e2473915", "comment": null, "contentIdentifier": null, "contentType": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "filePurpose": [], "name": "path/to/the/file/f1", "originatedBy": [], "summary": null, "verifiedUsing": [] } ], "verifiedUsing": [] }, { "@type": "File", "SPDXID": "urn:File:efe40ac114769e83b4d4971da76295a4", "comment": null, "contentIdentifier": null, "contentType": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "filePurpose": [], "name": "path/to/the/file/f0", "originatedBy": [], "summary": null, "verifiedUsing": [] } [...]
this is basically roughtly similar to the example generated in _testOut/example.spdx3.json, and can look like:
{ "@type": "SpdxDocument", "SPDXID": "urn:spdx:Document", "comment": null, "context": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "elements": [ { "@type": "Package", "SPDXID": "urn:spdx:curl-7.50.3-1", "comment": null, "contentIdentifier": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "downloadLocation": null, "externalIdentifiers": [], "externalReferences": [], "homePage": null, "name": "curl-7.50.3-1", "originatedBy": [], "packagePurpose": [], "packageUrl": "pkg:deb/debian/curl@7.50.3-1?arch=i386&distro=jessie", "summary": null, "verifiedUsing": [] }, { "@type": "Annotation", "SPDXID": "urn:spdx:Annotation0", "comment": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "name": null, "statement": "some Annotation", "subject": "urn:spdx:curl-7.50.3-1", "summary": null, "verifiedUsing": [] }, { "@type": "Relationship", "SPDXID": "urn:Relationship:d74e9f23525b8766dc81f5ada441e4fb", "comment": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "from": "urn:spdx:curl-7.50.3-1", "name": null, "relationshipCompleteness": null, "relationshipType": "CONTAINS", "summary": null, "to": [ "urn:File:efe40ac114769e83b4d4971da76295a4", { "@type": "File", "SPDXID": "urn:File:65f2e7526fd42ae9f0893991e2473915", "comment": null, "contentIdentifier": null, "contentType": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "filePurpose": [], "name": "path/to/the/file/f1", "originatedBy": [], "summary": null, "verifiedUsing": [] } ], "verifiedUsing": [] }, { "@type": "File", "SPDXID": "urn:File:efe40ac114769e83b4d4971da76295a4", "comment": null, "contentIdentifier": null, "contentType": null, "creationInfo": { "created": "2022-11-13T13:14:36.324980945Z", "createdBy": [ { "actorType": "PERSON", "name": "Some Actor" }, { "actorType": "TOOL", "name": "This Tool" } ], "dataLicense": "CC0-1.0", "profile": [ { "name": "core" }, { "name": "software" }, { "name": "licensing" } ], "specVer": "3.0.0" }, "description": null, "externalIdentifiers": [], "externalReferences": [], "filePurpose": [], "name": "path/to/the/file/f0", "originatedBy": [], "summary": null, "verifiedUsing": [] } ], "externalIdentifiers": [], "externalReferences": [], "imports": {}, "name": "The Document", "namespaces": {}, "rootElements": [], "summary": null, "verifiedUsing": [] }