Skip to content

Phase 1 Spec: Master Data Init + Tenant Onboarding (Catalog-first)

0. Mục tiêu Phase 1

Mục tiêu

  1. màn quản trị Master Data để khởi tạo dữ liệu mặc định “full” (seed) cho hệ thống — dùng cho vận hành/dev/QA/khách hàng mới.

  2. luồng khởi tạo Tenant từ trạng thái “đã login nhưng chưa có tenant”:

    • User chọn Catalog Template (UI kiểu “thư viện” có phân loại nhóm)
    • Điền thông tin tenant cần thiết
    • Bấm tạo tenant → hệ thống provision tenant + binding user thành Tenant Admin
    • Hệ thống đưa user vào Workspace và cho phép switch tenant (token tenant-bound)

Không làm trong Phase 1 (để tránh loãng)

  • Không làm đầy đủ “taxonomy master data ngành nghề” (industry taxonomy) như MDM nâng cao (để Phase 2+).
  • Không làm “tùy biến behavior module theo BusinessType” sâu (state machine phức tạp, shipping rules phức tạp…) — Phase 1 chỉ cần khung enablement + default policy.
  • Không làm miniapp.

1. Khái niệm & Invariants (bắt buộc)

1.1 Auth/Tenant invariants

  • Login trả Identity Token: chỉ định danh user, không có tenantId.
  • Khi user chọn tenant (switch) → backend trả Tenant Token: có tenantId.
  • API tenant-scoped reject cứng nếu token không có tenantId.
  • Các API “tenant provisioning / create tenant / list templates” là tenantless (skip tenant check).

1.2 BusinessType invariants (đã chốt)

  • BusinessType = Business Model Profile (taxonomy TBD)

  • BusinessType quyết định:

    • Enablement: module bật/tắt
    • Behavior variants: policy theo module (shipping on/off, order lifecycle template, appointment enabled…)
  • BusinessType nằm trên Catalog/CatalogProfile:

    • Tenant chọn BusinessType (hoặc dùng default)
    • CatalogProfile phải phù hợp capability của BusinessType

1.3 Catalog vs CatalogProfile

  • Catalog: product schema/master (entity cốt lõi: Product, Category, Attribute, Variant…)
  • CatalogProfile: cấu hình “middle layer” gắn tenant với catalog template + rules/attribute sets/constraints.

2. Actor / RBAC (Phase 1)

Roles

  • SYSTEM_ADMIN: quản trị hệ thống, seed master data, quản lý templates.
  • ORG_ADMIN / PLATFORM_ADMIN (optional): có thể gộp SYSTEM_ADMIN trong Phase 1.
  • TENANT_CREATOR: được phép tạo tenant mới (mặc định: user nào login cũng tạo được, hoặc giới hạn bởi policy).
  • TENANT_ADMIN: quản trị tenant sau khi tạo.

Permissions (gợi ý Phase 1)

  • SYS_MD_INIT: init/reset master data
  • SYS_TEMPLATE_MANAGE: quản lý catalog templates / business type templates
  • TENANT_CREATE: tạo tenant
  • TENANT_VIEW, TENANT_MANAGE: quản trị tenant

Phase 1 có thể “đơn giản hoá”: SYSTEM_ADMIN full quyền, còn user thường chỉ có TENANT_CREATE nếu cho phép.


3. Data Model (Phase 1)

3.1 System Master Data Seed

SeedSet

  • id
  • code (e.g. FULL_DEFAULT)
  • name
  • version (semver hoặc integer)
  • description
  • status: DRAFT | ACTIVE | DEPRECATED
  • checksum (đảm bảo idempotent)
  • createdAt, updatedAt

SeedRun (audit vận hành)

  • id
  • seedSetCode, seedSetVersion
  • mode: DRY_RUN | APPLY
  • status: RUNNING | SUCCESS | FAILED
  • startedByUserId
  • stats:
  • logRef (link tới log chi tiết)
  • createdAt, finishedAt

Phase 1: đủ để vận hành và rollback logic dựa trên idempotency.


3.2 BusinessType (Business Model Profile)

BusinessTypeTemplate (system-defined)

  • id
  • code (e.g. STANDARD_RETAIL, SERVICE_APPOINTMENT, DIGITAL_GOODS)
  • name, description
  • version
  • capabilities:
    • modules: map { moduleKey: boolean }
    • policies: map { policyKey: string | number | boolean }
  • status: ACTIVE | DEPRECATED
  • createdAt, updatedAt

TenantBusinessProfile (tenant binding)

  • tenantId
  • activeTemplateId
  • effectiveCapabilities (optional snapshot)
  • overrides (optional; Phase 1 có thể khóa override = empty)
  • updatedAt

Phase 1 tối thiểu: chọn template + computed effective.


