Skip to content

feat(api): add machine-readable HTTP and CDC contracts - #157

Closed
seonghobae wants to merge 8 commits into
developfrom
feat/machine-readable-api-contracts
Closed

feat(api): add machine-readable HTTP and CDC contracts#157
seonghobae wants to merge 8 commits into
developfrom
feat/machine-readable-api-contracts

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 9, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Execute issue #152 with a separate direct-develop interoperability slice. mightyETL currently exposes shipped HTTP and Kafka CDC behavior through Java/prose only; this PR establishes checked-in machine-readable OpenAPI and AsyncAPI contracts without promoting active-PR behavior to protected product truth.

Exact current identity

  • protected/live base: develop@622e5e6c3d534f230c390f10e3832efadfc01825;
  • branch: feat/machine-readable-api-contracts;
  • exact current head: d43c257c044ed3006980317bd8932cb5b22a32ab;
  • Draft: true;
  • GitHub mergeability: true at the latest refetch;
  • unresolved review threads: zero;
  • formal reviews: none.

Every check/review from an older head is stale and does not transfer.

Initial RED → checked-in contracts

Creation head 88f596305b643cdd5e17a86d9b10bf1e5e7a46fd added the contract test before either artifact existed. The branch now contains:

  • contracts/openapi/mightyetl.yaml using OpenAPI 3.2.0 for the protected HTTP surface;
  • contracts/asyncapi/mightyetl-cdc.yaml using AsyncAPI 3.1.0 for the live Kafka/Debezium publication boundary;
  • MachineReadableApiContractTest binding checked-in routes and event claims to protected controller/source code.

The protected spec includes synchronous ETL, target connector discovery, feature-gated durable submission/status, CDC start/stop/status/source/target discovery, RFC 9457 Problem Details, current idempotency/cache/location metadata, and raw Debezium JSON Kafka semantics. It deliberately excludes active-PR cancellation, replay, Retry-After, ETag/If-None-Match, exactly-once, and canonicalized CDC claims.

Follow-on RCA — secured ETL operations omitted their 401 contract

Protected etl-service source uses SecurityConfig with .requestMatchers("/api/**").authenticated() and HTTP Basic. The first checked-in OpenAPI revision declared basicAuth on all four ETL operations but did not describe the authentication-failure response. That leaves generated clients unaware that Spring Security can reject the request before it reaches the application Problem Details boundary.

RED

Commit 6f92fcc6d51cf15fc1600f994600091977d75257 extends MachineReadableApiContractTest so it binds the security declaration to protected SecurityConfig and requires all four secured ETL operations to declare a reusable 401 response with WWW-Authenticate.

The preceding OpenAPI source had zero such response declarations, so this is source-proven fail-first evidence. Hosted checks on that transient head were superseded by the following fix and are not reused as final evidence.

GREEN candidate

Exact current head d43c257c044ed3006980317bd8932cb5b22a32ab adds the 401 Unauthorized response to:

  • POST /api/etl/process;
  • GET /api/etl/connectors;
  • POST /api/etl/jobs;
  • GET /api/etl/jobs/{jobRecordId};

and defines reusable components.responses.Unauthorized with the HTTP Basic WWW-Authenticate challenge. Application-generated RFC 9457 responses remain distinct from Spring Security's pre-controller authentication boundary.

Remaining interoperability acceptance gap

The current Java test performs deterministic source/contract binding and truthful negative checks, but issue #152 also requires validation against pinned official OpenAPI/AsyncAPI schemas or maintained validators plus representative contract fixtures. Do not call this branch merge-ready merely because string/source assertions are green. The validator path must be selected from supported current tooling without adding an unpinned network dependency or inventing a library/version.

A generated SDK smoke test, or an explicit reviewed generator-neutral rationale, also remains required by #152 before issue closure.

Exact-current-head gate state

For exact head d43c257c044ed3006980317bd8932cb5b22a32ab at the latest refresh:

  • CI 31314052270: queued — not passing;
  • Dependency Review 31314052274: queued — not passing;
  • CycloneDX SBOM 31314052269: queued — not passing;
  • SAST Semgrep 31314052267: queued — not passing;
  • Security Scan 31314052271: queued — not passing;
  • CodeRabbit commit status: success, not a formal counted approval;
  • qualifying independent non-author exact-head APPROVED review: absent.

Queued/pending/absent/stale/predecessor/status-only/synthetic evidence is not passing. Keep Draft through official validator/schema evidence, representative fixtures, documentation/traceability linkage, exact-head CI/security and independent review.

Safety / compatibility

Do not advertise an active-PR endpoint/header/state early. Do not call raw Debezium publication exactly-once or canonicalized. If runtime/generated contracts are added later, compare or publish them deterministically from the exact release source instead of allowing checked-in and runtime contracts to drift.

@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fcb6598b-5645-4f52-8881-eee939b01128

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment on lines +266 to +268
type: http
scheme: basic
description: ETL service protected /api/** baseline uses Spring Security HTTP Basic authentication.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Confirmed as a valid current-head finding, not a false positive. The OpenAPI basicAuth scheme truthfully mirrors the protected etl-service runtime, which independently authenticates /api/** with HTTP Basic. Suppressing or relabeling the contract would make the machine-readable API false rather than remove the weak trust boundary. The root runtime remediation is tracked in #161: replace direct ETL Basic auth with a deployment-configured fail-closed service authentication boundary (leading design: JWT Resource Server), then update this OpenAPI scheme and regenerate SAST on the unchanged resulting head.

Live PR head is aa558f25363bfb833e49ed79b49cfdbea39c8eea on develop@622e5e6c3d534f230c390f10e3832efadfc01825; SAST run 31315084629 is correctly red on this finding. This branch moved during the current writer invocation, so source/ref mutation is frozen here rather than racing the active writer. Keep this thread unresolved until the runtime authentication boundary and contract are both changed and exact-head SAST proves the finding gone.

Copy link
Copy Markdown
Collaborator Author

Superseded by #278 after fresh preservation verification. The replacement carries the same four changed paths and 642-line additive contract/test surface; the old and replacement diffs are semantically identical except that the OpenAPI protected-baseline identity advances from the stale 622e5e6c3d534f230c390f10e3832efadfc01825 snapshot to #278's later protected baseline. No unique endpoint, event-contract, 401/authentication, test, or README work from this branch is lost. Keep #278 as the single active machine-readable-contract line; this PR must not be merged separately.

@seonghobae seonghobae closed this Aug 11, 2026
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