diff --git a/.github/trigger-deploy b/.github/trigger-deploy index 5aef4763..3a71c762 100644 --- a/.github/trigger-deploy +++ b/.github/trigger-deploy @@ -3,3 +3,4 @@ 2026-07-17T17:20:00Z deploy manifest-merge + alias collapse 2026-07-17T18:00:00Z deploy price tiebreak 2026-07-18T02:00:00Z deploy wish-bridge qualified-demand gate +2026-07-18T02:45:00Z deploy operator demand board diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml new file mode 100644 index 00000000..70871b52 --- /dev/null +++ b/.github/workflows/secret-scan.yml @@ -0,0 +1,38 @@ +# Always-on secret scanning. Unlike deploy.yml (marker-gated), this runs on +# EVERY push to a tracked branch and EVERY pull request — a committed +# credential should never depend on remembering a marker. gitleaks scans the +# working tree against its default high-signal ruleset (OpenAI sk- keys, +# GitHub/AWS tokens, private keys, mnemonics, ...) plus the repo allowlist in +# .gitleaks.toml, which suppresses this repo's structural false positives +# (public on-chain addresses, the demo JWT, test canaries). Only a genuinely +# new secret fails the job. +name: secret-scan + +on: + push: + branches: ["claude/sweet-brown-i99jl3", "main"] + pull_request: + +permissions: + contents: read + +jobs: + gitleaks: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd + - name: Scan for committed secrets (gitleaks, pinned + checksum-verified) + env: + GITLEAKS_VERSION: "8.21.2" + run: | + set -euo pipefail + FN="gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" + BASE="https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}" + curl -sSL --fail -o "/tmp/${FN}" "${BASE}/${FN}" + curl -sSL --fail -o /tmp/gitleaks_checksums.txt "${BASE}/gitleaks_${GITLEAKS_VERSION}_checksums.txt" + ( cd /tmp && grep " ${FN}\$" gitleaks_checksums.txt | sha256sum -c - ) + tar -xzf "/tmp/${FN}" -C /tmp gitleaks + # Tree scan (--no-git): fails the job on any finding not allowlisted + # in .gitleaks.toml. --redact keeps any match out of the public logs. + /tmp/gitleaks detect --no-git --config .gitleaks.toml --redact --verbose diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 00000000..9109dc96 --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,39 @@ +# gitleaks config for Agent402. Extends the default ruleset (which catches +# real high-signal secrets: OpenAI sk- keys, GitHub tokens, AWS keys, private +# keys, mnemonics, etc.) and allowlists the structural false positives this +# repo carries by design, so CI stays green until a GENUINELY new secret lands. +# +# Every allowlist entry below was verified against a full-tree + full-history +# scan (2026-07-18): all pre-existing hits are public on-chain addresses, the +# standard demo JWT, or fake test/canary fixtures. Real secrets live only in +# Railway env and GitHub Actions secrets, never in the repo. +[extend] +useDefault = true + +[allowlist] +description = "Agent402 known false positives: on-chain addresses, demo JWTs, test fixtures" +# Fixtures and copy that intentionally contain fake or public credential-shaped +# strings. Test files assert on canaries by design; docs carry example tokens. +paths = [ + '''scripts/test-.*\.js''', + '''docs/.*''', + '''package-lock\.json''', + '''\.gitleaks\.toml''', +] +# Matched against each finding's captured secret. +regexes = [ + # EVM contract/wallet addresses are public identifiers, never secrets. This + # is 40 hex chars precisely; a real EVM private key is 64 hex and is NOT + # covered here, so it would still fire. + '''0x[0-9a-fA-F]{40}\b''', + # The leak-guard test's own canary tokens (e.g. fredv2-LEAKCANARY0000). + '''LEAKCANARY''', + # Placeholder KDF-output example in the crypto-hash tool docs. + '''a1b2c3d4e5f6''', +] +# The standard demo JWT ({"alg":"HS256","typ":"JWT"} header) used as the +# decode-jwt tool's worked example in kit.js / kit2.js / skills.js. Stopwords +# match when the secret contains the substring. +stopwords = [ + '''eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9''', +]