3.3 Catalog Template / CatalogProfile

CatalogTemplate (system-defined library item)

  • id
  • code
  • name
  • description
  • groupTags: string[] (để phân loại “thư viện”: Retail, F&B, Services, Pharmacy…)
  • preview:
  • defaultAttributeSets
  • defaultUnits, defaultTaxes (optional)
  • status: ACTIVE | HIDDEN
  • createdAt, updatedAt

CatalogProfile (tenant-level)

  • id
  • tenantId
  • catalogTemplateId
  • businessTypeTemplateId (derived from TenantBusinessProfile hoặc explicit)
  • attributePolicy (constraints theo business type)
  • createdAt, updatedAt

Phase 1 user “chắc chỉ cần chọn catalog” → BusinessType có thể default STANDARD cho tenant mới, hoặc CatalogTemplate có recommendedBusinessTypeCode.


3.4 Tenant & Provisioning

Tenant

  • id
  • name
  • slug (unique)
  • status: PROVISIONING | ACTIVE | SUSPENDED
  • timezone, locale, currency
  • ownerUserId
  • createdAt, updatedAt

TenantProvisionJob

  • id
  • tenantId
  • requestId (idempotency)
  • status: QUEUED | RUNNING | SUCCESS | FAILED
  • steps: list (seed catalog, create roles, bind user, init workspace…)
  • error (if failed)
  • createdAt, updatedAt

4. Backend API Contracts (Phase 1)

4.1 System Admin — Master Data Init

GET /admin/master-data/seed-sets

  • Auth: SYSTEM_ADMIN
  • Response: list SeedSet (code/version/status/description)

POST /admin/master-data/initialize

  • Auth: SYSTEM_ADMIN
  • Body:
    • seedSetCode: string (default FULL_DEFAULT)
    • mode: DRY_RUN | APPLY (default APPLY)
    • force: boolean (default false)
  • Behavior:
    • Idempotent theo (seedSetCode, version, checksum) trừ khi force=true
    • Tạo SeedRun
  • Response: seedRunId, status, stats (nếu dry-run) hoặc jobId

GET /admin/master-data/seed-runs/:id

  • Auth: SYSTEM_ADMIN
  • Response: SeedRun + trạng thái + logRef

Phase 1 không khuyến nghị endpoint “reset toàn bộ” trừ khi môi trường dev. Nếu cần, phải có confirm key + audit.


4.2 System Admin — Template Library (Catalog/BusinessType)

Catalog Template

  • GET /admin/catalog-templates
  • POST /admin/catalog-templates
  • PATCH /admin/catalog-templates/:id
  • (Optional) POST /admin/catalog-templates/:id/publish

BusinessType Template

  • GET /admin/business-types
  • POST /admin/business-types
  • PATCH /admin/business-types/:id
  • (Optional) POST /admin/business-types/:id/publish

Phase 1 có thể seed sẵn 3–5 templates tiêu chuẩn.


4.3 Tenant Onboarding (Tenantless)

GET /onboarding/catalog-templates

  • Auth: Authenticated (identity token)
  • Purpose: portal hiển thị “thư viện template”
  • Query:
    • q (search)
    • group (filter tag)
    • status=ACTIVE
  • Response: list CatalogTemplate (id, name, description, groupTags, preview)

POST /tenants

  • Auth: Authenticated (identity token) + permission TENANT_CREATE (policy)
  • Headers:
    • Idempotency-Key (bắt buộc) → tránh create trùng khi user double-click
  • Body:
    • tenant:
    • catalogTemplateId (required)
    • businessTypeTemplateId (optional, Phase 1 có thể auto)
  • Behavior:
    • Validate slug unique
    • Create Tenant status PROVISIONING
    • Create TenantBusinessProfile (default template)
    • Create CatalogProfile (bind template)
    • Enqueue TenantProvisionJob
    • Bind user → TENANT_ADMIN membership
  • Response: tenantId, jobId, status=PROVISIONING

GET /tenants/:tenantId/provisioning

  • Auth: identity token (owner) OR system admin
  • Response: job status + steps

POST /tenants/:tenantId/activate (optional)

  • Nếu provisioning async, activate khi job success.
  • Phase 1 có thể auto activate.

Phase 1 Progress Trackers

Backend

  • [x] PR-BE-03: Provision worker (Scheduled interval, stale lock reset, 6-state logic matching enum)
  • [x] PR-BE-04: API Rate limits (IP + Identity based) & Onboarding Flags (TENANT_CREATE_OPEN override mapped to UI /auth/me).

Frontend

  • [x] PR-FE-01: Portal Workspace (Idempotency Key headers, UI state mapping for GET /provisioning and tenant-context routing switch upon SUCCESS).
  • [ ] PR-FE-02: Wizard UI Refinement (4-step layout transition, strict form validation hookup, preview cards).

