Skip to content

feat(acq-kits): add opencode agent-harness kit (SHA-pinned release binary) - #455

Merged
mogul merged 7 commits into
mainfrom
feat/opencode-agent-kit
Oct 2, 2026
Merged

mogul merged 7 commits into
mainfrom
feat/opencode-agent-kit

Conversation

@wz-gsa

@wz-gsa wz-gsa commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Summary

First harness-agent kit in the family: installs a pinned, SHA-256-verified OpenCode CLI release binary into the sandbox at create time, replacing acq's own unpinned MSB fallback (npm install -g opencode-ai, resolves to whatever npm currently calls "latest"). Declares the new top-level agent: block (name/entrypoint, schema added in #454, this PR's base) so acq's built-in agent-kit readiness gate (acq_validate_agent_builtin_kit_dir, in the sibling quickstart repo) can confirm this kit genuinely provides the opencode agent token before enabling it.

Part of the ADR-0030 devenv/agent-kits line of work (umbrella PR GSA-TTS/agentic-coding-quickstart#474, tracking issue #473, kit-specific issue #485).

Depends on #454 (adds the agent: schema block) — this PR targets that branch, not main, until #454 merges.

Install-method decision

Reached via a 3-role consensus_vote before authoring (SHA-pinned release binary vs. npm vs. nixpkgs), after live-verifying:

  • nixpkgs ruled out: at the devenv image's pinned revision, nixpkgs' own opencode package resolves to v0.3.112 from the pre-rename upstream repo (sst/opencode) — ~70 releases stale. Installing via that pinned nixpkgs would downgrade users rather than deliver current OpenCode.
  • npm ruled out: opencode-ai's own postinstall step has a documented, intermittent failure fetching the real binary (sibling quickstart repo's KNOWN_FAILURE_MODES.md).
  • SHA-pinned release binary chosen: mirrors the (unmerged) goose-server kit's pattern. No npm metadata, no postinstall step to fail — a single prebuilt tarball, fetched, SHA-256-verified, extracted. Both pins (v1.18.34, x64 + arm64) independently derived from the real GitHub release assets, not copied from any third party.

Integrity posture

Deliberately diverges from every sibling kit in this family: a SHA-256 mismatch refuses to install (fails CLOSED), with no fallback to degrade to — see docs/decisions/fail-closed-on-integrity.md. Every other failure path (no pin, unsupported arch, network failure, extraction failure) fails soft, matching the family's convention.

Review process

Two independent adversarial subagent reviews ran against the authored kit before this PR — a security-focused review and a QA/accuracy/vestigial-content review. Every finding both raised was fixed, not just logged:

Security fixes:

  • HIGH: tar extraction trusted a [ -f ] check that follows symlinks — a hash-matching-but-source-compromised release whose opencode member is a symlink would have its target's content silently copied, root-owned and world-readable, into /usr/local/bin/opencode. Added an explicit [ -L ] rejection before trusting the extracted member.
  • MEDIUM: the idempotency fast-path resolved opencode via a PATH lookup and trusted its self-reported --version with no re-verification — a persisted prior-boot compromise would never be re-checked. Fixed to check the kit's own fixed destination path directly, never PATH, with the same symlink rejection.
  • Confirmed non-issue after live testing (not just assumed): the version-pin glob looks exploitable in isolation but is closed by an existing second charset-negation check; no tainted variable reaches a shell-reparsing sink regardless.

QA/accuracy fixes:

  • HIGH (real functional bug): the kit's own scripts/verify called validate-kits.py without --root, unlike every sibling kit's verify script — reproduced live that this breaks the kit's own offline gate when run from outside the repo root. Fixed.
  • HIGH (accuracy): README mischaracterized objects.githubusercontent.com as a git-LFS-only host; sibling kits (openchamber, prime-agent) actually use that same host for the same purpose (release downloads). Rewrote to say so honestly, and reframed the egress-host choice as a documented latent fragility rather than an asserted settled fact.
  • MEDIUM (accuracy): README overclaimed the opencode-ai npm package itself lacks metadata/a postinstall step; it has both — the real point is this kit's own install path never touches npm. Rewrote accordingly.
  • MEDIUM (doc/code mismatch): spec.yaml and script comments described in-script literal fallback values that don't exist in the code. Rewrote to state accurately that spec.yaml's install command is the single source of truth for the pin.

