Evidence pack

Halcyon Payments · Q3 2026 · strength E2

This pack is what PRGuard holds about the changes that reached a default branch in the period: which were audited before they merged, which were not and why, what the audits found and what people decided about it. It is evidence for the controls listed below. Whether a control is met is the assessor's judgement, and nothing in this pack says that one is.

What it covers

PeriodQ3 2026: 1 Jul 2026 to 30 Sep 2026, on the organisation's reporting clock (Europe/London). Exactly: from 2026-06-30T23:00:00Z up to and not including 2026-09-30T23:00:00Z, in UTC.
FrameworksCyber Resilience Act, EU AI Act
Control catalogue2026-10-17.1
Repositories in the packHow PRGuard reviews itDefault branch
merchant-sdkFull review: a failed audit blocks the mergemain
risk-engineFull review: a failed audit blocks the mergemain
Left outWhy
infraNot a product with digital elements placed on the EU market. Not part of a high-risk AI system. The credit decision is made in risk-engine.
marketing-siteStatic marketing site: no customer data and no production access.
payments-serviceNot a product with digital elements placed on the EU market. Not part of a high-risk AI system. The credit decision is made in risk-engine.

A repository left out is in no count, no list and no sample in this pack.

Coverage

171 of 180 changes were audited before they merged: 95%. 18 are gaps.

OutcomeChanges
Passed162
Merged anyway9
Bypassed3
Not audited6
Not yet known0

Every change is a row of coverage.csv.

Who or what wrote the changes

OriginChangesAudited before mergeShare
Human888495.5%
AI-assisted464495.7%
AI agent212095.2%
Bot or automation252392%

Origin is classified from observable signals, such as a commit trailer or a bot's login. It is not ground truth. Each change an AI tool or a bot had a hand in is a row of ai-register.csv.

Controls

FrameworkCoveredPartly coveredGapsNot applicableShare covered
Cyber Resilience Act4000100%
EU AI Act301075%

Covered: a rule file is mapped to the control and audits in the period ran with it. Partly covered: a rule file is mapped and no audit ran with it. Gap: nothing is mapped. Not applicable: the organisation said so, with a reason. Each control is a row of controls.csv; the mapped ones are set out in controls.md.

Exceptions

Status when the pack was madeExceptions
Expired1
In force2
Waiting for approval1

Every exception that touched the period, with who asked, who decided and when it ends, is a row of exceptions.csv.

Policies as the period ended

Ignore skip markersOn
Minimum score to mergeOff
An error needs an exception to be closed as won’t fixOn
PR-only fix deliveryOn

The changes made during the period are in policies.json.

Sign-offs

I, Olivia Bennett, have reviewed the coverage ledger and the exceptions register of Halcyon Payments for Q3 2026 (1 Jul 2026 to 30 Sep 2026), for Cyber Resilience Act, EU AI Act, as PRGuard held them when I signed.

Signed 2026-10-05T09:12:00Z (UTC). Hash of what was held then: a9d51c54e9f67d57aa35333b21c13df7fa8dfc16458edd0a983b1f5f22a67356

A sign-off records that the period was reviewed. It is not a statement that the period was clean.

What is in the pack

manifest.jsonEvery file with its SHA-256, and the root hash over them.
signature.jsonPRGuard’s signature over manifest.json, and the key it was made with.
scope.jsonThe scope statement above, for a program to read.
coverage.csvEvery change that reached a default branch, or a branch a repository releases from: 180.
releases.csvEach tag pushed in the period, and the branch it was cut from: counted, not counted, or not known and why.
controls.csv, controls.mdEach control's state and counts; the rules, repositories and policies behind each mapped control.
rules/The full text of each rule file version that carried a control: 5. These are the organisation's own rules.
samples/82 sampled audits, up to 25 for each control, evenly spaced through the period. samples/index.csv says which belong to which control. Names, sizes, fingerprints and links: never source code.
exceptions.csvThe exceptions register for the period.
ai-register.csvChanges an AI tool or a bot had a hand in, with who approved and merged each.
policies.jsonThe organisation's policies and their changes.
journal.jsonlThe append-only journal for the period: 620 entries, each with its own hash and linked to the entry written before it. 1041 lines carry an entry by its hashes only, written outside the period, about a repository the pack leaves out or naming a framework not offered, so the chain has no gap.
attestations.jsonThe owner's sign-offs of this period.
verify.pyThe verifier.

