Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions .github/workflows/cli-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,16 @@ jobs:
run: |
curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \
| tar -xz gitleaks
./gitleaks git . --redact --verbose --no-banner
# --log-opts=HEAD scopes the scan to commits reachable from what's
# checked out: the whole history of this branch (or of the PR merge
# commit, i.e. base + PR commits), but NOT unrelated branches.
# `fetch-depth: 0` fetches refs/heads/* — every branch — and gitleaks
# otherwise scans all of them, so an open branch that legitimately
# commits a high-entropy value plus its own .gitleaks.toml allowlist
# would fail every OTHER branch's scan, which is judged against the
# allowlist at its own tip. Each branch is still fully scanned by its
# own PR, and pushes to dev/production scan their full history.
./gitleaks git . --redact --verbose --no-banner --log-opts=HEAD

lint-and-test:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -68,13 +77,13 @@ jobs:
/api/swagger.json

- name: Setup pnpm
uses: pnpm/action-setup@v6
uses: pnpm/action-setup@v6.0.9
with:
version: 10
run_install: false

- name: Setup Node.js
uses: actions/setup-node@v6
uses: actions/setup-node@v7
with:
node-version: '22'
cache: 'pnpm'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/npm-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ jobs:
- uses: actions/checkout@v7
# Setup .npmrc file to publish to npm
- name: Setup pnpm
uses: pnpm/action-setup@v6
uses: pnpm/action-setup@v6.0.9
with:
run_install: false

- uses: actions/setup-node@v6
- uses: actions/setup-node@v7
with:
node-version: '22.x'
registry-url: 'https://registry.npmjs.org'
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/release-binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,11 @@ jobs:
- uses: actions/checkout@v7

- name: Setup pnpm
uses: pnpm/action-setup@v6
uses: pnpm/action-setup@v6.0.9
with:
run_install: false

- uses: actions/setup-node@v6
- uses: actions/setup-node@v7
with:
node-version: '22.x'
cache: 'pnpm'
Expand Down
29 changes: 21 additions & 8 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
# Gitleaks configuration — extends the default ruleset.
#
# The only allowlisted secrets are the two PUBLIC Supabase anon keys committed
# in src/config/environments.ts. Those JWTs are anon-role keys, designed to be
# embedded in client code and gated by RLS (see the doc comment in that file) —
# they are intentionally not secret.
# The only allowlisted secrets are PUBLIC key material committed in
# src/config/environments.ts:
# - the two Supabase anon keys — anon-role JWTs, designed to be embedded in
# client code and gated by RLS (see the doc comment in that file).
# - the two KEK public keys (prod + dev) for client-side binary envelope
# encryption — base64 of the raw 32-byte X25519 PUBLIC half. They can only
# *encrypt*; the private halves live solely on the API, never in this repo.
# Both are intentionally not secret; gitleaks flags them on entropy alone
# (generic-api-key), not because it recognizes them as credentials.
#
# They are allowlisted by EXACT VALUE, deliberately not by file path or by the
# whole `jwt` rule: a Supabase service_role key is also a JWT, so a path/rule
# allowlist would let a genuinely sensitive key pasted into the same file slip
# through. Matching exact values keeps that detection intact.
# whole `jwt` / `generic-api-key` rule: a Supabase service_role key is also a
# JWT, and a KEK *private* key is the same shape as its public half, so a
# path/rule allowlist would let a genuinely sensitive key pasted into the same
# file slip through. Matching exact values keeps that detection intact.
#
# When a KEK is rotated, replace the corresponding value below — do not simply
# append, or the retired key stops being distinguishable from a live secret.
[extend]
useDefault = true

[allowlist]
description = "Public Supabase anon keys (safe to commit, gated by RLS)"
description = "Public Supabase anon keys and KEK public keys (safe to commit)"
regexes = [
'''eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InBneWRucGhiaW1ldGluc2dma2JvIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDc1OTQzNDYsImV4cCI6MjAyMzE3MDM0Nn0\.hAYOMFxxwX1exkQkY9xyQJGC_GhGnyogkj2N-kBkMI8''',
'''eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9\.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImxibXNvd2VodGp3bnFsdXJwZW1iIiwicm9sZSI6ImFub24iLCJpYXQiOjE3MDkyMTg0ODcsImV4cCI6MjAyNDc5NDQ4N30\.zeLTMAuZ_WwYvGdeP0kdvL_Zrs-RQee5APPyxmWq7qQ''',
# prod kekPublicKey v1
'''wtfyWEwK7nJzwI4PD\+9RAW8jxIR1u8kMQq2IhsrVnH4=''',
# dev kekPublicKey v1
'''RgcToF/OJpcQI9koYvSvtj/WLaebfcN4v5GJoqtr/00=''',
]
13 changes: 7 additions & 6 deletions eslint.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,9 @@

