diff --git a/docs/README.md b/docs/README.md index be08a7d..4a27457 100644 --- a/docs/README.md +++ b/docs/README.md @@ -9,6 +9,7 @@ built, operated, and evolved. |-----------------|---------------------------------------------------------------------| | `architecture/` | Architecture, boundaries, invariants, and ADRs | | `development/` | Local development and implementation guidance | +| `discovery/` | Phase reports: Phase 0 assessment, Phase 1 review | | `engineering/` | Engineering process and standards — testing, quality, workflow | | `operations/` | Deployment, infrastructure, monitoring, and incident procedures | | `product/` | Product requirements, scope, personas, goals, and product decisions | @@ -18,10 +19,14 @@ built, operated, and evolved. - New contributor? The repository [`../README.md`](../README.md) covers setup. - Building a change? [`engineering/definition-of-done.md`](engineering/definition-of-done.md) and [`engineering/git-workflow.md`](engineering/git-workflow.md). -- Understanding the system? [`product/vision.md`](product/vision.md), +- Understanding the product? [`product/product-requirements.md`](product/product-requirements.md) + and [`product/user-journeys.md`](product/user-journeys.md). +- Understanding the system? [`architecture/system-overview.md`](architecture/system-overview.md), + [`architecture/domain-context-map.md`](architecture/domain-context-map.md), [`architecture/INVARIANTS.md`](architecture/INVARIANTS.md), and the ADRs in [`architecture/adr/`](architecture/adr/). -- Where the marketplace is headed? [`architecture/marketplace-migration.md`](architecture/marketplace-migration.md). +- How Nexo 2.0 got here? [`discovery/`](discovery/): the Phase 0 assessment and the + Phase 1 review. ## Documentation Principle diff --git a/docs/architecture/INVARIANTS.md b/docs/architecture/INVARIANTS.md index c61d896..469222b 100644 --- a/docs/architecture/INVARIANTS.md +++ b/docs/architecture/INVARIANTS.md @@ -1,85 +1,172 @@ # System Invariants -These are properties that must remain true regardless of implementation details. +- **Status:** Revised 2026-11-01 (Phase 1 draft for owner review). This replaces the 2026-08-30 list. Every earlier invariant is kept, reworded or strengthened; the changes are listed at the end. -They represent architectural constraints rather than feature requirements. +These properties must hold regardless of implementation. Each one names its **enforcement**, meaning the mechanism that makes a violation impossible or detectable, and its **proof**, meaning the test or check that demonstrates it. An invariant without both is a wish, not an invariant. + +Requirement documents cite these as **[INV-n]**. --- -## Vendor Isolation +## Access and identity -Vendor-context queries must only expose records belonging to the -authenticated vendor. +**INV-1 · Vendor isolation.** A vendor context can read or change only records owned by its vendor. Storefront catalogue queries are intentionally not vendor-scoped. -Storefront catalog queries are intentionally not vendor-scoped. +- **Enforcement:** the `vendor.context` middleware fails closed; there is no global scope; route bindings are scoped; vendor queries require an explicit `vendorId`. +- **Proof:** the isolation suite (merge gate), plus an arch test that every vendor controller is covered (ADR-0011). ---- +**INV-2 · Identity.** -## Marketplace Identity +- A customer identity is marketplace-wide. +- A user is a member of at most one vendor. +- Platform staff belong to no vendor and place no orders. +- **Enforcement:** unique `vendor_members.user_id`, and application guards. +- **Proof:** domain tests. -A shopper has one marketplace-wide identity. +## Orders -A vendor-team user belongs to exactly one vendor. +**INV-3 · Order structure.** -A platform operator does not belong to a vendor. +- An OrderGroup is one customer checkout. +- A VendorOrder is exactly one vendor's portion, and all of its lines belong to that vendor. +- The group total equals the sum of its VendorOrder totals at creation. +- **Enforcement:** the checkout use case, plus a DB foreign key from line → variant → vendor that is checked at creation. +- **Proof:** property test over random carts. ---- +**INV-4 · Refund isolation.** A refund, cancellation or dispute outcome on one VendorOrder never changes the state or ledger entries of a sibling VendorOrder. -## Order Structure +- **Proof:** sibling-unchanged assertions in every refund and cancellation test. -An `OrderGroup` represents one shopper checkout. +**INV-5 · Refund cap.** For each VendorOrder, the sum of refunds in `requested | approved | submitted | succeeded` never exceeds the captured amount allocated to it. Per line, refunds never exceed the line's net amount. -An `Order` represents exactly one vendor's portion of that checkout. +- **Enforcement:** guarded counter updates on `vendor_orders.refund_committed_minor` and `vendor_order_lines.refund_committed_qty` (ADR-0015 §9). +- **Proof:** concurrent refund test on MySQL. -An order must never contain products belonging to multiple vendors. +**INV-6 · Snapshots and frozen rates.** Line prices, names and options, allocated discounts and points, shipping amounts, and the commission rate are fixed when a VendorOrder is created. Later catalogue, price or commission-configuration changes never alter existing orders. ---- +- **Proof:** mutation-after-order tests. -## Payment Ownership +**INV-14 · Guarded transitions.** OrderGroup, VendorOrder, ReturnRequest, Refund, PaymentAttempt, Reservation and Vendor statuses change only through their state machine. Each change uses a conditional update on the current status, so concurrent transitions cannot both succeed. -An `OrderGroup` has exactly one PaymentIntent for its total. +- **Proof:** an arch test (no status assignment outside state machines), plus concurrent transition tests. ---- +## Inventory -## Refund Isolation +**INV-7 · Stock.** For every variant: -A refund against one vendor's `Order` must never alter the financial state -of another vendor's `Order`. +- `0 ≤ reserved ≤ on_hand`; +- `reserved = Σ qty of active reservations`; +- `on_hand = Σ delta_on_hand of movements`. ---- +Stock is never oversold. -## Commission +- **Enforcement:** DB CHECK constraint, conditional updates, and the unique movement key. +- **Proof:** parallel-process tests and the nightly reconciliation check (ADR-0014). -The commission rate applied to an order is frozen at order creation. +## Money -Changing the platform commission configuration must not alter historical orders. +**INV-8 · Exact allocation.** Every split (discounts, points value, commission, dispute amounts) sums exactly to its source amount, in integer minor units. ---- +- **Proof:** property tests (ADR-0013). -## Inventory +**INV-9 · Idempotency.** -Inventory must never be oversold. +- One OrderGroup per (customer, checkout key). +- One effect per provider event id. +- At most one active payment attempt per group. +- At most one succeeded attempt per group. +- At most one ledger transaction per (type, reference). +- At most one consumption per inbox (consumer, message). +- **Enforcement:** unique keys. +- **Proof:** concurrent duplicate tests. -Stock reservation and release operations must be concurrency-safe. +**INV-10 · Ledger.** ---- +- Every ledger transaction balances (Σ debits = Σ credits, single currency). +- Entries are append-only. +- Balances are derived from entries. +- **Proof:** the posting-service assertion, the nightly check, and property tests (ADR-0016). -## Vendor Visibility +**INV-11 · Paid means captured.** An OrderGroup is `paid` if and only if exactly one PaymentAttempt has `succeeded`, with amount and currency equal to the group total. A provider event with a mismatched amount never marks a group paid. -A vendor's products are sellable only when the vendor satisfies the required -marketplace approval and payment-onboarding conditions. +- **Proof:** webhook processing tests plus nightly reconciliation. ---- +**INV-16 · Payout safety.** -## Auditability +- A payout never exceeds the vendor's available balance net of receivable. +- Held funds are never paid out. +- Each payout run pays each vendor at most once. +- **Proof:** concurrent payout-run test. -Money-moving operations and material vendor-state changes must produce an -auditable record. +**INV-17 · Points.** ---- +- A customer's spendable points balance equals the sum of their points-ledger entries and is never negative. +- Redemptions are held, then confirmed or released, exactly once. + +**INV-18 · Promotion limits.** Confirmed plus pending redemptions never exceed a promotion's total or per-customer limit. + +- **Enforcement:** a conditional update on the usage counter. +- **Proof:** parallel test on the last allowed use. + +## Catalogue and vendors -## Documentation +**INV-12 · Sellability.** A product is visible in the storefront and purchasable only if all of these hold: -Boundary-shaping architectural decisions must have an ADR. +- product `active`; +- not blocked; +- vendor `approved`; +- at least one active variant. + +One implementation is used by the storefront, search indexing and checkout. + +- **Proof:** a sellability matrix test across all three paths. + +**INV-13 · Vendor lifecycle.** + +- Vendor status is always one of `pending | approved | suspended`, and changes only through defined transitions. +- Vendors are never physically deleted. +- **Enforcement:** DB CHECK constraint, the state machine, and `RESTRICT` foreign keys. + +## Platform + +**INV-15 · Events if and only if commit.** An integration event is published if and only if the transaction that produced it commits. Consumers tolerate duplicates and reordering. + +- **Enforcement:** the outbox and inbox (ADR-0017). +- **Proof:** rollback and duplicate tests. + +**INV-19 · Auditability.** These actions write an audit record (actor, impersonator if any, action, subject, before/after, IP, timestamp) in the same transaction as the change: + +- money-moving actions; +- vendor lifecycle changes; +- moderation; +- commission changes; +- staff changes; +- reconciliation resolutions; +- impersonation. + +**INV-20 · Environment isolation.** + +- No Nexo 2.0 environment holds legacy production credentials. +- No environment accepts live payment keys. +- Tests run only against databases whose names end in `_testing`. +- **Enforcement:** boot checks and the test bootstrap guard (ADR-0009, ADR-0021). + +**INV-21 · Documentation.** Boundary-shaping decisions have an ADR. Scope changes update the product documents in the same change. + +--- -Changes to product scope must update the corresponding product documentation. \ No newline at end of file +## Changes from the 2026-08-30 version + +| Earlier invariant | Now | +|---|---| +| Vendor Isolation | INV-1, with enforcement made explicit | +| Marketplace Identity | INV-2, adding "staff place no orders" | +| Order Structure | INV-3 | +| Payment Ownership ("exactly one PaymentIntent for its total") | INV-9 / INV-11: retries can create several attempts over time; at most one active and at most one succeeded | +| Refund Isolation | INV-4, plus the new refund cap INV-5 | +| Commission (frozen at creation) | INV-6, extended to every snapshot | +| Inventory | INV-7, made quantitative | +| Vendor Visibility ("approval and payment-onboarding conditions") | INV-12; payment onboarding removed (no Stripe Connect, D-6) | +| Auditability | INV-19, with an explicit list | +| Documentation | INV-21 | +| — | New: INV-8, 10, 13–18, 20 | diff --git a/docs/architecture/README.md b/docs/architecture/README.md index 5b1c60b..a9d20f6 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -1,30 +1,50 @@ # Architecture Documentation -This directory records the architectural boundaries, invariants, and decisions -that shape Nexo. +This directory records Nexo's architectural boundaries, invariants and decisions. ## Contents -| Path | Purpose | -|-----------------------------|--------------------------------------------------------------------| -| `INVARIANTS.md` | Properties that must hold regardless of implementation | -| `marketplace-migration.md` | The plan for pivoting from multi-tenant SaaS to a single marketplace | -| `adr/` | Architecture Decision Records | +| Path | Purpose | +|---|---| +| [`system-overview.md`](system-overview.md) | Runtime components, code organisation, key flows | +| [`domain-context-map.md`](domain-context-map.md) | Modules (bounded contexts), owned data, relationships, glossary | +| [`dependency-rules.md`](dependency-rules.md) | Allowed and forbidden dependencies, enforced by arch tests | +| [`database-design.md`](database-design.md) | Initial database model, constraints and table ownership | +| [`INVARIANTS.md`](INVARIANTS.md) | Business invariants [INV-n], each with enforcement and proof | +| [`security-model.md`](security-model.md) | Roles, permission matrix, isolation and enforcement points | +| [`integration-contracts.md`](integration-contracts.md) | Browser ↔ Laravel, module ↔ module, and Nexo ↔ Stripe contracts | +| [`financial-model.md`](financial-model.md) | Ledger, commission, refunds, disputes, payouts, reconciliation, worked examples | +| [`lifecycles/`](lifecycles/) | Checkout and payment, inventory, orders/fulfilment/returns: state machines and failure-scenario matrices | +| [`vendor-domain-design.md`](vendor-domain-design.md) | Vendor entity design (2026-09), still current | +| [`marketplace-migration.md`](marketplace-migration.md) | *Superseded:* SaaS-to-marketplace migration plan | +| [`adr/`](adr/) | Architecture Decision Records | ## Architecture Decision Records -An ADR captures **one** boundary-shaping decision: why it was made, what was -rejected, and what must now be lived with. See -[`adr/0001-adr-template-and-process.md`](adr/0001-adr-template-and-process.md) -for when to write one and the template to use. +The template is [`adr/ADR-TEMPLATE.md`](adr/ADR-TEMPLATE.md) (ADR-0006). Proposed ADRs are not implemented until the owner accepts them. -| ADR | Decision | -|-----|----------| -| [0001](adr/0001-adr-template-and-process.md) | ADR template and process | -| [0002](adr/0002-vendor-is-a-tenant-record.md) | A "vendor" is the existing tenant record, reframed | -| [0003](adr/0003-context-dependent-vendor-scoping.md) | Context-dependent vendor scoping (retire the blanket global scope) | -| [0004](adr/0004-order-group-and-per-vendor-orders.md) | One basket, one payment, one Order per vendor | +| ADR | Decision | Status | +|---|---|---| +| [0001](adr/0001-adr-template-and-process.md) | ADR template and process | Accepted; template superseded by 0006 | +| [0002](adr/0002-vendor-is-a-tenant-record.md) | A vendor is the existing tenant record | Accepted. **Proposed to be marked Superseded by 0005** (fresh database) | +| [0003](adr/0003-context-dependent-vendor-scoping.md) | Context-dependent vendor scoping | Accepted; refined by 0011 | +| [0004](adr/0004-order-group-and-per-vendor-orders.md) | One basket, one payment, one order per vendor | Accepted. **Superseded by 0012 on acceptance** | +| [0005](adr/ADR-0005-vendor-naming.md) | Use Vendor as the seller entity | Proposed. **Recommended: accept** (file to be renamed `0005-vendor-naming.md`) | +| [0006](adr/0006-adr-process-v2.md) | Nexo 2.0 ADR template and statuses | Accepted (brief) | +| [0007](adr/0007-product-positioning-currency-and-locales.md) | Portfolio marketplace; MYR; EN primary with AR/MS | Accepted (D-4, D-5) | +| [0008](adr/0008-repository-and-frontend-stack.md) | This repository; Vue 3 + Inertia + TS | Accepted (D-1, D-2) | +| [0009](adr/0009-runtime-and-persistence-baseline.md) | Laravel 13 / PHP 8.5; MySQL 8.4 everywhere, including tests | Proposed (D-3) | +| [0010](adr/0010-modular-monolith-and-dependency-rules.md) | Modular monolith with enforced contracts | Proposed | +| [0011](adr/0011-identity-roles-and-vendor-isolation.md) | Identity, roles and fail-closed vendor isolation | Proposed | +| [0012](adr/0012-order-group-and-vendor-orders.md) | OrderGroup + VendorOrder state machines | Proposed | +| [0013](adr/0013-money-representation-and-allocation.md) | Money: integer minor units, deterministic allocation | Proposed | +| [0014](adr/0014-inventory-reservations.md) | Inventory: on-hand/reserved, TTL reservations, movement journal | Proposed | +| [0015](adr/0015-checkout-and-payment-orchestration.md) | Checkout saga, idempotency, webhook-driven payment | Proposed | +| [0016](adr/0016-financial-ledger-and-simulated-payouts.md) | Double-entry ledger; simulated payouts | Proposed (core approved as D-6; D-9/10/11 pending) | +| [0017](adr/0017-domain-events-and-transactional-outbox.md) | Transactional outbox and idempotent consumers | Proposed | +| [0018](adr/0018-backend-frontend-contracts.md) | PHP data objects → generated TS types | Proposed | +| [0019](adr/0019-search-behind-a-port.md) | Search port, MySQL first | Proposed (D-8) | +| [0020](adr/0020-platform-administration-in-filament.md) | Filament for staff; Vue for vendors and customers | Proposed | +| [0021](adr/0021-environments-demo-data-and-production-isolation.md) | Isolated environments; reproducible demo | Proposed | -Engineering standards that do **not** shape a domain, data-isolation, money, -runtime-dependency, or deployment boundary live in -[`../engineering/`](../engineering/), not in an ADR. +Engineering standards that do **not** shape a domain, data-isolation, money, runtime-dependency or deployment boundary live in [`../engineering/`](../engineering/), not in an ADR. diff --git a/docs/architecture/adr/0006-adr-process-v2.md b/docs/architecture/adr/0006-adr-process-v2.md new file mode 100644 index 0000000..0eb6abe --- /dev/null +++ b/docs/architecture/adr/0006-adr-process-v2.md @@ -0,0 +1,77 @@ +# ADR-0006: Adopt the Nexo 2.0 ADR template and status model + +- **Number:** 0006 +- **Status:** Accepted (settled by the Nexo 2.0 brief §4.3 and §18) +- **Date:** 2026-11-01 +- **Decision owner:** Project owner +- **Supersedes:** the template section of ADR-0001 (its "when to write one" rules stay in force) + +--- + +## Context + +ADR-0001 introduced ADRs with a four-section template: Context, Decision, Alternatives, Consequences. The Nexo 2.0 brief requires more fields: + +- problem; +- decision drivers; +- considered alternatives; +- positive and negative consequences; +- risks; +- testing implications; +- migration implications. + +It also requires the statuses Proposed, Accepted, Rejected, Deprecated and Superseded. + +Two template files currently exist: the one inside ADR-0001 and `ADR-TEMPLATE.md`. Filenames are inconsistent; `ADR-0005-vendor-naming.md` breaks the `NNNN-kebab-title.md` rule. + +## Problem + +Which template, statuses and location do Nexo 2.0 ADRs use? + +## Decision drivers + +- Compliance with the brief. +- One template, not two. +- Keep the existing repository convention, so no churn for its own sake. + +## Considered alternatives + +### A. Move ADRs to `docs/decisions/ADR-NNNN-*.md` (the brief's example layout) + +Rejected. The brief says to adapt to existing repository conventions. `docs/architecture/adr/` already holds ADR-0001 to ADR-0005, and moving them breaks links for no gain. + +### B. Keep the location; adopt the brief's fields in `ADR-TEMPLATE.md` (chosen) + +## Decision + +1. ADRs stay in `docs/architecture/adr/`, named `NNNN-short-kebab-title.md` and numbered sequentially. +2. `ADR-TEMPLATE.md` is the single template. It contains every field the brief requires. +3. Statuses are: Proposed, Accepted, Rejected, Deprecated, and Superseded by ADR-XXXX. +4. **Proposed ADRs are not implemented.** An ADR moves to Accepted only on owner approval, and the approval date is recorded in the status line. +5. After acceptance, only the status line changes. A changed decision needs a new ADR. +6. The ADR index in `docs/architecture/README.md` is updated in the same change as any ADR. + +## Positive consequences + +- Every significant decision records its testing and migration implications, which feed the Phase 3–5 test plans directly. + +## Negative consequences + +- Longer ADRs. This is mitigated by keeping one decision per ADR. + +## Risks + +- ADRs drift from the code. Mitigation: the definition of done requires ADR references in pull requests that touch a decided boundary. + +## Testing implications + +None directly. + +## Migration implications + +- ADR-0001 to ADR-0005 keep their original format; they are not rewritten. +- `ADR-0005-vendor-naming.md` should be renamed to `0005-vendor-naming.md` when ADR-0005 is accepted (owner action listed in the Phase 1 review). + +## Related + +- ADR-0001; the brief §4.3 and §18. diff --git a/docs/architecture/adr/0007-product-positioning-currency-and-locales.md b/docs/architecture/adr/0007-product-positioning-currency-and-locales.md new file mode 100644 index 0000000..1dafc12 --- /dev/null +++ b/docs/architecture/adr/0007-product-positioning-currency-and-locales.md @@ -0,0 +1,103 @@ +# ADR-0007: Position Nexo as a portfolio-grade general marketplace in MYR, English-primary + +- **Number:** 0007 +- **Status:** Accepted, by owner decisions D-4 and D-5 (2026-11-01) +- **Date:** 2026-11-01 +- **Decision owner:** Project owner +- **Supersedes:** the product framing in `docs/product/vision.md`, `scope.md`, `goals.md` and `personas.md` (ratified 2026-08-30), and `docs/architecture/marketplace-migration.md` + +--- + +## Context + +The existing product documents describe **aljebal-albeedos**: + +- a Sudan-market, Arabic-first marketplace; +- settlement in SDG; +- Stripe Connect transfers paying each vendor; +- a migration plan for an existing live SaaS database. + +The Nexo 2.0 brief describes something different: + +- **Nexo**, a premium multi-vendor general-merchandise marketplace; +- built as a portfolio showcase that must feel like a credible commercial product; +- on a fresh database, with no connection to the old production data. + +Phase 0 found (R2) that the Sudan + Stripe pairing was not viable as a real payment design. Stripe does not operate in Sudan, which is an assumption based on Stripe's published country list as of mid-2026. + +## Problem + +What product, market, currency and locale set do the Phase 1 specifications assume? + +## Decision drivers + +- Brief §2: the purpose is portfolio credibility for recruiters and engineers. +- A payment provider that genuinely supports the currency in test mode. +- A real RTL locale, to demonstrate internationalisation (brief §16). +- One currency, to keep the financial model provable. + +## Considered alternatives + +### A. Keep aljebal-albeedos, SDG, Arabic-primary + +Rejected (D-4). This contradicts the brief's purpose, and SDG has no Stripe support. + +### B. USD, English-primary + +This was a viable option. Owner chose MYR instead. + +### C. MYR, English-primary, with Arabic (RTL) and Malay as full peers (chosen) + +- Stripe supports MYR, including card payments in test mode. +- Malay is a natural second locale. +- Arabic demonstrates genuine RTL. + +### D. Multi-currency display + +Rejected. It needs an FX ADR and complicates the ledger and refunds, with no showcase benefit proportional to the cost. + +## Decision + +1. **Product:** Nexo, a single unified multi-vendor general-merchandise marketplace. It has three surfaces: customer storefront, vendor dashboard and platform administration. +2. **Settlement and display currency: MYR only.** + - Amounts are stored as integer sen (see ADR-0013). + - Every money column carries an explicit `currency` value, so a second currency later is an additive change. +3. **Locales:** + - `en` is primary and the fallback. + - `ar` (full RTL) and `ms` are full peers. Every UI string ships in all three before a feature is done. +4. **Prices are tax-inclusive.** Nexo v2 does not calculate, itemise or remit tax. + - This is a stated product limitation, not an oversight. + - A tax engine needs its own ADR. +5. **Market framing for demo content: Malaysia.** + - Fictional vendors and customers. + - Malaysian addresses and shipping zones: Peninsular, Sabah/Sarawak/Labuan. +6. The previous product documents stay in the repository marked **Superseded** for history. + +## Positive consequences + +- The payment design can be exercised end to end in Stripe test mode. +- One currency keeps allocation, rounding and reconciliation exact and testable. + +## Negative consequences + +- Arabic users see prices in MYR. This is acceptable for a showcase. +- No tax handling. This is visible to a knowledgeable reviewer, so it is stated in the README limitations. + +## Risks + +- Malaysian regulations (PDPA, SST registration) are out of scope. All demo data is fictional. The README must say Nexo is not a production service. + +## Testing implications + +- Locale coverage tests: every translation key exists in `en`, `ar` and `ms`. +- RTL visual checks in Phase 9. +- Money formatting tests per locale. + +## Migration implications + +- Product documents are superseded. New `product-requirements.md` and `functional-requirements.md` replace them. +- The REQ-VENDOR-* identifiers are carried into the new functional specification. + +## Related + +- ADR-0013 (money); `docs/product/product-requirements.md`; Phase 0 report §A.8. diff --git a/docs/architecture/adr/0008-repository-and-frontend-stack.md b/docs/architecture/adr/0008-repository-and-frontend-stack.md new file mode 100644 index 0000000..0f0aa0c --- /dev/null +++ b/docs/architecture/adr/0008-repository-and-frontend-stack.md @@ -0,0 +1,98 @@ +# ADR-0008: Build Nexo 2.0 in this repository with Vue 3, Inertia and TypeScript + +- **Number:** 0008 +- **Status:** Accepted, by owner decisions D-1 and D-2 (2026-11-01) +- **Date:** 2026-11-01 +- **Decision owner:** Project owner + +--- + +## Context + +Phase 0 found two candidate foundations. + +**The old repository `AdilAzhari/nexo-ecommerce`:** + +- Laravel 12, Vue 3, Inertia 2, Filament. +- Extensive, but with critical defects in payments, inventory and vendor authorisation. +- Its CI/CD is connected to a production database. + +**This repository `Sentients-AI/Nexo`:** + +- A clean Laravel 13 / PHP 8.5 shell: Pest 5, Larastan, Pint, arch tests and an engineering handbook. +- Branch `feat/vendor-frontend` (61 commits) holds a tested React 19 vendor workspace. +- `main` contains no frontend framework. + +The brief's technology baseline names Vue and Inertia. + +## Problem + +Which repository is the foundation, and which frontend framework does v2 use? + +## Decision drivers + +- A clean history and no inherited production coupling. +- Alignment with the brief's baseline. +- Reuse of the highest-quality existing work, where it does not compromise the above. + +## Considered alternatives + +### A. Continue in the old repository on an orphan branch + +Rejected (D-2). It inherits deploy pipelines wired to production and a confusing history. + +### B. Use this repository with React, reusing `feat/vendor-frontend` + +Rejected (D-1). The owner prefers the brief's Vue baseline. + +### C. Use this repository with Vue 3 + Inertia + TypeScript, keeping the React work as reference (chosen) + +## Decision + +1. `Sentients-AI/Nexo` is the Nexo 2.0 repository. The old repository is a read-only historical reference. +2. v2 starts from `main`, the Laravel 13 shell. `feat/vendor-frontend` is not merged. +3. The frontend is **Vue 3 (Composition API, `