From 7f876cce32a11c4ca0943d7aa07981fd45d7cda6 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Sat, 23 May 2026 17:42:03 +1200 Subject: [PATCH 1/4] debug: print SYNC_DOCS_TOKEN fingerprint in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI keeps failing ls-remote (falls back to voice@main) while the same token works locally. Add a one-off debug step printing length, prefix, suffix, and sha256 first-16 of the token, plus a direct ls-remote test — so we can compare CI's secret value to the local working one. To be reverted once we identify the mismatch. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ff4df8..0feb379 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,29 @@ jobs: - run: npm ci + - name: Debug SYNC_DOCS_TOKEN + env: + SYNC_DOCS_TOKEN: ${{ secrets.SYNC_DOCS_TOKEN }} + run: | + if [ -z "$SYNC_DOCS_TOKEN" ]; then + echo "SYNC_DOCS_TOKEN is EMPTY or UNSET" + exit 0 + fi + LEN=${#SYNC_DOCS_TOKEN} + PREFIX="${SYNC_DOCS_TOKEN:0:12}" + SUFFIX="${SYNC_DOCS_TOKEN: -4}" + # SHA256 of the token — full hash is irreversible, lets you fingerprint + # against the local value (echo -n "$YOUR_TOKEN" | sha256sum). + HASH=$(printf '%s' "$SYNC_DOCS_TOKEN" | sha256sum | cut -c1-16) + echo "length: $LEN" + echo "prefix: $PREFIX..." + echo "suffix: ...$SUFFIX" + echo "sha256-16: $HASH" + echo "--- git ls-remote direct test ---" + git ls-remote --tags --refs \ + "https://x-access-token:${SYNC_DOCS_TOKEN}@github.com/wavekat/wavekat-voice.git" \ + 2>&1 | head -3 || echo "ls-remote exit: $?" + - run: npm run cf:build env: SYNC_DOCS_TOKEN: ${{ secrets.SYNC_DOCS_TOKEN }} From b9a7dd144af8fe8a2d6b96ca51a9215a30e71caa Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Sat, 23 May 2026 17:45:06 +1200 Subject: [PATCH 2/4] debug: expand runner-side diagnostics for sync-docs Token sha256 matches local byte-for-byte, so bug is runner-side. Print system+global git config, egress IP, REST API check via curl, verbose git ls-remote, and an alt URL format (oauth2:) to identify which layer is rejecting the request. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 40 ++++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0feb379..8a0bf61 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,20 +28,36 @@ jobs: echo "SYNC_DOCS_TOKEN is EMPTY or UNSET" exit 0 fi - LEN=${#SYNC_DOCS_TOKEN} - PREFIX="${SYNC_DOCS_TOKEN:0:12}" - SUFFIX="${SYNC_DOCS_TOKEN: -4}" - # SHA256 of the token — full hash is irreversible, lets you fingerprint - # against the local value (echo -n "$YOUR_TOKEN" | sha256sum). HASH=$(printf '%s' "$SYNC_DOCS_TOKEN" | sha256sum | cut -c1-16) - echo "length: $LEN" - echo "prefix: $PREFIX..." - echo "suffix: ...$SUFFIX" - echo "sha256-16: $HASH" - echo "--- git ls-remote direct test ---" - git ls-remote --tags --refs \ + echo "sha256-16: $HASH (expect bb73f9330ae3aa1b)" + echo + echo "--- git --version ---" + git --version + echo + echo "--- git config --system --list ---" + git config --system --list 2>&1 || echo "(none)" + echo + echo "--- git config --global --list ---" + git config --global --list 2>&1 || echo "(none)" + echo + echo "--- public egress IP ---" + curl -fsS https://api.ipify.org && echo + echo + echo "--- REST API with token (curl) ---" + curl -sS -o /dev/null -w "HTTP %{http_code}\n" \ + -H "Authorization: Bearer $SYNC_DOCS_TOKEN" \ + -H "Accept: application/vnd.github+json" \ + https://api.github.com/repos/wavekat/wavekat-voice + echo + echo "--- git ls-remote with x-access-token: ---" + GIT_TRACE=1 GIT_CURL_VERBOSE=1 git ls-remote --tags --refs \ "https://x-access-token:${SYNC_DOCS_TOKEN}@github.com/wavekat/wavekat-voice.git" \ - 2>&1 | head -3 || echo "ls-remote exit: $?" + 2>&1 | grep -Ev "(SYNC_DOCS_TOKEN|x-access-token|github_pat_)" | head -40 || true + echo + echo "--- git ls-remote with oauth2: ---" + git ls-remote --tags --refs \ + "https://oauth2:${SYNC_DOCS_TOKEN}@github.com/wavekat/wavekat-voice.git" \ + 2>&1 | head -3 || echo "(exit $?)" - run: npm run cf:build env: From e94f759e430be2bc40adcec0a7eadea617532e4c Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Sat, 23 May 2026 17:47:59 +1200 Subject: [PATCH 3/4] debug: test Bearer extraheader auth (vs Basic URL creds) --- .github/workflows/ci.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a0bf61..cd60bf0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -58,6 +58,12 @@ jobs: git ls-remote --tags --refs \ "https://oauth2:${SYNC_DOCS_TOKEN}@github.com/wavekat/wavekat-voice.git" \ 2>&1 | head -3 || echo "(exit $?)" + echo + echo "--- git ls-remote with Bearer extraheader (no URL creds) ---" + git -c http.https://github.com/.extraheader="Authorization: Bearer ${SYNC_DOCS_TOKEN}" \ + ls-remote --tags --refs \ + https://github.com/wavekat/wavekat-voice.git \ + 2>&1 | head -5 || echo "(exit $?)" - run: npm run cf:build env: From 8b9b8c66c73ba202204e34efb946750dc74a1363 Mon Sep 17 00:00:00 2001 From: Eason WaveKat Date: Sat, 23 May 2026 17:51:31 +1200 Subject: [PATCH 4/4] ci: disable persist-credentials on checkout for private docs sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit actions/checkout@v4 was setting a local repo http.extraheader using the default repo-scoped GITHUB_TOKEN, which overrode the SYNC_DOCS_TOKEN embedded in URLs by scripts/sync-docs.js — so every clone of the private wavekat-voice repo authenticated as the (unauthorized) default token and got "Repository not found", silently falling back to main. persist-credentials: false stops checkout from setting that header. The wavekat-brand submodule is public so it still resolves without auth. No other steps in these workflows need the persisted creds. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/ci.yml | 46 +---------------------------------- .github/workflows/preview.yml | 1 + .github/workflows/release.yml | 1 + 3 files changed, 3 insertions(+), 45 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd60bf0..3c5c516 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + persist-credentials: false - uses: actions/setup-node@v4 with: @@ -20,51 +21,6 @@ jobs: - run: npm ci - - name: Debug SYNC_DOCS_TOKEN - env: - SYNC_DOCS_TOKEN: ${{ secrets.SYNC_DOCS_TOKEN }} - run: | - if [ -z "$SYNC_DOCS_TOKEN" ]; then - echo "SYNC_DOCS_TOKEN is EMPTY or UNSET" - exit 0 - fi - HASH=$(printf '%s' "$SYNC_DOCS_TOKEN" | sha256sum | cut -c1-16) - echo "sha256-16: $HASH (expect bb73f9330ae3aa1b)" - echo - echo "--- git --version ---" - git --version - echo - echo "--- git config --system --list ---" - git config --system --list 2>&1 || echo "(none)" - echo - echo "--- git config --global --list ---" - git config --global --list 2>&1 || echo "(none)" - echo - echo "--- public egress IP ---" - curl -fsS https://api.ipify.org && echo - echo - echo "--- REST API with token (curl) ---" - curl -sS -o /dev/null -w "HTTP %{http_code}\n" \ - -H "Authorization: Bearer $SYNC_DOCS_TOKEN" \ - -H "Accept: application/vnd.github+json" \ - https://api.github.com/repos/wavekat/wavekat-voice - echo - echo "--- git ls-remote with x-access-token: ---" - GIT_TRACE=1 GIT_CURL_VERBOSE=1 git ls-remote --tags --refs \ - "https://x-access-token:${SYNC_DOCS_TOKEN}@github.com/wavekat/wavekat-voice.git" \ - 2>&1 | grep -Ev "(SYNC_DOCS_TOKEN|x-access-token|github_pat_)" | head -40 || true - echo - echo "--- git ls-remote with oauth2: ---" - git ls-remote --tags --refs \ - "https://oauth2:${SYNC_DOCS_TOKEN}@github.com/wavekat/wavekat-voice.git" \ - 2>&1 | head -3 || echo "(exit $?)" - echo - echo "--- git ls-remote with Bearer extraheader (no URL creds) ---" - git -c http.https://github.com/.extraheader="Authorization: Bearer ${SYNC_DOCS_TOKEN}" \ - ls-remote --tags --refs \ - https://github.com/wavekat/wavekat-voice.git \ - 2>&1 | head -5 || echo "(exit $?)" - - run: npm run cf:build env: SYNC_DOCS_TOKEN: ${{ secrets.SYNC_DOCS_TOKEN }} diff --git a/.github/workflows/preview.yml b/.github/workflows/preview.yml index 99bc9cd..4d880e1 100644 --- a/.github/workflows/preview.yml +++ b/.github/workflows/preview.yml @@ -15,6 +15,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + persist-credentials: false - uses: actions/setup-node@v4 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2b10351..bc58c84 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -27,6 +27,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + persist-credentials: false - uses: actions/setup-node@v4 with: