fix(openapi): enforce stable unique operationIds - #337
Conversation
|
Important Review available on request
Reviews should be triggered manually for repositories with fewer than 10 stars. Select Trigger review above or comment ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthrough표준 라이브러리만 사용하는 OpenAPI ChangesOpenAPI operationId 계약
Estimated code review effort: 3 (Moderate) | ~20 minutes Mergeability Score: ⚪ Minimal · up to This localized OpenAPI contract change is merge-ready after normal checks and review; no actionable merge-blocking risk remains. 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@opencode-agent @cwl-noema-review Please independently review exact current head |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/openapi_operation_id_contract.py`:
- Around line 135-138: scripts/openapi_operation_id_contract.py:135-138의
operationId 수집을 메서드의 직접 속성 레벨로 제한해 중첩 x- 확장의 값을 사용하지 않도록 수정하고,
scripts/openapi_operation_id_contract.py:43-49의 YAML 스칼라 처리는 인라인 주석을 ID에 포함하지 않게
하거나 지원하지 않는 형식을 명시적으로 실패시키며 빈 주석 값도 유효한 ID로 취급하지 않도록 하십시오.
scripts/test_openapi_operation_id_contract.py:28-50에는 인라인 주석이 서로 다른 동일
operationId의 중복을 검증하는 회귀 테스트를 추가하고,
scripts/test_openapi_operation_id_contract.py:74-89에는 중첩 x- 확장의 operationId가 누락
검증을 우회하지 않는지 검증하는 테스트를 추가하십시오.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: fb350f21-65f6-4a39-86a1-d74d48a716eb
📒 Files selected for processing (2)
scripts/openapi_operation_id_contract.pyscripts/test_openapi_operation_id_contract.py
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/test_openapi_operation_id_contract.py`:
- Around line 119-141: Update inspect_operation_ids so an operationId counts
only when it is a direct property of the HTTP method, not when nested under
metadata such as x-metadata; enforce the operation-level indentation or track
the method mapping while parsing, and preserve the missing_operation_id
violation for the GET /api/v1/jobs case. Ensure the scripts unittest discovery
suite passes.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 6fbf339f-3e46-40c3-9d21-120fe62777f9
📒 Files selected for processing (1)
scripts/test_openapi_operation_id_contract.py
OpenCode Review Overview
Pull request overviewOpenCode reviewed the current-head bounded evidence and requested changes before merge. Findings1. P1 scripts/test_openapi_operation_id_contract.py:161 - OperationId contract tests have no trusted execution path; the PR's enforcement claim is unverified
SummaryInspected changed files scripts/openapi_operation_id_contract.py and scripts/test_openapi_operation_id_contract.py via inlined Focused changed hunks. Approval sufficiency: not sufficient; the enforcement claim lacks any trusted execution or wiring evidence (blocking P1 finding). Verification posture: supported suite = mvn test (Java) per test_commands; no python test command; no OPENCODE_EXECUTION_RECEIPT for the new tests; Coverage execution evidence reports Result: PASS for supported repository test suites, and python coverage is not applicable because no supported python package/test manifest was found (unpackaged_source_surfaces flags both new files). Linter/static: no python lint command configured (lint_commands = mvn verify, hadolint Dockerfile); scripts are stdlib-only. TDD/regression: 7 adversarial fixtures cover duplicate, inline-comment identity, missing, comment-only, nested-extension, and path-metadata cases, but no trusted evidence they execute. Docstring coverage: module and fixtures carry docstrings; Coverage decision reports docstring gates passed or advisory. DAG: head-flow Mermaid DAG below maps the contract file -> checker -> fixtures -> CI python job, with the CI wiring node not evidenced. PoC/execution: none trusted; no receipts for the new tests. DDD/domain: tooling script; domain surface is the buyer OpenAPI contract invariant. CDD/context: buyer-readiness gate / issue #315; the checker docstring implies gate integration that CodeGraph contradicts (no callers). Similar issues: none in evidence; sibling scripts/test_.py convention exists but is inferential, not trusted. Claim/concept check: PR claims enforcement; contradicted by absence of an execution path in trusted evidence. Standards search: OpenAPI 3.0.3 operationId uniqueness is the intended invariant; the 2/4/6-indent format is a documented repo-specific narrow format. Compatibility/convention: all new identifiers are multi-word snake_case (inspect_operation_ids, ContractViolation, InspectionResult, HTTP_METHODS, finish_operation); no reserved-word or casing issues. Breaking-change/backcompat: additive new files only; no existing contract changed. Implementation completeness: scanner logic complete for the documented narrow format, but the module has no CLI entry point, no gate caller, and no CI wiring. Performance: single linear pass, no dependencies. Developer experience: DX surface is the CI/gate wiring; sibling pattern (scripts/test_verify_maven_test_reports.py::test_ci_invokes_report_gate_after_maven_verify) requires wiring proof the new test lacks. User experience: non-web surface = CI gate behavior; gate failures on contract drift cannot occur until the suite is wired. Visual/DOM: non-web change; no DOM surface. Accessibility/i18n: not applicable (no UI). Supply-chain/license: stdlib only, zero new dependencies. Packaging: both files flagged unpackaged (no python package/test manifest); wiring still absent. Security/privacy: no auth/secrets/network surface; scanner reads only repo-owned YAML, no eval/exec, fails closed on tab indentation and unsupported quoted scalars. Residual risk: if the repository's CI already auto-discovers scripts/test_.py (inferred from 8 sibling test files and scripts/test_ci_workflow_stack_coverage.py, but not trusted-evidenced), enforcement may already work; remaining risks are the narrow-format parser matching the real contract file (real-file assertion has no trusted execution evidence) and the untested ValueError path for quoted operationId scalars with trailing comments. Adversarial validation{"status":"failed","probes":[{"path":"scripts/test_openapi_operation_id_contract.py","line":161,"hypothesis":"The PR's enforcement claim is unrealized: no trusted execution path runs the new contract tests, so a future duplicate or missing operationId would not fail CI.","attack_or_counterexample":"Attack the enforcement surface across every trusted place a test could run: the supported test-command contract, the changed-file list, the CodeGraph caller graph, and the execution-receipt section. The real contract docs/deployment/clearfolio-buyer-connector.openapi.yaml is read only by test_current_buyer_contract_has_unique_operation_ids (scripts/test_openapi_operation_id_contract.py:22); if nothing executes the suite, the invariant is unenforced.","evidence":"Trusted bounded evidence: Review execution contracts test_commands=[\"mvn test\"] (no python invocation; coverage_commands=[]); unpackaged_source_surfaces flags both new files as python with 'no package/test manifest was detected'; Changed files lists only the two scripts with no .github/workflows/ci.yml or gate-script change; CodeGraph 'Blast radius' lists no caller of inspect_operation_ids outside its own test; no OPENCODE_EXECUTION_RECEIPT line exists for these tests anywhere in bounded-review-evidence.md. Source trace at scripts/test_openapi_operation_id_contract.py:161 shows the sole entry point is the `if __name__ == \"__main__\": unittest.main()` guard, which no trusted command invokes; the counterexample is confirmed by the evidence corpus. source-line-sha256=796a5580141574dc9853ca03b199ff60a407c2d2e669ea69126c6b8062e24596","outcome":"confirmed"},{"path":"scripts/openapi_operation_id_contract.py","line":157,"hypothesis":"The scanner false-negatives a duplicate operationId reused by two different paths, letting an ambiguous generated-client identity pass the gate.","attack_or_counterexample":"Input: fixture contract with GET /api/v1/jobs operationId readJob and POST /api/v1/items operationId readJob, plus the variant with inline YAML comments after each operationId (fixtures in scripts/test_openapi_operation_id_contract.py:28 and :52).","evidence":"Trusted source trace at scripts/openapi_operation_id_contract.py:157 (the `return InspectionResult(operations=operations, violations=violations)` line): finish_operation() records the first use in first_use and, when the second operation completes, appends ContractViolation(code='duplicate_operation_id', detail=\"operationId 'readJob' is used by GET /api/v1/jobs and POST /api/v1/items\") before returning; the inlined fixtures assert exactly that violation object in result.violations, and _yaml_scalar strips trailing comments so commented duplicates still collide. The bounded branch rejected the counterexample; hypothesis falsified. source-line-sha256=068e11328baca54941dfcf967a3e688d9f70591368df9fc5d9cd8d8978065e4a","outcome":"falsified"},{"path":"scripts/test_openapi_operation_id_contract.py","line":1,"hypothesis":"An operation whose operationId is missing, comment-only, or nested under an extension (x-metadata) evades detection, and path-level metadata (parameters) is miscounted as an operation.","attack_or_counterexample":"Inputs: methods with no operationId, with `operationId: # comment`, with operationId nested under x-metadata at indent 8, and a path item with parameters: [] before get (fixtures at scripts/test_openapi_operation_id_contract.py:63, :88, :108, :128).","evidence":"Trusted source trace at scripts/test_openapi_operation_id_contract.py:1 (module header importing ContractViolation and inspect_operation_ids and declaring the fixture suite): the four fixtures assert exactly ContractViolation(missing_operation_id) or the exact operations list [('GET', '/api/v1/jobs/{jobId}', 'readJob')]; the checker's indent state machine accepts operationId only at exactly indent 6 directly under an HTTP method key (path-level parameters: [] is skipped, nested operationId at indent 8 is ignored, comment-only values collapse to None via _yaml_scalar) and delivers those violations at the return in scripts/openapi_operation_id_contract.py:157. Every evasion attempt was rejected; hypothesis falsified. source-line-sha256=381f9bfc69d49d39040a7d5fc3197ce385019a2ba2de649622f841a8c658ed37","outcome":"falsified"}],"residual_risk":"If the repository's CI already auto-discovers scripts/test_*.py (inferred from 8 sibling test files and scripts/test_ci_workflow_stack_coverage.py, but not trusted-evidenced), enforcement may already work; remaining risks are the narrow 2/4/6-indent parser matching the real contract file (the real-file assertion has no trusted execution evidence) and the untested ValueError path for quoted operationId scalars with trailing comments."}
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: openapi_operation_id_contract.py"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: openapi_operation_id_contract.py"]
R1 --> V1["required checks"]
Evidence --> S2["Test: test_openapi_operation_id_contract.py"]
S2 --> I2["regression suite"]
I2 --> R2["Review risk: Test: test_openapi_operation_id_contract.py"]
R2 --> V2["targeted test run"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and requested changes before merge.
Findings
1. P1 scripts/test_openapi_operation_id_contract.py:161 - OperationId contract tests have no trusted execution path; the PR's enforcement claim is unverified
- Problem: The PR title and body promise to 'enforce stable unique operationIds', but the new checker and its test suite are not reachable from any trusted execution path: no python test command, no workflow change, no gate caller, no execution receipt. The real-contract assertion (test_current_buyer_contract_has_unique_operation_ids) has no trusted evidence of passing against docs/deployment/clearfolio-buyer-connector.openapi.yaml.
- Root cause: The diff adds only two stdlib scripts; Review execution contracts test_commands=["mvn test"] contains no python invocation; unpackaged_source_surfaces flags both new files ('no package/test manifest was detected'); the changed-files list contains no .github/workflows/ci.yml or buyer-readiness-gate change; CodeGraph blast radius reports no caller of inspect_operation_ids outside its own test; the module has no CLI entry point; and no OPENCODE_EXECUTION_RECEIPT exists for these tests in bounded-review-evidence.md.
- Fix: Wire the checker into the executed verification path: add a CI python-job step running
python3 scripts/test_openapi_operation_id_contract.py(mirroring thepython3 scripts/verify_maven_test_reports.pystep asserted by scripts/test_verify_maven_test_reports.py::test_ci_invokes_report_gate_after_maven_verify), or invoke inspect_operation_ids from the buyer-readiness gate the module docstring references; optionally add a wiring-assertion test as suggested below; then provide an execution receipt for the new tests at head SHA 5778999. - Regression test: python3 scripts/test_openapi_operation_id_contract.py (must exit 0), then re-run CI to confirm the new workflow step executes the suite.
- Suggested diff: posted in this finding's inline review thread.
Summary
Inspected changed files scripts/openapi_operation_id_contract.py and scripts/test_openapi_operation_id_contract.py via inlined Focused changed hunks. Approval sufficiency: not sufficient; the enforcement claim lacks any trusted execution or wiring evidence (blocking P1 finding). Verification posture: supported suite = mvn test (Java) per test_commands; no python test command; no OPENCODE_EXECUTION_RECEIPT for the new tests; Coverage execution evidence reports Result: PASS for supported repository test suites, and python coverage is not applicable because no supported python package/test manifest was found (unpackaged_source_surfaces flags both new files). Linter/static: no python lint command configured (lint_commands = mvn verify, hadolint Dockerfile); scripts are stdlib-only. TDD/regression: 7 adversarial fixtures cover duplicate, inline-comment identity, missing, comment-only, nested-extension, and path-metadata cases, but no trusted evidence they execute. Docstring coverage: module and fixtures carry docstrings; Coverage decision reports docstring gates passed or advisory. DAG: head-flow Mermaid DAG below maps the contract file -> checker -> fixtures -> CI python job, with the CI wiring node not evidenced. PoC/execution: none trusted; no receipts for the new tests. DDD/domain: tooling script; domain surface is the buyer OpenAPI contract invariant. CDD/context: buyer-readiness gate / issue #315; the checker docstring implies gate integration that CodeGraph contradicts (no callers). Similar issues: none in evidence; sibling scripts/test_.py convention exists but is inferential, not trusted. Claim/concept check: PR claims enforcement; contradicted by absence of an execution path in trusted evidence. Standards search: OpenAPI 3.0.3 operationId uniqueness is the intended invariant; the 2/4/6-indent format is a documented repo-specific narrow format. Compatibility/convention: all new identifiers are multi-word snake_case (inspect_operation_ids, ContractViolation, InspectionResult, HTTP_METHODS, finish_operation); no reserved-word or casing issues. Breaking-change/backcompat: additive new files only; no existing contract changed. Implementation completeness: scanner logic complete for the documented narrow format, but the module has no CLI entry point, no gate caller, and no CI wiring. Performance: single linear pass, no dependencies. Developer experience: DX surface is the CI/gate wiring; sibling pattern (scripts/test_verify_maven_test_reports.py::test_ci_invokes_report_gate_after_maven_verify) requires wiring proof the new test lacks. User experience: non-web surface = CI gate behavior; gate failures on contract drift cannot occur until the suite is wired. Visual/DOM: non-web change; no DOM surface. Accessibility/i18n: not applicable (no UI). Supply-chain/license: stdlib only, zero new dependencies. Packaging: both files flagged unpackaged (no python package/test manifest); wiring still absent. Security/privacy: no auth/secrets/network surface; scanner reads only repo-owned YAML, no eval/exec, fails closed on tab indentation and unsupported quoted scalars. Residual risk: if the repository's CI already auto-discovers scripts/test_.py (inferred from 8 sibling test files and scripts/test_ci_workflow_stack_coverage.py, but not trusted-evidenced), enforcement may already work; remaining risks are the narrow-format parser matching the real contract file (real-file assertion has no trusted execution evidence) and the untested ValueError path for quoted operationId scalars with trailing comments.
Adversarial validation
{"status":"failed","probes":[{"path":"scripts/test_openapi_operation_id_contract.py","line":161,"hypothesis":"The PR's enforcement claim is unrealized: no trusted execution path runs the new contract tests, so a future duplicate or missing operationId would not fail CI.","attack_or_counterexample":"Attack the enforcement surface across every trusted place a test could run: the supported test-command contract, the changed-file list, the CodeGraph caller graph, and the execution-receipt section. The real contract docs/deployment/clearfolio-buyer-connector.openapi.yaml is read only by test_current_buyer_contract_has_unique_operation_ids (scripts/test_openapi_operation_id_contract.py:22); if nothing executes the suite, the invariant is unenforced.","evidence":"Trusted bounded evidence: Review execution contracts test_commands=[\"mvn test\"] (no python invocation; coverage_commands=[]); unpackaged_source_surfaces flags both new files as python with 'no package/test manifest was detected'; Changed files lists only the two scripts with no .github/workflows/ci.yml or gate-script change; CodeGraph 'Blast radius' lists no caller of inspect_operation_ids outside its own test; no OPENCODE_EXECUTION_RECEIPT line exists for these tests anywhere in bounded-review-evidence.md. Source trace at scripts/test_openapi_operation_id_contract.py:161 shows the sole entry point is the `if __name__ == \"__main__\": unittest.main()` guard, which no trusted command invokes; the counterexample is confirmed by the evidence corpus. source-line-sha256=796a5580141574dc9853ca03b199ff60a407c2d2e669ea69126c6b8062e24596","outcome":"confirmed"},{"path":"scripts/openapi_operation_id_contract.py","line":157,"hypothesis":"The scanner false-negatives a duplicate operationId reused by two different paths, letting an ambiguous generated-client identity pass the gate.","attack_or_counterexample":"Input: fixture contract with GET /api/v1/jobs operationId readJob and POST /api/v1/items operationId readJob, plus the variant with inline YAML comments after each operationId (fixtures in scripts/test_openapi_operation_id_contract.py:28 and :52).","evidence":"Trusted source trace at scripts/openapi_operation_id_contract.py:157 (the `return InspectionResult(operations=operations, violations=violations)` line): finish_operation() records the first use in first_use and, when the second operation completes, appends ContractViolation(code='duplicate_operation_id', detail=\"operationId 'readJob' is used by GET /api/v1/jobs and POST /api/v1/items\") before returning; the inlined fixtures assert exactly that violation object in result.violations, and _yaml_scalar strips trailing comments so commented duplicates still collide. The bounded branch rejected the counterexample; hypothesis falsified. source-line-sha256=068e11328baca54941dfcf967a3e688d9f70591368df9fc5d9cd8d8978065e4a","outcome":"falsified"},{"path":"scripts/test_openapi_operation_id_contract.py","line":1,"hypothesis":"An operation whose operationId is missing, comment-only, or nested under an extension (x-metadata) evades detection, and path-level metadata (parameters) is miscounted as an operation.","attack_or_counterexample":"Inputs: methods with no operationId, with `operationId: # comment`, with operationId nested under x-metadata at indent 8, and a path item with parameters: [] before get (fixtures at scripts/test_openapi_operation_id_contract.py:63, :88, :108, :128).","evidence":"Trusted source trace at scripts/test_openapi_operation_id_contract.py:1 (module header importing ContractViolation and inspect_operation_ids and declaring the fixture suite): the four fixtures assert exactly ContractViolation(missing_operation_id) or the exact operations list [('GET', '/api/v1/jobs/{jobId}', 'readJob')]; the checker's indent state machine accepts operationId only at exactly indent 6 directly under an HTTP method key (path-level parameters: [] is skipped, nested operationId at indent 8 is ignored, comment-only values collapse to None via _yaml_scalar) and delivers those violations at the return in scripts/openapi_operation_id_contract.py:157. Every evasion attempt was rejected; hypothesis falsified. source-line-sha256=381f9bfc69d49d39040a7d5fc3197ce385019a2ba2de649622f841a8c658ed37","outcome":"falsified"}],"residual_risk":"If the repository's CI already auto-discovers scripts/test_*.py (inferred from 8 sibling test files and scripts/test_ci_workflow_stack_coverage.py, but not trusted-evidenced), enforcement may already work; remaining risks are the narrow 2/4/6-indent parser matching the real contract file (the real-file assertion has no trusted execution evidence) and the untested ValueError path for quoted operationId scalars with trailing comments."}-
Result: REQUEST_CHANGES
-
Reason: The new operationId checker and its 7-test suite have no trusted execution path: test_commands lists only mvn test, both files are flagged unpackaged with no test manifest, no workflow change is in the diff, CodeGraph shows no caller of inspect_operation_ids, and no execution receipt exists, so the PR's stated enforcement objective is unverified and unwired.
-
Head SHA:
57789991ef307112208d8b600b37a1eef2f2f968 -
Workflow run: 31700909457
-
Workflow attempt: 1
Changed-File Evidence Map
flowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file: openapi_operation_id_contract.py"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file: openapi_operation_id_contract.py"]
R1 --> V1["required checks"]
Evidence --> S2["Test: test_openapi_operation_id_contract.py"]
S2 --> I2["regression suite"]
I2 --> R2["Review risk: Test: test_openapi_operation_id_contract.py"]
R2 --> V2["targeted test run"]
|
@opencode-agent review Review exact head Review read-only; preserve independent reviewer identity. Do not mutate the branch, synthesize author approval, weaken protection, or merge. |
Rate Limit Exceeded
|
Dismissed as predecessor-head evidence. This review is anchored to 57789991ef307112208d8b600b37a1eef2f2f968; the current head is 5d72b444bb1633e097f27462dc64abe85359ec11. The cited execution-path blocker is corrected: the contract test now asserts the existing exact-head CI invokes python -m pytest -q scripts, and CI run 31878563938 completed successfully on the current head. The inline finding is resolved. This dismissal is not approval; a fresh current-head independent verdict remains required.
|
Exact-current-head independent review request for The latest head is the verified current-main merge of the previously repaired implementation. Fresh current-head CI, Security Scan, and SAST Semgrep are terminal-success; this standard-library contract path does not emit fuzz; mergeable is true; all inline threads are resolved or outdated. Review this exact head only. @coderabbitai review |
Rate Limit Exceeded
|
|
Exact-current-head independent review request for This head is the protected-main update of the previously verified two-file operationId contract. CI, Security Scan, and SAST Semgrep are terminal-success; fuzz is not emitted for this Python contract-only path; every inline finding is resolved or outdated. The exact CI workflow executes @opencode-agent review Review this exact head read-only. Do not mutate the branch, synthesize author approval, weaken protection, or merge. |
Rate Limit Exceeded
|
Objective
Advance issue #315 with a bounded machine-readable API contract invariant: every HTTP operation in the repository-owned buyer OpenAPI must declare one explicit, unique
operationIdso standalone and naruon-compatible generated clients cannot acquire ambiguous method identities.Exact current-head evidence
eb0a32e87e7470469c8fa0f8c67d9583654bef57;13e4a4a2a422df9fee2a5dc3d8096bf7eb9fab4e;5d72b444bb1633e097f27462dc64abe85359ec11with current protectedmain;31880631763, Security Scan31880631770, and SAST Semgrep31880631819: terminal-success;Executed contract
The checker recognizes only actual HTTP methods under OpenAPI path items, accepts only direct non-empty string
operationIdproperties, strips YAML comments correctly, rejects nested extension values as substitutes, and reports duplicate identities with both method/path locations.The contract test verifies the repository-owned buyer OpenAPI and binds itself to the trusted exact-head CI path by requiring
.github/workflows/ci.ymlto executepython -m pytest -q scripts. The successful current-head CI run therefore proves the operationId suite ran within the existing buyer-readiness job rather than as an orphaned script.Scope boundary
This is one acceptance item under issue #315. It does not claim complete route/DTO/error/schema parity, API version negotiation, breaking-change detection, generated clients, release provenance, or standalone+naruon compatibility.
Merge gate
Keep this exact head unchanged. Auto-merge may act only after live required checks remain successful, zero valid unresolved findings remain, and a qualifying independent non-author approval is attached to this exact head. Any head movement requires full exact-head revalidation; no predecessor evidence transfers.