Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
117 commits
Select commit Hold shift + click to select a range
a9786e3
test(stellar): add proptest coverage across all four Soroban contract…
kaycke1337 Jun 1, 2026
640b2df
docs(stellar): design Soroban event topic strategy for announcer (#26)
David-patrick-chuks Jun 1, 2026
ebfd3f3
audit(stellar): cross-chain announcement schema conformance (#27)
clintjeff2 Jun 1, 2026
ff0df55
feat(stellar): stuck-funds rescue CLI + sender atomicity audit (#28)
Mitch5000 Jun 1, 2026
acfe3fb
docs(stellar): mainnet readiness checklist + go/no-go tracking (#31)
Nemenwq Jun 1, 2026
179fbd7
feat(stellar/wraith-names): multi-sig social recovery (#32)
Dennis-Ritchie1 Jun 1, 2026
eaad33a
audit(stellar): stealth-announcer security review (#34)
gloskull Jun 1, 2026
fee8d43
audit(stellar): stealth-sender security review + adversarial mocks (#38)
Olowodarey Jun 1, 2026
ccd13d6
feat(stellar): 1-to-N stealth payment splitter contract (#42)
SHEROSE0 Jun 1, 2026
c86efe7
audit(stellar): SAC compatibility matrix for stealth-sender (#43)
Faromzy Jun 1, 2026
02e4cea
perf(stellar): Soroban resource budget profiling + reusable bench har…
EslaSk Jun 1, 2026
5fd0123
feat(stellar/build): reproducible build attestation pipeline (#46)
Amarjeet325 Jun 1, 2026
9bf77bb
feat(stellar/stealth-announcer): v2 event topic schema with indexed v…
gloskull Jun 1, 2026
d2a9e56
feat(stellar): auto-generate TypeScript bindings for Soroban contract…
Jopsan-gm Jun 2, 2026
fc334d4
feat(stellar/wraith-names): gasless on-behalf register/update/release…
sudo-robi Jun 2, 2026
35332d1
audit(stellar/wraith-names): comprehensive security review (#40)
sudo-robi Jun 2, 2026
3fbcb6b
audit(stellar/stealth-registry): security review + persistent storage…
thebabalola Jun 2, 2026
9ff1184
feat(stellar): deployment script with JSON manifest + dry-run + idemp…
thebabalola Jun 2, 2026
7f7fd7c
docs(stellar): contract upgrade governance and migration plan (#37)
thebabalola Jun 2, 2026
5e90ea9
feat(stellar): preflight network validation script (#80)
gloriaelishahabu Jun 24, 2026
8689ee5
feat(stealth-sender): optional asset allowlist policy mechanism (#82)
Anadudev Jun 24, 2026
4478104
feat(stellar): stealth-batch-sender Soroban contract (#79)
cokehill Jun 24, 2026
bb54184
fix(stellar): persistent storage migration + rent audit (#83)
fhayvy Jun 24, 2026
7374fad
feat(stellar): Soroban storage recovery CLI (#84)
sublime247 Jun 24, 2026
108478d
feat(ci): Soroban test coverage measurement + CI gate (#86)
Mubking-dev Jun 25, 2026
0a5de56
feat(stellar): contract observability metrics standard (#87)
lamborghini21 Jun 25, 2026
08ac84f
feat(stellar): OZ-style Pausable circuit-breaker (#89)
gloriaelishahabu Jun 25, 2026
08e5d14
feat(stellar): futurenet integration test harness (#88)
gloriaelishahabu Jun 25, 2026
49aec9e
feat(stellar): wraith-names TTL keeper service (#90)
cashflaretech-glitch Jun 26, 2026
42ac8e8
feat(stellar): reproducible build verification (#91)
Husten150 Jun 26, 2026
5221174
perf(stellar): Wasm size optimization round 2 (#81)
OluRemiFour Jun 26, 2026
fda38a4
feat(stellar): hierarchical subdomain support for wraith-names (#85)
Trovic1 Jun 26, 2026
a3f73c9
refactor(stellar): wraith-names storage helpers + verification docs (…
debbieAmoni Jun 26, 2026
f2e9f6f
feat(stellar): multisig signer setup automation (#93)
debbieAmoni Jun 26, 2026
b8c0bf4
test(stellar): upgrade authority enforcement test suite (#94)
rahimatonize Jun 26, 2026
cd7884d
docs(audit): third-party audit preparation package (#95)
rahimatonize Jun 26, 2026
780ad26
refactor(stellar): symbol length compliance (#96)
Dubemtopsite Jun 27, 2026
282f6c0
audit(stellar): event indexing audit (#97)
Meme11030 Jun 27, 2026
a0e8fba
feat(stellar): stealth-vault time-locked payments crate (#98)
Meme11030 Jun 27, 2026
ca95b4b
feat(stellar): futurenet dry-run + SAC testnet asset integration (#99)
cashflaretech-glitch Jun 29, 2026
35bf3fc
fix(ci): unpin bookworm-slim digest in Stellar reproducible build
truthixify Jul 8, 2026
ed21968
fix(ci): install default stable rust toolchain in verification image
truthixify Jul 8, 2026
b621b46
fix(ci): correct paths in stellar reproducible-build Dockerfile
truthixify Jul 8, 2026
d1ff64a
fix(ci): also fix build.sh path
truthixify Jul 8, 2026
a319969
fix(ci): bump pinned rust toolchain to 1.86.0 for edition 2024 deps
truthixify Jul 8, 2026
2e7cacd
fix(ci): bump rust to 1.88.0 for darling/serde_with
truthixify Jul 8, 2026
9abf33a
fix(ci): make Stellar reproducible-build verification non-blocking
truthixify Jul 8, 2026
4892d3b
fix(ci): remove duplicated targets key in ci.yml
truthixify Jul 8, 2026
299aabf
ci: run CI on develop-targeting PRs and unblock stellar + solana jobs
truthixify Jul 24, 2026
d415288
ci: approve esbuild build script for pnpm 10
truthixify Jul 24, 2026
3c27c86
fix(stellar): unblock workspace compile and green the test suite
truthixify Jul 24, 2026
8310fba
test(stellar): regenerate test snapshots for updated contract behavior
truthixify Jul 24, 2026
d6f578c
ci: move pnpm onlyBuiltDependencies to pnpm-workspace.yaml
truthixify Jul 24, 2026
d7adde1
chore(stellar): add trailing newline to README to smoke-test CI trigger
truthixify Jul 24, 2026
b0c8c04
ci: pin pnpm to 10.28.2 via corepack so build-script allowlist is hon…
truthixify Jul 24, 2026
3b17911
chore(stellar): re-trigger CI with pinned pnpm 10.28.2 via corepack
truthixify Jul 24, 2026
c66a7c4
style(stellar): apply cargo fmt to test files touched by CI fixes
truthixify Jul 24, 2026
78373e3
chore(stellar): bump ethnum 1.5.2 -> 1.5.3
truthixify Jul 24, 2026
c0c5c2d
ci: pin stellar toolchain to Rust 1.88.0 for soroban-sdk 22 compat
truthixify Jul 24, 2026
23e3d57
ci: try Rust 1.86.0 for stellar (soroban-sdk 22.0.11 doesn't build on…
truthixify Jul 24, 2026
ebaf3c9
ci(stellar): back to stable rustc, mark WASM build non-blocking
truthixify Jul 24, 2026
26c9eb8
fix(stellar): use ESM-safe __dirname in generate-bindings script
truthixify Jul 24, 2026
b2db924
fix(stellar): scope generate-bindings WASM build to cdylib crates only
truthixify Jul 24, 2026
95ed0c8
fix(stellar): reuse WASM artifacts in generate-bindings when present
truthixify Jul 24, 2026
bb1a57a
ci: mark bindings + drift-check non-blocking until WASM build works
truthixify Jul 24, 2026
c98961e
feat(stellar): add one-command end-to-end deploy dry-run script for f…
otobongdev Jul 26, 2026
c0ffee3
bench(stellar): measure batch vs individual send crossover (#140)
Max-Owolabi Jul 26, 2026
766c4aa
feat(stellar): add on-chain multisig quorum rotation for signers (#141)
EmperorNexus Jul 26, 2026
0fdff8f
fix(stellar): bump soroban-sdk workspace dependency to 22.0.11 (#144)
jerryjuche Jul 26, 2026
cbc739b
test(stellar): add cargo-fuzz harness for stealth-sender batch payloa…
Olowodarey Jul 27, 2026
5c9eb3b
feat(governance): add on-chain governance PoC with token-weighted vot…
abimbolaalabi Jul 27, 2026
491d97d
ci: auto-retarget PRs from main to develop
truthixify Jul 29, 2026
cefcc94
ci: dedup stellar job cargo fmt + test steps
truthixify Jul 29, 2026
68a587a
fix(ci): pin pnpm to v10.32.1 and allow esbuild build scripts (#152)
odarome132 Jul 29, 2026
0e7368c
Contract-size optimization pass FIX (#153)
stpatrickghost Jul 30, 2026
eb647f3
feat: add batch withdraw support to stealth sender (#145)
pharwasz Jul 30, 2026
d917ca3
feat : cargo-fuzz harness for stealth-batch-sender (#154)
Olowodarey Jul 30, 2026
4027a07
ci(stellar): add ABI snapshot matching gate for contracts (#137)
odarome132 Jul 30, 2026
f940627
Subgraph-style JS/Postgres indexer example (#130)
heymide Aug 1, 2026
7f227a2
feat(stellar): wraith-names bulk registration / renewal (#118) (#134)
lockoabosede8-byte Aug 1, 2026
72b6c72
Docs/stellar v0 to v1 migration (#127)
Truphile Aug 1, 2026
9395ef3
test(stellar): add chaos harness for integration tests (#123) (#132)
Bidex-cmyk Aug 1, 2026
7c4119e
feat(stellar/wraith-names): sealed-bid auctions for premium names (#128)
raizo07 Aug 3, 2026
c1127d2
feat(stellar): circuit-breaker pause for stealth-sender and wraith-na…
Meet-hybrid Aug 4, 2026
eee4c89
feat(stealth-registry): add Kani formal verification for top 3 invari…
Michvista Aug 4, 2026
044b9e3
feat: Gas benchmark regression CI gate (#129)
raizo07 Aug 6, 2026
a3ee63e
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 6, 2026
196d3cd
chore(perf): rotate Stellar gas bench baseline
truthixify Aug 10, 2026
4dbdc41
chore(perf): rotate Stellar gas bench baseline
truthixify Aug 17, 2026
729c7f9
chore(perf): rotate Stellar gas bench baseline
truthixify Aug 24, 2026
7fb1957
docs: add per-contract READMEs for six Stellar crates (#167) (#169)
boalambo Aug 26, 2026
233c055
feat(stellar): wire wraith_metrics into names, splitter, vault, and g…
DSOTec Aug 26, 2026
2863425
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 26, 2026
b22ae33
feat(stellar): production-harden stealth-vault (#173)
DSOTec Aug 26, 2026
bfdd95f
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 26, 2026
cf6bddb
docs(dx): add unified error code catalog with CI validation (#170)
amosleoamadi Aug 27, 2026
22f1143
feat(bench): add governance and stealth-splitter benchmarks, update C…
ryzen-xp Aug 27, 2026
8c945c2
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 27, 2026
8bc5b0e
feat(stellar): rotate auction admin via multisig + timelock (#178)
DSOTec Aug 28, 2026
7977dd7
Chaos harness expansion to vault, splitter, batch-sender, governance …
EbukaMoses Aug 28, 2026
b101b3d
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 28, 2026
ac1d79f
feat: harden batch-sender (pause, admin, typed errors, multisig) (#175)
Eltimios Aug 28, 2026
ff49946
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 28, 2026
2d28131
feat(evm): parity uplift — subgraph mappings, Foundry invariants, sli…
gbengaeben Aug 31, 2026
529ba39
Batch sender fixed2 (#181)
stpatrickghost Aug 31, 2026
0cd8391
Add audit-freeze CI gate and ENGAGEMENT.md template (#158) (#183)
Jerryvic911 Aug 31, 2026
d1a9a2a
chore(perf): auto-update Stellar PERF.md bench table
truthixify Aug 31, 2026
63d563f
chore(perf): rotate Stellar gas bench baseline
truthixify Aug 31, 2026
95ebf06
chore: add CODEOWNERS to gate CI workflow changes
truthixify Sep 6, 2026
543de9c
chore(perf): auto-update Stellar PERF.md bench table
truthixify Sep 6, 2026
53603ef
perf(stellar): gate worst-case resource usage (#201)
poaspergillus Sep 25, 2026
fb3024b
feat(stellar): generate stealth batch sender bindings (#203)
Eldren-cmd Sep 25, 2026
6d1b16d
test(stellar): add storage rent exhaustion and TTL boundary tests (#208)
Oluwaseyi89 Sep 25, 2026
507b86f
chore(ci): pin CI supply chain and add dependency review (#205)
DSOTec Sep 25, 2026
42332d5
chore(deps): bump node in /stellar/examples/indexer (#209)
dependabot[bot] Sep 25, 2026
750c035
chore(deps): bump the github-actions group with 16 updates (#210)
dependabot[bot] Sep 25, 2026
079cbe2
fix: run Solana program tests in CI (issue #194)
Emmycivity Sep 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
56 changes: 56 additions & 0 deletions stellar/integration-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
pub mod harness;

#[cfg(test)]
mod tests {
use super::harness::*;

// ── Scenario 1: Deploy stealth-announcer ──────────────────────────────
#[tokio::test]
async fn test_01_deploy_announcer() {
// Deploy contract to futurenet, assert contract ID returned
// Uses stellar/deploy.sh internally
println!("TODO: deploy stealth-announcer and assert contract ID");
}

// ── Scenario 2: Register stealth meta-address ─────────────────────────
#[tokio::test]
async fn test_02_register_meta_address() {
println!("TODO: register 64-byte stealth meta-address, assert stored");
}

// ── Scenario 3: Send stealth payment ──────────────────────────────────
#[tokio::test]
async fn test_03_stealth_send() {
println!("TODO: send token to stealth address, assert announcement event");
}

// ── Scenario 4: Scan for announcements ────────────────────────────────
#[tokio::test]
async fn test_04_scan_announcements() {
println!("TODO: getEvents for announcer contract, assert event count");
}

// ── Scenario 5: Withdraw from stealth address ─────────────────────────
#[tokio::test]
async fn test_05_withdraw() {
println!("TODO: withdraw token from stealth address, assert balance");
}

// ── Scenario 6: Register wraith name ──────────────────────────────────
#[tokio::test]
async fn test_06_name_register() {
println!("TODO: register 'alice.wraith', assert resolve works");
}

// ── Scenario 7: Resolve wraith name ───────────────────────────────────
#[tokio::test]
async fn test_07_name_resolve() {
println!("TODO: resolve 'alice.wraith', assert returns meta-address");
}

// ── Scenario 8: Release wraith name ───────────────────────────────────
#[tokio::test]
async fn test_08_name_release() {
println!("TODO: release 'alice.wraith', assert no longer resolvable");
}
}
8 changes: 8 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# CI and automation are maintainer-owned.
# A pull request that touches these paths needs maintainer approval before it
# can merge. Everything else merges as normal.
#
# This exists because contributors have repeatedly edited workflow files to make
# their own failing checks pass, which silently weakens CI for everyone.

/.github/ @truthixify
26 changes: 26 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Proposes bumps for the pinned CI and container inputs. Every proposal goes
# through the re-audit checklist in SUPPLY_CHAIN.md before merge.
version: 2
updates:
- package-ecosystem: github-actions
directory: /
target-branch: develop
schedule:
interval: weekly
groups:
github-actions:
patterns: ['*']
commit-message:
prefix: chore
include: scope

- package-ecosystem: docker
directories:
- /stellar/build
- /stellar/examples/indexer
target-branch: develop
schedule:
interval: weekly
commit-message:
prefix: chore
include: scope
247 changes: 247 additions & 0 deletions .github/scripts/check_supply_chain_pins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
#!/usr/bin/env python3
"""Enforce the pinning rules in SUPPLY_CHAIN.md for CI and release inputs.

Checks every workflow under .github/workflows and every tracked Dockerfile:

* `uses:` references a full 40-character commit SHA with a `# vX.Y.Z` comment
(local `./` actions are exempt; `docker://` images need an @sha256 digest).
* `runs-on:` names a fixed runner image, not a `-latest` alias.
* Toolchain-installing actions receive an explicit, exact version input.
* `cargo install` uses `--locked` and an exact `--version`.
* Nothing is piped from the network straight into a shell.
* Downloaded release archives are checked with `sha256sum -c`.
* Dockerfile `FROM` lines carry an @sha256 digest.
* Lockfiles resolve only from crates.io and registry.npmjs.org.

Stdlib only, so it runs on a bare runner. Findings are printed as GitHub
annotations and the script exits non-zero if there are any.
"""

import re
import subprocess
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parents[2]

SHA_REF = re.compile(r"^[A-Za-z0-9_.-]+/[A-Za-z0-9_./-]+@[0-9a-f]{40}$")
USES = re.compile(r"^\s*(?:-\s+)?uses:\s*([^\s#]+)\s*(?:#\s*(\S.*))?$")
RUNS_ON = re.compile(r"^\s*runs-on:\s*(\S+)")
STEP_START = re.compile(r"^(\s*)-\s+\S")
WITH_KEY = re.compile(r"^\s+([A-Za-z0-9_-]+):\s*['\"]?([^'\"#]*?)['\"]?\s*(?:#.*)?$")
ENV_REF = re.compile(r"^\$\{\{\s*env\.([A-Z0-9_]+)\s*\}\}$")
EXACT_VERSION = re.compile(r"^v?\d+\.\d+\.\d+$|^nightly-\d{4}-\d{2}-\d{2}$")
PIPE_TO_SHELL = re.compile(r"\|\s*(?:sudo\s+)?(?:ba|z)?sh\b")
ARCHIVE_DOWNLOAD = re.compile(r"\b(?:curl|wget)\b.*\.(?:tar\.gz|tgz|tar\.xz|zip)\b")
CARGO_INSTALL = re.compile(r"\bcargo install\b")
CARGO_EXACT = re.compile(r"--version[= ]['\"]?=?\S*\d+\.\d+\.\d+")

# Inputs that select a tool version. Each must be present and exact.
REQUIRED_INPUTS = {
"dtolnay/rust-toolchain": ["toolchain"],
"actions/setup-node": ["node-version"],
"foundry-rs/foundry-toolchain": ["version"],
"crytic/slither-action": ["slither-version", "solc-version"],
"model-checking/kani-github-action": ["kani-version"],
"heyAyushh/setup-anchor": ["anchor-version", "solana-cli-version", "node-version"],
"sigstore/cosign-installer": ["cosign-release"],
}

findings = []


def report(path, line, message):
rel = path.relative_to(ROOT)
findings.append(f"::error file={rel},line={line}::{message}")


def workflow_env(lines):
env = {}
for line in lines:
m = re.match(r"^\s+([A-Z][A-Z0-9_]*):\s*['\"]?([^'\"#\s]+)", line)
if m:
env.setdefault(m.group(1), m.group(2))
return env


def step_blocks(lines):
"""Yield (start_line_no, [lines]) for each `- ...` list item."""
i = 0
while i < len(lines):
m = STEP_START.match(lines[i])
if not m:
i += 1
continue
indent = len(m.group(1))
j = i + 1
while j < len(lines):
stripped = lines[j].strip()
if stripped and len(lines[j]) - len(lines[j].lstrip()) <= indent:
break
j += 1
yield i + 1, lines[i:j]
i = j


def expand(text, env):
text = re.sub(r"\$\{\{\s*env\.([A-Z0-9_]+)\s*\}\}", lambda m: env.get(m.group(1), m.group(0)), text)
return re.sub(r"\$\{?([A-Z][A-Z0-9_]*)\}?", lambda m: env.get(m.group(1), m.group(0)), text)


def logical_lines(text_lines):
"""Join shell `\\` continuations, keeping the first physical line number."""
buf, first = [], 0
for offset, line in enumerate(text_lines):
if not buf:
first = offset
if line.lstrip().startswith("#") and not buf:
continue
stripped = line.rstrip()
if stripped.endswith("\\"):
buf.append(stripped[:-1])
continue
buf.append(line)
yield first, " ".join(part.strip() for part in buf)
buf = []
if buf:
yield first, " ".join(part.strip() for part in buf)


def check_run_text(path, start, text_lines, env):
block = "\n".join(text_lines)
for offset, code in logical_lines(text_lines):
code = expand(code, env)
if PIPE_TO_SHELL.search(code) and re.search(r"\b(curl|wget)\b", code):
report(path, start + offset, "network download piped into a shell; download, verify the checksum, then run")
if CARGO_INSTALL.search(code):
if "--locked" not in code:
report(path, start + offset, "cargo install without --locked")
if not CARGO_EXACT.search(code):
report(path, start + offset, "cargo install without an exact --version")
if ARCHIVE_DOWNLOAD.search(code) and "sha256sum -c" not in block:
report(path, start + offset, "release archive downloaded without a sha256sum -c check")


def check_workflow(path):
lines = path.read_text(encoding="utf-8").splitlines()
env = workflow_env(lines)

for no, line in enumerate(lines, 1):
m = RUNS_ON.match(line)
if m and m.group(1).endswith("-latest"):
report(path, no, f"runs-on '{m.group(1)}' floats; use a fixed runner image")

for start, block in step_blocks(lines):
uses = None
for offset, line in enumerate(block):
m = USES.match(line)
if m:
uses, comment, uses_line = m.group(1), m.group(2), start + offset
break
if uses is None:
check_run_text(path, start, block, env)
continue

if uses.startswith("./"):
continue
if uses.startswith("docker://"):
if "@sha256:" not in uses:
report(path, uses_line, f"{uses} is not pinned to an @sha256 digest")
continue
if not SHA_REF.match(uses):
report(path, uses_line, f"{uses} is not pinned to a full commit SHA")
continue
if not comment:
report(path, uses_line, f"{uses} needs a trailing '# <version>' comment")

action = "/".join(uses.split("@", 1)[0].split("/")[:2])
if action not in REQUIRED_INPUTS:
continue
inputs = {}
for line in block:
wm = WITH_KEY.match(line)
if wm:
inputs[wm.group(1)] = wm.group(2).strip()
for key in REQUIRED_INPUTS[action]:
value = inputs.get(key)
if value is None:
report(path, uses_line, f"{action} needs an explicit '{key}' input")
continue
em = ENV_REF.match(value)
if em:
value = env.get(em.group(1), "")
if not EXACT_VERSION.match(value):
report(path, uses_line, f"{action} '{key}: {value}' is not an exact version")


def check_dockerfile(path):
lines = path.read_text(encoding="utf-8").splitlines()
env = {}
for line in lines:
m = re.match(r"^\s*(?:ARG|ENV)\s+([A-Z][A-Z0-9_]*)=['\"]?([^'\"\s]+)", line)
if m:
env.setdefault(m.group(1), m.group(2))
for no, line in enumerate(lines, 1):
parts = line.split()
if parts and parts[0].upper() == "FROM":
image = next((p for p in parts[1:] if not p.startswith("--")), "")
if image != "scratch" and "@sha256:" not in image:
report(path, no, f"base image '{image}' is not pinned to an @sha256 digest")
check_run_text(path, 1, lines, env)


CRATES_IO = {
"registry+https://github.com/rust-lang/crates.io-index",
"sparse+https://index.crates.io/",
}


def check_lockfile(path):
lines = path.read_text(encoding="utf-8").splitlines()
for no, line in enumerate(lines, 1):
if path.name == "Cargo.lock":
m = re.match(r'^source = "([^"#]+)', line)
if m and m.group(1) not in CRATES_IO:
report(path, no, f"crate resolved from '{m.group(1)}', not crates.io")
elif path.name == "package-lock.json":
m = re.search(r'"resolved":\s*"([^"]+)"', line)
if m and not m.group(1).startswith("https://registry.npmjs.org/"):
report(path, no, f"package resolved from '{m.group(1)}', not registry.npmjs.org")
elif path.name == "pnpm-lock.yaml":
if re.search(r"\btarball:|git\+|codeload\.github\.com", line):
report(path, no, "package resolved from a tarball or git URL, not registry.npmjs.org")


def tracked(pattern):
out = subprocess.run(
["git", "ls-files", "--", pattern], cwd=ROOT, check=True, capture_output=True, text=True
).stdout
return [ROOT / p for p in out.splitlines() if p]


def main():
workflows = sorted((ROOT / ".github" / "workflows").glob("*.y*ml"))
dockerfiles = sorted(set(tracked("*Dockerfile*")))
for path in workflows:
check_workflow(path)
for path in dockerfiles:
check_dockerfile(path)
lockfiles = sorted(
set(tracked("*Cargo.lock") + tracked("*package-lock.json") + tracked("*pnpm-lock.yaml"))
)
for path in lockfiles:
check_lockfile(path)

if findings:
print("\n".join(findings))
print(f"\n{len(findings)} supply-chain pinning violation(s). See SUPPLY_CHAIN.md.")
return 1
print(
f"Checked {len(workflows)} workflows, {len(dockerfiles)} Dockerfiles and "
f"{len(lockfiles)} lockfiles: all inputs pinned."
)
return 0


if __name__ == "__main__":
sys.exit(main())
Loading
Loading