Skip to content

docs(integration-toolkit): add the interactive registration recipe - #166

Open
karlrank wants to merge 4 commits into
mainfrom
docs/interactive-registration
Open

karlrank wants to merge 4 commits into
mainfrom
docs/interactive-registration

Conversation

@karlrank

@karlrank karlrank commented Oct 9, 2026 •

Copy link
Copy Markdown
Member

What

Documents the Interactive Inbound Lane for integration partners: an "Interactive registration" recipe under the Integration Toolkit, plus the reference updates that go with it.

New page — docs/integrations/integration-toolkit/interactive-registration.md:

  • The problem, from the integrator's side. Today's advice is implicitly "push during the portal's poll window and hope". The portal polls entity search blind and cannot tell "not yet" from "never", which is why support tickets of this class exist and why none of them can be investigated afterwards.
  • The flow as a Mermaid sequence diagram: the portal mints a correlation id and passes it to the extension hook, the partner pushes with it, the portal waits on the correlation.
  • The partner minimum: two fields on the push — the portal's correlation_id and interactive: true — and nothing in the hook response. Returning the id from the hook is documented as optional (only for partners that push under an id of their own). correlation_complete: true on the last request is strongly recommended, never required.
  • The two failure patterns: customer found but bundle incomplete → push what exists and close the correlation in the same request; customer not found → answer the hook with an error and push nothing.
  • Request and response examples for POST /v3/erp/updates/events and the three read endpoints — one event, the correlation wait, and the correlations listing (GET /v3/erp/updates/correlations, newest first, 7-day horizon).
  • The correlation wait's two requirement sets, wait_for_entities and wait_for_use_cases: what "arrived" means, the selector rule (a selector may only name a member of the target's configured unique_ids), the selector syntax, the configuration rule for use case requirements (one use case per partner event type, every use case with a slug), and partial results — every requirement is met by the first matching event, so only correlation_complete says nothing further is coming.
  • The use case option interactive: disabled | on_request | always.
  • Rate limiting, honestly: over budget, the events run on the org's normal lane, the wait still works, it is just slower, and a monitoring warning is raised.
  • Event-stream partners (Kafka and similar): echo the id as a CloudEvents extension as the minimum, terminal event and full event set as improvements.
  • What not to do: wait on ingest (400), calling the wait from inside the hook, opening a correlation for a customer you could not find, selecting on an attribute that is not a configured unique id.
  • Monitoring: all ten codes with their levels.

Reference updates, slotted into the existing information architecture:

File Change
integration-toolkit/use-cases.md Inbound quick-reference row + an "Interactive Registration" use case section linking to the recipe
integration-toolkit/overview.md Component table row and a pointer in the Inbound direction section
integration-toolkit/configuration.md New "Inbound Use Case Options" table covering direct and interactive, plus the use case modelling rule
integration-toolkit/inbound/getting-started.md Note that ingestion is asynchronous, plus a Next Steps entry

Navigation is autogenerated from the directory, so the new page appears under Integrations → Integration Toolkit between Use Cases and Mapping Examples (sidebar_position: 5).

Why

Registrations that time out today do so silently: the portal's entity-search poll returns nothing whether the push is queued, arrived without a contract, or was never sent. Nothing records which it was. The recipe replaces that with a contract an integrator can implement with two fields on the push and a status endpoint that answers the only question that matters — did the data land, and if not, what was missing.

Related

  • Specification: Interactive Inbound Lane RFC — integration-toolkit-api MR !278
  • The API documented here ships in the integration-toolkit-api MR stack (feat/interactive-inbound-lane). This docs PR merges after those, so the page does not describe fields the API still rejects. The page carries an "Availability — rolling out" admonition in the meantime.
  • The runnable reference, erpilot-integration, is being updated in parallel and is linked from the page.

Checks

  • npm run build (what CI runs) is clean on a fresh npm ci checkout of this branch — 293 doc pages, no broken links; every new in-page anchor resolves in the built HTML.
  • No src changes, so the repo's existing npm run lint findings are untouched.

Follow-ups (not in this PR)

  • monitoring/codes.md is autogenerated from the backend snapshot. The ten interactive codes (INTERACTIVE_RATE_LIMITED, INTERACTIVE_NOT_ALLOWED, INTERACTIVE_CROSS_LANE_WRITE, CORRELATION_COMPLETED, CORRELATION_CLOSED_EMPTY, CORRELATION_LATE_EVENT, CORRELATION_ID_MISSING, CORRELATION_REQUIREMENT_FAILED, CORRELATION_WAIT_TIMEOUT, CORRELATION_WAIT_REJECTED) are described on the recipe page and land in the reference via npm run update-monitoring-codes once the toolkit change is merged.

Karl Rankla added 4 commits October 9, 2026 14:32
The only guidance we gave an integration partner for portal self-registration
was implicit: push your data while the portal is still polling entity search,
and hope. That poll cannot tell "not yet" from "never", so a registration that
fails produces a generic timeout and a support ticket nobody can investigate
afterwards — not the partner, not epilot.

This documents the correlation-id contract that replaces it. The portal mints
an id and hands it to the extension hook, the partner returns it and sends it
on every push for that customer, and the portal waits on that correlation
instead of searching blind. The recipe states the minimum ask in two lines
before anything else, then the optional interactive lane and completion flag,
the request and response contract for the ingest call and both status
endpoints, the two requirement sets of the correlation wait and when to use
which, the `interactive` use case option, what the rate limit actually does to
an org that exceeds it, the event-stream variant, and the two things not to do.

The reference updates slot it into the existing structure rather than beside
it: a quick-reference row and a use case section in Use Cases, the component
table and the inbound direction in the Overview, a new inbound use case
options table in Configuration, and a pointer from the inbound Getting
Started where the asynchronous response is first explained.

Documents the Interactive Inbound Lane RFC (integration-toolkit-api !278).
The API described here ships in the toolkit MR stack, so this merges after it.
An event-stream bridge whose terminal marker arrives alone in a batch has
no data to send with the close, so it closes the correlation with an empty
events array. That is the one case in which the ingest endpoint accepts one;
without correlation_complete an empty events array is still a 400. Spelling
out both halves, because the asymmetry is otherwise only discoverable by
getting the error.
…nal contract

The recipe was written against an earlier draft of the API. Several
things have since been decided or found to be wrong, and an integrator
building against the old page would ship code that silently never works.

- The partner minimum is two fields on the push: the portal's
  correlation_id and interactive: true. Processing is only recorded for
  interactive events, so the id alone leaves nothing to wait on.
  Returning the id from the hook is optional, needed only when a partner
  pushes under an id of its own, because the portal waits on the id it
  minted when the hook returns none.
- A requirement is met by the first matching event. Without
  correlation_complete a wait can answer requirements_met while more of
  the customer's data is still arriving, so the flag is presented as
  strongly recommended and never required, with a worked example of
  where several use cases help and where one use case firing twice
  needs a selector instead.
- A selector can only name a member of the target's configured
  unique_ids, because that is all the response carries per entity; any
  other attribute never matches and fails silently. The examples now
  select on configured unique ids only, and the claim that the identity
  id is returned and that bundles carry a separate billing contact is
  gone, as both were verified false.
- Use case requirements are only as fine-grained as the use case
  configuration: one inbound use case per partner event type, each with
  a slug, or the requirement cannot tell messages apart or cannot be
  named at all.
- The correlations listing is its own endpoint,
  GET /v3/erp/updates/correlations, newest first with a declared 7-day
  horizon.
- Response field names follow the final schema (mapped_at, writes_total,
  writes_done, the use_cases list, the errors[] item shape,
  first_ingested_at and last_done_at), and the close, wait-range and
  completion rules follow the decided behaviour.
- Monitoring lists the five added codes, CORRELATION_WAIT_TIMEOUT is a
  warning carrying missing_entities and missing_use_cases, and
  CORRELATION_CLOSED_EMPTY is info, so a partner that correctly reports
  "no data" never alerts louder than a user who waited for nothing.
- The two partner failure patterns are documented: customer found but
  bundle incomplete pushes what exists and closes in the same request;
  customer not found answers the hook with an error and pushes nothing.
…d rules and the new codes

Partners that push in parallel close with a zero-event request once
every push is accepted; sequential pushers keep the close on the last
request. A correlation id is unique per identification, 1-255 characters
of [A-Za-z0-9_-] on waitable requests, and holds at most 32 events. A
selector key outside the configured unique ids is now a 400. Monitoring
lists CORRELATION_CLOSE_IGNORED, CORRELATION_CLOSED_INCOMPLETE and
CORRELATION_EVENT_LIMIT_EXCEEDED, and the timeout counts once per
correlation.

This branch has not been deployed

No deployments
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.

1 participant