@1aboveio/skills 0.20.2 → 0.20.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -5
- package/package.json +1 -1
- package/runtime/skills/distribution/generated/recipes.json +220 -25
- package/runtime/skills/distribution/scripts/bundles.mjs +49 -5
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -0
- package/runtime/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +1 -1
- package/skills/compliance/compliance-audit/LICENSE +3 -0
- package/skills/compliance/compliance-audit/SKILL.md +466 -0
- package/skills/compliance/compliance-audit/references/findings-schema.md +290 -0
- package/skills/compliance/compliance-audit/references/vars-checklist.md +1068 -0
- package/skills/compliance/compliance-audit/references/vars-findings-schema.md +395 -0
- package/skills/compliance/compliance-audit/scripts/reconcile_tracker.py +454 -0
- package/skills/compliance/compliance-audit/scripts/test_validate_tracker.py +90 -0
- package/skills/compliance/compliance-audit/scripts/validate_tracker.py +752 -0
- package/skills/compliance/doc-authenticity/LICENSE +3 -0
- package/skills/compliance/doc-authenticity/SKILL.md +158 -0
- package/skills/compliance/doc-authenticity/references/agreement.md +66 -0
- package/skills/compliance/doc-authenticity/references/bank-statement.md +150 -0
- package/skills/compliance/doc-authenticity/references/forensic-signals.md +157 -0
- package/skills/compliance/doc-authenticity/references/image-signals.md +114 -0
- package/skills/compliance/doc-authenticity/references/invoice.md +66 -0
- package/skills/compliance/doc-authenticity/references/issuer-profiles.md +86 -0
- package/skills/compliance/doc-authenticity/references/verdict-and-report.md +95 -0
- package/skills/compliance/doc-authenticity/references/verdict.schema.json +81 -0
- package/skills/compliance/doc-authenticity/scripts/image_forensics.py +294 -0
- package/skills/compliance/doc-authenticity/scripts/pdf_forensics.py +401 -0
- package/skills/compliance/doc-authenticity/scripts/validate_codes.py +224 -0
- package/skills/compliance/doc-authenticity/scripts/validate_verdict.py +308 -0
- package/skills/compliance/report-writing/LICENSE +3 -0
- package/skills/compliance/report-writing/SKILL.md +206 -0
- package/skills/compliance/report-writing/references/audit-report-template.md +121 -0
- package/skills/compliance/report-writing/references/external-assessment-template.md +167 -0
- package/skills/compliance/report-writing/references/management-report-template.md +145 -0
- package/skills/compliance/report-writing/references/vars-report-template.md +224 -0
- package/skills/document-utils/doc-to-md/LICENSE +3 -0
- package/skills/document-utils/doc-to-md/SKILL.md +77 -0
- package/skills/document-utils/doc-to-md/scripts/convert.py +157 -0
- package/skills/document-utils/reg-parser/LICENSE +3 -0
- package/skills/document-utils/reg-parser/SKILL.md +201 -0
- package/skills/document-utils/reg-parser/references/checklist-schema.md +223 -0
- package/skills/document-utils/reg-parser/references/checklists/hk-amlo-checklist.json +1306 -0
- package/skills/document-utils/reg-parser/references/checklists/hk-amlo-checklist.md +469 -0
- package/skills/document-utils/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.json +634 -0
- package/skills/document-utils/reg-parser/references/checklists/hk-fi-corporate-onboarding-cdd-checklist.md +233 -0
- package/skills/document-utils/reg-parser/references/checklists/hk-mso-guideline-checklist.json +2194 -0
- package/skills/document-utils/reg-parser/references/checklists/hk-mso-guideline-checklist.md +771 -0
- package/skills/document-utils/reg-parser/references/checklists/kyc-aml-checklist.md +258 -0
- package/skills/document-utils/reg-parser/references/checklists/visa-vars-checklist.md +1058 -0
- package/skills/document-utils/reg-parser/references/mandates/hk-amlo-cap615.md +389 -0
- package/skills/document-utils/reg-parser/references/mandates/visa-vars.md +205 -0
- package/skills/document-utils/reg-parser/scripts/compare_checklist.py +228 -0
- package/skills/document-utils/reg-parser/scripts/dump_checklist.py +348 -0
- package/skills/document-utils/reg-parser/scripts/preprocess-mandate.sh +171 -0
- package/skills/document-utils/reg-parser/scripts/test_quarantine.sh +102 -0
- package/skills/document-utils/reg-parser/scripts/validate_checklist.py +532 -0
- package/skills/document-utils/reg-parser/scripts/validate_mandate.py +242 -0
- package/skills/engineering/engineering-runtime/coherence/workflow.json +16 -16
- package/skills/engineering/engineering-runtime/scripts/workflow-coherence.mjs +4 -0
- package/skills/engineering/engineering-runtime/scripts/workflow-policy.mjs +1 -1
- package/skills/payment/similar-domain/LICENSE +3 -0
- package/skills/payment/similar-domain/SKILL.md +178 -0
- package/skills/payment/similar-domain/references/entities.md +58 -0
- package/skills/payment/similar-domain/references/fingerprints.md +82 -0
- package/skills/payment/similar-domain/references/pivots.md +66 -0
- package/skills/payment/similar-domain/references/report-template.md +76 -0
- package/skills/payment/similar-domain/references/scoring.md +61 -0
- package/skills/payment/similar-domain/references/terminology.md +37 -0
- package/skills/payment/similar-domain/references/workflow.md +79 -0
- package/skills/payment/tld-detection/SKILL.md +76 -21
- package/skills/payment/tld-detection/references/clean.md +1 -1
- package/skills/payment/tld-detection/references/clustering.md +21 -6
- package/skills/payment/tld-detection/references/decision.md +7 -2
- package/skills/payment/tld-detection/references/fx-conversion.md +229 -0
- package/skills/payment/tld-detection/references/report-template.md +63 -27
- package/skills/payment/tld-detection/references/streams.md +90 -0
- package/skills/payment/tld-detection/references/terminology.md +15 -7
- package/skills/payment/tld-detection/references/workflow.md +1 -1
- package/skills/payment/tld-detection/scripts/detect_streams.py +542 -0
- package/skills/engineering/ensure-coverage/evals/evals.json +0 -125
- package/skills/engineering/rush-issues/evals/evals.json +0 -65
- package/skills/engineering/rush-release/evals/evals.json +0 -58
- package/skills/fullstack/shadcn/evals/evals.json +0 -90
- package/skills/payment/fraud-analysis/evals/evals.json +0 -40
- package/skills/payment/tld-detection/evals/evals.json +0 -107
- package/skills/payment/tld-detection/tests/test_detect_ladders.py +0 -132
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: doc-authenticity
|
|
3
|
+
version: 0.4.0
|
|
4
|
+
description: "Screen PDF documents and raster images for fabrication, tampering, Photoshop or other image-editor use, and content validity. Detects file type, runs format-specific authenticity forensics, classifies bank statements, conversation logs, invoices, agreements, and other documents, then applies type-specific validity checks. Produces separate authenticity (NO_EVIDENCE_OF_MODIFICATION / SUSPICIOUS / LIKELY_MODIFIED / INCONCLUSIVE) and validity (VALID / INVALID / INCONCLUSIVE) verdicts. Use whenever a user asks whether a document, screenshot, scan, statement, invoice, contract, chat log, receipt, or payment evidence is genuine, original, edited, Photoshopped, manipulated, fake, or valid."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Document and Image Authenticity
|
|
8
|
+
|
|
9
|
+
Use this file as the workflow index. Load only the references required by the
|
|
10
|
+
detected file type and document type.
|
|
11
|
+
|
|
12
|
+
Authenticity and validity answer different questions:
|
|
13
|
+
|
|
14
|
+
- **Authenticity:** does the supplied file show evidence of modification,
|
|
15
|
+
compositing, or recreation after its claimed origin?
|
|
16
|
+
- **Validity:** are the document's material claims, identifiers, calculations,
|
|
17
|
+
parties, and required terms internally correct and externally supportable?
|
|
18
|
+
|
|
19
|
+
An edited file can remain valid, and a cleanly generated fake can be invalid
|
|
20
|
+
without retaining an edit trail. Always issue both verdict axes independently.
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
### 1. Determine file type
|
|
25
|
+
|
|
26
|
+
Inspect magic bytes and decode the file; do not trust its extension.
|
|
27
|
+
|
|
28
|
+
| `file_type` | Input | Action |
|
|
29
|
+
|---|---|---|
|
|
30
|
+
| `pdf` | Bytes begin with a valid PDF header and parse as PDF | Use the PDF authenticity branch |
|
|
31
|
+
| `image` | JPEG, PNG, WebP, TIFF, BMP, or another Pillow-decodable raster image | Use the image authenticity branch |
|
|
32
|
+
|
|
33
|
+
A PDF containing scanned page images is still `file_type: pdf`; F7 records that
|
|
34
|
+
its content is scanned or flattened. If the file is neither PDF nor a supported
|
|
35
|
+
raster image, stop and report that this skill does not support the format.
|
|
36
|
+
|
|
37
|
+
Record the MIME type, extension/magic agreement, file size, SHA-256, and supplied
|
|
38
|
+
claim in `verdict.json`. Default output to `./doc-authenticity-out/<file-stem>/`
|
|
39
|
+
in the current workspace; if unwritable, use another writable workspace and
|
|
40
|
+
disclose the path.
|
|
41
|
+
|
|
42
|
+
### 2. Detect authenticity by file type
|
|
43
|
+
|
|
44
|
+
#### PDF
|
|
45
|
+
|
|
46
|
+
Run:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv run {baseDir}/scripts/pdf_forensics.py <input.pdf> --out <outdir>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Read `references/forensic-signals.md`, inspect `forensics.json` and extracted
|
|
53
|
+
pages, then rate every PDF authenticity check F1-F9. Copy the script's media
|
|
54
|
+
type, byte size, SHA-256, and extension/magic result into `verdict.json`.
|
|
55
|
+
|
|
56
|
+
#### Image
|
|
57
|
+
|
|
58
|
+
Run:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
uv run {baseDir}/scripts/image_forensics.py <input-image> --out <outdir>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Read `references/image-signals.md`, inspect `image-forensics.json`, and inspect
|
|
65
|
+
`ela.png` for JPEG inputs. Rate every image authenticity check I1-I9. Copy the
|
|
66
|
+
script's media type, byte size, SHA-256, and extension/magic result into
|
|
67
|
+
`verdict.json`.
|
|
68
|
+
|
|
69
|
+
For both branches, metadata absence is NA, not PASS. An editor trace proves tool
|
|
70
|
+
contact, not deceptive editing. ELA or another pixel heuristic alone can produce
|
|
71
|
+
at most FLAG. A flattened or uniformly re-exported file can conceal prior edits.
|
|
72
|
+
Marker presence and PDF byte-range coverage are not cryptographic validation.
|
|
73
|
+
If encryption or corruption blocks extraction, keep the detected file type,
|
|
74
|
+
rate unavailable checks NA, and return an appropriately limited verdict.
|
|
75
|
+
|
|
76
|
+
### 3. Detect document type
|
|
77
|
+
|
|
78
|
+
Classify the visible content after extraction/OCR. File type and document type
|
|
79
|
+
are independent: an invoice can be either a PDF or an image.
|
|
80
|
+
|
|
81
|
+
| `doc_type` | Classification signals |
|
|
82
|
+
|---|---|
|
|
83
|
+
| `bank_statement` | Account holder and account identifiers, statement period, opening/closing balance, transaction ledger, bank issuer |
|
|
84
|
+
| `conversation_log` | Ordered messages or transcript entries with participants/senders and timestamps, including chat screenshots and exported chats |
|
|
85
|
+
| `invoice` | Supplier and customer, invoice number/date, line items, quantities/prices, tax, total, and payment terms/details |
|
|
86
|
+
| `agreement` | Named parties, operative terms/obligations, effective or execution date, governing provisions, and signature blocks |
|
|
87
|
+
| `other` | None of the above, or evidence is too incomplete to classify reliably |
|
|
88
|
+
|
|
89
|
+
Classify from document structure, not the filename or user's label. Quote the
|
|
90
|
+
observed fields that support the classification. If two types appear, choose the
|
|
91
|
+
type governing the material claim and note embedded secondary content in `detail`.
|
|
92
|
+
|
|
93
|
+
### 4. Run validity checks by document type
|
|
94
|
+
|
|
95
|
+
Only these document types have specialized validity profiles:
|
|
96
|
+
|
|
97
|
+
| `doc_type` | Required reference | Required checks |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `bank_statement` | `references/bank-statement.md` | C1-C5 and D1-D5 |
|
|
100
|
+
| `invoice` | `references/invoice.md` | N1-N8 |
|
|
101
|
+
| `agreement` | `references/agreement.md` | A1-A8 |
|
|
102
|
+
| `conversation_log` | None | No specialized validity checks; validity is INCONCLUSIVE |
|
|
103
|
+
| `other` | None | No specialized validity checks; validity is INCONCLUSIVE |
|
|
104
|
+
|
|
105
|
+
Run the validity profile regardless of whether the source is PDF or image. Use
|
|
106
|
+
OCR only when native text is unavailable and disclose OCR uncertainty. Verify
|
|
107
|
+
all arithmetic programmatically. Verify banks, tax identifiers, company status,
|
|
108
|
+
addresses, signatory authority, and governing-law facts against current primary
|
|
109
|
+
sources where available.
|
|
110
|
+
|
|
111
|
+
Conversation logs can still contribute evidence to another document's packet,
|
|
112
|
+
but this skill does not equate a visually coherent chat with a valid transaction
|
|
113
|
+
or valid counterparty. Their standalone validity remains INCONCLUSIVE unless a
|
|
114
|
+
future specialized profile is added.
|
|
115
|
+
|
|
116
|
+
### 5. Verdict and report
|
|
117
|
+
|
|
118
|
+
Read `references/verdict-and-report.md`. Apply its rubrics independently to:
|
|
119
|
+
|
|
120
|
+
- authenticity: `NO_EVIDENCE_OF_MODIFICATION | SUSPICIOUS | LIKELY_MODIFIED | INCONCLUSIVE`
|
|
121
|
+
- validity: `VALID | INVALID | INCONCLUSIVE`
|
|
122
|
+
- confidence per axis: `HIGH | MEDIUM | LOW`
|
|
123
|
+
- check result: `PASS | FLAG | FAIL | NA`
|
|
124
|
+
|
|
125
|
+
Write `report.md` and `verdict.json` conforming to
|
|
126
|
+
`references/verdict.schema.json` schema version 2.2. Include every required
|
|
127
|
+
check for the selected file/document route, including NA rows:
|
|
128
|
+
|
|
129
|
+
| Route | Required check IDs |
|
|
130
|
+
|---|---|
|
|
131
|
+
| PDF bank statement | F1-F9 + C1-C5 + D1-D5 |
|
|
132
|
+
| Image bank statement | I1-I9 + C1-C5 + D1-D5 |
|
|
133
|
+
| PDF invoice | F1-F9 + N1-N8 |
|
|
134
|
+
| Image invoice | I1-I9 + N1-N8 |
|
|
135
|
+
| PDF agreement | F1-F9 + A1-A8 |
|
|
136
|
+
| Image agreement | I1-I9 + A1-A8 |
|
|
137
|
+
| PDF conversation log / other | F1-F9 only |
|
|
138
|
+
| Image conversation log / other | I1-I9 only |
|
|
139
|
+
|
|
140
|
+
Validate before delivery:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
python3 {baseDir}/scripts/validate_verdict.py <outdir>/verdict.json
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Fix all errors and rerun until exit 0. For multiple files, produce one directory
|
|
147
|
+
per file plus `summary.md` listing file type, document type, both verdicts and
|
|
148
|
+
confidences, and decisive evidence.
|
|
149
|
+
|
|
150
|
+
## Operating rules
|
|
151
|
+
|
|
152
|
+
- Evidence must quote the observed value, row, field, marker, coordinate, or
|
|
153
|
+
external source result. “Looks fine” is not evidence.
|
|
154
|
+
- Every FLAG must name a plausible innocent explanation.
|
|
155
|
+
- Do not treat public bank or company details as proof of account ownership.
|
|
156
|
+
- Recommend source-side verification for high-stakes decisions.
|
|
157
|
+
- This skill is defensive. Refuse guidance on evading these checks or making an
|
|
158
|
+
altered artifact pass them, then continue with defensive analysis.
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Agreement Validity Checks (A1-A8)
|
|
2
|
+
|
|
3
|
+
Run all checks for a document classified as `agreement`. This is document and
|
|
4
|
+
counterparty validation, not legal advice or an enforceability opinion. Use
|
|
5
|
+
PASS, FLAG, FAIL, or NA and quote exact clauses, page numbers, names, and dates.
|
|
6
|
+
|
|
7
|
+
## A1 — Party identity and capacity
|
|
8
|
+
|
|
9
|
+
Verify each party's exact legal name, registration number, status, jurisdiction,
|
|
10
|
+
and registered address against current primary registries. Confirm the named
|
|
11
|
+
entity has capacity to enter the stated transaction. A nonexistent or mismatched
|
|
12
|
+
party is FAIL.
|
|
13
|
+
|
|
14
|
+
## A2 — Document identity, dates, and completeness
|
|
15
|
+
|
|
16
|
+
Check title, version, effective date, execution date, page numbering, headers,
|
|
17
|
+
footers, and whether all referenced schedules/exhibits are present. Impossible
|
|
18
|
+
chronology or missing material pages/schedules is FAIL; benign unsigned drafts or
|
|
19
|
+
pagination defects may be FLAG when clearly disclosed.
|
|
20
|
+
|
|
21
|
+
## A3 — Execution and signatures
|
|
22
|
+
|
|
23
|
+
Check signature blocks, names, roles, dates, witnesses, seals, and electronic
|
|
24
|
+
signature evidence. Verify digital signatures cryptographically when present.
|
|
25
|
+
An image of a signature is not proof of authorization. A broken signature or a
|
|
26
|
+
signature demonstrably attributed to the wrong person is FAIL.
|
|
27
|
+
|
|
28
|
+
## A4 — Material terms and internal consistency
|
|
29
|
+
|
|
30
|
+
Compare defined terms, subject matter, quantities, price, currency, payment
|
|
31
|
+
schedule, duration, renewal, termination, and liability provisions throughout
|
|
32
|
+
the agreement. Conflicting material values or undefined operative parties are
|
|
33
|
+
FAIL when not resolved by an order-of-precedence clause.
|
|
34
|
+
|
|
35
|
+
## A5 — Obligations, deliverables, and milestones
|
|
36
|
+
|
|
37
|
+
Confirm each material obligation has an accountable party, deliverable or
|
|
38
|
+
performance standard, timing, acceptance mechanism, and remedy where expected.
|
|
39
|
+
Ambiguity is generally FLAG; direct contradictions between obligations and
|
|
40
|
+
schedules are FAIL.
|
|
41
|
+
|
|
42
|
+
## A6 — Governing law and required provisions
|
|
43
|
+
|
|
44
|
+
Check governing law, jurisdiction/dispute mechanism, notices, assignment,
|
|
45
|
+
confidentiality/data protection, sanctions/compliance, and any transaction- or
|
|
46
|
+
jurisdiction-specific mandatory wording. Rate only against verified requirements;
|
|
47
|
+
use NA rather than inventing a legal requirement.
|
|
48
|
+
|
|
49
|
+
## A7 — Amendments, references, and precedence
|
|
50
|
+
|
|
51
|
+
Verify amendment numbers/dates, recitals, cross-references, annex labels,
|
|
52
|
+
incorporated documents, and order of precedence. Missing or circular references
|
|
53
|
+
that change obligations are FAIL; harmless numbering errors are FLAG.
|
|
54
|
+
|
|
55
|
+
## A8 — Authority and external corroboration
|
|
56
|
+
|
|
57
|
+
Verify signatory titles/authority through board resolution, power of attorney,
|
|
58
|
+
company records, trusted e-signature audit trail, or direct counterparty
|
|
59
|
+
confirmation. Rate NA when authority evidence is unavailable. Do not treat a
|
|
60
|
+
company logo, stamp image, or public contact details as proof of authority.
|
|
61
|
+
|
|
62
|
+
## Decisive validity evidence
|
|
63
|
+
|
|
64
|
+
A nonexistent party, invalid/broken signature, unauthorized signatory supported
|
|
65
|
+
by primary evidence, impossible execution chronology, missing operative schedule,
|
|
66
|
+
or irreconcilable material terms can independently support `INVALID`.
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
# Bank Statement — Content & Domain Checks (C1–C5, D1–D5)
|
|
2
|
+
|
|
3
|
+
Detailed procedure for the bank-statement-specific layers. Work from the
|
|
4
|
+
extracted text in `pages/*.txt`; quote row-level evidence.
|
|
5
|
+
|
|
6
|
+
## Content plausibility (C-checks)
|
|
7
|
+
|
|
8
|
+
### C1 — Balance arithmetic
|
|
9
|
+
|
|
10
|
+
The single highest-value check. Parse every transaction row into
|
|
11
|
+
(date, description, debit/credit amount, running balance) and verify:
|
|
12
|
+
|
|
13
|
+
1. `opening_balance ± each transaction = next running balance`, row by row.
|
|
14
|
+
2. `opening + sum(credits) − sum(debits) = closing`.
|
|
15
|
+
3. Any "money in / money out" summary box equals the transaction sums.
|
|
16
|
+
|
|
17
|
+
Do this in Python (a throwaway script is fine). Mind the parsing traps before
|
|
18
|
+
declaring a FAIL: negative amounts as `(123.45)` or `123.45 DR` / `CR`
|
|
19
|
+
suffixes; thousand separators and European decimal commas; multi-line
|
|
20
|
+
descriptions that split a row across text lines; statements that list newest
|
|
21
|
+
first (reconcile in reverse). A parsing artifact misread as a balance break is
|
|
22
|
+
the most damaging false positive this skill can make — when a row doesn't
|
|
23
|
+
reconcile, re-read the raw text around it before rating.
|
|
24
|
+
|
|
25
|
+
A genuine break — especially several rows suddenly offset by the same amount
|
|
26
|
+
(one edited transaction shifts every balance after it, and fabricators forget
|
|
27
|
+
to propagate) — is decisive FAIL evidence. Quote the first broken row, the
|
|
28
|
+
expected vs printed balance, and the offset.
|
|
29
|
+
|
|
30
|
+
### C2 — Date sequence
|
|
31
|
+
|
|
32
|
+
- Transactions in consistent chronological order (all ascending or all
|
|
33
|
+
descending), all inside the printed statement period.
|
|
34
|
+
- Statement period itself sane: start < end, matches the "statement date".
|
|
35
|
+
- Value dates vs posting dates: value date may trail/lead a bit; a value date
|
|
36
|
+
*months* away from its posting date is an anomaly.
|
|
37
|
+
- Feb 30ths, dates that don't exist, or a period that ends after the file's
|
|
38
|
+
CreationDate (cross-check F2) → FAIL.
|
|
39
|
+
- Weekend/holiday postings: card transactions post on weekends routinely;
|
|
40
|
+
BACS/ACH batch credits (salary) on a Sunday is odd but not impossible —
|
|
41
|
+
FLAG, don't FAIL, and only when it recurs.
|
|
42
|
+
|
|
43
|
+
### C3 — Transaction plausibility
|
|
44
|
+
|
|
45
|
+
- Exact-duplicate rows (same date, description, amount) — real duplicates
|
|
46
|
+
happen (two coffees), so look for *implausible* duplicates: identical
|
|
47
|
+
salary credits twice in a month, duplicated references.
|
|
48
|
+
- Round-number saturation: fabricated statements over-index on 100.00 /
|
|
49
|
+
500.00 / 1,000.00. Compute the share of round amounts; > ~40% of rows in a
|
|
50
|
+
personal account is anomalous.
|
|
51
|
+
- Description/amount coherence: "TESCO STORES" for 4,900.00, a salary line
|
|
52
|
+
labelled like a card purchase, references that don't match the described
|
|
53
|
+
counterparty format (e.g. faster-payment references, card scheme suffixes).
|
|
54
|
+
- Copy-paste artifacts: identical timestamps-in-reference across different
|
|
55
|
+
days, sequential references out of order.
|
|
56
|
+
|
|
57
|
+
### C4 — Internal cross-consistency
|
|
58
|
+
|
|
59
|
+
- "Page X of Y" matches actual page count and pages are all present.
|
|
60
|
+
- Account number/sort code/IBAN printed identically on every page.
|
|
61
|
+
- Customer name/address identical everywhere it appears (watch for one
|
|
62
|
+
respelled instance — a splice trace).
|
|
63
|
+
- Summary boxes (opening, closing, money in, money out) agree with C1's sums.
|
|
64
|
+
- Statement number / period continuity if the user supplied adjacent
|
|
65
|
+
statements: closing of month N = opening of month N+1.
|
|
66
|
+
|
|
67
|
+
### C5 — Formatting consistency
|
|
68
|
+
|
|
69
|
+
Fabricators editing one row rarely match the original formatting exactly:
|
|
70
|
+
|
|
71
|
+
- Decimal places uniform (no `1,234.5` among `1,234.50`).
|
|
72
|
+
- Thousand-separator style uniform; currency symbol placement uniform.
|
|
73
|
+
- One date in `01/02/2026` among `1 Feb 2026` rows.
|
|
74
|
+
- Column alignment in the raw extracted text: a value whose x-position drifts
|
|
75
|
+
from its column (the script emits word x-coordinates) suggests re-set text.
|
|
76
|
+
|
|
77
|
+
## Domain knowledge (D-checks)
|
|
78
|
+
|
|
79
|
+
### D1 — Account identifiers mechanically valid
|
|
80
|
+
|
|
81
|
+
Run `scripts/validate_codes.py` with everything extractable:
|
|
82
|
+
|
|
83
|
+
- **IBAN** — mod-97 checksum, length-per-country. An invalid checksum on a
|
|
84
|
+
printed IBAN is decisive FAIL (banks do not misprint IBANs).
|
|
85
|
+
- **US ABA routing number** — 9 digits, checksum `3(d1+d4+d7)+7(d2+d5+d8)+(d3+d6+d9) ≡ 0 (mod 10)`.
|
|
86
|
+
- **UK sort code** — format `XX-XX-XX`; the script checks format and known
|
|
87
|
+
leading-range → bank-group hints, not the private EISCD modulus tables.
|
|
88
|
+
Format-valid ≠ real; pair with D3.
|
|
89
|
+
- **Account number** — country format (UK 8 digits, etc.).
|
|
90
|
+
|
|
91
|
+
### D2 — SWIFT/BIC belongs to the named bank
|
|
92
|
+
|
|
93
|
+
- Format: 8 or 11 chars, `AAAA BB CC (DDD)` — bank code letters, ISO country
|
|
94
|
+
code, location code. Country letters must match the statement's country.
|
|
95
|
+
- The 4-letter bank code should correspond to the claimed bank (BARC→Barclays,
|
|
96
|
+
HSBC/MIDL→HSBC, LOYD→Lloyds, NWBK→NatWest, ABBY→Santander UK, CHAS→JPMorgan
|
|
97
|
+
Chase, BOFA→Bank of America, CITI→Citi, DEUT→Deutsche, BNPA→BNP…). Verify
|
|
98
|
+
by web search when available; otherwise rate from knowledge and say so.
|
|
99
|
+
- A BIC whose country code contradicts the branch address → FAIL.
|
|
100
|
+
|
|
101
|
+
### D3 — Bank / branch / address consistency
|
|
102
|
+
|
|
103
|
+
- UK sort-code leading pairs map to bank groups (e.g. 20–29 Barclays [20s],
|
|
104
|
+
40–49 HSBC/first direct, 30–39 Lloyds group, 07/08 Nationwide/co-ops,
|
|
105
|
+
04 challengers/fintechs — Monzo 04-00-04, Starling 60-83-71 under NatWest
|
|
106
|
+
ranges…). A sort code from bank A on bank B's letterhead → FAIL. Web-search
|
|
107
|
+
the exact sort code when possible.
|
|
108
|
+
- Postcode/ZIP format valid for the country; branch address city consistent
|
|
109
|
+
with the branch name.
|
|
110
|
+
- Contact details: phone country code, domain of any printed email/URL
|
|
111
|
+
belongs to the bank (statement footer URLs on lookalike domains → FAIL).
|
|
112
|
+
|
|
113
|
+
### D4 — Template & branding match the claimed bank
|
|
114
|
+
|
|
115
|
+
- Regulatory footer text expected per jurisdiction: UK statements carry
|
|
116
|
+
FSCS protection wording and "Authorised by the PRA / regulated by the FCA
|
|
117
|
+
and PRA" + registration number; US statements carry Member FDIC / Equal
|
|
118
|
+
Housing Lender; EU statements name the local deposit-guarantee scheme. Its
|
|
119
|
+
*absence* on a full statement is a FLAG; a *wrong* registration number is a
|
|
120
|
+
FAIL (verify the FCA/FDIC number by search when available).
|
|
121
|
+
- Layout matches the bank's known statement style where you know it (column
|
|
122
|
+
order, summary-box placement, typography). Check `issuer-profiles.md` for
|
|
123
|
+
the issuer's typography and its evidence grade — Verified rows can support
|
|
124
|
+
a FAIL; knowledge-grade rows support at most a FLAG (brand font ≠ statement
|
|
125
|
+
font). Rate only what you actually know; "I don't know this bank's
|
|
126
|
+
template" → NA, not PASS.
|
|
127
|
+
- Producer tooling vs bank expectations (ties back to F1): e.g. big
|
|
128
|
+
retail banks emit composition-platform or server-library producers; a
|
|
129
|
+
boutique layout claiming a tier-1 bank with a Word producer contradicts D4
|
|
130
|
+
and F1 together.
|
|
131
|
+
|
|
132
|
+
### D5 — Address plausibility
|
|
133
|
+
|
|
134
|
+
- Customer address: real-format street/city/postcode for the country;
|
|
135
|
+
consistent across pages and with the user-supplied KYC context (if the
|
|
136
|
+
packet's proof-of-address disagrees with the statement, flag it for the
|
|
137
|
+
analyst — that's a packet-level finding, not necessarily forgery).
|
|
138
|
+
- Geocode-sanity by knowledge/search: postcode district matches the city
|
|
139
|
+
(e.g. an "M1" postcode in London → FAIL-grade inconsistency).
|
|
140
|
+
|
|
141
|
+
## Scoring reminders (bank statements specifically)
|
|
142
|
+
|
|
143
|
+
- C1 multi-row breaks and D1 checksum failures are decisive validity FAILs;
|
|
144
|
+
F6 splices on amounts are decisive authenticity FAILs. Together they support
|
|
145
|
+
`LIKELY_MODIFIED` authenticity and `INVALID` validity.
|
|
146
|
+
- A statement that is a clean scan (F-layer NA) but reconciles perfectly and
|
|
147
|
+
has valid, mutually consistent identifiers has authenticity INCONCLUSIVE and
|
|
148
|
+
may have validity VALID. A scan can still depict a fabricated original.
|
|
149
|
+
- When the user names the expected bank, D3/D4 disagreements weigh more; when
|
|
150
|
+
they don't, an unknown template is NA.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Forensic Signals — Interpretation Guide (F1–F9)
|
|
2
|
+
|
|
3
|
+
How to read `forensics.json` and rate each F-check. The recurring theme:
|
|
4
|
+
distinguish **evidence of tampering** (FAIL) from **evidence of an untidy but
|
|
5
|
+
innocent document journey** (FLAG) from **no signal** (NA).
|
|
6
|
+
|
|
7
|
+
## F1 — Producer / Creator tool
|
|
8
|
+
|
|
9
|
+
`metadata.producer` and `metadata.creator` name the software that generated
|
|
10
|
+
the PDF. Banks generate statements with **document-composition platforms**;
|
|
11
|
+
fabricators use **desktop editors and web tools**.
|
|
12
|
+
|
|
13
|
+
**Consistent with a bank (PASS):**
|
|
14
|
+
- Quadient / Inspire, OpenText Exstream, HP Exstream, Smart Communications /
|
|
15
|
+
SmartCOMM, Messagepoint, Papyrus (ISIS), StreamServe / OpenText StreamServe,
|
|
16
|
+
Xenos, Elixir, Crawford Technologies
|
|
17
|
+
- Big-bank in-house stacks often show generic library names: iText, Apache
|
|
18
|
+
FOP, PDFBox, Aspose, BIRT, JasperReports, Eclipse BIRT, XSL-FO processors
|
|
19
|
+
(AntennaHouse, RenderX XEP), wkhtmltopdf / headless Chromium ("Skia/PDF")
|
|
20
|
+
— these are server-side generation traces and are normal.
|
|
21
|
+
|
|
22
|
+
**Editor-associated (FLAG, often FAIL with corroboration):**
|
|
23
|
+
- iLovePDF, Smallpdf, Sejda, PDFescape, pdfFiller, DocHub, SodaPDF, PDF24
|
|
24
|
+
- Adobe Acrobat (as *Producer* on a re-save; banks don't hand-edit statements
|
|
25
|
+
in Acrobat), Foxit PhantomPDF / PDF Editor, PDF-XChange Editor, Nitro
|
|
26
|
+
- Canva, Photoshop, Illustrator, GIMP — image tools have no business
|
|
27
|
+
producing a bank statement
|
|
28
|
+
- Word / LibreOffice / Google Docs ("Microsoft® Word", "Writer", "Skia/PDF
|
|
29
|
+
m… Google Docs renderer") — someone authored this as a document
|
|
30
|
+
|
|
31
|
+
**Ambiguous (FLAG with innocent explanation, or NA):**
|
|
32
|
+
- "Microsoft: Print To PDF", macOS Quartz PDFContext, browser "Save as PDF" —
|
|
33
|
+
the classic customer flow: opened online banking, printed to PDF. The
|
|
34
|
+
original bank metadata is destroyed, not forged. Lean FLAG + note; push the
|
|
35
|
+
weight onto C/D checks.
|
|
36
|
+
- Scanner strings (ScanSnap, Epson Scan, "TWAIN") — see F7; usually NA here.
|
|
37
|
+
|
|
38
|
+
Rate FAIL only when the editor trace is corroborated (e.g. editor producer
|
|
39
|
+
**and** incremental updates **and** a font splice), or when the claimed bank's
|
|
40
|
+
statements are reliably known to carry different tooling (see the bank notes
|
|
41
|
+
in `bank-statement.md`).
|
|
42
|
+
|
|
43
|
+
## F2 — Creation vs modification timestamps
|
|
44
|
+
|
|
45
|
+
`metadata.creation_date` vs `metadata.mod_date`.
|
|
46
|
+
|
|
47
|
+
- Equal or mod within seconds of creation → PASS (single-pass generation).
|
|
48
|
+
- ModDate later than CreationDate → someone re-saved it. FLAG, innocent
|
|
49
|
+
explanations abound (mail clients, previewers, print-to-PDF chains).
|
|
50
|
+
- **ModDate earlier than CreationDate, impossible dates, or dates after the
|
|
51
|
+
statement was supposedly issued but before it covers** → strong anomaly;
|
|
52
|
+
FAIL when corroborated.
|
|
53
|
+
- Timezone offsets wildly inconsistent with the bank's country → FLAG.
|
|
54
|
+
- Statement period ends *after* the file's CreationDate → the file predates
|
|
55
|
+
the data it reports. FAIL. (Check against the period parsed in C2.)
|
|
56
|
+
|
|
57
|
+
## F3 — Incremental updates
|
|
58
|
+
|
|
59
|
+
`structure.eof_count`, `structure.xref_sections`, `structure.prev_pointers`.
|
|
60
|
+
A PDF saved incrementally appends a new body + xref; the count of `%%EOF`
|
|
61
|
+
markers approximates the number of save generations.
|
|
62
|
+
|
|
63
|
+
- 1 EOF → single generation. PASS.
|
|
64
|
+
- 2+ EOFs → the file was modified after creation. What matters is **what
|
|
65
|
+
changed**: `structure.updated_objects` lists object numbers that appear in
|
|
66
|
+
more than one generation. Content-stream or font objects updated → the
|
|
67
|
+
visible page was altered → FAIL. Only metadata/annotation objects → FLAG
|
|
68
|
+
(e.g. a viewer stamped it opened).
|
|
69
|
+
- Note: a digital-signature workflow legitimately adds a generation (that's
|
|
70
|
+
how signing works). Cross-check F8 before rating.
|
|
71
|
+
|
|
72
|
+
## F4 — XMP metadata consistency
|
|
73
|
+
|
|
74
|
+
`xmp` block: `xmp_toolkit`, `history`, `derived_from`, and agreement with
|
|
75
|
+
docinfo.
|
|
76
|
+
|
|
77
|
+
- XMP history events (`saved` entries with softwareAgent) narrate the edit
|
|
78
|
+
chain — an entry with an editor agent after creation corroborates F1/F3.
|
|
79
|
+
- `derived_from` naming another document → this file was built from a source
|
|
80
|
+
file. FLAG→FAIL depending on what the source appears to be.
|
|
81
|
+
- Docinfo says one producer, XMP says another → the metadata was partially
|
|
82
|
+
scrubbed or spoofed. FLAG, FAIL with corroboration.
|
|
83
|
+
- Absent XMP entirely: common in minimal server-side generators. NA, not
|
|
84
|
+
suspicious on its own.
|
|
85
|
+
|
|
86
|
+
## F5 — Font inventory
|
|
87
|
+
|
|
88
|
+
`fonts` array: name, subset prefix (6 letters + `+`), embedded flag, per page.
|
|
89
|
+
|
|
90
|
+
- Bank statements are typographically boring: 1–3 families, consistently
|
|
91
|
+
subset-embedded. PASS.
|
|
92
|
+
- A family appearing **twice with different subset prefixes** (e.g.
|
|
93
|
+
`ABCDEF+Helvetica` and `GHIJKL+Helvetica`) means two tools embedded that
|
|
94
|
+
font — classic edit trace. FAIL with corroboration, FLAG alone.
|
|
95
|
+
- Non-embedded standard-14 fonts (plain `Helvetica`, `Arial`) mixed with
|
|
96
|
+
embedded subsets → text added by a lightweight editor. FLAG→FAIL.
|
|
97
|
+
- A font present on exactly one page that otherwise matches the others'
|
|
98
|
+
typography → localized edit. Investigate with F6.
|
|
99
|
+
|
|
100
|
+
## F6 — In-line font splice
|
|
101
|
+
|
|
102
|
+
`text_fonts` in the per-page extraction: font name and size per word. The
|
|
103
|
+
smoking gun is a **single value rendered in a different font/size than its
|
|
104
|
+
row** — a pasted-over balance or name.
|
|
105
|
+
|
|
106
|
+
- Compare each transaction row's amount/balance cells to the column's modal
|
|
107
|
+
font. One cell differing in font name, or in size by >0.3pt, while the rest
|
|
108
|
+
of the column is uniform → FAIL, and quote the exact row and fonts.
|
|
109
|
+
- Whole-column or whole-block differences (headers vs body, bold totals) are
|
|
110
|
+
design, not splices. PASS.
|
|
111
|
+
- Kerning/width anomalies aren't extracted by the script; if the user supplies
|
|
112
|
+
a rendered image and something looks visually off, say so as a FLAG with a
|
|
113
|
+
note that pixel-level analysis wasn't performed.
|
|
114
|
+
|
|
115
|
+
## F7 — Text layer type
|
|
116
|
+
|
|
117
|
+
`pages[].char_count`, `pages[].image_coverage`.
|
|
118
|
+
|
|
119
|
+
- Native text, low image coverage → full forensic surface. PASS (as a check,
|
|
120
|
+
this "passes" when the layer is native — it's about signal availability).
|
|
121
|
+
- Full-page image, no/synthetic text (OCR layer) → scan or flattened export.
|
|
122
|
+
Most F-checks and F6 go NA. **This alone must not drive the verdict
|
|
123
|
+
negative** — it drives it toward INCONCLUSIVE unless C/D find substance.
|
|
124
|
+
- Hybrid: native text pages plus one image-only page in the same statement →
|
|
125
|
+
FLAG; why would page 2 of a digital statement be a picture?
|
|
126
|
+
|
|
127
|
+
## F8 — Digital signatures
|
|
128
|
+
|
|
129
|
+
`signatures` block: presence, field name, and whether byte ranges structurally
|
|
130
|
+
cover the file. The bundled script does not verify the signature value,
|
|
131
|
+
certificate chain, revocation status, or trust anchor; it reports
|
|
132
|
+
`cryptographic_validation: not_performed`. Use a trusted signature verifier
|
|
133
|
+
before rating F8 PASS or FAIL.
|
|
134
|
+
|
|
135
|
+
- A cryptographically valid signature covering the full file from the issuing
|
|
136
|
+
bank is the strongest possible PASS; this lifts the
|
|
137
|
+
`NO_EVIDENCE_OF_MODIFICATION` confidence cap (see rubric).
|
|
138
|
+
- Signature present but broken byte range / document modified after signing →
|
|
139
|
+
FAIL, decisive, only after a signature verifier confirms the failure. A
|
|
140
|
+
malformed-looking byte range from the extractor alone is FLAG.
|
|
141
|
+
- No signature → NA for most retail statements (banks rarely sign customer
|
|
142
|
+
PDFs); FLAG only if the claimed issuer is known to sign — check the
|
|
143
|
+
signature table in `issuer-profiles.md` (Verified rows only) or a verified
|
|
144
|
+
local sample before flagging absence.
|
|
145
|
+
|
|
146
|
+
## F9 — Structural anomalies
|
|
147
|
+
|
|
148
|
+
Grab bag from `structure` and `annotations`:
|
|
149
|
+
|
|
150
|
+
- **FreeText / Square / Ink annotations** overlapping content → text placed on
|
|
151
|
+
top of the page. FAIL if over a value, FLAG if marginal.
|
|
152
|
+
- **Redaction annotations** (`/Redact`) → content was masked. FLAG minimum.
|
|
153
|
+
- JavaScript, launch actions, embedded files → not typical of statements;
|
|
154
|
+
FLAG (and a mild malware caution to the analyst).
|
|
155
|
+
- Broken xref rebuilt by the library, objects claimed but missing, garbage
|
|
156
|
+
after `%%EOF` → hand-edited or corrupted; FLAG→FAIL with corroboration.
|
|
157
|
+
- `pikepdf` repair warnings surface in `structure.repairs` — quote them.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Image Authenticity Signals — Interpretation Guide (I1–I9)
|
|
2
|
+
|
|
3
|
+
Use these checks for JPEG, PNG, WebP, TIFF, BMP, and other Pillow-decodable raster images.
|
|
4
|
+
The goal is to detect evidence of editing or recomposition, including traces
|
|
5
|
+
from Photoshop and other image tools. No individual metadata or pixel test can
|
|
6
|
+
prove originality: editors can strip metadata, and legitimate messaging or
|
|
7
|
+
export workflows routinely recompress images.
|
|
8
|
+
|
|
9
|
+
## I1 — Container integrity
|
|
10
|
+
|
|
11
|
+
- PASS: the decoder accepts the file, declared format matches magic bytes, and
|
|
12
|
+
the marker/chunk stream terminates normally without unexplained trailing data.
|
|
13
|
+
- FLAG: extension and magic disagree, non-zero payload follows JPEG EOI, or the
|
|
14
|
+
decoder reports repairable corruption. Innocent causes include transfer damage.
|
|
15
|
+
- FAIL: embedded active payload or a deliberately deceptive polyglot is found.
|
|
16
|
+
|
|
17
|
+
## I2 — Editor metadata and signatures
|
|
18
|
+
|
|
19
|
+
Inspect EXIF `Software`, XMP `CreatorTool`/history, IPTC, PNG text chunks, JPEG
|
|
20
|
+
APP13 `Photoshop 3.0`/`8BIM`, APP14 Adobe markers, and raw strings.
|
|
21
|
+
|
|
22
|
+
- PASS: source-native capture/export tooling is identified and no editor trace exists.
|
|
23
|
+
- FLAG: Photoshop, Lightroom, GIMP, Canva, Affinity, Pixelmator, ImageMagick,
|
|
24
|
+
or another editor is named. The trace proves tool contact, not a deceptive edit;
|
|
25
|
+
resizing, color correction, and metadata work are innocent explanations.
|
|
26
|
+
- FAIL: editor history records a material post-capture composite/change and the
|
|
27
|
+
user requires an unedited original, or editor evidence corroborates a pixel splice.
|
|
28
|
+
- NA: metadata is absent or stripped. Never treat absent editor strings as PASS.
|
|
29
|
+
|
|
30
|
+
## I3 — Capture-device provenance
|
|
31
|
+
|
|
32
|
+
- PASS: coherent camera/device make, model, lens, and capture settings are present,
|
|
33
|
+
or a platform-native screenshot marker is independently verifiable.
|
|
34
|
+
- FLAG: mutually inconsistent make/model/software fields or camera metadata on a
|
|
35
|
+
purported screenshot. Re-encoding can copy stale metadata, so seek corroboration.
|
|
36
|
+
- NA: device metadata absent. Messaging apps commonly strip it.
|
|
37
|
+
|
|
38
|
+
## I4 — Timestamp consistency
|
|
39
|
+
|
|
40
|
+
Compare EXIF original/digitized/modify times, filesystem times, visible timestamps,
|
|
41
|
+
and the claimed event date. Filesystem timestamps alone are weak transfer evidence.
|
|
42
|
+
|
|
43
|
+
- PASS: embedded capture chronology is possible and agrees with the claim.
|
|
44
|
+
- FLAG: modify time is later than capture, with export or messaging as an innocent cause.
|
|
45
|
+
- FAIL: impossible chronology directly contradicts the claim and is corroborated.
|
|
46
|
+
- NA: no embedded timestamp or no claimed event time.
|
|
47
|
+
|
|
48
|
+
## I5 — Encoding and quantization
|
|
49
|
+
|
|
50
|
+
Record baseline/progressive mode, chroma subsampling, JPEG quantization tables,
|
|
51
|
+
quality estimate, PNG chunks, and encoder comments.
|
|
52
|
+
|
|
53
|
+
- FLAG: unusual or mixed encoder signatures, thumbnail/main-image mismatch, or
|
|
54
|
+
repeated-save indicators. Social platforms and format conversion are common causes.
|
|
55
|
+
- FAIL only with independent evidence of a material edit.
|
|
56
|
+
- NA when the format or available tooling cannot expose the signal.
|
|
57
|
+
|
|
58
|
+
## I6 — Recompression / error-level consistency
|
|
59
|
+
|
|
60
|
+
Open `ela.png` and inspect the numeric tile errors in `image-forensics.json`.
|
|
61
|
+
Compare like regions: text against text, flat background against flat background.
|
|
62
|
+
Naturally detailed edges always produce more error than flat areas.
|
|
63
|
+
|
|
64
|
+
- PASS: comparable regions have broadly consistent error and no material area is isolated.
|
|
65
|
+
- FLAG: a semantically important region has a sharply different error profile.
|
|
66
|
+
- FAIL: a localized error boundary exactly surrounds altered material and is
|
|
67
|
+
corroborated by I2, I7, or content inconsistency.
|
|
68
|
+
- NA: lossless source, uniformly flattened/re-exported image, or inadequate resolution.
|
|
69
|
+
|
|
70
|
+
ELA alone must never produce LIKELY_MODIFIED. A full-image export after editing
|
|
71
|
+
can normalize errors, while an untouched image can have nonuniform errors.
|
|
72
|
+
|
|
73
|
+
## I7 — Splice, copy-move, and boundary evidence
|
|
74
|
+
|
|
75
|
+
Inspect material regions at native pixels for hard seams, halos, mismatched blur,
|
|
76
|
+
duplicate texture, inconsistent antialiasing, alignment, perspective, shadow, and
|
|
77
|
+
noise. Automated copy-move matches need manual confirmation because repeated UI
|
|
78
|
+
components and textures create false positives.
|
|
79
|
+
|
|
80
|
+
- FAIL: a material value/object has a confirmed compositing boundary or duplicated
|
|
81
|
+
source patch with no plausible scene explanation.
|
|
82
|
+
- FLAG: a visible anomaly is plausible but not conclusive.
|
|
83
|
+
- NA: resolution/compression is too poor for reliable inspection.
|
|
84
|
+
|
|
85
|
+
## I8 — Sensor, noise, and resampling consistency
|
|
86
|
+
|
|
87
|
+
For camera photos, compare local noise, demosaicing/CFA behavior, sharpening,
|
|
88
|
+
resampling grids, and depth-of-field. For screenshots, assess raster scaling and
|
|
89
|
+
text antialiasing instead; camera sensor tests are NA.
|
|
90
|
+
|
|
91
|
+
- FLAG: a material region has inconsistent noise/resampling.
|
|
92
|
+
- FAIL only when localized and independently corroborated.
|
|
93
|
+
- NA when the source type, resolution, or tools do not support the test.
|
|
94
|
+
|
|
95
|
+
## I9 — Trusted provenance or signature
|
|
96
|
+
|
|
97
|
+
The bundled script only scans for possible C2PA/JUMBF markers and reports
|
|
98
|
+
`cryptographic_validation: not_performed`; marker presence is not validation.
|
|
99
|
+
Use a trusted C2PA or signature verifier before rating I9 PASS or FAIL.
|
|
100
|
+
|
|
101
|
+
- PASS: valid C2PA/Content Credentials or another trusted signature covers the
|
|
102
|
+
file and validates to the expected source.
|
|
103
|
+
- FAIL: provenance exists but fails validation or the protected file was changed.
|
|
104
|
+
- NA: no signed provenance. This is normal and not suspicious by itself.
|
|
105
|
+
|
|
106
|
+
## Rating reminders
|
|
107
|
+
|
|
108
|
+
- An editor name proves editor contact, not fraud.
|
|
109
|
+
- Metadata absence means NA, not PASS.
|
|
110
|
+
- A clean marker stream proves only that the current export is structurally clean.
|
|
111
|
+
- A screenshot of a genuine page and a fabricated screenshot can look identical.
|
|
112
|
+
- Prefer the original file from the capture device or source application. Comparing
|
|
113
|
+
hashes, native exports, adjacent frames, chat exports, or issuer-side records is
|
|
114
|
+
stronger than analyzing a forwarded JPEG.
|