Skip to content
Back to skills

Add Inbound Event

ASecurity

TRIGGER when user asks to listen for, subscribe to, or handle an event from another microservice. Wires up the event sink handler. Affects intermediate.go, mock.go, manifest.yaml.

  • 172 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added June 6, 2026
testinggoexpresstestinggitapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned June 6, 2026

npx -y skills add microbus-io/fabric --skill add-inbound-event --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Inbound Event?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Add Inbound Event
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/microbus-io-add-inbound-event/badge)](https://www.skillsdirectory.com/skills/microbus-io-add-inbound-event)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: add-inbound-event
description: TRIGGER when user asks to listen for, subscribe to, or handle an event from another microservice. Wires up the event sink handler. Affects intermediate.go, mock.go, manifest.yaml.
---

**CRITICAL**: Do NOT explore or analyze other microservices unless explicitly instructed to do so. The instructions in this skill are self-contained to this microservice.

**CRITICAL**: Do not omit the `MARKER` comments when generating the code. They are intended as waypoints for future edits.

**CRITICAL**: Inbound event sinks are not exposed via OpenAPI (only functional, web, and workflow endpoints are). The connector's built-in `:888/openapi.json` handler enforces this filter automatically - there is nothing to configure in this skill.

## Workflow

Copy this checklist and track your progress:

```
Creating or modifying a sink endpoint:
- [ ] Step 1: Read local CLAUDE.md file
- [ ] Step 2: Locate the source of the outbound event and determine signature
- [ ] Step 3: Determine a description
- [ ] Step 4: Determine the required claims
- [ ] Step 5: Extend the ToDo interface
- [ ] Step 6: Implement the inbound event sink logic
- [ ] Step 7: Bind the inbound event sink to the microservice
- [ ] Step 8: Regenerate the mock
- [ ] Step 9: Test the inbound event sink
- [ ] Step 10: Housekeeping
```

#### Step 1: Read Local `CLAUDE.md` File

Read the local `CLAUDE.md` file in the microservice's directory. It contains microservice-specific instructions that should take precedence over global instructions.

#### Step 2: Locate the Source of the Outbound Event and Determine Signature

Locate the `Hook` in the API directory of the microservice that is the source of the event. Determine the signature of the outbound event.

```go
func OnMyEvent(ctx context.Context, input1 string, input2 ThirdPartyStruct) (output1 map[string]MyStruct, err error)
```

#### Step 3: Determine a Description

Pull the event description from the `Hook`. Embed this description in followup steps instead of the placeholder `OnMyEvent is triggered when X`.

#### Step 4: Determine the Required Claims

Determine if the endpoint should be restricted to authorized actors only. Compose a boolean expression over the JWT claims associated with the request that if not met will cause the request to be denied. For example: `roles.manager && level>2`. Leave empty if the endpoint should be accessible by all.

#### Step 5: Extend the `ToDo` Interface

Extend the `ToDo` interface in `intermediate.go`.

```go
type ToDo interface {
	// ...
	OnMyEvent(ctx context.Context, input1 string, input2 eventsourceapi.ThirdPartyStruct) (output1 map[string]eventsourceapi.MyStruct, err error) // MARKER: OnMyEvent
}
```

#### Step 6: Implement the Inbound Event Sink Logic

Implement the inbound event sink in `service.go`. Complex types should always refer to their definition in `eventsourceapi`, even if owned by a third-party.

```go
/*
OnMyEvent is triggered when X.
*/
func (svc *Service) OnMyEvent(ctx context.Context, input1 string, input2 eventsourceapi.ThirdPartyStruct) (output1 map[string]eventsourceapi.MyStruct, err error) { // MARKER: OnMyEvent
	// Implement logic here...
	return
}
```

#### Step 7: Bind the Inbound Event Sink to the Microservice

Use the event source's `Hook` to bind the inbound event sink to the microservice in the `NewIntermediate` constructor in `intermediate.go`, after the corresponding `HINT` comment. If other bindings already exist under this HINT, add the new one after the last existing binding.

- The queue option indicate how requests are distributed among replicas of the microservice
  - `sub.DefaultQueue()`: requests are load balanced among peers and processed by only one. This is the default option and may be omitted
  - `sub.NoQueue()`: requests are processed by all subscribers
  - `sub.Queue(queueName)`: requests are load balanced among peers associated with this queue name. Subscribers associated with other queue names receive the requests separately based on their own queue option
- The `sub.RequiredClaims(requiredClaims)` option defines the authorization requirements of the endpoint. This option can be omitted to allow all requests
- Pass queue and claims options via `WithOptions`, not as arguments to the event method
- The return values of the `Hook` method are discarded by intent

```go
func NewIntermediate(impl ToDo) *Intermediate {
	// ...
	eventsourceapi.NewHook(svc).OnMyEvent(svc.OnMyEvent) // MARKER: OnMyEvent
	// ...
}
```

If the endpoint requires a non-default queue or required claims, chain `WithOptions` before the event method:

```go
eventsourceapi.NewHook(svc).WithOptions(sub.NoQueue()).OnMyEvent(svc.OnMyEvent) // MARKER: OnMyEvent
```

```go
eventsourceapi.NewHook(svc).WithOptions(sub.RequiredClaims(requiredClaims)).OnMyEvent(svc.OnMyEvent) // MARKER: OnMyEvent
```

Add the appropriate import to `github.com/company/project/eventsource/eventsourceapi`.

#### Step 8: Regenerate the Mock

Run `go run github.com/microbus-io/fabric/cmd/genmock --path .` from the microservice's directory. This regenerates both `mock.go` and `mock_test.go`.

#### Step 9: Test the Inbound Event Sink

Append the integration test to `service_test.go`.

```go
func TestMyService_OnMyEvent(t *testing.T) { // MARKER: OnMyEvent
	t.Parallel()
	ctx := t.Context()
	_ = ctx

	// Initialize the microservice under test
	svc := NewService()

	// Initialize the testers
	tester := connector.New("tester.client")
	eventsourceTrigger := eventsourceapi.NewMulticastTrigger(tester)
	_ = eventsourceTrigger

	// Run the testing app
	app := application.New()
	app.Add(
		// HINT: Add microservices or mocks required for this test
		svc,
		tester,
	)
	app.RunInTest(t)

	/*
		HINT: Use the following pattern for each test case

		t.Run("test_case_name", func(t *testing.T) {
			assert := testarossa.For(t)

			actor := jwt.MapClaims{}
			for e := range eventsourceTrigger.WithOptions(pub.Actor(actor)).OnMyEvent(ctx, input1, input2) {
				output1, err := e.Get()
				if frame.Of(e.HTTPResponse).FromHost() == svc.Hostname() {
					assert.Expect(
						output1, expectedResult1,
						err, nil,
					)
				}
			}
		})
	*/
}
```

Skip the remainder of this step if instructed to be "quick" or to skip tests.

Insert test cases at the bottom of the integration test function using the recommended pattern.

- You may omit the `pub.Actor` option if the inbound event does not require claims.
- Do not remove the `HINT` comments.

```go
t.Run("test_case_name", func(t *testing.T) {
	assert := testarossa.For(t)

	actor := jwt.MapClaims{}
	for e := range eventsourceTrigger.WithOptions(pub.Actor(actor)).OnMyEvent(ctx, input1, input2) {
		output1, err := e.Get()
		if frame.Of(e.HTTPResponse).FromHost() == svc.Hostname() {
			assert.Expect(
				output1, expectedResult1,
				err, nil,
			)
		}
	}
})
```

#### Step 10: Housekeeping

Follow the `housekeeping` skill.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.