Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Five unresolved documentation nits remain in the package README and cloud setup guide.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Documentation PR covering package usage, cloud identity setup, contribution guidance, security reporting, and release metadata.
Changes:
- Expands root and package README quickstarts.
- Adds least-privilege cloud identity and Azure SQL setup guidance.
- Adds contribution, security, PR template, and changeset documentation.
File summaries
| File | Summary |
|---|---|
SECURITY.md |
Adds vulnerability reporting policy. |
README.md |
Updates project overview and quickstart. |
docs/cloud-identity-setup.md |
Documents cloud setup and least-privilege permissions. Final nits: clarify startup refresh behavior (3 votes, line 199) and scope schema execution grants (1 vote, line 136). |
Csag.AzureSqlFederatedIdentity/README.md |
Adds package usage documentation. Final nits: narrow hosted-service registration wording (2 votes, line 23), mark overloads as alternatives (1 vote, line 100), and qualify the no-network-round-trip claim (2 votes, line 117). |
CONTRIBUTING.md |
Adds build, test, and contribution guidance. |
.github/PULL_REQUEST_TEMPLATE.md |
Adds a pull request checklist. |
.changeset/docs-usage-and-guides.md |
Declares the packaged documentation patch release. |
Review details
Suppressed comments (2)
Csag.AzureSqlFederatedIdentity/README.md:103
- These two overloads are invoked sequentially in one service collection, even though they are alternatives. A copy-paste user can therefore combine multiple options configurators and silently override values; mark the calls as alternatives or put them in separate snippets.
services.AddAzureSqlFederatedIdentity(configuration);
// Sets the options in code; the section name is available as AzureSqlFederatedIdentityOptions.ConfigurationSectionName.
services.AddAzureSqlFederatedIdentity(options =>
docs/cloud-identity-setup.md:136
GRANT EXECUTE ON SCHEMA::dbogrants execute on every routine in the schema, including future ones, so it contradicts the guide's least-privilege recommendation and the claim that these are object-scoped grants. Scope this example to a named procedure, or remove it unless the application needs schema-wide execution.
GRANT EXECUTE ON SCHEMA::dbo TO [<app-registration-display-name>];
- Files reviewed: 8/8 changed files
- Comments generated: 3
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
🔵 Needs a closer look
Two moderate documentation issues remain unresolved regarding hosted-service replacement and background-refresh timing.
Review details
Suppressed comments (2)
Csag.AzureSqlFederatedIdentity/README.md:23
- This says every service is registered with
TryAdd, but the registration code usesAddHostedService<AzureSqlTokenRefreshService>()for the refresh service. A consumer cannot replace that hosted service just by registering an implementation first, so the feature list overstates the replacement guarantee; limit the statement to the replaceable token-pipeline services (or document how to replace the hosted service).
- Every service is registered with `TryAdd`, so you can replace any part of the pipeline, including `IAzureSqlTokenProvider`, by registering your own implementation first.
docs/cloud-identity-setup.md:199
- With the default
EnableBackgroundRefresh=true,AzureSqlTokenRefreshServiceperforms the first token exchange as soon as the host starts (seeCsag.AzureSqlFederatedIdentity/Internal/Services/AzureSqlTokenRefreshService.cs:79-104), before any database access. Only when background refresh is disabled does the first database call trigger the exchange, so this flow description can mislead operators about when startup failures and latency occur. Please make the two cases explicit.
At startup the application validates its configuration: the three required settings must be present and `RefreshAheadWindow` must be positive. On the first database access it requests an ID token for the configured service account through ADC (as the runtime service account), exchanges it at Microsoft Entra ID, and opens the connection with the resulting access token. If something fails, the application log names the failing step; the troubleshooting table in the [package README](../Csag.AzureSqlFederatedIdentity/README.md) maps the usual messages to their cause.
- Files reviewed: 8/8 changed files
- Comments generated: 0 new
- Review effort level: Lite
35260e1 to
13a2468
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Two documentation clarifications remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (1)
Csag.AzureSqlFederatedIdentity/README.md:117
- The hosted refresh task is scheduled at the refresh boundary, but a request can arrive in this window before that task runs (or while it is delayed), even when background refresh is enabled and healthy. The parenthetical incorrectly makes this fallback sound limited to disabled or failing background refresh; remove that qualification so the documented behavior matches the implementation.
Resolve `IAzureSqlTokenProvider` (namespace `Csag.AzureSqlFederatedIdentity.Abstractions`), call `GetAzureSqlAccessTokenAsync` and assign the result to `SqlConnection.AccessToken` before opening the connection. Do this for every new connection: until the held token enters the refresh-ahead window the call returns it without any network round trip; inside the window (reachable only when background refresh is off or has been failing) the first caller exchanges a new token and concurrent callers wait for that one exchange.
- Files reviewed: 8/8 changed files
- Comments generated: 1
- Review effort level: Lite
13a2468 to
d9451cc
Compare
There was a problem hiding this comment.
🟡 Changes recommended
Two moderate and three nit review comments remain unresolved.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (3)
Csag.AzureSqlFederatedIdentity.Demo/README.md:87
- The PR description calls out consistent Microsoft Entra ID naming, but this Demo README still uses the old “Azure AD” name in its introduction, prerequisites, and settings table. Please update those remaining labels as part of this documentation pass so the linked end-to-end guide does not contradict the stated terminology.
Push the image to Artifact Registry and deploy it with the runtime service account set to the configured Google service account and the four settings supplied as environment variables. Cloud Run sends traffic to port 8080, which is the port the image listens on. The [setup guide](../docs/cloud-identity-setup.md) covers the Cloud Run configuration in detail.
Csag.AzureSqlFederatedIdentity/README.md:103
- The overload example invokes both registration methods in one code block. If copied as written, the later code-based
Configureruns after the configuration bind and overwrites the configured tenant, client, service account and other values with the placeholders, so these need to be presented as alternatives with an explicit instruction to call only one.
services.AddAzureSqlFederatedIdentity(configuration);
// Sets the options in code; the section name is available as AzureSqlFederatedIdentityOptions.ConfigurationSectionName.
services.AddAzureSqlFederatedIdentity(options =>
Csag.AzureSqlFederatedIdentity/README.md:31
- This prerequisite only says to create the app-registration user, but that
CREATE USER ... FROM EXTERNAL PROVIDERstep also requires the logical SQL server to have a managed identity with directory-read permissions (for example Directory Readers or the documented Microsoft Graph permissions). Without that setup the stated prerequisite fails with the principal-not-found error. The linked setup guide explains it, but this README is described as self-contained and is the documentation shipped in the nupkg, so include the prerequisite here or explicitly make the setup guide a required dependency.
- **Azure SQL:** a contained database user for the app registration (`CREATE USER [...] FROM EXTERNAL PROVIDER`) with the permissions your application needs.
- Files reviewed: 8/8 changed files
- Comments generated: 2
- Review effort level: Lite
d9451cc to
9a3fb28
Compare
…ing and security The package README ships inside the nupkg, so it is now self-contained: absolute links only (the licence badge pointed at ../LICENSE, a dead link on nuget.org), links to the repository and the setup guide, and a complete quickstart covering install, every configuration key including RefreshAheadWindow and EnableBackgroundRefresh, all three AddAzureSqlFederatedIdentity overloads, obtaining the token from IAzureSqlTokenProvider and assigning SqlConnection.AccessToken, an EF Core factory modelled on the Demo, prerequisites, notes on credential-free connection strings and the ADC runtime identity, and a troubleshooting table. The feature list describes what the background refresh actually does. All four C# samples were compiled against the library with warnings as errors. The root README gains a projects table with links to each project and the Demo README, a quick start pointing at the package README and docs/cloud-identity-setup.md, and Contributing/Security sections; the Release process section is unchanged. The setup guide now recommends roles/iam.serviceAccountOpenIdTokenCreator bound on the service account resource, explains why a project-level binding or Service Account Token Creator is too broad, adds enabling iamcredentials.googleapis.com, corrects the ID token audience to the fixed api://AzureADTokenExchange, marks db_datareader/db_datawriter as a starting point to narrow, adds a Configure the application section with the exact keys, a Cloud Run deployment with the runtime service account, and uses Microsoft Entra ID consistently. Google and Microsoft facts were verified against their current documentation. New: CONTRIBUTING.md (build/test on both TFMs, central package management, changesets and the 0.x bump convention, PR expectations), SECURITY.md (private vulnerability reporting, supported versions) and a PR template, plus a patch changeset. The links to Csag.AzureSqlFederatedIdentity.Demo/README.md target the file added on feat/demo-fixes, which merges ahead of this branch. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Add the Csag.AzureSqlFederatedIdentity.Options using directive to the registration-overloads sample so it compiles as printed. State the background-refresh schedule exactly: half the remaining lifetime when that is shorter than the refresh-ahead window, clamped to 10 s - 1 d. Note that the PermissionDenied RpcException appears in the log and reaches callers wrapped in AuthenticationFailedException. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CONTRIBUTING.md listed AutoFixture among the test libraries, but no test uses it and the package is being dropped from the test project; the tests use xunit, Shouldly and NSubstitute directly. Also: the package README's token-handling note now carries the SqlClient caveat that a Min Pool Size above zero requires SqlConnection.ClearPool after a token expires (verified against the AccessToken remarks on learn.microsoft.com), and the setup guide's startup sentence names the RefreshAheadWindow check alongside the three required settings, matching AzureSqlFederatedIdentityOptionsValidator. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mber Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… the refresh-ahead window; first exchange timing Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…e CREATE USER for a service principal Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
9a3fb28 to
26c886e
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
Cloud Run environment-variable guidance and the schema-wide database grant need correction.
Review details
Suppressed comments (3)
Csag.AzureSqlFederatedIdentity/README.md:75
- The README lists
Csag.AzureSqlFederatedIdentity__...as a generic environment-variable form, but this form is not usable on Cloud Run because the section name contains.and Cloud Run rejects such environment-variable names. Since Cloud Run is one of the documented runtime prerequisites, add a Cloud Run-safe configuration alternative or explicitly warn that these names require a different configuration source there.
Environment variables follow the usual .NET mapping, with `__` as the section separator: `Csag.AzureSqlFederatedIdentity__TenantId`, `Csag.AzureSqlFederatedIdentity__ClientId`, `Csag.AzureSqlFederatedIdentity__Google__ServiceAccountEmail`, and so on.
docs/cloud-identity-setup.md:186
- These environment-variable names contain
.in the section name, but Cloud Run rejects environment variable names that are not valid identifier-style names. Consequently the documentedgcloud run deploy --env-vars-file env.yamlfails before the application starts. Please use a Cloud Run-compatible configuration path (for example, an env-safe section/alias or a mounted configuration/secret file) and update these names and the binding instructions accordingly.
Csag.AzureSqlFederatedIdentity__TenantId: "<tenant-id>"
Csag.AzureSqlFederatedIdentity__ClientId: "<client-id>"
Csag.AzureSqlFederatedIdentity__Google__ServiceAccountEmail: "<name>@<project-id>.iam.gserviceaccount.com"
docs/cloud-identity-setup.md:138
- This example grants
EXECUTEon every procedure and function in thedboschema, which conflicts with the preceding least-privilege guidance and the claim that these grants target particular objects. A consumer copying it would give the app more database capability than intended; use an object-level grant for a named procedure, or clearly label the schema-wide grant as a broader alternative.
GRANT EXECUTE ON SCHEMA::dbo TO [<app-registration-display-name>];
- Files reviewed: 8/8 changed files
- Comments generated: 0 new
- Review effort level: Lite
Summary
Documentation for the API as it stands after the runtime PR.
appsettings.jsonwith every option → the three registration overloads → obtaining the token fromIAzureSqlTokenProviderand assigningSqlConnection.AccessToken, plus an EF Core factory modelled on the Demo → prerequisites and notes (credential-free connection string withEncrypt=True; the Google ID token is minted via Application Default Credentials, so the runtime identity must be the configured service account). The features list describes what the background refresh actually does.docs/cloud-identity-setup.md: least privilege —roles/iam.serviceAccountOpenIdTokenCreatorbound on the service account (the library only callsgenerateIdToken), with thegcloudcommand and why a project-level binding is too broad; enable the IAM Service Account Credentials API; the audience isapi://AzureADTokenExchange, not the Entra application; database roles as a starting point to narrow; a "Configure the application" section with the exact keys; consistent Microsoft Entra ID naming.CONTRIBUTING.md(build/test on both TFMs, changesets, 0.x bump convention),SECURITY.md(private vulnerability reporting — now enabled on the repository),.github/PULL_REQUEST_TEMPLATE.md.Stacked on the Demo PR (it links the Demo README).
Review findings addressed
21, 22, 24, 25, 26, 27 (and the setup guide's copy of 23).
Validation
Csag.*release is published).usingin a sample was caught and fixed).🤖 Generated with Claude Code