diff --git a/.editorconfig b/.editorconfig
index d94dd8b..4e41e32 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -20,7 +20,7 @@ insert_final_newline = true
 trim_trailing_whitespace = true
 
 # Git configuration files uses tabs as indentation units
-[.git*]
+[/.git{modules,config}]
 indent_style = tab
 
 # Avoid git patch fail to apply due to stripped unmodified lines that contains only spaces
@@ -59,3 +59,8 @@ indent_size = 2
 
 [.*.{yml,yaml}]
 indent_size = 2
+
+# Keep the indentation style of the license text verbatim
+[/LICENSES/*]
+indent_size = unset
+indent_style = unset
diff --git a/.github/workflows/check-potential-problems.yml b/.github/workflows/check-potential-problems.yml
index c85e79f..018c486 100644
--- a/.github/workflows/check-potential-problems.yml
+++ b/.github/workflows/check-potential-problems.yml
@@ -9,7 +9,9 @@
 # SPDX-License-Identifier: CC-BY-SA-4.0
 name: 檢查專案中的潛在問題
 on:
-  - push
+  push:
+    branches:
+      - '**'
 jobs:
   check-using-precommit:
     name: 使用 pre-commit 檢查專案中的潛在問題
@@ -17,6 +19,7 @@ jobs:
     env:
       PIP_CACHE_DIR: ${{ github.workspace }}/.cache/pip
       PRE_COMMIT_HOME: ${{ github.workspace }}/.cache/pre-commit
+      SHELLCHECK_DIR: ${{ github.workspace }}/.cache/shellcheck-stable
     steps:
       - name: 自版控庫取出內容
         uses: actions/checkout@v4
@@ -34,7 +37,19 @@ jobs:
           key: pre-commit|${{ env.PY }}|${{ hashFiles('.pre-commit-config.yaml') }}
           path: ${{ env.PRE_COMMIT_HOME }}
 
-      - name: Running static analysis program
+      - name: >-
+          Configure pre-built ShellCheck cache to speed up continuous integration
+        uses: actions/cache@v3
+        with:
+          key: ${{ runner.os }}-${{ runner.arch }}-shellcheck
+          path: ${{ env.SHELLCHECK_DIR }}
+
+      - name: >-
+          Patch the sudo security policy so that programs run via sudo
+          will recognize environment variables predefined by GitHub
+        run: sudo ./continuous-integration/patch-github-actions-sudo-security-policy.sh
+
+      - name: Run the static analysis programs
         run: |
           sudo ./continuous-integration/do-static-analysis.install-system-deps.sh
           ./continuous-integration/do-static-analysis.sh
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index fe95e42..48c3f2b 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -18,8 +18,27 @@ jobs:
     name: Release product and their build aritfacts
     runs-on: ubuntu-20.04
     steps:
-      - name: Checkout content from the Git repository
+      - name: Check out content from the Git repository
         uses: actions/checkout@v4
+        with:
+          # Increase fetch depth if you may have more than this amount
+          # of revisions between releases
+          fetch-depth: 100
+
+          # Fetch tags as well to generate detailed changes between two releases
+          # WORKAROUND: Adding this option triggers actions/checkout#1467
+          #fetch-tags: true
+
+      - name: >-
+          WORKAROUND: Fetch tags that points to the revisions
+          checked-out(actions/checkout#1467)
+        run: |-
+          git fetch \
+            --prune \
+            --prune-tags \
+            --force \
+            --depth=100 \
+            --no-recurse-submodules
 
       - name: Determine the project identifier
         run: printf "project_id=${GITHUB_REPOSITORY##*/}\\n" >> $GITHUB_ENV
@@ -33,6 +52,11 @@ jobs:
       - name: Determine the release identifier
         run: printf "release_id=${project_id}-${release_version}\\n" >> $GITHUB_ENV
 
+      - name: >-
+          Patch the sudo security policy so that programs run via sudo
+          will recognize environment variables predefined by GitHub
+        run: sudo ./continuous-integration/patch-github-actions-sudo-security-policy.sh
+
       - name: Generate the release archive
         run: |-
           sudo ./continuous-integration/generate-build-artifacts.install-system-deps.sh
diff --git a/.gitignore b/.gitignore
index 60348c7..7def9e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,7 +7,7 @@
 # https://github.com/the-common/gitignore-templates
 #
 # Copyright 2022 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 # Don't track regular Unix hidden files
 .*
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 4a0e67e..9fc5987 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -6,7 +6,7 @@
 #   https://docs.gitlab.com/ee/ci/yaml/
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 do-static-analysis:
   stage: test
   rules:
@@ -16,12 +16,14 @@ do-static-analysis:
   variables:
     PIP_CACHE_DIR: ${CI_PROJECT_DIR}/.cache/pip
     PRE_COMMIT_HOME: ${CI_PROJECT_DIR}/.cache/pre-commit
+    SHELLCHECK_DIR: ${CI_PROJECT_DIR}/.cache/shellcheck-stable
   cache:
     # Enable per-job and per-branch caching
     key: $CI_JOB_NAME-$CI_COMMIT_REF_SLUG
     paths:
       - ${PIP_CACHE_DIR}
       - ${PRE_COMMIT_HOME}
+      - ${SHELLCHECK_DIR}
 
   script:
     - ./continuous-integration/do-static-analysis.install-system-deps.sh
diff --git a/.gitmodules b/.gitmodules
index b130482..9ea7f86 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -6,4 +6,4 @@
 #   https://git-scm.com/docs/gitmodules
 #
 # Copyright 2021 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
diff --git a/.markdownlint.yml b/.markdownlint.yml
index 800a1b2..b5663d5 100644
--- a/.markdownlint.yml
+++ b/.markdownlint.yml
@@ -5,7 +5,7 @@
 # https://github.com/Lin-Buo-Ren/common-markdownlint-nodejs-config-templates
 #
 # Copyright 2021 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 # Inherit Markdownlint rules
 default: True
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 266efa5..0608f7e 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -6,7 +6,7 @@
 # https://github.com/Lin-Buo-Ren/common-precommit-config-template
 #
 # Copyright 2021 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 repos:
   # Some out-of-the-box hooks for pre-commit
@@ -42,13 +42,34 @@ repos:
   # Check REUSE compliance
   # https://reuse.software/
   - repo: https://github.com/fsfe/reuse-tool
-    rev: v1.0.0
+    rev: v3.0.2
     hooks:
       - id: reuse
 
+  # Check shell scripts with ShellCheck
+  # NOTE: ShellCheck must be available in the command search PATHs
+  # https://www.shellcheck.net/
+  # https://github.com/jumanjihouse/pre-commit-hooks#shellcheck
+  - repo: https://github.com/jumanjihouse/pre-commit-hooks
+    rev: 3.0.0
+    hooks:
+      - id: shellcheck
+
   # Check YAML files
   # https://github.com/adrienverge/yamllint
   - repo: https://github.com/adrienverge/yamllint
     rev: v1.30.0
     hooks:
       - id: yamllint
+
+  # Check EditorConfig style compliance
+  # https://github.com/editorconfig-checker/editorconfig-checker.python
+  - repo: https://github.com/editorconfig-checker/editorconfig-checker.python
+    rev: 2.7.3
+    hooks:
+      - id: editorconfig-checker
+        alias: ec
+        exclude: |
+          (?ix)^(
+            LICENSES/.*
+          )$
diff --git a/.reuse/dep5 b/.reuse/dep5
index 31c9300..3b2d3d9 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -4,8 +4,8 @@ Upstream-Contact: Issues · libre-knowledge/subject-template <https://gitlab.com
 Source: https://gitlab.com/libre-knowledge/subject-template
 
 Files:
-  *README.md
-  */README.md
-  _config.yml
-Copyright: Copyright 2023 自由知識協作平台貢獻者 <https://gitlab.com/libre-knowledge/libre-knowledge/-/issues>
-License: CC-BY-SA-4.0
+    *README.md
+    */README.md
+    _config.yml
+Copyright: Copyright 2024 自由知識協作平台貢獻者 <https://gitlab.com/libre-knowledge/libre-knowledge/-/issues>
+License: CC-BY-SA-4.0+ OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
diff --git a/.yamllint b/.yamllint
index 243251a..ba05db4 100644
--- a/.yamllint
+++ b/.yamllint
@@ -13,7 +13,7 @@
 # https://github.com/Lin-Buo-Ren/yamllint-configuration-templates
 #
 # Copyright 2021 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 rules:
   # Use this rule to control the number of spaces inside braces (`{` and `}`).
   # https://yamllint.readthedocs.io/en/stable/rules.html#module-yamllint.rules.braces