Verification (post-fix, not just pre-fix)

  • validate-kits.py --strict passes 9/9 kits
  • The kit's own scripts/verify passes 6/6 checks, including a live integrity-negative test (a deliberately wrong hash correctly refuses to install anything)
  • shellcheck clean
  • markdownlint-cli2 clean
  • Full repo pytest suite: 401/401 (no regression)

A final 3-role consensus_vote sanity pass on the fixed kit was dispatched before opening this PR but did not resolve within a reasonable wait; opening on the strength of the two completed, finding-fixed adversarial reviews rather than blocking further. Will report the vote's result separately if it surfaces anything new once it resolves.

AI-assisted change (OpenCode).

Co-authored-by: OpenCode Agent agent@gsa.gov

OpenCode Agent added 2 commits October 1, 2026 09:26
Quickstart's built-in agent-kit readiness gate (acq_validate_agent_builtin_kit_dir
/ kit_spec_agent_field in acq.backends/common.sh, on the in-progress
refactor/acq-devenv-base-image branch) parses a top-level `agent:` block with
`name:`/`entrypoint:` children from a kit's spec.yaml, to confirm a fetched kit
genuinely matches the agent token acq is about to enable it for. The hybrid/v1
schema had no such field and additionalProperties: false, so any kit declaring
agent: failed validate-kits.py outright. Confirmed live before this change:
jsonschema.validate() on a spec with an agent: block raised "Additional
properties are not allowed ('agent' was unexpected)".

This blocks GSA-TTS/agentic-coding-quickstart#485 (the OpenCode agent-kit
migration, part of the ADR-0030 devenv/agent-kits epic tracked on
GSA-TTS/agentic-coding-quickstart#473) before any kit content can even pass
CI, independent of the kit's own correctness. Landing it as its own
small, independently-reviewable change rather than bundled into the kit PR.

Added `agent` as an optional object (required: name, entrypoint; both
kebab-case-pattern strings, additionalProperties: false) matching exactly the
shape the quickstart parser expects.

Verified:
- A spec.yaml with a valid agent: block now validates.
- The schema itself remains valid Draft 2020-12.
- No regression: existing kits without the field (spot-checked: paseo) still
  validate unchanged.
- `validate-kits.py --strict` run clean against all 8 real kits on current
  main (agentic-coding-playbook, git-ssh-sign, openchamber, paseo,
  pi-coding-agent, prime-agent, usai-provider, zscaler-ca-certificate).

Co-authored-by: OpenCode Agent <agent@gsa.gov>
…nary)

First harness-agent kit in the family: installs a pinned, SHA-256-verified
OpenCode CLI release binary into the sandbox at create time, replacing acq's
own unpinned MSB fallback (`npm install -g opencode-ai`, resolves to
whatever npm currently calls "latest"). Declares the new top-level `agent:`
block (name/entrypoint, schema added in the prerequisite PR) so acq's
built-in agent-kit readiness gate can confirm this kit genuinely provides
the `opencode` agent token before enabling it.

Install-method decision (SHA-pinned release binary, not npm or nixpkgs) was
reached via a 3-role consensus_vote before authoring, after live-verifying:
nixpkgs at the devenv image's pinned revision resolves `opencode` to v0.3.112
from the pre-rename upstream repo (sst/opencode) — ~70 releases stale — so
installing via that pinned nixpkgs would downgrade users rather than deliver
current OpenCode. The npm path (`opencode-ai`) has its own documented bug
(the sibling quickstart repo's KNOWN_FAILURE_MODES.md): its postinstall step
intermittently fails fetching the real binary. This kit's method has no
npm metadata and no postinstall step to fail — downloaded, SHA-256-verified,
and independently derived both pins (v1.18.34, x64 + arm64) from the real
GitHub release assets, not copied from any third party.

Integrity posture deliberately diverges from every sibling kit in this
family: a SHA-256 mismatch refuses to install (fail CLOSED), rather than
degrading to any fallback — see docs/decisions/fail-closed-on-integrity.md.
Every other failure path (no pin, unsupported arch, network failure,
extraction failure) fails soft, matching the family's convention.

Went through two independent adversarial subagent reviews before this
commit — a security-focused review and a QA/accuracy/vestigial-content
review — and fixed every finding both raised, not just logged them:

Security fixes:
- HIGH: tar extraction trusted a `[ -f ]` check that follows symlinks: a
  hash-matching-but-source-compromised release whose `opencode` member is a
  symlink would have its target's content silently copied, root-owned and
  world-readable, into /usr/local/bin/opencode. Added an explicit `[ -L ]`
  rejection before trusting the extracted member.
- MEDIUM: the idempotency fast-path resolved `opencode` via a PATH lookup
  and trusted its self-reported --version with no re-verification — a
  persisted prior-boot compromise (or another kit's binary earlier on PATH)
  would never be re-checked. Fixed to check the kit's own fixed destination
  path directly, never PATH, with the same symlink rejection.
- Confirmed non-issue after live testing (not just assumed): the version-pin
  glob looks exploitable in isolation but is closed by an existing second
  charset-negation check; no tainted variable reaches a shell-reparsing sink
  regardless.

QA/accuracy fixes:
- HIGH (real functional bug): the kit's own scripts/verify called
  validate-kits.py WITHOUT --root, unlike every sibling kit's verify script —
  reproduced live that this breaks the kit's own offline gate when run from
  outside the repo root. Fixed.
- HIGH (accuracy): README mischaracterized objects.githubusercontent.com as
  a git-LFS-only host; sibling kits (openchamber, prime-agent) actually use
  that same host for the same purpose (release downloads). Rewrote to say
  so, and reframed the egress-host choice as a documented latent fragility
  (GitHub has changed release-asset redirect hosts before) rather than an
  asserted settled fact.
- MEDIUM (accuracy): README overclaimed the opencode-ai npm package itself
  lacks metadata/a postinstall step; it has both — the real point is this
  kit's own install path never touches npm. Rewrote accordingly.
- MEDIUM (doc/code mismatch): spec.yaml and script comments described
  in-script literal fallback values that don't exist in the code. Rewrote to
  state accurately that spec.yaml's install command is the single source of
  truth for the pin, deliberately not duplicated.

Verified post-fix (not just pre-fix): validate-kits.py --strict passes 9/9
kits, the kit's own scripts/verify passes 6/6 checks including a live
integrity-negative test (wrong hash correctly refuses to install anything),
shellcheck clean, markdownlint clean, full repo pytest 401/401 (no
regression).

A final 3-role consensus_vote sanity pass on the fixed kit was dispatched
async before this commit but did not resolve within a reasonable wait;
proceeding on the strength of the two completed, finding-fixed adversarial
reviews rather than blocking further — the vote's result will be reported
and acted on separately if it surfaces anything new.

Co-authored-by: OpenCode Agent <agent@gsa.gov>
mogul and others added 3 commits October 2, 2026 00:30
Address adversarial review findings for the opencode agent-harness kit. Make the offline verifier truly offline, reject unsafe temp-dir fallback, validate archive member type/count before extraction, avoid PATH in the final run check, and add kit troubleshooting documentation.

Co-authored-by: OpenCode Agent <agent@gsa.gov>
@mogul

mogul commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

AI-assisted follow-up review and fixes pushed in d49ea73.

What was fixed

  • Hardened opencode-install.sh temporary workspace handling: removed the predictable /tmp/opencode-install.$$ fallback and now fail soft if mktemp -d cannot create a private temp directory.
  • Made the kit's offline integrity-negative verifier truly offline by shadowing curl with a local stub that copies deterministic local tarballs instead of reaching GitHub.
  • Changed the install-script syntax check from bash -n to sh -n, matching the actual spec.yaml execution path.
  • Added fail-closed archive-layout validation before extraction:
    • rejects missing opencode member
    • rejects non-regular opencode members, including hardlinks
    • rejects duplicate opencode members, including duplicate regular-file entries
  • Added offline verifier regressions for wrong-hash, hardlink member, duplicate mixed member, and duplicate regular member archives.
  • Changed the final installer runnability check to execute the fixed destination path (/usr/local/bin/opencode) instead of trusting PATH.
  • Added integrations/isolation/acq-kits/opencode/TROUBLESHOOTING.md and listed opencode/ in the top-level acq-kits inventory.
  • Removed unresolved “ADR-0030 epic” wording from durable README/spec prose and replaced it with self-contained rationale.

Adversarial review

Ran adversarial sub-agent review before and after fixes. The first pass found the offline verifier/network dependency, temp-dir fallback, shell syntax checker mismatch, missing inventory/troubleshooting docs, and durable-reference wording. Follow-up passes found and then verified fixes for hardlink/non-regular archive members, final PATH trust, and duplicate tar members. Final sub-agent review reported no remaining actionable findings for the installer/verifier changes.

Verification

  • uv run --extra dev integrations/isolation/acq-kits/opencode/scripts/verify
    • Result: 12 passed, 0 failed
    • Live sandbox check intentionally skipped because RUN_ACQ=1 was not set.
  • shellcheck integrations/isolation/acq-kits/opencode/files/home/opencode-install.sh integrations/isolation/acq-kits/opencode/scripts/verify
    • Result: passed, no output.
  • git diff --check
    • Result: passed, no output.
  • uv run --extra dev python integrations/isolation/acq-kits/validate-kits.py --root . --strict
    • Result: all 10 acq-kits valid.
  • uv run --extra dev make validate
    • Result: passed. Existing advisory sensitive-term/network warnings only; no blocking failures.
  • uv run --extra dev make generate-check
    • Result: INDEX.yaml and CATALOG.md up to date.
  • uv run --extra dev make test
    • Result: 407 passed.
  • uv run --extra dev pre-commit run --files integrations/isolation/acq-kits/README.md integrations/isolation/acq-kits/opencode/README.md integrations/isolation/acq-kits/opencode/TROUBLESHOOTING.md integrations/isolation/acq-kits/opencode/files/home/opencode-install.sh integrations/isolation/acq-kits/opencode/scripts/verify integrations/isolation/acq-kits/opencode/spec.yaml
    • Result: passed.

Notes

  • Plain make validate / make generate-check failed on this host because there is no python executable. The equivalent uv run --extra dev ... commands passed using the project environment.
  • Full make ci was not used as the final gate because its pre-commit --all-files path auto-modified unrelated files and hit existing ruff findings in security fixture files outside this PR scope. I reverted those unrelated auto-fixes and ran targeted pre-commit hooks on this PR's files instead.
  • The commit is unsigned because the environment's SSH signing config failed with no SSH agent/signing key available. Commit signing is recommended but not enforced by repository policy.

@mogul

mogul commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

I pushed the fixes above because I thought we needed to land this before landing all of the other stuff around GSA-TTS/agentic-coding-quickstart#474, but I'm uncertain about the state of the provider-kit changes so I'm holding off on pushing a merge through. In the meantime, I'd be happy for someone else to take a good look at the state of this branch and confirm it's good to go!

@wz-gsa

wz-gsa commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

AI-assisted independent re-verification (OpenCode), confirming @mogul's d49ea73 hardening pass before merge.

Pulled the current head and independently re-verified all 4 security fixes — not by trusting the summary, but by building my own test fixtures from scratch and exercising the actual validation logic:

1. Offline verifier is genuinely offline now. Confirmed via diff: the local curl stub copies a deterministic local tarball instead of reaching GitHub. Ran the kit's own scripts/verify: 12/12 checks pass with zero network calls.

2. Temp-dir hardening. Confirmed: the old mktemp -d ... || echo "/tmp/opencode-install.$$" fallback (a predictable, pre-creatable path) is now a hard failure with no fallback.

3. Archive member-type/count validation — independently stress-tested with my own fixtures. Built a symlink-member archive, a genuine regular-file archive, and (most usefully) a duplicate-member archive with two different-content opencode entries. Along the way confirmed something that validates why this check matters: tar -x on a duplicate-member archive silently extracts the LAST entry — a real, demonstrable archive-smuggling primitive. Ran the actual validation logic from the script against all three fixtures:

  • Symlink member → correctly rejected (case ... -*) ;; *) bad_member=... catches anything not starting with -)
  • Regular file → correctly accepted, no false positive
  • Duplicate members → correctly rejected (member_count -ne 1)

4. Final runnability check no longer trusts PATH. Confirmed via diff: command -v opencode (a PATH lookup, which the idempotency check elsewhere in this same file was already fixed to avoid) replaced with "$dest_dir/opencode" --version — closing a gap we'd fixed in one place but missed in this second location.

Also verified:

  • shellcheck --severity=warning on both touched files: clean.
  • sh -n syntax check (matching spec.yaml's actual invocation shell, correcting the prior bash -n mismatch): valid.
  • Full scripts/verify run: 12/12 passed, 0 failed, including the 3 new archive-layout negative tests.
  • TROUBLESHOOTING.md: cross-checked every claimed failure mode and every quoted SECURITY:-prefixed message against the actual script — all accurate.
  • The removal of the "ADR-0030 epic" reference from README.md/spec.yaml: confirmed this is the correct call, not just a stylistic trim — ADR-0030 is still an open, unmerged PR in the quickstart repo, so the old wording was a durable reference to something that doesn't durably exist yet, exactly the anti-pattern this repo's own durable-reference rule exists to prevent.

This is a genuinely good adversarial-review catch on your part — the archive-layout validation in particular is a real gap neither of my own two earlier reviews considered. Every fix holds up under independent, from-scratch adversarial testing, not just its own author's test cases.

I'm confident this branch is good to merge.

@mogul
mogul merged commit 36038a6 into main Oct 2, 2026
7 checks passed
@mogul
mogul deleted the feat/opencode-agent-kit branch October 2, 2026 21:47
@mogul

mogul commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

IMPORTANT

Merging this PR makes the OpenCode harness kit present in agentic-coding-patterns, but it does not by itself turn on the full ADR-0030 agent-kit path.

State after merge:

  • GSA-TTS/agentic-coding-patterns#455 will land a valid opencode kit that installs a pinned, SHA-256-verified OpenCode binary and declares the agent.name / agent.entrypoint metadata enabled by GSA-TTS/agentic-coding-patterns#454.
  • Normal acq run opencode ... users will not exercise it yet until GSA-TTS/agentic-coding-quickstart#474 pins a patterns ref containing this PR and flips the built-in OpenCode agent-kit gate.
  • Quickstart still has the old MSB npm install -g opencode-ai path live as part of GSA-TTS/agentic-coding-quickstart#474 until the consumer-side migration suppresses/removes it when the kit owns installation.
  • This PR does not complete provider-facts plumbing or agent-owned config rendering. GSA-TTS/agentic-coding-quickstart#474 has the provider-facts consumer/fallback path; the producer/config work is still covered by the provider-facts follow-ups such as GSA-TTS/agentic-coding-patterns#436, and the current OpenCode config writer remains usai-provider.
  • Once provider-facts artifacts land, a follow-up is still needed for the OpenCode agent kit to render/merge its own config from those facts, unless we intentionally revise the ADR-0030 ownership model to keep that responsibility elsewhere.

So this merge is a safe prerequisite/availability step: it lands the binary-install kit and metadata target for ACQ readiness checks. It should not be read as “the end-to-end provider facts → OpenCode config → runnable configured agent path is complete.”

mogul added a commit to GSA-TTS/agentic-coding-quickstart that referenced this pull request Oct 4, 2026
Move the built-in patterns bundle from v1.10.0
(2dd2ad6ad5f63b842d732424bed5ba9aebeed676) to v1.11.0
(f2227413df78dc5ef6580b5e29c59542dfe1f66a).

Included patterns commits:

- 36038a6 feat(acq-kits): add opencode agent-harness kit (SHA-pinned release
  binary) (GSA-TTS/agentic-coding-patterns#455)
- 73606d7 fix(usai-provider): make the catalog drift check report real drift
  (GSA-TTS/agentic-coding-patterns#459)
- 56500ba fix(usai-provider): drop embedding models from the chat-model catalog
  (GSA-TTS/agentic-coding-patterns#462)

The oci-engine kit this PR adds to the opt-in catalog is still present at the
new ref, so catalog selection is unchanged.

The opencode agent kit becomes fetchable at this pin for the first time, but it
stays dormant: acq_agent_builtin_kit_enabled returns false for every agent, so
_build_kit_list still yields four built-in kits and no agent kit is applied.
Enabling it is separate work tracked by
#485.

provider-facts/usai.env remains absent at v1.11.0, so the provider-facts loader
still returns 2 (artifact absent, tolerated) and the transitional fallback
defaults remain the only reachable path. #481
is unaffected.

Behavior change riding along with the bump: the usai-provider kit applies to
every sandbox, and its model catalog no longer advertises the
cohere_english_v3 embedding model (13 lines removed from
files/home/usai-config/opencode.jsonc), with 7 lines added to
scripts/sync-usai-models.mjs so the drift check reports real drift.

Co-authored-by: OpenCode [claude-opus-5] <bret.mogilefsky@gsa.gov>
mogul added a commit to GSA-TTS/agentic-coding-quickstart that referenced this pull request Oct 4, 2026
Move the built-in patterns bundle from v1.10.0
(2dd2ad6ad5f63b842d732424bed5ba9aebeed676) to v1.11.0
(f2227413df78dc5ef6580b5e29c59542dfe1f66a).

Included patterns commits:

- 36038a6 feat(acq-kits): add opencode agent-harness kit (SHA-pinned release
  binary) (GSA-TTS/agentic-coding-patterns#455)
- 73606d7 fix(usai-provider): make the catalog drift check report real drift
  (GSA-TTS/agentic-coding-patterns#459)
- 56500ba fix(usai-provider): drop embedding models from the chat-model catalog
  (GSA-TTS/agentic-coding-patterns#462)

The oci-engine kit this PR adds to the opt-in catalog is still present at the
new ref, so catalog selection is unchanged.

The opencode agent kit becomes fetchable at this pin for the first time, but it
stays dormant: acq_agent_builtin_kit_enabled returns false for every agent, so
_build_kit_list still yields four built-in kits and no agent kit is applied.
Enabling it is separate work tracked by
#485.

provider-facts/usai.env remains absent at v1.11.0, so the provider-facts loader
still returns 2 (artifact absent, tolerated) and the transitional fallback
defaults remain the only reachable path. #481
is unaffected.

Behavior change riding along with the bump: the usai-provider kit applies to
every sandbox, and its model catalog no longer advertises the
cohere_english_v3 embedding model (13 lines removed from
files/home/usai-config/opencode.jsonc), with 7 lines added to
scripts/sync-usai-models.mjs so the drift check reports real drift.

Co-authored-by: OpenCode [claude-opus-5] <bret.mogilefsky@gsa.gov>
mogul added a commit to GSA-TTS/agentic-coding-quickstart that referenced this pull request Oct 4, 2026
Move the built-in patterns bundle from v1.10.0
(2dd2ad6ad5f63b842d732424bed5ba9aebeed676) to v1.11.0
(f2227413df78dc5ef6580b5e29c59542dfe1f66a).

Included patterns commits:

- 36038a6 feat(acq-kits): add opencode agent-harness kit (SHA-pinned release
  binary) (GSA-TTS/agentic-coding-patterns#455)
- 73606d7 fix(usai-provider): make the catalog drift check report real drift
  (GSA-TTS/agentic-coding-patterns#459)
- 56500ba fix(usai-provider): drop embedding models from the chat-model catalog
  (GSA-TTS/agentic-coding-patterns#462)

The oci-engine kit this PR adds to the opt-in catalog is still present at the
new ref, so catalog selection is unchanged.

The opencode agent kit becomes fetchable at this pin for the first time, but it
stays dormant: acq_agent_builtin_kit_enabled returns false for every agent, so
_build_kit_list still yields four built-in kits and no agent kit is applied.
Enabling it is separate work tracked by
#485.

provider-facts/usai.env remains absent at v1.11.0, so the provider-facts loader
still returns 2 (artifact absent, tolerated) and the transitional fallback
defaults remain the only reachable path. #481
is unaffected.

Behavior change riding along with the bump: the usai-provider kit applies to
every sandbox, and its model catalog no longer advertises the
cohere_english_v3 embedding model (13 lines removed from
files/home/usai-config/opencode.jsonc), with 7 lines added to
scripts/sync-usai-models.mjs so the drift check reports real drift.

Co-authored-by: OpenCode [claude-opus-5] <bret.mogilefsky@gsa.gov>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants