Operations


Publish

Creates attestations from build information and published them to the attestation store.

Path

  • /packages/{type}/{namespace}/{name}/{version}/attestations

  • /packages/{type}/{name}/{version}/attestations (when namespace is absent)

Path Variables

  • {type}: The package type (e.g., oci, maven)

  • {namespace}: The package namespace or organization (may be omitted)

  • {name}: The package name

  • {version}: The package version

Consumes

  • application/json

  • application/x-www-form-urlencoded

  • multipart/form-data

Produces

  • application/json (Buffered: Returns a JSON array containing all results)

  • application/x-ndjson (Streaming: Returns Newline Delimited JSON objects as they become available)

Request Body

The request body must be a JSON object (for application/json) or form fields (for form-encoded/multipart) matching the following structure:

{
  "sha256": "73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497", (1)
  "repositoryUrl": "artifactory.example.com/maven-repo-local", (2)
  "buildScan": {
    "ids": [ (3)
      "1234567890aaaa",
      "22222bbb"
    ],
    "queries": [ (4)
      "project:my-app value:\"CI Provider=GitHub Actions\" tag:CI tag:3.4.x"
    ]
  }
}
1 The SHA-256 hash of the package.
2 The repository the package is located in.
3 A list of Build Scan IDs to retrieve information from. Optional.
4 A list of queries to retrieve Build Scan data, using the Develocity advanced search syntax. Optional.

Responses

  • 200 OK: Returns PolicyScan.Result objects.

    • If Accept: application/json (default): Returns a JSON array of results.

    • If Accept: application/x-ndjson: Returns a stream of newline-delimited JSON objects.

  • 400 Bad Request: The request content or criteria is invalid.

  • 401 Unauthorized: The credential information presented (if any) is not allowed access to this endpoint.

  • 403 Forbidden: The endpoint is accessible (authorized) but access to the resource requested is disallowed.

  • 500 Internal Server Error: An error occurred during attestation publishing.

Example Request

curl --verbose --request POST "https://provenance-governor.example.com/packages/oci/testifact/1.0/attestations" \
     --header "Content-Type: application/json" \
     --header "Accept: application/json, application/problem+json" \
     --header "Authorization: Basic $(echo -n 'admin:password' | base64)" \
     --data '
{
  "sha256": "df9b564df8de07153224faa58da743ca6bc281610a6dbbec772535de19bd06e2",
  "repositoryUrl": "repo.example.com/docker",
  "buildScan": {
    "ids": [
      "bjvognekiphus"
    ],
    "queries": [
    ]
  }
}
Form URL-Encoded Request (OCI Package)
curl --verbose --request POST "https://provenance-governor.example.com/packages/oci/testifact/1.0/attestations" \
     --header "Content-Type: application/x-www-form-urlencoded" \
     --header "Accept: application/json, application/problem+json" \
     --header "Authorization: Basic $(echo -n 'admin:password' | base64)" \
     --data-urlencode "sha256=df9b564df8de07153224faa58da743ca6bc281610a6dbbec772535de19bd06e2" \
     --data-urlencode "repositoryUrl=repo.example.com/docker" \
     --data-urlencode "buildScan.ids=bjvognekiphus"
Multipart Form Data Request (OCI Package)
curl --verbose --request POST "https://provenance-governor.example.com/packages/oci/testifact/1.0/attestations" \
     --header "Accept: application/json, application/problem+json" \
     --header "Authorization: Basic $(echo -n 'admin:password' | base64)" \
     --form "sha256=df9b564df8de07153224faa58da743ca6bc281610a6dbbec772535de19bd06e2" \
     --form "repositoryUrl=repo.example.com/docker" \
     --form "buildScan.ids=bjvognekiphus"
JSON Request (Maven Package)
curl --verbose --request POST "https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/attestations" \
     --header "Content-Type: application/json" \
     --header "Accept: application/json, application/problem+json" \
     --header "Authorization: Basic $(echo -n 'admin:password' | base64)" \
     --data '
{
  "sha256": "df9b564df8de07153224faa58da743ca6bc281610a6dbbec772535de19bd06e2",
  "repositoryUrl": "https://repo.example.com/maven2",
  "buildScan": {
    "ids": [
      "bjvognekiphus"
    ],
    "queries": [
    ]
  }
}
Form URL-Encoded Request (Maven Package)
curl --verbose --request POST "https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/attestations" \
     --header "Content-Type: application/x-www-form-urlencoded" \
     --header "Accept: application/json, application/problem+json" \
     --header "Authorization: Basic $(echo -n 'admin:password' | base64)" \
     --data-urlencode "sha256=df9b564df8de07153224faa58da743ca6bc281610a6dbbec772535de19bd06e2" \
     --data-urlencode "repositoryUrl=https://repo.example.com/maven2" \
     --data-urlencode "buildScan.ids=bjvognekiphus"
Multipart Form Data Request (Maven Package)
curl --verbose --request POST "https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/attestations" \
     --header "Accept: application/json, application/problem+json" \
     --header "Authorization: Basic $(echo -n 'admin:password' | base64)" \
     --form "sha256=df9b564df8de07153224faa58da743ca6bc281610a6dbbec772535de19bd06e2" \
     --form "repositoryUrl=https://repo.example.com/maven2" \
     --form "buildScan.ids=bjvognekiphus"

Example Response

{
  "status": "SUCCESS",
    "details": {
    "store": "attestation-store-1"
  }
}

Evaluate

Path

  • /packages/{type}/{namespace}/{name}/{version}/policy-scans/{policy-scan-name}

  • /packages/{type}/{name}/{version}/policy-scans/{policy-scan-name} (when namespace is absent)

Path Variables

  • {type}: The package type (e.g., oci, maven)

  • {namespace}: The package namespace or organization (may be omitted for some package types)

  • {name}: The package name

  • {version}: The package version

  • {policy-scan-name}: The name of the Policy Scan™ to execute

Consumes

  • application/json

  • application/x-www-form-urlencoded

  • multipart/form-data

Produces

  • application/json (Buffered: Returns a JSON array containing all results)

  • application/x-ndjson (Streaming: Returns Newline Delimited JSON objects as they become available)

Request Body

The request body must be a JSON object matching the following structure:

{
  "sha256": "string", (1)
  "repositoryUrl": "string" (2)
}
1 The SHA-256 hash of the package.
2 The repository the package is located in.

Responses

Success Response

  • 200 OK: Returns PolicyScan.Result objects.

    • If Accept: application/json (default): Returns a JSON array of results.

    • If Accept: application/x-ndjson: Returns a stream of newline-delimited JSON objects.

Error Responses

All error responses return an RFC 7807 ProblemDetail JSON object with the following structure:

  • 400 Bad Request: The request content or criteria is invalid.

    {
      "type": "about:blank",
      "title": "Bad Request",
      "status": 400,
      "detail": "Invalid request content. Bad criteria (sha256 or repositoryUrl)."
    }
  • 401 Unauthorized: Authentication not allowed.

    {
      "type": "about:blank",
      "title": "Unauthorized",
      "status": 401,
      "detail": "Full authentication is required to access this resource"
    }
  • 403 Forbidden: Access to specific resource disallowed.

    {
      "type": "about:blank",
      "title": "Forbidden",
      "status": 403,
      "detail": "Access to this resource is forbidden"
    }
  • 404 Not Found: The specified Policy Scan definition was not found.

    {
      "type": "about:blank",
      "title": "Not Found",
      "status": 404,
      "detail": "Policy scan 'build-gate' not found"
    }
  • 429 Too Many Requests: The service is overloaded. This occurs when the connection pool is exhausted due to high concurrency.

    {
      "type": "about:blank",
      "title": "Too Many Requests",
      "status": 429,
      "detail": "The service is experiencing too many requests. Please try again later."
    }

    When receiving a 429 response, implement exponential backoff retry logic. The connection pool exhaustion typically resolves within seconds as in-flight requests complete.

  • 500 Internal Server Error: An error occurred communicating with an external service (Develocity, Artifactory, S3, etc.).

    {
      "type": "about:blank",
      "title": "Internal Server Error",
      "status": 500,
      "detail": "An error occurred while trying to communicate with an external service: Connection refused"
    }

Example Request

JSON Request (OCI Package)
curl --request POST \
  --url https://provenance-governor.example.com/packages/oci/my-app/1.0.0/policy-scans/build \
  --header 'authorization: Basic ***********=' \
  --header 'content-type: application/json' \
  --data '{
  "sha256": "3f6cabfb527d740e79e0f49e2f4e564279d8c74a0bfc4481fc3a44e6b085fe91",
  "repositoryUrl": "example.com/docker"
}'
Form URL-Encoded Request (OCI Package)
curl --request POST \
  --url https://provenance-governor.example.com/packages/oci/my-app/1.0.0/policy-scans/build \
  --header 'authorization: Basic ***********=' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data-urlencode "sha256=3f6cabfb527d740e79e0f49e2f4e564279d8c74a0bfc4481fc3a44e6b085fe91" \
  --data-urlencode "repositoryUrl=example.com/docker"
Multipart Form Data Request (OCI Package)
curl --request POST \
  --url https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/policy-scans/build \
  --header 'authorization: Basic ***********=' \
  --form "sha256=3f6cabfb527d740e79e0f49e2f4e564279d8c74a0bfc4481fc3a44e6b085fe91" \
  --form "repositoryUrl=example.com/docker"
JSON Request (Maven Package)
curl --request POST \
  --url https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/policy-scans/build \
  --header 'authorization: Basic ***********=' \
  --header 'content-type: application/json' \
  --data '{
  "sha256": "3f6cabfb527d740e79e0f49e2f4e564279d8c74a0bfc4481fc3a44e6b085fe91",
  "repositoryUrl": "https://repo.example.com/maven2"
}'
Form URL-Encoded Request (Maven Package)
curl --request POST \
  --url https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/policy-scans/build \
  --header 'authorization: Basic ***********=' \
  --header 'content-type: application/x-www-form-urlencoded' \
  --data-urlencode "sha256=3f6cabfb527d740e79e0f49e2f4e564279d8c74a0bfc4481fc3a44e6b085fe91" \
  --data-urlencode "repositoryUrl=https://repo.example.com/maven2"
Multipart Form Data Request (Maven Package)
curl --request POST \
  --url https://provenance-governor.example.com/packages/maven/com.example/my-maven-app/1.0.0/policy-scans/build \
  --header 'authorization: Basic ***********=' \
  --form "sha256=3f6cabfb527d740e79e0f49e2f4e564279d8c74a0bfc4481fc3a44e6b085fe91" \
  --form "repositoryUrl=https://repo.example.com/maven2"

Example Response

