Skip to content

Network connectors (Lambda Core service) - #37

Merged
lex00 merged 1 commit into
mainfrom
feature/13-connectors
Jul 31, 2026
Merged

lex00 merged 1 commit into
mainfrom
feature/13-connectors

Conversation

@lex00

@lex00 lex00 commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

All five Lambda Core operations, the PENDING → ACTIVE state machine on the clock, the asynchronous DELETING window, and an injection lever for each of the seven reason codes. Based on main.

Connectors are a second service model, not a second resource: different API version, different URI family, and PascalCase members where Lambda Microvms uses lowercase.

Three things the model would have led me to get wrong

All three surfaced by running the recorded fixtures against a real implementation — the same class the handoff warned about, and the reason I ran conformance before believing any of it.

Bad requests come back two ways. Model constraints — list lengths, enum membership — are answered by a validation layer in front of the service, as ValidationException in AWS's standard wording, with the member path in camelCase even though every wire member is PascalCase:

1 validation error detected: Value '[subnet-…, …]' at
'configuration.vpcEgressConfiguration.subnetIds' failed to satisfy constraint:
Member must have length less than or equal to 16

ValidationException is not listed as an error of any connector operation in the Lambda Core model. The four enforced-but-modeled-optional members are service logic instead, and come back as InvalidParameterValueException with prose.

That layer runs first, and in full. Precedence was the one thing I had assumed was m80's to choose. It isn't. The too-many-subnets probe sent seventeen subnets and omitted ClientToken, OperatorRole, NetworkProtocol and AssociatedComputeResourceTypes — four of the enforced members missing — and the service still answered about subnetIds. validate now runs constraints to exhaustion before the service's required-member logic gets a look.

Not-found uses a capital Message — Lambda Core's own member style, not the lowercase message the other service uses — and echoes the ARN it built from whatever identifier arrived rather than the identifier itself.

Modeled optional, enforced anyway

ClientToken, OperatorRole, NetworkProtocol, AssociatedComputeResourceTypes. A client written from the model alone gets four 400s in a row. ClientToken is the strangest: the model marks it optional and tags it idempotencyToken, which normally means the SDK generates one for you.

Response shapes

Four responses, four different member sets — the model, not an accident of recording. Create and Delete return a base six; Get adds LastModified and the state/update status members; Update adds LastModified and update status but not StateReason; only the list summary carries Type. Absent means absent: a connector that has never been updated has no LastUpdateStatus at all, and emitting one as null would diverge on every read. List omits NextMarker entirely, so a client looping until the marker is null would loop forever.

The injection lever

The seven NetworkConnectorStateReasonCode values are the point. None can be provoked against real AWS on demand — you cannot ask EC2 to run a subnet out of addresses — so without injection a consumer's whole error-handling path stays untested, and KubeMicroVM's MicroVMNetwork reconciler has visible handling for them. One test per code; the lever is consumed on use so one failing connector does not poison a suite running several.

It is a Go API, matching the images build lever. I deliberately did not add m80-only cases to the conformance suite — that suite is a fidelity instrument measured against real AWS, and injected failures have no recorded fixture and never could. The acceptance's "one injected failure per reason code" is met by unit tests. If you want the lever drivable over HTTP for #18's offline drift UAT, that is a small addition and probably belongs with the rest of the drift levers.

Result

66 pass, 0 fail, 27/29 operations exercised, up from 58 and 24. Only ListTags and UntagResource remain, both #14. go build, go vet, gofmt, go test -race clean.

Closes #13

All five Lambda Core operations, the PENDING to ACTIVE state machine on the
clock, the asynchronous DELETING window, and an injection lever for each of
the seven reason codes.

Connectors are a second service model, not a second resource: different
API version, different URI family, and PascalCase members where Lambda
Microvms uses lowercase. One m80 process serves both because both sign as
lambda.

Four members are modeled optional and enforced anyway — ClientToken,
OperatorRole, NetworkProtocol and AssociatedComputeResourceTypes, each
recorded live. A client written from the model alone gets four 400s in a
row. ClientToken is the strangest of them: the model marks it optional and
tags it idempotencyToken, which normally means the SDK generates one.

Three findings came out of running the fixtures against a real
implementation, all of them things the model would have led me to get
wrong.

Bad requests come back two ways. Model constraints — list lengths, enum
membership — are answered by a validation layer in front of the service, as
ValidationException in AWS's standard wording, with the member path in
camelCase even though every wire member is PascalCase. ValidationException
is not listed as an error of any connector operation in the model. The four
enforced-but-optional members are service logic and come back as
InvalidParameterValueException with prose.

That layer runs first and in full. The too-many-subnets probe sent
seventeen subnets and also omitted ClientToken, OperatorRole,
NetworkProtocol and AssociatedComputeResourceTypes, and the service still
answered about subnetIds. Precedence was the one thing I had assumed was
m80's to choose; it is recorded. validate now runs constraints to
exhaustion before the service's required-member logic gets a look.

Not-found answers with a capital Message, matching Lambda Core's own member
style rather than the lowercase message the other service uses, and echoes
the ARN it built from whatever identifier arrived rather than the
identifier itself.

The four responses carry four different member sets, which is the model
rather than an accident of recording, and absent means absent: a connector
that has never been updated has no LastUpdateStatus at all. List omits
NextMarker entirely, so a client looping until the marker is null would
loop forever. Type is on the list summary and nowhere else.

The seven reason codes are the point of the lever. None can be provoked
against real AWS on demand — you cannot ask EC2 to run a subnet out of
addresses — so without injection a consumer's whole error path stays
untested. One test per code, and the lever is consumed on use so one
failing connector does not poison a suite running several.

Conformance: 66 pass, 0 fail, 27 of 29 operations exercised, up from 58 and
24. Only ListTags and UntagResource remain, both #14.

Closes #13

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X6T4MeDN1RBiWaNtud6x77
@lex00
lex00 merged commit 042cf75 into main Jul 31, 2026
2 checks passed
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.

Network connectors (Lambda Core service)

1 participant