Surfaced while triaging pip-audit findings (PR #123).
Problem
The .github/workflows/integration-nightly.yml workflow exists and the cron has been firing nightly, but it silently no-ops because KALSHI_KEY_ID is not configured as a repo secret:
```yaml
if [ -z "${KALSHI_KEY_ID}" ]; then
echo "KALSHI_KEY_ID secret is not set; skipping integration job."
echo "has_secrets=false" >> "$GITHUB_OUTPUT"
fi
```
The job exits "success" with zero work done. Looking at gh run list shows ~1 actual cron run; subsequent runs are silently skipped. We've had no CI signal on demo-API behavior since v1.0.
Meanwhile, running uv run pytest tests/integration/ locally exposes 11 failing tests that have been silently failing.
Action items
1. Configure secrets (you, not Claude)
```bash
gh secret set KALSHI_KEY_ID --repo TexasCoding/kalshi-python-sdk --body ""
gh secret set KALSHI_PRIVATE_KEY --repo TexasCoding/kalshi-python-sdk < /path/to/demo-key.pem
```
2. Fail loud when secrets are absent
Today the guard step quietly sets has_secrets=false and other steps just skip. Replace with a hard fail if the repo is the canonical one (so the nightly cron screams when secrets disappear), keeping the soft-skip only for forks.
3. Triage the 11 failing tests
```
tests/integration/test_account.py::TestAccountSync::test_limits
tests/integration/test_account.py::TestAccountAsync::test_limits
tests/integration/test_errors.py::TestErrorPaths::test_bad_auth_returns_auth_error
tests/integration/test_order_groups.py::TestOrderGroupsSync::test_create_and_get
tests/integration/test_order_groups.py::TestOrderGroupsSync::test_update_limit
tests/integration/test_orders.py::TestOrdersSync::test_order_fill_lifecycle
tests/integration/test_orders.py::TestOrdersSync::test_create_get_cancel
tests/integration/test_orders.py::TestOrdersAsync::test_create_get_cancel
tests/integration/test_search.py::TestSearchSync::test_tags_by_categories
tests/integration/test_search.py::TestSearchAsync::test_tags_by_categories
tests/integration/test_subaccounts.py::TestSubaccountsSync::test_list_balances_reflects_ephemeral_subaccount
```
Categorize each as one of:
- Real bug in SDK (e.g.
test_bad_auth_returns_auth_error doesn't raise — likely upstream made the endpoint unauthenticated; test needs to pick an actually-auth-gated endpoint like portfolio.balance())
- Demo state issue (account-specific data assumption)
- Spec drift (response shape changed; SDK model needs update)
- Test brittleness (timing, ordering)
4. Lifecycle commitment
Each new resource/method added to the SDK should ship with at least one integration test that exercises the happy path against demo. Add to the "Adding a new resource" checklist in CLAUDE.md.
Scope
- This is a meta-issue. Sub-issues per failing test can be split out as scope is decided.
- Wave 2 (test coverage backfill) was queued next; the systemic gap above is more important to address first.
Surfaced while triaging pip-audit findings (PR #123).
Problem
The
.github/workflows/integration-nightly.ymlworkflow exists and the cron has been firing nightly, but it silently no-ops becauseKALSHI_KEY_IDis not configured as a repo secret:```yaml
if [ -z "${KALSHI_KEY_ID}" ]; then
echo "KALSHI_KEY_ID secret is not set; skipping integration job."
echo "has_secrets=false" >> "$GITHUB_OUTPUT"
fi
```
The job exits "success" with zero work done. Looking at
gh run listshows ~1 actual cron run; subsequent runs are silently skipped. We've had no CI signal on demo-API behavior since v1.0.Meanwhile, running
uv run pytest tests/integration/locally exposes 11 failing tests that have been silently failing.Action items
1. Configure secrets (you, not Claude)
```bash
gh secret set KALSHI_KEY_ID --repo TexasCoding/kalshi-python-sdk --body ""
gh secret set KALSHI_PRIVATE_KEY --repo TexasCoding/kalshi-python-sdk < /path/to/demo-key.pem
```
2. Fail loud when secrets are absent
Today the guard step quietly sets
has_secrets=falseand other steps just skip. Replace with a hard fail if the repo is the canonical one (so the nightly cron screams when secrets disappear), keeping the soft-skip only for forks.3. Triage the 11 failing tests
```
tests/integration/test_account.py::TestAccountSync::test_limits
tests/integration/test_account.py::TestAccountAsync::test_limits
tests/integration/test_errors.py::TestErrorPaths::test_bad_auth_returns_auth_error
tests/integration/test_order_groups.py::TestOrderGroupsSync::test_create_and_get
tests/integration/test_order_groups.py::TestOrderGroupsSync::test_update_limit
tests/integration/test_orders.py::TestOrdersSync::test_order_fill_lifecycle
tests/integration/test_orders.py::TestOrdersSync::test_create_get_cancel
tests/integration/test_orders.py::TestOrdersAsync::test_create_get_cancel
tests/integration/test_search.py::TestSearchSync::test_tags_by_categories
tests/integration/test_search.py::TestSearchAsync::test_tags_by_categories
tests/integration/test_subaccounts.py::TestSubaccountsSync::test_list_balances_reflects_ephemeral_subaccount
```
Categorize each as one of:
test_bad_auth_returns_auth_errordoesn't raise — likely upstream made the endpoint unauthenticated; test needs to pick an actually-auth-gated endpoint likeportfolio.balance())4. Lifecycle commitment
Each new resource/method added to the SDK should ship with at least one integration test that exercises the happy path against demo. Add to the "Adding a new resource" checklist in
CLAUDE.md.Scope