diff --git a/LICENSES/LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects.txt b/LICENSES/LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects.txt
new file mode 100644
index 0000000..b293d10
--- /dev/null
+++ b/LICENSES/LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects.txt
@@ -0,0 +1,17 @@
+# The Apache-2.0-If-Not-Used-In-Template-Projects pseudo license
+
+Assets that are declared as either licensed under [the 4.0 International
+version of the Creative Commons Attribution-ShareAlike license](https://creativecommons.org/licenses/by-sa/4.0/)
+or this pseudo license can be licensed otherwise under [the 2.0 version
+of the Apache license](https://www.apache.org/licenses/LICENSE-2.0) _if_
+it is used to instantiate/refactor a project based on it rather than
+using it in the making of another template project.  This allows
+re-licensing the project assets to your liking in your non-template
+projects with only a legal conformance requirement of attributing this
+product somewhere in your project/product credits/acknowledgment/copyright
+notice documentation/user interface.
+
+Note that some assets that are not declared using this pseudo license
+may also allow re-licensing as the declared license does not impose such
+restrictions in the first place, refer the individual license terms for
+details.
diff --git a/README.md b/README.md
index 41fa6a9..9dee428 100644
--- a/README.md
+++ b/README.md
@@ -60,6 +60,7 @@
     + .markdownlint.yml
 1. 編輯子模組專案 [real.README.md 主題說明文件模板](real.README.md),將 `_佔位字_` 替換為適當之內容(別忘了替換 `libre-knowledge/_專案ID_`),並移除未使用之(待補)章節
 1. 用 [real.markdownlint.yml Markdownlint 配置文件](real.markdownlint.yml)替換掉 [.markdownlint.yml 本專案專屬的 Markdownlint 配置文件](.markdownlint.yml)
+1. 將「real.gitattributes Git 路徑屬性配置文件」更名為「.gitattributes」
 1. 替換 [.reuse/dep5 REUSE DEP5 機器可讀著作權宣告文件](.reuse/dep5)文件中的 `Upstream-Name`(替換為 _主題名稱_)欄位、 `Upstream-Contact`(替換為該主題專案議題追蹤系統的網頁標題與網址)欄位跟 `Source`(替換為專案網址)欄位
 1. 將 [real.README.md 主題說明文件模板](real.README.md) 替換掉 [README.md 本專案說明文件](README.md)
 1. 將變更提交為新修訂版(參考提交標題: `docs: 撰寫主題說明文件雛型`)
diff --git a/continuous-integration/create-gitlab-release.sh b/continuous-integration/create-gitlab-release.sh
index 7b19eab..51433d6 100755
--- a/continuous-integration/create-gitlab-release.sh
+++ b/continuous-integration/create-gitlab-release.sh
@@ -2,7 +2,7 @@
 # Create GitLab project release
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 set \
     -o errexit \
diff --git a/continuous-integration/do-static-analysis.install-system-deps.sh b/continuous-integration/do-static-analysis.install-system-deps.sh
index 3dce3c3..650e0b0 100755
--- a/continuous-integration/do-static-analysis.install-system-deps.sh
+++ b/continuous-integration/do-static-analysis.install-system-deps.sh
@@ -2,11 +2,34 @@
 # System dependency installation logic for the static analysis program
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 set \
     -o errexit \
     -o nounset
 
+if test -v BASH_SOURCE; then
+    # Convenience variables
+    # shellcheck disable=SC2034
+    {
+        script="$(
+            realpath \
+                --strip \
+                "${BASH_SOURCE[0]}"
+        )"
+        script_dir="${script%/*}"
+        script_filename="${script##*/}"
+        script_name="${script_filename%%.*}"
+    }
+fi
+
+trap_exit(){
+    if test -v temp_dir \
+        && test -e "${temp_dir}"; then
+        rm -rf "${temp_dir}"
+    fi
+}
+trap trap_exit EXIT
+
 if test "${EUID}" -ne 0; then
     printf \
         'Error: This program should be run as the superuser(root) user.\n' \
@@ -14,6 +37,29 @@ if test "${EUID}" -ne 0; then
     exit 1
 fi
 
+project_dir="$(dirname "${script_dir}")"
+cache_dir="${project_dir}/.cache"
+
+if ! test -e "${cache_dir}"; then
+    install_opts=(
+        --directory
+    )
+    if test -v SUDO_USER; then
+        # Configure same user as the running environment to avoid access
+        # problems afterwards
+        install_opts+=(
+            --owner "${SUDO_USER}"
+            --group "${SUDO_GID}"
+        )
+    fi
+    if ! install "${install_opts[@]}" "${cache_dir}"; then
+        printf \
+            'Error: Unable to create the cache directory.\n' \
+            1>&2
+        exit 2
+    fi
+fi
+
 apt_archive_cache_mtime_epoch="$(
     stat \
         --format=%Y \
@@ -35,24 +81,24 @@ fi
 # Silence warnings regarding unavailable debconf frontends
 export DEBIAN_FRONTEND=noninteractive
 
-if ! test -v CI; then
-    base_runtime_dependency_pkgs=(
-        wget
-    )
-    if ! dpkg -s "${base_runtime_dependency_pkgs[@]}" &>/dev/null; then
+base_runtime_dependency_pkgs=(
+    wget
+)
+if ! dpkg -s "${base_runtime_dependency_pkgs[@]}" &>/dev/null; then
+    printf \
+        'Info: Installing base runtime dependency packages...\n'
+    if ! \
+        apt-get install \
+            -y \
+            "${base_runtime_dependency_pkgs[@]}"; then
         printf \
-            'Info: Installing base runtime dependency packages...\n'
-        if ! \
-            apt-get install \
-                -y \
-                "${base_runtime_dependency_pkgs[@]}"; then
-            printf \
-                'Error: Unable to install the base runtime dependency packages.\n' \
-                1>&2
-            exit 2
-        fi
+            'Error: Unable to install the base runtime dependency packages.\n' \
+            1>&2
+        exit 2
     fi
+fi
 
+if ! test -v CI; then
     printf \
         'Info: Detecting local region code...\n'
     wget_opts=(
@@ -136,11 +182,18 @@ if ! test -v CI; then
 fi
 
 runtime_dependency_pkgs=(
+    # For matching the ShellCheck version string
+    grep
+
     git
 
     python3-minimal
     python3-pip
     python3-venv
+
+    # For extracting prebuilt ShellCheck software archive
+    tar
+    xz-utils
 )
 if ! dpkg -s "${runtime_dependency_pkgs[@]}" &>/dev/null; then
     printf \
@@ -154,5 +207,128 @@ if ! dpkg -s "${runtime_dependency_pkgs[@]}" &>/dev/null; then
     fi
 fi
 
+shellcheck_dir="${cache_dir}/shellcheck-stable"
+
+if ! test -e "${shellcheck_dir}/shellcheck"; then
+    printf \
+        "Info: Determining the host machine's hardware architecture...\\n"
+    if ! arch="$(arch)"; then
+        printf \
+            "Error: Unable to determine the host machine's hardware architecture.\\n" \
+            1>&2
+        exit 1
+    fi
+
+    printf \
+        'Info: Checking ShellCheck architecure availability...\n'
+    case "${arch}" in
+        x86_64|armv6hf|aarch64)
+            # Assuming the ShellCheck architecture is the same, which
+            # is probably incorrect...
+            shellcheck_arch="${arch}"
+        ;;
+        *)
+            printf \
+                'Error: Unsupported ShellCheck architecture "%s".\n' \
+                "${arch}" \
+                1>&2
+            exit 1
+        ;;
+    esac
+
+    printf \
+        'Info: Determining the ShellCheck prebuilt archive details...\n'
+    prebuilt_shellcheck_archive_url="https://github.com/koalaman/shellcheck/releases/download/stable/shellcheck-stable.linux.${shellcheck_arch}.tar.xz"
+    prebuilt_shellcheck_archive_filename="${prebuilt_shellcheck_archive_url##*/}"
+
+    printf \
+        'Info: Creating the temporary directory for storing downloaded files...\n'
+    mktemp_opts=(
+        --directory
+        --tmpdir
+    )
+    if ! temp_dir="$(
+        mktemp \
+            "${mktemp_opts[@]}" \
+            "${script_name}.XXXXXX"
+        )"; then
+        printf \
+            'Error: Unable to create the temporary directory for storing downloaded files.\n' \
+            1>&2
+        exit 2
+    fi
+
+    printf \
+        'Info: Downloading the prebuilt ShellCheck software archive...\n'
+    downloaded_prebuilt_shellcheck_archive="${temp_dir}/${prebuilt_shellcheck_archive_filename}"
+    wget_opts=(
+        --output-document "${downloaded_prebuilt_shellcheck_archive}"
+    )
+    if ! \
+        wget \
+            "${wget_opts[@]}" \
+            "${prebuilt_shellcheck_archive_url}"; then
+        printf \
+            'Error: Unable to download the prebuilt ShellCheck software archive...\n' \
+            1>&2
+        exit 2
+    fi
+
+    printf \
+        'Info: Extracting the prebuilt ShellCheck software archive...\n'
+    tar_opts=(
+        --extract
+        --verbose
+        --directory="${cache_dir}"
+        --file="${downloaded_prebuilt_shellcheck_archive}"
+    )
+    if test -v SUDO_USER; then
+        # Configure same user as the running environment to avoid access
+        # problems afterwards
+        tar_opts+=(
+            --owner="${SUDO_USER}"
+            --group="${SUDO_GID}"
+        )
+    fi
+    if ! tar "${tar_opts[@]}"; then
+        printf \
+            'Error: Unable to extract the prebuilt ShellCheck software archive.\n' \
+            1>&2
+        exit 2
+    fi
+fi
+
+printf \
+    'Info: Setting up the command search PATHs so that the locally installed shellcheck command can be located...\n'
+PATH="${shellcheck_dir}:${PATH}"
+
+printf \
+    'Info: Querying the ShellCheck version...\n'
+if ! shellcheck_version_raw="$(shellcheck --version)"; then
+    printf \
+        'Error: Unable to query the ShellCheck version.\n' \
+        1>&2
+    exit 2
+fi
+
+grep_opts=(
+    --perl-regexp
+    --only-matching
+)
+if ! shellcheck_version="$(
+    grep \
+        "${grep_opts[@]}" \
+        '(?<=version: ).*' \
+        <<<"${shellcheck_version_raw}"
+    )"; then
+    printf \
+        'Error: Unable to parse out the ShellCheck version string.\n' \
+        1>&2
+fi
+
+printf \
+    'Info: ShellCheck version is "%s".\n' \
+    "${shellcheck_version}"
+
 printf \
     'Info: Operation completed without errors.\n'
