From a116325e1b94355a51b3c90fd8326ad31807b70e Mon Sep 17 00:00:00 2001 From: reemi01 Date: Thu, 10 Sep 2026 18:34:20 +0800 Subject: [PATCH 1/3] update vendor domain documentaion --- .../adr/ADR-0005-vendor-naming.md | 56 ++++++ docs/architecture/vendor-domain-design.md | 169 ++++++++++++++++++ .../platform/vendor-management.md | 43 +++++ .../product/requirements/vendor/onboarding.md | 43 +++++ docs/vendor-domain-design.md | 159 ++++++++++++++++ 5 files changed, 470 insertions(+) create mode 100644 docs/architecture/adr/ADR-0005-vendor-naming.md create mode 100644 docs/architecture/vendor-domain-design.md create mode 100644 docs/vendor-domain-design.md diff --git a/docs/architecture/adr/ADR-0005-vendor-naming.md b/docs/architecture/adr/ADR-0005-vendor-naming.md new file mode 100644 index 0000000..0274b0d --- /dev/null +++ b/docs/architecture/adr/ADR-0005-vendor-naming.md @@ -0,0 +1,56 @@ +# ADR-0005: Use Vendor as the Marketplace Seller Entity + +- Status: Proposed +- Date: 2026-09-10 + +## Context + +Nexo is being developed as a single multi-vendor marketplace for aljebal-albeedos. The marketplace contains independent sellers who share one storefront. + +ADR-0002 established the use of the existing `Tenant` model and terminology for the previous multi-tenant SaaS architecture. That decision was made in the context of an existing live SaaS database. + +The current Vendor domain is being established as part of the greenfield marketplace design. The marketplace concept is a seller, not an isolated tenant or storefront. + +## Decision + +The new marketplace domain will use explicit `Vendor` terminology for the seller entity. + +A Vendor has its own stable identity and lifecycle and exists independently of user accounts. Vendor-owned data will reference the Vendor explicitly where required. + +The design will use `Vendor` consistently in new marketplace domain concepts, documentation, relationships, and application code. + +## Why + +Using `Vendor` reflects the actual business meaning of the entity and makes the marketplace architecture easier to understand. + +Continuing to use `Tenant` would carry terminology from the retired multi-tenant SaaS model into the new marketplace model and could imply that each Vendor owns an isolated storefront. + +The greenfield design does not have the historical database constraint that originally motivated ADR-0002. + +## Consequences + +### Positive + +- The domain language matches the marketplace business model. +- Vendor ownership and isolation boundaries are explicit. +- New developers can distinguish Vendors from marketplace-wide shoppers and Platform Operators. +- The design avoids speculative multi-marketplace or multi-tenant abstractions. + +### Negative + +- Existing SaaS-era `Tenant` terminology may need to be removed or renamed where it is no longer applicable. +- Future migration work may require additional changes if existing SaaS structures are reused. + +## Alternatives Considered + +### Continue using Tenant + +Rejected because `Tenant` represents an isolated SaaS store, while the current product is one shared marketplace containing multiple Vendors. + +### Support both Tenant and Vendor + +Rejected because it would introduce unnecessary complexity and two concepts for the same marketplace seller boundary. + +## Scope + +This decision applies to the new Vendor domain design. It does not implement database migrations, onboarding, authorization, payments, or other Vendor functionality. \ No newline at end of file diff --git a/docs/architecture/vendor-domain-design.md b/docs/architecture/vendor-domain-design.md new file mode 100644 index 0000000..1c25b93 --- /dev/null +++ b/docs/architecture/vendor-domain-design.md @@ -0,0 +1,169 @@ +# Vendor Domain Design + +## 1. What is a Vendor? + +A Vendor is an independent seller operating within the aljebal-albeedos marketplace. A Vendor is a first-class domain entity with its own stable identity and lifecycle, independent of any user account. Vendor-team users may later belong to a Vendor, but the Vendor itself exists independently and represents the seller responsible for its own marketplace operations. + +The Vendor is treated as a marketplace seller rather than a user or storefront because aljebal-albeedos is a single shared marketplace where multiple independent vendors sell through one storefront. + +## 2. What Identifies a Vendor? + +A Vendor should have a stable internal primary key that uniquely identifies the vendor within the system. The primary key should be generated by the database and should not change during the Vendor's lifetime. + +In addition to the internal primary key, each Vendor should have a unique public slug. The slug provides a stable, human-readable identifier that can be used in URLs and other public-facing contexts. + +The Vendor name is the human-readable display name of the seller. It is not used as a unique identifier because different vendors may have similar or identical names. + +The proposed identity fields are: + +- `id` — stable primary key. +- `slug` — unique public identifier. +- `name` — human-readable Vendor name. + +The database should enforce uniqueness for the primary key and slug. + +## 3. What Information Must Not Live on Vendor? + +The Vendor entity should contain only information that defines the Vendor's identity, lifecycle, and core business status. Data belonging to other domains should not be stored directly on Vendor. + +The following information should not live on Vendor: + +- User accounts and authentication data — these belong to the user and authentication domain. +- Products — products belong to the product/catalog domain and are associated with a Vendor through an explicit relationship. +- Inventory quantities — inventory belongs to the inventory domain. +- Orders and order details — orders belong to the order domain. +- Payments, Stripe accounts, transfers, and commissions — these belong to the payment and marketplace financial domains. +- Customer information — customers are marketplace-wide identities and should not be owned by a single Vendor. +- Vendor-team roles and permissions — these belong to the authorization and user-management domain. + +Keeping these concerns outside Vendor prevents the entity from becoming a large container for unrelated data and keeps the domain boundaries clear. + +## 4. Vendor Lifecycle States and Transitions + +The Vendor lifecycle represents whether a Vendor is allowed to operate in the marketplace. + +### Proposed Lifecycle States + +| State | Meaning | +|---|---| +| `pending` | The Vendor exists but has not yet been approved by the Platform Operator. | +| `approved` | The Vendor has been approved and may operate in the marketplace, subject to other required conditions. | +| `suspended` | The Vendor remains in the system but is temporarily prevented from operating. | + +### Proposed Transitions + +| From | To | Triggered By | Meaning | +|---|---|---|---| +| `pending` | `approved` | Platform Operator | The Vendor has been reviewed and approved. | +| `approved` | `suspended` | Platform Operator | The Vendor is temporarily prevented from operating. | +| `suspended` | `approved` | Platform Operator | The suspension has been removed and the Vendor may operate again. | + +Invalid transitions must be rejected by the domain/application layer. The Vendor's current status must remain unchanged when an invalid transition is attempted. + +A Vendor should not be physically deleted as part of a normal lifecycle transition. Suspension preserves the Vendor's identity and historical relationships while preventing further operation. + +## 5. Who May Manage a Vendor? + +Vendor lifecycle management should be performed by the Platform Operator. The Platform Operator is responsible for approving and suspending Vendors. + +Vendor-team users belong to exactly one Vendor and may manage vendor-specific operational activities within their permitted scope, but they should not control the Vendor's platform-level lifecycle. + +Although authentication and authorization are outside the scope of this task, the design should establish an explicit application boundary for Vendor management. Later, authorization rules can enforce that only authorized Platform Operators can execute lifecycle-changing operations. + +This separation ensures that Vendor lifecycle changes are controlled by the marketplace platform rather than by individual Vendor users. + +## 6. Vendor Invariants + +The Vendor domain must preserve the following invariants: + +- **Stable identity:** A Vendor must have a stable primary identifier that does not change during its lifetime. +- **Unique public identifier:** Each Vendor must have a unique slug. +- **Valid lifecycle:** A Vendor must always have a valid lifecycle status. +- **Valid transitions:** Vendor status changes must follow the defined lifecycle transitions. Invalid transitions must be rejected. +- **Vendor isolation:** Vendor-owned data must remain associated with the correct Vendor and must not be accessible across Vendors without an explicit platform-level reason. +- **Ownership:** A Vendor is independent of user accounts. A Vendor may have vendor-team users associated with it, while a Platform Operator does not belong to any Vendor. +- **Operating ability:** A Vendor's ability to operate must be determined by its lifecycle status and other explicitly defined marketplace conditions, rather than by an unrelated field or assumption. + +## 7. Database Constraints vs Application/Domain Code + +Database constraints should enforce structural rules that must always be true, while application and domain code should enforce business rules and behavior. + +### Database Constraints + +The database should enforce: + +- Primary key uniqueness for `id`. +- Non-null constraints for required fields. +- Unique constraint for `slug`. +- Appropriate foreign key constraints when relationships to other entities are introduced. +- Valid data types for stored values. + +These constraints protect data integrity even if data is written through a different application path. + +### Application and Domain Code + +Application and domain code should enforce: + +- Valid Vendor lifecycle transitions. +- Who is allowed to perform lifecycle changes. +- Whether a Vendor is allowed to operate based on its current status. +- Business rules that require context or behavior rather than simple structural validation. + +For example, the database can ensure that a Vendor has a valid stored status value, while the domain layer should determine whether a transition from `suspended` to `approved` is permitted. + +Using both layers provides stronger protection: the database protects structural integrity, while the application and domain layers protect business behavior. + +## 8. Meaning of Suspended and Non-Active States + +A `suspended` Vendor remains a valid Vendor in the marketplace but is temporarily prevented from operating. Suspension does not remove the Vendor's identity or historical data. + +A `pending` Vendor has not yet been approved by the Platform Operator and therefore cannot operate as an approved seller. + +An `approved` Vendor is eligible to operate, subject to other marketplace conditions such as required payment onboarding. + +A `suspended` Vendor cannot perform normal seller operations such as selling products or receiving new marketplace orders. Existing historical data and records should remain available where required for auditability and order history. + +Operating ability should therefore be derived from the Vendor's lifecycle status and other explicitly defined marketplace conditions rather than from a separate `is_active` field. + +## 9. Proposed Vendor Schema + +The proposed Vendor schema contains only fields required for Vendor identity, lifecycle, and core platform management. + +| Column | Type | Null | Default | Unique | Index | Delete Behavior | Storage | +|---|---|---|---|---|---|---|---| +| `id` | BIGINT UNSIGNED | No | Auto-generated | Yes | Primary | N/A | Hard | +| `slug` | VARCHAR(255) | No | None | Yes | Yes | N/A | Hard | +| `name` | VARCHAR(255) | No | None | No | No | N/A | Hard | +| `status` | VARCHAR(50) | No | `pending` | No | Yes | N/A | Hard | +| `created_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Hard | +| `updated_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Hard | + +### Field Justification + +- `id` provides a stable internal identity for the Vendor. +- `slug` provides a unique, human-readable public identifier. +- `name` stores the Vendor's display name and does not need to be unique. +- `status` stores the Vendor's lifecycle state. The proposed default is `pending` so a newly created Vendor cannot operate before approval. +- `created_at` and `updated_at` provide standard record timestamps and support auditing of changes. + +The Vendor table should not use soft deletion as part of the initial lifecycle design. Vendor suspension is represented explicitly through `status`, allowing the Vendor and its historical relationships to remain identifiable. + +Relationships to products, orders, users, payments, and other domains should be introduced through their respective entities rather than adding unrelated fields to Vendor. + +Database constraints should enforce the primary key, required fields, and unique slug. Indexes should be added where they support lifecycle or public-identifier lookups. + +## 10. ADR Decision: Tenant Naming vs Vendor Naming + +The greenfield Nexo marketplace should use explicit `Vendor` terminology rather than continuing the `Tenant` naming from ADR-0002. + +ADR-0002 was created for an existing live SaaS database where the `tenants` table and `Tenant` model were already used across multiple models. That historical constraint does not apply to the greenfield marketplace domain. + +In aljebal-albeedos, the domain meaning is different. The system is a single marketplace with multiple independent sellers, so the correct business concept is a Vendor rather than a Tenant. + +Using explicit Vendor naming makes the domain model clearer and avoids carrying SaaS multi-tenancy terminology into a marketplace architecture. Vendor is also the explicit data-isolation and ownership boundary described by the current marketplace architecture. + +Therefore, the proposed design is to use `Vendor` consistently for the new marketplace domain, including the model, table, relationships, and documentation. + +### Proposed ADR + +This decision should be documented in a new ADR explaining the divergence from ADR-0002 and establishing `Vendor` as the marketplace domain terminology. \ No newline at end of file diff --git a/docs/product/requirements/platform/vendor-management.md b/docs/product/requirements/platform/vendor-management.md index e69de29..49d49e1 100644 --- a/docs/product/requirements/platform/vendor-management.md +++ b/docs/product/requirements/platform/vendor-management.md @@ -0,0 +1,43 @@ +# Platform Vendor Management Requirements + +## Draft Requirements + +### REQ-VENDOR-MGMT-001 — Vendor Visibility + +The system shall allow the Platform Operator to view Vendor records and their current lifecycle status. + +### REQ-VENDOR-MGMT-002 — Vendor Approval + +The system shall allow the Platform Operator to approve Vendors in the `pending` state. + +### REQ-VENDOR-MGMT-003 — Vendor Suspension + +The system shall allow the Platform Operator to suspend Vendors in the `approved` state. + +### REQ-VENDOR-MGMT-004 — Vendor Reactivation + +The system shall allow the Platform Operator to reactivate a suspended Vendor by returning it to the `approved` state. + +### REQ-VENDOR-MGMT-005 — Lifecycle Enforcement + +The system shall prevent Vendor lifecycle changes that are not defined by the approved Vendor lifecycle. + +### REQ-VENDOR-MGMT-006 — Vendor Identity Preservation + +The system shall preserve a Vendor's stable identity throughout its lifecycle, including while suspended. + +### REQ-VENDOR-MGMT-007 — Vendor Isolation + +The system shall maintain Vendor boundaries so that Vendor-owned data cannot be accessed or modified through another Vendor's context. + +### REQ-VENDOR-MGMT-008 — Operator Vendor Management + +The system shall provide a platform-level management boundary for Vendor lifecycle operations so that authorization can later restrict these operations to Platform Operators. + +### REQ-VENDOR-MGMT-009 — Auditability + +The system shall produce an auditable record for material Vendor lifecycle changes, including approval and suspension. + +### REQ-VENDOR-MGMT-010 — Vendor Operating Status + +The system shall determine whether a Vendor may operate from its lifecycle status and other explicitly defined marketplace conditions. \ No newline at end of file diff --git a/docs/product/requirements/vendor/onboarding.md b/docs/product/requirements/vendor/onboarding.md index e69de29..1ec9a16 100644 --- a/docs/product/requirements/vendor/onboarding.md +++ b/docs/product/requirements/vendor/onboarding.md @@ -0,0 +1,43 @@ +# Vendor Onboarding Requirements + +## Draft Requirements + +### REQ-VENDOR-001 — Vendor Application + +The system shall provide an application boundary through which a prospective Vendor can be created as a Vendor record. + +### REQ-VENDOR-002 — Vendor Identity + +The system shall assign each Vendor a stable unique internal identifier and a unique public slug. + +### REQ-VENDOR-003 — Vendor Pending State + +A newly created Vendor shall have a `pending` lifecycle status until approved by the Platform Operator. + +### REQ-VENDOR-004 — Vendor Approval + +The system shall allow the Platform Operator to approve a pending Vendor. + +### REQ-VENDOR-005 — Vendor Suspension + +The system shall allow the Platform Operator to suspend an approved Vendor when the Vendor must no longer operate in the marketplace. + +### REQ-VENDOR-006 — Vendor Reactivation + +The system shall allow a suspended Vendor to return to the approved state through an authorized Platform Operator action. + +### REQ-VENDOR-007 — Lifecycle Enforcement + +The system shall reject invalid Vendor lifecycle transitions and shall preserve the current Vendor status when an invalid transition is attempted. + +### REQ-VENDOR-008 — Vendor Operating Eligibility + +A Vendor shall not be considered eligible to operate while its lifecycle status is `pending` or `suspended`. + +### REQ-VENDOR-009 — Vendor Identity Preservation + +Suspending a Vendor shall not remove its identity or historical marketplace records. + +### REQ-VENDOR-010 — Marketplace Vendor Independence + +A Vendor shall exist independently of individual user accounts. Vendor-team users may later be associated with a Vendor, while Platform Operators shall not belong to a Vendor. diff --git a/docs/vendor-domain-design.md b/docs/vendor-domain-design.md new file mode 100644 index 0000000..d11cf57 --- /dev/null +++ b/docs/vendor-domain-design.md @@ -0,0 +1,159 @@ +# Vendor Domain Design +## 1. What is a Vendor? + +A Vendor is an independent seller operating within the aljebal-albeedos marketplace. A Vendor is a first-class domain entity with its own stable identity and lifecycle, independent of any user account. Vendor-team users may later belong to a Vendor, but the Vendor itself exists independently and represents the seller responsible for its own marketplace operations. + +The Vendor is treated as a marketplace seller rather than a user or storefront because aljebal-albeedos is a single shared marketplace where multiple independent vendors sell through one storefront. +## 2. What Identifies a Vendor? + +A Vendor should have a stable internal primary key that uniquely identifies the vendor within the system. The primary key should be generated by the database and should not change during the Vendor's lifetime. + +In addition to the internal primary key, each Vendor should have a unique public slug. The slug provides a stable, human-readable identifier that can be used in URLs and other public-facing contexts. + +The Vendor name is the human-readable display name of the seller. It is not used as a unique identifier because different vendors may have similar or identical names. + +The proposed identity fields are: + +- `id` — stable primary key. +- `slug` — unique public identifier. +- `name` — human-readable Vendor name. + +The database should enforce uniqueness for the primary key and slug. +## 3. What Information Must Not Live on Vendor? + +The Vendor entity should contain only information that defines the Vendor's identity, lifecycle, and core business status. Data belonging to other domains should not be stored directly on Vendor. + +The following information should not live on Vendor: + +- User accounts and authentication data — these belong to the user and authentication domain. +- Products — products belong to the product/catalog domain and are associated with a Vendor through an explicit relationship. +- Inventory quantities — inventory belongs to the inventory domain. +- Orders and order details — orders belong to the order domain. +- Payments, Stripe accounts, transfers, and commissions — these belong to the payment and marketplace financial domains. +- Customer information — customers are marketplace-wide identities and should not be owned by a single Vendor. +- Vendor-team roles and permissions — these belong to the authorization and user-management domain. + +Keeping these concerns outside Vendor prevents the entity from becoming a large container for unrelated data and keeps the domain boundaries clear. +## 4. Vendor Lifecycle States and Transitions + +The Vendor lifecycle represents whether a Vendor is allowed to operate in the marketplace. + +### Proposed Lifecycle States + +| State | Meaning | +|---|---| +| `pending` | The Vendor exists but has not yet been approved by the Platform Operator. | +| `approved` | The Vendor has been approved and may operate in the marketplace, subject to other required conditions. | +| `suspended` | The Vendor remains in the system but is temporarily prevented from operating. | + +### Proposed Transitions + +| From | To | Triggered By | Meaning | +|---|---|---|---| +| `pending` | `approved` | Platform Operator | The Vendor has been reviewed and approved. | +| `approved` | `suspended` | Platform Operator | The Vendor is temporarily prevented from operating. | +| `suspended` | `approved` | Platform Operator | The suspension has been removed and the Vendor may operate again. | + +Invalid transitions must be rejected by the domain/application layer. The Vendor's current status must remain unchanged when an invalid transition is attempted. + +A Vendor should not be physically deleted as part of a normal lifecycle transition. Suspension preserves the Vendor's identity and historical relationships while preventing further operation. +## 5. Who May Manage a Vendor? + +Vendor lifecycle management should be performed by the Platform Operator. The Platform Operator is responsible for approving and suspending Vendors. + +Vendor-team users belong to exactly one Vendor and may manage vendor-specific operational activities within their permitted scope, but they should not control the Vendor's platform-level lifecycle. + +Although authentication and authorization are outside the scope of this task, the design should establish an explicit application boundary for Vendor management. Later, authorization rules can enforce that only authorized Platform Operators can execute lifecycle-changing operations. + +This separation ensures that Vendor lifecycle changes are controlled by the marketplace platform rather than by individual Vendor users. +## 6. Vendor Invariants + +The Vendor domain must preserve the following invariants: + +- **Stable identity:** A Vendor must have a stable primary identifier that does not change during its lifetime. +- **Unique public identifier:** Each Vendor must have a unique slug. +- **Valid lifecycle:** A Vendor must always have a valid lifecycle status. +- **Valid transitions:** Vendor status changes must follow the defined lifecycle transitions. Invalid transitions must be rejected. +- **Vendor isolation:** Vendor-owned data must remain associated with the correct Vendor and must not be accessible across Vendors without an explicit platform-level reason. +- **Ownership:** A Vendor is independent of user accounts. A Vendor may have vendor-team users associated with it, while a Platform Operator does not belong to any Vendor. +- **Operating ability:** A Vendor's ability to operate must be determined by its lifecycle status and other explicitly defined marketplace conditions, rather than by an unrelated field or assumption. +## 7. Database Constraints vs Application/Domain Code + +Database constraints should enforce structural rules that must always be true, while application and domain code should enforce business rules and behavior. + +### Database Constraints + +The database should enforce: + +- Primary key uniqueness for `id`. +- Non-null constraints for required fields. +- Unique constraint for `slug`. +- Appropriate foreign key constraints when relationships to other entities are introduced. +- Valid data types for stored values. + +These constraints protect data integrity even if data is written through a different application path. + +### Application and Domain Code + +Application and domain code should enforce: + +- Valid Vendor lifecycle transitions. +- Who is allowed to perform lifecycle changes. +- Whether a Vendor is allowed to operate based on its current status. +- Business rules that require context or behavior rather than simple structural validation. + +For example, the database can ensure that a Vendor has a valid stored status value, while the domain layer should determine whether a transition from `suspended` to `approved` is permitted. + +Using both layers provides stronger protection: the database protects structural integrity, while the application and domain layers protect business behavior. +## 8. Meaning of Suspended and Non-Active States + +A `suspended` Vendor remains a valid Vendor in the marketplace but is temporarily prevented from operating. Suspension does not remove the Vendor's identity or historical data. + +A `pending` Vendor has not yet been approved by the Platform Operator and therefore cannot operate as an approved seller. + +An `approved` Vendor is eligible to operate, subject to other marketplace conditions such as required payment onboarding. + +A `suspended` Vendor cannot perform normal seller operations such as selling products or receiving new marketplace orders. Existing historical data and records should remain available where required for auditability and order history. + +Operating ability should therefore be derived from the Vendor's lifecycle status and other explicitly defined marketplace conditions rather than from a separate `is_active` field. +## 9. Proposed Vendor Schema + +The proposed Vendor schema contains only fields required for Vendor identity, lifecycle, and core platform management. + +| Column | Type | Null | Default | Unique | Index | Delete Behavior | Storage | +|---|---|---|---|---|---|---|---| +| `id` | BIGINT UNSIGNED | No | Auto-generated | Yes | Primary | N/A | Hard | +| `slug` | VARCHAR(255) | No | None | Yes | Yes | N/A | Hard | +| `name` | VARCHAR(255) | No | None | No | No | N/A | Hard | +| `status` | VARCHAR(50) | No | `pending` | No | Yes | N/A | Hard | +| `created_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Hard | +| `updated_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Hard | + +### Field Justification + +- `id` provides a stable internal identity for the Vendor. +- `slug` provides a unique, human-readable public identifier. +- `name` stores the Vendor's display name and does not need to be unique. +- `status` stores the Vendor's lifecycle state. The proposed default is `pending` so a newly created Vendor cannot operate before approval. +- `created_at` and `updated_at` provide standard record timestamps and support auditing of changes. + +The Vendor table should not use soft deletion as part of the initial lifecycle design. Vendor suspension is represented explicitly through `status`, allowing the Vendor and its historical relationships to remain identifiable. + +Relationships to products, orders, users, payments, and other domains should be introduced through their respective entities rather than adding unrelated fields to Vendor. + +Database constraints should enforce the primary key, required fields, and unique slug. Indexes should be added where they support lifecycle or public-identifier lookups. +## 10. ADR Decision: Tenant Naming vs Vendor Naming + +The greenfield Nexo marketplace should use explicit `Vendor` terminology rather than continuing the `Tenant` naming from ADR-0002. + +ADR-0002 was created for an existing live SaaS database where the `tenants` table and `Tenant` model were already used across multiple models. That historical constraint does not apply to the greenfield marketplace domain. + +In aljebal-albeedos, the domain meaning is different. The system is a single marketplace with multiple independent sellers, so the correct business concept is a Vendor rather than a Tenant. + +Using explicit Vendor naming makes the domain model clearer and avoids carrying SaaS multi-tenancy terminology into a marketplace architecture. Vendor is also the explicit data-isolation and ownership boundary described by the current marketplace architecture. + +Therefore, the proposed design is to use `Vendor` consistently for the new marketplace domain, including the model, table, relationships, and documentation. + +### Proposed ADR + +This decision should be documented in a new ADR explaining the divergence from ADR-0002 and establishing `Vendor` as the marketplace domain terminology. From 61ae1fe54ce402d3376c5fe07aade600916d4384 Mon Sep 17 00:00:00 2001 From: reemi01 Date: Sat, 12 Sep 2026 01:28:29 +0800 Subject: [PATCH 2/3] Refine vendor domain design based on review --- docs/architecture/vendor-domain-design.md | 117 +++++++++++------- .../product/requirements/vendor/onboarding.md | 10 +- 2 files changed, 78 insertions(+), 49 deletions(-) diff --git a/docs/architecture/vendor-domain-design.md b/docs/architecture/vendor-domain-design.md index 1c25b93..8811efd 100644 --- a/docs/architecture/vendor-domain-design.md +++ b/docs/architecture/vendor-domain-design.md @@ -10,18 +10,19 @@ The Vendor is treated as a marketplace seller rather than a user or storefront b A Vendor should have a stable internal primary key that uniquely identifies the vendor within the system. The primary key should be generated by the database and should not change during the Vendor's lifetime. -In addition to the internal primary key, each Vendor should have a unique public slug. The slug provides a stable, human-readable identifier that can be used in URLs and other public-facing contexts. +In addition to the internal primary key, each Vendor should have a unique public slug. The slug provides a human-readable identifier that can be used in URLs and other public-facing contexts. The slug should remain unchanged during the Vendor's normal lifecycle, including approval, suspension, and reactivation. Changes to the Vendor name should not require the slug to change. The Vendor name is the human-readable display name of the seller. It is not used as a unique identifier because different vendors may have similar or identical names. The proposed identity fields are: -- `id` — stable primary key. -- `slug` — unique public identifier. -- `name` — human-readable Vendor name. +* `id` — stable primary key. +* `slug` — unique public identifier that remains stable during the Vendor's normal lifecycle. +* `name` — human-readable Vendor name. The database should enforce uniqueness for the primary key and slug. + ## 3. What Information Must Not Live on Vendor? The Vendor entity should contain only information that defines the Vendor's identity, lifecycle, and core business status. Data belonging to other domains should not be stored directly on Vendor. @@ -40,37 +41,52 @@ Keeping these concerns outside Vendor prevents the entity from becoming a large ## 4. Vendor Lifecycle States and Transitions -The Vendor lifecycle represents whether a Vendor is allowed to operate in the marketplace. +The Vendor lifecycle represents the operational state of a Vendor after a Vendor record has been created. ### Proposed Lifecycle States -| State | Meaning | -|---|---| -| `pending` | The Vendor exists but has not yet been approved by the Platform Operator. | -| `approved` | The Vendor has been approved and may operate in the marketplace, subject to other required conditions. | -| `suspended` | The Vendor remains in the system but is temporarily prevented from operating. | +| State | Meaning | +| ----------- | ----------------------------------------------------------------------------------------------------------------------- | +| `pending` | The Vendor record exists but has not yet been approved by the Platform Operator. The Vendor is not eligible to operate. | +| `approved` | The Vendor has been approved and is eligible to operate, subject to other required marketplace conditions. | +| `suspended` | The Vendor remains in the system but is temporarily prevented from operating. | + +These three states are sufficient to represent the Vendor's operational lifecycle: + +* `pending` represents a Vendor that exists but has not yet received platform approval. +* `approved` represents a Vendor that has received approval and may operate when other required conditions are satisfied. +* `suspended` represents a previously approved Vendor that is temporarily prevented from operating. + +A rejected application is not represented as a separate Vendor lifecycle state. Rejection is an onboarding/application outcome rather than an operational state of an active Vendor. The application may be rejected without allowing the prospective seller to become an approved Vendor. If the marketplace later requires persistent application history, that outcome should be represented in the onboarding/application domain rather than adding another Vendor lifecycle state. ### Proposed Transitions -| From | To | Triggered By | Meaning | -|---|---|---|---| -| `pending` | `approved` | Platform Operator | The Vendor has been reviewed and approved. | -| `approved` | `suspended` | Platform Operator | The Vendor is temporarily prevented from operating. | -| `suspended` | `approved` | Platform Operator | The suspension has been removed and the Vendor may operate again. | +| From | To | Triggered By | Meaning | +| ----------- | ----------- | ----------------- | ----------------------------------------------------------------- | +| `pending` | `approved` | Platform Operator | The Vendor has been reviewed and approved. | +| `approved` | `suspended` | Platform Operator | The Vendor is temporarily prevented from operating. | +| `suspended` | `approved` | Platform Operator | The suspension has been removed and the Vendor may operate again. | Invalid transitions must be rejected by the domain/application layer. The Vendor's current status must remain unchanged when an invalid transition is attempted. A Vendor should not be physically deleted as part of a normal lifecycle transition. Suspension preserves the Vendor's identity and historical relationships while preventing further operation. + ## 5. Who May Manage a Vendor? +Vendor creation and lifecycle management should be controlled by the Platform Operator through the platform's Vendor management boundary. A prospective Vendor may submit an application, but submitting an application does not create a Vendor record directly. + +After reviewing the application, the Platform Operator may create a Vendor record through the controlled Vendor creation boundary. A newly created Vendor record has a `pending` status and must be approved before it becomes eligible to operate. If the application is rejected, no Vendor record is created. + + Vendor lifecycle management should be performed by the Platform Operator. The Platform Operator is responsible for approving and suspending Vendors. -Vendor-team users belong to exactly one Vendor and may manage vendor-specific operational activities within their permitted scope, but they should not control the Vendor's platform-level lifecycle. +Vendor-team users belong to exactly one Vendor and may manage vendor-specific operational activities within their permitted scope, but they should not create Vendors or control the Vendor's platform-level lifecycle. Although authentication and authorization are outside the scope of this task, the design should establish an explicit application boundary for Vendor management. Later, authorization rules can enforce that only authorized Platform Operators can execute lifecycle-changing operations. -This separation ensures that Vendor lifecycle changes are controlled by the marketplace platform rather than by individual Vendor users. +This separation ensures that Vendor creation and lifecycle changes are controlled by the marketplace platform rather than by individual Vendor users. + ## 6. Vendor Invariants @@ -82,7 +98,7 @@ The Vendor domain must preserve the following invariants: - **Valid transitions:** Vendor status changes must follow the defined lifecycle transitions. Invalid transitions must be rejected. - **Vendor isolation:** Vendor-owned data must remain associated with the correct Vendor and must not be accessible across Vendors without an explicit platform-level reason. - **Ownership:** A Vendor is independent of user accounts. A Vendor may have vendor-team users associated with it, while a Platform Operator does not belong to any Vendor. -- **Operating ability:** A Vendor's ability to operate must be determined by its lifecycle status and other explicitly defined marketplace conditions, rather than by an unrelated field or assumption. +- **Operating eligibility:** A Vendor with `pending` or `suspended` status is not eligible to operate. An `approved` status is required but is not necessarily sufficient for operation; any additional marketplace conditions required for operation must also be satisfied. ## 7. Database Constraints vs Application/Domain Code @@ -92,65 +108,72 @@ Database constraints should enforce structural rules that must always be true, w The database should enforce: -- Primary key uniqueness for `id`. -- Non-null constraints for required fields. -- Unique constraint for `slug`. -- Appropriate foreign key constraints when relationships to other entities are introduced. -- Valid data types for stored values. +* Primary key uniqueness for `id`. +* Non-null constraints for required fields. +* Unique constraint for `slug`. +* A constraint on `status` that permits only the defined lifecycle values: `pending`, `approved`, and `suspended`. +* Appropriate foreign key constraints when relationships to other entities are introduced. +* Valid data types for stored values. These constraints protect data integrity even if data is written through a different application path. +The database constraint on `status` prevents invalid lifecycle values from being stored. The exact database mechanism, such as a `CHECK` constraint or an equivalent database-supported constraint, may depend on the selected database technology. + ### Application and Domain Code Application and domain code should enforce: -- Valid Vendor lifecycle transitions. -- Who is allowed to perform lifecycle changes. -- Whether a Vendor is allowed to operate based on its current status. -- Business rules that require context or behavior rather than simple structural validation. +* Valid Vendor lifecycle transitions. +* Who is allowed to perform lifecycle changes. +* Whether a Vendor is allowed to operate based on its current status and other required marketplace conditions. +* Business rules that require context or behavior rather than simple structural validation. -For example, the database can ensure that a Vendor has a valid stored status value, while the domain layer should determine whether a transition from `suspended` to `approved` is permitted. +For example, the database can ensure that `status` contains only a defined lifecycle value, while the domain layer determines whether a transition from `suspended` to `approved` is permitted. Using both layers provides stronger protection: the database protects structural integrity, while the application and domain layers protect business behavior. + ## 8. Meaning of Suspended and Non-Active States A `suspended` Vendor remains a valid Vendor in the marketplace but is temporarily prevented from operating. Suspension does not remove the Vendor's identity or historical data. -A `pending` Vendor has not yet been approved by the Platform Operator and therefore cannot operate as an approved seller. +A `pending` Vendor has not yet been approved by the Platform Operator and is not eligible to operate. -An `approved` Vendor is eligible to operate, subject to other marketplace conditions such as required payment onboarding. +An `approved` Vendor is eligible to operate, subject to other explicitly required marketplace conditions such as payment onboarding. -A `suspended` Vendor cannot perform normal seller operations such as selling products or receiving new marketplace orders. Existing historical data and records should remain available where required for auditability and order history. +A `suspended` Vendor must not perform normal seller operations that would create new marketplace activity. This includes offering products for sale, accepting new marketplace orders, and other Vendor operations that require an operating Vendor status. Suspension does not prevent access to historical records that are required for order history, auditing, or platform administration. -Operating ability should therefore be derived from the Vendor's lifecycle status and other explicitly defined marketplace conditions rather than from a separate `is_active` field. +Operating eligibility should therefore be derived from the Vendor's lifecycle status and other explicitly defined marketplace conditions rather than from a separate `is_active` field. ## 9. Proposed Vendor Schema The proposed Vendor schema contains only fields required for Vendor identity, lifecycle, and core platform management. -| Column | Type | Null | Default | Unique | Index | Delete Behavior | Storage | -|---|---|---|---|---|---|---|---| -| `id` | BIGINT UNSIGNED | No | Auto-generated | Yes | Primary | N/A | Hard | -| `slug` | VARCHAR(255) | No | None | Yes | Yes | N/A | Hard | -| `name` | VARCHAR(255) | No | None | No | No | N/A | Hard | -| `status` | VARCHAR(50) | No | `pending` | No | Yes | N/A | Hard | -| `created_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Hard | -| `updated_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Hard | +| Column | Type | Null | Default | Unique | Index | Delete Behavior | Storage | +| ------------ | --------------- | ---- | ----------------- | ------ | ------- | --------------- | ---------- | +| `id` | BIGINT UNSIGNED | No | Auto-generated | Yes | Primary | N/A | Persistent | +| `slug` | VARCHAR(255) | No | None | Yes | Yes | N/A | Persistent | +| `name` | VARCHAR(255) | No | None | No | No | N/A | Persistent | +| `status` | VARCHAR(50) | No | `pending` | No | Yes | N/A | Persistent | +| `created_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Persistent | +| `updated_at` | TIMESTAMP | No | Current timestamp | No | No | N/A | Persistent | ### Field Justification -- `id` provides a stable internal identity for the Vendor. -- `slug` provides a unique, human-readable public identifier. -- `name` stores the Vendor's display name and does not need to be unique. -- `status` stores the Vendor's lifecycle state. The proposed default is `pending` so a newly created Vendor cannot operate before approval. -- `created_at` and `updated_at` provide standard record timestamps and support auditing of changes. +* `id` provides a stable internal identity for the Vendor. +* `slug` provides a unique, human-readable public identifier. +* `name` stores the Vendor's display name and does not need to be unique. +* `status` stores the Vendor's lifecycle state. The proposed default is `pending` so a newly created Vendor cannot operate before approval. +* `created_at` and `updated_at` provide standard record timestamps and support auditing of changes. + +The Vendor table should not use soft deletion as part of the initial lifecycle design. Vendor suspension is represented explicitly through `status`, rather than by deleting or hiding the Vendor record. -The Vendor table should not use soft deletion as part of the initial lifecycle design. Vendor suspension is represented explicitly through `status`, allowing the Vendor and its historical relationships to remain identifiable. +A Vendor should not be physically deleted as part of its normal lifecycle. If deletion is ever required for an administrative or legal reason, it must be treated as a separate data-management decision and must account for the Vendor's historical relationships and referential integrity. Deletion is therefore not a Vendor lifecycle transition. Relationships to products, orders, users, payments, and other domains should be introduced through their respective entities rather than adding unrelated fields to Vendor. -Database constraints should enforce the primary key, required fields, and unique slug. Indexes should be added where they support lifecycle or public-identifier lookups. +Database constraints should enforce the primary key, required fields, unique slug, and valid lifecycle status. Indexes should be added where they support lifecycle or public-identifier lookups. + ## 10. ADR Decision: Tenant Naming vs Vendor Naming diff --git a/docs/product/requirements/vendor/onboarding.md b/docs/product/requirements/vendor/onboarding.md index 1ec9a16..c7545aa 100644 --- a/docs/product/requirements/vendor/onboarding.md +++ b/docs/product/requirements/vendor/onboarding.md @@ -4,11 +4,17 @@ ### REQ-VENDOR-001 — Vendor Application -The system shall provide an application boundary through which a prospective Vendor can be created as a Vendor record. +The system shall provide an application boundary through which a prospective Vendor may submit an application for consideration by the Platform Operator. Submitting an application shall not directly create a Vendor record. A Vendor record shall only be created through the platform's controlled Vendor creation boundary after the application has been reviewed. + +### REQ-VENDOR-001A — Rejected Vendor Application + +The system shall allow the Platform Operator to reject a Vendor application without creating a Vendor record. A rejected application shall not result in a Vendor becoming eligible to operate. + ### REQ-VENDOR-002 — Vendor Identity -The system shall assign each Vendor a stable unique internal identifier and a unique public slug. +The system shall assign each Vendor a stable unique internal identifier and a unique public slug. The slug shall remain unchanged during the Vendor's normal lifecycle, including approval, suspension, and reactivation. + ### REQ-VENDOR-003 — Vendor Pending State From df90bfaf518f6bd686ae3c607a073edf5f04609a Mon Sep 17 00:00:00 2001 From: reemi01 Date: Wed, 23 Sep 2026 03:40:14 +0800 Subject: [PATCH 3/3] docs: clarify vendor creation and suspension behavior --- docs/architecture/vendor-domain-design.md | 36 ++++++++++++++++------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/docs/architecture/vendor-domain-design.md b/docs/architecture/vendor-domain-design.md index 8811efd..7c8288d 100644 --- a/docs/architecture/vendor-domain-design.md +++ b/docs/architecture/vendor-domain-design.md @@ -74,19 +74,21 @@ A Vendor should not be physically deleted as part of a normal lifecycle transiti ## 5. Who May Manage a Vendor? -Vendor creation and lifecycle management should be controlled by the Platform Operator through the platform's Vendor management boundary. A prospective Vendor may submit an application, but submitting an application does not create a Vendor record directly. +Vendor lifecycle management should be performed by the Platform Operator. The Platform Operator is responsible for reviewing Vendor applications, creating Vendor records, approving Vendors, and suspending Vendors. -After reviewing the application, the Platform Operator may create a Vendor record through the controlled Vendor creation boundary. A newly created Vendor record has a `pending` status and must be approved before it becomes eligible to operate. If the application is rejected, no Vendor record is created. +### Vendor Creation +A prospective seller submits an application before a Vendor record exists. Submitting an application does not directly create a Vendor record. -Vendor lifecycle management should be performed by the Platform Operator. The Platform Operator is responsible for approving and suspending Vendors. +The Platform Operator reviews the application. If the application is accepted, the Platform Operator explicitly creates the Vendor through the Vendor management boundary. -Vendor-team users belong to exactly one Vendor and may manage vendor-specific operational activities within their permitted scope, but they should not create Vendors or control the Vendor's platform-level lifecycle. +The `pending` state begins when the Vendor record is created. A newly created Vendor starts as `pending` and must then be explicitly approved through the defined lifecycle transition before it can operate. -Although authentication and authorization are outside the scope of this task, the design should establish an explicit application boundary for Vendor management. Later, authorization rules can enforce that only authorized Platform Operators can execute lifecycle-changing operations. +Vendor-team users belong to exactly one Vendor and may manage vendor-specific operational activities within their permitted scope, but they should not control the Vendor's platform-level lifecycle. -This separation ensures that Vendor creation and lifecycle changes are controlled by the marketplace platform rather than by individual Vendor users. +Although authentication and authorization are outside the scope of this task, the design should establish an explicit application boundary for Vendor management. Later, authorization rules can enforce that only authorized Platform Operators can execute lifecycle-changing operations. +This separation ensures that Vendor lifecycle changes are controlled by the marketplace platform rather than by individual Vendor users. ## 6. Vendor Invariants @@ -135,16 +137,28 @@ Using both layers provides stronger protection: the database protects structural ## 8. Meaning of Suspended and Non-Active States -A `suspended` Vendor remains a valid Vendor in the marketplace but is temporarily prevented from operating. Suspension does not remove the Vendor's identity or historical data. +A `suspended` Vendor remains a valid Vendor in the marketplace but is temporarily prevented from starting new marketplace activity. Suspension does not remove the Vendor's identity or historical data. + +A `pending` Vendor has not yet been approved by the Platform Operator and therefore cannot operate as an approved seller. + +An `approved` Vendor is eligible to operate, subject to other marketplace conditions such as required payment onboarding. -A `pending` Vendor has not yet been approved by the Platform Operator and is not eligible to operate. +### Suspended Vendor Permissions -An `approved` Vendor is eligible to operate, subject to other explicitly required marketplace conditions such as payment onboarding. +A suspended Vendor remains able to access historical information and complete existing operational obligations, but cannot perform new selling activities. -A `suspended` Vendor must not perform normal seller operations that would create new marketplace activity. This includes offering products for sale, accepting new marketplace orders, and other Vendor operations that require an operating Vendor status. Suspension does not prevent access to historical records that are required for order history, auditing, or platform administration. +| Action | Suspended Vendor | +|---|---| +| View historical orders | Allowed | +| Fulfill existing orders | Allowed | +| View historical earnings | Allowed | +| Edit existing products | Blocked | +| Create new products | Blocked | +| Receive new orders | Blocked | -Operating eligibility should therefore be derived from the Vendor's lifecycle status and other explicitly defined marketplace conditions rather than from a separate `is_active` field. +A suspended Vendor remains identifiable and its historical records are preserved. Suspension blocks new marketplace activity without removing existing historical data or obligations. +Operating ability should therefore be derived from the Vendor's lifecycle status and other explicitly defined marketplace conditions rather than from a separate `is_active` field. ## 9. Proposed Vendor Schema The proposed Vendor schema contains only fields required for Vendor identity, lifecycle, and core platform management.