Skip to content

Expose invitation email binding through the Aspire API - #102

Merged
woksin merged 1 commit into
mainfrom
feat/85-aspire-invite-email-binding
Aug 13, 2026
Merged

Expose invitation email binding through the Aspire API#102
woksin merged 1 commit into
mainfrom
feat/85-aspire-invite-email-binding

Conversation

@woksin

@woksin woksin commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Added

Invite.EmailClaim is the opt-in recipient binding, but no Aspire builder
emitted it, so it could only be set with a hand-spelled environment
variable. That also left a shipped feature unreachable: signed invitation
attestations require EmailClaim unconditionally, so an AppHost using
WithInvite(...).WithSignedInvitationAttestations(...) failed startup
options validation with no typed way to satisfy it.

A separate fluent extension rather than a parameter on the existing
WithInvite overloads: a trailing optional parameter is binary breaking
because C# bakes defaults into the call site, and a same-name overload
differing only by it would make existing calls ambiguous.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@woksin woksin added the minor label Aug 12, 2026
@woksin

woksin commented Aug 12, 2026

Copy link
Copy Markdown
Contributor Author

Reviewer context (kept out of the body so it stays release-note clean).

Why a separate extension and not a parameter. Adding a trailing optional emailClaim to either existing WithInvite overload is binary breaking — C# bakes the default into the call site, so already-compiled AppHosts would hit MissingMethodException. The usual escape hatch fails too: a same-name overload differing only by the trailing optional argument makes every existing omitting call ambiguous (CS0121). Composing after either overload also means one method covers both invite configuration shapes. WithSignedInvitationAttestations is the in-repo precedent for exactly this shape.

The unreachable-feature finding. InvitationAttestationConfigurationValidator.cs:71-74 requires Invite.EmailClaim unconditionally when attestations are enabled, and the guard is genuinely reached: the validator returns early only when invite?.Attestation is null (:23-28), WithSignedInvitationAttestations binds Invite.Attestation to non-null, it is registered as IValidateOptions<Configuration.AuthProxy> (InvitesServiceCollectionExtensions.cs:25), and IngressExtensions.cs:49-53 calls ValidateOnStart() on that same options type. TenantClaim is required identically but was already exposed through Aspire; EmailClaim was the only one with no typed route.

Gate. Debug and Release, --no-incremental -warnaserror: 0 errors, 0 warnings. Aspire.Specs 68 passed / 0 failed (66 before, +2).

Mutation evidence, run independently of the implementer, with an assertion that the mutation actually applied before testing:

  • Emitted key changed to ...__Invite__EmailClaimMUTANTand_a_claim_is_named RED, dying at its own assertion indexer (KeyNotFoundException on the real key), not in Because(). SPECIFIC. and_no_claim_is_named correctly stayed green.
  • Guard if (!string.IsNullOrEmpty(...)) removed → and_no_claim_is_named RED, and_a_claim_is_named green. SPECIFIC.
  • Restore verified by shasum -a 256 (not diff): 742e21d6...272ebd before and after, then rebuilt and re-ran to confirm GREEN.

Worth recording: the implementer's first attempt at the second mutation reported a survivor that was a false negative — its perl -0pi pattern silently matched nothing, so the file was never mutated. Any mutation harness should assert the pattern matched exactly once and compare pre/post digests before running the spec.

Not verified: no AppHost was actually booted, so the startup-validation failure is established from the four code paths above rather than observed. Nothing asserts it end to end; a spec composing both builders and running the real validator over the bound configuration would close that, but it spans the Aspire and AuthProxy projects and was outside this change.

@woksin
woksin merged commit 4b8bbe7 into main Aug 13, 2026
5 checks passed
@woksin
woksin deleted the feat/85-aspire-invite-email-binding branch August 13, 2026 07:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants