Skip to content

feat(setup): capture verified security image identity - #351

Merged
mrizzi merged 7 commits into
RHEcosystemAppEng:mainfrom
ruromero:TC-7136
Oct 26, 2026
Merged

mrizzi merged 7 commits into
RHEcosystemAppEng:mainfrom
ruromero:TC-7136

Conversation

@ruromero

@ruromero ruromero commented Oct 23, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Use docs/templates/security-matrix.template.md as the sole scaffold and turn its sibling .md file into a worked example.
  • Add per-version/component container image identity and revision-label verification to Setup, with a review-before-write gate.
  • Preserve dynamic source repository columns and ecosystem mappings; document the contract and add valid/mismatched image eval coverage.
  • Clarify the Setup eval's CPE semantics: platform rows retain valid CPEs but may share a product/version CPE.
  • Extend triage-security on-demand matrix population with per-component image identity, revision-label checks, mapping preservation, and a no-write gate for unresolved evidence.
  • Make the canonical Supportability Matrix header product-neutral and cover a non-RHTPA product prefix in Setup evals.
  • Recheck snapshots for every local matrix write (fallback saves, format repairs, scaffolds, and population); trigger completion when required component rows are missing, even if the image table exists.

Implements TC-7136

Evidence

  • Setup evals: 10/10 cases, 76/76 assertions passed.
  • Triage-security evals: 34 cases; 175/181 assertions passed after retrying the initially failing cases. Six assertions remain in evals 1, 2, 8, 14, and 17; the targeted write-safety/component-coverage cases pass.
  • Python script tests: 729 passed, 3 skipped.
  • uvx skillsaw: 0 errors (9 warnings).
  • claude plugin validate plugins/sdlc-workflow: passed (existing missing-icon warning).

Merge Danger

Door: Two-way

Blast Radius: Workflow

The change affects Setup and triage-security instructions, matrix templates, constraints, and evaluations; it does not modify customer project matrices.

Summary by Sourcery

Require verified container image identity and review-gated, concurrency-safe security matrix updates across Setup and triage-security.

New Features:

  • Add verified container image identity tracking to Setup and on-demand triage-security matrix population, including release tags, resolved commits, image references, digests, CPEs, and revision-label checks.

Bug Fixes:

  • Prevent scaffolding from using the worked-example matrix and prevent stale, incomplete, or unresolved proposals from overwriting security matrices.

Enhancements:

  • Make security matrix generation preserve dynamic source repository columns, pinning methods, ecosystem mappings, existing rows, and product-neutral headers while requiring review before writes.
  • Clarify CPE handling for platform-specific rows and add create-if-absent, fallback/repair write guards, and partial-component coverage checks.

Documentation:

  • Document the security matrix container-image evidence contract and distinguish the canonical scaffold from the worked example.

Tests:

  • Extend Setup and triage-security evaluations for valid and mismatched image evidence, non-default product prefixes, partial component coverage, write races, and safe repairs.

Chores:

  • Update constraint references for the new Setup and triage-security matrix integrity requirements.

@sourcery-ai

sourcery-ai Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Reviewer's Guide

Setup now scaffolds security matrices only from the canonical template and optionally populates them with per-version/component container image identity. It resolves release tags to full commits, verifies published OCI revision labels before accepting image rows, preserves dynamic repository and ecosystem mappings, and requires review before writing; documentation and Setup evals define and exercise the updated contract.

Sequence diagram for verified security matrix population

sequenceDiagram
    participant Setup
    participant ReleaseRepo
    participant Registry
    participant User
    participant Matrix

    Setup->>ReleaseRepo: Read release tags/history
    ReleaseRepo-->>Setup: Versions, builds, source commits, pinning methods
    Setup->>Registry: Resolve image reference and inspect revision label
    Registry-->>Setup: Image digest, CPE, org.opencontainers.image.revision
    Setup->>Setup: Compare revision label with resolved release commit SHA
    alt Evidence missing or mismatched
        Setup-->>User: Ask for corrected evidence
        Setup-->>Matrix: Leave matrix unchanged
    else Evidence verified
        Setup-->>User: Present complete proposed matrix and revision checks
        User->>Setup: Confirm review
        Setup->>Matrix: Write matrix and Last-Updated timestamp
    end
Loading

Entity relationship diagram for container image identity

erDiagram
    PRODUCT_VERSION ||--o{ CONTAINER_IMAGE : has
    CONTAINER_IMAGE {
        string product_version
        string component
        string release_tag
        string resolved_release_commit_sha
        string image_reference
        string image_digest
        string cpe
        string revision_label
    }
    RELEASE_TAG ||--|| CONTAINER_IMAGE : resolves_to
    RELEASE_TAG {
        string tag
        string commit_sha
    }
    CONTAINER_IMAGE }o--|| SOURCE_REPOSITORY : supports
    SOURCE_REPOSITORY {
        string repository
        string source_pinning_method
    }
Loading

Flow diagram for canonical security matrix scaffolding

flowchart TD
    A[Configured security-matrix.md path] --> B{Matrix exists?}
    B -->|Yes| C[Report existing matrix and skip]
    B -->|No| D[Read security-matrix.template.md]
    D --> E[Expand source repository columns and pinning entries]
    E --> F[Retain ecosystem mappings]
    F --> G[Offer scaffold for confirmation]
    G --> H[Write confirmed scaffold]
Loading

File-Level Changes

Change Details Files
Strengthen the security-matrix contract and distinguish the canonical scaffold from the worked example.
  • Document template-only scaffolding, dynamic source repository columns, matching pinning entries, and ecosystem preservation.
  • Define the Container Images schema and revision-label verification requirements.
  • Convert the sibling matrix file into a fictional completed reference example.
docs/constraints.md
docs/project-config-contract.md
docs/templates/security-matrix.template.md
docs/templates/security-matrix.md
Update Setup to collect, verify, review, and safely write image identity evidence.
  • Scaffold missing matrices exclusively from the canonical template with configured repository mappings.
  • Populate per-version/component image rows with release tags, resolved SHAs, references, digests, and CPEs.
  • Require OCI revision labels to match resolved release SHAs and block writes for missing or mismatched evidence.
  • Present the complete proposed matrix for confirmation before writing and preserve existing mappings.
plugins/sdlc-workflow/skills/setup/SKILL.md
Add evaluation fixtures covering valid and mismatched image identity evidence.
  • Provide synthetic supportability, source-pinning, ecosystem, release-resolution, and published-image data.
  • Expand Setup eval coverage for image identity verification and review-before-write behavior.
evals/setup/evals.json
evals/setup/files/security-matrix-image-identity.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 4 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="plugins/sdlc-workflow/skills/setup/SKILL.md" line_range="560" />
<code_context>
+| 1.94 | `setup` MUST preserve one Supportability Matrix source-commit column and one Source Pinning Method entry per configured Source Repositories entry, and preserve Ecosystem Mappings; it MUST present the complete proposed matrix for review before writing and leave it unchanged while image evidence is missing or mismatched. | `setup/SKILL.md` — Steps 10.5–10.6 |

 ### Prior Art — Cross-phase integrity (§1.33–1.35)

</code_context>
<issue_to_address>
**Concurrent matrix edits get overwritten**

When the target matrix changes after Setup checks or reads it but before Setup writes after confirmation, setup writes a scaffold over a matrix created after its existence check, or writes its proposed matrix over changes made after its earlier read. A concurrent triage-security population or another Setup run therefore loses its newer matrix contents.

Re-read and compare the target immediately before writing, use create-if-absent for scaffolds, and merge or abort if the target changed.

Also at `plugins/sdlc-workflow/skills/setup/SKILL.md:597-600`.
</issue_to_address>

### Comment 2
<location path="plugins/sdlc-workflow/skills/setup/SKILL.md" line_range="580-581" />
<code_context>
+> "Would you like me to populate the Supportability Matrix and Container Images table
+> from release history and published-image evidence?"

 If the user declines, skip to Step 11. The matrix can be populated later on demand
 by `/triage-security` during CVE investigation.

 If the user accepts, for each Version Stream:
</code_context>
<issue_to_address>
**Image identity evidence stays incomplete**

When triage-security is relied on to populate an empty or incomplete matrix after Setup population is declined, `triage-security` writes legacy supportability data without Container Images rows or revision-label checks, so the matrix appears populated while lacking verified image identity evidence.

Update on-demand population to add Container Images rows and verify revision labels against release SHAs before writing the matrix.

Also at `plugins/sdlc-workflow/skills/setup/SKILL.md:590-592`.
</issue_to_address>

### Comment 3
<location path="plugins/sdlc-workflow/skills/setup/SKILL.md" line_range="566" />
<code_context>
-  to write it to the configured path in the project directory. The user must confirm each file.
-- **If it DOES exist**: Report "security-matrix.md already exists at <path> — skipping."
+- **If it exists**: Report "security-matrix.md already exists at <path> — skipping."
+- **If missing**: Scaffold only from the plugin-root
+  `docs/templates/security-matrix.template.md`; `docs/templates/security-matrix.md` is a
+  worked example. Expand `{source-repo-name}` / `{source-ref}` and matching separator
</code_context>
<issue_to_address>
**Other products get an RHTPA header**