const js = require('@eslint/js');
const tseslint = require('typescript-eslint');
// These plugins ship as ESM with a `default` export under CJS interop.
// This plugin ships as ESM with a `default` export under CJS interop.
const unicornPlugin =
require('eslint-plugin-unicorn').default ?? require('eslint-plugin-unicorn');
const importPlugin =
require('eslint-plugin-import').default ?? require('eslint-plugin-import');

module.exports = tseslint.config(
{
Expand All @@ -23,12 +21,15 @@ module.exports = tseslint.config(
js.configs.recommended,
...tseslint.configs.recommended,
{
// `unicorn` and `import` are only registered so legacy
// `unicorn` is only registered so legacy
// `// eslint-disable-next-line unicorn/...` comments scattered through
// the source resolve. We don't enable any rules from them.
// the source resolve. We don't enable any rules from it.
// `eslint-plugin-import` used to be registered here for the same reason,
// but it was dropped: it dragged in minimatch@3 -> brace-expansion@1.x,
// which has an unpatched DoS advisory (GHSA-mh99-v99m-4gvg, no 1.x
// backport) and failed `pnpm audit`. No rules from it were ever enabled.
plugins: {
unicorn: unicornPlugin,
import: importPlugin,
},
languageOptions: {
ecmaVersion: 2022,
Expand Down
19 changes: 13 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
"@modelcontextprotocol/sdk": "^1.29.0",
"@supabase/supabase-js": "^2.108.2",
"bplist-parser": "^0.3.2",
"chalk": "^5.6.2",
"chalk": "^6.0.0",
"citty": "^0.2.2",
"js-yaml": "^5.0.0",
"js-yaml": "^5.2.2",
"node-apk": "^1.2.1",
"node-stream-zip": "^1.15.0",
"plist": "^5.0.0",
Expand All @@ -31,8 +31,7 @@
"chai": "^6.2.2",
"eslint": "^10.5.0",
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-unicorn": "^69.0.0",
"eslint-plugin-unicorn": "^72.0.0",
"husky": "^9.1.7",
"mocha": "^11.7.6",
"prettier": "^3.8.4",
Expand Down Expand Up @@ -87,6 +86,7 @@
"overrides": {
"js-yaml@<3.14.2": ">=3.14.2",
"js-yaml@>=4.0.0 <4.2.0": ">=4.2.0",
"js-yaml@>=5.0.0 <5.2.2": ">=5.2.2",
"tar@<7.5.16": ">=7.5.16",
"@isaacs/brace-expansion": ">=5.0.1",
"fast-xml-parser": ">=5.5.7",
Expand All @@ -103,13 +103,20 @@
"ajv@<7.0.0": "6.14.0",
"diff@>=4.0.0 <6.0.0": "4.0.4",
"diff@>=6.0.0": "8.0.3",
"brace-expansion@<1.1.13": "1.1.13",
"brace-expansion@<1.1.16": "1.1.16",
"brace-expansion@>=2.0.0 <2.0.3": "2.0.3",
"brace-expansion@>=4.0.0 <5.0.6": "5.0.6",
"brace-expansion@>=3.0.0 <5.0.9": "5.0.9",
"ws@>=8.0.0 <8.21.0": "8.21.0",
"esbuild@<0.28.1": ">=0.28.1",
"fast-uri@>=3.0.0 <3.1.5": "3.1.5",
"hono@>=4.0.0 <4.12.34": "4.12.34",
"micromatch>picomatch": "^2.3.2",
"tinyglobby>picomatch": "^4.0.4"
},
"auditConfig": {
"ignoreGhsas": [
"GHSA-frvp-7c67-39w9"
]
}
}
}
Loading
Loading