From 57c870596f7d5f3887a4613abf358853e55ac742 Mon Sep 17 00:00:00 2001 From: Pyronewbic Date: Thu, 14 May 2026 02:46:21 +0530 Subject: [PATCH 1/3] fix: pass alert_email secret to Terraform plan and apply --- .github/workflows/deploy.yml | 3 +++ .github/workflows/terraform.yml | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 95e0607..1b2182d 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -56,6 +56,9 @@ jobs: echo "digest=$DIGEST" >> "$GITHUB_OUTPUT" echo "Image digest: $DIGEST" + - name: Configure Docker auth for GCR + run: gcloud auth configure-docker --quiet + - uses: sigstore/cosign-installer@v3 - name: Sign image (keyless) diff --git a/.github/workflows/terraform.yml b/.github/workflows/terraform.yml index c7fabaa..031a110 100644 --- a/.github/workflows/terraform.yml +++ b/.github/workflows/terraform.yml @@ -43,6 +43,12 @@ jobs: run: terraform fmt -check -recursive working-directory: ${{ env.TF_DIR }} + - name: Write tfvars from secrets + run: | + cat > ${{ env.TF_DIR }}/ci.auto.tfvars <&1 | tee plan.txt @@ -93,6 +99,12 @@ jobs: run: terraform init -input=false working-directory: ${{ env.TF_DIR }} + - name: Write tfvars from secrets + run: | + cat > ${{ env.TF_DIR }}/ci.auto.tfvars < Date: Thu, 14 May 2026 02:51:37 +0530 Subject: [PATCH 2/3] sec: add CodeQL SAST scanning on PRs and weekly schedule --- .github/workflows/codeql.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 .github/workflows/codeql.yml diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..f1ab020 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,22 @@ +name: CodeQL +on: + pull_request: + branches: [main] + schedule: + - cron: "0 6 * * 1" + +permissions: + contents: read + security-events: write + +jobs: + analyze: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v5 + + - uses: github/codeql-action/init@v3 + with: + languages: javascript-typescript + + - uses: github/codeql-action/analyze@v3 From 66ba6a6f1dbd03cc8069a4b5b202cced161fa3df Mon Sep 17 00:00:00 2001 From: Pyronewbic Date: Thu, 14 May 2026 02:55:35 +0530 Subject: [PATCH 3/3] docs: security pipeline, set browser, collection tracking in changelog/README/internals - CHANGELOG: set browser, collection tracking, Sigstore, SBOM, Grype, Binary Auth, CodeQL, Terraform CI, security fixes - README: security section with signing, SBOM, scanning, SAST - Internals: security pipeline table with tool/stage/purpose --- CHANGELOG.md | 19 ++++++++++++++++++- README.md | 10 ++++++++++ docs/internals.md | 15 +++++++++++++++ 3 files changed, 43 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d6539f..4df9d34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,17 @@ ## Unreleased ### Added +- Set browser: GET /api/sets (238 sets with logos, era groups, card count breakdown) and GET /api/sets/:setCode (cards with rarity) +- Collection tracking: GET /api/portfolio/set/:setCode returns owned cardIds for progress bars and owned/missing indicators +- Set metadata from TCGdex: 236 named, 154 with logos, official/secret card count split +- Rarity data from TCGdex rarity-filter endpoints (~4K cards tagged: SAR, IR, UR, HR, SR, AR, RR, ACE, CR) +- Era classification: Scarlet & Violet, Sword & Shield, Sun & Moon, XY, Pokemon TCG Pocket, Diamond & Pearl, Black & White, Classic +- Sigstore container signing: cosign keyless signing via GitHub OIDC, deploy by image digest +- SBOM generation: Syft SPDX JSON uploaded as build artifact (90 day retention) +- Grype vulnerability scanning: SARIF report uploaded to GitHub Security tab +- Binary Authorization: DRYRUN audit policy on both Cloud Run services +- CodeQL SAST: static analysis on PRs + weekly schedule +- Terraform CI: plan posted as PR comment, auto-apply on merge to main - Card autocomplete: GET /api/autocomplete with TCGdex EN+JP database (29K cards), card preview images, EN→JP name mapping - Search filters: format (raw/slab), multi-select source pills, condition dropdown, slab provider+grade selectors - Autocomplete dropdown on dashboard: card thumbnails, card preview panel on hover, keyboard navigation @@ -77,7 +88,13 @@ - Card identity: cleaned up long names (strips pack names, condition text from titles) - track-prices: now also tracks cards from active alerts, not just 3 hardcoded defaults - Demo condition filter: checks detectedCondition in addition to raw condition field -- Tests: 290 total (128 unit + 88 API + 74 smoke), up from 183 +- Tests: 300 total (130 unit + 96 API + 74 smoke), up from 183 +- PR template: type, endpoints, checks, infrastructure, frontend impact, deploy notes +- Kaniko pinned to v1.23.2 with --reproducible builds, dual tags (latest + SHA) +- Deploy by image digest instead of :latest tag +- Health endpoint: eBay usage stats hidden from non-owner requests +- PSA endpoint: demo mode returns canned data (was making live API calls) +- All error responses use safeErrorMessage() (fixed 3 places leaking raw e.message) - AI grading prompts: full PSA rubric (5-10), perspective correction, per-corner/edge detail, holo-specific surface guidance - Demo grades re-evaluated with improved prompts (more conservative scores, honest confidence) - Removed dead code: Redis import from api.js, updateCardField from card-identity.js diff --git a/README.md b/README.md index 066c67a..2d780ac 100644 --- a/README.md +++ b/README.md @@ -170,6 +170,16 @@ curl "https://api.casecomp.xyz/api/portfolio/set/sv8a?demo=true" `GET /api/health` | `GET /api/demo` | `GET /api/sitemap` | `GET /api/autocomplete` | `GET /api/sets` | `GET /api/sets/:setCode` | `GET /docs` | `GET /docs/spec.json` | `?demo=true` (sample data) on search/sold/arbitrage/price-history +## Security + +- **Container signing** - Sigstore cosign keyless signing via GitHub OIDC, logged to Rekor transparency log +- **Deploy by digest** - immutable image SHA, not mutable `:latest` tag +- **SBOM** - Syft SPDX JSON generated per deploy, uploaded as build artifact +- **Vulnerability scanning** - Grype scans SBOM for CVEs, SARIF uploaded to GitHub Security tab +- **SAST** - CodeQL static analysis on every PR + weekly schedule +- **Binary Authorization** - GCP policy on both Cloud Run services (audit mode) +- **Reproducible builds** - Kaniko `--reproducible` flag, pinned version + ## Claude Code Skills **`/casecomp`** - search for cards in plain English. Claude parses intent and runs the CLI with the right flags. diff --git a/docs/internals.md b/docs/internals.md index 50571c2..c6e9f53 100644 --- a/docs/internals.md +++ b/docs/internals.md @@ -107,6 +107,21 @@ Use `--refresh` to delete all cache files before a run. 5. Overall = minimum of all subgrades (matches PSA methodology). 6. Falls back to single combined prompt for non-Claude providers or missing back image. +## Security pipeline + +Deploy workflow: Build (Kaniko) → Get digest → Sign (cosign keyless) → Deploy (by digest) → Scan (parallel). + +| Tool | Stage | What | +|------|-------|------| +| Kaniko v1.23.2 | Build | Pinned version, `--reproducible`, dual tags (latest + SHA) | +| Cosign | Post-build | Keyless signing via GitHub OIDC → Sigstore Rekor | +| Syft | Post-deploy | SBOM generation (SPDX JSON), 90-day artifact retention | +| Grype | Post-deploy | CVE scan from SBOM, SARIF → GitHub Security tab | +| CodeQL | PR + weekly | SAST for JavaScript/TypeScript | +| Binary Auth | Cloud Run | GCP policy, DRYRUN audit mode (logs unsigned deploys) | + +The scan job runs in parallel after deploy — adds zero time to the deploy critical path. CodeQL runs on PRs only (~60s). + ## Scheduled tasks Cloud Scheduler runs two jobs every 6 hours: