Gå til hovedindhold

fremforge CLI

fremforge CLI er en enkelt binærfil, der pakker det offentlige REST API ind. Samme verber, samme autorisationsmodel, samme scopes. Distribueres kun fra PoP’er i EU; ingen afhængighed af npm-registryet, Docker Hub eller Sigstore Fulcio.

Supportperiode, sikkerhedsopdateringer og SBOM

Supportperiode5 år fra udgivelsesdatoen for hver minor-version. Det er supportperioden i henhold til artikel 13, stk. 8, i Cyber Resilience Act (forordning (EU) 2024/2847), og den knytter sig til den udgivne version, ikke til dit abonnement.
SikkerhedsrettelserGratis, altid, og aldrig forbeholdt et bestemt abonnement. Rettelser udgives fremad som en ny version på de samme URL’er og er dækket af den samme signerede SHA256SUMS. Kører du en version, der er afløst? Opgradér for at få rettelsen.
Rapportering af sårbarhedersecurity@frem.sh – koordineret offentliggørelse, detaljer på www.frem.sh/security.
SBOMCycloneDX JSON på cli.frem.sh/cli/SBOM.cdx.json, pr. version på cli.frem.sh/cli/v<version>/SBOM.cdx.json.
KontraktvilkårVilkårenes §7.5 – licens, garanti og ansvar specifikt for binærfilen.

SBOM’en er kort, og det er hele pointen. CLI’en erklærer nul npm-afhængigheder fra tredjeparter. Den har to afhængigheder, begge vores egne: @fremverk/audit-chain, den samme hashkæde-kode, som API’et selv kører (delt i stedet for genimplementeret, så audit-verify ikke kan glide væk fra det, den verificerer), og @fremforge/tlog-verify, som kontrollerer optagelse i transparensloggen for attest-verify. Ingen af dem har egne afhængigheder; begge importerer kun Nodes indbyggede moduler, så hele overfladen fra tredjeparter i den leverede binærfil er Bun-runtimen, der indlejres ved kompilering. Fra v0.3.1 viser SBOM’en også de to førstepartspakker, markeret som vores, så den nævner alle komponenter og ikke kun tredjepartskomponenten.

SBOM’ens hash står i SHA256SUMS, så den er dækket af den samme Ed25519-signatur som binærfilerne – verificér den på samme måde (se §“Verificér Ed25519-signaturen” nedenfor – det gælder alle filer, der står i manifestet, ikke kun binærfilerne):

curl -fsSL https://cli.frem.sh/cli/SBOM.cdx.json -o SBOM.cdx.json
curl -fsSL https://trust.frem.sh/SHA256SUMS -o SHA256SUMS
grep SBOM.cdx.json SHA256SUMS | shasum -a 256 -c -

CLI’en er valgfri, med én undtagelse. Alle de handlinger, den udfører, er tilgængelige via REST API’et, så er din politik ikke at køre leverandørers binærfiler, mister du ingen funktionalitet ved at springe den over. Undtagelsen er audit-verify, som genberegner din revisions-hashkæde på din maskine – det kan et API ikke gøre for dig, for hele pointen med at genberegne en hashkæde er ikke at stole på den part, der har lavet den. De rå rækker leveres af GET /orgs/{org}/audit/chain, så du kan lave regnestykket i dine egne værktøjer i stedet; det, du ikke kan, er at lade os gøre det og kalde resultatet en verifikation.

Installation

Én linje (anbefalet)

curl -sSfL https://cli.frem.sh/cli/install.sh | sh

Installationsscriptet finder selv dit operativsystem (Linux eller macOS) og din arkitektur (arm64 eller x86_64), henter den matchende binærfil fra https://cli.frem.sh/cli/, henter den kanoniske SHA256SUMS fra https://trust.frem.sh/ (en separat vært med separate skriverettigheder, så et kompromis af værten for binærfiler alene ikke kan forfalske et match), verificerer SHA-256 og installerer til ~/.local/bin/fremforge eller /usr/local/bin/fremforge.

Tilsidesæt installationsstedet med FREMFORGE_INSTALL_DIR:

curl -sSfL https://cli.frem.sh/cli/install.sh | FREMFORGE_INSTALL_DIR=/opt/fremforge/bin sh

Fastlås en bestemt version:

curl -sSfL https://cli.frem.sh/cli/install.sh | FREMFORGE_VERSION=0.1.0 sh

Manuel download

Vil du hellere lade være med at sende et script fra nettet direkte til sh, kan du hente binærfilerne direkte. Vælg det passende par:

OSArkitekturURL
macOSarm64https://cli.frem.sh/cli/fremforge-darwin-arm64
macOSx86_64https://cli.frem.sh/cli/fremforge-darwin-x64
Linuxarm64https://cli.frem.sh/cli/fremforge-linux-arm64
Linuxx86_64https://cli.frem.sh/cli/fremforge-linux-x64
Windowsx86_64https://cli.frem.sh/cli/fremforge-windows-x64.exe

Arkitektursuffikset er x64 (ikke x86_64) og arm64 – de svarer til Buns --target-betegnelser. uname -m rapporterer x86_64 på Intel/AMD, så omsæt det til x64, når du bygger URL’en i hånden (installationsscriptet på én linje gør det for dig).

Verificér mod den kanoniske hash på trust.frem.sh, før du kører binærfilen:

# 0. Map uname -m's x86_64 to the published x64 token
arch=$(uname -m); [ "$arch" = x86_64 ] && arch=x64

# 1. Download the binary
curl -fsSL https://cli.frem.sh/cli/fremforge-$(uname -s | tr A-Z a-z)-$arch \
  -o fremforge

# 2. Download the canonical SHA256SUMS (separate host, separate credential)
curl -fsSL https://trust.frem.sh/SHA256SUMS -o SHA256SUMS

# 3. Verify
sha256sum --check --ignore-missing SHA256SUMS

# 4. Install
chmod +x fremforge
sudo install -m 0755 fremforge /usr/local/bin/fremforge

Verificér Ed25519-signaturen (valgfrit, anbefalet)

Ud over SHA-256-matchet er hver udgivelse signeret som en DSSE-indpakket in-toto Statement under den samme tillidsrod som fremforges SLSA-build-provenance. Verifikationen henter den offentlige tillidsrod fra www.frem.sh/.well-known/slsa-trust-root.json og kontrollerer Ed25519-signaturen på bytes i SHA256SUMS.

Brug ikke slsa-verifier verify-artifact. Den underkommando har intet --trusted-root-flag, og den kan hverken læse fremforges JSON-tillidsrod eller en ren Ed25519-DSSE-konvolut – den forventer en bundle i Sigstore-stil. Denne side viste tidligere en sådan kommando; den kunne aldrig have kørt. Verificér i stedet direkte med værktøjer, din distribution allerede har.

SHA256SUMS.intoto.jsonl er JSON Lines: én DSSE-konvolut pr. udgivet binærfil. Verificér hver linje, du interesserer dig for.

# Pull the trust root and the signed envelopes
curl -fsSL https://www.frem.sh/.well-known/slsa-trust-root.json -o slsa-trust-root.json
curl -fsSL https://trust.frem.sh/SHA256SUMS.intoto.jsonl -o SHA256SUMS.intoto.jsonl

# Extract the builder public key: v2, the active key since 2026-09-12. An envelope's
# .signatures[0].keyid names its key; one signed before 2026-09-12 needs ...-v1.
jq -r '.trusted_keys[] | select(.kid=="fremforge-slsa-builder-v2") | .pem' \
  slsa-trust-root.json > builder.pub

# Verify every envelope: rebuild the DSSE pre-authentication encoding and check it
while read -r line; do
  pt=$(printf '%s' "$line" | jq -r .payloadType)
  printf '%s' "$line" | jq -r .payload | base64 -d > payload.bin
  printf '%s' "$line" | jq -r '.signatures[0].sig' | base64 -d > sig.bin
  { printf 'DSSEv1 %s %s %s ' "${#pt}" "$pt" "$(wc -c < payload.bin)"; cat payload.bin; } > pae.bin
  openssl pkeyutl -verify -pubin -inkey builder.pub -rawin -in pae.bin -sigfile sig.bin \
    && jq -r '.subject[] | .name + "  " + .digest.sha256' payload.bin
done < SHA256SUMS.intoto.jsonl

Hver verificeret konvolut udskriver alle de artefakter, den dækker, og den digest, fremforge har signeret for hver af dem. Sammenlign den digest med den binærfil, du har hentet – det er sammenligningen, der er pointen; signaturen fortæller dig kun, at digesten er vores.

