Skip to content

feat(lambda): expose a resolvable qualified ARN on AWS::Lambda::Version - #163

Merged
clanker-pel[bot] merged 3 commits into
mainfrom
clanker/PLA-453
Aug 8, 2026
Merged

feat(lambda): expose a resolvable qualified ARN on AWS::Lambda::Version#163
clanker-pel[bot] merged 3 commits into
mainfrom
clanker/PLA-453

Conversation

@clanker-pel

@clanker-pel clanker-pel Bot commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Summary

AWS::Lambda::Version exposed no Resolvable, so nothing in a forma could
reference a published version's qualified function ARN. That matters most for
Lambda@Edge: CloudFront rejects an unqualified ARN (and $LATEST) on a
lambdaFunctionAssociations entry, so the association had to carry the
versioned ARN as a hand-written literal — and every function code change
publishes a new version and requires re-editing that pin, reintroducing exactly
the hand-managed drift IaC exists to remove.

This adds a VersionResolvable with a single functionArn accessor on the
CloudControl read-only property FunctionArn, exposed as Version.res. It
mirrors the existing pattern in func.pkl and layerversion.pkl, and names the
accessor after the CloudControl property as those do. A distribution can now
write:

lambdaFunctionAssociations {
  new {
    eventType = "origin-request"
    lambdaFunctionARN = edgeVersion.res.functionArn
  }
}

The consumer side already accepted a Resolvable and carries
edgeKind = "runtimeDependency", so dependency ordering works once there is
something to point at.

Also included:

  • examples/cloudfront-lambda-edge/main.pkl — a worked Lambda@Edge example
    (role trusted by both lambda and edgelambda, function, version,
    distribution) that resolves the association rather than pinning an ARN.
  • testdata/lambda-version-ref.pkl — a conformance fixture whose
    Permission.functionName consumes the version's res.functionArn, so an
    apply fails outright if the reference cannot resolve. Validated against real
    AWS alongside the existing lambda-version fixture; both pass.
  • A Verify examples step in the checks job. make verify-examples exists to
    catch precisely this class of Resolvable regression but was not wired into any
    workflow, so the examples could rot silently. It is pkl eval only — no
    credentials, seconds.

Known limitation, unchanged by this PR

Every field on Version is create-only, so a function code change publishes a
replacement version rather than updating the existing one. The safe order is
publish, re-point the distribution, wait for CloudFront to propagate, and only
then delete the old version — and a replicated Lambda@Edge version can remain
undeletable for a long time after the association is removed, which makes such a
stack slow to tear down. This hazard exists today with a hardcoded ARN; exposing
the resolvable removes the hand-edit but does not change the ordering. It is
stated in the example header and the changelog entry, and the
replacement-ordering analysis is tracked separately.

Note also that no automated test deploys a live Lambda@Edge association — edge
replica teardown blocks deletion far beyond a test's lifetime. The conformance
fixture proves the qualified ARN resolves and round-trips; it does not prove
CloudFront's acceptance of it.

res.version is deliberately not included: no modelled field can consume it
today (Alias.functionVersion, Url.qualifier and EventInvokeConfig.qualifier
are all bare String, and Url's pattern excludes a purely numeric version), so
it would ship dead. Tracked as a follow-up together with widening
Alias.functionVersion.

clanker-pel Bot added 3 commits August 8, 2026 01:06
A published AWS::Lambda::Version had no Resolvable, so nothing in a forma
could reference the version's qualified function ARN. CloudFront rejects an
unqualified ARN (and $LATEST) on a Lambda@Edge association, which forced
callers to hardcode the ARN literal and hand-edit the pin on every publish.

Add VersionResolvable with a functionArn property and wire it up as
Version.res, mirroring the other Lambda resources. The new
cloudfront-lambda-edge example wires a role, function, version and
distribution together and resolves the association from the version.
Wires a Lambda Permission to the qualified function ARN published by a Lambda Version, so an apply fails outright if that reference cannot be resolved.
Add a `Verify examples` step to the checks job, right after
`Verify schema`, so `make verify-examples` runs on every PR and catches
Resolvable shape regressions in the example formae. Also record the new
`AWS::Lambda::Version` functionArn resolvable in the changelog.

@JeroenSoeters JeroenSoeters left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved.

Reviewed the diff against the agreed design, the review ledger, and the CI result.

Head SHA 2cc7b80 is byte-identical to the SHA debug-conformance validated (run 31246285555, both lambda-version and lambda-version-ref green, pre/post-cleanup clean). That matters more than usual here: this repo's PR CI skips conformance-tests, test-integration, discover-tests and pre-cleanup, so the PR run on its own carries no conformance signal. The branch-first dispatch is the only real evidence the accessor resolves against AWS, and it covers exactly what merges.

Ledger floor is clear. Pass 2's single P2 finding (private S3 origin with an OAC but no bucket policy) is correctly rejected, and I verified both load-bearing claims independently rather than taking them on trust:

  • DistributionResolvable (schema/pkl/cloudfront/distribution.pkl:317-326) exposes only id and domainName, no ARN. A properly scoped OAC policy needs AWS:SourceArn, which embeds the account id, so writing it would hardcode an account-id literal into an example: precisely the hand-managed pin this change exists to remove.
  • examples/cloudfront-edge-minimal/main.pkl has no bucket policy either, so the omission is the existing house pattern, not a regression introduced here. PLA-487 to fix both together is the right call.

Merging with two documented, unfixed limitations, both stated rather than buried:

  1. Every field on Version is create-only, so a code change publishes a replacement version, and a replicated Lambda@Edge version can stay undeletable well after the association is removed. Pre-existing, borne manually today with a hardcoded ARN; PLA-459 tracks the ordering analysis.
  2. Nothing automated deploys a live Lambda@Edge association. lambda-version-ref proves generic resolution of the qualified ARN, not CloudFront's acceptance of it. Confirming end to end remains a manual apply of the new example.

The scope extension wiring Verify examples into the checks job was confirmed on the design turn and is included.

@clanker-pel
clanker-pel Bot merged commit e741005 into main Aug 8, 2026
13 checks passed
@clanker-pel
clanker-pel Bot deleted the clanker/PLA-453 branch August 8, 2026 09:29
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