[
  {
    "labels": {
      "policy.my-corp.com/gate": "build"
    },
    "status": "unsatisfied",
    "policyUri": "/policies/ResolvedDependenciesRepositories/disallow-untrusted-repos",
    "policyDescription": "Disallow untrusted Maven repositories.",
    "policyRemediation": "Remove 'https://untrusted.repo.com/maven2' from your build's dependency repositories.",
    "attestationUri": "/packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:prod/uuid",
    "sourcedFromUri": "https://develocity.example.com/s/abcdef1234567",
    "details": {
      "uris": ["https://untrusted.repo.com/maven2"]
    }
  },
  {
    "labels": {
      "policy.my-corp.com/gate": "build"
    },
    "status": "unsatisfied",
    "policyUri": "/policies/PackageUrl/disallow-vulnerable-dependency",
    "policyDescription": "Disallow usage of specific vulnerable package versions.",
    "policyRemediation": "Upgrade 'pkg:maven/org.example/bad-lib@1.0.0' to a non-vulnerable version (e.g., 1.0.1 or higher).",
    "attestationUri": "/packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:prod/uuid",
    "sourcedFromUri": "https://develocity.example.com/s/abcdef1234567",
    "details": {
      "vulnerablePackage": "pkg:maven/org.example/bad-lib@1.0.0",
      "predicateType": "https://cyclonedx.org/schema/sbom/v1.4"
    }
  },
  {
    "labels": {
      "policy.my-corp.com/gate": "build"
    },
    "status": "satisfied",
    "policyUri": "/policies/TrustedPublicKeys/release-pipeline-signer",
    "policyDescription": "Verify all attestations are signed by the release pipeline's trusted key.",
    "policyRemediation": "Ensure the attestation is signed by a trusted key from the release pipeline. Re-run the build if necessary.",
    "attestationUri": "/packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:prod/uuid",
    "sourcedFromUri": null,
    "details": {
      "keyIds": ["abcd1234"]
    }
  },
  {
    "labels": {
      "policy.my-corp.com/gate": "build"
    },
    "status": "not-applicable",
    "policyUri": "/policies/JavaToolchains/disallow-jdk8",
    "policyDescription": "Disallow Java 8 toolchains in new builds.",
    "policyRemediation": "Update build configuration to use Java 11 or higher.",
    "attestationUri": "/packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:prod/uuid",
    "sourcedFromUri": "https://develocity.example.com/s/abcdef1234567",
    "details": {
      "message": "Attestation does not contain 'https://gradle.com/attestation/java-toolchains/v1' predicate. Policy is not applicable."
    }
  },
  {
    "labels": {
      "policy.my-corp.com/gate": "build"
    },
    "status": "satisfied",
    "policyUri": "/policies/BuildTool/only-gradle-builds",
    "policyDescription": "Ensure only Gradle is used as the build tool.",
    "policyRemediation": "Use Gradle as the build tool. Consult migration guides if necessary.",
    "attestationUri": "/packages/maven/com.example/my-app/1.0.0/sha256:73f482a2296dcc654c380979aae3916a1925ff906b1c43a0659f97fd56e44497/attestations/s3:prod/uuid",
    "sourcedFromUri": "https://develocity.example.com/s/abcdef1234567",
    "details": {
      "buildTool": "Gradle"
    }
  }
]

Response Fields:

  • labels - Policy labels used for organizing and selecting policies

  • status - Result status: satisfied, unsatisfied, or not-applicable

  • policyUri - URI identifying the policy that was evaluated

  • policyDescription - Human-readable description of what the policy checks

  • policyRemediation - Guidance on how to fix policy violations (empty if status is satisfied)

  • attestationUri - URI of the attestation that was evaluated against this policy (may be null)

  • sourcedFromUri - URI to the source of the data that produced the attestation (may be null)

  • details - Policy-specific additional information about the evaluation result

Fetch Attestation by ID

Retrieves a specific attestation by its unique identifier.

Path

  • /packages/{type}/{namespace}/{name}/{version}/{digestType}:{digest}/attestations/{instance}/{id}

  • /packages/{type}/{name}/{version}/{digestType}:{digest}/attestations/{instance}/{id} (when namespace is absent)

Path Variables

  • {type}: The package type (e.g., oci, maven)

  • {namespace}: The package namespace or organization (may be omitted)

  • {name}: The package name

  • {version}: The package version

  • {digestType}: The digest algorithm (e.g., sha256)

  • {digest}: The digest value

  • {instance}: The storage instance identifier (e.g., s3:prod-bucket, af:dev)

  • {id}: The unique identifier of the attestation

Instance Identifier Format: The instance identifier follows the format {store-type}:{instance-name}, where:

  • store-type is either s3 or af

  • instance-name matches the configured instance name in your application configuration

Examples: s3:prod-bucket, s3:local-s3, af:main, af:compliance-repo

Produces

  • application/json (Buffered: Returns a JSON array containing the attestation)

  • application/x-ndjson (Streaming: Returns Newline Delimited JSON objects)

