Skip to content

[ENG-3568] Use one credential for Pulse ingest and block-logs - #154

Merged
mariojgt merged 1 commit into
mainfrom
mariot/eng-3568-single-credential
Aug 20, 2026
Merged

[ENG-3568] Use one credential for Pulse ingest and block-logs#154
mariojgt merged 1 commit into
mainfrom
mariot/eng-3568-single-credential

Conversation

@mariojgt

Copy link
Copy Markdown
Contributor

apiKey and pulseAuth have always held the same value — there is one oauth_clients row per site, so there is one secret. Two fields isolated nothing (a bad credential breaks both paths regardless) while obliging every write site to keep them in step.

That obligation already produced a bug: login rotated the credential and wrote only pulseAuth, leaving apiKey holding a value the server had just invalidated — block-log delivery would have stopped silently.

No breaking changes

Reading is completely unchanged. Pulse resolution already falls back to apiKey in both paths:

Path
CLI config.ts:83fromEnv.pulseAuth ?? fromFile.pulseAuth ?? apiKeyRaw
Guard runtime.js:694,704resolvePulseAuth()resolveApiKey()

So every existing config keeps working, in every combination:

Config Result
apiKey only (pre-ADR-0018 sites) ✅ both paths authenticate
apiKey + pulseAuth (current version) pulseAuth still wins
PATCHSTACK_PULSE_AUTH set ✅ still overrides
New install apiKey only

persistPulseAuth stays exported — removing it would break the package's public API — and is documented for deployments that genuinely want Pulse on a different credential from block-logs.

The one hazard, and the fix

pulseAuth resolves ahead of apiKey. So a config written by the current version would, after a rotation that wrote only apiKey, keep authenticating Pulse with the replaced value.

persistApiKey now drops the field when it writes. That is correct in every case: a new apiKey invalidates any older pulseAuth by definition. Without it this change would have introduced exactly the class of bug it exists to remove.

Tests

Four new tests pin the compatibility surface:

  • apiKey alone resolves for Pulse
  • an existing pulseAuth still wins
  • a stale one is dropped on rotation
  • PATCHSTACK_PULSE_AUTH still overrides

1224 pass (up 4), typecheck clean. README and AGENT-INSTALL updated to describe one credential, with the pulseAuth escape hatch noted as something an agent should not add by default.

Ref ENG-3568

🤖 Generated with Claude Code

apiKey and pulseAuth have always held the same value: there is one
oauth_clients row per site, so there is one secret. Two fields isolated
nothing — a bad credential broke both paths regardless — while obliging
every write site to keep them in step.

That obligation already caused a bug. `login` rotated the credential and
wrote only pulseAuth, leaving apiKey holding a value the server had just
invalidated, which would have stopped block-log delivery silently.

Stops writing pulseAuth. Nothing else changes: Pulse resolution already
falls back to apiKey in both the CLI (config.ts) and the guard
(runtime.js), so a config carrying only apiKey authenticates both paths.

The one hazard is a stale copy. pulseAuth resolves ahead of apiKey, so a
config written by the previous version would keep authenticating Pulse with
the replaced value after a rotation. persistApiKey now drops the field when
it writes, which is correct in every case: a new apiKey invalidates any
older pulseAuth by definition.

Reading is unchanged. An existing pulseAuth is still honoured and
PATCHSTACK_PULSE_AUTH still overrides, for deployments that do want Pulse
ingest on a different credential from block-logs. persistPulseAuth stays
exported for them.

Four tests pin the compatibility surface: apiKey-only resolves for Pulse, an
existing pulseAuth still wins, a stale one is dropped on rotation, and the
env override still applies.

Co-Authored-By: Claude <noreply@anthropic.com>
@coderbuds

coderbuds Bot commented Aug 20, 2026

Copy link
Copy Markdown

Unified credential logic simplifies config and removes redundant pulseAuth handling.

🎯 Quality: 100% Elite · 📦 Size: Medium

📈 This month: Your 59th PR — above team average · Averaging Excellent

See how your team is trending →

@mariojgt

Copy link
Copy Markdown
Contributor Author

/review

@mariojgt
mariojgt merged commit 49fa0fa into main Aug 20, 2026
6 checks passed
@mariojgt
mariojgt deleted the mariot/eng-3568-single-credential branch August 20, 2026 07:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants