
A Photo Stamped After Sunset: Nine Deterministic Rules That Catch Impossible Recycling Claims
Inside ClaimGuard: capacity, mass balance, sun elevation and duplicate photo checks that flag what is physically impossible, stay silent on honest twilight shots, and treat missing data as missing, not guilty.
Rules that can be defended in a room
When a regulator, a brand or a recycler's lawyer asks "why was this claim flagged?", the answer needs to be a formula with numbers filled in and a cited source. That requirement produced ClaimGuard: nine deterministic rules, each with a severity, a published logic and a source for every limit.
Four outcomes, not two
Most checkers say pass or fail. Ours has four, because absence of data is a different thing from wrongdoing.
Outcome | Meaning |
|---|---|
PASS | Data present and consistent with the sourced limit. Shown in grey, never "verified" green. |
FLAG (HARD) | Physically impossible given the cited numbers. |
FLAG (SOFT) | Odd, but innocent explanations exist. |
INSUFFICIENT_EVIDENCE | Data or a sourced limit is missing. The UI says what would resolve it. |
INCONCLUSIVE | Data is present but the test cannot decide. |
We even planted a test claim, C-108, with no bills, no EXIF and zero custody coverage. The expected result is no flags and INSUFFICIENT_EVIDENCE. That test matters as much as any flag, because missing data is not fraud.
The nine rules
Rule | Question | Severity |
|---|---|---|
R1 Capacity | Could the plant physically process this much? | HARD |
R2 Mass balance | Does stock in and out add up, and is recovered metal plausible? | HARD |
R3 Energy | Is power use plausible for the tonnage? | SOFT only |
R4 Custody | Do recorded handovers support the claim? | HARD or SOFT |
R5 Photo light vs time | Does the picture's light match its time stamp? | HARD or SOFT |
R6 Duplicate photos | Was the same photo reused across batches? | SOFT |
R7 Documents | Do invoices match tonnage, dates and numbers? | HARD or SOFT |
R8 Weight drift | Does weight change oddly along the chain? | SOFT |
R9 Site activity | Does Sentinel-2 imagery show heat at the plant? | Review signal only |
R9 deserves a note. Satellite evidence is noisy, so it can only return PASS or INCONCLUSIVE, never a flag.
R1: capacity, and an arithmetic error in the guideline
R1 is the simplest rule and the most satisfying:
Plain text
processed_tonnes <= rated_t_per_hour * hours_per_day * operating_days
It also checks the annual licensed cap, and it compares against the lowest sourced capacity while showing every source.
While building the sourced limits we noticed something odd. CPCB's own guideline prints a worked example of "20 h x 4 t/h x 330 d = 46,200 t". The correct product is 26,400 t. We did not hide this. The dashboard has a "Show the CPCB erratum" toggle on the card, and our test claim C-102 (30,000 t claimed against a 26,400 t ceiling) triggers a HARD flag that displays it.
Boundaries are tested precisely: a claim equal to capacity passes, and capacity plus 0.001 t flags.
R2: does the metal add up?
Two checks. First, opening stock plus inputs minus outputs minus losses minus closing stock must not fall below a negative tolerance. Second, recovered metal must not exceed input times a maximum recoverable fraction. You cannot recover more lead than the batteries contained.
R4: custody coverage
Coverage is kilograms linked to recorded handovers divided by kilograms claimed. R4 flags intake with no upstream event, impossible event order, split or merge steps that do not conserve mass, and the same batch cited in two claims. For a double claim, the earlier
submitted_at wins and the later claim is flagged HARD.R5: the photo that argued with the sky
This is the rule that most directly mirrors the news story, and it is where careless engineering would hurt honest people.
Inputs are the photo time (from EXIF, with offset, or IST assumed and labelled), the location (EXIF GPS or the registered plant) and the image. Sun elevation is computed with the NOAA algorithm, with no AI involved. The light class comes from deterministic image statistics.
Sun elevation | Image shows | Result |
|---|---|---|
below -1 degrees | direct sun with hard shadows | FLAG HARD |
below -12 degrees | bright outdoor daylight sky | FLAG HARD |
-12 to -1 degrees | bright diffuse light | INCONCLUSIVE |
above +10 degrees | outdoor night scene | FLAG SOFT |
any | indoor or unclear | INCONCLUSIVE |
no time stamp | none | INSUFFICIENT_EVIDENCE |
Why the thresholds are so conservative
Twenty nine minutes after sunset in June at Hapur, the sun is only a few degrees below the horizon. The sky is still bright. Floodlights, haze and long twilight are all normal. A rule that flags every bright photo shortly after sunset would punish honest recyclers.
So R5 flags only what is impossible: hard sun shadows when the sun is below the horizon. We planted two test claims to prove it. C-105 has a photo at 20:22 IST on 16 June 2025 with hard shadows, which gives a HARD flag. C-105b has a photo at 19:48 IST with bright diffuse light, which must return INCONCLUSIVE.
Two more safeguards. If one device's photos are all offset by whole hours, we report a likely time zone error instead of a pile of flags. And because WhatsApp strips EXIF, photos sent over WhatsApp produce INSUFFICIENT_EVIDENCE, never a flag. R5 runs on in-app camera photos and files uploaded as documents.
R6: duplicate photos
An exact SHA-256 match catches reuse. A perceptual hash (dHash) with Hamming distance of 3 or less catches the photo that was re-encoded or lightly cropped. We test the re-encode case explicitly.
Three scores, never one
We resisted the dashboard instinct to boil everything into a single number. Instead:
Score | Question | Fed by |
|---|---|---|
Physical consistency | Do capacity, mass and energy add up? | R1, R2, R3 |
Traceability coverage | What share of claimed kg links to handovers? | R4 |
Evidence quality | Is the evidence one-sided, confirmed, supported or contradicted? | field statuses, R5, R6, R7 |
A recycler can have excellent physical consistency and poor traceability. Blending those into one score would hide exactly the information a reviewer needs.
Running it on AWS
A Step Functions workflow runs the four rule families (physical, custody, photos, documents) in parallel, then a join step computes the three scores and stores the run in DynamoDB. Evidence runs through Textract (
AnalyzeExpense for invoices, AnalyzeDocument for weigh slips), parsed into totals, dates and GSTINs and shown beside the source crop.Fairness features
- Right to respond. The recycler sees its own flags and can answer with evidence.
- Human in the loop. Reviewer actions (Accept, Request evidence, Escalate) are themselves ledger events.
- Soft wording. We say "inconsistent with data", never "fraudulent".
- A test that enforces sourcing. A unit test fails if any rule parameter has no entry in
data/sources.yaml.
Honest caveats
The rule engine passes its offline tests and the nine acceptance claims produce exactly the expected results, but the workflow has not yet run on AWS. The energy bands, the R6 threshold on real photos and the R9 heat threshold need calibration on real plant data. The photo light classifier has only been calibrated on synthetic images. Public rules can also be gamed, so we describe the output as triage for human reviewers, not certification.
Takeaways
- Design for four outcomes, so missing data never becomes guilt.
- Make every limit cite a source, and enforce it in a test.
- Choose thresholds that only flag the impossible.
- Keep scores separate so reviewers can see what is actually wrong.
- Plant your own test claims, including the boring clean ones.
Enjoyed reading this content? Let the author know!
Your likes, comments, shares, and saves help creators reach more builders.
Loading recommendations
Loading article