Skip to content

Build a consumer

A consumer — a UI, client app, or downstream system — implements none of these contracts; it relies on them. The Microcks mock stack stands in for the real services, so a consumer can be built and demonstrated, with data, before any implementation exists. This is what the mocks are for: consumers, and the spec repo's own conformance checks. Holding a real implementation to the contracts is a different job with a different command — see Drive an implementation.

The loop below is carried end-to-end by the consume-service skill. Install the plugin — /plugin marketplace add hungovercoders/sysspec, then /plugin install — and ask to build against a service; the skill runs everything on this page, from interview to verified definition of done. What follows is the shape of that loop, so you can recognise it, review it, or run it by hand.

flowchart TD
  tag["spec repo: merge to main cuts service/vX.Y.Z"]
  lock["contracts.lock pins the tag + its commit sha"]
  fetch["task contracts:fetch - read-only .contracts/ (specs + mocks + kit)"]
  mocks["task -d .contracts mocks:load - pinned mocks up, fixtures included"]
  build["build: generate types from the fetched specs"]
  verify["verify: client flows, envelope handling, idempotence"]
  done(["consumer satisfies the pinned surface"])
  tag -->|"pin the newest tag"| lock
  lock --> fetch --> mocks --> build --> verify
  verify -->|green| done
  verify -->|red| build
  tag -.->|"each new tag: Renovate re-pins"| lock

1. Pin and fetch, exactly like an implementation

The consumer records which released surface it builds against in a contracts.lock and fetches it read-only into .contracts/ — the same lock and contracts:fetchthe implementation journey uses, mock stack included, so the mocks a consumer sees are versioned by the pin. A consumer may pin more than one service.

2. Stand up the pinned mocks

task -d .contracts mocks:load SERVICE=<service>   # stack up + pinned specs loaded
task -d .contracts mocks:watch CHANNEL=<Title>/<version>/<operation>
task -d .contracts mocks:down

Point the client at the mocks (title and version come from the spec's info block):

  • REST http://localhost:8585/rest/<Title>/<version>/…with fixture data included, so list and detail screens render real-looking aggregates.
  • Events ws://localhost:8081/api/ws/<Title>/<version>/<operation>emits the example CloudEvents on a schedule.

3. Build against them

Generate client types from the fetched OpenAPI and the AsyncAPI message schemas — never hand-model a payload from memory or from observed mock traffic. Honour the event conventions the features state: dedupe on the CloudEvents envelope id, expect at-least-once delivery, assume ordering only within an aggregate, and tolerate additive change — a minor bump must never break a consumer.

4. Verify — the consumer's definition of done

  1. Client flows against the REST mocks — every call the consumer makes, responses parsed through the generated types.
  2. Event handling against real envelopes — feed the handler from the WS mock or the pinned example files, validating each payload against the AsyncAPI schema before acting on it.
  3. Idempotence — replaying the same envelope id must not double-apply; the features promise at-least-once delivery, so this is contract, not hygiene.
  4. Falsifiability — prove the suite can fail: run it once against the kit's null service (task -d .contracts null:run …) or, minimally, with the mock stack down, and require zero passes. A check that stays green against a service answering 200 {} to everything verifies nothing.

Green proves the consumer satisfies the pinned surface's examples and schemas. It does not prove the real service behaves — that is the implementation's verification loop, on the other page.

5. Stay current

Identical machinery to implementations: new release tags arrive as Renovate pin-bump PRs, the suite above runs against the new pin — new mocks, new fixtures — and green minors auto-merge with no human and no agent. The consume-service skill (hungovercoders/sysspec) carries the full walkthrough.