diff --git a/continuous-integration/do-static-analysis.sh b/continuous-integration/do-static-analysis.sh
index 3424661..69ff394 100755
--- a/continuous-integration/do-static-analysis.sh
+++ b/continuous-integration/do-static-analysis.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 # Check potential problems in the project
 # Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 set \
     -o errexit \
     -o nounset
@@ -19,6 +19,8 @@ if ! script="$(
 fi
 
 script_dir="${script%/*}"
+project_dir="$(dirname "${script_dir}")"
+cache_dir="${project_dir}/.cache"
 
 if ! test -e "${script_dir}/venv"; then
     printf \
@@ -53,6 +55,10 @@ if ! pip show pre-commit &>/dev/null; then
     fi
 fi
 
+printf \
+    'Info: Setting up the command search PATHs so that the installed shellcheck command can be located...\n'
+PATH="${cache_dir}/shellcheck-stable:${PATH}"
+
 printf \
     'Info: Running pre-commit...\n'
 if ! \
diff --git a/continuous-integration/generate-build-artifacts.install-system-deps.sh b/continuous-integration/generate-build-artifacts.install-system-deps.sh
index 9122d7f..7fbfbea 100755
--- a/continuous-integration/generate-build-artifacts.install-system-deps.sh
+++ b/continuous-integration/generate-build-artifacts.install-system-deps.sh
@@ -3,7 +3,7 @@
 # build artifacts
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <buo.ren.lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 set \
     -o errexit \
