From c0acf6bbf86865cef33657b63c3fb1fdf24cd69d Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 00:57:45 -0500 Subject: [PATCH 01/13] ci: adopt shared orb 0.7.11 (#52) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 113ce37..def7f95 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.3 + qqq-orb: kingsrook/qqq-orb@0.7.11 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.3 + orb_version: 0.7.11 filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index 6ade08d..a8863c3 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.3 +orb_version: 0.7.11 default_branch: develop java_version: '21' browsers: true -- 2.54.0 From f4cbdae305e05c2b3bd00fe7e5523d5515f39e4d Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 02:06:06 -0500 Subject: [PATCH 02/13] ci: adopt verified orb rc timeout recovery (#53) Co-authored-by: Codex --- .github/workflows/release-rc.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release-rc.yml b/.github/workflows/release-rc.yml index 5aab78d..a63288b 100644 --- a/.github/workflows/release-rc.yml +++ b/.github/workflows/release-rc.yml @@ -10,6 +10,15 @@ name: Release candidate description: Retry finalization of an existing cut; do not cut another RC type: boolean default: false + recover: + description: Recover the same published RC after a deployment timeout; never + reupload + type: boolean + default: false + circle_build: + description: Original Circle publisher build number (recovery only) + type: string + default: '' merge_sha: description: Existing cut merge_sha (finalize retry only) type: string @@ -44,12 +53,16 @@ jobs: || (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name, 'release:rc')) - uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@ee8953bd937d7f69c7a54308ffd5f9aed95aa768 + uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@edc1365ac934cd8d3aae097d8012628f5c3970ed with: dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false }} finalize: ${{ github.event_name == 'repository_dispatch' || (github.event_name == 'workflow_dispatch' && inputs.finalize) }} + recover: ${{ github.event_name == 'workflow_dispatch' && inputs.recover || false + }} + circle_build: ${{ github.event_name == 'workflow_dispatch' && inputs.circle_build + || '' }} merge_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.merge_sha || inputs.merge_sha || '' }} bump_sha: ${{ github.event_name == 'repository_dispatch' && github.event.client_payload.bump_sha -- 2.54.0 From d1939eefd52e1686531155b4a572427b6269dd3c Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 02:18:17 -0500 Subject: [PATCH 03/13] ci: use corrected orb rc reference lookup (#54) Co-authored-by: Codex --- .github/workflows/release-rc.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release-rc.yml b/.github/workflows/release-rc.yml index a63288b..0158aa2 100644 --- a/.github/workflows/release-rc.yml +++ b/.github/workflows/release-rc.yml @@ -53,7 +53,7 @@ jobs: || (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name, 'release:rc')) - uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@edc1365ac934cd8d3aae097d8012628f5c3970ed + uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@7d73ac90b6b5a6acb61b4d3fa56625c5b6dcc652 with: dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false }} -- 2.54.0 From 5e7661139382e95bc2bc2b5fc8afa91c4bf225ff Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 03:26:52 -0500 Subject: [PATCH 04/13] ci: adopt orb 0.7.12 and stable verification gate (#55) * ci: qualify the shared stable verification gate Co-Authored-By: Codex * ci: adopt verified stable orb 0.7.12 Co-Authored-By: Codex --------- Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .github/workflows/release-rc.yml | 2 +- .qqq-ci.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index def7f95..c9cb461 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.11 + qqq-orb: kingsrook/qqq-orb@0.7.12 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.11 + orb_version: 0.7.12 filters: branches: ignore: automation/qbit-rc-pending diff --git a/.github/workflows/release-rc.yml b/.github/workflows/release-rc.yml index 0158aa2..b48a32a 100644 --- a/.github/workflows/release-rc.yml +++ b/.github/workflows/release-rc.yml @@ -53,7 +53,7 @@ jobs: || (github.event_name == 'pull_request' && github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name, 'release:rc')) - uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@7d73ac90b6b5a6acb61b4d3fa56625c5b6dcc652 + uses: QRun-IO/qqq-orb/.github/workflows/qbit-release-rc.yml@cc30f599e63c8e41629c99d23395bac1adb8bc44 with: dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false }} diff --git a/.qqq-ci.yml b/.qqq-ci.yml index a8863c3..be6666b 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.11 +orb_version: 0.7.12 default_branch: develop java_version: '21' browsers: true -- 2.54.0 From 84b4c00f9468bed5198a14164888d9bc8c1fa4b5 Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 10:44:44 -0500 Subject: [PATCH 05/13] ci: centralize QBit source scanning (#56) Co-authored-by: Codex --- .github/workflows/codeql.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..bd3ceaf --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,23 @@ +name: CodeQL +'on': + push: + branches: + - main + - develop + - release/** + - hotfix/** + pull_request: {} + schedule: + - cron: 41 16 * * 0 + workflow_dispatch: {} +permissions: + contents: read + actions: read + security-events: write + packages: read +concurrency: + group: codeql-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} +jobs: + analyze: + uses: QRun-IO/qqq-orb/.github/workflows/qbit-codeql.yml@c288a8864fe9054f68410e1d78f5863aea4c4d22 -- 2.54.0 From 9bb529d3bdb321a24394836f6a82d1a610b7bfea Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 14:17:24 -0500 Subject: [PATCH 06/13] ci: adopt shared orb 0.7.17 (#58) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index c9cb461..1d4fa0d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.12 + qqq-orb: kingsrook/qqq-orb@0.7.17 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.12 + orb_version: 0.7.17 filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index be6666b..a9e9f43 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.12 +orb_version: 0.7.17 default_branch: develop java_version: '21' browsers: true -- 2.54.0 From fcdfb7ddc145909f4b154ababbd58a6ff67c971b Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 14:47:29 -0500 Subject: [PATCH 07/13] ci: adopt shared orb 0.7.18 (#59) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 1d4fa0d..42b73df 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.17 + qqq-orb: kingsrook/qqq-orb@0.7.18 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.17 + orb_version: 0.7.18 filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index a9e9f43..967a18e 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.17 +orb_version: 0.7.18 default_branch: develop java_version: '21' browsers: true -- 2.54.0 From a3fc6ac5aafa060f74ca40fb528cb48a47eaa2ad Mon Sep 17 00:00:00 2001 From: James Maes Date: Wed, 21 Oct 2026 15:29:39 -0500 Subject: [PATCH 08/13] ci: adopt managed orb 0.8 patch track (#60) Co-authored-by: Codex --- .circleci/config.yml | 4 ++-- .qqq-ci.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 42b73df..f890c28 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,12 +1,12 @@ version: 2.1 setup: true orbs: - qqq-orb: kingsrook/qqq-orb@0.7.18 + qqq-orb: kingsrook/qqq-orb@0.8 workflows: setup: jobs: - qqq-orb/generate_pipeline: - orb_version: 0.7.18 + orb_version: '0.8' filters: branches: ignore: automation/qbit-rc-pending diff --git a/.qqq-ci.yml b/.qqq-ci.yml index 967a18e..6777ede 100644 --- a/.qqq-ci.yml +++ b/.qqq-ci.yml @@ -1,5 +1,5 @@ profile: qbit -orb_version: 0.7.18 +orb_version: '0.8' default_branch: develop java_version: '21' browsers: true -- 2.54.0 From f8058639f1818f520906da6b955ed08c5808ada3 Mon Sep 17 00:00:00 2001 From: Forge Recovery Date: Mon, 2 Nov 2026 06:15:25 +0000 Subject: [PATCH 09/13] ci: move the QRun release caller to the thin v2 contract Co-Authored-By: Claude Sonnet 5.5 Co-Authored-By: Codex --- .gitea/workflows/qrun-release.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .gitea/workflows/qrun-release.yaml diff --git a/.gitea/workflows/qrun-release.yaml b/.gitea/workflows/qrun-release.yaml new file mode 100644 index 0000000..77794cf --- /dev/null +++ b/.gitea/workflows/qrun-release.yaml @@ -0,0 +1,16 @@ +# Standard QRun release caller (v2, thin contract): every push and manual dispatch delegates to the protected qrun-release-v1 channel. Do not edit per repository. +name: qrun-release +on: + push: {} + workflow_dispatch: {} +permissions: + contents: read + actions: read +jobs: + release: + uses: self:KofTwentyTwo/platform-ci/.gitea/workflows/java-docker.yaml@qrun-release-v1 + with: + runner: linux-small + docker-runner: container-build + browsers: true + browser-runner: browser-build -- 2.54.0 From db7e0e0eac223b601f9957eb9261605148c0a34b Mon Sep 17 00:00:00 2001 From: Forge Recovery Date: Mon, 2 Nov 2026 15:44:56 +0000 Subject: [PATCH 10/13] ci: add the isolated postpublish job to the QRun release caller Co-Authored-By: Claude Sonnet 5.5 Co-Authored-By: Codex --- .gitea/workflows/qrun-release.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitea/workflows/qrun-release.yaml b/.gitea/workflows/qrun-release.yaml index 77794cf..5ebc530 100644 --- a/.gitea/workflows/qrun-release.yaml +++ b/.gitea/workflows/qrun-release.yaml @@ -14,3 +14,12 @@ jobs: docker-runner: container-build browsers: true browser-runner: browser-build + postpublish: + if: ${{ needs.release.outputs.capture == 'true' }} + needs: release + permissions: + contents: write + actions: write + uses: self:KofTwentyTwo/platform-ci/.gitea/workflows/qrun-source-version.yaml@qrun-release-v1 + with: + runner: linux-small -- 2.54.0 From 8774fb0700c652a1eb1d0dcb8ac9e5d116df5677 Mon Sep 17 00:00:00 2001 From: Forge Recovery Date: Mon, 2 Nov 2026 20:13:07 +0000 Subject: [PATCH 11/13] ci: enroll shared Gitea release-candidate lifecycle Co-Authored-By: Codex --- .gitea/workflows/release-rc.yaml | 72 ++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .gitea/workflows/release-rc.yaml diff --git a/.gitea/workflows/release-rc.yaml b/.gitea/workflows/release-rc.yaml new file mode 100644 index 0000000..12ec9fc --- /dev/null +++ b/.gitea/workflows/release-rc.yaml @@ -0,0 +1,72 @@ +name: Release candidate +'on': + workflow_dispatch: + inputs: + dry_run: + description: Plan a cut without changing release state + type: boolean + default: false + finalize: + description: Retry finalization of an existing cut; do not cut another RC + type: boolean + default: false + recover: + description: Recover the same published RC after a deployment timeout; never + reupload + type: boolean + default: false + circle_build: + description: Original release run id (recovery only) + type: string + default: '' + merge_sha: + description: Existing cut merge_sha (finalize retry only) + type: string + default: '' + bump_sha: + description: Existing cut bump_sha (finalize retry only) + type: string + default: '' + branch: + description: Existing cut branch (finalize retry only) + type: string + default: '' + version: + description: Existing cut version (finalize retry only) + type: string + default: '' + pull_request: + types: + - closed + branches: + - develop +permissions: + contents: read +jobs: + release-rc: + # The old qbit-rc-published repository_dispatch is replaced by the already-proven workflow_dispatch + # completion: the publisher's own ActionsWRITE job dispatches this workflow with finalize=true plus + # merge_sha/bump_sha/branch/version (same inputs as the manual finalize retry). + permissions: + contents: write + actions: read + pull-requests: write + if: github.event_name == 'workflow_dispatch' + || (github.event_name == 'pull_request' && github.event.pull_request.merged + == true && github.event.pull_request.base.ref == 'develop' && contains(github.event.pull_request.labels.*.name, + 'release:rc')) + uses: self:KofTwentyTwo/platform-ci/.gitea/workflows/qbit-release-rc.yaml@qrun-release-v1 + with: + dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || false + }} + finalize: ${{ github.event_name == 'workflow_dispatch' && inputs.finalize }} + recover: ${{ github.event_name == 'workflow_dispatch' && inputs.recover || false + }} + circle_build: ${{ github.event_name == 'workflow_dispatch' && inputs.circle_build + || '' }} + merge_sha: ${{ inputs.merge_sha || '' }} + bump_sha: ${{ inputs.bump_sha || '' }} + branch: ${{ inputs.branch || '' }} + version: ${{ inputs.version || '' }} + secrets: + QRUN_TAG_SIGNING_KEY: ${{ secrets.QRUN_TAG_SIGNING_KEY }} -- 2.54.0 From 2954345e5d2741d413fb6c84a74dbf7babc7579d Mon Sep 17 00:00:00 2001 From: James Maes Date: Mon, 2 Nov 2026 14:15:58 -0600 Subject: [PATCH 12/13] fix: avoid Liquibase include directive in explanatory headers Use ordinary prose in changelog headers so the CLI does not interpret documentation as a licensed include directive. Changeset content is unchanged. Actual packaged schema and defaults pass the PostgreSQL CLI gate (cluster 8 changesets; alerts 58). Co-Authored-By: GPT-6 (Codex) --- .../db/liquibase/qbit-alerts/alerts-defaults.changelog.sql | 2 +- .../resources/db/liquibase/qbit-alerts/alerts.changelog.sql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/db/liquibase/qbit-alerts/alerts-defaults.changelog.sql b/src/main/resources/db/liquibase/qbit-alerts/alerts-defaults.changelog.sql index 77ac3c2..b693aa8 100644 --- a/src/main/resources/db/liquibase/qbit-alerts/alerts-defaults.changelog.sql +++ b/src/main/resources/db/liquibase/qbit-alerts/alerts-defaults.changelog.sql @@ -3,7 +3,7 @@ -- qbit-alerts starter defaults: the two channels every install needs, and the -- two groups the qbit itself files alerts under, so Delivery health and the -- group lists are not empty before the first alert. --- Include it from the host's master changelog AFTER alerts.changelog.sql: +-- Load this file from the host's master changelog AFTER alerts.changelog.sql: -- -- - include: { file: db/liquibase/qbit-alerts/alerts-defaults.changelog.sql } -- diff --git a/src/main/resources/db/liquibase/qbit-alerts/alerts.changelog.sql b/src/main/resources/db/liquibase/qbit-alerts/alerts.changelog.sql index 6a0406b..bd5f839 100644 --- a/src/main/resources/db/liquibase/qbit-alerts/alerts.changelog.sql +++ b/src/main/resources/db/liquibase/qbit-alerts/alerts.changelog.sql @@ -1,7 +1,7 @@ -- liquibase formatted sql -- qbit-alerts schema (QRun-IO/qqq docs/specs/2026-10-12-qbit-alerts-design.md section 4). --- Include it from the host's master changelog: +-- Load this file from the host's master changelog: -- -- - include: { file: db/liquibase/qbit-alerts/alerts.changelog.sql } -- -- 2.54.0 From 818ff9909167b4177be2154e43da8defd9afbd42 Mon Sep 17 00:00:00 2001 From: James Maes Date: Tue, 3 Nov 2026 15:15:51 -0600 Subject: [PATCH 13/13] docs: record Forge prerequisite fix for release Co-Authored-By: Claude Co-Authored-By: Codex --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0620f12..b37cefc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project are documented here. The format follows Keep ## [0.1.0] - Unreleased ### Fixed +- SQL changelog headers: explanatory "-- Include it from the host..." comments were parsed as a licensed Liquibase `include` directive. Replaced with neutral wording; changeset bodies and schema are unchanged. - Under OAuth2, per-recipient checks (alert visibility for external channels, follower record access, audience sessions) never worked: they used token-less automated sessions, which OAuth2 rejects, so external sends fell back to the conservative rule. When the host declares the QQQ `alerts` service principal (`AlertsQBitConfig.withServicePrincipal`, default `alerts`), these checks run on the recipient's behalf through it: the recipient's current access intersected with the principal's. Alert recording and routing bookkeeping stay on the system session, so alerting does not depend on the identity provider being up. With no principal declared, behavior is unchanged. Needs the QQQ release with service identities (qqq#1255, #1256). - Audit noise: every monitor run (lease claim, then run result) and every reminder check wrote a "Record was Edited" audit (about 7,000 `alerts_monitor` and 1,800 `alerts_alert` audits in 6 hours on one production host, most with no field details). Engine updates that touch only bookkeeping fields (`RuntimeFields`: monitor `claimedBy`, `claimedUntil`, `lastRunAt`, `nextRunAt`, `lastStatus`, `lastValue`, `lastError`, `lastElapsedMs`, `consecutiveFailures`, `conditionSince`; alert `timedNotificationCheckedAt`, `lastNotifiedAt`, `recordRefCount`) are written with `omitDmlAudit`. Configuration edits, raises and alert state changes are audited as before, as are UI and API edits of any field. - Read the QBit metadata version from the Maven-filtered artifact version so release builds report their release version. -- 2.54.0