Skip to content

fix(sdk): select deployed cross-read by per-request envelope, not process IsLambda#140

Merged
I-am-nothing merged 1 commit into
mainfrom
fix/deployed-read-per-request-gate
Jul 5, 2026
Merged

fix(sdk): select deployed cross-read by per-request envelope, not process IsLambda#140
I-am-nothing merged 1 commit into
mainfrom
fix/deployed-read-per-request-gate

Conversation

@I-am-nothing

Copy link
Copy Markdown
Contributor

Problem

The local deploy-sim module-runtime serves DEPLOYED invokes over HTTP with runtime.IsLambda() == false — setting AWS_LAMBDA_FUNCTION_NAME would make module.Start() call the real lambda.Start() and hijack the process, killing the HTTP server the shim needs to serve. So the IsLambda-gated deployed DependencyDB branch never fires locally, blocking the scenario-3 (all-deployed) E2E — even though the shim already injects the dependency manifest per-request.

Fix

Gate on the PER-REQUEST envelope signal instead: auth.PayloadTrusted(ctx) — the deployed-envelope / payload-trust mark set by runtime.NewLambdaHandler for BOTH real Lambda (module.go Start -> lambda.Start) AND the dev lambda-invoke shim (lambda_shim.go), unconditionally per invoke, and never for a dev-tunnel HTTP request.

Used ALONE — runtime.IsLambda is removed entirely, not OR'd. Investigation showed PayloadTrusted is the single discriminator correct in all four cases — critically case 4 (all-degraded deployed invoke, manifest nil) stays on the deployed branch -> errDevPlaneOnly fail-closed, whereas keying on manifest-presence would wrongly divert it to the proxy error.

Behavior preserved exactly:

  • Dev-tunnel (no envelope) -> proxy / MS_INTERNAL_SECRET path preserved.
  • resultDeployed manifest-absent rollout hard-error ("dev-plane only", no typed sentinel) preserved.
  • Real-Lambda behavior unchanged; dev-tunnel still uses the proxy.

Verification

  • gofmt -l clean on all 3 changed files.
  • go build ./... OK.
  • go vet ./internal/core/ clean.
  • go test ./internal/core/ ./auth/ ./internal/runtime/ all green.
  • Focused go test ./internal/core -run TestDependencyDB -v passes, including the new pin TestDependencyDB_Result_DeployedFiresInLocalShimNotOnlyRealLambda (3 subtests).
  • Independently reproduced the regression: temporarily modeling the pre-fix gate (false && auth.PayloadTrusted) makes subtest (a) dev-sim-shim FAIL with "dependency read unauthorized ... MS_INTERNAL_SECRET is unset" (want ErrNotExposed) — i.e. the pin fails before the fix and passes after; the dev-tunnel-proxy subtest (b) passes both before and after, confirming scenario 1/2 is preserved. Restored the tree clean after the experiment (git status --porcelain empty).
  • The pre-existing internal/refcache TestSlowPath_SingleflightCoalesces timing flake is unrelated — this diff touches only internal/core/dependency_db*.go.

Relationship

Follow-up to #139 decision-18 PR2; enables the local all-deployed E2E.

🤖 Generated with Claude Code

…cess IsLambda

DependencyDB.Result gated the cross-read plane on the process-global
runtime.IsLambda(). That is wrong altitude: whether a read is "deployed"
is a PER-REQUEST property (did this invoke arrive through the deployed
Lambda envelope?), not a per-process one.

The local deploy-sim module-runtime serves DEPLOYED invokes over HTTP via
the dev lambda-invoke shim, which is mounted ONLY when !runtime.IsLambda()
— and it MUST run with IsLambda==false: setting AWS_LAMBDA_FUNCTION_NAME
would make module.Start() call the real lambda.Start(), which stops the
HTTP server the shim needs. So on the local shim the envelope-arrival
signals (auth.PayloadTrusted + the injected Dependencies manifest) are all
present, yet the IsLambda gate took the dev-tunnel PROXY branch and failed
with ErrDependencyUnauthorized ("MS_INTERNAL_SECRET unset") instead of
resultDeployed. Real Lambda worked (IsLambda true); only the shim was
blocked — which blocked the scenario-3 (all-deployed) E2E on the local
stack entirely.

Gate on auth.PayloadTrusted(ctx) instead: it is set by
runtime.NewLambdaHandler for BOTH the real Lambda entrypoint AND the dev
shim, unconditionally per invoke, and never for a dev-tunnel HTTP request.
The result() seam keeps its injected bool (renamed inLambda -> deployed)
so the three planes stay explicitly testable.

Behavior preserved exactly: dev-tunnel requests (no envelope) still take
the read-exposed proxy; resultDeployed keeps its manifest-absent hard-error
rollout gate; an all-deps-degraded deployed invoke (manifest nil but
PayloadTrusted true) routes to resultDeployed and fail-closes to the
typed sentinel, NOT the proxy error. Real-Lambda behavior is unchanged.
Unblocks the scenario-3 local E2E on the deploy-sim shim.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@I-am-nothing I-am-nothing merged commit 89b72aa into main Jul 5, 2026
1 check 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.

1 participant