@@ -14,12 +14,12 @@ required_commands=(
     realpath
 )
 flag_dependency_check_failed=false
-for required_command in "${required_commands[@]}"; do
-    if ! command -v "${required_command}" >/dev/null; then
+for command in "${required_commands[@]}"; do
+    if ! command -v "${command}" >/dev/null; then
         flag_dependency_check_failed=true
         printf \
             'Error: Unable to locate the "%s" command in the command search PATHs.\n' \
-            "${required_command}" \
+            "${command}" \
             1>&2
     fi
 done
diff --git a/continuous-integration/generate-build-artifacts.sh b/continuous-integration/generate-build-artifacts.sh
index 7601473..67f6f11 100755
--- a/continuous-integration/generate-build-artifacts.sh
+++ b/continuous-integration/generate-build-artifacts.sh
@@ -2,7 +2,7 @@
 # Generate the project build artifacts
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <buo.ren.lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 set \
     -o errexit \
     -o nounset
diff --git a/continuous-integration/generate-release-description.sh b/continuous-integration/generate-release-description.sh
index 32fc7d7..45bc956 100755
--- a/continuous-integration/generate-release-description.sh
+++ b/continuous-integration/generate-release-description.sh
@@ -3,7 +3,7 @@
 # previous release
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 set \
     -o errexit \
