Migration Status — EC-CUBE 4.3 → BEAR.Sunday + Be Framework
Migration Status — EC-CUBE 4.3 → BEAR.Sunday + Be Framework
Living document. Update the relevant row/cell whenever a layer’s status changes. Updated 2026-06-09 JST against
1.xcommitf4d77609,alps.json,be/src,src/Resource,var/templates,var/sql,docs/api/openapi.json, and the Web E2E evidence set.
The migration runs through 5 layers. ALPS is the source of truth; the lower layers implement it. “Done / partial / pending” is judged against the ALPS spec, route-gate coverage, and the explicit residual boundary, not optimistically.
1. Summary
| Layer | Done | State |
|---|---|---|
1. ALPS spec (alps.json) |
534 descriptors, 207 transition descriptors | Complete as current contract. 207 transitions = 97 safe + 46 unsafe + 64 idempotent descriptors. Route connection / safety-retreat decisions are explicit instead of implicit controller behavior. |
2. Be domain (be/src) |
147 Input / 148 Final / 157 Semantic / 14 Being / 39 Reason Entity | Complete for the migrated behavioral contract and connected hard-route surfaces. Remaining work is not unknown domain coverage; it is named compatibility residuals (target-engine SQL verification, product CSV import, plugin lifecycle, export fidelity). |
| 3. BEAR Resource | 146 Page resource files | Aura route extras map EC-CUBE route name ↔ URL path ↔ resource URI. Resource files include storefront, admin, fallback/action, and support-style page resources, so this metric is broader than older “139 page resource” snapshots. |
4. SQL persistence (var/sql + Ray.MediaQuery) |
54 query interfaces, 150 #[DbQuery], 150 SQL files |
Phase 2 has been cut over from concrete Sql* adapter classes to Ray.MediaQuery direct proxies. Prod SQL binding is SqlModule → MediaQueryRuntimeModule; reproducible prod DB seed script exists. |
5. HTML presentation (var/templates) |
133 Twig templates | Phase 3 complete for the in-scope migration. Current inventory: 43 storefront/non-admin page templates, 72 admin page/partial templates, 15 shared Block templates, 3 frames. Storefront is covered; admin in-scope editor waves are covered; Store/Plugin install/search subtree remains out of scope. |
Test baseline: after the PR closeout and API doc refresh, GitHub Actions on 1.x
passes composer psalm and composer test; PHPUnit reports 1734 tests, 26059 assertions.
The latest Web E2E evidence set (20260608-canonical-resource-routes-web-e2e) runs
html-prod-hal-api-app against an actual DB and records 181 pass / 2 fail / 3 out-of-scope
across 186 features with 140 retained screenshots. Target-engine SQL portability still needs
explicit MariaDB 10.11 verification where noted in §4.
2. Feature matrix
Rows = flow-* feature areas (see docs/tag.md for the tag taxonomy). Columns = the 5 layers.
Counts are ALPS transitions per flow. ✓ done · ~ partial · ✗ pending.
| Feature area (flow) | ALPS | Be domain | BEAR Resource (JSON) | SQL | HTML |
|---|---|---|---|---|---|
| flow-browse (catalog browse) | ✓ 5 | ✓ | ✓ | ✓ | ✓ storefront |
| flow-purchase (cart→checkout) | ✓ 19 | ✓ (doCreateOrder + doCheckout both: PurchaseFlow + dtb_order_item snapshot) |
✓ | ~ (order-item snapshot SQL caveat in §4) | ✓ storefront |
| flow-register (customer signup) | ✓ 3 | ✓ | ✓ | ✓ | ✓ storefront |
| flow-account (mypage / address) | ✓ 15 | ✓ | ✓ | ✓ | ✓ storefront |
| flow-favorite | ✓ 3 | ✓ | ✓ | ✓ | ✓ storefront |
| flow-inquiry (contact form) | ✓ 2 | ✓ | ✓ | ✓ (Contact has no table) |
✓ storefront |
| flow-admin-auth | ✓ 1 | ✓ | ✓ | ✓ | ✓ admin |
| flow-manage-product | ✓ 26 | ~ (no Be transition for product CSV import — ProductCsv::onPost parses inline; category/class CSV paths go through Be) |
✓ | ✓ | ✓ admin (list/tag/class + product/category/csv editors + product-class register done) |
| flow-manage-order | ✓ 14 | ~ (PDF fidelity residual; shipping CSV persistence connected) | ✓ | ✓ | ✓ admin (list + edit/shipping/mail/mail_confirm/pdf/csv-shipping done) |
| flow-manage-customer | ✓ 11 | ✓ | ✓ | ✓ | ~ admin (list + customer edit done; customer-delivery-edit creates new addresses only — update/delete are unreachable from the UI, see CustomerDeliveryEdit.php docblock) |
| flow-manage-shop | ✓ 15 | ✓ | ✓ | ✓ | ✓ admin (payment/delivery/tax list + calendar/csv/order-status/tradelaw + payment/delivery edits + shop-master editors done) |
| flow-manage-content | ✓ 9 | ✓ | ✓ | ✓ | ~ admin (news/page/css/js/cache/maintenance done; content/file-manager renders POST forms with no write handler — see §2.1) |
| flow-manage-cms (layout/block) | ✓ 8 | ✓ | ~ (Template list/add only) | ✓ | ✓ admin (layout/block/template list + template_add done) |
| flow-manage-system | ✓ 8 | ✓ | ✓ | ✓ | ~ admin (member/login-history + system/log/security/masterdata/authority done; two-factor-auth-edit renders a POST form with no write handler — see §2.1) |
| flow-manage-mail | ✓ 2 | ✓ | ✓ | ✓ | ✓ admin (mail-template editor done) |
| flow-manage-plugin (out of scope) | ✓ 6 | ~ (doInstallPlugin stub) |
✓ | ✓ | ~ admin (plugin list done; install/search out of scope) |
| route-gate transitions | ✓ 60 | ~ (connected surfaces; some fidelity residuals) | ✓ | n/a | n/a |
| non-flow behavioral transitions | ✓ 9 | ✓ | n/a | n/a | n/a |
Layer-specific notes:
- ALPS: 217 transitions — the older 144-transition snapshot has been superseded by route-gate additions and several behavioral descriptors that make route/fallback decisions explicit.
- SQL: 150/150 — every
#[DbQuery]id has a matching SQL file undervar/sql/, and the smoke coverage test enforces this pairing. - HTML: storefront ✓ / admin ✓ (in scope) —
var/templatesholds 133.html.twigfiles: 43 storefront/non-admin pages, 72 admin pages/partials, 15 Block widgets, and 3 frames (base.html.twig,admin-base.html.twig,admin-login-base.html.twig). The remaining admin Store/Plugin install/search subtree is out of scope because the plugin runtime is excluded. The render-diff fidelity tests (tests/Resource/*HtmlRenderTest.php) activate only when the gitignoredtools/ec-cube-source/4.3 clone is present. - flow-manage-cms Resource —
Admin/Template/TemplateList.php+TemplateAddexist for the CMS template feature; layout/block resources are present but the CMS template-management surface is partial — unverified in full.
2.1 Rendered forms without a write handler
Two admin resources still render a <form method="post"> that no method
answers. The markup was ported ahead of the handler, so the button reaches
BEAR\Resource and comes back 405. Reproduce any row with
composer page -- post <path>.
| Template | POST target | Resource | Methods |
|---|---|---|---|
Page/Admin/TwoFactorAuthEdit.html.twig:125 |
/admin/two-factor-auth-edit |
Admin/TwoFactorAuthEdit.php |
onGet |
Page/Admin/Content/FileManager.html.twig:308,348,382 |
/admin/content/file-manager |
Admin/Content/FileManager.php |
onGet |
Each of the remaining two needs a scope decision before a transition: file-manager
needs a multipart file-I/O design, and two-factor-auth-edit needs the
admin-editing-another-member 2FA semantics worked out (issue #143).
Page/Admin/Product/CsvProduct.html.twig was an earlier entry. Its upload posted
to its own screen URL instead of /admin/product-csv, where ProductCsv::onPost
already implements the import (the router turns an import_file upload into the
csv parameter). Repointing the action was the whole fix — no new transition.
Admin/CustomerDeliveryEdit.php, Admin/Customer.php, and
Admin/Product/ProductClass.php were three more entries, fixed for #143: each
gained an admin-specific Be Input/Final (AdminCreateCustomerDeliveryAddressInput,
AdminUpdateCustomerDeliveryAddressInput, AdminDeleteCustomerDeliveryAddressInput,
AdminUpdateCustomerInput, AdminRegisterProductClassInput) distinct from the
storefront transitions —
UpdateCustomerAddressInput omits customerId on purpose and derives the owner
from the customer session, which is the opposite of an administrator editing
someone else’s row.
tests/Router/TemplateFormActionTest.php holds the same list and fails both
ways: a third dead form breaks the build, and so does an entry that is no
longer dead. The other 121 POST forms resolve to a resource that writes.
2.2 #[Alps] references the profile does not define
alps.json is the SSOT and #[Alps('id')] is a resource claiming to implement
one of its transitions. Nothing checked that the id exists — asd --validate
validates the profile, not the references into it — and 19 had drifted; 15 were
resolved for #143. tests/Alps/AlpsReferenceTest.php now holds the remaining
list and fails on a fifth as well as on an entry that has since been resolved.
| Group | Count | What it needs |
|---|---|---|
| Screens and actions absent from the profile | 4 | A descriptor each |
The four: doCreateMailTemplate, goAdminContentFileManager,
goAdminTwoFactorAuthEdit, goShoppingShippingMultipleEdit.
goShoppingShippingMultipleEdit is not a rename — it is an editor screen
distinct from the goShoppingShippingMultiple (list) transition it links to.
Two of the four are also the two remaining §2.1 dead forms
(goAdminContentFileManager / goAdminTwoFactorAuthEdit), so for those the
read descriptor, the write descriptor and the handler land together.
Resolved for #143: the route-gate/fallback ids (doActionRedirect,
goUnsupportedRoute, +6) and the placeholder goAdminEmptyPage dropped
#[Alps] — a client cannot discover a URL EC-CUBE has that BeMart
deliberately does not model as an application transition. goAdminLog /
goAdminOrderOrderPdf / goAdminOrderMailConfirm / goAdminTemplateTemplateAdd
were renamed (the last two to existing profile ids goOrderMailConfirm /
goTemplateInstall; the first two to new descriptors goLog / goOrderPdf,
since goAdminOrderOrderPdf is not a rename of goExportOrderPdf — it is the
distinct options-form screen that links to it). goAdminCustomerDeliveryEdit
/ goAdminProductProductClass became goCustomerDeliveryEdit /
goProductClass alongside the §2.1 dead-form fixes above.
3. Phase log
| Phase | Scope | Key commits |
|---|---|---|
| Phase A | Be domain + BEAR JSON resources. Pilots 1–5 established the Be patterns, then parallel waves took the original behavioral transition set to completion. Later ALPS remediation and route-gate additions expanded the contract, but the original Phase-A figure remains historical. Phase B added Psalm taint setup, ProdModule, env-gated entry point. | Recorded in docs/HANDOVER.md (historical log) |
| Phase 2 — SQL | Fake → SQL, then SQL → Ray.MediaQuery boundary cleanup. The original storage-interface migration used G-23’s workflow/state-transition contract discipline, historically named hypermedia-test-as-contract; the current form is 54 MediaQuery interfaces and 150 SQL files with prod context bound through SqlModule / MediaQueryRuntimeModule. Reproducible prod DB seed (mtb_* masters + setup script) exists. |
3a439a2, 0757f26, 051d235, fd96242 (2a); f6f22ee…9a9c89b (2b); f128ba6, 6ed334d (2c); later Ray.MediaQuery cutover |
| Phase 3 — HTML | BEAR resources rendered as HTML; templates are faithful ports of EC-CUBE’s default and admin Twig themes (see var/templates/README.md). Storefront done in waves plus shared Block widgets. Ray.WebFormModule adopted for form pages. Enrichment re-derived thin resource bodies from EC-CUBE so HTML can be faithful (Cart, Mypage History, Shopping confirm/complete). Admin theme then ported through Tier-1 and in-scope Tier-2 editor waves; Store/Plugin install/search subtree remains out of scope. Current template inventory is 133 Twig files. |
762a739/2525710/9d06ec3 (Cart pilot); 1507dc2 (wave 1) → 46b2a08 (wave 7); 5a95435 (WebFormModule); f91e10f (admin News pilot); 1e91e92 (per-section ja-split); da48413 (Customer); section-waves batches 1–2; 2f59bb3…a455281 (Order Tier-2); 4eb93f3…0296306 (Product Tier-2); 571dd5b (Store template_add); f3df0d4 (Block widgets); 1177e0d/2f8d17a (Shopping enrich); 5d9e6ba (fidelity-test fixes); f9c5580 (doResendActivationMail) |
| Phase B — security / production hardening | Psalm taint setup, ProdModule, env-gated CLI entry point, EC-CUBE static-asset deployment (default + admin themes), and the HTTP router — Aura.Router maps EC-CUBE route name ↔ URL path ↔ resource URI through route extras; the BEAR.Sunday RouterInterface adapter returns RouterMatch, while BEAR\Resource owns missing resource 404 and method 405; BeMartTwigExtension::url()/path() resolve through Aura’s generator. |
a002097 (asset deploy); 53e587e/39f1117 (HTTP router); 16e8c9d (asset-package-aware render stubs) |
ALPS remediation (f01e1ae, per docs/phases/alps-audit-phase3.md) happened during Phase 3:
it re-tagged Favorite and added transitions that Phase A’s domain never saw. Later route-gate work made hard route/fallback decisions explicit in ALPS, so the current profile is larger than the Phase-A/Phase-3 snapshots.
4. Outstanding work
Punch-list, roughly highest-effort first:
- Admin HTML Tier-2 — rendered, two write handlers missing. Admin Tier-1 plus every in-scope Tier-2 editor wave is ported as markup: flow-manage-system, Customer delivery-edit, Setting/System, Setting/Shop, Order, Product, and Store template_add. Current admin inventory is 72 admin page/partial templates. Two of those screens post to a resource that cannot answer — §2.1 lists them, and until each gains a write handler the editor is display-only. The remaining Store/Plugin install/search subtree is out of scope because plug-ins are excluded from this migration. Per-section history:
docs/phases/admin-fanout-plan.mdandvar/templates/README.md“Fan-out status”. - HTML enrichment backlog. Phase 3 flagged data pages whose resource bodies are too thin for a faithful EC-CUBE port; each needs the Cart-style re-derive (ALPS → Entity/SQL/Fake enrich → template wiring). Done: Mypage History (
a31f8d8/3c1b03d), Shopping confirm/complete (1177e0d/2f8d17a). Still open: Mypage dashboard, Favorite, Address, Contact. Block/*widget templates — done. ✓ Done. ThelogoandfooterBlock widgets are ported (var/templates/Block/,f3df0d4). The remaining Block regions (cart/login/search) stay EC-CUBE-runtime residuals; Block is intentionally not modelled in ALPS.- Phase-3 remediation transitions — all implemented. ✓ Done. The named transitions the Phase-3 ALPS remediation added are implemented in
be/src(doSortNoMove,doToggleVisible,doUpdateTrackingNumber,doSendShippingNotifyMail,doResendActivationMail— domain + storage/mailer + JSON resource + tests). Later route-gate descriptors are tracked separately from this remediation set. - Phase-A stub / compatibility residuals.
goExportOrderPdfis now the Issue #24 compatibility pilot: Resource reachability, download headers, and%PDF-body generation are implemented through an isolated EC-CUBE/TCPDF service, but full EC-CUBE fidelity (delivery-note layout parity,dtb_order_pdfsaved settings, multi-shipping template reproduction) is intentionally left as a tracked residual.doImportCategoryCsvanddoImportShippingCsvare real —CategoryCsvImportedparses the 4-column EC-CUBE format and upserts/deletes viaCategoryStorageInterface(+CategoryIdQueryInterfacefor new ids);AdminShippingCsvImportedresolves each row’s order and writes the tracking number through the sameShippingAddressStorageInterface::updateTrackingNumbersurface as the inlinedoUpdateTrackingNumber(durable persistence covered by the SQL suite; Fake writes are no-ops).doUpdateCsvis consumed end-to-end — the export Finals overlay saveddtb_csvconfiguration on their default column vector viaCsvColumnLayout::resolve, preserving default output when config is absent or enables no known columns.doCreateOrderanddoCheckoutnow converge on PurchaseFlow +dtb_order_itemsnapshot writes — admin order creation and storefront checkout both freeze line items throughOrderItemCommandInterface::register, with domain wiring pinned byAdminOrderCreatedTest/CheckoutCompletedSnapshotTest. ⚠ SQL verification caveat: the durable order-item SQL path still needs a green target-engine run ofDATABASE_URL=... vendor/bin/phpunit --testsuite sql;order_item_register.sqlusesJSON_TABLEwhile the target is documented as MariaDB 10.11, so portability must be confirmed or the INSERT rewritten withoutJSON_TABLE. Thealps.jsoncontract was synced to match (OrderItemInput, regenerated HTML/SVG artifacts). Still stubbed / intentionally-not-modelled:doImportProductCsv(intentionally not migrated — the route is export-only),doInstallPlugin(plugin scope, out of scope). #[Input]-vs-Form refactor. Noted from MyVendor.Cms issue #37 — reconcile Be Framework#[Input]with theRay.WebFormModuleAbstractForm. Unverified here — confirm against that issue before acting.- Production DB bring-up. Phase 2c shipped the seed script and prod
SqlModulebinding; an actual production database bring-up / cutover is still pending. - Hard ActionRedirect routes — connected. ✓ Done. The 22 Hard rows that Issue #24 parked on
ActionRedirect(docs/eccube-feature-alps-status.html) are now wired to concrete Be/BEAR resources with the Be domain transition implemented: 認証/credential (doChangePassword / doVerifyTwoFactorAuth / doSetTwoFactorAuth / doUpdateSecurity), コンテンツ/file (doClearCache / doUpdateContentCss / doUpdateContentJs / doToggleMaintenance), マスタデータ (doSelectMasterData / doUpdateMasterData), 規格CSV (goExportClassName / goExportClassCategory / doImportClassNameCsv / doImportClassCategoryCsv), Store/template (doSelectTemplate / doDeleteTemplate / doDownloadTemplate / doInstallTemplate). Each side-effect (credential hash, TOTP, config/cache/asset files, CSV encode/parse, template zip/install) is isolated behind abe/src/Reason/Service/*Interfaceboundary with ansrc/Compatibility/Eccube/default + a Fake — the Issue #24 PDF-pilot pattern. Full EC-CUBE fidelity for those side-effects (real file writes, byte-exact CSV, persisted TOTP secret) is the tracked production-cutover residual. Difficulty stays Hard; the routes are now実装済み, so the Hard-ActionRedirect count is 0. ⚠ 2FA setup pre-auth residual (PR #28 review —TwoFactorAuthSet::onPut): the device-setup page is reached PRE-AUTH (anonymous login-context), so it currently takesloginId+ the candidate TOTP secret from the request body, andTwoFactorAuthInterface::enable()overwrites the secret for thatloginIdwith no ownership check — a caller who passes another admin’sloginIdcould replace that admin’s 2FA device. The production cutover must bind a server-generated secret + the pending login identity into a pre-auth session/challenge state at credential-verification time and consume it here instead of trusting the client values; until then the route relies on CSRF + the documentedenable()contract. Do not widen this surface (e.g. expose it post-auth for an arbitraryloginId) before the challenge state lands.
5. Where things live
| You want… | Look at |
|---|---|
| The feature list (source of truth) | alps.json · docs/alps.json.html · docs/alps.svg |
Tag taxonomy (flow-*, src-*) |
docs/tag.md |
| Phase A detail (Be domain + JSON) | docs/HANDOVER.md |
| Phase 2 detail (SQL) | sql/diff/entity-vs-eccube.md · var/sql/ · src/Module/MediaQueryRuntimeModule.php |
| Phase 3 detail (HTML) | docs/phases/alps-audit-phase3.md · var/templates/README.md |
| Route/function status + migration difficulty | docs/eccube-feature-alps-status.html |
| Migration skills / lessons (G-14…G-25) | docs/skills/ |
| Docs map / index | docs/README.md |
| Continuation guide | docs/HOW_TO_CONTINUE.md |
| Stale older trackers (Phase A era, do not trust for current state) | docs/archive/progress.md · docs/archive/task_plan.md |