Skip to content

The checklist

Everything below is pulled from the detailed pages in this section — this page exists so you can work through it top to bottom while you build, and come back to it when you’re not sure what’s left. Each item links to the page that explains the why.

  • Talk to the Cratis team about generating and publishing a contracts package for your language, rather than hand-rolling a protoc toolchain yourself. See Two ways to start.
  • Treat the generated contracts package as read-only — never hand-edit it, never hand-maintain a fork of it. It’s regenerated by Chronicle’s own pipeline on every kernel release.
  • Depend on the published contracts package as an ordinary dependency in your idiomatic client. Don’t vendor it, and don’t build your idiomatic client in the same package. See Layering an idiomatic client.
  • Build it as a separate, hand-maintained package with its own release cadence — not inside the generated contracts package, and not by hiding hand-written code inside generated files.
  • Name and export it so nobody consuming it ever needs to import the contracts package directly.
  • Make it a complete, general-purpose client on its own: usable from a console tool, a script, or a background worker with no hosting framework required. A convenience/hosting package (an ASP.NET-Core- or Spring-Boot-style integration) is optional and comes later, once the idiomatic client is stable — see Layering an idiomatic client.
  • Parse all three authentication modes from the connection string: client credentials, API key, and none (auth=none).
  • For client credentials, implement the OAuth client_credentials exchange against /connect/token — the username and password in the connection string map to client_id and client_secret, not to HTTP Basic auth.
  • Fall back to the chronicle-dev-client / chronicle-dev-secret development defaults when the connection string carries no credentials at all.
  • Attach authorization: Bearer {token} to every outgoing call, across every streaming shape your gRPC library exposes.
  • Cache the token, refresh it proactively ahead of expiry, and retry exactly once on an Unauthenticated response.
  • Never log a raw connection string or a raw token — always log through a redacted rendering. See Authentication and bearer tokens.
  • Support both connection-string forms: an explicit, comma-separated host list and chronicle+srv:// DNS-based discovery.
  • Re-resolve the server list on every connect and reconnect, not just once at startup.
  • Ship at least least-connections (matching the real probe/reserve protocol against /connections/count and /connections/reserve) and round-robin (with a random start offset per instance).
  • Embed your contracts package’s compiled descriptor set, and run the wire-compatibility check before treating a new connection as usable. Fail hard on a real incompatibility — don’t degrade silently.
  • Run a keep-alive watchdog with capped exponential backoff, and reuse the same connect path for reconnects that the initial connect uses. See Clustering and the connection lifecycle.
  • Parse the connection string into a typed value once. Don’t re-parse or grep the raw string wherever a setting is needed.
  • Compute the authentication mode from the parsed fields rather than storing it separately, so the two can’t drift apart.
  • Offer a fluent builder that validates as it assembles (reject “credentials and API key both present” at construction time, not at first connect).
  • Offer a redacted rendering of the connection string, and use it everywhere the client itself logs. See Connection string elements.
  • Publish the contracts package from Chronicle’s own release pipeline, version-locked to the kernel release it was generated from.
  • Publish the idiomatic client as its own artifact, on its own release cadence, once it’s stable enough to ship.
  • The moment you add a second publishable module — a testing package, a convenience/hosting package — add it to your CI’s actual publish job in the same change that adds its build config. This is not a hypothetical: io.cratis:chronicle-testing and io.cratis:chronicle-spring-boot-starter both had correct Maven coordinates and a working mavenPublishing block for weeks before anyone noticed the release workflow only ever ran :Source:publishAndReleaseToMavenCentral. Valid build config for a module that CI never tells to publish is indistinguishable, from the outside, from a module that doesn’t exist.
  • Create a Documentation/ folder with a toc.yml, an index.md, and a client-snippets/** tree from day one.
  • Add a snippet validator and a CI workflow that runs it before your first snippet ships.
  • Don’t write your own “Events” or “Projections” pages — those concepts live in the shared Chronicle docs. Your repo only owns pages that are genuinely different per client: installation, connection setup, framework integration, troubleshooting.
  • If your artifact serves two languages the way Kotlin serves Java, plan for two parallel snippet trees (client-snippets/, client-snippets-<other-language>/) from the start. See Documentation and snippets.

Next: Two ways to start walks through the first decision in more depth.