@@ -21,69 +21,99 @@ fi
 script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)"
 project_dir="${script_dir%/*}"
 
-printf \
-    'Info: Determining release description...\n'
-git_tag_list="$(git tag --list)"
-git_tag_count="$(wc -l <<<"${git_tag_list}")"
+printf 'Info: Querying the list of the release tag(s)...\n'
+if ! git_tag_list="$(git tag --list 'v*')"; then
+    printf \
+        'Error: Unable to query the list of the release tag(s).\n' \
+        1>&2
+    exit 2
+fi
+
+printf 'Info: Counting the release tags...\n'
+if ! git_tag_count="$(wc -l <<<"${git_tag_list}")"; then
+    printf \
+        'Error: Unable to count the release tags.\n' \
+        1>&2
+    exit 2
+fi
 
 detailed_changes_markup="## Detailed changes"$'\n\n'
-git_log_opts=(
-    --format='format:* %s (%h) - %an'
-)
 
 if test -v CI_COMMIT_TAG; then
     release_tag="${CI_COMMIT_TAG}"
 fi
 
 if test "${git_tag_count}" -eq 1; then
+    printf \
+        'Info: Only one release tag was detected, generating the release description text from the very beginning to the "%s" release tag...\n' \
+        "${release_tag}"
     if ! detailed_changes_markup+="$(
         git log \
             "${git_log_opts[@]}" \
             "${release_tag}"
         )"; then
         printf \
-            'Error: Unable to generate the commit list from Git.\n' \
+            'Error: Unable to generate the release description text from Git.\n' \
             1>&2
         exit 2
     fi
 else
+    printf \
+        'Info: Multiple release tags were detected, determining the previous release tag...\n'
+    printf \
+        'Info: Version-sorting the release tag list...\n'
     if ! sorted_git_tag_list="$(
         sort \
             -V \
             <<<"${git_tag_list}"
         )"; then
         printf \
-            'Error: Unable to version-sort the Git tag list.\n' \
+            'Error: Unable to version-sort the release tag list.\n' \
             1>&2
         exit 2
     fi
+
+    printf \
+        'Info: Filtering out the two latest release tags from the release tag list...\n'
     if ! latest_two_git_tags="$(
         tail \
             -n 2 \
             <<<"${sorted_git_tag_list}"
         )"; then
         printf \
-            'Error: Unable to filter out the two latest tags from the Git tag list.\n' \
+            'Error: Unable to filter out the two latest release tags from the release tag list.\n' \
             1>&2
         exit 2
     fi
+
+    printf \
+        'Info: Filtering out the previous release tag from the two latest release tags...\n'
     if ! previous_git_tag="$(
         head \
             -n 1 \
             <<<"${latest_two_git_tags}"
         )"; then
         printf \
-            'Error: Unable to filter out the previous release tag from the two latest Git tags.\n' \
+            'Error: Unable to filter out the previous release tag from the two latest release tags.\n' \
             1>&2
         exit 2
     fi
+
+    printf \
+        'Info: Generating the release description text from the previous release tag(%s) to the current release tag(%s)...\n' \
+            "${previous_git_tag}" \
+            "${release_tag}" \
+            1>&2
+    git_log_opts=(
+        --format='format:* %s (%h) - %an'
+    )
     if ! detailed_changes_markup+="$(
         git log \
             "${git_log_opts[@]}" \
             "${previous_git_tag}..${release_tag}"
         )"; then
         printf \
-            'Error: Unable to generate the Git commit list between the "%s" tag and the "%s" tag.\n' \
+            'Error: Unable to generate the release description text from the previous release tag(%s) to the current release tag(%s).\n' \
             "${previous_git_tag}" \
             "${release_tag}" \
             1>&2
@@ -97,9 +127,9 @@ printf \
     "${detailed_changes_file}"
 if ! \
     printf \
-        '%s' \
+        '%s\n' \
         "${detailed_changes_markup}" \
-        >"${detailed_changes_file}"; then
+        | tee "${detailed_changes_file}"; then
     printf \
         'Error: Unable to write the detailed changes markup to the "%s" file.\n' \
         "${detailed_changes_file}" \
