Skip to content

merge main#1

Open
ReuschelCGN wants to merge 59 commits into
ReuschelCGN:develop-testfrom
PGAN-Dev:main
Open

merge main#1
ReuschelCGN wants to merge 59 commits into
ReuschelCGN:develop-testfrom
PGAN-Dev:main

Conversation

@ReuschelCGN

Copy link
Copy Markdown
Owner

No description provided.

hokiepokedad2 and others added 30 commits May 22, 2026 09:55
CI installs Node 22 which ships npm 10.9.7. That version's `npm ci`
strictly requires the nested `chokidar@4.0.3` / `readdirp@4.1.2`
entries that `@angular-devkit/*` packages declare as optional peer
deps. Dependabot regenerates `package-lock.json` with a newer npm
that prunes those entries, producing lockfiles npm 10.9.7 rejects
with EUSAGE — blocking #248, #250, #256, #261, #262.

Aligning CI to npm 11 matches Dependabot's resolution so the
post-rebase lockfile is accepted.
Bumps Microsoft.AspNetCore.Authentication.JwtBearer from 10.0.5 to 10.0.8
Bumps Microsoft.AspNetCore.Mvc.Testing from 10.0.5 to 10.0.8
Bumps Microsoft.AspNetCore.OpenApi from 10.0.5 to 10.0.8
Bumps Microsoft.EntityFrameworkCore from 10.0.5 to 10.0.8
Bumps Microsoft.EntityFrameworkCore.Design from 10.0.5 to 10.0.8
Bumps Microsoft.EntityFrameworkCore.InMemory from 10.0.5 to 10.0.8
Bumps Microsoft.Extensions.Caching.Memory from 10.0.5 to 10.0.8
Bumps Microsoft.Extensions.Configuration.Abstractions from 10.0.5 to 10.0.8
Bumps Microsoft.Extensions.Http from 10.0.5 to 10.0.8
Bumps Microsoft.Extensions.Logging.Abstractions from 10.0.5 to 10.0.8
Bumps Microsoft.NET.Test.Sdk from 18.4.0 to 18.5.1

---
updated-dependencies:
- dependency-name: Microsoft.AspNetCore.Authentication.JwtBearer
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.AspNetCore.Mvc.Testing
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.AspNetCore.OpenApi
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.EntityFrameworkCore.Design
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.EntityFrameworkCore.InMemory
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.Extensions.Caching.Memory
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.Extensions.Logging.Abstractions
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.Extensions.Configuration.Abstractions
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.Extensions.Http
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: microsoft
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: microsoft
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the angular group with 13 updates in the /Applications/Pgan.PoracleWebNet.App/ClientApp directory:

| Package | From | To |
| --- | --- | --- |
| [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations) | `21.2.8` | `21.2.14` |
| [@angular/cdk](https://github.com/angular/components) | `21.2.6` | `21.2.12` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `21.2.8` | `21.2.14` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `21.2.8` | `21.2.14` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `21.2.8` | `21.2.14` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `21.2.8` | `21.2.14` |
| [@angular/material](https://github.com/angular/components) | `21.2.6` | `21.2.12` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `21.2.8` | `21.2.14` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `21.2.8` | `21.2.14` |
| [@angular/build](https://github.com/angular/angular-cli) | `21.2.7` | `21.2.12` |
| [@angular/cli](https://github.com/angular/angular-cli) | `21.2.7` | `21.2.12` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `21.2.8` | `21.2.14` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `21.2.8` | `21.2.14` |



Updates `@angular/animations` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/animations)

Updates `@angular/cdk` from 21.2.6 to 21.2.12
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](angular/components@v21.2.6...v21.2.12)

Updates `@angular/common` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/common)

Updates `@angular/compiler` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/compiler)

Updates `@angular/core` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/core)

Updates `@angular/forms` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/forms)

Updates `@angular/material` from 21.2.6 to 21.2.12
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](angular/components@v21.2.6...v21.2.12)

Updates `@angular/platform-browser` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/platform-browser)

Updates `@angular/router` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/router)

Updates `@angular/build` from 21.2.7 to 21.2.12
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@v21.2.7...v21.2.12)

Updates `@angular/cli` from 21.2.7 to 21.2.12
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@v21.2.7...v21.2.12)

Updates `@angular/compiler-cli` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/compiler-cli)

Updates `@angular/platform-browser-dynamic` from 21.2.8 to 21.2.14
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.14/packages/platform-browser-dynamic)

---
updated-dependencies:
- dependency-name: "@angular/animations"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/build"
  dependency-version: 21.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cdk"
  dependency-version: 21.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cli"
  dependency-version: 21.2.8
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/common"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/compiler"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/compiler-cli"
  dependency-version: 21.2.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/core"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/forms"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/material"
  dependency-version: 21.2.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/platform-browser"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 21.2.10
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/router"
  dependency-version: 21.2.10
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [@jest/globals](https://github.com/jestjs/jest/tree/HEAD/packages/jest-globals) from 30.3.0 to 30.4.1.
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.4.1/packages/jest-globals)

---
updated-dependencies:
- dependency-name: "@jest/globals"
  dependency-version: 30.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
)

Bumps [jsdom](https://github.com/jsdom/jsdom) from 28.1.0 to 29.1.1.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Commits](jsdom/jsdom@v28.1.0...v29.1.1)

---
updated-dependencies:
- dependency-name: jsdom
  dependency-version: 29.1.1
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the jest group with 3 updates in the /Applications/Pgan.PoracleWebNet.App/ClientApp directory: [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest), [jest-environment-jsdom](https://github.com/jestjs/jest/tree/HEAD/packages/jest-environment-jsdom) and [jest-preset-angular](https://github.com/thymikee/jest-preset-angular).


Updates `jest` from 30.3.0 to 30.4.2
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.4.2/packages/jest)

Updates `jest-environment-jsdom` from 30.3.0 to 30.4.1
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.4.1/packages/jest-environment-jsdom)

Updates `jest-preset-angular` from 16.1.4 to 16.1.5
- [Release notes](https://github.com/thymikee/jest-preset-angular/releases)
- [Changelog](https://github.com/thymikee/jest-preset-angular/blob/main/CHANGELOG.md)
- [Commits](thymikee/jest-preset-angular@v16.1.4...v16.1.5)

---
updated-dependencies:
- dependency-name: jest
  dependency-version: 30.4.2
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: jest
- dependency-name: jest-environment-jsdom
  dependency-version: 30.4.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: jest
- dependency-name: jest-preset-angular
  dependency-version: 16.1.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: jest
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the eslint group with 3 updates in the /Applications/Pgan.PoracleWebNet.App/ClientApp directory: [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin), [eslint-plugin-perfectionist](https://github.com/azat-io/eslint-plugin-perfectionist) and [prettier](https://github.com/prettier/prettier).


Updates `@typescript-eslint/eslint-plugin` from 8.58.1 to 8.59.4
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.4/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.58.1 to 8.59.4
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.4/packages/parser)

Updates `@typescript-eslint/utils` from 8.58.1 to 8.59.4
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/utils/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.59.4/packages/utils)

Updates `eslint-plugin-perfectionist` from 5.8.0 to 5.9.0
- [Release notes](https://github.com/azat-io/eslint-plugin-perfectionist/releases)
- [Changelog](https://github.com/azat-io/eslint-plugin-perfectionist/blob/main/changelog.md)
- [Commits](azat-io/eslint-plugin-perfectionist@v5.8.0...v5.9.0)

Updates `prettier` from 3.8.2 to 3.8.3
- [Release notes](https://github.com/prettier/prettier/releases)
- [Changelog](https://github.com/prettier/prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/prettier@3.8.2...3.8.3)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.58.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.58.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.58.2
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: eslint-plugin-perfectionist
  dependency-version: 5.9.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: prettier
  dependency-version: 3.8.3
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: HokiePokeDad <hokiepokedad@pogoalerts.net>
The auto-merge-deps workflow listed both `pull_request_target` and
`push:` as triggers. In practice GitHub fired it only on push events —
the last 100+ runs were all `push`, zero were `pull_request_target` —
even though the sibling `pr-labeler.yml` (only `pull_request_target`)
fires correctly. The job-level `if: github.event_name == 'pull_request_target'`
then skipped every step on those push runs, recording each as failure
with 0 successful steps.

Two changes:
- Drop the `push:` trigger so only pull_request_target events run.
- Drop the job-level gate; gate each step instead and add a sentinel
  first step so non-Dependabot PRs still record as success rather
  than 0-step failure.

#231 attempted this with job-level if assuming "all-skipped = success",
but GitHub treats 0-job runs as failure regardless.
The approval body string contained Auto-approved: — an unquoted
colon inside an unquoted YAML scalar. PyYAML rejects this with
`mapping values are not allowed here`, and GitHub Actions appears
to silently fail to register the workflow's `pull_request_target`
trigger as a result (the workflow only ever fires on push events,
the friendly name from `name:` never resolves in the API). Sibling
`pr-labeler.yml` has no such ambiguity and fires correctly.

Dropping the colon from the body resolves both symptoms without
needing to nest YAML quoting.
---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-version: 10.0.1
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: test
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.5.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: test
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps Microsoft.EntityFrameworkCore from 10.0.5 to 10.0.8
Bumps Microsoft.EntityFrameworkCore.Design from 10.0.5 to 10.0.8
Bumps Microsoft.EntityFrameworkCore.InMemory from 10.0.5 to 10.0.8
Bumps MySql.EntityFrameworkCore from 10.0.1 to 10.0.7

---
updated-dependencies:
- dependency-name: Microsoft.EntityFrameworkCore
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ef-core
- dependency-name: Microsoft.EntityFrameworkCore.Design
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ef-core
- dependency-name: MySql.EntityFrameworkCore
  dependency-version: 10.0.7
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ef-core
- dependency-name: Microsoft.EntityFrameworkCore.InMemory
  dependency-version: 10.0.8
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: ef-core
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: hokiepokedad2 <38219945+hokiepokedad2@users.noreply.github.com>
Loose .png screenshots from Playwright MCP sessions and the `.playwright-mcp/`
output directory keep showing up as untracked at the repo root. None of them
belong in the tree (tracked PNGs all live under
`Applications/Pgan.PoracleWebNet.App/ClientApp/public/assets/`). Add a
root-only `/*.png` rule plus `.playwright-mcp/` so `git status` stays clean.
#260) (#279)

LikeEscape (added in #232) used `\` as the SQL LIKE escape character,
and ScannerService.SearchGymsAsync passed `\` to EF.Functions.Like
via `"\\"`. MariaDB's default mode (`NO_BACKSLASH_ESCAPES=OFF`) also
treats `\` as a string-literal escape, so an escaped `\` in the
pattern (which LikeEscape itself produces for user-supplied
backslashes) left the SQL string literal unbalanced and broke gym
search with `near ''\')`.

Switch the escape character to `|`, which has no special meaning in
MariaDB string literals. The LIKE pattern can no longer interact with
quote escaping no matter what the user types. Added a `LikeEscape.EscapeChar`
constant so callers stay in sync.

Tests updated to match the new escape sequences.

Reported by @prof-miles0 in #260.
Bumps the angular group in /Applications/Pgan.PoracleWebNet.App/ClientApp with 13 updates:

| Package | From | To |
| --- | --- | --- |
| [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations) | `21.2.14` | `21.2.15` |
| [@angular/cdk](https://github.com/angular/components) | `21.2.12` | `21.2.13` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `21.2.14` | `21.2.15` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `21.2.14` | `21.2.15` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `21.2.14` | `21.2.15` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `21.2.14` | `21.2.15` |
| [@angular/material](https://github.com/angular/components) | `21.2.12` | `21.2.13` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `21.2.14` | `21.2.15` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `21.2.14` | `21.2.15` |
| [@angular/build](https://github.com/angular/angular-cli) | `21.2.12` | `21.2.13` |
| [@angular/cli](https://github.com/angular/angular-cli) | `21.2.12` | `21.2.13` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `21.2.14` | `21.2.15` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `21.2.14` | `21.2.15` |


Updates `@angular/animations` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/animations)

Updates `@angular/cdk` from 21.2.12 to 21.2.13
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](angular/components@v21.2.12...v21.2.13)

Updates `@angular/common` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/common)

Updates `@angular/compiler` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/compiler)

Updates `@angular/core` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/core)

Updates `@angular/forms` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/forms)

Updates `@angular/material` from 21.2.12 to 21.2.13
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](angular/components@v21.2.12...v21.2.13)

Updates `@angular/platform-browser` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/platform-browser)

Updates `@angular/router` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/router)

Updates `@angular/build` from 21.2.12 to 21.2.13
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@v21.2.12...v21.2.13)

