diff --git a/README.md b/README.md
index 0d7019dccb2c4433ccd02bec5ff57e1b890fe2f9..002019548a213d3776be713a9199ff8010a1d80b 100644
--- a/README.md
+++ b/README.md
@@ -412,6 +412,7 @@ It is bound to the `test` stage, and uses the following variables:
 | Input / Variable                       | Description                                                 | Default value        |
 | -------------------------------------- | ----------------------------------------------------------- | -------------------- |
 | `sbom-disabled` / `NODE_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` / `NODE_SBOM_DISABLED` takes precedence | `onrelease` |
 | `sbom-version` / `NODE_SBOM_VERSION`   | The version of @cyclonedx/cyclonedx-npm used to emit SBOM   | _none_ (uses latest) |
 | `sbom-opts` / `NODE_SBOM_OPTS`         | Options for @cyclonedx/cyclonedx-npm used for SBOM analysis | `--omit dev`         |
 
diff --git a/kicker.json b/kicker.json
index b3cd5df508dfaa992c42eb60bff8cade702ce4a0..d1a0a0fd52dab788d82b1e5685a39df4ddf15d09 100644
--- a/kicker.json
+++ b/kicker.json
@@ -154,6 +154,14 @@
       "description": "This job generates a file listing all dependencies using [@cyclonedx/cyclonedx-npm](https://www.npmjs.com/package/@cyclonedx/cyclonedx-npm)",
       "disable_with": "NODE_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": "NODE_SBOM_VERSION",
           "description": "Version of the @cyclonedx/cyclonedx-npm used for SBOM analysis",
diff --git a/templates/gitlab-ci-node.yml b/templates/gitlab-ci-node.yml
index b206ba1d1bd15e46cc71be0d820a33a5ad2768e0..7524752dd74d12a9e8fecfbf89e421d455a84b88 100644
--- a/templates/gitlab-ci-node.yml
+++ b/templates/gitlab-ci-node.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 docker image for Node
   NODE_IMAGE: $[[ inputs.image ]]
   # Default Node project root directory
@@ -835,7 +846,13 @@ node-sbom:
     # exclude if disabled
     - if: '$NODE_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]
 
 node-publish:
   extends: .node-base