Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: NpgsqlRest/NpgsqlRest
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 3.12.0
Choose a base ref
...
head repository: NpgsqlRest/NpgsqlRest
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 3.13.0
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 11 commits
  • 129 files changed
  • 2 contributors

Commits on Apr 2, 2026

  1. Update README with 3.12.0 features and fix positional @Result example

    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
    vbilopav and claude committed Apr 2, 2026
    Configuration menu
    Copy the full SHA
    c6f4572 View commit details
    Browse the repository at this point in the history

Commits on Apr 5, 2026

  1. Increase HTTP client retry test delays to fix CI flakiness

    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
    vbilopav and claude committed Apr 5, 2026
    Configuration menu
    Copy the full SHA
    714ef32 View commit details
    Browse the repository at this point in the history

Commits on Apr 28, 2026

  1. bump 3.13.0

    - New: WrapInTransaction option (PgBouncer transaction-mode safety)
    - New: BeforeRoutineCommands option (parameterized SQL run before routine call; multi-tenant search_path pattern)
    - Fix: 400 Bad Request responses now log at Warning level (previously silent)
    - Docker: native AOT images rebased on Ubuntu 26.04 LTS
    - NuGet upgrades for main library and client app
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed Apr 28, 2026
    Configuration menu
    Copy the full SHA
    55dc86b View commit details
    Browse the repository at this point in the history

Commits on Apr 30, 2026

  1. test: regression for claim-mapped param in cache key

    Verifies that when a parameter is auto-populated from a claim (via
    ParameterNameClaimsMapping + user_parameters annotation), the cache key
    uses the resolved post-claim value, not the request-time null. Two
    different users get separate cache entries; same user hits cache.
    
    Catches a hypothetical security regression where the cache could leak
    responses across identities if the key were built before claim
    resolution.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed Apr 30, 2026
    Configuration menu
    Copy the full SHA
    53ec974 View commit details
    Browse the repository at this point in the history

Commits on May 1, 2026

  1. feat: caching profiles and conditional When rules

    Adds named cache profiles to CacheOptions, selected per endpoint via the
    new @cache_profile annotation. Profiles bundle backend (Memory/Redis/Hybrid),
    default expiration, cache-key parameter list, and per-parameter When rules.
    
    When rules evaluate against resolved parameter values at request time;
    first match wins. Each rule's Then is either "skip" (bypass cache for the
    request) or a PostgreSQL interval (override TTL for the write). This
    unlocks dynamic TTL by input shape — e.g. cache historical queries for 1
    hour but switch to 5 minutes when the to-date is open-ended, or skip
    caching entirely when a real-time flag is on.
    
    Backends are pooled by Type and lazily instantiated — only types actually
    used by the root or some enabled profile are spun up. Cache entries are
    prefixed with profile name so two profiles sharing the same Memory backend
    cannot collide.
    
    Misconfiguration is loud at startup: unknown profile names referenced by
    @cache_profile fail-fast with a single error listing every unresolved
    name + offending endpoints. When rules referencing parameters not in the
    cache key are dropped with a Warning. Disabled profiles (Enabled: false)
    are skipped at startup with an Information log; the default appsettings
    ships three disabled examples.
    
    IRoutineCache.AddOrUpdate gains an optional TimeSpan? overrideExpiration
    parameter so per-rule TTL overrides flow through Memory, Redis, and
    HybridCache backends uniformly.
    
    21 new test files in CacheProfilesTests/ cover resolution, validation,
    inheritance/override of Expiration and Parameters, dynamic TTL,
    first-match-wins, skip-on-condition variants, invalidation routing
    through profile cache, and unknown-name startup failures. 134/134
    combined regression suite passes.
    
    Changelog: 3.13.0 entry extended with full Caching Profiles section
    including the never-expire workaround (omit Expiration field).
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed May 1, 2026
    Configuration menu
    Copy the full SHA
    7ceb9b0 View commit details
    Browse the repository at this point in the history
  2. gitignore

    vbilopav committed May 1, 2026
    Configuration menu
    Copy the full SHA
    a51183f View commit details
    Browse the repository at this point in the history
  3. fix: sync ConfigTemplate with appsettings.json Profiles comments

    The Config_OutputMatchesAppsettingsJson test compares --config CLI output
    (driven by ConfigTemplate.cs) byte-for-byte against the checked-in
    appsettings.json. The Profiles section in ConfigTemplate was missing two
    comment blocks that appsettings.json has — the "Common patterns" block
    (showing skip-on-null and tiered-TTL examples) and the "Three disabled
    example profiles" paragraph. Also corrected `cache_profile` → `@cache_profile`
    to match. Test now passes.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed May 1, 2026
    Configuration menu
    Copy the full SHA
    bad45cf View commit details
    Browse the repository at this point in the history
  4. chore: reorganize changelog into per-version files under changelog/

    Splits the monolithic changelog.md and changelog-old.md into one file per
    release under changelog/, mirroring the structure already used by the
    published docs site (npgsqlrest-docs/docs/guide/changelog/).
    
    - 37 per-version files: changelog/v3.0.0.md through changelog/v3.13.0.md
    - changelog/legacy.md: pre-3.0 versions and separately-versioned components
      (e.g. client-2.x), 56 entries total
    - Top-level changelog.md kept as a thin pointer so existing NuGet
      PackageReleaseNotes URLs (5 csproj files), docker/readme.md, and the
      GitHub root convention continue to work
    - changelog-old.md removed (content moved into changelog/legacy.md;
      git tracks this as a rename)
    - Removed orphaned docs/guide/changelog/v3.12.0.md (abandoned partial
      copy, superseded by the npgsqlrest-docs published version)
    
    CI updated: .github/workflows/build-test-publish.yml release-notes
    extraction now reads changelog/v$VERSION.md directly via tail -n +2,
    replacing the awk-based section extraction over the monolithic file.
    Simpler and faster.
    
    Test verified: Config_OutputMatchesAppsettingsJson and the caching
    profile suite still pass.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed May 1, 2026
    Configuration menu
    Copy the full SHA
    577056f View commit details
    Browse the repository at this point in the history
  5. refactor!: RateLimiterOptions:Policies is now a dict keyed by name

    Aligns the shape of named-policies sections in appsettings.json:
    
      ValidationOptions.Rules     - dict (already)
      CacheOptions.Profiles       - dict (added in 3.13.0)
      RateLimiterOptions.Policies - was array, now dict
    
    Before:
      "Policies": [
        { "Name": "fixed",   "Type": "FixedWindow", "Enabled": true, ... },
        ...
      ]
    
    After:
      "Policies": {
        "fixed":   { "Type": "FixedWindow", "Enabled": true, ... },
        ...
      }
    
    Move each policy's Name value to be the JSON key and drop the Name
    field. No other field changes; runtime behavior identical.
    
    This is a hard breaking change. Builder.cs detects the legacy array
    form (numeric keys "0", "1", ... from IConfiguration.GetChildren()) and
    throws InvalidOperationException at startup with migration instructions.
    Failing fast is deliberate — silently registering policies under names
    like "0" would make endpoint annotations referencing them stop matching,
    leading to silent loss of rate limiting.
    
    Also fixed two pre-existing inconsistencies:
    - ConfigDefaults had bucket/concurrency policies marked Enabled: true,
      contradicting appsettings.json (which had all four as Enabled: false).
      Aligned both to false.
    - ConfigSchemaGenerator had four duplicate "RateLimiterOptions:Policies:Type"
      entries, only the last surviving (concurrency description). Consolidated
      into a single entry linking to all four ASP.NET Core docs sections.
    
    Tests: rate limiter test fixtures configure via C# direct API, not JSON
    config, so unaffected by the shape change. 159/159 broad regression
    suite passes including Config_OutputMatchesAppsettingsJson.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed May 1, 2026
    Configuration menu
    Copy the full SHA
    2360787 View commit details
    Browse the repository at this point in the history
  6. feat: per-user rate limiting via Partition on policies

    Rate-limiter policies can now declare an optional Partition block with an
    ordered list of Sources (Claim, IpAddress, Header, Static). Each request
    resolves a partition key and gets its own bucket — typical "per-user" or
    "per-IP" patterns instead of a single shared global bucket. BypassAuthenticated
    lets signed-in users skip rate limiting entirely.
    
    IpAddress source uses the existing Request.GetClientIpAddress() helper, so
    X-Forwarded-For is honored ahead of Connection.RemoteIpAddress (the only
    production site that was reading RemoteIpAddress directly outside the helper).
    
    Tests:
    - 12 unit tests for Builder.ResolvePartitionKey covering each source type,
      fallthrough order, X-Forwarded-For precedence, and the unpartitioned fallback.
    - Integration fixture (RateLimiterPartitionTestFixture) with 3 E2E tests for
      per-claim bucketing, claim->IP fallthrough, and BypassAuthenticated.
    
    Shared test fixtures' NameNotSimilarTo updated to also exclude rlpt_* so the
    new fixture's database functions don't leak into other fixtures' endpoint
    auto-discovery.
    
    appsettings.json gets a disabled "per_user" example policy demonstrating
    the Partition shape as live JSON; the existing four policies stay lean.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed May 1, 2026
    Configuration menu
    Copy the full SHA
    105b40b View commit details
    Browse the repository at this point in the history
  7. feat!: Auth Schemes for all types + breaking interval-only time fields

    Two related auth changes for 3.13.0:
    
    1. Auth:Schemes — named additional authentication schemes (Cookies / BearerToken / Jwt)
    
       New Auth:Schemes dict registers fully-fledged ASP.NET Core auth schemes
       alongside the main one. Login functions select a scheme by returning the
       scheme name in the `scheme` column. Use cases:
         - short-lived single-session cookies for sensitive operations
         - per-scope JWT signing keys (separate JwtSecret limits leak blast radius)
         - multiple bearer-token APIs with different expirations / refresh paths
    
       Schemes inherit any unset field from the root Auth section. Per-type
       overrides:
         - Cookies: CookieValid, CookieName, CookiePath, CookieDomain,
           CookieMultiSessions, CookieHttpOnly
         - BearerToken: BearerTokenExpire, BearerTokenRefreshPath
         - Jwt: JwtExpire, JwtRefreshExpire, JwtSecret, JwtIssuer, JwtAudience,
           JwtClockSkew, JwtRefreshPath, all four JwtValidate* flags
    
       Validation at startup: scheme-name collision with main schemes, unsupported
       Type, CookieName uniqueness, refresh-path uniqueness across all schemes,
       JwtSecret >=32 chars, invalid interval strings.
    
       JwtLoginHandler refactored from singleton to scheme-keyed dict so the
       correct config + generator is resolved by scheme name from the login
       function. Per-scheme refresh middlewares are constructed in Program.cs
       from Builder.AdditionalBearerTokenConfigs / AdditionalJwtTokenConfigs.
    
    2. BREAKING: legacy integer auth time fields removed
    
       Auth:CookieValidDays, BearerTokenExpireHours, JwtExpireMinutes,
       JwtRefreshExpireDays are removed in favor of interval notation
       (Auth:CookieValid, BearerTokenExpire, JwtExpire, JwtRefreshExpire).
    
       Fail-fast detection (Builder.DetectLegacyAuthTimeFields): any of the four
       removed keys in user config throws at startup with a clear migration
       message naming the offending field, replacement field, and example
       interval. Silently ignoring would risk a "30-day cookies" intent flipping
       to the new field's default of 14 days.
    
       Default appsettings.json ships explicit values
       ("14 days" / "1 hour" / "60 minutes" / "7 days") rather than null, so
       users see exactly what they get.
    
    Tests (1932/1932 pass):
    - 7 unit tests for simplified ResolveAuthTimeSpan
    - 6 fail-fast tests for the four removed legacy fields
    - 19 unit tests covering RegisterAuthSchemes across all three types
    - 4 integration tests through the full HTTP login pipeline (cookie main,
      cookie additional with session-only, JWT main, JWT additional with
      per-scheme secret + 5-minute expire)
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
    vbilopav and claude committed May 1, 2026
    Configuration menu
    Copy the full SHA
    efab11b View commit details
    Browse the repository at this point in the history
Loading