The .froga/* artefacts
✅ Stable
The .froga/ directory in the repository holds the signed evidence artefacts written by the engine when the corresponding subcommands are run. Each artefact is a JSON file inside a versioned envelope (FrogaArtifact<T>) accompanied by a signature file (.sig). The cloud platform reads these files from the repository and verifies them before rendering any report.
The FrogaArtifact<T> envelope
Section titled “The FrogaArtifact<T> envelope”All .froga/* artefacts follow the same envelope contract defined in crates/froga-core/src/froga_artifact.rs. The envelope is a versioned wrapper with deterministic serialisation (no timestamps, stable field ordering):
{ "schema_version": 1, "kind": "conformance", "system": "loan", "payload": { ... }}Envelope fields
Section titled “Envelope fields”| Field | Rust type | Description |
|---|---|---|
schema_version | u32 | Incremental schema version of the payload (per artefact type). Currently 1 for all types. |
kind | String | Artefact type: "conformance" or "reconstruct". |
system | String | Name of the system the artefact belongs to (human-readable anchor; the technical anchor is the external git reference). |
payload | T | Artefact-specific content (varies by kind). |
Serialisation is deterministic (pretty JSON, declaration order of fields) — the same bytes are signed and stored. There are no timestamps in the envelope; temporal traceability is provided by git history.
Signature file (.sig)
Section titled “Signature file (.sig)”Every <name>.json artefact has a sibling file <name>.json.sig. The signature follows the same scheme as the main bundle:
- Algorithm: ECDSA over the NIST P-256 curve with SHA-256, deterministic signatures (RFC 6979); signature in raw
r‖sform (64 bytes) inside a DSSE envelope (Dead Simple Signing Envelope) - Statement: in-toto Statement v1 (type
https://in-toto.io/Statement/v1) - Canonical payload: JCS (RFC 8785) for byte-for-byte determinism
- Subject: SHA-256 of the artefact bytes — links signature and content
keyid:hex(SHA-256(uncompressed SEC1 pubkey, 65 B))— identifies the verifying key without transporting it
The signing backend is pluggable (environment variable FROGA_SIGNING_BACKEND): local (32-byte EC P-256 scalar in hex in FROGA_SIGNING_KEY; without it, a fixed development scalar, integrity only, no non-repudiation) or scaleway-kms (signing delegated to the Scaleway Key Manager, alg EC-P256-SHA256; the private key never leaves the KMS). froga pubkey exports the verifying pubkey (SEC1, 65 B hex) to register it in the cloud per connection (ScmConnection.signerPubkey).
See Sign and verify evidence for the full flow and the current state of the trust chain.
Artefact table
Section titled “Artefact table”.froga/ file | Signature | Command that writes it | Required flag | kind |
|---|---|---|---|---|
bundle.json | bundle.json.sig | froga run | (always) | (bundle, not FrogaArtifact) |
reconstruct.json | reconstruct.json.sig | froga reconstruct | --out | "reconstruct" |
conformance/<slug>.json | conformance/<slug>.json.sig | froga conformance | --out | "conformance" |
risk-projection/<slug>.json | risk-projection/<slug>.json.sig | froga risk-projection | (always, on demand) | "risk-projection" |
Notes on the main bundle
Section titled “Notes on the main bundle”bundle.json does not use the FrogaArtifact<T> envelope: it is a directly signed EvidenceBundle. It is the central artefact that the others reference. Its signature is verified with froga verify.
Conformance slug
Section titled “Conformance slug”The conformance file slug is generated from the standard id by replacing / and @ with _:
eu/pren-18228@2026 → .froga/conformance/eu_pren-18228_2026.jsoniso/23894@2023 → .froga/conformance/iso_23894_2023.jsonThis transformation is performed by the standard_slug function in froga_artifact.rs.
Risk-projection slug
Section titled “Risk-projection slug”The risk-projection file slug is derived from the framework id in the same way:
iso/14971@2019 → .froga/risk-projection/iso_14971_2019.jsoneu/pren-18228@2026 → .froga/risk-projection/eu_pren-18228_2026.jsoniso/23894@2023 → .froga/risk-projection/iso_23894_2023.jsonHow the CLI writes them
Section titled “How the CLI writes them”The write_froga_artifact function in crates/froga-cli/src/util/artifact.rs follows this pattern for all artefacts:
// 1. Build the envelopelet art = FrogaArtifact::new(1, "conformance", &system, payload);
// 2. Serialise to deterministic JSONlet json = artifact.to_json()?;
// 3. Sign the bytes (ECDSA-P256; the backend is chosen by FROGA_SIGNING_BACKEND// internally via signer_from_env: LocalSigner or ScalewayKmsSigner)let proof = EcdsaDsseSigner.sign(json.as_bytes())?;
// 4. Write <rel>.json and <rel>.json.sigstd::fs::write(&path, &json)?;std::fs::write(sig_path, &proof)?;Subdirectories are created automatically (e.g. .froga/conformance/ for conformance reports).
How the cloud verifies them
Section titled “How the cloud verifies them”The cloud platform (TypeScript, cloud/lib/froga/) reproduces the froga verify check without calling the CLI:
- Reads the artefact bytes (
.json) and signature (.sig). - Parses the DSSE envelope and in-toto Statement from the
.sigfile. - Verifies the ECDSA-P256 signature (raw
r‖s) over the PAE (DSSE Pre-Authentication Encoding) with@noble/curves. - Checks that the envelope
keyidmatcheshex(SHA-256(SEC1 pubkey))of the expected pubkey for THAT connection (ScmConnection.signerPubkey), in a fail-loud manner: with no registered pubkey, the cloud does not verify silently but fails. - Verifies that the Statement
subject.sha256matches the SHA-256 of the artefact bytes.
The cloud does not compute evidence: it only reads and verifies what the engine has committed. The git repository is always the source of truth.
froga verify --repo /path/to/projectLifecycle
Section titled “Lifecycle”froga compile → generates oscal.assessment_plan (not a FrogaArtifact)froga run → writes .froga/bundle.json + bundle.json.sigfroga reconstruct --out → writes .froga/reconstruct.json + .sigfroga conformance --out → writes .froga/conformance/<slug>.json + .sigfroga risk-projection → writes .froga/risk-projection/<slug>.json + .sig[git commit -A .froga/] → artefacts are versioned and traceableArtefacts are not committed automatically; the commit is a deliberate human act that constitutes the “placing on the market” of the conformance state.
See also: froga CLI Reference, Sign and verify evidence.