154 lines
5.9 KiB
Markdown
154 lines
5.9 KiB
Markdown
---
|
|
title: "Ford — Client Knowledge"
|
|
aliases: [ford, ford-motor]
|
|
tags: [client, ford, box, sftp, qc, automation]
|
|
sources: [01 Projects/ford_qc, 01 Projects/ford-gechub-sftp]
|
|
created: 2026-04-15
|
|
updated: 2026-04-29
|
|
---
|
|
|
|
> [!info] SSH Alias
|
|
> SSH into the Ford QC server using `box-cli` (→ 10.220.176.3). `box-cli-01` does NOT resolve.
|
|
|
|
# Ford
|
|
|
|
Oliver Agency works with Ford on asset pack automation — QC validation and delivery to Ford's GECHUB SFTP system.
|
|
|
|
## Key Takeaways
|
|
- Ford has **3 environments**: PROD, EDU, QA — each has separate Box folders and SFTP targets
|
|
- Asset packs are ZIP files — QC runs 13 checks before delivery
|
|
- Ford uses GECHUB as their SFTP-based delivery system
|
|
- Box JWT service account (`ford_box_config.json`) — never commit this file
|
|
- The Ford QC daemon runs as a **systemd service** on the production server
|
|
|
|
## Projects
|
|
| Project | Purpose | Entry Point |
|
|
|---------|---------|-------------|
|
|
| [[01 Projects/ford_qc/Ford QC System\|Ford QC System]] | QC validation of asset pack ZIPs | systemd or `python qc_engine.py` |
|
|
| [[01 Projects/ford-gechub-sftp/Ford SFTP Transfer\|Ford SFTP Transfer]] | Box → GECHUB SFTP transfer | `python main.py [--daemon]` |
|
|
|
|
## Environment Details
|
|
| Env | Purpose | Box Folder | SFTP Target |
|
|
|-----|---------|-----------|-------------|
|
|
| PROD | Production assets | Box/PROD | GECHUB PROD |
|
|
| EDU | Educational assets | Box/EDU | GECHUB EDU |
|
|
| QA | QA testing | Box/QA | GECHUB QA |
|
|
|
|
## Box Folder IDs (Ford QC)
|
|
| Folder | ID |
|
|
|--------|-----|
|
|
| Input hotfolder | 332861865120 |
|
|
| Reports output | 332864939558 |
|
|
| Archive | 332861653811 |
|
|
|
|
## Ford QC Checks (13 modules)
|
|
- Image resolution, format, file size
|
|
- Layer depth, colour existence
|
|
- Linking validation
|
|
- MEC/BAU compliance
|
|
- Powertrain validation
|
|
- Lifestyle inventory
|
|
- HTML report generation
|
|
|
|
## Tech Preferences
|
|
- Box API (JWT auth) — file exchange platform
|
|
- SFTP (GECHUB) — delivery system
|
|
- systemd for production daemons
|
|
- Email notifications via Mailgun
|
|
- QC profiles in JSON (configurable per asset type)
|
|
- HTML reports (not PDFs)
|
|
|
|
## Quirks & Lessons
|
|
- Ranger ptvl pattern must be configurable via QC profile — don't hardcode it (fix: 2026-03-16)
|
|
- Always archive processed ZIPs immediately — daemon reprocesses if not archived
|
|
- Ford has 3 completely separate environments — changes in PROD profiles don't affect EDU/QA
|
|
- GECHUB SFTP credentials differ per environment
|
|
|
|
## Ford QC Server Path Confusion
|
|
|
|
> [!warning] Always verify working directory before deploying
|
|
> The systemd service for Ford QC runs from `ford_qc_git_dev/ford_qc/` — NOT from `FORD_ASSET_PACK_QC` or `FORD_ASSET_PACK_QC_NEW` (legacy directory names that still exist on disk).
|
|
|
|
**SSH:** `box-cli` (→ 10.220.176.3). Do NOT use `box-cli-01` — it does not resolve.
|
|
|
|
**Service names:**
|
|
- Dev: `ford-qc-hotfolder.service`
|
|
- Production: `ford-qc-hotfolder-PROD.service`
|
|
|
|
**To find the real working directory before deploying:**
|
|
|
|
```bash
|
|
systemctl show ford-qc-hotfolder-PROD --property=ExecStart
|
|
# or
|
|
systemctl cat ford-qc-hotfolder-PROD
|
|
# WorkingDirectory=/home/box-cli/FORD_SCRIPTS/ford_qc_git_dev/ford_qc
|
|
```
|
|
|
|
Never assume the working directory from directory names alone. Always use `systemctl show` or `systemctl cat` to confirm.
|
|
|
|
**Known directories on the Ford QC server (do not confuse):**
|
|
|
|
| Directory | Status | Notes |
|
|
|-----------|--------|-------|
|
|
| `/home/box-cli/FORD_SCRIPTS/ford_qc_git_dev/ford_qc/` | **Active** | This is where the service runs |
|
|
| `/home/box-cli/FORD_SCRIPTS/FORD_ASSET_PACK_QC/` | Legacy | Old deployment, do not use |
|
|
| `/home/box-cli/FORD_SCRIPTS/FORD_ASSET_PACK_QC_NEW/` | Stale | Abandoned migration attempt |
|
|
|
|
**Git pull with local edits on server:**
|
|
|
|
```bash
|
|
git stash && git pull && git stash pop
|
|
```
|
|
|
|
**ford-gechub-sftp deploy path:** `/home/box-cli/FORD_SCRIPTS/ford-gechub-sftp` (different project)
|
|
|
|
## GPAS Zip Naming Convention
|
|
|
|
> [!important] Zip filename format changed
|
|
> Ford image packs must now end in `_GPAS.zip` — the old `_image.zip` suffix is no longer accepted.
|
|
|
|
This is enforced by `zip_filename_check.py`. Packs with incorrect suffixes fail QC immediately at the filename check stage. Update any scripts or templates that generate pack filenames.
|
|
|
|
| Old format | New format |
|
|
|-----------|-----------|
|
|
| `ford_pack_2026_image.zip` | `ford_pack_2026_GPAS.zip` |
|
|
|
|
## Ford BnP WERS Code Allowlist Pattern
|
|
|
|
When validating WERS (World Engineering Release System) codes in Ford Build-and-Price asset packs, use an **allowlist** of known prefixes rather than exclusion-based stripping.
|
|
|
|
**Shared code prefixes (always pass through QC):**
|
|
|
|
```python
|
|
shared_code_prefixes = ["abm", "acm", "vs-", "se#", "bs-", "dr-", "dga", "en-", "ca#"]
|
|
```
|
|
|
|
**Critical distinctions:**
|
|
|
|
- `TR-` = **transmission code**, NOT a trim code — do not strip it
|
|
- `ptvl` must equal `model[:3]` — the powertrain validation level must match the first 3 chars of the model code
|
|
- Pack type determines valid code combinations:
|
|
- **PV (Passenger Vehicle)** = `VS-` + `ACM` pair required
|
|
- **CV (Commercial Vehicle) non-Ranger** = `ABM-` only
|
|
- **CV Ranger** = `SE#` + `ABM` pair required
|
|
|
|
**Implementation pattern:**
|
|
|
|
```python
|
|
def is_valid_shared_code(code: str, shared_code_prefixes: list[str]) -> bool:
|
|
"""Allowlist-based WERS code validation — preferred over exclusion stripping."""
|
|
code_lower = code.lower()
|
|
return any(code_lower.startswith(prefix.lower()) for prefix in shared_code_prefixes)
|
|
|
|
def validate_pack(pack_codes: list[str], pack_type: str, model: str) -> list[str]:
|
|
errors = []
|
|
ptvl = next((c for c in pack_codes if c.lower().startswith("ptvl")), None)
|
|
if ptvl and ptvl[4:7].lower() != model[:3].lower():
|
|
errors.append(f"ptvl mismatch: {ptvl} vs model {model}")
|
|
# ... pack_type checks
|
|
return errors
|
|
```
|
|
|
|
## Related
|
|
- [[wiki/architecture/hotfolder-daemon|hotfolder-daemon]] — the daemon pattern
|
|
- [[wiki/tech-patterns/box-api-integration|box-api-integration]] — Box details
|