감사 remediation 의 마지막 항목 두 개. ## 아무 데서도 안 돌던 레인 등록 태스크 97개 중 어느 CI 경로로도 도달하지 않는 것이 20개였다. 있는 줄 알았는데 안 도는 상태 — 이번에 고친 `*CleanArchitectureTest` 와 같은 종류의 문제다. 각각 판단해서 처리했고, 삭제는 0건이다. - stage 2(`integration-main.yml`, push:main + 03:00) 에 잡 3개 신설: mongo 컨테이너 레인 6개 / messaging 계약 증거 3개 / app-bootstrap integrationTest. 컨테이너가 필요한 레인은 PR 에 두지 않는다 — PR 예산은 5분이고, 단계를 나눈 이유가 이것이다 - stage 3(`release.yml`) 에 `grpc-stable-release-gate` 신설 (inprocess/netty/fault) + `app-image-release` 의 needs 로 연결 - 수동 확정 3개: `grpcPerformanceTest`, `openapiCheckSnapshot`(드리프트 검사는 이미 stage 1 의 `check` 안에 있고 이 태스크는 승인 지점), `sampleOffCompile`(stage 1 `sampleOffTest` 의 진부분집합). 전용 레지스트리 대신 루트 README 에 적었다 — `verifyReadmeCommands` 가 거기 적힌 태스크의 실재를 검증하므로, 문서가 곧 검사 대상이 된다 - 게이트 매트릭스 행 11개 신설. 잡↔행 양방향 대조 결과 68개 잡 전부 행이 있고 행 없는 잡도, 어디서도 안 도는 잡도 없다 측정이 틀린 4건은 배선하지 않았다 — 이미 도달하고 있었다: `jpaPlatformReleaseGate`(`jpaReleaseGate dependsOn`), `generateJpaEvidenceManifests`(`verifyJpaCandidateEvidence` 경유), `messagingCertificationTest`(`verifyMessagingCertificationEvidence` 경유), `stageDockerJar`(호출자가 Gradle 이 아니라 `release.yml` 의 `docker build`). ## 버전 카탈로그 이관 카탈로그를 우회해 문자열로 박혀 있던 값 11개를 `gradle/libs.versions.toml` 로 옮겼다. plugin 5개는 `[plugins]` + `alias(...)`, 툴 3개는 `libs.versions.*.get()`. `grpcVersion`/`protobufVersion`/`awsSdkVersion` 은 이관이 불가하다고 넘어온 항목이었으나, `ext.x` 를 접근자로 남기고 값만 카탈로그에서 읽으면 소비 파일 9개와 `ca.grpc-platform-module.gradle:28` 의 `findProperty` 계약이 그대로이고 해석 결과도 동일하다. **lockfile 재생성 0건.** `commons-lang3` / `netty` 는 BOM 오버라이드라 그대로 둔다 — 오버라이드하는 이유가 주석과 분리되면 값만 남고 근거가 사라진다. ## 검증 (깨끗한 체크아웃, 커밋 전) `verify-gate-matrix.sh` → 107 gates, 101 verified, drift 0 · `verify-gradle-wrapper.sh` PASS · 워크플로 YAML 21개 파싱 OK · `gradlew help` · `verifyCleanArchitectureDependencies` · `build-logic test` · `:app-bootstrap:test` **1001 tests 실패 0** · `:domain-core:check` · `verifyDocumentationContracts` · `verifyDependencyLocks` · `verifyReadmeCommands`. ## 남은 문제 mongo 6레인 · `bootstrap-integration` · messaging 매니페스트 스키마 검증은 CI 에서 한 번도 돈 적이 없다. Docker 가 없으면 실패하도록 설계돼 있으므로 **첫 main push 와 03:00 run 이 빨간 것이 정상 시나리오**다. 로컬에서 Docker 레인을 돌려보지 않았고, `mongo-container-lanes` 의 timeout 90분은 실측이 아니라 추정치다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1026 lines
40 KiB
YAML
1026 lines
40 KiB
YAML
# Every CI control in this checkout: one row per job in .github/workflows, plus the delegated-pending
|
|
# rows for controls that are real and that no workflow runs.
|
|
#
|
|
# The rows are grouped by STAGE, because that is how the workflows are now split. Stage 1 blocks a
|
|
# merge, stage 2 reports on main after the merge, stage 3 stops a release. A control's stage is the
|
|
# honest form of "does this gate development", and it is what release_blocking below records.
|
|
#
|
|
# Image signing and provenance attestation are still absent. So is any join between the image build
|
|
# in release.yml and the two evidence workflows that answer the same release tag from their own files
|
|
# (jpa-release.yml, fileserver-release.yml); that join is registered delegated-pending rather than
|
|
# left unstated. .github/scripts/verify-gate-matrix.sh checks every row against the repository and is
|
|
# itself the gate-matrix-lint job below; it pins no gate count, so registering a new control is
|
|
# adding a row here and nothing else.
|
|
#
|
|
# Fields:
|
|
# release_blocking: true, false, or conditional
|
|
# mechanism: gradle-custom-task, gradle-plugin-task, contract-test, workflow-job,
|
|
# or delegated-pending
|
|
# ref: task, plugin@task, repository-relative test path below src/, or workflow job id
|
|
# workflow/job: canonical workflow and job that execute or represent the control
|
|
# execution: check (through Gradle check), explicit (named in the job), or job
|
|
#
|
|
# release_blocking is verified, not declared:
|
|
# true a release gate waits on this job — it is ci-quality-gates.yml::release-gate itself,
|
|
# one of that job's `needs:`, a name in its REQUIRED_CHECKS, or a job in a workflow
|
|
# that only runs on a release tag. The lint fails a `true` row that is none of those.
|
|
# conditional the control is real and gates something, but no release gate can require it: it runs
|
|
# behind a path filter, a schedule, a manual dispatch, or an input, so its check run
|
|
# does not exist for every commit a release gate sees.
|
|
# false advisory. A failure here is a signal, not a stop.
|
|
gates:
|
|
# =================================================================================
|
|
# STAGE 1 — pull request. These block a merge.
|
|
# =================================================================================
|
|
#
|
|
# ci-quality-gates.yml — the repository-wide gate. No path filter: it runs on every pull request
|
|
# and every push to main, which is what makes the leaf test suites, the architecture dependency
|
|
# gate and the Checkstyle ruleset below cover a diff without any per-adapter job repeating them.
|
|
- id: format-lint
|
|
release_blocking: true
|
|
mechanism: gradle-plugin-task
|
|
ref: com.diffplug.spotless@spotlessCheck
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: unit-and-contract-tests
|
|
release_blocking: true
|
|
mechanism: gradle-plugin-task
|
|
ref: java@test
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: conditional-transport-qualification
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: conditionalTransportQualification
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: explicit
|
|
- id: clean-architecture-dependencies
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyCleanArchitectureDependencies
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: environment-contract
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyEnvKeys
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: declared-dependency-absence
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyDependencyPolicy
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: notification-api-surface
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyNotificationApiSurface
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: notification-configuration-contract
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyNotificationConfiguration
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: notification-support-grade-evidence
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyNotificationEvidence
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: graphql-api-surface
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyGraphQlApiSurface
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: mongo-api-surface
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyMongoApiSurface
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
#
|
|
# The strongest evidence this repository produces, and CI does not run it. Fifteen Compose lanes
|
|
# start real PostgreSQL, MongoDB, Kafka, MinIO, Mailpit and Keycloak, take a real client-credentials
|
|
# JWT, and prove things no in-JVM test can: that all-off boots with no external resource, that the
|
|
# notification handoff delivers exactly once across a restart on the same volume, that the startup
|
|
# log is silent. It runs from a developer's machine via scripts/run-compose-runtime-smoke.sh and
|
|
# from nowhere else — no workflow invokes it, so nothing re-runs it on a pull request.
|
|
#
|
|
# Registered delegated-pending so the gap is a tracked absence rather than an unstated one.
|
|
# Executing it in CI needs a Docker-capable runner and a decision about the minutes fifteen
|
|
# container lanes cost, which is an infrastructure choice rather than a wiring oversight.
|
|
- id: runtime-smoke-matrix
|
|
release_blocking: conditional
|
|
mechanism: delegated-pending
|
|
ref: runtime-smoke-matrix-lane
|
|
workflow: ci-quality-gates.yml
|
|
job: release-gate
|
|
execution: job
|
|
#
|
|
# `conditional-transport-qualification` above is the registered GraphQL control, and it is a
|
|
# boundary test: a @SpringBootTest over a nested test application with in-memory Basic Auth. Its own
|
|
# javadoc says so — "the nested application deliberately owns only test authentication and CORS
|
|
# policy". That is a legitimate transport-boundary proof and it is not release evidence for the
|
|
# security posture, which is the distinction the Definition of Done draws.
|
|
#
|
|
# The real proof exists: the local-graphql Compose lane obtains a Keycloak client-credentials token
|
|
# and posts it to /graphql on the running bootJar, asserting that anonymous and malformed
|
|
# credentials are refused and the authenticated query answers. It is part of the runtime smoke
|
|
# matrix above, so it inherits that control's pending status rather than having none of its own.
|
|
- id: graphql-runtime-jwt
|
|
release_blocking: conditional
|
|
mechanism: delegated-pending
|
|
ref: graphql-runtime-jwt-lane
|
|
workflow: ci-quality-gates.yml
|
|
job: release-gate
|
|
execution: job
|
|
#
|
|
# Checkstyle, not the retired regex. verifyOneTypePerFile parsed Java with
|
|
# `^public\s+...` line by line; OneTopLevelClass and OuterTypeFilename ask the same two questions
|
|
# against a parsed file and see the package-private top-level types the regex could not. The task
|
|
# still exists in src/build.gradle as an aggregate of every leaf's checkstyleMain, but no workflow
|
|
# names it any more, so this row names what actually runs: checkstyleMain, inside `check`.
|
|
- id: one-type-per-file
|
|
release_blocking: true
|
|
mechanism: gradle-plugin-task
|
|
ref: checkstyle@checkstyleMain
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: trivy-suppression-governance
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyTrivyignore
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: quarantine-sunset
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyQuarantineSunset
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: public-path-snapshot
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyPublicPathSnapshot
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: explicit
|
|
- id: dependency-locks
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: verifyDependencyLocks
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: explicit
|
|
#
|
|
# Points at the inventory guard rather than at one suite. The 87 architecture rules used to be
|
|
# 74-in-one-class plus a scattered remainder, so naming CleanArchitectureTest.java named most of
|
|
# them and silently omitted the rest; after the split (BOOT-012) it would have named a fifth of
|
|
# them. ArchRuleDiscoveryContractTest pins every rule in the package by name and fails if one is
|
|
# declared where ArchUnit cannot discover it, which is the property this gate actually exists to
|
|
# protect.
|
|
- id: architecture-contract-test
|
|
release_blocking: true
|
|
mechanism: contract-test
|
|
ref: app-bootstrap/src/test/java/dev/caskeleton/bootstrap/architecture/ArchRuleDiscoveryContractTest.java
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
- id: sample-off
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: sampleOffTest
|
|
workflow: ci-quality-gates.yml
|
|
job: sample-off
|
|
execution: explicit
|
|
- id: gate-matrix-lint
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: gate-matrix-lint
|
|
workflow: ci-quality-gates.yml
|
|
job: gate-matrix-lint
|
|
execution: job
|
|
- id: redis-sdk
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: redis-sdk
|
|
workflow: ci-quality-gates.yml
|
|
job: redis-sdk
|
|
execution: job
|
|
- id: jpa-candidate-evidence
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: jpa-candidate-evidence
|
|
workflow: ci-quality-gates.yml
|
|
job: jpa-candidate-evidence
|
|
execution: job
|
|
- id: quality-release-gate
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: release-gate
|
|
workflow: ci-quality-gates.yml
|
|
job: release-gate
|
|
execution: job
|
|
- id: flaky-quarantine
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: quarantine
|
|
workflow: ci-quality-gates.yml
|
|
job: quarantine
|
|
execution: job
|
|
- id: redis-sdk-support-matrix
|
|
release_blocking: true
|
|
mechanism: contract-test
|
|
ref: adapter/outbound/cache-redis/src/test/java/dev/caskeleton/adapter/outbound/cache/redis/sdk/RedisSupportMatrixTest.java
|
|
workflow: ci-quality-gates.yml
|
|
job: quality-gates
|
|
execution: check
|
|
#
|
|
# pr-adapters.yml — the lanes `check` cannot reach: a second servlet container, a real Nginx,
|
|
# Reactor Netty, one PostgreSQL major per job, one HTTP transport per job. Each job is behind a
|
|
# per-job path filter computed from the pull request's diff, so no release gate can wait on one.
|
|
- id: httpclient-contract-stable-contract
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: httpclient-stable-contract
|
|
workflow: pr-adapters.yml
|
|
job: httpclient-stable-contract
|
|
execution: job
|
|
- id: httpclient-security-and-compatibility
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: httpclient-security-and-compatibility
|
|
workflow: pr-adapters.yml
|
|
job: httpclient-security-and-compatibility
|
|
execution: job
|
|
- id: jpa-postgresql-contract
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: jpa-postgresql-contract
|
|
workflow: pr-adapters.yml
|
|
job: jpa-postgresql-contract
|
|
execution: job
|
|
- id: jpa-migration-smoke
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: jpa-migration-smoke
|
|
workflow: pr-adapters.yml
|
|
job: jpa-migration-smoke
|
|
execution: job
|
|
- id: web-cross-stack-parity
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: web-cross-stack-parity
|
|
workflow: pr-adapters.yml
|
|
job: web-cross-stack-parity
|
|
execution: job
|
|
- id: web-nginx-proxy-contract
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: web-nginx-proxy-contract
|
|
workflow: pr-adapters.yml
|
|
job: web-nginx-proxy-contract
|
|
execution: job
|
|
- id: websocket-container-matrix
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: websocket-container-matrix
|
|
workflow: pr-adapters.yml
|
|
job: websocket-container-matrix
|
|
execution: job
|
|
- id: websocket-nginx-contract
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: websocket-nginx-contract
|
|
workflow: pr-adapters.yml
|
|
job: websocket-nginx-contract
|
|
execution: job
|
|
#
|
|
# The job every lane in that file reads. It fails closed on an unreadable diff rather than
|
|
# reporting that nothing changed, because a filter that answers false on a broken comparison
|
|
# turns off every gate behind it and reports green.
|
|
- id: pr-adapter-change-filter
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: changes
|
|
workflow: pr-adapters.yml
|
|
job: changes
|
|
execution: job
|
|
#
|
|
# fileserver-pr.yml — path-filtered pull-request gates. They stay in their own file because
|
|
# FileserverDocumentationCoverageTest requires every job id docs/fileserver/support-matrix.md
|
|
# names to be defined in a .github/workflows/fileserver-*.yml.
|
|
#
|
|
# Path-filtered pull-request gates. They are the only automated check of the fileserver's
|
|
# ext4 and HTTP contracts, but they start only when the filtered paths change, so no release
|
|
# gate can wait on them.
|
|
- id: fileserver-unit-and-architecture
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: fileserver-unit-and-architecture
|
|
workflow: fileserver-pr.yml
|
|
job: fileserver-unit-and-architecture
|
|
execution: job
|
|
- id: fileserver-local-ext4-contract
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: fileserver-local-ext4-contract
|
|
workflow: fileserver-pr.yml
|
|
job: fileserver-local-ext4-contract
|
|
execution: job
|
|
- id: fileserver-http-contract
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: fileserver-http-contract
|
|
workflow: fileserver-pr.yml
|
|
job: fileserver-http-contract
|
|
execution: job
|
|
- id: fileserver-security-suite
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: fileserver-security-suite
|
|
workflow: fileserver-pr.yml
|
|
job: fileserver-security-suite
|
|
execution: job
|
|
- id: fileserver-bounded-memory
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: fileserver-bounded-memory
|
|
workflow: fileserver-pr.yml
|
|
job: fileserver-bounded-memory
|
|
execution: job
|
|
#
|
|
# dependency-vulnerability.yml — supply chain. trivy-fs is the one cross-workflow check
|
|
# ci-quality-gates.yml::release-gate requires by name through REQUIRED_CHECKS.
|
|
- id: dependency-review
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: dependency-review
|
|
workflow: dependency-vulnerability.yml
|
|
job: dependency-review
|
|
execution: job
|
|
- id: dependency-submission
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: dependency-submission
|
|
workflow: dependency-vulnerability.yml
|
|
job: dependency-submission
|
|
execution: job
|
|
- id: filesystem-vulnerability-scan
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: trivy-fs
|
|
workflow: dependency-vulnerability.yml
|
|
job: trivy-fs
|
|
execution: job
|
|
#
|
|
# link-check.yml — committed documentation links, path-filtered.
|
|
- id: documentation-links
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: lychee
|
|
workflow: link-check.yml
|
|
job: lychee
|
|
execution: job
|
|
|
|
# =================================================================================
|
|
# STAGE 2 — merged state. These do not block a merge; the merge already happened.
|
|
# =================================================================================
|
|
#
|
|
# integration-main.yml — push to main, nightly, or dispatch. The documentation-drift gates that
|
|
# left `check`, and the lanes that need a machine which is not simultaneously compiling.
|
|
- id: documented-leaf-count
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: verifyDocumentedLeafCount
|
|
workflow: integration-main.yml
|
|
job: documentation-contracts
|
|
execution: job
|
|
- id: runbook-reference-drift
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: verifyRunbookReferences
|
|
workflow: integration-main.yml
|
|
job: documentation-contracts
|
|
execution: job
|
|
- id: readme-command-drift
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: verifyReadmeCommands
|
|
workflow: integration-main.yml
|
|
job: documentation-contracts
|
|
execution: job
|
|
#
|
|
# Scheduled. httpclient-nightly-http3-experimental is continue-on-error on purpose: HTTP/3 is
|
|
# an opt-in experiment (-Phttp3.tests.enabled) and a red experiment must not bury a real
|
|
# nightly regression. Registered false so the matrix says that out loud instead of leaving a
|
|
# job that cannot fail unrecorded.
|
|
- id: httpclient-nightly-fault-injection
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: httpclient-fault-injection
|
|
workflow: integration-main.yml
|
|
job: httpclient-fault-injection
|
|
execution: job
|
|
- id: httpclient-nightly-performance
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: httpclient-performance
|
|
workflow: integration-main.yml
|
|
job: httpclient-performance
|
|
execution: job
|
|
- id: httpclient-nightly-http3-experimental
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: httpclient-http3-experimental
|
|
workflow: integration-main.yml
|
|
job: httpclient-http3-experimental
|
|
execution: job
|
|
#
|
|
# Scheduled load, abuse and shutdown lane.
|
|
- id: web-load-abuse-and-shutdown
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: web-load-abuse-and-shutdown
|
|
workflow: integration-main.yml
|
|
job: web-load-abuse-and-shutdown
|
|
execution: job
|
|
#
|
|
# The four documentation-drift gates, as one task. They were `dependsOn` of the root `check`
|
|
# and are not any more: a README sentence about a renamed task should not fail a
|
|
# compile-and-test run. This job is what keeps that a demotion rather than a deletion — with
|
|
# no workflow invoking the aggregate, all four would run nowhere. release_blocking: false is
|
|
# the demotion stated as a fact the lint can check.
|
|
- id: documentation-contracts
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: verifyDocumentationContracts
|
|
workflow: integration-main.yml
|
|
job: documentation-contracts
|
|
execution: explicit
|
|
#
|
|
# Ran inside verifyDocumentationContracts above rather than named in the job, which is why
|
|
# this row is execution: job. It had no row at all before.
|
|
- id: test-source-set-registry
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: verifyTestSourceSetRegistry
|
|
workflow: integration-main.yml
|
|
job: documentation-contracts
|
|
execution: job
|
|
#
|
|
# The six Docker-backed MongoDB lanes. Registered in the leaf, excluded from `test` by tag, absent
|
|
# from `check`, and named by no workflow until now — scripts/verify-mongodb-platform.sh was the
|
|
# only caller and nothing in .github runs it. One row per lane because each is its own single-line
|
|
# command, which is what makes `execution: explicit` checkable.
|
|
#
|
|
# release_blocking: false is the honest value, not a demotion: stage 2 runs after the merge, so no
|
|
# release gate can wait on it. Promoting these to stage 1 would put a replica set, a three-node
|
|
# failover and a Toxiproxy on the pull-request budget.
|
|
- id: mongo-replica-set-lane
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: mongoReplicaSetTest
|
|
workflow: integration-main.yml
|
|
job: mongo-container-lanes
|
|
execution: explicit
|
|
- id: mongo-failover-lane
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: mongoFailoverTest
|
|
workflow: integration-main.yml
|
|
job: mongo-container-lanes
|
|
execution: explicit
|
|
- id: mongo-migration-lane
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: mongoMigrationTest
|
|
workflow: integration-main.yml
|
|
job: mongo-container-lanes
|
|
execution: explicit
|
|
- id: mongo-compatibility-lane
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: mongoCompatibilityTest
|
|
workflow: integration-main.yml
|
|
job: mongo-container-lanes
|
|
execution: explicit
|
|
- id: mongo-security-integration-lane
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: mongoSecurityIntegrationTest
|
|
workflow: integration-main.yml
|
|
job: mongo-container-lanes
|
|
execution: explicit
|
|
- id: mongo-performance-lane
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: mongoPerformanceTest
|
|
workflow: integration-main.yml
|
|
job: mongo-container-lanes
|
|
execution: explicit
|
|
#
|
|
# The messaging contract evidence DAG. One row, because one job is one control and the control is
|
|
# the aggregate: `verifyMessagingContracts` reaches five strict qualification tasks, and through
|
|
# them `prepareMessagingContractEvidence`, plus both manifest schema validators
|
|
# (validateMessagingJsonSchemaV1EvidenceManifestSchema by dependsOn,
|
|
# validateMessagingContractsEvidenceManifestSchema by finalizedBy). Strict qualification tasks are
|
|
# registered outside `check` by design, so before this job none of the seven executed anywhere.
|
|
- id: messaging-contract-evidence
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: verifyMessagingContracts
|
|
workflow: integration-main.yml
|
|
job: messaging-contract-evidence
|
|
execution: explicit
|
|
#
|
|
# app-bootstrap's Testcontainers lane. Its own source set exists so that `:app-bootstrap:test`
|
|
# needs no Docker daemon; the unclosed consequence was that a source set outside `test` is also
|
|
# outside `check`, so these contracts compiled everywhere and ran nowhere.
|
|
- id: bootstrap-integration-contracts
|
|
release_blocking: false
|
|
mechanism: gradle-custom-task
|
|
ref: integrationTest
|
|
workflow: integration-main.yml
|
|
job: bootstrap-integration
|
|
execution: explicit
|
|
#
|
|
# notification-platform.yml — `pr` is path-filtered and also runs on push to main; nightly-chaos
|
|
# is schedule/dispatch only. The release-blocking notification controls are the verifyNotification*
|
|
# rows above, which run inside check on every pull request.
|
|
#
|
|
# `pr` is path-filtered (and runs on push to main); nightly-chaos is schedule/dispatch only.
|
|
# The release-blocking notification controls are the verifyNotification* rows above, which run
|
|
# inside check on every pull request.
|
|
- id: notification-platform-pr
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: pr
|
|
workflow: notification-platform.yml
|
|
job: pr
|
|
execution: job
|
|
- id: notification-platform-nightly-chaos
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: nightly-chaos
|
|
workflow: notification-platform.yml
|
|
job: nightly-chaos
|
|
execution: job
|
|
#
|
|
# messaging-certification.yml — path-filtered pull request plus a weekly schedule.
|
|
#
|
|
# The messaging platform's only claim that needs a real broker to be true. The gate is the
|
|
# evidence check rather than the lane, and it depends on the lane: passing means both that every
|
|
# fault scenario produced the outcome the shared contract fixes and that the committed manifest is
|
|
# what this run wrote. Before it existed, `CertifiedEvidence` was a hand-authored list and
|
|
# "certified against a live broker" was a sentence a developer could type.
|
|
- id: messaging-broker-certification
|
|
release_blocking: conditional
|
|
mechanism: gradle-custom-task
|
|
ref: verifyMessagingCertificationEvidence
|
|
workflow: messaging-certification.yml
|
|
job: broker-certification
|
|
execution: explicit
|
|
#
|
|
# object-storage-qualification.yml — pull request, weekly schedule, and two protected dispatch
|
|
# inputs for the AWS sandbox lane.
|
|
#
|
|
# These three ran under `release_blocking: true` while nothing waited on them. object-storage-
|
|
# qualification.yml has no push-to-main trigger and messaging-certification.yml is behind a path
|
|
# filter, so neither produces a check run for every commit ci-quality-gates.yml::release-gate
|
|
# judges; requiring them there would hang on the commits where they never start. They are
|
|
# conditional — real controls on their own trigger — until someone decides to widen that trigger,
|
|
# which is a CI-minutes decision about MinIO and Kafka containers, not a wiring oversight.
|
|
- id: object-storage-minio-managed-contract
|
|
release_blocking: conditional
|
|
mechanism: gradle-custom-task
|
|
ref: objectStorageMinioContractTest
|
|
workflow: object-storage-qualification.yml
|
|
job: minio-managed-contract
|
|
execution: explicit
|
|
- id: poster-image-migration
|
|
release_blocking: conditional
|
|
mechanism: gradle-custom-task
|
|
ref: posterImageMigrationTest
|
|
workflow: object-storage-qualification.yml
|
|
job: poster-image-v7-migration
|
|
execution: explicit
|
|
- id: object-storage-minio-managed-fault
|
|
release_blocking: conditional
|
|
mechanism: gradle-custom-task
|
|
ref: objectStorageMinioFaultTest
|
|
workflow: object-storage-qualification.yml
|
|
job: minio-managed-fault
|
|
execution: explicit
|
|
- id: object-storage-aws-protected-qualification
|
|
release_blocking: conditional
|
|
mechanism: delegated-pending
|
|
ref: approval-gate-b
|
|
workflow: object-storage-qualification.yml
|
|
job: aws-managed-common-subset
|
|
execution: job
|
|
#
|
|
# redis-sdk-topology.yml — path-filtered pull request (standalone only) and the nightly matrix.
|
|
#
|
|
# Promoted from delegated-pending: the workflow is no longer manual-only. A pull request that
|
|
# touches the Redis leaf runs the standalone lane, and the full supported-version x topology
|
|
# matrix runs nightly and on a release candidate. While it was dispatch-only, a release could
|
|
# claim topology evidence that nobody had produced for that commit.
|
|
- id: redis-sdk-topology-evidence
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: topology-evidence
|
|
workflow: redis-sdk-topology.yml
|
|
job: topology-evidence
|
|
execution: job
|
|
#
|
|
# The lane that topology-evidence needs. Same trigger as the evidence row above it.
|
|
- id: redis-sdk-topology-lanes
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: lanes
|
|
workflow: redis-sdk-topology.yml
|
|
job: lanes
|
|
execution: job
|
|
#
|
|
# fileserver-nightly.yml — scheduled only. NFS ambiguity, process-kill and lease behaviour need
|
|
# hours and real filesystems; a failure is a signal to act on, not a stop on a release that did not
|
|
# cause it.
|
|
#
|
|
# Scheduled only. NFS ambiguity, process-kill and lease behaviour need hours and real
|
|
# filesystems; a failure is a signal to act on, not a stop on a release that did not cause it.
|
|
- id: fileserver-nfs-ambiguity
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: fileserver-nfs-ambiguity
|
|
workflow: fileserver-nightly.yml
|
|
job: fileserver-nfs-ambiguity
|
|
execution: job
|
|
- id: fileserver-process-kill-matrix
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: fileserver-process-kill-matrix
|
|
workflow: fileserver-nightly.yml
|
|
job: fileserver-process-kill-matrix
|
|
execution: job
|
|
- id: fileserver-large-file-performance
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: fileserver-large-file-performance
|
|
workflow: fileserver-nightly.yml
|
|
job: fileserver-large-file-performance
|
|
execution: job
|
|
- id: fileserver-multi-instance-lease
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: fileserver-multi-instance-lease
|
|
workflow: fileserver-nightly.yml
|
|
job: fileserver-multi-instance-lease
|
|
execution: job
|
|
#
|
|
# jpa-nightly.yml — the middle of the PostgreSQL matrix and the suites too slow or too
|
|
# Docker-heavy for a pull request.
|
|
#
|
|
# Scheduled JPA matrix, failure injection, query-plan/security and pool pressure.
|
|
- id: jpa-full-matrix
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: jpa-full-matrix
|
|
workflow: jpa-nightly.yml
|
|
job: jpa-full-matrix
|
|
execution: job
|
|
- id: jpa-failure-injection
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: jpa-failure-injection
|
|
workflow: jpa-nightly.yml
|
|
job: jpa-failure-injection
|
|
execution: job
|
|
- id: jpa-query-plan-and-security
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: jpa-query-plan-and-security
|
|
workflow: jpa-nightly.yml
|
|
job: jpa-query-plan-and-security
|
|
execution: job
|
|
- id: jpa-pool-pressure
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: jpa-pool-pressure
|
|
workflow: jpa-nightly.yml
|
|
job: jpa-pool-pressure
|
|
execution: job
|
|
#
|
|
# jpa-next-*.yml — weekly early-warning lanes against unreleased upstream versions. They exist to
|
|
# find out before the upgrade, so they block nothing.
|
|
#
|
|
# Weekly early-warning lanes against unreleased upstream versions. They exist to find out
|
|
# before the upgrade, so they block nothing.
|
|
- id: hibernate8-compatibility
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: hibernate8-compatibility
|
|
workflow: jpa-next-hibernate8.yml
|
|
job: hibernate8-compatibility
|
|
execution: job
|
|
- id: jpa4-compatibility
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: jpa4-compatibility
|
|
workflow: jpa-next-jpa4.yml
|
|
job: jpa4-compatibility
|
|
execution: job
|
|
- id: postgresql19-compatibility
|
|
release_blocking: false
|
|
mechanism: workflow-job
|
|
ref: postgresql19-compatibility
|
|
workflow: jpa-next-postgresql19.yml
|
|
job: postgresql19-compatibility
|
|
execution: job
|
|
#
|
|
# jpa-r2-evidence.yml — dispatch-only production-profile manifest run.
|
|
- id: jpa-r2-evidence
|
|
release_blocking: conditional
|
|
mechanism: workflow-job
|
|
ref: jpa-r2-evidence
|
|
workflow: jpa-r2-evidence.yml
|
|
job: jpa-r2-evidence
|
|
execution: job
|
|
|
|
# =================================================================================
|
|
# STAGE 3 — release tag. These stop a release.
|
|
# =================================================================================
|
|
#
|
|
# release.yml — one workflow, one deployable unit. Evidence jobs first, then app-image-release,
|
|
# which `needs:` all of them: while the image build lived in its own workflow it could publish
|
|
# while a sibling suite was still running or already red.
|
|
- id: httpclient-stable-contract
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: httpClientStableContractTest
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
- id: httpclient-security-suite
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: httpClientSecurityTest
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
- id: httpclient-fault-injection
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: httpClientFailureInjectionTest
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
- id: httpclient-performance-certification
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: httpClientPerformanceTest
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
- id: httpclient-spring62-api-surface
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: spring62ApiSurfaceScan
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
#
|
|
# The 6.2 API-surface scan above proves the common packages compile against the older surface. It
|
|
# does not prove they run on it, and the two were being conflated: a lane called
|
|
# "spring62CompatibilityTest" reads as a runtime compatibility proof. The Gradle task is renamed to
|
|
# say what it does, and the runtime claim is registered here as its own delegated-pending control
|
|
# so the gap is a tracked absence rather than an unstated one. Executing it needs a Spring
|
|
# Framework 6.2 distribution resolved into a separate test runtime, which this repository's
|
|
# Boot 4.0 baseline does not carry.
|
|
- id: httpclient-spring62-runtime
|
|
release_blocking: conditional
|
|
mechanism: delegated-pending
|
|
ref: spring62-runtime-lane
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: job
|
|
- id: httpclient-spring70-compatibility
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: spring70CompatibilityTest
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
- id: httpclient-documentation-drift
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: httpclient-documentation
|
|
workflow: release.yml
|
|
job: httpclient-documentation
|
|
execution: job
|
|
- id: httpclient-event-loop-blocking
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: httpClientBlockHoundTest
|
|
workflow: release.yml
|
|
job: httpclient-release-gate
|
|
execution: explicit
|
|
#
|
|
# Tag-triggered (`v*`). The Stable web release gate.
|
|
- id: web-stable-release-gate
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: web-stable-release-gate
|
|
workflow: release.yml
|
|
job: web-stable-release-gate
|
|
execution: job
|
|
#
|
|
# Tag-triggered (`v*`). The Stable websocket release gate.
|
|
- id: websocket-stable-release-gate
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: websocket-stable-release-gate
|
|
workflow: release.yml
|
|
job: websocket-stable-release-gate
|
|
execution: job
|
|
#
|
|
# Tag-triggered (`v*`). The three gRPC certification lanes, one row each because each runs as its
|
|
# own single-line command and `execution: explicit` is only verifiable that way.
|
|
#
|
|
# These were registered lanes that no workflow named. Their tests are not new coverage — the
|
|
# `grpc-inprocess`, `grpc-netty` and `grpc-fault` tags run inside `:grpc:grpc-testkit:test`, which
|
|
# is inside `check` — so what the lanes add is the fail-on-nothing-discovered guard that a tag
|
|
# filter inside `test` cannot give you. Same argument as web-advanced and websocket-advanced above,
|
|
# and the same placement.
|
|
- id: grpc-inprocess-contract-lane
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: grpcInProcessContractTest
|
|
workflow: release.yml
|
|
job: grpc-stable-release-gate
|
|
execution: explicit
|
|
- id: grpc-netty-transport-lane
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: grpcNettyContractTest
|
|
workflow: release.yml
|
|
job: grpc-stable-release-gate
|
|
execution: explicit
|
|
- id: grpc-fault-lane
|
|
release_blocking: true
|
|
mechanism: gradle-custom-task
|
|
ref: grpcFaultTest
|
|
workflow: release.yml
|
|
job: grpc-stable-release-gate
|
|
execution: explicit
|
|
#
|
|
# Tag-triggered (`v*`). The only job in this repository that produces a deployable artifact.
|
|
#
|
|
# One row, not three, because one job is one control: the job builds the app-bootstrap image,
|
|
# generates its CycloneDX SBOM, refuses to publish on a CRITICAL or HIGH finding, and only then
|
|
# pushes the semver and sha- tags and records the digest. The scan is a step inside that control
|
|
# rather than a control of its own, which is the same shape filesystem-vulnerability-scan uses for
|
|
# the trivy-fs job. `release_blocking: true` holds because the workflow runs only for a release
|
|
# tag, so the job failing fails that release run.
|
|
- id: container-image-release
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: app-image-release
|
|
workflow: release.yml
|
|
job: app-image-release
|
|
execution: job
|
|
#
|
|
# The join this repository cannot express, stated rather than implied.
|
|
#
|
|
# Most of it is closed now. app-image-release lives in release.yml and `needs:` the four evidence
|
|
# jobs in that file, so the image cannot be built, scanned or pushed past a failed web, websocket,
|
|
# httpclient or architecture gate. `needs:` still reaches only inside one workflow file, and two
|
|
# evidence workflows are still outside it: jpa-release.yml and fileserver-release.yml both answer
|
|
# the same `v*` tag and neither can be waited on from here.
|
|
#
|
|
# Those two are not in release.yml for a mechanical reason rather than a design one —
|
|
# JpaReleaseRenderingTest reads `.github/workflows/jpa-release.yml` by that exact path, and
|
|
# FileserverDocumentationCoverageTest requires the job ids docs/fileserver/support-matrix.md names
|
|
# to be defined in a `.github/workflows/fileserver-*.yml`. Folding them in means changing a test
|
|
# and a document in src/ and docs/ in the same commit, which is a decision with owners rather than
|
|
# a wiring oversight.
|
|
#
|
|
# Until then the remaining control is a human one: the GitOps repository promotes a digest whose
|
|
# tag's jpa-release and fileserver-release runs somebody has looked at, not a digest that merely
|
|
# exists. Registered here so that sentence lives somewhere a lint can point at, the way
|
|
# fileserver-pvc-cluster-certification does for the storage claim.
|
|
- id: container-release-evidence-join
|
|
release_blocking: conditional
|
|
mechanism: delegated-pending
|
|
ref: container-release-evidence-join
|
|
workflow: release.yml
|
|
job: app-image-release
|
|
execution: job
|
|
#
|
|
# verifyCleanArchitectureDependencies, verifyPublicPathSnapshot, verifyEnvKeys and the
|
|
# bootstrap architecture suite, once per release. The four release workflows this replaced ran
|
|
# the dependency gate six times and the architecture suite four times for one tag, on separate
|
|
# runners, against one commit.
|
|
- id: release-architecture-and-surface
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: architecture-and-surface
|
|
workflow: release.yml
|
|
job: architecture-and-surface
|
|
execution: job
|
|
#
|
|
# jpa-release.yml — tag-triggered (`v*`). jpa-release-promotion needs jpa-release-gate, so the
|
|
# promotion cannot run past a failed gate. Its own file because JpaReleaseRenderingTest reads that
|
|
# exact path and holds its matrix to src/config/jpa/release-registry.json.
|
|
#
|
|
# Tag-triggered (`v*`). jpa-release-promotion needs jpa-release-gate, so the promotion cannot
|
|
# run past a failed gate.
|
|
- id: jpa-release-gate
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: jpa-release-gate
|
|
workflow: jpa-release.yml
|
|
job: jpa-release-gate
|
|
execution: job
|
|
- id: jpa-release-promotion
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: jpa-release-promotion
|
|
workflow: jpa-release.yml
|
|
job: jpa-release-promotion
|
|
execution: job
|
|
- id: jpa-architecture-and-docs
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: jpa-architecture-and-docs
|
|
workflow: jpa-release.yml
|
|
job: jpa-architecture-and-docs
|
|
execution: job
|
|
#
|
|
# fileserver-release.yml — tag-triggered (`v*`). Its own file for the same reason fileserver-pr.yml
|
|
# is.
|
|
#
|
|
# Tag-triggered: `v*` runs this workflow and a failing job fails that
|
|
# release. fileserver-pvc-certification checks the manifest only — the cluster half is the
|
|
# delegated-pending row below it.
|
|
- id: fileserver-full-verification
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: fileserver-full-verification
|
|
workflow: fileserver-release.yml
|
|
job: fileserver-full-verification
|
|
execution: job
|
|
- id: fileserver-documentation-gate
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: fileserver-documentation-gate
|
|
workflow: fileserver-release.yml
|
|
job: fileserver-documentation-gate
|
|
execution: job
|
|
- id: fileserver-pvc-certification
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: fileserver-pvc-certification
|
|
workflow: fileserver-release.yml
|
|
job: fileserver-pvc-certification
|
|
execution: job
|
|
#
|
|
# The other half of the PVC claim, and the half no runner can produce. An operator
|
|
# applies infra/fileserver/kubernetes/pvc-certification-job.yaml to a real cluster and
|
|
# records the result in docs/fileserver/storage-certification.md. The workflow step
|
|
# that pretended to do this in CI reported success whenever the cluster secret was
|
|
# absent, which is every checkout of this template; it is gone, and the claim is
|
|
# tracked here instead of being green for nothing.
|
|
- id: fileserver-pvc-cluster-certification
|
|
release_blocking: conditional
|
|
mechanism: delegated-pending
|
|
ref: fileserver-pvc-cluster-lane
|
|
workflow: fileserver-release.yml
|
|
job: fileserver-pvc-certification
|
|
execution: job
|
|
- id: fileserver-sensitive-telemetry-scan
|
|
release_blocking: true
|
|
mechanism: workflow-job
|
|
ref: fileserver-sensitive-telemetry-scan
|
|
workflow: fileserver-release.yml
|
|
job: fileserver-sensitive-telemetry-scan
|
|
execution: job
|