← Back to brief

reference hs auth state

memory · reference_hs_auth_state.md

TL;DR

The fortified CSRF path (2026-05-13)

Three layers of defense replaced what was previously a "hope it works" path:

Layer 1 — HS in the keep-alive prober fleet

Layer 2 — hs_auth_healthy() pre-flight in reconcilers

Three skills now call hs_auth_healthy() at the top of main() / reconcile():

Before this patch, a dead HS auth meant the reconcilers would load SoT, build Chrome state, then fail on the first HS call — burning ~30+ seconds before surfacing the issue. Now they abort within ~3 seconds and the heartbeat carries the right operator-action flag.

Layer 3 — CSRF retry-on-401 with tab refresh

hs_api_client._csrf_request now has a _retry_on_401 flag (default True). If the first call returns 401: 1. Force the HS tab to reload via window.location.reload() 2. Wait for document.readyState === 'complete' 3. Re-fire the call exactly once with _retry_on_401=False (bounded — no loops)

This catches the most common transient failure mode: csrf.app cookie aged out but the session is still valid. A page reload re-issues the cookie. Verified 2026-05-13 with a synthetic 401-injection test: bad CSRF → tab refresh → retry succeeds with status 200.

When PAT becomes available (future)

If Joseph's HS permissions change (promoted to Super Admin, or a new role is granted):

1. Verify access: navigate to https://app.hubspot.com/private-apps/23273108 — should show "Create a private app" button instead of "no permission" copy.
2. Create the app:
- Name: "SkyRun Ambient System"
- Scopes: crm.objects.contacts.read, crm.objects.contacts.write, crm.objects.deals.read, crm.objects.deals.write, crm.schemas.contacts.read
3. Copy the access token (one-time visibility — copy immediately)
4. Set in Keychain:


python3 ~/Library/Application\ Support/SkyRun/secrets.py set hubspot_pat "<token>"

5. Verify:

python3 ~/Library/Application\ Support/SkyRun/hs_api_client.py health

Should return auth_path: pat (was csrf).

After that, all HS-touching skills automatically prefer PAT and the Chrome dependency becomes a fallback only. The keep-alive prober continues to probe both paths.

Verification commands

bash

Probe HS auth right now

python3 ~/Library/Application\ Support/SkyRun/hs_api_client.py auth-healthy

Same via the full client

python3 ~/Library/Application\ Support/SkyRun/hs_api_client.py health

See HS in the keep-alive output

python3 ~/Library/Application\ Support/SkyRun/session_keep_alive.py cat ~/Library/Application\ Support/SkyRun/pwa/source_health.json | python3 -m json.tool | grep -A8 hubspot

Files touched 2026-05-13

No launchd plist changes needed — the existing com.skyrun.session-keep-alive already runs every 300s and now probes HS as a side-effect of the API_SOURCES loop.