Skip to content

Commit 6ed6dda

Browse files
docs(migration): add ResourceDoc parity (per-version drift from Lift)
New section under "Resource-docs (separate workstream)" capturing the state of http4s vs Lift ResourceDoc parity per version, so reviewers can see what's pending without re-running the audit script. Covers: - The source-of-truth principle (APIMethodsXYZ.scala = canonical) and the verification that the commented stub files are byte-equivalent on ResourceDoc bodies to the pre-stub live Lift code (243/243 in v6, 111/111 in v5.1). - The three scripts in `scripts/` (audit + 2 restoration tools) and what each is good for. - A per-version drift table summarising 377 outstanding mismatches across 956 endpoints. - Detailed fix candidates for v6.0.0 (12 drifts), v5.1.0 (1 drift), and v5.0.0 (8 drifts + 3 only-http4s) — each row tags whether the resolution is "fix http4s to match Lift" or "document the intentional drift at the http4s site". - Strategy summary for the untouched versions (v1.2.1 → v4.0.0).
1 parent 98084ea commit 6ed6dda

1 file changed

Lines changed: 88 additions & 0 deletions

File tree

LIFT_HTTP4S_MIGRATION.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,94 @@ Currently served via a raw Lift `serve { case Req(..., "openapi.yaml", ...) }` b
164164

165165
---
166166

167+
## ResourceDoc parity (per-version drift from Lift)
168+
169+
Separate from the resource-docs **serving** workstream above, there is a parity workstream covering the **content** of each migrated ResourceDoc declaration. The goal is for every http4s `ResourceDoc(...)` to render identically to its Lift original, so the public API docs aren't silently degraded by migration.
170+
171+
### Principle
172+
173+
**`APIMethodsXYZ.scala` (Lift) is the source of truth for migration.** The commented-out Lift ResourceDocs and endpoints inside each `APIMethodsXYZ.scala` are the canonical reference for what the http4s version should render: URL templates, verb casing, summaries, descriptions, example bodies, error lists, tags. **Do NOT edit these files to make the audit pass** — the audit compares http4s against the Lift source-of-truth. When the audit flags a diff, the resolution is either (a) update http4s to match Lift, or (b) document the difference at the http4s site as a known intentional drift (placeholder rename for middleware, upstream-driven case-class shift, etc.). Rewriting the Lift comments runs the comparison backwards and erases the historical record. (Mistakes in commits `d95c1df01` and `6154bf2cc` did this; reverted in `27f48af72`.)
174+
175+
**Stub fidelity verified.** Commits `810589330` (v6) and `88f46f854` (v5.1) replaced the live Lift code with commented-out stubs. Comparing each stub's uncommented ResourceDoc bodies against the pre-stub live versions: **0 field diffs across 243/243 v6 docs and 111/111 v5.1 docs**. The non-ResourceDoc deltas (imports, etc., ~16KB v6 / ~5KB v5.1) are immaterial. The stubs are an exact preservation of the original Lift ResourceDocs.
176+
177+
### Tooling (`scripts/`)
178+
179+
| Script | Role |
180+
|---|---|
181+
| `check_lift_http4s_resource_doc_parity.py` | Read-only audit. Parses both files, matches by `nameOf(...)` (with `.replace("a","b")` evaluation for derived names), reports per-field diffs. `--field=X` to focus, `--list-only` for endpoint-presence summary. |
182+
| `rehydrate_resource_docs.py` | Upstream (simonredfern, `67593ea28`). Lifts positional args 7/8/9 (description, exampleRequestBody, successResponseBody) from commented Lift blocks into http4s. Has a `split-init` subcommand for JVM 64KB method-size workaround. |
183+
| `restore_resource_doc_bodies.py` | Companion to the above. Restores any subset of (summary, description, exampleRequestBody, successResponseBody, errorResponseBodies, tags) from Lift into http4s. Surgical per-field replacement preserves layout. `--fields=X,Y` to scope, `--only=ep` to target one endpoint. |
184+
185+
### Current drift (audit re-run 2026-05-21 evening)
186+
187+
| Version | shared | mismatch | only-lift | only-http4s | Status |
188+
|---|---|---|---|---|---|
189+
| v1_2_1 | 70 | 48 | 0 | 0 | not started |
190+
| v1_3_0 | 3 | 0 | 0 | 0 | clean |
191+
| v1_4_0 | 10 | 1 | 0 | 0 | one minor |
192+
| v2_0_0 | 37 | 19 | 0 | 0 | not started |
193+
| v2_1_0 | 23 | 13 | 5 | 2 | not started |
194+
| v2_2_0 | 18 | 13 | 0 | 0 | not started |
195+
| v3_0_0 | 47 | 41 | 0 | 0 | not started |
196+
| v3_1_0 | 102 | 49 | 0 | 0 | not started |
197+
| v4_0_0 | 254 | 172| 2 | 5 | not started |
198+
| v5_0_0 | 39 | 8 | 0 | 3 | descriptions restored; structural/errors remain |
199+
| v5_1_0 | 111 | 1 | 1 | 2 | one verb-casing drift to fix |
200+
| v6_0_0 | 243 | 12 | 0 | 1 | 11 placeholder renames + 1 routing-shape upstream change |
201+
| **Total** | **956** | **377** | | | |
202+
203+
### v6.0.0 — 12 specific drifts (each is a fix candidate)
204+
205+
These are the cases where http4s deviates from Lift. Under the source-of-truth rule, the default is to fix http4s; deliberate exceptions need to be documented at the http4s site.
206+
207+
| Endpoint | Field | Lift | http4s | Resolution |
208+
|---|---|---|---|---|
209+
| `createCounterpartyAttribute` | requestUrl | `…/counterparties/COUNTERPARTY_ID/attributes` | `…/COUNTERPARTY_ID_PARAM/…` | TBD — verify `ResourceDocMatcher` correctly handles `COUNTERPARTY_ID` as a wildcard (the literal set contains `COUNTERPARTY`, but `COUNTERPARTY_ID` is whole-segment-different). If safe, revert to Lift's name. |
210+
| `deleteCounterpartyAttribute` | requestUrl | same | same | same as above |
211+
| `getAllCounterpartyAttributes` | requestUrl | same | same | same as above |
212+
| `getCounterpartyAttributeById` | requestUrl | same | same | same as above |
213+
| `updateCounterpartyAttribute` | requestUrl | same | same | same as above |
214+
| `createTransactionRequestCardano` | requestUrl | `…/ACCOUNT_ID/owner/transaction-request-types/CARDANO/…` | `…/ACCOUNT_ID/VIEW_ID/…/CARDANO/…` | **Functional broadening** — http4s lets any view, Lift hardcoded `owner`. Keep http4s; document at the http4s ResourceDoc site. |
215+
| `createTransactionRequestHold` | requestUrl | `…/owner/…HOLD/…` | `…/VIEW_ID/…HOLD/…` | same as above |
216+
| `getSystemViewById` | requestUrl | `/management/system-views/VIEW_ID` | `/management/system-views/SYS_VIEW_ID` | TBD — disambiguation rename. If `ResourceDocMatcher` handles both fine, revert. |
217+
| `updateSystemView` | requestUrl | `/system-views/VIEW_ID` | `/system-views/UPD_VIEW_ID` | same as above |
218+
| `removeBankReaction` | requestUrl | `…/reactions/EMOJI` | `…/reactions/EMOJI_REACTION` | `EMOJI` is NOT in `literalAllCapsSegments` (only `EMAIL`/`SMS`/`IMPLICIT` of the SCA cluster are). Rename may have been defensive; safe to revert. |
219+
| `removeSystemReaction` | requestUrl | same | same | same as above |
220+
| `getAccountDirectory` | successResponseBody | `FastFirehoseRoutings(bank_id, account_id)` | `AccountRoutingJsonV121(scheme, address)` | **Upstream functional change** (`9e151c524` / `9dc4c4c46` migrated the case class). Cannot revert; document. Also note: the same change broke `mvn test` (pre-existing upstream compile error in `JSONFactory6.0.0.scala:2934`). |
221+
222+
Also: 1 only-http4s (`createWebUiProps`) — genuinely http4s-only with no Lift counterpart. Document.
223+
224+
### v5.1.0 — 1 specific drift
225+
226+
| Endpoint | Field | Lift | http4s | Resolution |
227+
|---|---|---|---|---|
228+
| `revokeMyConsent` | requestVerb | `"Delete"` | `"DELETE"` | Trivial casing fix on the http4s side. |
229+
230+
Also:
231+
- 1 only-lift (`createConsentImplicit`) + 1 only-http4s (`createConsent`) — Lift had `lazy val createConsentImplicit = createConsent` aliasing and registered the doc under the alias; http4s registers under the canonical name. Fix: in http4s, either rename the partial function to `createConsentImplicit` to match Lift, or register a second `nameOf(createConsentImplicit)` doc for the same handler.
232+
- 1 only-http4s (`getBanks`) — kept in the v5.1.0 layer for metrics attribution (intentional addition; see comment at `Http4s510.scala:288`). Document.
233+
234+
### v5.0.0 — 8 specific drifts + 3 only-http4s
235+
236+
| Category | Count | Endpoints | Resolution |
237+
|---|---|---|---|
238+
| requestUrl placeholder rename | 1 | `createAccount` (Lift `ACCOUNT_ID` → http4s `NEW_ACCOUNT_ID` for the PUT-creates pattern) | Verify matcher behavior; may be required for `ACCOUNT_ID` literal handling. |
239+
| errorResponseBodies — SCA val-vs-inline | 3 | `createConsentByConsentRequestIdEmail` / `Sms` / `Implicit` | http4s uses `private val createConsentByConsentRequestIdCommonErrors = List(...)` for DRY; Lift inlined the list. Either inline the val in the 3 doc registrations to match Lift verbatim, or extend the audit script to expand simple `val X = List(...)` references. |
240+
| errorResponseBodies — system-view accuracy | 4 | `createSystemView`, `deleteSystemView`, `getSystemView`, `updateSystemView` | http4s has more accurate errors (`SystemViewNotFound`, `SystemViewCannotBePublicError`, `InvalidSystemViewFormat`). Lift had wrong/legacy errors (`BankAccountNotFound`, `$BankNotFound`, `"user does not have owner access"`). **Genuine improvement** — document at http4s site. |
241+
242+
Also: 3 only-http4s (`getBanks`, `getProduct`, `getProducts`) — kept in this layer for metrics attribution. Document.
243+
244+
### Strategy summary
245+
246+
For each remaining drift on a migrated version:
247+
1. **Default**: fix http4s to match Lift verbatim. Use `restore_resource_doc_bodies.py` for field-level restoration.
248+
2. **Documented exceptions**: where the drift is a deliberate http4s improvement or required by middleware semantics, leave the drift and add a `// Lift had X; we use Y because Z` comment at the http4s ResourceDoc site.
249+
3. **Never**: edit `APIMethodsXYZ.scala` to make the audit pass. The Lift comments are the canonical record.
250+
251+
Untouched versions (v1_2_1 through v4_0_0, plus v2_1_0) need the same treatment: run `rehydrate_resource_docs.py` then `restore_resource_doc_bodies.py`, then audit and address any residual drifts at the http4s site.
252+
253+
---
254+
167255
## Auth Stack (separate workstream)
168256

169257
Token-generation paths — not version-file endpoints. Each `extends RestHelper` and needs to become an http4s route or middleware independently. Can run in parallel with the APIMethods migration.

0 commit comments

Comments
 (0)