diff --git a/continuous-integration/patch-github-actions-sudo-security-policy.sh b/continuous-integration/patch-github-actions-sudo-security-policy.sh
new file mode 100755
index 0000000..5492007
--- /dev/null
+++ b/continuous-integration/patch-github-actions-sudo-security-policy.sh
@@ -0,0 +1,143 @@
+#!/usr/bin/env bash
+# Patch the sudo security policy so that the environment variables
+# defined in the GitHub Actions CI environment would be inherited in
+# processes run using sudo
+#
+# References:
+#
+# * Including other files from within sudoers | Sudoers Manual | Sudo
+#   https://www.sudo.ws/docs/man/sudoers.man/#Including_other_files_from_within_sudoers
+#
+# Copyright 2023 林博仁(Buo-ren, Lin) <buo.ren.lin@gmail.com>
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
+
+# Configure the interpreter behavior to bail out during problematic
+# situations
+set \
+    -o errexit \
+    -o nounset
+
+required_commands=(
+    install
+    realpath
+
+    # For checking the validity of the sudoers file
+    visudo
+)
+flag_dependency_check_failed=false
+for required_command in "${required_commands[@]}"; do
+    if ! command -v "${required_command}" >/dev/null; then
+        flag_dependency_check_failed=true
+        printf \
+            'Error: Unable to locate the "%s" command in the command search PATHs.\n' \
+            "${required_command}" \
+            1>&2
+    fi
+done
+if test "${flag_dependency_check_failed}" == true; then
+    printf \
+        'Error: Dependency check failed, please check your installation.\n' \
+        1>&2
+    exit 1
+fi
+
+if test "${EUID}" -ne 0; then
+    printf \
+        'Error: This program is required to be run as the superuser(root).\n' \
+        1>&2
+    exit 1
+fi
+
+if test -v BASH_SOURCE; then
+    # Convenience variables
+    # shellcheck disable=SC2034
+    {
+        script="$(
+            realpath \
+                --strip \
+                "${BASH_SOURCE[0]}"
+        )"
+        script_dir="${script%/*}"
+    }
+fi
+
+ci_dir="${script_dir}"
+sudoers_dropin_dir="${ci_dir}/sudoers.d"
+
+sudoers_dropin_dir_system=/etc/sudoers.d
+if ! test -e "${sudoers_dropin_dir_system}"; then
+    printf \
+        'Info: Creating the sudoers drop-in directory...\n'
+    install_opts=(
+        --directory
+        --owner=root
+        --group=root
+        --mode=0755
+        --verbose
+    )
+    if ! \
+        install \
+            "${install_opts[@]}" \
+            "${sudoers_dropin_dir_system}"; then
+        printf \
+            'Error: Unable to create the sudoers drop-in directory.\n' \
+            1>&2
+        exit 2
+    fi
+fi
+
+for dropin_file in "${sudoers_dropin_dir}/"*.sudoers; do
+    dropin_filename="${dropin_file##*/}"
+
+    printf \
+        'Info: Validating the "%s" sudoers drop-in file...\n' \
+        "${dropin_filename}"
+    visudo_opts=(
+        # Enable check-only mode
+        --check
+
+        # Specify an alternate sudoers file location
+        --file="${dropin_file}"
+
+        # NOTE: We don't use --quiet as it will also inhibit the syntax
+        # error messages, dump the stdout stream instead
+        #--quiet
+    )
+    if ! visudo "${visudo_opts[@]}" >/dev/null; then
+        printf \
+            'Error: Syntax validation failed for the "%s" sudoers drop-in file.\n' \
+            "${dropin_filename}" \
+            1>&2
+        exit 2
+    fi
+
+    printf \
+        'Info: Installing the "%s" sudoers drop-in file...\n' \
+        "${dropin_filename}"
+
+    # sudo will not accept filename with the period symbol in the
+    # filename, strip the convenicence filename suffix
+    dropin_filename_without_suffix="${dropin_filename%.sudoers}"
+
+    installed_dropin_file="${sudoers_dropin_dir_system}/${dropin_filename_without_suffix}"
+    install_opts=(
+        --owner=root
+        --group=root
+        --mode=0644
+        --verbose
+    )
+    if ! \
+        install \
+            "${install_opts[@]}" \
+            "${dropin_file}" \
+            "${installed_dropin_file}"; then
+        printf \
+            'Error: Unable to install the sudoers drop-in configuration file "%s".\n' \
+            "${dropin_filename}" \
+            1>&2
+        exit 2
+    fi
+done
+
+printf \
+    'Info: Operation completed without errors.\n'
diff --git a/continuous-integration/sudoers.d/90_allow_github_actions_default_envvars.sudoers b/continuous-integration/sudoers.d/90_allow_github_actions_default_envvars.sudoers
new file mode 100644
index 0000000..c188aa5
--- /dev/null
+++ b/continuous-integration/sudoers.d/90_allow_github_actions_default_envvars.sudoers
@@ -0,0 +1,20 @@
+# Allow exposing GitHub Actions default environment variables to the invoked superuser processes
+#
+# References:
+#
+# * Command environment | Sudoers Manual | Sudo
+#   https://www.sudo.ws/docs/man/sudoers.man/#Command_environment
+# * Default environment - variablesVariables - GitHub Docs
+#   https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables
+#
+# Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
+
+# Whether we are in an CI environment
+Defaults env_keep += "CI"
+
+# Variables defined by GitHub
+Defaults env_keep += "GITHUB_*"
+
+# Variables defined by the GitHub Action runners
+Defaults env_keep += "RUNNER_*"
diff --git a/continuous-integration/sudoers.d/README.md b/continuous-integration/sudoers.d/README.md
new file mode 100644
index 0000000..87dffa0
--- /dev/null
+++ b/continuous-integration/sudoers.d/README.md
@@ -0,0 +1,8 @@
+# sudoers.d
+
+The drop-in configuration files for [the Sudoers configuration file](https://www.sudo.ws/docs/man/sudoers.man/)
+
+## References
+
+* [Sudoers Manual | Sudo](https://www.sudo.ws/docs/man/sudoers.man/)
+* [Including other files from within sudoers | Sudoers Manual | Sudo](https://www.sudo.ws/docs/man/sudoers.man/#Including_other_files_from_within_sudoers)
diff --git a/continuous-integration/upload-gitlab-generic-packages.sh b/continuous-integration/upload-gitlab-generic-packages.sh
index 97e7639..635061e 100755
--- a/continuous-integration/upload-gitlab-generic-packages.sh
+++ b/continuous-integration/upload-gitlab-generic-packages.sh
@@ -2,7 +2,7 @@
 # Upload release packages as GitLab generic packages
 #
 # Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 set \
     -o errexit \
@@ -25,7 +25,7 @@ script_dir="$(CDPATH='' cd -- "$(dirname -- "$0")" && pwd)"
 project_dir="${script_dir%/*}"
 
 for file in "${project_dir}/${CI_PROJECT_NAME}-"*; do
-    if test "${file}" == "${project_dir}/${CI_PROJECT_NAME}-*"; then
+    if test "${file}" = "${project_dir}/${CI_PROJECT_NAME}-*"; then
         # No release packages are found, avoid missing file error
         break
     fi
diff --git a/real.gitattributes b/real.gitattributes
new file mode 100644
index 0000000..af1a06c
--- /dev/null
+++ b/real.gitattributes
@@ -0,0 +1,24 @@
+# Git path attributes configuration file
+#
+# References:
+#
+# * Git - Git Attributes
+#   https://git-scm.com/book/en/v2/Customizing-Git-Git-Attributes
+# * Git - gitattributes Documentation
+#   https://www.git-scm.com/docs/gitattributes
+#
+# Copyright 2023 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
+
+# Avoid exporting development files to release archive
+/.* export-ignore
+/continuous-integration export-ignore
+
+# Keep editorconfig for ease of editing of product files
+/.editorconfig -export-ignore
+
+# Keep REUSE DEP5 declaration file in the release archive for legal
+# conformance
+/.reuse/ -export-ignore
+/.reuse/* export-ignore
+/.reuse/dep5 -export-ignore
diff --git a/real.markdownlint.yml b/real.markdownlint.yml
index e3c6e02..fc7eb65 100644
--- a/real.markdownlint.yml
+++ b/real.markdownlint.yml
@@ -5,7 +5,7 @@
 # https://github.com/Lin-Buo-Ren/common-markdownlint-nodejs-config-templates
 #
 # Copyright 2021 林博仁(Buo-ren, Lin) <Buo.Ren.Lin@gmail.com>
-# SPDX-License-Identifier: CC-BY-SA-4.0
+# SPDX-License-Identifier: CC-BY-SA-4.0 OR LicenseRef-Apache-2.0-If-Not-Used-In-Template-Projects
 
 # Inherit Markdownlint rules
 default: True