The cdn.provider.<id> health check returned UNKNOWN ("CDN provider does not
support connection tests") for any adapter without CdnOperations, i.e. the
NONE placeholder and Souin. The central evaluator never alerts or changes
state on UNKNOWN, so such a check is permanently useless.
- New optional SPI CdnHealthProbe/CdnHealth; the health check prefers it,
then the connection test, then reports UP with testable=false.
- CloudFront implements it: GetDistribution -> UP when enabled and
Deployed, DEGRADED while InProgress, DOWN when NoSuchDistribution or
disabled; throttling/5xx/network errors DEGRADED; rejected or missing
credentials DOWN. On AccessDenied it falls back to GetDistributionConfig
(the kof22 policy grants that, not GetDistribution) and reports
testable=false; if both are denied, UP with testable=false.
- CloudWatch AWS/CloudFront 5xxErrorRate (Average, 5-min periods, last 30
minutes) goes into details; above 5% the check is DEGRADED. Best effort.
- Messages are fixed text; details hold only booleans, numbers and known
states.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
QRun-IO/.github#2 adds a tag-and-release job that signs vX with the
QRUN_TAG_SIGNING_KEY secret after Maven Central confirms the artifact.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The producer read a literal version, so released artifacts reported a stale
or -SNAPSHOT version. qbit-cdn.properties (version=${project.version}) is
Maven-filtered and the producer loads it; tests assert producer == bundle ==
artifact version.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The bundle version is now Maven-filtered, so a literal SNAPSHOT in the test
fails every release build. Surefire passes the artifact version in
qbit.artifactVersion.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
On release branches the bundle's version and the producer's differed, so the
bundle test that asserts they match failed, and released bundles recorded
SNAPSHOT as their provenance. help/*.yaml is now filtered:
version: ${project.version}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Host-neutral help (deployment-specific facts removed), registered with
HelpBundles, gated by HelpBundleAssertions. QQQ 4.1.0-RC.7.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
onlyWhenFieldsChange was only an allow-list, so a rule could not say
"purge on any change except this derived counter" without listing every
rendered field. An entry starting with "!" now names an ignored field:
with only ignored entries, any other changed field still purges; with a
mixed list the allow-list applies and ignored fields never count.
Inserts and deletes are unaffected. No schema change.
For kof22: the cms_blog_post rule gets "!viewCount" so the nightly view
count refresh purges nothing (Website-Backend#206).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With no live CDN (provider NONE, or every hostname at stage OFF) the
Purge From CDN, Purge Everything and Retry Purge actions said the
requests were "sent within seconds" while the dispatcher skipped them.
Review and Result now carry a warning line ("No CDN provider configured:
purges are recorded only, not sent." or "CDN hostnames are not live"),
from the same status logic CdnPurgeService records (sendingStatus).
The home's Connection, Health and Purges cards say the same, and the
Origin headers card no longer implies a check is scheduled.
Refs KofTwentyTwo/Website-Backend#199
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Moves qqq-orb@0.6.8 to qqq-orb@0.6.9, which passes --update-snapshots so cached SNAPSHOT dependencies are re-checked on every build (QRun-IO/qqq-orb#22).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Move the core baseline to the released 4.1.0-RC.6 (architecture review
finding F19, guardrail G7). Adopt qbit-build-parent 2.1.0 with the
architecture guardrails enforced (G1, G3, G4, G7) and tests in strict
raw-route mode (G2). Everything passes with no source changes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replace the hand-rolled HMAC in RevalidationHookRunner with core
WebhookSigner (Standard Webhooks) from QQQ 4.1.0-RC.5, and send through
core SafeHttpClient.
New cdn_revalidation_hook fields:
- signatureFormat: STANDARD_WEBHOOKS (the default for new rows) or LEGACY,
which keeps X-Revalidate-Signature byte-for-byte. A null format, as on
existing rows, stays LEGACY.
- allowPlainHttp and internalAllowlist: explicit exceptions to the SSRF
policy.
Closes#15 (architecture review QRun-IO/qqq#1150, finding F11).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Removes publish_hotfix_release: a hotfix/* branch push published a GA
release to Maven Central with no tag or review (QRun-IO/qbit-cdn#12,
QRun-IO/qqq#1121). hotfix/* branches now run test_only; a hotfix
release publishes from a reviewed vX.Y.Z tag through publish_release.
Adds .github/workflows/release-rc.yml (reusable QRun-IO/.github
qbit-release-rc): a manual dispatch, or merging a develop PR labelled
release:rc, merges develop into the release line and the release/* push
runs the existing CircleCI RC publish.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2.41.10 carries the HIGH advisory GHSA-443w-3rq3-5m5h (flagged by a Trivy scan); 2.41.30+ fixes it. Same minor line, so no API change.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
{blog.slug} used the prefix as both the FK field name and the table name, so
apps with prefixed tables (cms_blog) silently lost those purge paths. The
joined table now comes from the <prefix>Id field's possible-value source,
falling back to the bare prefix. A missing joined table is logged once.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Readable at every width without inner scrolling: label/value blocks are dl grids, hostnames and recent purges are lists (passes the kof22 widget readability guard).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>