When the configured product is not RHTPA, setup now scaffolds from the canonical template, whose Supportability Matrix header is hard-coded as `RHTPA Version`; projects for other products therefore receive a matrix that labels their versions as RHTPA versions.

Use a product-neutral `Version` header or make the product name a scaffold placeholder.
</issue_to_address>

### Comment 4
<location path="evals/setup/files/security-matrix-image-identity.md" line_range="35-36" />
<code_context>
+
+| Product Version | Component | Image Reference | Immutable Image Digest | CPE | `org.opencontainers.image.revision` |
+|---|---|---|---|---|---|
+| 2.1.0 | api-rhel9 | `registry.example.test/trustify/api:2.1.0-rhel9` | `sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` | `cpe:2.3:a:example:trustify_api:2.1.0:*:*:*:*:*:*:*` | `0123456789abcdef0123456789abcdef01234567` |
+| 2.1.0 | api-rhel10 | `registry.example.test/trustify/api:2.1.0-rhel10` | `sha256:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb` | `cpe:2.3:a:example:trustify_api:2.1.0:*:*:*:*:*:*:*` | `0123456789abcdef0123456789abcdef01234567` |
+| 2.1.1 | api-rhel10 | `registry.example.test/trustify/api:2.1.1-rhel10` | `sha256:cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc` | `cpe:2.3:a:example:trustify_api:2.1.1:*:*:*:*:*:*:*` | `fedcba9876543210fedcba9876543210fedcba98` |
</code_context>
<issue_to_address>
**Duplicate CPEs contradict eval**

When the grader interprets “distinct … CPE values” as requiring different CPEs for the two platform rows, when the grader requires distinct CPEs for the two platform rows, Setup eval 7’s assertion at `evals/setup/evals.json:116` fails even when Setup correctly preserves its input: the `api-rhel9` and `api-rhel10` fixture rows have the same CPE. Changing the output to satisfy the assertion would instead make it inaccurate.

Give the platform rows distinct CPEs in the fixture, or clarify that only image references and digests must be distinct.
</issue_to_address>

Sourcery assessment

Needs a human reviewer. 4 findings to address first, and if Setup records an incorrect release commit, image digest, or source pin in the security matrix, later CVE triage could associate evidence with the wrong product image and produce an inaccurate impact assessment. The matrix is a persisted but editable record, so correcting it can repair the mapping; reverting the skill change alone would not undo rows already written.

Blocking findings: plugins/sdlc-workflow/skills/setup/SKILL.md:560, plugins/sdlc-workflow/skills/setup/SKILL.md:581, plugins/sdlc-workflow/skills/setup/SKILL.md:566, evals/setup/files/security-matrix-image-identity.md:36


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

Comment thread plugins/sdlc-workflow/skills/setup/SKILL.md
Comment thread plugins/sdlc-workflow/skills/setup/SKILL.md
Comment thread plugins/sdlc-workflow/skills/setup/SKILL.md
Comment thread evals/setup/files/security-matrix-image-identity.md
@ruromero

Copy link
Copy Markdown
Collaborator Author

[sdlc-workflow/verify-pr] Re: @sourcery-ai[bot] review — Classified as code change request for each of the four distinct requests: protect concurrent matrix writes (TC-7145); add image identity checks to triage-security on-demand population (TC-7143); make the shared-template version header product-neutral (TC-7144); clarify CPE uniqueness expectations in the eval (TC-7142). The review-body items duplicate the corresponding inline findings.

@ruromero

Copy link
Copy Markdown
Collaborator Author

Verification Report for TC-7136 (commit 2dde9e4)

Check Result Details
Review Feedback WARN Four distinct code-change requests were classified; linked fix Tasks created: TC-7142–TC-7145. Inline replies and one review-body comment posted.
Root-Cause Investigation DONE Three root-cause Tasks created: TC-7146 (plan-feature), TC-7147 (implement-task), TC-7148 (convention). Concurrent-write phase attribution was skipped because no originating Feature link was available.
Scope Containment PASS All 7 changed files match the task's file lists; no out-of-scope files.
Diff Size PASS 179 additions, 114 deletions (293 changed lines) across 7 expected files.
Commit Traceability PASS Both PR commits reference TC-7136.
Sensitive Patterns PASS No sensitive patterns found in 179 added lines across 7 files.
CI Status WARN Sourcery review passed; wait-for-checks, remove-ok-to-test, and verify-pr were skipped; none failed.
Acceptance Criteria PASS 5/5 direct criteria met. Setup eval 7 covers valid and mismatched mappings and passed 10/10.
Test Quality PASS Repetitive-test and test-documentation checks passed; Eval Quality is N/A (no CI eval-result review). The local suite failure is recorded under Verification Commands.
Test Change Classification MIXED Eval 7 adds coverage; eval 3 no longer requires the user prompt and instead checks that the simulated choice is recorded.
Verification Commands FAIL uvx skillsaw: 0 errors, 7 warnings. claude plugin validate plugins/sdlc-workflow: passed with an icon warning. Required Setup eval suite: 56/57 (98%); eval 4 failed because outputs/changes-log.md was missing. The exact base commit is unavailable locally, so regression status is unknown.

Overall: FAIL

The direct acceptance criteria are met, but the required Setup eval suite has one failing assertion. The review fixes are tracked in TC-7142–TC-7145. Jira also has a Depend link from TC-7136 to TC-7137 (status New), although the task description says Dependencies: None; this should be reconciled.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.10.

@github-actions

github-actions Bot commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

Eval Results

Source head: 4b0faf5
Merge: b48b31e

Eval Results: setup

Eval Passed Failed Pass Rate
eval-1 9/9 0 100%
eval-10 5/5 0 100%
eval-2 8/8 0 100%
eval-3 8/8 0 100%
eval-4 7/7 0 100%
eval-5 8/8 0 100%
eval-6 7/7 0 100%
eval-7 10/10 0 100%
eval-8 9/9 0 100%
eval-9 5/5 0 100%

Pass rate: 100% · Tokens: 76,967 · Duration: 36s

Baseline (f32bd713): 100% · 17,795 tokens · 44s


Generated by sdlc-workflow/run-evals v0.13.10

Eval Results: triage-security

Eval Passed Failed Pass Rate
eval-1 13/13 0 100%
eval-10 5/5 0 100%
eval-11 5/5 0 100%
eval-12 5/5 0 100%
eval-13 5/5 0 100%
eval-14 5/5 0 100%
eval-15 5/5 0 100%
eval-16 7/7 0 100%
eval-17 5/5 0 100%
eval-18 5/5 0 100%
eval-19 5/5 0 100%
eval-2 5/5 0 100%
eval-20 4/4 0 100%
eval-21 4/4 0 100%
eval-22 4/4 0 100%
eval-23 4/4 0 100%
eval-24 4/4 0 100%
eval-25 4/4 0 100%
eval-26 5/5 0 100%
eval-27 5/5 0 100%
eval-28 5/5 0 100%
eval-29 5/5 0 100%
eval-3 5/5 0 100%
eval-30 4/4 0 100%
eval-31 4/4 0 100%
eval-32 4/4 0 100%
eval-33 8/8 0 100%
eval-34 7/7 0 100%
eval-4 5/5 0 100%
eval-5 6/6 0 100%
eval-6 6/6 0 100%
eval-7 5/5 0 100%
eval-8 8/8 0 100%
eval-9 5/5 0 100%

Pass rate: 100% · Tokens: 126,654 · Duration: 63s

Baseline (f32bd713): 99% · 59,221 tokens · 139s


Generated by sdlc-workflow/run-evals v0.13.10

Implements TC-7136

Assisted-by: Claude Code
Implements TC-7136

Assisted-by: Claude Code
Clarify that image references and digests distinguish platform images while a valid product-version CPE may be shared.

Implements TC-7142

Assisted-by: Claude Code
Add component-keyed image rows to interactive on-demand matrix updates and block writes while revision evidence is unresolved. Add valid/mismatch eval coverage.

Implements TC-7143

Assisted-by: Claude Code
Update the canonical template and add eval coverage for non-RHTPA projects.

Implements TC-7144

Assisted-by: Claude Code
Recheck matrix snapshots before writing, create scaffolds only if absent, and require renewed review or abort when targets change.

Implements TC-7145

Assisted-by: Claude Code
Apply final snapshot checks to fallback saves and format repairs, and trigger completion for missing component rows.

Implements TC-7145

Assisted-by: Claude Code

@github-actions github-actions Bot left a comment •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Native Fullsend Eval Results

Head: 4b0faf5
Merge: b48b31e
Trusted workflow: e1c811c
Reviewed eval source: e1c811c

Native job: success; complete: true.
Execution evidence: valid; quality score (advisory): 27/28 passed.

Case Execution evidence Quality score (advisory)
033-absent valid 4/4
034-empty valid 5/5
035-malformed valid 4/5
036-valid valid 7/7
037-release valid 7/7

@mrizzi mrizzi added the ok-to-test Enable verify-pr execution on PRs from forks label Oct 26, 2026
@fullsend-ai-review

fullsend-ai-review Bot commented Oct 26, 2026 •

Copy link
Copy Markdown

🤖 Finished Verify Pr · ✅ Success · Started 3:49 PM UTC · Completed 4:00 PM UTC

Commit: 4b0faf5 · View workflow run →

Runtime: claude · Model: claude-opus-4-8 · Effort: high · Cost: $6.17

@fullsend-ai-review

Copy link
Copy Markdown

Verification Report for TC-7136 (commit 4b0faf5)

Check Result Details
Review Feedback WARN Four code-change requests classified in a prior run; linked fix Tasks TC-7142-TC-7145 already exist. Idempotent re-run - no new sub-tasks or replies created.
Root-Cause Investigation N/A No new sub-tasks were created this run, so nothing new to investigate. Prior-run root-cause Tasks already exist: TC-7146 (plan-feature), TC-7147 (implement-task), TC-7148 (convention).
Scope Containment WARN All 7 task-spec files present (none missing); 4 out-of-scope files added (evals/triage-security/evals.json, triage-security/version-impact-analysis.md, a non-RHTPA Setup fixture, test_fullsend_gate_eval.py) by the TC-7142-TC-7145 review-fix commits on this branch.
Diff Size PASS 441 additions, 134 deletions (575 lines) across 11 files - proportionate for a documentation/eval-heavy task plus tracked review fixes.
Commit Traceability WARN Commits 1-2 reference TC-7136; commits 3-7 reference sub-tasks TC-7142-TC-7145 (review fixes targeting this same PR) rather than TC-7136.
Sensitive Patterns PASS No secrets in added lines; image digests, commit SHAs, CPEs, and synthetic-fixture values are not credentials.
CI Status PASS All 8 check-runs pass or skip (Skill Lint, Plugin Validation, Script Unit Tests 3.11-3.14, Trigger Eval Dispatch, Sourcery) and the Eval PR Run commit status is success; none failed or pending.
Acceptance Criteria PASS 5/5 criteria met, verified against the PR-head tree (single canonical template, re-labeled worked example, 7 image-identity fields, Step 10.6 populate-and-confirm, valid + mismatched eval mappings).
Test Quality PASS Repetitive-test detection PASS and test-documentation PASS. Eval Quality: N/A (no CI eval-result review carrying the '## Eval Results' marker + run-evals footer was posted as a review).
Test Change Classification ADDITIVE One modified test file (test_fullsend_gate_eval.py): +4 assertions and tightened count/slice checks extend coverage with no removals, relaxations, or skips.
Verification Commands PASS 'claude plugin validate plugins/sdlc-workflow' passes locally on the PR-head tree; 'uvx skillsaw' (no egress in sandbox) is validated via its authoritative CI equivalent Skill Lint, which succeeded at head 4b0faf5.

Overall: WARN

The direct acceptance criteria (5/5) are met and CI is green at head 4b0faf5: all check-runs pass or skip, the Eval PR Run status is success, and the current-head eval suites report 100% (setup and triage-security). Three checks are WARN, none FAIL, so the overall result is WARN:

  • Review Feedback - four sourcery-ai code-change requests are tracked in fix Tasks TC-7142-TC-7145.
  • Scope Containment / Commit Traceability - the PR adds 4 out-of-scope files and 5 of 7 commits reference TC-7142-TC-7145 rather than TC-7136, because those review fixes were committed onto this same branch.

This was an idempotent re-run at a new commit: all sub-tasks (TC-7142-TC-7145), classification replies, and root-cause Tasks (TC-7146-TC-7148) already existed, so no new Jira or PR writes were made - only this per-commit report was refreshed.

Note (unchanged from the prior verification): Jira has a Depend link from TC-7136 to TC-7137 even though the task description states Dependencies: None; this should be reconciled by a human. Per project rules, the WARN rows do not block merge - a human reviewer decides.


This comment was AI-generated by sdlc-workflow/verify-pr v0.13.10.

@mrizzi
mrizzi merged commit 6922b59 into RHEcosystemAppEng:main Oct 26, 2026
23 checks passed
@ruromero
ruromero deleted the TC-7136 branch October 26, 2026 17:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test Enable verify-pr execution on PRs from forks

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants