obsidian/wiki/client-knowledge/ford.md
2026-04-29 21:58:01 +01:00

5.9 KiB

title aliases tags sources created updated
Ford — Client Knowledge
ford
ford-motor
client
ford
box
sftp
qc
automation
01 Projects/ford_qc
01 Projects/ford-gechub-sftp
2026-04-15 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 QC validation of asset pack ZIPs systemd or python qc_engine.py
01 Projects/ford-gechub-sftp/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:

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:

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

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:

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