4.4 Auth helper endpoints (tenantless)

  • GET /auth/me (identity token): trả availableTenants + roles global + flags.
  • POST /auth/switch-tenant: nhận tenantId → trả tenant token.

5. Portal UX Spec (Phase 1)

5.1 Màn “Master Data Initialization” (System Admin)

Entry

  • Menu: System Admin → Master Data → Initialization

UI states

  • Status panel
    • Seed status: NOT_INITIALIZED | INITIALIZED (version) | OUTDATED
    • Last SeedRun (success/failed, time, by whom)
  • SeedSet list
    • FULL_DEFAULT là lựa chọn mặc định (full)
    • Có mô tả nội dung: units, currencies, payment methods, default roles, default templates…
  • Action
    • Button: Initialize (Full Default)
    • Toggle: Dry-run
    • Confirm modal: yêu cầu nhập “CONFIRM” + hiển thị cảnh báo môi trường
  • Progress
    • Hiển thị SeedRun status + stats, link xem log

Rules

  • Chỉ SYSTEM_ADMIN thấy màn này.
  • Apply seed là idempotent (tránh người bấm nhiều lần làm loạn).

5.2 Luồng “Create Tenant” (Tenantless onboarding)

Bối cảnh User đã login (identity token) nhưng chưa có tenant / hoặc muốn tạo tenant mới.

Entry points

  • /workspace hiển thị:
    • List tenants user có quyền truy cập
    • CTA: Create new tenant (nếu policy cho phép)

Wizard steps

  • Step 1 — Choose Catalog Template (Library UI)

    • UI giống “thư viện template”
    • Có: Search box, Filter theo groupTags (chips), Cards: cover + highlights + sample categories, Sort.
    • Selecting a template → next step
    • Empty state: “No template found”
  • Step 2 — Tenant Information

    • Form fields tối thiểu:
      • Tenant Name (required)
      • Slug (required, unique)
      • Timezone (default user locale)
      • Locale (vi-VN default)
      • Currency (VND default)
      • Contact, Address (optional)
    • Validation: slug regex + uniqueness check (async), name length
  • Step 3 — Review & Create

    • Summary: Catalog template selected, Tenant info, (BusinessType default: STANDARD) hiển thị read-only (Phase 1)
    • Button: Create
  • Step 4 — Provisioning Progress

    • Show job status: queued/running/success/failed, steps list
    • On success: CTA: Go to workspace + auto refresh tenants list

Behavior & routing rules

  • State A: Unauthenticated → redirect /login
  • State B: Authenticated but no active tenant: allowed /workspace, onboarding pages. module routes redirect /workspace.
  • State C: Active tenant selected: full module routes as permitted

6. Enforcement & Behavior: BusinessType (Phase 1)

6.1 Enablement

  • Khi tenant active, backend trả effectiveCapabilities (modules enabled).
  • Portal dùng nó để: hide menu module disabled, chặn route module disabled (show “Not enabled”).

6.2 Backend guard/policy check

  • Mỗi module entry service phải có assertModuleEnabled(moduleKey)
  • Nếu disabled: trả 403 FEATURE_DISABLED (hoặc 409) với message chuẩn.

7. Validation & Error Handling (chuẩn chung)

7.1 Error format (gợi ý)

json
{
  "code": "TENANT_SLUG_TAKEN",
  "message": "Tenant slug already exists",
  "details": { "field": "slug" },
  "traceId": "..."
}

7.2 Errors quan trọng Phase 1

  • TENANT_SLUG_TAKEN (409)
  • CATALOG_TEMPLATE_NOT_FOUND (404)
  • TENANT_CREATE_FORBIDDEN (403)
  • SEED_ALREADY_APPLIED (409) (trừ force)
  • SEED_RUN_FAILED (500)
  • PROVISIONING_FAILED (500/409)

8. Audit & Observability (vận hành thật)

  • Mọi action nhạy cảm (master data init/apply, create tenant, change business type)
  • Lưu audit: actorUserId, action, targetId, timestamp, diff summary
  • Provisioning job có logRef + steps metrics.

9. Test Plan (Phase 1)

Backend integration tests (P0)

  1. Create tenant idempotency: same Idempotency-Key → không tạo tenant thứ 2
  2. Create tenant validates slug unique
  3. Onboarding endpoints không cần tenant token
  4. Tenant-scoped endpoint reject nếu chỉ có identity token
  5. Switch tenant → token có tenantId → gọi tenant-scoped OK

Portal smoke tests

  1. Login → /workspace (tenant null)
  2. Create tenant wizard full flow
  3. Provisioning success → tenant xuất hiện → switch tenant
  4. Module routes bị chặn khi tenant null

FitZalo Platform Documentation