diff --git a/project-ideas/unigate/uniship/CarrierAccountManagement.md b/project-ideas/unigate/uniship/CarrierAccountManagement.md new file mode 100644 index 00000000..6170ea61 --- /dev/null +++ b/project-ideas/unigate/uniship/CarrierAccountManagement.md @@ -0,0 +1,115 @@ +# Unigate Setup Guide: Single Tenant with Multiple Carrier Accounts + +**The Previous Approach:** Creating a new "Tenant" in Unigate for every single facility strictly because each facility required its own carrier credentials. This inevitably creates hundreds of tenants, and it was very cumbersome to create config data and manage them. + +**The Solution:** Decouple the carrier credentials from the concept of a Tenant. +- A single logical Tenant represents the overarching business. +- A single generic `ShippingGatewayConfig` defines the carrier's API services. +- Numerous distinct `SystemMessageRemote` (SystemMessageRemote) records in Unigate hold the isolated credentials for each specific facility. +- Unigate links these via `ShippingGatewayAuth`. +- OMS natively stores the `systemMessageRemoteId` mapping at the facility level and injects it into the request payload. Unigate then seamlessly queries the precise auth record using the triad of `tenantId`, `shippingGatewayConfigId`, and `systemMessageRemoteId`. + +--- + +## Architecture Breakdown + +### 1. In Unigate +* **Tenant Setup:** The Tenant (`Party`, `Organization`, `UserAccount`, `UserLoginKey`) represents the oms-instance and acts as the integration user. +* **Carrier Config:** The `ShippingGatewayConfig` per carrier maps the integration Java services. +* **API Credentials:** Distinct `SystemMessageRemote` records store the unique Carrier API Keys for each facility. +* **Auth Mapping:** `ShippingGatewayAuth` records map the `Tenant` + `ShippingGatewayConfig` perfectly to its corresponding unique `SystemMessageRemote`. + +### 2. In OMS +* **Facility Configuration:** The `ShippingCarrierConfig` entity at the facility level natively points to: + 1. The `tenantId` + 2. The `shippingGatewayConfigId` + 3. **The Unigate `systemMessageRemoteId`** (The unique identifier representing this facility's credentials inside Unigate's SystemMessageRemote table). +* **Unigate Connection:** OMS maintains a `SystemMessageRemote` per Tenant. This SystemMessageRemote stores the Unigate instance URL and the single super-secret Login Key to talk to Unigate on behalf of all the stores for that Tenant. + +--- + +## Multi Account Use Case Example + +To illustrate this design, we will use a retail ecosystem (encompassing multiple brands across hundreds of facilities) as our primary example. For the purpose of this analogy, we have considered 150 fulfillment facilities/warehouses. + +- **Tenant Setup:** A single Tenant, `SMUS`, represents the entire company entity acting as the interface to OMS. +- **Carrier Config:** `FEDEX_CONFIG` maps the generic FedEx rate and label services for all 150 facilities. +- **API Credentials:** 150 different SystemMessageRemote records are created to hold specific credentials for Facility 1, Facility 2, etc. (e.g., `FEDEX_ACCOUNT_01`). +- **Auth Mapping:** 150 records link the `SMUS` tenant and its `FEDEX_CONFIG` to the 150 distinct facility SystemMessageRemote records. +- **Facility Configuration:** The facility configuration for Facility 1 in OMS natively points to `SMUS` (Tenant), `FEDEX_CONFIG` (Gateway), and `FEDEX_ACCOUNT_01` (SystemMessageRemote ID). +- **Unigate Connection:** OMS uses a single `UNIGATE_CONFIG` SystemMessageRemote holding the single super-secret key to connect to Unigate on behalf of all 150 stores. + +--- + +## Execution Flow +1. Facility `FACILITY_01` triggers a FedEx shipping label request in OMS. +2. OMS extracts `tenantId`, `shippingGatewayConfigId`, and `systemMessageRemoteId` from `ShippingCarrierConfig`. +3. OMS authenticates against the Unigate API using its stored Unigate URL and Login Key. +4. The label request payload securely carries the specific `tenantId`, `shippingGatewayConfigId`, and `systemMessageRemoteId`. +5. Unigate receives the payload and queries the `ShippingGatewayAuth` entity matching all three identifiers perfectly. +6. Unigate extracts the specific API credentials natively from the matched SystemMessageRemote, authenticates with the carrier, and returns the result. + +--- + +## Sample Data (XML Implementation) + +### Unigate Data Model +```xml + + + + + + + + + + + + + + + + + + + + + + + + +``` + +### OMS Data Model +```xml + + + + + + + + + + + + +``` diff --git a/project-ideas/unigate/uniship/entity/ShippingGatewayAuth.md b/project-ideas/unigate/uniship/entity/ShippingGatewayAuth.md new file mode 100644 index 00000000..f3ee3c11 --- /dev/null +++ b/project-ideas/unigate/uniship/entity/ShippingGatewayAuth.md @@ -0,0 +1,72 @@ +# Configure `ShippingGatewayAuth` + +## 1. Overview + +The `ShippingGatewayAuth` mapping record is the critical bridge connecting a tenant to a shipping carrier gateway and their private authentication credentials. + +This entity is **immutable**. To update any credential mapping, a **new record must be created**, and the previous mapping record should be **expired by setting its `thruDate`**. This ensures a complete history of configuration changes for audit and rollback purposes across all tenants. + +--- + +## 2. Purpose + +* Maps a specific tenant to a predefined shipping gateway (e.g., FedEx, USPS). +* Links to the raw credentials securely stored in Moqui's native `moqui.service.message.SystemMessageRemote`. +* Ensures traceability and historical accuracy by enforcing immutability natively via `fromDate` scaling. + +--- + +## 3. Entity: `ShippingGatewayAuth` + +| Field Name | Type | Required | Description | +| --------------------------- | -------- | -------- | ------------------------------------------------------------------------------------------ | +| systemMessageRemoteId | String | Yes | Primary key (Part 1). Links to the encrypted credentials. | +| shippingGatewayConfigId | String | Yes | Primary key (Part 2). Refers to the predefined shipping gateway type (e.g., FedEx). | +| tenantPartyId | String | Yes | Primary key (Part 3). Party ID of the specific tenant using this configuration. | +| fromDate | DateTime | Yes | Primary key (Part 4). Effective start date, enabling multiple historical records. | +| thruDate | DateTime | No | Expiry date, if any. | + +> **Note on Credentials:** Sensitive connection details like the API Key, Shared Secret, Username, and Password, alongside the actual connection URL are **never** stored in `ShippingGatewayAuth`. They are instead securely managed inside the linked `SystemMessageRemote` record. + +--- + +## 4. Setup Workflow + +### Step-by-Step Instructions + +1. **Tenant Manager Logs In** + A privileged user logs into the UniShip tenant manager interface. + +2. **Navigate to Shipping Gateway Setup Page** + Admin chooses to configure shipping gateway access for the tenant. + +3. **Provide Secure Credentials to SystemMessageRemote** + The system securely provisions a new `SystemMessageRemote` record, automatically encrypting the provided authentication tokens and URLs. + +4. **Choose Gateway Type** + Admin selects from predefined gateway options (sourced from the global `ShippingGatewayConfig` entity). + +5. **Create Immutable Mapping** + A new record is generated in the `ShippingGatewayAuth` entity scoped directly to the `tenantPartyId`, `shippingGatewayConfigId`, and the newly created `systemMessageRemoteId`. + +6. **Effective Dating** + The mapping is effective immediately via `fromDate`. + +7. **Update Handling** + If changes are needed later, a new `SystemMessageRemote` and `ShippingGatewayAuth` mapping is provisioned, and the old mapping's `thruDate` is populated. + +--- + +## 5. Security Considerations + +* Credential fields (e.g., `password`, `sharedSecret`) are natively encrypted at rest by Moqui inside `SystemMessageRemote`. +* The `ShippingGatewayAuth` table serves purely as a lookup router without ever exposing the sensitive string values directly. +* All backend API calls should filter entity queries using `conditionDate("fromDate", "thruDate", now)` to return only current/valid mappings and sort them descending by `fromDate`. + +--- + +## 6. Internal Entity Relationship + +* `tenantPartyId` → references the tenant Organization (`Party`) +* `shippingGatewayConfigId` → references the global definition for the carrier (`ShippingGatewayConfig`) +* `systemMessageRemoteId` → references the safe vault for credentials (`SystemMessageRemote`) diff --git a/project-ideas/unigate/uniship/entity/ShippingGatewayAuthConfig.md b/project-ideas/unigate/uniship/entity/ShippingGatewayAuthConfig.md deleted file mode 100644 index c87cff0a..00000000 --- a/project-ideas/unigate/uniship/entity/ShippingGatewayAuthConfig.md +++ /dev/null @@ -1,127 +0,0 @@ -# Configure `ShippingGatewayAuthConfig` - -## 1. Overview - -The `ShippingGatewayAuthConfig` record stores **tenant-specific authentication and endpoint information** for third-party shipping carriers such as FedEx, UPS, or ShipHawk. - -This entity is **immutable**. To update any credential or endpoint information, a **new record must be created**, and the previous record should be **expired by setting its \*\*\*\*`thruDate`**. This ensures a complete history of configuration changes for audit and rollback purposes. - ---- - -## 2. Purpose - -* Allows each tenant to configure one or more shipping gateways they intend to use. -* Enables the UniShip engine to route API requests to the appropriate gateway with tenant-specific credentials. -* Stores details such as authentication keys, mode (sandbox or production), and base URLs. -* Ensures traceability and historical accuracy by enforcing immutability. - ---- - -## 3. Entity: `ShippingGatewayAuthConfig` - -| Field Name | Type | Required | Description | -| --------------------------- | -------- | -------- | ---------------------------------------------------------------------------- | -| shippingGatewayAuthConfigId | String | Yes | Primary key. | -| tenantPartyId | String | Yes | Party ID of the tenant (a.k.a. tenantPartyId). | -| shippingGatewayConfigId | String | Yes | Refers to the predefined shipping gateway type (e.g., ShipHawk, FedEx, UPS). | -| modeEnumId | String | No | Enum for environment: Sandbox or Production. | -| authTypeEnumId | String | Yes | Enum that defines the type of authentication: API key, OAuth2, etc. | -| baseUrl | String | Yes | The base URL of the gateway endpoint for this tenant. | -| apiKey | String | Optional | API key or equivalent credential. | -| clientId | String | Optional | OAuth2 client ID (if applicable). | -| clientSecret | String | Optional | OAuth2 client secret (if applicable). | -| accessToken | String | Optional | OAuth2 access token (if managed manually). | -| fromDate | DateTime | Yes | Effective start date. | -| thruDate | DateTime | No | Expiry date, if any. | -| description | String | No | Optional metadata or remarks. | - ---- - -## 4. Setup Workflow - -### Step-by-Step Instructions - -1. **Tenant Manager Logs In** - A privileged user (tenant admin or UniShip support) logs into the UniShip tenant manager interface. - -2. **Navigate to Shipping Gateway Setup Page** - Admin chooses to configure shipping gateway access for the tenant. - -3. **Choose Gateway Type** - Select from predefined options like ShipHawk, FedEx, UPS. These options are sourced from the `ShippingGatewayConfig` master entity. - -4. **Enter Credentials** - Provide base URL, auth type, and relevant credentials (API key, OAuth2 credentials, etc.). - -5. **Save Configuration** - A record is created in the `ShippingGatewayAuthConfig` entity scoped to the `tenantPartyId`. - -6. **Effective Dating (Optional)** - Admin can provide a `fromDate` and optional `thruDate` to control when the configuration is active. - -7. **Update Handling** - If changes are needed later, a new configuration record is created with updated values and `fromDate`, while the old record's `thruDate` is set to expire it. - ---- - -## 5. Example Use Case - -A retailer (tenant) signs up and selects FedEx and ShipHawk for their shipments. The tenant admin configures: - -* **FedEx:** - - * `modeEnumId`: `Sandbox` - * `authTypeEnumId`: `ApiKey` - * `baseUrl`: `https://api-sandbox.fedex.com` - * `apiKey`: `abc123tenantfedexkey` - -* **ShipHawk:** - - * `modeEnumId`: `Production` - * `authTypeEnumId`: `ApiKey` - * `baseUrl`: `https://api.shiphawk.com` - * `apiKey`: `tenant-shiphawk-key` - -These values are stored securely in `ShippingGatewayAuthConfig` and used by the `get#OrderShippingRate` and `request#ShippingLabel` services. - ---- - -## 6. Security Considerations - -* Credential fields (e.g., `apiKey`, `clientSecret`) should be encrypted at rest using Moqui's field encryption capabilities. -* Access to view/edit credentials should be restricted via artifact authorization. -* Consider adding a service to rotate or deactivate credentials based on `thruDate`. - ---- - -## 7. Internal Entity Relationship - -* `tenantId` → references `Party` (Organization) -* `shippingGatewayConfigId` → references the predefined configuration for supported gateways -* Enum IDs (`modeEnumId`, `authTypeEnumId`) → map to values defined in `moqui.basic.Enumeration` - ---- - -## 8. Admin Tools & Future Enhancements - -* Admin UI for editing existing configurations -* Support for encrypted OAuth token refresh cycles (future) -* Multi-tenant validation tests (e.g., ping gateway) - ---- - -## 9. Related Entities - -| Entity Name | Purpose | -| ----------------------- | ------------------------------------------ | -| `Party` | Identifies the tenant | -| `ShippingGatewayConfig` | Identifies supported gateway integrations | -| `Enumeration` | Stores enum values like auth type and mode | - ---- - -## 10. Developer Tips - -* Use `conditionDate("fromDate", "thruDate", now)` in queries to ensure current configuration is valid. -* Cache sensitive fields minimally (`cache="false"` recommended). -* Never expose raw credentials via logs or API responses. diff --git a/project-ideas/unigate/uniship/entity/ShippingGatewayConfig.md b/project-ideas/unigate/uniship/entity/ShippingGatewayConfig.md index 438c4365..93f96ecb 100644 --- a/project-ideas/unigate/uniship/entity/ShippingGatewayConfig.md +++ b/project-ideas/unigate/uniship/entity/ShippingGatewayConfig.md @@ -4,35 +4,19 @@ 1. `ShippingGatewayConfig` - * Purpose: This entity serves as the central hub for configuring each shipping gateway you integrate with. This could be a third-party service like Shippo or EasyPost, or even a direct integration with a carrier's API (like FedEx or UPS). It stores the main settings and links to other entities for more detailed configurations. - * Key Fields: - * `shippingGatewayConfigId` (Primary Key): A unique identifier for this configuration. - * `shippingGatewayTypeEnumId`: Specifies the type of gateway being configured. - * Service Names (e.g., `getOrderRateServiceName`, `requestLabelsServiceName`): These fields store the names of Moqui services responsible for handling specific shipping operations with this gateway. These services would contain the logic to interact with the gateway's API (e.g., request shipping rates, generate labels, track shipments). + * **Purpose**: This entity serves as the global, tenant-agnostic central hub for configuring each shipping gateway integrated into the platform. This represents the API definition for a carrier (like FedEx or UPS) and defines the underlying software services used to process requests to that carrier. + * **Key Fields**: + * `shippingGatewayConfigId` (Primary Key): A unique identifier for this configuration (e.g., `FEDEX_GLOBAL`). + * Service Names (e.g., `getOrderRateServiceName`, `requestLabelsServiceName`): These fields store the names of the internal Moqui services responsible for handling specific shipping operations with this gateway. When UniShip routes a tenant's request for FedEx, it will invoke these specific service definitions. - Example (JSON): + **Example Representation (JSON):** ```json { - "shippingGatewayConfigId": "SHIPPO_DEMO", - "shippingGatewayTypeEnumId": "ShGtwyRemote", - "description": "Shippo API Demo", - "getOrderRateServiceName": "mantle.shippo.ShippoServices.get#OrderShippingRate", - "requestLabelsServiceName": "mantle.shippo.ShippoServices.request#ShippingLabels", - "getShippingRatesBulkName": "mantle.shippo.ShippoServices.get#ShippingRatesBulk", - "getAutoPackageInfoName": "", - "getRateServiceName": "mantle.shippo.ShippoServices.get#ShippingRate", - "refundLabelsServiceName": "mantle.shippo.ShippoServices.refund#ShippingLabels", - "trackLabelsServiceName": "mantle.shippo.ShippoServices.track#ShippingLabels", - "validateAddressServiceName": "mantle.shippo.ShippoServices.validate#PostalAddress" + "shippingGatewayConfigId": "FEDEX_GLOBAL", + "description": "FedEx REST API Integration", + "getOrderRateServiceName": "co.hotwax.unigate.UnigateServices.get#OrderShippingRate", + "requestLabelsServiceName": "co.hotwax.unigate.UnigateServices.request#ShippingLabels", + "refundLabelsServiceName": "co.hotwax.unigate.UnigateServices.refund#ShippingLabels" } ``` - -2. `ShippingGatewayOption` - - * Purpose: This entity allows you to store additional configuration options or parameters that are specific to a particular shipping gateway. These options might not fit into the other entities but are necessary for the gateway to function correctly. - * Key Fields: - * `shippingGatewayConfigId` (Part of Primary Key): The ID of the gateway configuration. - * `optionEnumId` (Part of Primary Key): An enumeration value that identifies the type of option being stored. - * `optionValue`: The value of the option. - diff --git a/project-ideas/unigate/uniship/readme.md b/project-ideas/unigate/uniship/readme.md index 624be33b..66a0fd86 100644 --- a/project-ideas/unigate/uniship/readme.md +++ b/project-ideas/unigate/uniship/readme.md @@ -38,8 +38,9 @@ Key entities: - **Party** — Represents both tenants (retailers) and shipping carriers. - **PartyRole** — Distinguishes between Tenant and Application user parties. -- **ShippingGatewayConfig** — Defines the configuration for each shipping gateway (e.g., FedEx, UPS). -- **ShippingGatewayAuthConfig** — Stores tenant-specific API credentials securely. +- **ShippingGatewayConfig** — Defines the global configuration for each shipping gateway (e.g., FedEx, UPS). +- **SystemMessageRemote** — Stores tenant-specific API credentials securely with native encryption. +- **ShippingGatewayAuth** — The immutable mapping entity linking tenants, gateway configs, and their credentials. 👉 Refer to the full [Entity Model Design](entity/entity-model.md) document for detailed definitions.