Skip to content

feat(compat): say which feature and version a request needs, and document the version axis - #820

Merged
hokiepokedad2 merged 3 commits into
developfrom
feat/unsupported-request-surface
Aug 24, 2026
Merged

feat(compat): say which feature and version a request needs, and document the version axis#820
hokiepokedad2 merged 3 commits into
developfrom
feat/unsupported-request-surface

Conversation

@hokiepokedad2

Copy link
Copy Markdown
Contributor

Extracted from the abandoned feat/poracleng-two-branch-support, plus the compatibility documentation that branch was carrying. Independent of the other open PRs; can go in any time.

Why the parent branch was abandoned

Its premise — that PoracleNG keeps two long-lived branches and this application should serve both — died when PoracleNG's develop shipped as 5.2.1. The real axis is 5.1.0 versus 5.2.1+.

Its foundation was also already here. PoracleServerProfile and PoracleServerProfileService are on develop, and ISummaryCapabilityService already establishes the per-feature capability-service shape the 5.2.1 feature branches went on to follow. PoracleCapabilityService / PoracleCapabilityKeys were a competing second design for an idea that already had one, which is how a codebase ends up with two implementations and one of them lying.

The abandoned work is preserved at 3d33b35 on that branch. Two pieces were worth keeping; this is one of them (quest pokécoins is the other, separately).

Part 1 — a request an old Poracle cannot serve now says so

PoracleUnsupportedException carries a plain feature name and a required version, not a registry key — that was the rework needed to drop the registry dependency. PoracleUnsupportedResponse puts the 409 body in one place, mirroring FeatureDisabledResponse, so the wire format cannot drift. The filter registers globally beside the other five.

Five tests, matching FeatureDisabledExceptionFilterTests: the mapping, the message naming both feature and version, that it emits neither a disableKey nor a 403, that it ignores unrelated exceptions, and that it declines FeatureDisabledException — both filters run on every request, so each has to leave the other's exception alone.

No SPA interceptor branch, deliberately. error.interceptor.ts has no 409 handling at all, and that absence is already load-bearing: TrackingConflictExceptionFilter returns 409 and the alarm dialogs show its message beside the control. Adding a branch here would replace a useful sentence ("requires PoracleNG database migration 6") with a generic toast, and copying the 403 disableKey path would conflate an operator's switch with an old server. The reasoning is in the filter's remarks and asserted by two of the tests.

Nothing throws this yet, so there is no user-visible change today. The changelog entry says exactly that.

Part 2 — the compatibility page

docs/architecture/poracleng-compatibility.md, rewritten from scratch, registered in mkdocs.yml and linked from docs/index.md.

Claims were re-verified against live 5.1.0 and 5.2.1 servers rather than carried over:

  • PoracleNG's v1 surface is frozen and unchanged on 5.2.1. A v1 tracking POST returns {"message":...,"status":"error"} byte-identical on both. The RFC 9457 problem+json bodies and 422 statuses in its release notes are /api/v2 only. Assuming otherwise cost a wrongly-framed issue and PR earlier in this batch, so it is written down.
  • Do not take active_hours day numbering from the v2 schema. It declares day as 0–6, "0=Sunday", while the scheduler uses ISO Monday 1 to Sunday 7. It rejects Sunday and accepts a meaningless 0.
  • Prefer the migration number over the version string where a column is the real question: self-hosters cherry-pick, and a locally built binary reports 0.0.0.
  • The /health capability map gained exactly one key on 5.2.1 (derivedDtsTypes) and says nothing about alarm columns, so reaching for Supports() where HasSchema() is the question answers false forever.

Three claims from the old page were dropped rather than repeated, because they could not be verified: that diff.go is byte-identical between versions, and the disabledHooks pokestop-versus-fort difference (both dev servers report an empty array).

One correction I made on top of the extraction

The first pass concluded no description field exists on any 5.2.1 tracking-rule schema, and left rule descriptions out of the feature table. It does exist?include_descriptions=true is a documented query parameter and the envelope carries description. It is missing from the named V2PokemonRule request schema, and the response envelope is an inline object under rules.items rather than a named component, so searching components/schemas finds nothing. The page now records how to avoid that specific mistake, since PR #819 depends on the field existing.

Also corrected: the page said costume was blocked on PoracleNG publishing no costume-name list. PR #815 solved that by reading the same WatWowMap masterfile PoracleNG itself reads, which is why those names are English in every language.

Verification

Backend 2135 passed, five of them new. No SPA files touched.

A request an older PoracleNG cannot serve arrived either in that server's own
wording, which names a database column, or as a generic 500. PoracleUnsupportedException
carries a plain feature name and what the server would need, in words, and the
global PoracleUnsupportedExceptionFilter answers 409 with both.

409 rather than 403: the 403 branch is the disable_* path and keys off disableKey.
An old server is not a switched-off feature, and borrowing that shape would put
both behind the same toast while losing the one detail worth reading. 409 has no
interceptor branch, so it falls through to the caller and lands beside the control
that asked -- the route TrackingConflictExceptionFilter already takes.

It carries a feature name and a version, not a registry key. Support is decided
per feature by IPoracleServerProfileService and small services on top of it, so
there is nothing central to look a key up in, and the words are what the reader
sees.

Nothing throws it yet.

Rewrites the PoracleNG compatibility page, whose premise was that PoracleNG keeps
two long-lived branches. Develop shipped as 5.2.1 and merged; the axis is 5.1.0
versus 5.2.1+. Records two traps verified against live 5.1.0 and 5.2.1 servers:
the v1 API is unchanged on 5.2.1, so the RFC 9457 bodies and 422 codes in its
release notes apply to v2 only; and its OpenAPI declares active_hours.day as 0-6
"0=Sunday" while the scheduler uses ISO weekdays 1-7.
The page said no `description` field appears on any tracking rule schema on 5.2.1.
It does. A v2 read takes `?include_descriptions=true` and returns a `description`
per rule -- the same sentence the bot answers `!pokemon` with -- and v1's
`allProfiles` accepts the same flag.

The mistake is worth recording rather than just fixing, so the page now says how to
avoid it: `description` is absent from the named `V2PokemonRule` request schema, and
the envelope carrying it is an inline object under `rules.items` rather than a named
component, so searching `components/schemas` finds nothing. Resolve
`V2ListOutput...Body.properties.rules.items` before concluding a field is absent.

Also corrected two claims that the branches in review have overtaken: costume is not
blocked on the missing name list (the picker reads the same WatWowMap masterfile
PoracleNG reads, which is why the names are English everywhere), and the features
table now lists rule descriptions.
@hokiepokedad2
hokiepokedad2 merged commit 324df94 into develop Aug 24, 2026
6 checks passed
@hokiepokedad2
hokiepokedad2 deleted the feat/unsupported-request-surface branch August 24, 2026 17:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant