refactor: remove retired API standards and superseded Lift stubs - #2904
Open
hongwei1 wants to merge 31 commits into
Open
refactor: remove retired API standards and superseded Lift stubs#2904hongwei1 wants to merge 31 commits into
hongwei1 wants to merge 31 commits into
Conversation
…lish, STET, MxOF) These five standards were commented out of the Lift bridge in PR OpenBankProject#2814 (commit d19af2b) and have had no live route since. The http4s migration never targeted them and nothing in the codebase references their objects; delete the dead source outright instead of keeping it as commented-out text.
The 20 Lift *Api.scala files under UKOpenBanking/v3_1_0 have been fully replaced by the corresponding Http4sUKOBv310* objects, as documented in OBP_UKOpenBanking_310's aggregator comment. Their routes and resource docs are served natively; nothing else in the codebase references these types.
APIMethods_UKOpenBanking_200 is fully commented out; its routes are served natively by Http4sUKOBv200, gated in Http4sApp's baseServices chain. Nothing references the Lift object.
The 5 Lift *Api.scala files under berlin/group/v1_3 have been fully replaced by the corresponding Http4sBGv13* objects. OBP_BERLIN_GROUP_1_3's aggregator comment documents the migration and confirms routes are served by Http4sBGv13.wrappedRoutes; BgSpecValidation.scala (live validation logic) is untouched.
Superseded by v1_2_1/OBPAPI1.2.1.scala. JSONFactory1.2.scala in the same package stays untouched — it defines AccountJSON/AccountsJSON/ ErrorMessage, which are still imported by APIUtil.scala and API2_2_0Test.scala.
Both packages are fully commented out (Authorisation/AuthorisationProvider/ MappedAuthorisationProvider and YearlyCharge/MappedYearlyChargeProvider), with zero live consumers across the codebase.
Entire file is dead Lift-era source with no active declarations.
EthereumConnector_vSept2025Test.scala and API3_0_0Test.scala are entirely commented out and exercise nothing.
- OpenTokUtil.scala and SandboxApiCalls.scala: fully commented out. - APIMethodsCustom300.scala: empty trait for a retired endpoint whose only route was hard-coded to null and whose resourceDocs buffer was always empty; no consumer references it anywhere in the codebase. - MockedJune2017Connector.scala: empty file.
Zero consumers anywhere in the repo (not wired into any CI workflow, build step, or documentation), last touched 2026-01-20. It parsed Lift ResourceDoc text out of APIMethods600.scala with an anchor-less regex that matches inside comment lines, so it has been silently broken since that file's contents went fully commented-out. Not part of the Maven build (a standalone `scala` script, not referenced from any pom.xml). A replacement exporter, if needed, should read the current http4s resource-doc/OpenAPI output instead of depending on retired Lift source text.
ResourceDocs140.scala and the UK Open Banking v2.0.0/v3.1.0 and Berlin Group v1.3 aggregator objects each carried a trailing block of commented-out Lift dispatch code below their still-active http4s delegation. Removed the dead blocks; kept the explanatory comment that documents why each object is retained and where its routes are actually served.
test.default.props is gitignored and each developer maintains their own local copy, so it can silently drift from what CI's "Setup props" step injects. Without berlin_group_v1_3_alias_path set, OBP_BERLIN_GROUP_1_3_Alias reports an empty ScannedApiVersion and ScannedApis.isAddressable filters it out of versionMapScannedApis entirely, so ApiVersionUtilsTest's `versions.length shouldBe(21)` sees only 20 registered API versions locally while CI (which does set the prop) sees 21. Inject OBP_BERLIN_GROUP_V1_3_ALIAS_PATH as an env var override, mirroring how run_tests_parallel.sh already closes the same kind of gap for mail.test.mode, dynamic_code_sandbox_permissions and allow_user_generated_scala_code, rather than editing the developer's local props file. Confirmed by reproducing the failure on a clean origin/develop checkout with the var unset, then reproducing a pass with it set.
Http4s400's getAllJsonSchemaValidations and getAllAuthenticationTypeValidations each serve two GET routes: /management/... (authenticated) and /endpoints/... (a public variant). The public variant was live but had no ResourceDoc of its own, so it silently piggy-backed on the management route's doc -- which lists $AuthenticatedUserIsRequired even though the public route enforces no such thing. The two props Lift used to gate this (read_json_schema_validation_requires_role, read_authentication_type_validation_requires_role) were fully dead: never read anywhere in the http4s port. Recovered the original Lift ResourceDoc text for both public variants (from the now-deleted APIMethods400.scala's commented-out history) and added them as dedicated ResourceDoc entries with roles=None and an error list that conditionally includes $AuthenticatedUserIsRequired based on the prop. ResourceDocMiddleware.needsAuthentication reads this per-request from the matched doc, so no handler-body branching is needed -- the existing executeAndRespond handler already works for both prop states, and the middleware enforces auth before it ever runs when the prop is true. Also corrected a stale "no Lift counterpart" comment on the existing getAllAuthenticationTypeValidationsPublic alias (a commented-out Lift counterpart does exist) and added the equivalent getAllJsonSchemaValidationsPublic alias, which was missing. Because the prop's effect on a ResourceDoc's error list is computed once at object-init time, a single running JVM only ever observes one value of it. Added two test classes tagged PropGatedPublicEndpoint that boot their own JVM with the props forced true (JsonSchemaValidationPublicPropTrueTest, AuthenticationTypeValidationPublicPropTrueTest), verifying anonymous 401 / authenticated 200. Every ordinary shard continues to exercise the default (false) branch via the existing JsonSchemaValidationTest / AuthenticationTypeValidationTest anonymous-200 scenarios. Wired PropGatedPublicEndpoint into pom.xml's default tagsToExclude (via a new test.tagsToExclude property, since a plain literal there can't be overridden by a command-line -D), run_tests_parallel.sh (a dedicated sequential step after the main shards), and both CI workflows (a new shard 10, mirroring the existing per-shard override pattern).
…line The 12 APIMethodsXYZ.scala files (about to be deleted in a follow-up commit) had shrunk to thin runtime shims plus ~60,000 lines of commented-out original Lift ResourceDoc text, kept only so check_lift_http4s_resource_doc_parity.py could audit http4s against it. Exported that text into scripts/resource_doc_baseline/ instead, one JSON file per API version, each field stored as the literal, unevaluated Scala source snippet it always was (not a parsed value) -- rehydrate_resource_docs.py and restore_resource_doc_bodies.py splice this text verbatim into a live .scala file, so the JSON has to stay reproducible Scala source text, not an evaluated representation. export_and_verify.py did the one-time export: extract every field from the live .scala source, write the JSON, read it back, and assert the two digest sets are identical -- same keys, same values, not just the same count -- before writing digest_manifest.json. That gate is what lets the .scala files be deleted with confidence nothing was lost in translation; --check-only re-verifies it any time after. check_lift_http4s_resource_doc_parity.py now reads the Lift side from this JSON baseline (the http4s side is untouched -- still live .scala). Added an allowlist mechanism (parity_allowlist.json) since none existed before: every difference between the two sides is either a new failure or a reviewed, digest-bound entry -- rename pairs, endpoints that only exist on one side, or individual field differences -- bound to the normalized value's digest so reformatting is tolerated but any real content change re-triggers a failure rather than being silently suppressed forever. allowlist_helper.py computes those digests from live data instead of hand-typing sha256 hashes. Populated the allowlist after reviewing all 154 current differences (2 rename pairs, 4 Lift-only, 13 http4s-only, 136 field mismatches): every one is an intentional http4s improvement over the Lift original (a fixed verb-casing bug, a corrected stale description, a clarified URL template variable, a documented new field) -- verified against the actual handler code on both sides, not just the doc text, with a handful of security-relevant fixes (a role gate added to signal-channel deletion, input validation added to signal messages, the password-reset endpoint no longer echoing the reset URL in its response) worth a specific mention for anyone auditing this later. None were regressions. check_lift_http4s_resource_doc_parity.py now exits 0. Also fixed a real, pre-existing bug in rehydrate_resource_docs.py and restore_resource_doc_bodies.py while updating them to read the JSON baseline: both hardcoded ResourceDoc constructor argument positions assuming the pre-Lift-teardown signature (a leading partialFunction parameter that no longer exists), so both silently matched zero endpoints against any current-signature Http4sXYZ.scala file. Fixed by detecting which signature a given call uses, the same way check_lift_http4s_resource_doc_parity.py already did, instead of a second hardcoked guess that had drifted out of sync with it.
…letion CLAUDE.md's migration rule pointed at the 12 APIMethodsXYZ.scala files as the source of truth for what http4s should match. Repointed it at scripts/resource_doc_baseline/ (see the previous commit) and the allowlist workflow for documenting reviewed differences, before those .scala files are deleted in a follow-up commit -- so the rule never points at files that don't exist. count_v7_endpoints.py's docstring/comments and its "no files found" error message still described APIMethods*.scala as a fallback discovery source; its actual discover_version_files() never read them (Http4s*.scala only), so this is a text-only correction.
…ents Every APIMethodsNNN.scala left in the tree is now a pure runtime shim -- a literal alias (val ImplementationsX = Http4sNNN.ImplementationsX) plus an empty trait, kept only so existing imports still compile. This redirects every remaining production and test reference to the real Http4sNNN object directly, clearing the way to delete the 12 shim files entirely in a follow-up commit. Production code: - ResourceDocsAPIMethods.scala: dropped the 6 empty-trait mixins (APIMethods220/210/200/140/130/121, confirmed empty by direct read) and its 9 APIMethods400.Implementations4_0_0.X call sites, now Http4s400.Implementations4_0_0.X. - APIUtil.scala: two nameOf(...) fully-qualified references (APIMethods510/500 -> Http4s510/500). - OBPAPI5_1_0.scala / OBPAPI6_0_0.scala / OBPAPI5_0_0.scala: dropped the APIMethods310/400/500/510 imports and mixins (all confirmed empty), consolidated the now-orphaned "re-export so this compiles after APIMethods* was replaced with a stub" comments into one accurate note per file (the stub isn't just replaced now, it's gone). ~41 test files: mechanical import + reference swap (code.api.vX.APIMethodsNNN -> code.api.vX.Http4sNNN; APIMethodsNNN.ImplementationsX -> Http4sNNN.ImplementationsX) across v3_1_0/v4_0_0/v5_0_0/v5_1_0/v6_0_0 test suites. These are literal aliases to the same object, so this is a pure text substitution with no behavior change -- verified by a full test-compile afterward. Cleaned up stale comments/docs that would otherwise reference deleted files after the follow-up deletion commit: Http4s600.scala, Http4s210.scala, Glossary.scala (incl. an ASCII diagram), RateLimitingUtil.scala, ChatEventPublisher.scala, FAQ.md, and introductory_system_documentation.md (including removing a logback logger entry targeting a class that would no longer exist). Left the "Intentional drift from Lift's APIMethodsNNN.scala source-of-truth" comments elsewhere untouched -- those are historical citations of where a documented behavioral decision came from, not claims that the file currently exists, so they stay accurate after the deletion.
Every one of these files had shrunk to a thin runtime shim (object
APIMethodsNNN { val ImplementationsX = Http4sNNN.ImplementationsX })
plus an empty trait, with everything else -- the original Lift
ResourceDoc registrations -- commented out. All production and test
code that imported them was redirected to the real HttpsNNN objects
directly in the previous commit; the parity audit that used to read
their commented-out text now reads scripts/resource_doc_baseline/'s
JSON export instead, verified byte-for-byte lossless against this
exact commit's source before it was allowed to proceed.
APIMethods121.scala, APIMethods130.scala, APIMethods140.scala,
APIMethods200.scala, APIMethods210.scala, APIMethods220.scala,
APIMethods300.scala, APIMethods310.scala, APIMethods400.scala,
APIMethods500.scala, APIMethods510.scala, APIMethods600.scala --
60,634 lines, all net removal, no archive copy kept in the tree
(git history is the archive).
check_lift_http4s_resource_doc_parity.py and
export_and_verify.py --check-only both still pass with these files
gone, confirming the JSON baseline and its digest manifest don't
depend on them being present.
…oints.py parse_file() hardcoded ResourceDoc constructor argument positions assuming the pre-Lift-teardown signature (a leading partialFunction parameter that no longer exists in any current file): name at args[2], verb at args[3], url at args[4]. Every current Http4sXYZ.scala uses the post-teardown signature (no leading partialFunction), where those same fields sit one position earlier. This meant args[3] -- read as the verb -- was actually the URL string, which never matched HTTP_VERBS, so every single ResourceDoc registration in every version file was silently discarded with a WARN and the script always reported 0 total endpoints. Fixed by detecting which signature a given call uses (checking whether args[2] looks like an HTTP verb literal) and computing the field positions from that, the same way check_lift_http4s_resource_doc_parity.py already does with its POSITIONAL_FIELDS / CURRENT_POSITIONAL_FIELDS split -- instead of a second hardcoded guess that had drifted out of sync with it. Confirmed via direct testing: parse_file on v1.2.1 alone went from 0 docs / 0 stderr warnings suppressed as "unexpected verb" (all 70 silently dropped) to 70 docs matched correctly. Full run now reports 852 endpoints reachable via /obp/v7.0.0/ with zero stderr warnings, in the same ballpark as V7ResourceDocsAggregationTest's independently measured 858 (the two won't match exactly -- this script's dedup/ exclude logic is a separate, simpler reimplementation of the runtime aggregation, not the same code path).
getAllJsonSchemaValidationsPublic and getAllAuthenticationTypeValidationsPublic are new v4.0.0 endpoints, so FrozenClassUtil's persisted snapshot needs regenerating to reflect the expected count increase.
Adds the two new v4.0.0 public endpoints to the text sibling. Also picks up APIUtil.JArrayBody dropping out of the reachable type set - that type stopped being reachable from any STABLE endpoint body before this branch started (confirmed against origin/develop), so this is stale-fixture drift the regeneration corrects, not a change introduced by this branch.
--allowlist was read without checking where it pointed, and the version positional was interpolated straight into a baseline filename. Constrain the former to the repo root and require the latter to match the same vN_N_N pattern the auto-discovery path already enforces.
The aggregation reached back into OBPAPI4_0_0/5_1_0/6_0_0 for these three lists, which is the last thing tying it to the aggregator objects. nameOf is a compile-time macro over the member name, so sourcing it from Http4sNNN.ImplementationsX yields the identical strings.
Http4s500/Http4s510 already declare their own versionStatus, so the root endpoints can read version and status locally instead of borrowing them from the aggregator. ResourceDocsAPIMethods' twelve OBPAPI imports and ObpGrpcServer's were unused, and APIUtil only wanted Implementations2_2_0, which Http4s220 exposes directly.
The aggregators only re-exported other objects' members, so each reference has an exact equivalent. Note the mapping keys off the Implementations number rather than the OBPAPI one: OBPAPI3_0_0.Implementations2_2_0 is Http4s220.Implementations2_2_0. allResourceDocs becomes the corresponding Http4sResourceDocAggregation catalog.
FrozenClassUtil recovered the version list by scanning for VersionedOBPApis implementors, which in practice meant the OBPAPIx_x_x objects. Http4sResourceDocAggregation already had to name all twelve versions, so it now also exposes their status and cumulative catalogs and the scan becomes a plain list. versionStatus is still read from each Http4sNxx rather than restated, so there remains one declaration per version. The frozen fixtures were produced by the old scan and still match byte for byte, which is what makes the two paths provably equivalent.
Nothing references them any more: the resource-doc aggregation, the excludeEndpoints lists, the version/status pairs and every test reference now come from Http4sResourceDocAggregation or the Http4sNxx objects directly. Removes the last Lift OBPRestHelper subclasses in the versioned API packages.
Its only consumer was FrozenClassUtil's classpath scan, and its only remaining implementors were the two dynamic aggregators, whose members are read directly rather than through the trait. Also refreshes the comments and frozen-test scenario names that still described the deleted objects.
The lists moved into Http4sResourceDocAggregation as excludeEndpointsV{nnn},
so the per-version lookup found nothing and the script stopped filtering:
it reported 871 reachable endpoints instead of 852. Match the suffixed names
and the count is right again (6/8/14 excludes for v4.0.0/v5.1.0/v6.0.0).
v121 was the one catalog that did not force its own Implementations object, on the grounds that Http4sApp startup always did it. The deleted OBPAPI objects were quietly doing it too, from their static initializers, so a caller that reads a catalog without booting a server no longer has that cover. Every later catalog snapshots v121 into a new buffer, so an unpopulated one would drop v1.2.1 from the whole chain for the life of the JVM.
Both scripts picked the constructor layout by testing whether positional 2 held a verb literal, and fell back to the pre-teardown layout otherwise. Anything they could not classify was therefore patched at offsets shifted by one, writing each field's text into its neighbour's slot -- in a file they rewrite in place. Require a verb literal at exactly one of positional 2 and 3, and on anything else warn with the file and line, skip the registration and exit non-zero rather than guess.
The step ran after all four shards but allocated its ports with `alloc_free_port || exit 1`, so a transient allocation failure exited before the summary, the per-shard diagnostics and the Surefire audit -- discarding results that were already computed. Record a failing RC and carry on instead.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Summary
Removes the dead Scala source left behind by the Lift-to-http4s migration, in three
stages: the retired standards and orphan files, the 12
APIMethods*.scalashims, andfinally the 12
OBPAPI*.scalaaggregator objects. Net removal — nothing is moved to anarchive directory, and the historical
ResourceDocdocumentation that lived in thosefiles is preserved as a digest-verified JSON baseline rather than lost.
BASE_SHA:
a98ba9847d843c6717f7f7aaa6c5cf6488819c9a(origin/develop).343 files changed, ~103,000 lines removed.
Stage 1 — retired standards and orphans (~41,000 lines)
Five retired API standards (fully commented out and taken off the routing bridge in
#2814 / commit
d19af2b92, confirmed zero live consumers):code/api/BahrainOBF/v1_0_0/(22 files),
code/api/AUOpenBanking/v1_0_0/(11),code/api/Polish/v2_1_1_1/(5),code/api/STET/v1_4/(5),code/api/MxOF/(4, includesCNBV9_1_0_0.scala).Superseded Lift stubs, already fully commented out, with routes now served natively by
the corresponding
Http4sXXXobjects:code/api/UKOpenBanking/v3_1_0/(20*Api.scala,replaced by
Http4sUKOBv310*),code/api/UKOpenBanking/v2_0_0/APIMethods_UKOpenBanking_200.scala(replaced by
Http4sUKOBv200),code/api/berlin/group/v1_3/(5*Api.scala, replaced byHttp4sBGv13*).The aggregator objects (
OBP_UKOpenBanking_310,OBP_UKOpenBanking_200,OBP_BERLIN_GROUP_1_3) are kept — still needed forScannedApisclasspath registration —but their trailing blocks of commented-out Lift dispatch are stripped. Same for
ResourceDocs140.scala.Zero-consumer orphans:
code/api/v1_2/OBPAPI1.2.scala(the siblingJSONFactory1.2.scalais untouched — still live),
code/database/authorisation/,code/yearlycustomercharges/,code/api/openidconnect.scala,code/opentok/OpenTokUtil.scala,code/api/sandbox/SandboxApiCalls.scala,code/api/v3_0_0/custom/APIMethodsCustom300.scala,two fully commented-out test files, one zero-byte test file, and
scripts/OpenAPI31Exporter.scala(a standalone script with no consumers that parsed Lift
ResourceDoctext with ananchor-less regex, silently broken since
APIMethods600.scalawent fully commented-out).Stage 2 — the 12
APIMethods*.scalashims (~60,600 lines)These had shrunk to thin runtime shims plus commented-out Lift
ResourceDoctext. Beforedeleting them:
Two real endpoint gaps fixed (
Http4s400.scala).getAllJsonSchemaValidationsandgetAllAuthenticationTypeValidationseach serve a/management/...(authenticated) and an/endpoints/...(public) route, but the public variant had noResourceDocof its own — itpiggy-backed on the management route's doc, which wrongly implied auth was required, and the
two props that were supposed to gate it (
read_json_schema_validation_requires_role,read_authentication_type_validation_requires_role) had never been wired into the http4spath at all, leaving
/endpoints/...unconditionally public. Recovered the original Liftdesign from the doomed file's own history and restored it: a dedicated public
ResourceDocper endpoint with a prop-conditional error list. Since
ResourceDocMiddleware.needsAuthenticationreads this from the matched doc, no handler-body branching was needed.
Two new test classes (
JsonSchemaValidationPublicPropTrueTest,AuthenticationTypeValidationPublicPropTrueTest) cover the prop=true branch. They are taggedPropGatedPublicEndpointand run in their own JVM, because the prop's effect on the doc'serror list is fixed at object-init time — one JVM can only ever observe one branch. Wired into
pom.xml(via atest.tagsToExcludeproperty, so the exclusion is actually overridable fromthe command line),
run_tests_parallel.sh, and both CI workflows as a new shard 10.JSON baseline replaces the commented-out Lift source (
scripts/resource_doc_baseline/).One file per API version, 964 endpoints, each field stored as the literal unevaluated Scala
source snippet it always was —
rehydrate_resource_docs.py/restore_resource_doc_bodies.pysplice that text verbatim into live
.scalafiles, so it has to stay text.export_and_verify.pyperformed the one-time export and proved it lossless: extract from
.scala, write JSON, read itback, and assert the digest sets are identical — same keys, same values, not merely the same
count — before writing
digest_manifest.json. That gate is what made deleting the files safe.Parity audit rewritten, allowlist added.
check_lift_http4s_resource_doc_parity.pynowreads the Lift side from the JSON baseline (the http4s side is unchanged, still live
.scala).parity_allowlist.jsonis new: every previously-unreviewed difference is now either a freshfailure or a digest-bound, reviewed entry. All 154 current differences (2 rename pairs, 4
Lift-only, 13 http4s-only, 136 field mismatches) were checked against the handler code on both
sides rather than just the doc text. Every one is an intentional http4s improvement — including
a few worth flagging: a role gate added to signal-channel deletion, input validation added to
signal messages, and the password-reset endpoint no longer echoing the reset URL in its response.
None were regressions.
A pre-existing tooling bug found along the way.
rehydrate_resource_docs.pyandrestore_resource_doc_bodies.pyboth hardcodedResourceDocconstructor argument positionsfrom the pre-teardown signature (a leading
partialFunctionparameter that no longer exists),so both silently matched zero endpoints against any current file — verified before the fix
(0 matches everywhere) and after (e.g. 243/244 on v6.0.0).
scripts/count_v7_endpoints.pyhadthe identical bug, reporting 0 endpoints instead of 852. Fixed by detecting which signature a
call uses, reusing the logic the parity script already had rather than adding a third
hardcoded guess.
Stage 3 — the 12
OBPAPI*.scalaaggregators (787 lines)Http4sResourceDocAggregationalready computed every version's catalog; these objects wereits last remaining callers, plus a set of re-export
vals. Moved out in order:excludeEndpointslists intoHttp4sResourceDocAggregation(nameOfis acompile-time macro over the member name, so sourcing it from
Http4sNNN.ImplementationsXyields identical strings).
version/versionStatusfor the v5.0.0 and v5.1.0 root endpoints — bothHttp4sNNNobjects already declared their own
versionStatuswith matching values, so the/rootpayload is byte-identical.OBPAPI one:
OBPAPI3_0_0.Implementations2_2_0really isHttp4s220.Implementations2_2_0.FrozenClassUtil's version list. It recovered this by scanning the classpath forVersionedOBPApisimplementors, which in practice meant exactly these objects — so deletingthem would have emptied it. Worth noting how that would have failed: only the first of the
five frozen-contract scenarios asserts against an empty list; the other four iterate the
intersection and pass vacuously. Regenerating the fixture to "fix" the one red test would
have written an empty fixture and disabled all five guards with a green build. Instead the
enumeration is now explicit on
Http4sResourceDocAggregation, reading each version's statusfrom its
Http4sNNNso there is still one declaration per version. The fixtures were producedby the old scan and still match byte for byte, which is what makes the two paths equivalent.
VersionedOBPApisitself is deleted: with that scan gone it had no consumers, and its onlyremaining implementors were the two dynamic aggregators, whose members are read directly.
Two latent defects surfaced while doing this, both of which the deleted objects had been
masking, and both fixed here:
Http4sResourceDocAggregation.v121was the one catalog that did not force its ownImplementationsobject, on the documented grounds thatHttp4sAppstartup always did.The
OBPAPI*objects were also doing it from their static initializers, so a caller thatreads a catalog without booting a server (
SwaggerPathOrderAndArrayBodyTestis a plainFlatSpec) lost that cover. Since every later catalog snapshotsv121into a fresh buffer,an unpopulated one would drop all 70 v1.2.1 docs from the entire chain for the life of the JVM.
scripts/count_v7_endpoints.pyreadexcludeEndpointsper-version from theOBPAPI*files.With them gone it found nothing and, by design, treated "absent" as "empty" — so it silently
stopped filtering and reported 871 reachable endpoints instead of 852. It now reads the
suffixed names from their new home; the count is 852 again, with 6/8/14 excludes for
v4.0.0/v5.1.0/v6.0.0.
Not touched
obp-commons(published artifact for sibling repos)code/api/v1_2/JSONFactory1.2.scala,code/api/berlin/group/v1_3/BgSpecValidation.scala—live code in the same packages as deleted files
OBPAPIDynamicEntity,OBPAPIDynamicEndpoint), beyond droppingthe now-empty trait
Testing
mvn -o test-compile: clean, checked after every commit.export_and_verify.py --write: digest gate passed (9,288 field digests matching byte forbyte across all 12 versions) before any
.scalafile was touched;--check-onlypassesbefore and after the deletion commit.
check_lift_http4s_resource_doc_parity.py: exits 0, zero stale allowlist entries. Confirmedthe JSON-reading path produces identical shared/mismatch/only-* counts (958/115/6/15) to the
original
.scala-reading path before any allowlist entries existed.count_v7_endpoints.py: 852 reachable endpoints, unchanged across stages 2 and 3.FrozenClassTest+FrozenMetaDataTextTestpass against fixturesgenerated by the old reflection path, with the aggregators still present and after their
removal.
bootstrap.http4s.Http4sServer, isolated port): with the two propsat their default,
/obp/v4.0.0/endpoints/json-schema-validationsand/endpoints/authentication-type-validationsreturn 200 anonymously while their/management/...twins still 401; with both props forced true, the public routes return 401.Root and the v4.0.0 resource-docs listing responded normally throughout.
grepforAPIMethods(121|130|...|600)andOBPAPI(1_2_1|...|6_0_0)across*.scala: zero hits.run_tests_parallel.sh: all 4 shards plus the dedicatedPropGatedPublicEndpointstep green — 3688 tests, 0 failures, 0 errors, 16 skipped/canceledThe
ApiVersionUtilsTestfailure noted in this PR's earlier description ("20 was not equal to21") was pre-existing and is fixed here:
test.default.propsis gitignored, so local copiesdrift from what CI's "Setup props" step injects; without
berlin_group_v1_3_alias_path,OBP_BERLIN_GROUP_1_3_Aliasreports an emptyScannedApiVersionand is filtered out ofversionMapScannedApis, giving 20 versions instead of 21.run_tests_parallel.shnow injectsOBP_BERLIN_GROUP_V1_3_ALIAS_PATH, mirroring the three other CI-vs-local props gaps thatfunction already works around.