Tillidsroden er den samme, som bruges til build-provenance for artefakter, som din runner producerer – samme Ed25519-nøgle, samme builderId, samme opskrift på verifikation. Vi angiver ikke et SLSA-niveau; sikkerhedssiden forklarer hvorfor.

Godkendelse

CLI’en understøtter tre slags legitimationsoplysninger, som slås op i denne rækkefølge: flaget --token=…, miljøvariablen FREMFORGE_TOKEN og derefter det gemte login i ~/.config/fremforge/auth.json.

Anbefalet – login i browseren (intet at indsætte)

fremforge auth login

Åbner din browser på frem.sh, du godkender enheden, tokenet lander i ~/.config/fremforge/auth.json (tilstand 600), og alle efterfølgende kald indlæser det automatisk. Det er samme OAuth2 + PKCE-flow, som dit git push allerede bruger, så tilbagekalder du tokenet på frem.sh/user/settings/applications, tilbagekalder du adgangen for både git og CLI i ét trin.

fremforge auth status      # show current login + expiry
fremforge auth logout      # revoke + delete the local file

Tokenet virker på både fremforges REST API (/_app/api/v1/orgs/…) OG Forgejos eget API (/api/v1/repos/…) – Forgejo accepterer sine egne OAuth-bearer-tokens direkte, og fremforges API validerer dem via introspektion mod Forgejos /api/v1/user. Samme identitet på begge flader.

CI og scripts – PAT

Til sammenhænge uden brugerinteraktion (CI-jobs, scripts, agenter) opretter du et PAT med afgrænsede scopes. Det nemmeste er at bruge selve CLI’en, når du først har logget ind interaktivt én gang (fremforge auth tokens create --name=… --scopes=… – se Opret et PAT med afgrænsede scopes til CI); eller opret et på https://frem.sh/user/settings/applications. Derefter:

export FREMFORGE_TOKEN='<your PAT>'
fremforge whoami

Tilsidesæt basis-URL’en med FREMFORGE_URL= (skal være HTTPS); standard er https://frem.sh.

Kommandoer

fremforge auth login                              Browser-based OAuth2+PKCE login.
fremforge auth logout                             Revoke + delete the stored token.
fremforge auth status                             Show current login + expiry.
fremforge whoami                                  Print the user the token authenticates as.
fremforge data-export start <slug>                Queue a full data export for the org.
fremforge data-export list <slug>                 List recent export jobs.
fremforge dependency-updates enable <slug>        Enable hosted Renovate for the org.
fremforge dependency-updates disable <slug>       Disable hosted Renovate for the org.
fremforge dependency-updates run-now <slug>       Trigger an out-of-cycle Renovate run (1/h cap).
fremforge audit-log <slug>                        Fetch the org audit-log slice.
                  [--since=DATE] [--actor=…] [--action=…] [--limit=N]
fremforge audit-verify <slug>                     RECOMPUTE the per-tenant audit hash chain
                  [--human] [--full]              locally, then cross-check our own verdict.
                                                  Exit 0=ok, 2=partial, 3=broken,
                                                  4=anchor_mismatch, 5=local ok but we
                                                  disagreed. --full walks from the chain
                                                  epoch instead of the latest anchor.
fremforge sbom <owner>/<repo> <tag>               Download a release SBOM.
                  [--format=spdx|cyclonedx]
fremforge runs <owner>/<repo>                     List recent CI runs (JSON; --human for a table).
                  [--limit=N] [--status=…] [--event=…]
fremforge runs logs <owner>/<repo> <run-id>       Fetch a run's logs (text/plain, all jobs).
fremforge auth tokens create                      Mint a scoped PAT (printed once).
                  --name=N --scopes=a,b [--ttl-days=N]
fremforge auth tokens list                        List your PATs (--human for a table).
fremforge auth tokens revoke <token-id>           Revoke a PAT.
fremforge findings <type> <slug>                  Security findings. type ∈ secrets |
                  [--status=…] [--repo=…]         dependencies | signed-commits | attestations.
fremforge secrets list <slug>                     List org Actions/CI secret names.
fremforge secrets set <slug> <NAME>               Set a secret (value via FREMFORGE_SECRET_VALUE).
fremforge secrets delete <slug> <NAME>            Delete a secret.
fremforge seats list <slug>                       List org members + seat usage.
fremforge seats add <slug> --email=E              Add a member (--username=, --full-name= optional).
fremforge seats remove <slug> <username>          Remove a member.
fremforge work start <org>/<repo>                 Declare work before the first push (Active work).
                  --title=TEXT [--intent=TEXT]    Prints the branch to create and related work.
                  [--areas=a,b] [--branch=NAME]
fremforge work list <org>/<repo>                  Who is building what in a repository.
                  [--area=AREA]
fremforge version                                 Print the CLI version.

Kør fremforge --help for den kanoniske reference, eller tilføj --human på en kommando, der understøtter det, for at få output formateret som tabel.

Eksempler

Verificér selv din revisionskæde (brug i CI)

audit-verify spørger ikke os, om din revisionslog er intakt. Den henter de rå rækker, genberegner hver eneste hash og hvert eneste led på din maskine og sammenligner først derefter sit resultat med vores. Exitkoden er dit resultat, ikke vores påstand – og er de to uenige, rapporteres uenigheden i sig selv, og kommandoen fejler.

Den forskel er grunden til, at kommandoen findes. Indtil august 2026 læste den et integrity_status-felt i et svar fra API’et og omsatte det til en exitkode, hvilket betyder, at den part, der blev revideret, beregnede svaret, og “verifikations”-værktøjet bare videregav det. Intet, du kunne køre, ville have opdaget et kompromitteret eller uærligt API. Nu er der noget, der gør.

export FREMFORGE_TOKEN='<your PAT, audit:read scope>'

# Human-readable, for terminals
fremforge audit-verify acme --human

# Script-friendly. The exit code reflects the LOCAL walk:
#   0 = ok
#   2 = partial          — some of the chain could not be checked (see below)
#   3 = broken           — a row's content or its link does not match. Investigate.
#   4 = anchor_mismatch  — the WORM-anchored tip is not present in your chain
#   5 = we disagreed     — your walk was clean but our verdict was not
#   6 = bad signature    — the anchor's signature failed against our published key
fremforge audit-verify acme || {
  echo "audit verification failed with exit code $?"
  exit 1
}

# Walk the entire chain from its first row instead of just the tail since the
# last anchor. Slower and much larger; appropriate for a quarterly review.
fremforge audit-verify acme --full --human

Sådan læser du resultaterne ærligt, for et verifikationsværktøj, der overdriver, er værre end intet:

  • partial er ikke bestået. Det betyder, at en afskæring skjulte en del af kæden, så rækkerne uden for vinduet ikke er verificeret. Vi rapporterer ok i det tilfælde, og CLI’en gør det bevidst ikke.
  • Slettede og redigerede rækker giver ikke samme hash igen, og det er bevidst. GDPR-sletning og oprydningen af payloads efter 90 dage omskriver rækkernes indhold bagefter, så de rækker ikke længere matcher deres egen hash. De tælles separat (tenant_erased_count, payload_redacted_count) og er ikke manipulation. Deres led kontrolleres stadig.
  • WORM-ankeret er signeret, og CLI’en kontrollerer det mod en tillidsrod, den selv henter. audit-verify henter www.frem.sh/.well-known/slsa-trust-root.json direkte – aldrig en nøgle fra API’et – verificerer Ed25519-DSSE-signaturen og bekræfter, at konvolutten er bundet til dette anker og ikke et andet. Exitkode 6 betyder, at signaturen blev kontrolleret og fejlede; behandl det som en hændelse. NOT CHECKED (exitkoden uændret) betyder enten, at ankeret er ældre end signeringen (2026-08-04), eller at tillidsroden ikke kunne nås fra din maskine – ingen af delene er en fejl, og CLI’en fortæller, hvilken det er.

Vil du gøre det samme uden binærfilen, så læs rækkerne fra GET /orgs/{org}/audit/chain, og hash hver rækkes kanoniske JSON med nøglerne i rækkefølgen action, actor, created_at_iso, fields_json, prev_hash, tenant_id. Bevar fields_json byte for byte – lad være med at parse og serialisere det igen, ellers matcher dine digests ikke.

Se integritet i revisionskæden for den fulde garanti.

Dataeksport via selvbetjening

# Kick off
fremforge data-export start acme | jq .

# Poll
fremforge data-export list acme | jq '.[] | {id, status, created_at}'

Se dataeksport for artefaktets format, opbevaring og download via signeret URL.

Afhængighedsopdateringer (hostet Renovate)

fremforge dependency-updates enable acme
fremforge dependency-updates run-now acme   # 1/h rate-limit applies

Se opdateringer af afhængigheder for, hvad der tilmeldes, og hvordan du afgrænser det pr. repository.

Download af SBOM

fremforge sbom acme/api v1.4.0 --format=spdx > sbom.spdx.json
fremforge sbom acme/api v1.4.0 --format=cyclonedx > sbom.cyclonedx.json

Udsnit af revisionsloggen

fremforge audit-log acme --since=2026-05-01 --action=push-protection-override | jq .

CI-kørsler + logs

Vis de seneste kørsler, og hent derefter en kørsels fulde logs (alle jobs sat sammen) via dens globale kørsels-id:

# List the 20 most recent runs as a table
fremforge runs acme/api --human

# Script-friendly: grab the newest run id, then fetch its logs
run_id=$(fremforge runs acme/api --limit=1 | jq -r '.workflow_runs[0].id')
fremforge runs logs acme/api "$run_id"

# Tail just the failing step
fremforge runs logs acme/api "$run_id" | grep -iE "error|failed|exit code" | tail

<run-id> er det globale kørsels-id, som fremforge runs viser (feltet .workflow_runs[].id) – ikke kørselsnummeret pr. workflow i webbrugerfladens URL. Log-endpointet returnerer text/plain med alle jobs i ét svar; der er ikke brug for at hente artefakter pr. job.

Opret et PAT med afgrænsede scopes til CI

Efter dit første fremforge auth login kan du oprette underordnede tokens med snævre scopes til CI uden at forlade terminalen. Tokenet udskrives én gang – gem det med det samme:

fremforge auth tokens create --name=ci-readonly --scopes=findings:read,orgs:read --ttl-days=30 \
  | jq -r .token
fremforge auth tokens list --human
fremforge auth tokens revoke <token-id>

Du kan kun give scopes, som dit eget token allerede har, og wildcard (*) kan ikke oprettes her.

Administrér CI-secrets

fremforge secrets list acme

# Pass the value via env (preferred — not in shell history or `ps`)
FREMFORGE_SECRET_VALUE="$(cat ./deploy-key)" fremforge secrets set acme DEPLOY_KEY

fremforge secrets delete acme OLD_TOKEN

Brugere / medlemmer

fremforge seats list acme --human                       # cap + usage + roster
fremforge seats add acme --email=jane@acme.example --full-name="Jane Doe"
fremforge seats remove acme jane

Tilføjer du et medlem ud over det aftalte antal brugere, får du en 409 med et link til fakturering – køb flere brugere først.

Outputformat

Som standard skriver alle kommandoer JSON til stdout, så det er nemt at bruge i scripts og pipes. Angiv --human på de kommandoer, der understøtter det (audit-verify, attest-verify, release verify, runs, auth tokens list, seats list og work), for at få et formateret resumé.

Opdatering af CLI’en

Installationsscriptet på én linje kan køres igen og igen: kører du det igen, hentes den nyeste binærfil, checksummen verificeres igen, og den gamle binærfil overskrives på stedet:

curl -sSfL https://cli.frem.sh/cli/install.sh | sh

Om suverænitet

CLI’ens distributionsvej er fuldt EU-suveræn:

  • Binærfiler: T Cloud Public OBS (eu-de, Magdeburg / Biere, Tyskland) bag en Bunny-pull-zone, der er begrænset til PoP’er i EU.
  • SHA256SUMS + DSSE-konvolut: En separat T Cloud Public OBS-bucket (trust.frem.sh) med separate skriverettigheder; når værten for binærfiler er adskilt fra værten for integritet, kan et kompromis af den ene ikke forfalske et match mod den anden.
  • Tillidsrod: Statisk JSON-fil, der leveres fra www.frem.sh (samme Bunny-routing kun i EU).
  • Ingen afhængighed af npm-registryet: registry.npmjs.com kører i AWS i USA; CLI’en rører det aldrig, hverken ved installation eller brug.
  • Ingen afhængighed af Docker Hub: samme grund.
  • Ingen Sigstore Fulcio / Rekor: Sigstores transparenslog er hostet i USA. fremforge kører sin egen Ed25519-signering + en statisk tillidsrod i stedet for at være afhængig af Fulcio.

Underdatabehandlerne på installationsvejen står i det offentlige register over underdatabehandlere og er de samme, som allerede dækker kundernes personoplysninger i henhold til databehandleraftalens bilag B.