Updates `@angular/cli` from 21.2.12 to 21.2.13
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@v21.2.12...v21.2.13)

Updates `@angular/compiler-cli` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/compiler-cli)

Updates `@angular/platform-browser-dynamic` from 21.2.14 to 21.2.15
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.15/packages/platform-browser-dynamic)

---
updated-dependencies:
- dependency-name: "@angular/animations"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cdk"
  dependency-version: 21.2.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/common"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/compiler"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/core"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/forms"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/material"
  dependency-version: 21.2.13
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/platform-browser"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/router"
  dependency-version: 21.2.15
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/build"
  dependency-version: 21.2.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cli"
  dependency-version: 21.2.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/compiler-cli"
  dependency-version: 21.2.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 21.2.15
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
#259) (#280)

* feat(raids): redesign level selector with named tiers + custom palette (#259)

The raid/egg add dialog had three level-pickers (raid checkboxes, egg
checkboxes, boss-level dropdown) all driven by a hardcoded
`levels = [1, 2, 3, 4, 5, 6]` array, even though PoracleNG accepts
any positive integer. Users with Elite Raids (level 7) or custom
server schemes had to configure those via the bot's `!command`
interface; the UI silently locked them out.

Replace all three sites with a new `<app-level-selector>` shared
component — a Material 3 chip listbox in three sections:

- STANDARD: T1-T5
- SPECIAL:  Mega (6), Elite (7), plus "Any" (9000) when showAny=true
- CUSTOM:   any user-added integer, persisted per-user in localStorage

Power users add a custom level via an inline "+ Add level" affordance
that transforms into a numeric input. The chip then persists across
dialog opens (one-click selection on subsequent alarms) and seeds
itself from saved alarm data on open, so editing an existing
level-42 alarm renders the chip pre-selected rather than orphaned.

Single source of truth for label resolution lives in
`core/models/raid-level.models.ts`. `resolveLevel(value)` maps any
integer to the right LevelOption — adopted by raid-list cards too,
so the dialog and the cards now speak the same vocabulary
("Elite", not "Level 7" vs "7" on different surfaces).

Edge cases:
- 0 / negatives / non-integers in custom input -> inline validation error
- 9000 in custom input -> snaps to the "Any" chip (no duplicate)
- duplicate of built-in -> flashes existing chip + selects, no new entry
- 20-entry LRU cap on the localStorage palette

i18n: new `RAIDS.LEVEL.*` keys added in all 11 locales with English
fallbacks for non-en (translation volunteers can localize later,
per discussion #211).

Bonus correctness: the boss tab used to default level=0 ("any") but
PoracleNG's canonical wildcard sentinel is 9000. New alarms now use
9000; old alarms with 0 continue to work and edit fine.

37 new unit tests across the model, store, pipe, and component.

Closes #259, reported by @prof-miles0.

* fix(raids): address #259 review — compact layout, per-type palette, unblock save

Follow-up on d58752e (the initial #259 redesign), addressing visual,
correctness, and backend-validation issues found during testing.

UI / UX
- Collapse the three-section (Standard/Special/Custom) chip layout
  into one wrapping row per picker. Categories are encoded in chip
  content (T1 / "Mega · 6" / "42 ⊗") rather than container labels;
  cuts dialog height roughly in half.
- Replace the heavy mat-form-field "+ Add custom level" with a
  chip-sized inline numeric input. Enter commits, Esc cancels,
  blur commits. Help text only renders when the input is open or
  there's a validation error.
- Override Material 3 selected-chip font-weight so the selected
  state actually pops; bind `hideSingleSelectionIndicator` to
  `!multiple` so multi-select chips get a leading checkmark.
- Cap card star icons to levels 1-7 (was 1-100) — alarms at
  level 23 no longer render 23 stars in the card.

Per-type palette
- Adding a custom level on the raid picker was leaking it into the
  egg and boss pickers. `CustomLevelStore` now keys palettes by
  `paletteKey` ("raid" / "egg" / "boss"), each persisted to its own
  localStorage slot. Required `paletteKey` input on
  `<app-level-selector>`.

Any chip surfaced where PoracleNG actually honors it
- Raid + boss pickers show the `Any` chip (PoracleNG treats
  level=9000 as the wildcard sentinel — see trackingRaid.go).
- Egg picker deliberately omits Any: PoracleNG's trackingEgg.go
  only validates level >= 1 with no wildcard semantic, so an "Any
  egg" alarm at 9000 would simply never fire.

Server-side fix that was blocking custom-level alarms
- `[Range(0, 10)]` on `RaidCreate.Level`, `RaidUpdate.Level`,
  `EggCreate.Level`, `EggUpdate.Level` was rejecting custom
  integers (8+) and the new Any=9000 sentinel with 400 Bad
  Request before they could reach PoracleNG. Relaxed to
  `[Range(0, int.MaxValue)]` matching PoracleNG's actual range.

Label vocabulary consistency
- Edit dialog (raid/egg) now uses the same `resolveLevel` resolver
  as the cards via the new `LevelLabelPipe` — an alarm at level 7
  reads "Elite" on the card AND in the edit dialog (was "Level 7"
  in the dialog before). Egg image alt-text in the card list now
  uses the pipe too.

Error UX
- Removing a custom chip (`⊗`) opens a 3-second snackbar with
  Undo — accidental click is recoverable; intentional removal
  still wipes the palette entry.

State-machine clarity
- `addInputOpen: signal(boolean)` replaced with an explicit
  `addMode: signal<'closed' | 'open'>` and named `isAddClosed()` /
  `isAddOpen()` getters in the template — removes the `!` negation
  pattern that prior renders sometimes appeared to misread.

Tests
- Updated `custom-level-store.service.spec.ts` for the keyed API.
- Updated `level-selector.component.spec.ts` to set `paletteKey`
  per test and assert per-key isolation.
- 697/697 frontend tests pass, 1063/1063 backend tests pass.

i18n
- Added `RAIDS.LEVEL.REMOVED` and `COMMON.UNDO` keys in all 11
  locales (English placeholder text for non-en — translation
  volunteers per discussion #211).

* fix(raids): align level selector with WatWowMap masterfile (19 named levels)

Builds on the v2 review-pass (2c2f0aa). Follow-up driven by the issue
reporter pointing to the canonical Pokémon GO raid level vocabulary in
the WatWowMap masterfile — there are 19 named raid types (1-Star
through Coordinated 2), not 7, and the prior UI labeled level 7 as
"Elite" when the masterfile says it's "Mega Legendary".

Backend
- `GET /api/masterdata/raid-levels` returns the canonical list with
  per-level integer, category, and singular/plural English names.
- New `IRaidLevelService` / `RaidLevelService` returns a baked-in
  snapshot of the masterfile. A TODO documents how to swap the
  implementation for a live fetch from
  raw.githubusercontent.com/WatWowMap/Masterfile-Generator without
  changing the wire contract.
- 6 new unit tests cover the service + controller endpoint.

Frontend
- `RaidLevelService` (Angular) calls the new API on first dialog use,
  caches the result in a signal. Falls back to `KNOWN_LEVELS`
  baked-in constants when the network fails or before resolve.
- `raid-level.models.ts` rewritten around 19 canonical levels keyed
  by `RAIDS.LEVEL.RAID_1` through `RAID_19` (plus `_PLURAL` variants).
  Removed the bogus `T1`-`T5` / `MEGA` / `ELITE` keys.
- `LevelSelectorComponent` simplified to a `pickerType` input
  (`'raid' | 'egg' | 'boss'`). Inputs:
    • raid  → primary chips 1-7, overflow menu for 8-19, Any chip, +Add
    • egg   → star tiers (1-5) only, +Add (no overflow, no Any)
    • boss  → single-select with the same primary + overflow as raid
  "More raid types…" overlay menu (mat-menu) surfaces the 12 less
  common levels without crowding the chip row.
- i18n: 19 singular + 19 plural keys in all 11 locales, with English
  placeholders for the 10 non-en locales (volunteers per #211).
- Card star icons now render only for the literal 1-5 "N Star Raid"
  tier (was 1-7, producing ~23 stars for custom-level alarms).
- Label vocabulary consistency: alarm at level 7 now reads "Mega
  Legendary Raid" on the card and in the edit dialog (was "Elite"
  on the card, "Level 7" in the edit dialog).

Forward compatibility
- Any positive integer remains addable via the `+ Add` chip. When
  the WatWowMap masterfile adds raid_20+ in the future, the backend
  service can pick it up automatically (once the live-fetch path is
  wired); existing custom alarms at that level continue to work.

Tests: 711/711 frontend, 1069/1069 backend. Lint + prettier clean.

* fix(raids): shorten labels, ephemeral palette, review fixes

Follow-up on 12be778 (v3 masterfile alignment). User feedback +
internal PR review revealed several issues; this commit addresses
them.

User feedback
- Custom levels typed via `+ Add` were persisting across modal
  close AND page refresh because the per-type palette was backed
  by localStorage. Deleted CustomLevelStore entirely; LevelSelector
  now tracks the palette in a local `customPalette` signal that
  lives for the component lifetime only. Refresh or close-and-reopen
  wipes typed-but-not-saved chips. Existing alarms still seed the
  palette through the `[value]` input.
- Chip labels were too long ("Mega Legendary Raid"), and the same
  string caused "All Mega Legendary Raid Raids" double-Raid in card
  titles. Dropped the "Raid" suffix from the 19 RAID_N keys in all
  11 locales — chips now read "Mega Legendary", "Legendary",
  "1 Star", etc. The card-title template
  (`RAIDS.ALL_LEVEL_RAIDS = "All {{level}} Raids"`) supplies the
  noun once; result reads natural English. Also dropped the unused
  `pluralKey` from `LevelOption` and the `_PLURAL` i18n keys (the
  shortened `RAID_N` strings work in both card and chip contexts).
  Backend `RaidLevelInfo.Name` is now the modifier form
  ("Mega Legendary") while `NamePlural` retains the full
  "Mega Legendary Raids" for any future standalone use.

Review fixes (MUST FIX)
- Snackbar undo subscription in `LevelSelector.removeCustom` now
  pipes through `takeUntilDestroyed(this.destroyRef)` so closing
  the dialog mid-toast can't fire the callback against a destroyed
  component.
- `raid-list.getRaidLevelName` was bypassing the live
  `RaidLevelService.byValue()` and using the baked-in `KNOWN_LEVELS`
  constant — cards would drift from the dialog if the API ever
  extended the canonical list. Cards now consult the service first,
  fall back to the baked-in resolver. `raid-list.ngOnInit` primes
  the cache so the list page doesn't depend on a dialog open.
- `LevelLabelPipe` now detects ngx-translate's "key not found"
  pass-through (translated string === key) and falls back to
  "Level {n}" instead of leaking "RAIDS.LEVEL.RAID_20" into the UI.
  Graceful degradation for future masterfile additions before
  locales catch up.

Review fixes (SHOULD FIX)
- `raid-edit-dialog.formatLevel` deleted — the dialog now injects
  `LevelLabelPipe` and calls `.transform()`, eliminating the
  duplicate label-resolution logic. Single source of truth.

Analyzers
- xUnit2032 in `MasterDataControllerRaidLevelsTests`: switched
  `Assert.IsAssignableFrom<T>` to `Assert.IsType<T>(..., exactMatch:
  false)`.
- CA1707 in `RaidLevelServiceTests` and the new controller test:
  test method names renamed to PascalCase to match the project's
  preferred style and silence the analyzer.

Dev workflow
- New `proxy.conf.json` forwards `/api/*` and `/auth/*` from the
  Angular dev server to the API. `environment.development.ts`
  apiUrl set to `''` so all HTTP calls are same-origin from the
  browser's view — works identically for `ng serve` + proxy and
  for the production single-port deployment. OAuth flows survive
  the proxy because Host is preserved.

Tests: 700/700 frontend (+1 fallback test), 1069/1069 backend.
Lint + prettier + dotnet format (scoped) all clean.

* docs: cover the level-selector redesign + ng-serve proxy workflow

- features/alarms.md: replace the generic "tier" wording on Raids/Eggs
  rows with pointers to a new "Raid level selector" subsection that
  documents the chip layout, the 19 masterfile-defined raid types,
  primary vs overflow split per pickerType, the ephemeral custom-add
  affordance, and the wildcard sentinel.
- architecture/backend.md: add a "Raid level service" section
  documenting IRaidLevelService, GET /api/masterdata/raid-levels, the
  baked-in fallback + live-fetch upgrade path, and the [Range] relax
  that lets PoracleNG-accepted custom integers pass validation. Also
  register the singleton in the service lifetimes table.
- architecture/frontend.md: document LevelSelectorComponent + the
  Angular RaidLevelService consumer (signal cache, baked-in fallback,
  LevelLabelPipe missing-key fallback), and the ephemeral palette
  behavior.
- getting-started/development-setup.md: the "proxies API requests"
  claim is now accurate thanks to the committed proxy.conf.json —
  describe it explicitly (changeOrigin: false to preserve Host for
  OAuth callbacks), note the empty apiUrl + same-origin dev flow,
  and document the --port override for matching a non-default
  Discord OAuth redirect URI.
The standalone `dotnet run` DataProtection fallback writes keys to
Applications/Pgan.PoracleWebNet.Api/data/ (Program.cs uses ./data when
DATA_DIR is unset), and the published Angular bundle is copied into the
API host at Applications/Pgan.PoracleWebNet.Api/wwwroot/. Both are
regenerated build/runtime output and were showing up as untracked.

The existing Data/dataprotection-keys/ rule only covered the Data
project path, not the API host path. Added both so a local build/run
leaves a clean working tree.
Poracle's `pvp_ranking_cap` field was never surfaced by PoracleWeb.NET, so
every PvP alarm defaulted to matching all caps (L50 + L51) server-side.
New users got flooded with L51 noise even when admins configured
`tracking.defaultUserTrackingLevelCap = 50` in Poracle.

This wires `pvp_ranking_cap` end-to-end and mirrors the PoracleWeb PHP
passthrough pattern — no new admin setting; the cap list and default
come from Poracle's existing `/api/config/poracleWeb` response
(`pvpCaps`, `defaultPvpCap`).

Backend:
- `Monster` / `MonsterCreate` / `MonsterUpdate` / `MonsterEntity`:
  new `PvpRankingCap` field (0 = all caps).
- `AlarmMappingExtensions.ToMonster` + `ApplyUpdate`: mapping + null-skip.
- `PoracleConfig.PvpCaps` (list) and `DefaultPvpCap` (int), parsed in
  `PoracleApiProxy.GetConfigAsync`. Accepts number or string caps
  (PoracleJS is inconsistent on this).
- `QuickPickService.SafeMonsterFilterKeys`: allow `pvpRankingCap` so
  quick-pick authors can pin a cap per definition.

Frontend:
- `Monster.pvpRankingCap`, `PoracleServerConfig` interface.
- New `PoracleConfigService` caches `/api/config` behind a signal.
- `pokemon-add-dialog`: `mat-button-toggle-group` under the PvP league
  field with `All` / `L{cap}` options. Pre-fills from `defaultPvpCap`.
  Italic "Default · from Poracle config" hint disappears the moment
  the user changes the selection. Hidden entirely when Poracle offers
  only one cap.
- `pokemon-edit-dialog`: same toggle group; shows stored cap on load.

Tests (+1066 backend, +658 frontend):
- Mapping tests cover `PvpRankingCap` in `ToMonster`, null-skip
  `ApplyUpdate`, and explicit-overwrite cases.
- `ConfigControllerTests` verify `PvpCaps` + `DefaultPvpCap` flow
  through the controller unmodified.
- `monster.service.spec.ts` fixtures updated with the new field.
)

* feat(raids): RSVP notification mode for raid and egg alarms (#233)

Surface the existing `rsvpChanges` field as a three-option mode toggle
(Matches only / Matches + RSVP / RSVP only) in the raid & egg add/edit
dialogs, with a matching pill on alarm cards.

The field, mapping, and dialog form binding already exist on main; this
adds the missing UI control and the third mode value.

- New self-contained shared components: rsvp-toggle (FormControl input)
  and rsvp-pill (numeric value input).
- Widen [Range(0, 1)] -> [Range(0, 2)] on RsvpChanges in RaidCreate,
  RaidUpdate, EggCreate, EggUpdate so mode 2 isn't rejected with HTTP 400.
- Wire rsvp-toggle into both dialogs (raid + egg) bound to the
  rsvpChanges form control; rsvp-pill onto raid/egg cards.
- RSVP i18n keys added to all 11 locales (incl. new pl/sv/da).
- RsvpRangeValidationTests covering the 0..2 range and null updates.

Salvaged from #235, dropping that branch's raid-dialog section-refactor
which conflicted with the #280 level-selector restructure already on main.

* feat(raids): set edit-in-place bit when RSVP updates are enabled

PoracleNG's `clean` field is a bitmask (bit 1 = auto-delete, bit 2 =
edit-in-place). Raid/egg RSVP updates are PoracleNG's first edit-tracking
consumer: with the edit bit set, RSVP count changes edit the existing
alert in place; without it, each change sends a brand-new message.

Verified against PoracleNG main (processor/internal/dts/renderer.go):
the per-user editKey is gated on db.IsEdit(user.Clean), so RSVP mode
alone is not enough — the edit bit must accompany it.

- raid/egg add + edit dialogs: OR in `clean` bit 2 when rsvpChanges >= 1.
- edit dialog: read the auto-delete toggle from `clean & 1` (was
  `clean === 1`) so it round-trips correctly once bit 2 can be set.
- raid-list: new isAutoDelete() helper masks bit 1 for the card
  auto-delete badge (Angular templates can't express bitwise &).
- CHANGELOG + docs note the edit-in-place coupling.

* style(raids): align RSVP toggle + pill with the app design system

The RSVP components were copied from a pre-#280 branch and used a bespoke
look (stacked icon+label+description button rows, hardcoded indigo pill)
that didn't match the current Material 3 language.

rsvp-toggle: rebuilt to mirror the #237 PvP-cap pattern — a <fieldset>
with an uppercase <legend> section header, a plain full-width segmented
mat-button-toggle-group (no icons/no inline descriptions), and a single
hint below that shows the selected mode's description (so the "RSVP only
silences without a scanner" caveat stays visible). Uses --text-muted /
--text-secondary tokens instead of raw opacity.

rsvp-pill: now a .clean-tag-style status badge themed with --mat-sys-primary
/ --mat-sys-on-primary (was hardcoded #3f51b5). Moved out of the stat grid
into card-top-actions so it sits beside the auto-delete tag as a sibling
status indicator.

Specs updated for the new structure; docs reworded (themed badge, not
"indigo pill"). prettier/lint/jest(712)/ng build all green.

* chore: keep Dockerfile.local out of the PR (local test artifact)

* style(raids): square off the RSVP toggle ends (--mat-button-toggle-shape)

M3 defaults the segmented button group to a pill radius; override the
shape token to 4px so the end segments read as a crisp Material control
rather than a rounded pill.

* fix(raids): stop RSVP toggle overflow + vertically center labels

- fieldset defaulted to min-inline-size: auto and overflowed its container
  (right edge clipped); force min-inline-size: 0 / width 100% / border-box.
- flex-center the button-toggle label content so single-line options align
  with the wrapped 'Matches + RSVP updates' segment.

* fix(raids): RSVP toggle overflow (drop fieldset, border-box) + drop dead i18n key

- Replace the <fieldset>/<legend> with a plain block + border-box group so
  the segmented control fits the dialog width (right edge was clipped); the
  toggle group keeps its aria-label for the accessible name.
- Remove the now-unused RSVP_HINT key from all 11 locales (the restyle
  replaced the static hint with the per-mode description).

* fix(raids): widen Clean [Range] to bitmask 0-7 so RSVP edit bit saves

The RSVP edit-in-place coupling sets clean bit 2 (clean = 2 or 3), but
Clean was still [Range(0, 1)] on RaidCreate/RaidUpdate/EggCreate/EggUpdate
-> creating/editing an RSVP alarm failed model validation with HTTP 400
('failed to create alarm'). clean is a PoracleNG bitmask (auto-delete |
edit-in-place | summary); widened to [Range(0, 7)]. Added validation tests.

* style(raids): hide RSVP toggle selection checkmark for more label room

Single-select group, so the M3 checkmark only ate ~24px and pushed labels
to wrap. hideSingleSelectionIndicator drops it; the accent fill + bold
already signal the selected mode.
node:22-alpine bundles npm 10.9.x, which rejects the npm-11-generated
package-lock.json with EUSAGE (pruned chokidar/readdirp optional peers),
so docker build / compose up --build failed from source. CI already pins
npm 11 for this; mirror it in the Dockerfile's angular-build stage.
…292 PR1) (#294)

PoracleNG reads `clean` as a 3-bit bitmask (1=auto-delete, 2=edit-in-place,
4=summary) but PoracleWeb treated it as a boolean for 8 of 10 alarm types,
which (a) 400'd bot-set values >1 via [Range(0,1)] and (b) clobbered bits
2/4 on every web edit. This is the invisible correctness fix; the lure-edit
and quest-summary user controls follow in PR2.

- New CleanFlags helper (Core.Models) + clean-flags.ts twin with
  Preserve(existing, mask, changes) read-modify-write; unit tests for both.
- Widen Clean [Range(0,1)] -> [Range(0,7)] on the 16 Monster/Quest/Invasion/
  Lure/Nest/Gym/MaxBattle/FortChange Create+Update models (Raid/Egg already done).
- CleaningService: preserve unknown bits on bulk-clean toggle; bit-aware AllClean.
- All 10 alarm types' edit dialogs preserve unknown bits on save and read
  auto-delete via the bit; list cards + profile overview gate the badge via
  an isAutoDelete() method (Angular templates can't parse bitwise &).
- Fix the raid/egg RSVP save dropping bit 4; fix the quick-pick apply clobber.
- Tests: CleanFlags, clean-range validation (8 types), CleaningService bit
  preservation, mapping round-trip. Backend 1324 pass; frontend 743 pass.
…PR2) (#295)

* feat(alarms): lure edit-in-place + quest daily-summary controls (#292 PR2)

Surfaces the two remaining meaningful clean bits as user controls, building
on PR1's CleanFlags helper and preservation fixes.

- Lure add+edit dialogs: "Edit message in place" toggle (clean bit 2),
  default off, edit-dialog inits from isEdit() and save composes via
  preserve(clean, AUTO_DELETE|EDIT, ...) so the summary bit survives.
- Quest add+edit dialogs: "Daily summary" toggle (clean bit 4), default off,
  same preserve pattern; hint notes it needs a summary schedule on the bot.
- Card badges: lure edit (--mat-sys-secondary), quest summary
  (--mat-sys-tertiary), gated via methods, matching .clean-tag/.rsvp-tag.
- i18n: LURES.EDIT_* / QUESTS.SUMMARY_* added + translated in all 11 locales.
- Only lure/quest get controls (the only types whose PoracleNG processor
  reads the bit). New dialog specs cover init-from-bit + save-preserves-bits.

Frontend: prettier/eslint/build clean, jest 781 pass. No backend change.

* docs(#292): document clean delivery modes (alarms doc, in-app help, CLAUDE.md)

- docs/features/alarms.md: new 'Delivery & message modes' section covering
  the clean bitmask (auto-delete / edit-in-place / daily-summary), which
  types support each, and that PoracleWeb preserves bot-set bits (gh-pages).
- In-app Help (HELP.CONTENT_DELIVERY): appended an 'Edit in place & summaries'
  block describing the lure edit + quest daily-summary modes, translated in
  all 11 locales.
- CLAUDE.md: dev note on the clean bitmask + CleanFlags helper + the Angular
  'templates can't parse &' gotcha.

* docs(rsvp): document RSVP notification mode (alarms doc + in-app help, 11 locales)

Mirrors the #292 delivery-mode docs for RSVP (#233), authored by a
tech-writer swarm:
- docs/features/alarms.md: new '### RSVP updates (raids & eggs)' subsection
  under Delivery & message modes, explaining the 3 modes + edit-in-place
  coupling + the scanner caveat.
- In-app Help (HELP.CONTENT_DELIVERY): appended an 'RSVP updates' block in
  all 11 locales, alongside the edit/summary block.

Jest 781 pass; all 11 i18n files valid JSON.
Bumps [peter-evans/create-pull-request](https://github.com/peter-evans/create-pull-request) from 7 to 8.
- [Release notes](https://github.com/peter-evans/create-pull-request/releases)
- [Commits](peter-evans/create-pull-request@v7...v8)

---
updated-dependencies:
- dependency-name: peter-evans/create-pull-request
  dependency-version: '8'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [marocchino/sticky-pull-request-comment](https://github.com/marocchino/sticky-pull-request-comment) from 2 to 3.
- [Release notes](https://github.com/marocchino/sticky-pull-request-comment/releases)
- [Commits](marocchino/sticky-pull-request-comment@v2...v3)

---
updated-dependencies:
- dependency-name: marocchino/sticky-pull-request-comment
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](actions/upload-artifact@v4...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/github-script](https://github.com/actions/github-script) from 7 to 9.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](actions/github-script@v7...v9)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-version: '9'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps Microsoft.NET.Test.Sdk from 18.5.1 to 18.6.0

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-version: 18.6.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: microsoft
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the eslint group in /Applications/Pgan.PoracleWebNet.App/ClientApp with 5 updates:

| Package | From | To |
| --- | --- | --- |
| [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) | `8.59.4` | `8.60.1` |
| [@typescript-eslint/parser](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/parser) | `8.59.4` | `8.60.1` |
| [@typescript-eslint/utils](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/utils) | `8.59.4` | `8.60.1` |
| [eslint-import-resolver-typescript](https://github.com/import-js/eslint-import-resolver-typescript) | `4.4.4` | `4.4.5` |
| [eslint-plugin-prettier](https://github.com/prettier/eslint-plugin-prettier) | `5.5.5` | `5.5.6` |


Updates `@typescript-eslint/eslint-plugin` from 8.59.4 to 8.60.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.60.1/packages/eslint-plugin)

Updates `@typescript-eslint/parser` from 8.59.4 to 8.60.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/parser/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.60.1/packages/parser)

Updates `@typescript-eslint/utils` from 8.59.4 to 8.60.1
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/utils/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v8.60.1/packages/utils)

Updates `eslint-import-resolver-typescript` from 4.4.4 to 4.4.5
- [Release notes](https://github.com/import-js/eslint-import-resolver-typescript/releases)
- [Changelog](https://github.com/import-js/eslint-import-resolver-typescript/blob/master/CHANGELOG.md)
- [Commits](import-js/eslint-import-resolver-typescript@v4.4.4...v4.4.5)

Updates `eslint-plugin-prettier` from 5.5.5 to 5.5.6
- [Release notes](https://github.com/prettier/eslint-plugin-prettier/releases)
- [Changelog](https://github.com/prettier/eslint-plugin-prettier/blob/main/CHANGELOG.md)
- [Commits](prettier/eslint-plugin-prettier@v5.5.5...v5.5.6)

---
updated-dependencies:
- dependency-name: "@typescript-eslint/eslint-plugin"
  dependency-version: 8.60.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/parser"
  dependency-version: 8.60.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: "@typescript-eslint/utils"
  dependency-version: 8.60.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: eslint
- dependency-name: eslint-import-resolver-typescript
  dependency-version: 4.4.5
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
- dependency-name: eslint-plugin-prettier
  dependency-version: 5.5.6
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: eslint
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/setup-node](https://github.com/actions/setup-node) from 4 to 6.
- [Release notes](https://github.com/actions/setup-node/releases)
- [Commits](actions/setup-node@v4...v6)

---
updated-dependencies:
- dependency-name: actions/setup-node
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
)

Surface the Poracle `notes` field on channel-type users in the admin user
list so admins can disambiguate channels that share the same name across
different servers. PoracleJS/PoracleNG can auto-fill notes with the Discord
guild name and channel category; that column already existed on the humans
table but was dropped at every layer.

Reuses data PoracleNG already provides — no new database queries and no live
Discord API calls:
- Single-user reads come from the PoracleNG human JSON (HumanService
  .DeserializeHuman now reads `notes`).
- The admin bulk list maps the `notes` column through the existing read
  (Human model + EntityMappingExtensions); projected by GET /api/admin/users
  and GET /api/admin/users/by-id.

Frontend renders notes as a muted second line under the name with a tooltip,
and the admin search box matches against it. A notesLabel() normalizer trims
whitespace and strips a surrounding quote layer so PoracleJS/NG's quoted-empty
`""` sentinel (and any JSON-quoted note) doesn't render a stray value.

Tests: extend HumanEntity.ToModel mapping test and the admin.service spec mock.
)

* feat: add admin setting to disable user-submitted geofences (#297)

From discussion #214: let operators turn off the custom/user-drawn
geofence feature via a new `disable_user_geofences` site setting,
reusing the existing `disable_*` feature-gate pattern.

Backend
- DisableFeatureKeys.UserGeofences constant.
- Gate the "provide a geofence" actions on UserGeofenceController
  (create, submit-for-review, GeoJSON import) with
  [RequireFeatureEnabled], plus a defense-in-depth
  IFeatureGate.EnsureEnabledAsync guard in UserGeofenceService
  .CreateAsync (also covers import, which funnels through it) and
  .SubmitForReviewAsync.
- Reads, delete, activate/deactivate and the admin review queue stay
  ungated so existing geofences keep working and are still served by
  /api/geofence-feed.
- SettingsMigrationService CategoryMap + BooleanKeys carry the key.

Frontend
- Hide the My Geofences nav item (disableKey) and guard the
  /geofences route (disabledFeatureGuard) -> redirect to dashboard
  with the existing ERROR.FEATURE_DISABLED toast; the 403 interceptor
  handles direct API hits.
- Admin settings toggle in the Features group.
- ADMIN_SETTINGS.DISABLE_USER_GEOFENCES_* label/description added and
  translated across all 11 locales.

Tests: UserGeofenceService gate tests for CreateAsync and
SubmitForReviewAsync; existing test setup updated for the new
IFeatureGate dependency.

* feat: hide admin "User Geofences" review queue when disabled

Extend disable_user_geofences to also hide the admin-facing geofence
review queue: add the disableKey to the /admin/geofence-submissions
nav item, make the adminNavItems computed honour isFeatureDisabled
(it previously ignored disableKey), and guard the route with
disabledFeatureGuard. Enabling the toggle now hides the whole feature
end to end. The admin review backend stays ungated so any pre-existing
submissions aren't bricked and reappear if the feature is re-enabled.
hokiepokedad2 and others added 29 commits June 3, 2026 13:47
New alarms always opened pre-set to Areas; radius users had to switch the
location mode and re-type a distance on every add. Add a user-level default.

- AlertDefaultsService persists mode + default distance (km) to localStorage,
  mirroring the theme/accent/language pattern; distance clamped 0.1-100 km.
- New Alert Defaults dialog (user menu) reusing the distance-dialog idiom:
  Areas/Distance mode cards, km input, live delivery preview.
- All 9 add-alarm dialogs (Pokemon, Raids/Eggs, Quests, Invasions, Lures,
  Nests, Gyms, Fort Changes, Max Battles) and the quick-pick apply dialog
  seed distanceMode/distanceKm from the service instead of hard-coded values.
- ALERT_DEFAULTS.* + MENU.ALERT_DEFAULTS i18n keys across all 11 locales.
- Service + dialog unit tests; CHANGELOG entry.
- Docs: gh-pages site (features/alarms.md "Default delivery scope" section +
  Quick Picks note, index.md + README feature bullets), in-app Help (Delivery
  Settings section), and CLAUDE.md developer note.

Tracks discussion #217.
)

#301 changed the quick-pick apply dialog (and every add-dialog) to seed the delivery
form's distanceKm from AlertDefaultsService.defaultDistanceKm() (default 1 km), so the
radius is pre-filled if the user switches to Distance mode. The
quick-pick-apply-dialog spec still asserted the pre-#301 default of 0, so it failed and
turned the Frontend (Angular) CI red on main from the #301 merge onward.

The component is correct and matches all sibling add-dialogs (in Areas mode apply()
sends 0 m regardless of distanceKm); only the assertion was stale. Updated it to expect
the AlertDefaultsService default (1) with a comment.

Verified: full Jest suite green (792/792), prettier + eslint clean.
* feat(quests): quest summary delivery schedule management UI (#300)

Implements the deferred summary_schedules management UI from #292 — the piece
the per-alarm quest "Daily summary" clean-bit toggle (#295) depends on. Users
can now view, edit, clear, and force-deliver ("Send summary now") their quest
summary schedule, wired to PoracleNG's /api/summaries endpoints.

Backend
- IPoracleSummaryProxy / PoracleSummaryProxy mirroring PoracleHumanProxy:
  X-Poracle-Secret, Uri.EscapeDataString, raw-JSON active_hours pass-through,
  404 -> null, 503 -> SummaryBackendUnavailableException (transient, not
  feature-off). Distinguishes 400/404/500 rather than collapsing them.
- SummaryScheduleController: GET/GET{alertType}/PUT/DELETE/POST trigger, all
  derived from this.UserId (JWT) with NO {userId} route segment (IDOR-safe);
  [RequireFeatureEnabled(disable_quests)]; trigger rate-limited test-alert
  (5/60s), writes auth-read; quest-only alertType allow-set.
- Capability from tracking.quest_summary_enabled via the config proxy, surfaced
  as questSummaryEnabled in auth/me (Golbat-style 200 boolean), IMemoryCache
  5-min. Defaults true when the field is absent from a successful config,
  degrades to false on fault.
- Extracted ProfileController.ValidateActiveHours into a shared
  ActiveHoursValidator; both controllers and the tests re-pointed.

Frontend
- SummaryScheduleService (CRUD + trigger, 404 -> null, capability signal).
- SummaryScheduleDialogComponent reusing ActiveHoursEditorDialogComponent and
  LocationWarningComponent; staggered schedule pills, empty/loading states,
  accent-theme tokens, reduced-motion + ARIA; client cooldown/dedup on trigger.
- Quests toolbar menu entry gated on capability; SUMMARY_DISABLED_HINT on the
  quest dialogs when off (clean-bit logic untouched).
- New QUESTS.SUMMARY_SCHEDULE_* keys across all 11 locales.

Tests: PoracleSummaryProxyTests, SummaryScheduleControllerTests,
SummaryCapabilityServiceTests, ActiveHoursValidationTests (re-pointed), and
summary-schedule service + dialog Jest specs.

Verified locally: dotnet test 1382 pass; ng build (AOT) ok; jest feature suites
pass; eslint + prettier clean.

* docs(changelog): add quest summary delivery schedule UI entry (#300)

* fix(quests): return 200 empty schedule (not 404) when no summary schedule exists

Opening the Quest summary delivery dialog calls GET /api/summary-schedules/{alertType},
which returned 404 when the user had no schedule yet — a normal empty state. The SPA's
global error interceptor toasts ERROR.NOT_FOUND on any non-silent 404, so users saw
'The requested resource was not found.' on first open. Return 200 with an empty schedule
(active_hours = []), consistent with the list endpoint returning []. The dialog renders
its empty state and no toast fires.

* feat(quests): honest capability default + Send-now expectation copy (#300)

(1) Default quest-summary capability to OFF when PoracleNG's tracking.quest_summary_enabled
is absent, instead of ON. When the flag is unset PoracleNG's matcher never buffers quests,
so showing the UI was a dead-end (schedule + per-alarm bit set, but nothing ever delivered).
PoracleConfig.QuestSummaryEnabled now defaults false; the menu appears only when the bot has
the feature explicitly enabled. PoracleWeb stays read-only on Poracle config — no toggle here.

(2) "Send summary now" now sets expectations: it flushes only quest matches PoracleNG has
buffered since the last summary, so an empty send isn't surprising. Added
QUESTS.SUMMARY_SCHEDULE_SEND_NOW_HINT (all 11 locales), shown under the schedule pills and as
the button tooltip.

Verified: dotnet test 1382 pass; ng build (AOT) ok; jest + eslint + prettier clean.

* fix(quests): read quest_summary_enabled from /api/config/values, not /api/config/poracleWeb

The capability probe read tracking.quest_summary_enabled from GetConfigAsync() — which hits
/api/config/poracleWeb, a PoracleWeb-specific view that does NOT include the [tracking] section.
So the flag was never read. It happened to "work" only while the default was true-when-absent;
once that flipped to off-when-absent, the menu could never appear even with the flag set on the bot.

Add IPoracleApiProxy.GetQuestSummaryEnabledAsync() which reads the effective value from
/api/config/values (values.tracking.quest_summary_enabled) — the config-editor endpoint that
exposes the merged-with-defaults config. SummaryCapabilityService now uses it: true -> enabled,
false/absent/fault -> hidden. Removed the dead parse in GetConfigAsync and the now-unused
PoracleConfig.QuestSummaryEnabled property; rewrote SummaryCapabilityServiceTests against the
new method.

Verified: dotnet test 1381 pass.

* style(quests): mobile refinements for the summary schedule dialog

- openSummaryDialog now passes maxWidth: '95vw' (matches the reused active-hours
  editor) so the dialog uses the full phone width instead of Material's 80vw default.
- At <=600px: action buttons get a 44px min-height (comfortable thumb targets),
  the "Send summary now" button goes full-width as a clear primary action, and the
  flex spacer is dropped so the secondary buttons pack cleanly.

Verified: ng build (AOT) ok, jest + eslint + prettier clean.

* docs: document quest summary delivery (MkDocs site + in-app help)

gh-pages (MkDocs):
- New features/quest-summary-schedules.md — user + operator guide with a mermaid
  buffer/delivery diagram, the two-part model (per-alarm Daily summary toggle +
  per-user delivery schedule), the schedule editor, Send-now semantics, the
  per-user (not per-profile) note, validation table, timezone/location warning,
  and a "For server operators" section (quest_summary_enabled + processor bind).
- mkdocs.yml: add the page to the Features nav.
- troubleshooting.md: "Quest summary delivery menu is missing" and "Send summary
  now delivers nothing" entries.

In-app help:
- help-sections.ts: new "Quest Summary Delivery" section (schedule_send / amber).
- i18n: HELP.SECTION_QUEST_SUMMARY(+_SUB) and HELP.CONTENT_QUEST_SUMMARY added and
  fully translated for all 11 locales (da, de, en, es, fr, it, nl, pl, pt, pt-BR,
  sv), reusing the existing UI terminology (menu name, Edit schedule, Send now).
- Updated the en Delivery help section's "Daily summary" line to point at the new
  schedule UI instead of "configure on the bot".

Verified: jest (help + i18n parity) pass, ng build (AOT) ok, eslint + prettier clean.

* refactor(quests): code-review cleanups for the summary-schedule feature

- Remove the unused auth/me quest-summary capability "fast-path": nothing consumed
  UserInfo.questSummaryEnabled / auth.service.questSummaryEnabled — the UI gates on
  the dedicated GET /api/summary-schedules/capability endpoint. Drops a per-auth/me
  capability call (a hot path) and dead frontend state. Removed the property,
  AuthController dependency + Me() call, the TS field + computed, and the now-moot
  ISummaryCapabilityService args in the AuthController tests.
- PoracleSummaryProxy now Encode()s the alertType path segment too (defense-in-depth
  consistency with userId), and the helper doc reflects it.
- dotnet format applied to the changed files (whitespace + analyzer fixes: CA1861
  array hoist in tests, redundant `public` removed from IPoracleApiProxy members).

Verified: dotnet test 1381 pass, dotnet format 0 errors on changed files, ng build
(AOT) ok, eslint + prettier clean, jest feature suites pass.
… matches the codebase (#305)

`.editorconfig` had `csharp_preserve_single_line_statements = false`, which makes
`dotnet format` explode the codebase's deliberate compact one-liners. The clearest
victim is `AlarmMappingExtensions.cs`, whose ~98 null-skip mappings
(`if (src.X != null) dest.X = src.X.Value;`) `dotnet format` rewrites into ~480 lines —
a 5x readability regression. The single-line style is used throughout the mapping/guard
code, so the setting contradicted the actual code (and was never enforced — CI does not
run `dotnet format`).

Flipping it to `true` makes `dotnet format` PRESERVE existing single-line statements
(it never collapses multi-line into single-line), so the tool aligns with the codebase
and `dotnet format --verify` stops flagging these files — with zero code changes.

(Sibling `csharp_preserve_single_line_blocks` is left as-is; this targets the reported
single-line *statement* explosion.)
Co-authored-by: hokiepokedad2 <38219945+hokiepokedad2@users.noreply.github.com>
… cut workflow (#307)

The `release-changelog.yml` "Update comparison links" step used
`grep ... | head -2 | tail -1`, which picks the *second*-newest version as the
previous release — an off-by-one. Every cut release since has produced a wrong
`[x.y.z]:` compare link (e.g. `[2.9.0]: compare/v2.7.0...v2.9.0` instead of
`v2.8.0...v2.9.0`), and re-runs accumulated duplicate link-def lines.

- Workflow: `head -2 | tail -1` -> `head -1`. The new version's link-def isn't
  added until the following sed, so the first existing version link is the
  immediately-preceding release.
- CHANGELOG.md: regenerated the footer compare links so each points at its true
  predecessor tag (10 corrected), and removed 5 duplicate link-def lines. Only the
  footer link section changed — no changelog content touched. The three pre-tag
  entries (0.1.0–0.3.0) and the oldest tag (0.4.0) are left as-is.
…308) (#311)

The admin settings page rendered two rows that both wrote to the
allowed_languages key -- "Allowed UI Languages" (Features group) and
"Allowed Languages" (Administration group). The component keys its value
map by the setting key, so the two collapsed onto one entry: editing one
changed the other, and a save could silently clobber the value with an
empty string.

Remove the redundant Administration-group row and its now-unused
ADMIN_ALLOWED_LANGUAGES_LABEL / ADMIN_ALLOWED_LANGUAGES_DESC keys across
all 11 locales, keeping the single Features-group control whose
description matches the actual behavior.
The LanguageSelectorComponent — the only path from the web app to a user's
Poracle DM language (human.Language, which controls alert text and Pokemon
names) — was imported into app.ts but never rendered in any template, so it
was unreachable dead code. The toolbar globe menu only calls i18n.use(),
changing the Angular UI translation, not the bot's DM language.

- Render the selector in a labelled "Notification language" section on the
  Areas & Location page, distinct from the toolbar display-language menu.
- Reconcile its stale hardcoded 18-language list with I18nService.allLanguages
  (the 11 supported locales) so it can't drift again.
- Seed the value from the persisted human.Language via a new
  GET /api/location/language endpoint (reconciles with bot-set changes)
  instead of trusting only localStorage; show success/failure feedback.
- Remove the now-orphaned dead import and app-language-selector style from the
  app shell.
- Add AREAS.NOTIFICATION_LANGUAGE / _DESC / SNACK_LANGUAGE_UPDATED / _FAILED
  i18n keys across all 11 locales.

Whether localized Pokemon names actually render still depends on the Poracle
server having that language's master data loaded — PoracleWeb's responsibility
ends at writing human.Language. Service and component tests cover the new GET
endpoint and the load/save/revert behavior.
Co-authored-by: hokiepokedad2 <38219945+hokiepokedad2@users.noreply.github.com>
…ator docs (#315)

* fix(geofences): make region optional, set Koji __parent null for region-less geofences (#314)

The geofence draw dialog forced the user to pick a region before saving, but the
region list is derived from Koji's parent/child nesting. A flat Koji project has no
regions, so the dropdown was a dead end and the geofence could not be saved.

- Region is now optional in the draw dialog; the picker hides when no regions exist,
  and the "All Regions" sentinel clears the field instead of leaving a blank chip.
- Admins can set or override the region at approval time (approval dialog plus a
  parentId/groupName override on ApproveSubmissionAsync and the approve endpoint).
- KojiService now sends __parent: null (not 0) when parentId <= 0. A live probe
  confirmed Koji returns HTTP 500 "[GEOFENCE]: Does not exist" on __parent: 0 while
  still persisting the row, which would otherwise break every region-less promotion.
  The same guard is applied to the currently-unused PromoteGeofenceAsync.

Adds KojiServiceTests plus controller/service/dialog coverage. Updates CHANGELOG.

* docs(geofences): add operator guide for custom geofences, areas & regions

Replace the single Custom Geofences page with a multi-page, operator-focused
section under Features (MkDocs Material + Mermaid):

- Overview, with a summary of how PoracleJS/PoracleNG reads geofences from
  PoracleWeb.NET instead of Koji, and why.
- Key concepts: areas vs geofences vs regions.
- Koji & regions: connection config plus how to set up regions, with the
  geofence-to-region relationship diagram.
- Private geofences & promotion: private by default, and the promote-to-public flow.
- Admin operations: review/approve/reject/delete, Discord forum, limits.
- Troubleshooting: empty region dropdown, the combined feed, Koji errors.

Wires the new section into mkdocs.yml nav and updates the home-page link.
…ased] check (#316) (#317)

The old "Update Changelog" workflow ran after merge, auto-generated an entry, and
pushed directly to `main` — which is protected, so the push was always rejected
(GH006). It failed on every feat/fix PR, risked duplicate entries (its skip-guard
keyed on PR number while manual entries reference the issue number), and fought the
project's manual-changelog convention.

Replace it with a verify-only check on pull_request that confirms the PR adds an
entry under "## [Unreleased]". It never writes to the repo, so branch protection is
a non-issue; it gives authors feedback before merge instead of red noise after.

- Exempt PR types: docs/style/chore/ci/test/build.
- Escape hatch: the `skip-changelog` label (re-runs on label change).
- Detects new top-level entries by diffing the [Unreleased] block between base and head.
- PR title/labels passed via env to avoid shell injection; permissions dropped to read.

release-changelog.yml (the release-cut flow) is unchanged. Docs updated. Closes #316.
* feat(pokemon): multi-select forms in alarm add dialog (#318)

The Form & Gender picker only allowed one specific form or "All Forms",
so tracking e.g. Meowth's Alola and Galarian forms while ignoring Kanto
meant adding each alarm by hand.

PoracleNG models `form` as a single int per tracking entry (no array
support on the wire), so instead of changing the data model end-to-end
the add dialog reuses its existing per-Pokemon forkJoin fan-out and now
emits one MonsterCreate per (Pokemon x selected form) combination. An
empty selection means "all forms" (form 0), matching the previous
default; a hint makes that explicit.

Scope is the add dialog only -- the edit dialog stays single-form, since
splitting one existing alarm into several on edit is a create-plus-delete
operation. A dedicated `forms` control backs the multi-select, leaving
the manual numeric form-id fallback on the original `form` control.

New POKEMON.FORM_MULTI_HINT i18n key added and translated across all 11
locales.

* test(pokemon): cover multi-select form fan-out in add dialog

Adds pokemon-add-dialog.component.spec.ts verifying save() emits one
MonsterCreate per (Pokemon x form): multi-form fan-out, empty selection
=> all forms (0), cartesian product across pokemon, manual numeric
form-id fallback, snackbar total, and the no-selection no-op.

MatSnackBar is providedIn MatSnackBarModule (imported by the standalone
component), so it resolves from the element injector and shadows an
environment-level useValue -- overridden via TestBed.overrideComponent.
The #319 squash merge anchored the new changelog bullet to its
surrounding context (the notification-language line), which had since
moved under ## [2.10.0] when v2.10.0 was cut (#313). As a result the
multi-select forms entry landed under the already-released 2.10.0
section instead of [Unreleased], making it look like the feature
shipped in 2.10.0 (it did not).

Relocates the bullet to ## [Unreleased] > ### Added and corrects the
wording ("translated across all 11 locales" — the locale translations
landed in #319; the unit tests too).
Co-authored-by: hokiepokedad2 <38219945+hokiepokedad2@users.noreply.github.com>
…token (#322)

* ci(changelog): auto-approve and auto-merge the release changelog cut

The cut-changelog PR was opened with GITHUB_TOKEN, which (by GitHub's
recursion guard) does not trigger the required CI checks
(Backend/Frontend/Changelog). Those required checks therefore never
reported, leaving every changelog-cut PR permanently BLOCKED and needing
a manual admin merge (e.g. v2.11.0 / #321).

Open the PR with a fine-grained PAT (secrets.CHANGELOG_PAT) instead, so
the push/PR events trigger the required checks. Then approve from the
github-actions[bot] identity (distinct from the PAT author, so it
satisfies the 1-approval rule) and enable squash auto-merge.

Degrades gracefully: when CHANGELOG_PAT is absent the PR is still opened
with GITHUB_TOKEN (a warning is emitted) and the approve/merge steps are
skipped, preserving today's manual-merge behavior.

* ci(changelog): use a GitHub App token instead of a PAT

Switch the auto-merge mechanism from a fine-grained PAT to a GitHub App
installation token (actions/create-github-app-token). App tokens are
minted per run and short-lived, so there is no token to rotate, and the
app's permissions are scoped to exactly what it needs.

The PR is authored by the app bot (a real, non-GITHUB_TOKEN identity), so
push/PR events trigger the required CI checks. github-actions[bot] then
approves (distinct identity -> satisfies the 1-approval rule) and squash
auto-merge finishes the job. Falls back to GITHUB_TOKEN (manual merge,
with a warning) when the app secrets are absent.

Secrets: CHANGELOG_APP_ID, CHANGELOG_APP_PRIVATE_KEY.
…324)

MasterDataService.loadForms() discarded every form named Normal, but for
a species with a regional variant the Normal entry is the original/base
form (e.g. Stunfisk lists Normal id 2246 for Unova and Galarian id 2345).
That left only All Forms and Galarian, with no way to alert on Unova
Stunfisk alone.

Keep all real forms (form.id !== 0, including Normal) and only drop a
Normal form when it is a species' lone form, where All Forms already
covers it. Tests cover keep-when-sibling and drop-when-lone.

Fixes #323
Co-authored-by: hokiepokedad2 <38219945+hokiepokedad2@users.noreply.github.com>
The mkdocs-material header version badge is baked into the static HTML at
gh-deploy time from the GitHub Releases API. Since docs.yml only triggered
on docs/ or mkdocs.yml changes, code-only releases (v2.11.0, v2.11.1) never
rebuilt the site, leaving the badge frozen at v2.10.0. Add release:published
and workflow_dispatch triggers so the docs (and badge) refresh on every
release and on demand.
…s + docs (#328)

* feat(auth): add generic external SSO / OIDC login provider (#327)

Delegate PoracleWeb login to any external OAuth2/OpenID Connect provider, alongside the built-in Discord and Telegram methods. Enables single sign-on (e.g. pointing PoracleWeb at the PogoAlerts OAuth2 server) while staying provider-agnostic so any self-hoster can configure their own IdP.

Implemented as a configurable twin of the Discord flow:
- OidcSettings (URLs, client id/secret, scopes, claim mapping, PKCE flag)
- GET /api/auth/oidc/login + /callback: auth-code exchange with PKCE, CSRF state in HttpOnly cookies; reads a configurable identity claim (default discord_id, falls back to sub), looks it up in the human table, reuses GetRolesAsync + guild-role gating, mints the existing internal JWT
- providers endpoint gains an oidc block; enable_oidc site-setting runtime toggle (admins can always log in to re-enable); OIDC_* env bridge with auto-infer; documented in .env.example
- Frontend: oidc provider model, loginWithOidc(), /auth/oidc/callback route, login button + disabled hint + error codes, admin External SSO group, English i18n keys

Tests: backend providers oidc block + /oidc/login redirect/PKCE (1394 pass); frontend OIDC button visibility + click delegation (48 pass).

* feat(auth): OIDC refresh-token sessions, SSO refinements, and docs

Optional, provider-agnostic consumption of the external SSO provider's refresh
token for silent session renewal + revocation propagation (default OFF via
OIDC_USE_REFRESH_TOKENS), plus surrounding SSO login refinements and a
comprehensive OIDC documentation set. Fully OIDC-provider-agnostic; PogoAlerts
is only the reference provider.

Backend:
- oidc_sessions table (EF migration AddOidcSessions): the provider refresh token
  is stored server-side, DataProtection-encrypted, never sent to the browser; the
  browser holds only an opaque rotating token keyed to a rotation family.
- POST /api/auth/oidc/refresh (rotate + live user re-validation + family-revoke on
  replay/provider-revoke) and /oidc/refresh/revoke; OidcSessionCleanupService reaps
  expired/stale rows (OIDC_SESSION_REVOKED_RETENTION_DAYS, default 2).
- Provider-agnostic IOidcClient shared by login callback and refresh: configurable
  client_secret_post|client_secret_basic, optional/non-rotating refresh tokens,
  offline_access auto-appended; no discovery/JWKS/id_token dependency.
- Per-login short JWT for refresh-backed OIDC sessions (OIDC_ACCESS_TOKEN_MINUTES,
  default 30); Discord/Telegram/local logins keep the 24h JWT.
- Refresh is env-controlled only (no runtime admin toggle — coupled to JWT lifetime).

Frontend:
- TokenStoreService (single-flight refresh) + oidcRefreshInterceptor (proactive
  pre-expiry + reactive 401-retry, null-refresh-token guard so non-refresh logins
  keep the existing 401->logout path); callback stores the opaque token; logout
  revokes the session server-side.
- SSO login refinements: Local/SSO auth-mode switch, single-logout toggle,
  auto-redirect + signed-out panel, i18n.

Docs (MkDocs / gh-pages):
- New "External SSO (OIDC)" setup page + reworked "OIDC Refresh Tokens" page
  (Mermaid flows, security model, provider matrix: Keycloak/Authentik/Auth0/
  Google/Azure-Entra/Okta/PogoAlerts).
- OIDC env vars added to the Configuration Reference, enable_oidc/enable_oidc_slo
  to Site Settings, an OIDC troubleshooting section, and nav entries.

Tests: xUnit (session rotation/replay/cap/cleanup over SQLite, provider-agnostic
client, providers/callback) + Jest (token-store single-flight, interceptor
proactive/reactive/loop-guard). Backend 1422 pass, frontend 872 pass.
The EXTERNAL SSO / OIDC sample in .env.example hardcoded PGAN's pogoalerts.net
endpoints as the example provider. PoracleWeb is fully OIDC-provider-agnostic and
open source, so the example should not be branded to one deployment.

Replace the sample provider name and authorize/token/userinfo URLs with neutral
placeholders (My SSO / https://sso.example.com/...), generalize the intro to list
common providers (Keycloak, Authentik, Auth0, Okta), and add a note to swap in your
provider's real endpoints. The per-provider reference matrix (which carries no URLs)
is unchanged.
…t URLs (#331)

PogoAlerts was made standards-compliant (it now issues a refresh token only when
the offline_access scope is requested), so the docs that told operators to leave
OIDC_OFFLINE_ACCESS_SCOPE empty for PogoAlerts were stale. PogoAlerts now uses
offline_access (the default), like every other standards-compliant provider —
this already matched .env.example, which the docs contradicted.

- external-sso.md / oidc-refresh-tokens.md provider matrices: PogoAlerts
  OIDC_OFFLINE_ACCESS_SCOPE (empty) -> offline_access.
- oidc-refresh-tokens.md: drop "(PogoAlerts)" from the "set empty / issues
  unconditionally" guidance; Google's access_type=offline remains the empty case.

De-branding (open-source hygiene): remove the dedicated "PogoAlerts (reference)"
copy-paste snippets (the only place carrying real pogoalerts.net URLs). PogoAlerts
remains documented as a row in the provider matrix; Keycloak/Auth0 serve as the
concrete copy-paste examples. No pogoalerts.net URLs remain in the docs.
* i18n: translate OIDC/SSO keys into all locales

The external SSO / OIDC login feature (#327/#328) added 30 i18n keys to en.json
only, so every non-English locale fell back to English for the SSO sign-in button,
the signed-out panel, OIDC error messages, and the entire admin Authentication /
External SSO settings group.

Translate all 30 keys (ADMIN_SETTINGS.* OIDC config + auth-mode + single-logout,
AUTH.* SSO sign-in / signed-out / OIDC errors, MENU.LOGOUT_EVERYWHERE) into the
10 remaining locales: da, de, es, fr, it, nl, pl, pt, pt-BR, sv.

Placeholders ({{provider}}), technical tokens (OIDC/SSO/PKCE/URL/ID), env names
(AUTH_FORCE_LOCAL, OIDC_END_SESSION_URL, OIDC_*, .env) and brand names are
preserved verbatim. Additive only — no existing keys changed or removed; all files
valid JSON and Prettier-clean.

* docs(changelog): note OIDC locale translations
…tive toggles (#332)

* feat(admin-settings): search, sticky save, collapsible sections, positive toggles

Reworks the admin Server Settings page for clarity and scannability.

- Live search/filter: sticky search bar that filters settings across all sections
  with <mark> highlighting; '/' or Ctrl/Cmd+K focuses it, Esc clears.
- Sticky save + discard bar: replaces the header-only save button; appears with the
  unsaved count and a Discard (revert to loaded values) action whenever there are
  pending changes, so saving is always reachable on the long page.
- Regrouped auth: Telegram and Discord now sit directly under the Authentication
  section so all sign-in config is together.
- Collapsible sections (persisted in localStorage) with a per-section "unsaved"
  chip and a state summary in the header (e.g. "7 of 9 enabled").
- Positive toggles: the alarm-type/feature toggles were a confusing double negative
  (ON = "Disable X" = feature off) mixed with positive enable_* toggles. They are
  now uniformly positive — ON = enabled, labels are the feature name ("Pokémon",
  "Areas", …), descriptions are "Let users …". The stored disable_* keys are
  UNCHANGED (presentation-only inversion), so backend feature-gating is unaffected.
- Polish: staggered fade-in on load (respects prefers-reduced-motion) and a subtle
  per-section color tint.
- i18n: new ADMIN_SETTINGS UX keys and the reframed (positive) alarm/feature
  labels+descriptions translated across all 11 locales.

ng build + prettier + eslint clean.

* docs(changelog): note admin settings UX overhaul
Bumps [docker/build-push-action](https://github.com/docker/build-push-action) from 5 to 7.
- [Release notes](https://github.com/docker/build-push-action/releases)
- [Commits](docker/build-push-action@v5...v7)

---
updated-dependencies:
- dependency-name: docker/build-push-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 5 to 6.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](actions/setup-python@v5...v6)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/create-github-app-token](https://github.com/actions/create-github-app-token) from 2 to 3.
- [Release notes](https://github.com/actions/create-github-app-token/releases)
- [Changelog](https://github.com/actions/create-github-app-token/blob/main/CHANGELOG.md)
- [Commits](actions/create-github-app-token@v2...v3)

---
updated-dependencies:
- dependency-name: actions/create-github-app-token
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [dependabot/fetch-metadata](https://github.com/dependabot/fetch-metadata) from 2 to 3.
- [Release notes](https://github.com/dependabot/fetch-metadata/releases)
- [Commits](dependabot/fetch-metadata@v2...v3)

---
updated-dependencies:
- dependency-name: dependabot/fetch-metadata
  dependency-version: '3'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps [actions/cache](https://github.com/actions/cache) from 4 to 5.
- [Release notes](https://github.com/actions/cache/releases)
- [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md)
- [Commits](actions/cache@v4...v5)

---
updated-dependencies:
- dependency-name: actions/cache
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the angular group with 13 updates in the /Applications/Pgan.PoracleWebNet.App/ClientApp directory:

| Package | From | To |
| --- | --- | --- |
| [@angular/animations](https://github.com/angular/angular/tree/HEAD/packages/animations) | `21.2.15` | `21.2.16` |
| [@angular/cdk](https://github.com/angular/components) | `21.2.13` | `21.2.14` |
| [@angular/common](https://github.com/angular/angular/tree/HEAD/packages/common) | `21.2.15` | `21.2.16` |
| [@angular/compiler](https://github.com/angular/angular/tree/HEAD/packages/compiler) | `21.2.15` | `21.2.16` |
| [@angular/core](https://github.com/angular/angular/tree/HEAD/packages/core) | `21.2.15` | `21.2.16` |
| [@angular/forms](https://github.com/angular/angular/tree/HEAD/packages/forms) | `21.2.15` | `21.2.16` |
| [@angular/material](https://github.com/angular/components) | `21.2.13` | `21.2.14` |
| [@angular/platform-browser](https://github.com/angular/angular/tree/HEAD/packages/platform-browser) | `21.2.15` | `21.2.16` |
| [@angular/router](https://github.com/angular/angular/tree/HEAD/packages/router) | `21.2.15` | `21.2.16` |
| [@angular/build](https://github.com/angular/angular-cli) | `21.2.13` | `21.2.14` |
| [@angular/cli](https://github.com/angular/angular-cli) | `21.2.13` | `21.2.14` |
| [@angular/compiler-cli](https://github.com/angular/angular/tree/HEAD/packages/compiler-cli) | `21.2.15` | `21.2.16` |
| [@angular/platform-browser-dynamic](https://github.com/angular/angular/tree/HEAD/packages/platform-browser-dynamic) | `21.2.15` | `21.2.16` |



Updates `@angular/animations` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/animations)

Updates `@angular/cdk` from 21.2.13 to 21.2.14
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](angular/components@v21.2.13...v21.2.14)

Updates `@angular/common` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/common)

Updates `@angular/compiler` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/compiler)

Updates `@angular/core` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/core)

Updates `@angular/forms` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/forms)

Updates `@angular/material` from 21.2.13 to 21.2.14
- [Release notes](https://github.com/angular/components/releases)
- [Changelog](https://github.com/angular/components/blob/main/CHANGELOG.md)
- [Commits](angular/components@v21.2.13...v21.2.14)

Updates `@angular/platform-browser` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/platform-browser)

Updates `@angular/router` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/router)

Updates `@angular/build` from 21.2.13 to 21.2.14
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@v21.2.13...v21.2.14)

Updates `@angular/cli` from 21.2.13 to 21.2.14
- [Release notes](https://github.com/angular/angular-cli/releases)
- [Changelog](https://github.com/angular/angular-cli/blob/main/CHANGELOG.md)
- [Commits](angular/angular-cli@v21.2.13...v21.2.14)

Updates `@angular/compiler-cli` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/compiler-cli)

Updates `@angular/platform-browser-dynamic` from 21.2.15 to 21.2.16
- [Release notes](https://github.com/angular/angular/releases)
- [Changelog](https://github.com/angular/angular/blob/main/CHANGELOG.md)
- [Commits](https://github.com/angular/angular/commits/v21.2.16/packages/platform-browser-dynamic)

---
updated-dependencies:
- dependency-name: "@angular/animations"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/build"
  dependency-version: 21.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cdk"
  dependency-version: 21.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/cli"
  dependency-version: 21.2.14
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/common"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/compiler"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/compiler-cli"
  dependency-version: 21.2.16
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/core"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/forms"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/material"
  dependency-version: 21.2.14
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/platform-browser"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/platform-browser-dynamic"
  dependency-version: 21.2.16
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: angular
- dependency-name: "@angular/router"
  dependency-version: 21.2.16
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: angular
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
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.

2 participants