4.6 KiB
id, name, status, depends_on, scope, risk, impact, level
| id | name | status | depends_on | scope | risk | impact | level | |
|---|---|---|---|---|---|---|---|---|
| call-envelope-integration | Update PendingRequestMap and CallHandler for ResponseEnvelope | completed |
|
broad | medium | project | implementation |
Description
Update src/call.ts to integrate ResponseEnvelope throughout the call protocol. This covers all changes documented in call-protocol.md and api-surface.md's "Source vs. Spec Drift" sections for ADR-005.
Changes needed:
CallEventSchema["call.responded"]
- Change
outputfromType.Unknown()toResponseEnvelopeSchema
PendingRequestMap.respond()
- Add
isResponseEnvelope()guard — throws ifoutputis not a valid envelope - This enforces the invariant that all call protocol responses carry source metadata
PendingRequestMap.call()
- Return type changes from
Promise<unknown>toPromise<ResponseEnvelope> - Resolution: the
call.respondedsubscription handler resolves with theResponseEnvelopefromoutputfield (which is already validated byrespond())
CallHandler
- Handler model change: Handler returns a value;
CallHandlerwraps and publishes. Handler does NOT publishcall.respondeditself. - Capture handler return value
- Apply shared result pipeline:
- Detect:
isResponseEnvelope(result)→ pass through - Wrap:
localEnvelope(result, operationId) - Normalize:
Value.Cast(spec.outputSchema, envelope.data)whenoutputSchema !== Type.Unknown() - Validate:
collectErrorsonenvelope.data— warning-only
- Detect:
- Publish
call.respondedviacallMap.respond(requestId, envelope) - On handler exception:
mapError()converts toCallError, publishcall.error
Note: Access control in CallHandler stays as-is (checking identity and checkAccess). ADR-006's change to make CallHandler call execute() is a separate task.
Acceptance Criteria
CallEventSchema["call.responded"].outputisResponseEnvelopeSchemaPendingRequestMap.respond()validatesoutputwithisResponseEnvelope(), throws on raw valuesPendingRequestMap.call()return type isPromise<ResponseEnvelope>CallHandlercaptures handler return value instead of discarding itCallHandlerapplies result pipeline: detect → wrap → normalize → validateCallHandlerpublishescall.respondedviacallMap.respond()with the envelopeCallHandleron handler exception publishescall.error(not re-throws)- Adapter handlers (pre-built envelopes via
mcpEnvelope/httpEnvelope) pass through viaisResponseEnvelope() - Existing
call.test.tstests updated for new return types and behavior - New tests for: envelope validation in
respond(), envelope wrapping inCallHandler, envelope passthrough, Value.Cast normalization npm run buildpassesnpm run lintpassesnpm testpasses
References
- docs/architecture/call-protocol.md § Source vs. Spec Drift (ADR-005 items)
- docs/architecture/api-surface.md § Source vs. Spec Drift (ADR-005 items)
- docs/architecture/response-envelopes.md § CallHandler, § PendingRequestMap
- src/call.ts
Notes
CallHandlerConfig changed from { registry, eventTarget? } to { registry, callMap? } to support publishing call.responded via callMap.respond(). When callMap is not provided, errors are thrown directly (backward-compatible for direct use without the call protocol).
Value.Cast in TypeBox does not strip excess properties from objects — it only fills defaults and upcasts values. The test was updated to verify default-filling behavior rather than property stripping.
Summary
Integrated ResponseEnvelope throughout the call protocol in src/call.ts.
- Modified:
src/call.ts(52 lines changed)CallEventSchema["call.responded"].output→ResponseEnvelopeSchemaPendingRequest.call()→Promise<ResponseEnvelope>PendingRequestMap.respond()→ validates withisResponseEnvelope(), throws on raw valuesCallHandler→ captures return value, applies detect→wrap→normalize→validate pipeline, publishes viacallMapCallHandlerConfig→{ registry, callMap? }replacingeventTarget?- Added imports:
KindGuard,Value,collectErrors,formatValueErrors,ResponseEnvelopeSchema,isResponseEnvelope,localEnvelope
- Modified:
test/call.test.ts(547 lines added)- Updated existing tests to pass
ResponseEnvelopetorespond() - Added 23 new tests: envelope validation in
respond(), envelope wrapping inCallHandler, envelope passthrough (mcp/http),Value.Castnormalization, error publishing, and no-callMap fallback behavior
- Updated existing tests to pass
- All 189 tests passing
- Build and lint passing