@cfxlabsinc/eventsThe central event registries and their publishers. See docs/proposals/EVENT_BUS.md for the design.
| Subpath | Contents |
|---|---|
./sns |
SnsEventPublisher, the envelope, message attributes |
./customer |
The customer-facing registry and CustomerEventPublisher |
./internal |
The internal registry and InternalEventPublisher |
./docs |
Per-event documentation + the public webhook page generator |
./docs is separate from ./customer on purpose: every Lambda that publishes an event loads the ./customer barrel, and none of them needs the prose, the ReadMe slugs, or node:fs.
https://docs.cfx.to/docs/webhook-events is generated from src/customer/registry.ts.
main deploy that touches this package overwrites it.src/docs/webhook-events.template.md. Everything below its <!-- events --> marker is generated.src/docs/customerEventDocs.ts: a one-line summary, the ReadMe ref: slug(s) for the GET that returns the object's current state, and optional notes. Event names, entity scopes, and every field and enum member of data are read from the registry, so they cannot drift.customerEventDocs is typed Record<CustomerEventName, EventDoc>. Registering an event without documenting it fails nx run events:typecheck — that is the mechanism that keeps the page complete.Set hiddenReason on its EventDoc and the page omits it — from the summary table, the payload sections, and the count. Five events are withheld today; webhookDocs.test.ts locks that set, so adding to or removing from it is a deliberate edit.
docs.cfx.to shows.exhaustive never reaches the page.| Task | Command |
|---|---|
Render to dist/docs/readme/ |
nx run events:gen-webhook-docs |
| Check ReadMe accepts it (needs API key) | nx run events:validate-webhook-docs |
| Upload (CI only) | nx run events:publish-webhook-docs |
CI wiring mirrors the OpenAPI specs: pr.yml runs the dry-run validate, main.yml's Publish Specs & Guides job uploads with README_API_KEY. ReadMe's bidirectional git sync mirrors the uploaded page back into CFXLabsInc/cfx-b2b-platform-docs at docs/Conventions/webhook-events.md; nothing in this repo pushes to that repo directly.
rdme docs upload actually doesThree behaviours of rdme@10 this wiring depends on, from node_modules/rdme/dist/lib/syncPagePath.js and readPage.js:
frontmatter.slug or, absent that, the lowercased file name. The template pins slug: webhook-events explicitly so renaming the file can never orphan the live page and create a second one.GETs /guides/<slug> first: 404 → POST (create), otherwise PATCH (update). The PATCH body carries only the frontmatter keys present plus the content, so the page's category is untouched — that is why the template declares no category and the page stays under Conventions.--confirm-autofixes to the publish target; a page ReadMe wants to rewrite should fail the build and be fixed in the template.The markdown files ReadMe's git sync writes into cfx-b2b-platform-docs are v1 shaped. rdme docs upload PATCHes the v2 API, whose schema is additionalProperties: false and rejects the v1 keys outright. Copying front matter out of the synced repo is the obvious move and it does not work:
| v1 — what git sync exports | v2 — what rdme docs upload requires |
|---|---|
hidden: false |
privacy: { view: public } |
deprecated: false |
state: current |
metadata: { robots: index } |
allow_crawlers: enabled |
The v2 root key set is allow_crawlers, appearance, category, content, metadata, parent, position, privacy, slug, state, title, type. metadata survives but holds only title / description / image / keywords / x_import — never robots.
rdme autofixes hidden and deprecated but not metadata.robots, and it refuses to autofix anything under CI, so the whole file fails the upload with 1 file(s) have issues that should be fixed before uploading. webhookDocs.test.ts asserts the v2 keys are present and that no v1 key survives, so this is caught by nx run events:test — no API key, no network — rather than on a PR.
To reproduce rdme's validation offline: fetchSchema() reads a bundled OAS (node_modules/rdme/dist/lib/types/openapiDoc.js, path /branches/{branch}/guides/{slug} → patch → request body schema), so the same ajv pass runs with no credentials. It is not an exported subpath of the package, which is why the test asserts the key shape directly instead of importing it.
src/customer/registry.ts.EXPECTED_EVENT_NAMES in test/customerRegistry.test.ts and bump the count.customerEventDocs. Typecheck fails until you do.A ReadMe slug is the markdown filename under reference/ in the docs repo, minus the extension — those files are generated by ReadMe from the OpenAPI specs main.yml uploads, so a slug changes only when an operation's method or path changes.