Skip to content

Commit 41f6553

Browse files
authored
feat: implement AsyncAPI generation script and specs (#1317)
* feat: add AsyncAPI 3.0.0 generation script and specs Add gen-asyncapi.sh that reads the Kafka topic registry (topics.yaml) and proto event definitions to produce one AsyncAPI 3.0.0 YAML file per BIAN service domain. The script extracts schema properties from proto message definitions, infers partition keys as Kafka message binding keys, and correctly excludes deprecated topics. Generated specs cover all 9 service domains: audit, current-account, financial-accounting, internal-account, market-information, party, payment-order, position-keeping, and reconciliation. Add `make asyncapi` target to Makefile. * fix: address review feedback on gen-asyncapi.sh Add python3 dependency check alongside yq check. Add payment_order_id to the describe_partition_key case statement for human-readable Kafka key descriptions. Regenerate payment-order.yaml with updated descriptions. * fix: emit warning for unresolved proto messages instead of silent fallback When a proto message cannot be resolved, the script now emits a warning to stderr rather than silently writing placeholder schemas. This makes source-of-truth drift visible in CI output while still generating structurally valid YAML for partial specs. * fix: preserve repeated-field element types and warn on parse failures Capture element type from proto repeated fields so array schemas emit the correct items type (integer, number, boolean) instead of always defaulting to string. Also emit a warning to stderr when field JSON parsing fails instead of silently falling back to placeholder schemas. --------- Co-authored-by: Ben Coombs <bjcoombs@users.noreply.github.com>
1 parent 31c9990 commit 41f6553

11 files changed

Lines changed: 2472 additions & 1 deletion

Makefile

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ GOMOD=$(GOCMD) mod
3232
GOGET=$(GOCMD) get
3333
GOFMT=$(GOCMD) fmt
3434

35-
.PHONY: all help build seed-dev seed-dev-build test lint clean proto proto-v1 proto-v2 proto-openapi proto-lint proto-breaking proto-descriptors docker deploy-local fmt tidy deps coverage install proto-validate proto-deps-update proto-deps-graph proto-plugins-info validate-tilt validate-semconv validate-sagas proto-jsonschema validate-manifest-jsonschema validate-manifests control-plane-ci test-control-plane migrate-diff-all migrate-diff-current migrate-diff-position migrate-apply-all migrate-status-all migrate-lint-all migrate-hash-all migrate-apply-orgs migrate-status-orgs docs generate-saga-docs swagger-split swagger-ui dev-up dev-down dev-clean
35+
.PHONY: all help build seed-dev seed-dev-build test lint clean proto proto-v1 proto-v2 proto-openapi proto-lint proto-breaking proto-descriptors docker deploy-local fmt tidy deps coverage install proto-validate proto-deps-update proto-deps-graph proto-plugins-info validate-tilt validate-semconv validate-sagas proto-jsonschema validate-manifest-jsonschema validate-manifests control-plane-ci test-control-plane migrate-diff-all migrate-diff-current migrate-diff-position migrate-apply-all migrate-status-all migrate-lint-all migrate-hash-all migrate-apply-orgs migrate-status-orgs docs generate-saga-docs swagger-split swagger-ui dev-up dev-down dev-clean asyncapi
3636

3737
# Default target
3838
all: help
@@ -490,6 +490,12 @@ generate-saga-docs:
490490
@go run tools/saga-doc-gen/main.go tools/saga-doc-gen/generator.go -schema-dir=shared/pkg/saga/schema -output-dir=docs
491491
@echo "Documentation generated successfully"
492492

493+
## asyncapi: Generate AsyncAPI 3.0.0 specs from topic registry and proto definitions
494+
asyncapi:
495+
@echo "Generating AsyncAPI specs..."
496+
@./scripts/gen-asyncapi.sh
497+
@echo "AsyncAPI specs generated in api/asyncapi/"
498+
493499
## validate-manifests: Validate example manifests against protobuf schema, CEL, and Starlark
494500
validate-manifests:
495501
@echo "Validating example manifests..."

api/asyncapi/audit.yaml

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
asyncapi: 3.0.0
2+
info:
3+
title: "Audit Events"
4+
version: 1.0.0
5+
description: "Audit trail events for compliance and observability"
6+
servers:
7+
kafka:
8+
host: kafka:9092
9+
protocol: kafka
10+
channels:
11+
audit.events.v1:
12+
address: "audit.events.v1"
13+
description: "Audit events for all service operations"
14+
messages:
15+
AuditEvent:
16+
$ref: '#/components/messages/AuditEvent'
17+
audit.events.v1.dlq:
18+
address: "audit.events.v1.dlq"
19+
description: "Dead letter queue for audit events that could not be processed"
20+
operations:
21+
publishEvents:
22+
action: send
23+
channel:
24+
$ref: '#/channels/audit.events.v1'
25+
publishEventsDlq:
26+
action: send
27+
channel:
28+
$ref: '#/channels/audit.events.v1.dlq'
29+
components:
30+
messages:
31+
AuditEvent:
32+
name: "AuditEvent"
33+
title: "AuditEvent"
34+
description: "Audit events for all service operations"
35+
contentType: application/protobuf
36+
headers:
37+
type: object
38+
properties:
39+
event_type:
40+
type: string
41+
description: Logical event type identifier
42+
correlation_id:
43+
type: string
44+
format: uuid
45+
description: Links related events across services
46+
tenant_id:
47+
type: string
48+
description: Tenant identifier for multi-tenant isolation
49+
payload:
50+
$ref: '#/components/schemas/AuditEvent'
51+
schemas:
52+
AuditEvent:
53+
type: object
54+
description: "Derived from protobuf message meridian.events.v1.AuditEvent"
55+
properties:
56+
event_type:
57+
type: string
58+
description: "Proto definition not yet available in api/proto/meridian/events/v1/"

api/asyncapi/current-account.yaml

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,248 @@
1+
asyncapi: 3.0.0
2+
info:
3+
title: "Current Account Events"
4+
version: 1.0.0
5+
description: "Account lifecycle and withdrawal events for current (demand deposit) accounts"
6+
servers:
7+
kafka:
8+
host: kafka:9092
9+
protocol: kafka
10+
channels:
11+
current-account.account-frozen.v1:
12+
address: "current-account.account-frozen.v1"
13+
description: "Published when an account is frozen (no debits or credits permitted)"
14+
messages:
15+
AccountFrozenEvent:
16+
$ref: '#/components/messages/AccountFrozenEvent'
17+
current-account.account-unfrozen.v1:
18+
address: "current-account.account-unfrozen.v1"
19+
description: "Published when a previously frozen account is unfrozen"
20+
messages:
21+
AccountUnfrozenEvent:
22+
$ref: '#/components/messages/AccountUnfrozenEvent'
23+
current-account.account-closed.v1:
24+
address: "current-account.account-closed.v1"
25+
description: "Published when an account is permanently closed"
26+
messages:
27+
AccountClosedEvent:
28+
$ref: '#/components/messages/AccountClosedEvent'
29+
current-account.withdrawal-status.v1:
30+
address: "current-account.withdrawal-status.v1"
31+
description: "Published when a withdrawal status changes (initiated, completed, failed, reversed)"
32+
messages:
33+
WithdrawalStatusUpdated:
34+
$ref: '#/components/messages/WithdrawalStatusUpdated'
35+
operations:
36+
publishAccountFrozen:
37+
action: send
38+
channel:
39+
$ref: '#/channels/current-account.account-frozen.v1'
40+
publishAccountUnfrozen:
41+
action: send
42+
channel:
43+
$ref: '#/channels/current-account.account-unfrozen.v1'
44+
publishAccountClosed:
45+
action: send
46+
channel:
47+
$ref: '#/channels/current-account.account-closed.v1'
48+
publishWithdrawalStatus:
49+
action: send
50+
channel:
51+
$ref: '#/channels/current-account.withdrawal-status.v1'
52+
components:
53+
messages:
54+
AccountFrozenEvent:
55+
name: "AccountFrozenEvent"
56+
title: "AccountFrozenEvent"
57+
description: "Published when an account is frozen (no debits or credits permitted)"
58+
contentType: application/protobuf
59+
bindings:
60+
kafka:
61+
key:
62+
type: string
63+
description: "Account ID"
64+
headers:
65+
type: object
66+
properties:
67+
event_type:
68+
type: string
69+
description: Logical event type identifier
70+
correlation_id:
71+
type: string
72+
format: uuid
73+
description: Links related events across services
74+
tenant_id:
75+
type: string
76+
description: Tenant identifier for multi-tenant isolation
77+
payload:
78+
$ref: '#/components/schemas/AccountFrozenEvent'
79+
AccountUnfrozenEvent:
80+
name: "AccountUnfrozenEvent"
81+
title: "AccountUnfrozenEvent"
82+
description: "Published when a previously frozen account is unfrozen"
83+
contentType: application/protobuf
84+
bindings:
85+
kafka:
86+
key:
87+
type: string
88+
description: "Account ID"
89+
headers:
90+
type: object
91+
properties:
92+
event_type:
93+
type: string
94+
description: Logical event type identifier
95+
correlation_id:
96+
type: string
97+
format: uuid
98+
description: Links related events across services
99+
tenant_id:
100+
type: string
101+
description: Tenant identifier for multi-tenant isolation
102+
payload:
103+
$ref: '#/components/schemas/AccountUnfrozenEvent'
104+
AccountClosedEvent:
105+
name: "AccountClosedEvent"
106+
title: "AccountClosedEvent"
107+
description: "Published when an account is permanently closed"
108+
contentType: application/protobuf
109+
bindings:
110+
kafka:
111+
key:
112+
type: string
113+
description: "Account ID"
114+
headers:
115+
type: object
116+
properties:
117+
event_type:
118+
type: string
119+
description: Logical event type identifier
120+
correlation_id:
121+
type: string
122+
format: uuid
123+
description: Links related events across services
124+
tenant_id:
125+
type: string
126+
description: Tenant identifier for multi-tenant isolation
127+
payload:
128+
$ref: '#/components/schemas/AccountClosedEvent'
129+
WithdrawalStatusUpdated:
130+
name: "WithdrawalStatusUpdated"
131+
title: "WithdrawalStatusUpdated"
132+
description: "Published when a withdrawal status changes (initiated, completed, failed, reversed)"
133+
contentType: application/protobuf
134+
bindings:
135+
kafka:
136+
key:
137+
type: string
138+
description: "Withdrawal ID"
139+
headers:
140+
type: object
141+
properties:
142+
event_type:
143+
type: string
144+
description: Logical event type identifier
145+
correlation_id:
146+
type: string
147+
format: uuid
148+
description: Links related events across services
149+
tenant_id:
150+
type: string
151+
description: Tenant identifier for multi-tenant isolation
152+
payload:
153+
$ref: '#/components/schemas/WithdrawalStatusUpdated'
154+
schemas:
155+
AccountFrozenEvent:
156+
type: object
157+
description: "Derived from protobuf message meridian.events.v1.AccountFrozenEvent"
158+
properties:
159+
event_id:
160+
type: string
161+
account_id:
162+
type: string
163+
reason:
164+
type: string
165+
frozen_at:
166+
type: string
167+
frozen_by:
168+
type: string
169+
correlation_id:
170+
type: string
171+
causation_id:
172+
type: string
173+
timestamp:
174+
type: string
175+
version:
176+
type: integer
177+
idempotency_key:
178+
type: string
179+
AccountUnfrozenEvent:
180+
type: object
181+
description: "Derived from protobuf message meridian.events.v1.AccountUnfrozenEvent"
182+
properties:
183+
event_id:
184+
type: string
185+
account_id:
186+
type: string
187+
unfrozen_at:
188+
type: string
189+
unfrozen_by:
190+
type: string
191+
correlation_id:
192+
type: string
193+
causation_id:
194+
type: string
195+
timestamp:
196+
type: string
197+
version:
198+
type: integer
199+
idempotency_key:
200+
type: string
201+
AccountClosedEvent:
202+
type: object
203+
description: "Derived from protobuf message meridian.events.v1.AccountClosedEvent"
204+
properties:
205+
event_id:
206+
type: string
207+
account_id:
208+
type: string
209+
closing_balance:
210+
type: string
211+
closure_reason:
212+
type: string
213+
closed_by:
214+
type: string
215+
closure_date:
216+
type: string
217+
correlation_id:
218+
type: string
219+
causation_id:
220+
type: string
221+
timestamp:
222+
type: string
223+
version:
224+
type: integer
225+
idempotency_key:
226+
type: string
227+
WithdrawalStatusUpdated:
228+
type: object
229+
description: "Derived from protobuf message meridian.events.v1.WithdrawalStatusUpdatedEvent"
230+
properties:
231+
event_id:
232+
type: string
233+
withdrawal_id:
234+
type: string
235+
account_id:
236+
type: string
237+
status:
238+
type: string
239+
correlation_id:
240+
type: string
241+
causation_id:
242+
type: string
243+
timestamp:
244+
type: string
245+
version:
246+
type: integer
247+
idempotency_key:
248+
type: string
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
asyncapi: 3.0.0
2+
info:
3+
title: "Financial Accounting Events"
4+
version: 1.0.0
5+
description: "Financial booking log control events"
6+
servers:
7+
kafka:
8+
host: kafka:9092
9+
protocol: kafka
10+
channels:
11+
financial-accounting.booking-log-controlled.v1:
12+
address: "financial-accounting.booking-log-controlled.v1"
13+
description: "Published when a booking log receives a control action (SUSPEND, RESUME, TERMINATE)"
14+
messages:
15+
BookingLogControlledEvent:
16+
$ref: '#/components/messages/BookingLogControlledEvent'
17+
operations:
18+
publishBookingLogControlled:
19+
action: send
20+
channel:
21+
$ref: '#/channels/financial-accounting.booking-log-controlled.v1'
22+
components:
23+
messages:
24+
BookingLogControlledEvent:
25+
name: "BookingLogControlledEvent"
26+
title: "BookingLogControlledEvent"
27+
description: "Published when a booking log receives a control action (SUSPEND, RESUME, TERMINATE)"
28+
contentType: application/protobuf
29+
headers:
30+
type: object
31+
properties:
32+
event_type:
33+
type: string
34+
description: Logical event type identifier
35+
correlation_id:
36+
type: string
37+
format: uuid
38+
description: Links related events across services
39+
tenant_id:
40+
type: string
41+
description: Tenant identifier for multi-tenant isolation
42+
payload:
43+
$ref: '#/components/schemas/BookingLogControlledEvent'
44+
schemas:
45+
BookingLogControlledEvent:
46+
type: object
47+
description: "Derived from protobuf message meridian.events.v1.BookingLogControlledEvent"
48+
properties:
49+
event_type:
50+
type: string
51+
description: "Proto definition not yet available in api/proto/meridian/events/v1/"

0 commit comments

Comments
 (0)