Responses

Success Response

  • 200 OK: Returns the attestation envelope as a DSSE-wrapped in-toto Statement.

Error Responses

All error responses return an RFC 7807 ProblemDetail JSON object:

  • 400 Bad Request: The request parameters are invalid (e.g., malformed digest, invalid instance identifier).

    {
      "type": "about:blank",
      "title": "Bad Request",
      "status": 400,
      "detail": "Invalid request content. Bad criteria (sha256 or repositoryUrl)."
    }
  • 401 Unauthorized: Authentication not allowed.

    {
      "type": "about:blank",
      "title": "Unauthorized",
      "status": 401,
      "detail": "Full authentication is required to access this resource"
    }
  • 403 Forbidden: Access to the resource is disallowed (user lacks read permissions for this package/repository).

    {
      "type": "about:blank",
      "title": "Forbidden",
      "status": 403,
      "detail": "Access to this resource is forbidden"
    }
  • 404 Not Found: The attestation was not found (either the ID doesn’t exist or the storage instance is not configured).

    {
      "type": "about:blank",
      "title": "Not Found",
      "status": 404,
      "detail": "No attestation found matching request."
    }

Example Request

curl --request GET \
  --url https://provenance-governor.example.com/packages/maven/com.example/my-lib/1.0.0/sha256:abc123.../attestations/s3:prod-bucket/123e4567-e89b-12d3-a456-426614174000 \
  --header 'authorization: Basic ***********=' \
  --header 'accept: application/json'

Example Response

The response is a DSSE (Dead Simple Signing Envelope) containing the attestation.

{
  "payload": "eyJfdHlwZSI6Imh0dHBzOi8vaW4tdG90by5pby9TdGF0ZW1lbnQvdjEiLCJwcmVkaWNhdGVUeXBlIjoiaHR0cHM6Ly9ncmFkbGUuY29tL2F0dGVzdGF0aW9uL2J1aWxkLXRvb2wvdjEiLCJzdWJqZWN0IjpbeyJuYW1lIjoicGtnOm1hdmVuL2NvbS5leGFtcGxlL215LWxpYkAxLjAuMCIsImRpZ2VzdCI6eyJzaGEyNTYiOiJhYmMxMjMuLi4ifX1dLCJwcmVkaWNhdGUiOnsiYnVpbGRUb29sIjp7Im5hbWUiOiJHcmFkbGUiLCJ2ZXJzaW9uIjoiOC41In19fQ==", (1)
  "payloadType": "application/vnd.in-toto+json", (2)
  "signatures": [ (3)
    {
      "keyid": "SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA",
      "sig": "MEUCIQDx8VjW7UXqBVZFxJe9KQOPQmQr6iXzOK7/dZqN8VQG2AIgKTYDLT0Kv1X5mH0Eo7w3xA4MF7B9j3jV8H2q5YN4R0w="
    }
  ]
}
1 Base64-encoded payload: When decoded, this contains an in-toto Statement with the attestation’s predicate (e.g., build tool information, dependencies, etc.)
2 Payload type: Indicates the payload is an in-toto Statement in JSON format
3 Signatures: Cryptographic signatures verifying the attestation’s authenticity

Understanding the DSSE Envelope Structure:

The returned JSON is a DSSE (Dead Simple Signing Envelope) that wraps the attestation:

  1. payload: Base64-encoded in-toto Statement containing:

    • _type: Always https://in-toto.io/Statement/v1

    • predicateType: The type of attestation (e.g., build tool, dependencies, SLSA provenance)

    • subject: The package being attested about

    • predicate: The actual attestation data (varies by predicate type)

  2. payloadType: Always application/vnd.in-toto+json for in-toto Statements

  3. signatures: One or more cryptographic signatures with:

    • keyid: Identifier of the signing key (SHA256 fingerprint)

    • sig: Base64-encoded signature

To extract the attestation data, decode the payload field from base64, then parse the JSON to access the predicate field.