The columns of coverage.csv

ColumnWhat it says
merged_at_utcWhen the change landed on the branch, in UTC.
repositoryThe repository it landed in.
branchThe branch it landed on: the default branch, or a release branch the repository names.
pull_requestThe pull request's number. Empty for a direct push.
merge_commitThe commit that landed on the branch.
merged_commitThe pull request's last commit, the one that was merged.
authorThe GitHub login that opened the pull request or pushed the change.
author_typeWhat GitHub says the author is: User or Bot.
originWho or what wrote the change, as PRGuard classified it from what it could observe: HUMAN, AI_ASSISTED, AI_AGENT or DEPENDENCY_BOT (dependency bots and other automation).
origin_agentThe tool PRGuard recognised, where it recognised one.
origin_confidenceHow sure the classification is: high, medium or low.
origin_signalWhat the classification rests on, such as a commit trailer or a bot's login.
merged_byThe GitHub login that merged it.
merged_by_its_authoryes when a person merged their own pull request.
approved_byThe people, not bots, whose approval on GitHub stood when it merged.
reviewsWhether PRGuard read the pull request's reviews from GitHub: read, not read yet, could not be read, or no pull request. It says the reviews were read, not that anyone approved.
outcome_classThe outcome's key: what PRGuard did about the change before it merged.
outcomeThe outcome in words.
reasonWhy, where the outcome needs a reason, such as why a change was not audited.
verdictThe deciding audit's verdict: PASS, WARN or FAIL. Empty when no audit decided it.
scoreThe deciding audit's score out of 100.
auditsHow many audits PRGuard ran on the change.
review_modeHow PRGuard reviewed the repository that day: FULL_REVIEW, where a failed audit asks GitHub to block the merge, or COMMENT_ONLY.
prguard_review_eventThe review PRGuard itself posted on the pull request for the deciding audit: APPROVE, REQUEST_CHANGES or COMMENT; empty where none was posted. It is PRGuard's own review, never a person's approval: people's approvals are in approved_by.
forcedyes when the change arrived by a force-push.
sourceHow PRGuard learned of it: pr_closed (a merged pull request), push (a push to the branch) or backfill (read from GitHub's history).
record_idPRGuard's id for this record of the change.
audit_idPRGuard's id for the deciding audit. Empty when no audit decided it.

A change PRGuard did not audit has no verdict, score or audit id. Times are UTC.

How to check it

  1. Unzip the pack, or leave it zipped.
  2. Run: python verify.py <pack.zip or folder> --expect <the root hash PRGuard sent you> --key <PRGuard's public key>
  3. VERIFIED means every listed file matches its hash, nothing is missing or added, the root hash is the one expected, a signed pack's signature is PRGuard's, and every journal line links to the one before.
  4. PRGuard publishes every key it has signed packs with at /.well-known/prguard-pack-key.json on its site, each with its id, its public key, its dates and whether it was revoked; the Packs tab and the email name the one used. Pass its public key; its id alone names only part of it.
  5. verify.py needs Python 3.9 or later and nothing else. It reads the pack and writes nothing. prguard verify does the same check.

E2. Attested: E1, plus PRGuard's signature over the manifest, checked against its published key, and a journal whose entries are chained, so the pack shows who made it and that no entry between its first and last line was removed after it was written; neither shows the records were right.

The records are append-only: PRGuard does not edit or delete them. That is not the same as tamper-proof. The signature shows PRGuard made this manifest, when it is checked against PRGuard’s published key; the chain shows no entry between the journal’s first and last line was removed after it was written. Neither shows the records were right.

The records this pack was made from are retained while the organisation's PRGuard account exists.

prguard-evidence-pack/2