diff --git a/README.md b/README.md
index e4faef8269bd690303e1c4c97b98b31937deb7b2..09d669261e6667ec712b4710f92f5715da5e1817 100644
--- a/README.md
+++ b/README.md
@@ -256,6 +256,7 @@ It is bound to the `test` stage, and uses the following variables:
 | Input / Variable | Description                            | Default value     |
 | --------------------- | -------------------------------------- | ----------------- |
 | `sbom-disabled` / `GO_SBOM_DISABLED` | Set to `true` to disable this job | _none_ |
+| `TBC_SBOM_MODE`                      | Controls when SBOM reports are generated (`onrelease`: only on `$INTEG_REF`, `$PROD_REF` and `$RELEASE_REF` pipelines; `always`: any pipeline).<br/>:warning: `sbom-disabled` / `GO_SBOM_DISABLED` takes precedence | `onrelease` |
 | `sbom-image` / `GO_SBOM_IMAGE` | Image of cyclonedx-gomod used for SBOM analysis | `registry.hub.docker.com/cyclonedx/cyclonedx-gomod:latest` |
 | `sbom-opts` / `GO_SBOM_OPTS` | [@cyclonedx/cyclonedx-gomod options](https://github.com/CycloneDX/cyclonedx-gomod#usage) used for SBOM analysis | `-main .` |
 
diff --git a/kicker.json b/kicker.json
index df960da1ff442cda4674a2f6ff14807617b75a4c..f709fcfa2330d48973dc414cf2b517994dced62d 100644
--- a/kicker.json
+++ b/kicker.json
@@ -140,6 +140,14 @@
       "description": "This job generates a file listing all dependencies using [cyclonedx-gomod](https://github.com/CycloneDX/cyclonedx-gomod)",
       "disable_with": "GO_SBOM_DISABLED",
       "variables": [
+        {
+          "name": "TBC_SBOM_MODE",
+          "type": "enum",
+          "values": ["onrelease", "always"],
+          "description": "Controls when SBOM reports are generated (`onrelease`: only on `$INTEG_REF`, `$PROD_REF` and `$RELEASE_REF` pipelines; `always`: any pipeline)",
+          "advanced": true,
+          "default": "onrelease"
+        },
         {
           "name": "GO_SBOM_IMAGE",
           "default": "registry.hub.docker.com/cyclonedx/cyclonedx-gomod:latest"
diff --git a/templates/gitlab-ci-golang.yml b/templates/gitlab-ci-golang.yml
index 07fe9f7d25dcc97f82d6e4503ecc3d1ef1e6da60..335998cf78ffe871f1b61885017c8656eb893a47 100644
--- a/templates/gitlab-ci-golang.yml
+++ b/templates/gitlab-ci-golang.yml
@@ -164,7 +164,18 @@ workflow:
     # else (Ready MR): auto & failing
     - when: on_success
 
+# software delivery job prototype: run on production and integration branches + release pipelines
+.delivery-policy:
+  rules:
+    # on tag with release pattern
+    - if: '$CI_COMMIT_TAG =~ $RELEASE_REF'
+    # on production or integration branch(es)
+    - if: '$CI_COMMIT_REF_NAME =~ $PROD_REF || $CI_COMMIT_REF_NAME =~ $INTEG_REF'
+
 variables:
+  # Global TBC SBOM Mode (onrelease -> only generate SBOMs for releases, always -> generate SBOMs for all refs)
+  TBC_SBOM_MODE: "onrelease"
+
   # Default Go project root directory
   GO_PROJECT_DIR: $[[ inputs.project-dir ]]
 
@@ -228,6 +239,8 @@ variables:
   PROD_REF: /^(master|main)$/
   # default integration ref name (pattern)
   INTEG_REF: /^develop$/
+  # default release tag name (pattern)
+  RELEASE_REF: '/^v?[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9-\.]+)?(\+[a-zA-Z0-9-\.]+)?$/'
 
 stages:
   - build
@@ -815,7 +828,13 @@ go-sbom:
     # exclude if disabled
     - if: '$GO_SBOM_DISABLED == "true"'
       when: never
-    - !reference [.test-policy, rules]
+    # 'always' mode: run
+    - if: '$TBC_SBOM_MODE == "always"'
+    # exclude unsupported modes
+    - if: '$TBC_SBOM_MODE != "onrelease"'
+      when: never
+    # 'onrelease' mode: use common software delivery rules
+    - !reference [.delivery-policy, rules]
 
 go-govulncheck:
   extends: .go-base