# io-product — V3 migration plan

**Branch:** `v3` (forked from `master` @ v1.0.9, 2026-05-13)
**Target first V3 release:** `v3.0.1`
**Triggered by:** [Project Hermes](https://gitlab.apexl/apexl-internal/hermes) needs a Cygnus V3-compatible product/catalogue module for its Product + Plan model.

## Why migrate

- V1 codebase targets `apexl/io ^1.0` + PHP `^7.1`. Cygnus V3 era requires `apexl/io ^3.6` + PHP 8.4.
- V1 has just one Entity (`Product`) with `parent_id` for variant/child products. Hermes will extend the schema with `Plan` (a billable variant of a Product with associated pricing + limits) — likely in `apexl/io-subscription` or a new `apexl/io-billing` module.
- V3 modernises to align with the platform-extension layer (taxonomies, views, search, custom fields).

## Migration scope

### Composer constraints
- `php` `^7.1` → `^8.4`
- `apexl/io` `^1.0.0` → `^3.6`
- Drop `minimum-stability: dev`
- Switch repos from `codestore.sc.vg` to `packages.apexl` at release time.

### Namespace
- `apexl\Io\modules\product\*` — unchanged from V1.

### PHP 8.4 compatibility sweep
- `declare(strict_types=1)` throughout.
- Add return + parameter types.
- Audit Entity casts (use `array_merge(parent::casts(), [...])` per V3 framework-bug note).
- Replace any `app\module\*` namespaces.
- `phpstan` level 6 before tagging.

### Entity modernisation
- `productEntity` adopts V3 patterns: `HasEntityFactory`, `getData()` if denormalised columns added, `Indexable`, `Ownable`, `Tagged`.
- Add `product_category`, `product_status` taxonomies (system-seeded) so consumers categorise products without enum hardcoding.
- Add Feature tests.

### Custom fields integration
V3 io-product should expose itself to `apexl/io-custom-fields` so consumers can extend the product schema per-tenant (e.g. Hermes vendors adding their own product attributes without forking the entity).

### Display module (productDisplay → @apexl/icarus-product)

Extract Vue components from `productDisplay/` into a new `@apexl/icarus-product` npm package on `http://npm.apexl/`. Components TBD on inspection — likely product editor form + product list + variant picker.

## Phasing

1. **Scaffold v3 branch + composer constraints + plan doc** ✅ (this commit)
2. **PHP 8.4 sweep** — types, strict_types, casts merge.
3. **Bump apexl/io to ^3.6** — fix the API breakages.
4. **Taxonomy + custom-fields integration** — `product_category` + `product_status` seeded; entity exposed to custom-fields.
5. **Vue split** — extract `productDisplay/` → `@apexl/icarus-product`.
6. **Tag v3.0.1**.

## Open questions

- **Repo group:** keep on Bitbucket / codestore (legacy GlobalSim) or migrate to GitLab / packages.apexl (V3 era)? **Recommend GitLab** for V3 publication, leaving V1 on Bitbucket for back-compat.
- **Plan entity placement:** Plans are a Hermes concept (plan tier with pricing + limits). Should Plan live in io-product (extending it) or in io-subscription (where it's billed) or a new module? Probably **io-subscription** — Plan is the billable definition; Product is the saleable thing.
- **Hermes's per-vendor product catalog:** does Hermes use io-product directly, or wrap it? Hermes vendors define their own products + plans. Probably uses io-product directly with `tenant_id` scoping.

## Status

- 2026-05-13: v3 branch created. Migration plan committed. composer.json bumped. No code changes yet.
- 2026-06-06: **Minimal finance-scoped V3 implemented + released as 3.0.0.** Clean-room rewrite to
  modern Cygnus conventions (flattened `src/`, `apexl\Io\modules\product\` PSR-4, `BasicApiModule`,
  modern `Entity`+`HasCasts`, `services.php` autowire, phinx migration in `src/db/migrations`,
  `extra.module` self-declaration, phpunit tests). The legacy V1 tree (operators / hook-callbacks /
  schema.json / payment+subscription coupling) was removed. Scope intentionally limited to the generic
  catalogue (`products`: code/name/kind/price/cost/markup/currency/variants/flags) + `ProductService` +
  `ProductPermission` + REST. **DEFERRED to a later (Hermes-coordinated) pass:** `product_category` /
  `product_status` taxonomies, io-custom-fields integration, and the `productDisplay` → `@apexl/icarus-
  product` Vue split. Driven by the Town Centre finance programme (Phase A.2.0) which consumes this for
  its rate-card catalogue.
