Custom profiles
Create trust profiles tailored to your exact requirements. Select specific checks, write custom expressions, and integrate with your existing systems.
Creating custom profiles
Start with the "custom" template (no checks enabled) and add exactly the checks you need:
from jpegtrust import create_profile, save_profile # Pick only the checks relevant to your workflow profile = create_profile( check_ids=["signature_chain", "pixel_hash", "copyright"], name="Content Licensing Policy", issuer="My Stock Photo Platform", ) save_profile(profile, "licensing.yml")
Writing custom expressions
Profile expressions use json-formula syntax to query the indicator metadata. You can write your own checks beyond the predefined ones by editing the YAML directly.
Expression syntax
Custom check example
Add a custom check to a generated profile by editing the YAML:
# Add after the generated checks in your profile YAML # declaration: the Trust Declaration made when the asset was created # manifests[0]: the active manifest (ISO/DIS 21617-1 A.4.1) - id: specific_camera_app description: "Image must come from our approved camera app" expression: > declaration.'claim.v2'.claim_generator_info[0].name == "Approved Camera v2" report_text: 'true': en: "Image captured with approved camera app" 'false': en: "Image was NOT captured with the approved camera app" - id: newcastle_location description: "Photo taken in Newcastle area" expression: > manifests[0].assertions.'cawg.metadata'.'photoshop:City' == "Newcastle upon Tyne" report_text: 'true': en: "Location confirmed: Newcastle area" 'false': en: "Location does not match Newcastle"
Extending with custom workflows
The jpegtrust package integrates into any Python workflow. Here are common patterns:
CI pipeline integration
# In your CI/CD pipeline script import sys from jpegtrust import batch_verify result = batch_verify("./uploads", "policy.yml") if result["summary"]["failed"] > 0: print("FAILED: Some images do not meet trust policy") sys.exit(1) print("All images passed trust verification")
Web API wrapper
# FastAPI example from fastapi import FastAPI, UploadFile from jpegtrust import extract_from_file, verify import tempfile app = FastAPI() @app.post("/verify") async def verify_upload(image: UploadFile): with tempfile.NamedTemporaryFile(suffix=".jpg") as tmp: tmp.write(await image.read()) tmp.flush() indicator = extract_from_file(tmp.name) if not indicator: return {"error": "No metadata found"} profile_yaml = open("policy.yml").read() report = verify(indicator, profile_yaml) return report.to_dict()
Automated ingest pipeline
import os from jpegtrust import extract_from_file, verify, load_profile profile_yaml = load_profile("newsroom.yml") watch_dir = "/incoming/photos" for fname in os.listdir(watch_dir): if not fname.endswith(".jpg"): continue path = os.path.join(watch_dir, fname) indicator = extract_from_file(path) if indicator is None: print(f"SKIP {fname}: no metadata") continue report = verify(indicator, profile_yaml) if report.status == "pass": os.rename(path, f"/approved/{fname}") else: os.rename(path, f"/review/{fname}") print(f"REVIEW {fname}: {report.verdict} ({report.score})")
Environment variables and configuration
The jpegtrust package is stateless -- all configuration is passed explicitly through function arguments and profile YAML files. This makes it easy to integrate into any environment without hidden state.
# Common pattern: load profile path from environment import os from jpegtrust import verify_image profile_path = os.environ.get("TRUST_PROFILE", "default_policy.yml") report = verify_image("photo.jpg", profile_path)