---
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
