Skip to content

feat: add secret_key config, deprecate personal_api_key#727

Merged
turnipdabeets merged 9 commits into
mainfrom
rename-personal-api-key-to-secret-key
Jul 7, 2026
Merged

feat: add secret_key config, deprecate personal_api_key#727
turnipdabeets merged 9 commits into
mainfrom
rename-personal-api-key-to-secret-key

Conversation

@turnipdabeets

Copy link
Copy Markdown
Contributor

Problem

The credential used for local feature flag evaluation and remote config accepts either a Personal API Key (phx_...) or a Project Secret API Key (phs_...), but the config field is named personal_api_key. Passing a project secret key to a field called "personal api key" is confusing now that project secret keys exist.

Change

  • Add secret_key as the canonical config field — accepts a Personal API Key or a Project Secret API Key.
  • Keep personal_api_key as a deprecated alias that resolves into secret_key. Non-breaking: existing code keeps working and gets a DeprecationWarning.
  • Prefer secret_key when both are provided.
  • Update docstrings and user-facing error messages to reference secret_key.

Context

From the Slack discussion + PostHog/posthog-js#4046. This covers the rename only. The other two items from that thread — making flag refresh opt-in, and a config to enable/disable local eval independent of the env var — are separate.

Part of a coordinated rename across the backend SDKs (python, node, php, ruby, go, dotnet, rs).

@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff (1)

  1. posthog/test/test_client.py, line 69-79 (link)

    P1 This existing test still passes personal_api_key to the constructor without wrapping it in assertWarns(DeprecationWarning). The PR's deprecation logic fires the warning whenever personal_api_key is not None and secret_key is None, which is exactly this call's shape. Any CI run with -W error::DeprecationWarning (or filterwarnings = error in pytest.ini) will fail this test. The simplest fix is to migrate the test to use secret_key directly, which is the canonical param being introduced here.

Reviews (1): Last reviewed commit: "feat: add secret_key config, deprecate p..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

posthog-python Compliance Report

Date: 2026-07-07 14:47:40 UTC
Duration: 338828ms

✅ All Tests Passed!

111/111 tests passed


Capture_V1 Tests

94/94 tests passed

View Details
Test Status Duration
Endpoint And Method.Targets V1 Endpoint 517ms
Endpoint And Method.Does Not Use Legacy Endpoints 1010ms
Required Headers.Has Authorization Bearer Header 1009ms
Required Headers.Has Content Type Json 1009ms
Required Headers.Has Posthog Sdk Info Format 1008ms
Required Headers.Has Posthog Attempt Header 1008ms
Required Headers.Has Posthog Request Id 1009ms
Required Headers.Has Posthog Request Timestamp 1009ms
Required Headers.Has User Agent 1009ms
Body Format.Body Has Created At And Batch 1008ms
Body Format.No Api Key In Body 1009ms
Body Format.No Sent At In Body 1009ms
Event Format.Event Has Required Root Fields 1008ms
Event Format.Event Uuid Is Valid 1008ms
Event Format.Event Timestamp Is Rfc3339 1009ms
Event Format.Distinct Id Is String 1008ms
Event Format.Distinct Id At Root Not Properties 1008ms
Event Format.Custom Properties Preserved 1009ms
Event Format.Set Properties Preserved 1008ms
Event Format.Set Once Properties Preserved 1009ms
Event Format.Groups Properties Preserved 1008ms
Event Format.Sdk Generates Uuid If Not Provided 1008ms
Event Format.Event Has Required Root Fields Batch 1013ms
Event Format.Event Uuid Is Valid Batch 1012ms
Event Format.Event Timestamp Is Rfc3339 Batch 1012ms
Event Format.Distinct Id Is String Batch 1012ms
Event Format.Distinct Id At Root Not Properties Batch 1013ms
Event Format.Custom Properties Preserved Batch 1012ms
Event Format.Set Properties Preserved Batch 1012ms
Event Format.Set Once Properties Preserved Batch 1012ms
Event Format.Groups Properties Preserved Batch 1013ms
Event Format.Sdk Generates Uuid If Not Provided Batch 1012ms
Batch Behavior.Multiple Events In Single Batch 1506ms
Batch Behavior.Batch Envelope Smoke 1014ms
Batch Behavior.Flush With No Events Sends Nothing 1004ms
Batch Behavior.Flush At Triggers Batch 1508ms
Batch Behavior.Created At Reflects Batch Creation Time 1010ms
Deduplication.Generates Unique Uuids 1507ms
Deduplication.Different Events Same Content Different Uuids 1506ms
Deduplication.Preserves Uuid On Retry 7515ms
Deduplication.Preserves Timestamp On Retry 7510ms
Deduplication.Preserves Uuid And Timestamp On Batch Retry 7514ms
Deduplication.No Duplicate Events In Batch 1502ms
Header Behavior On Retry.Attempt Header Starts At One 1009ms
Header Behavior On Retry.Attempt Header Increments On Retry 14523ms
Header Behavior On Retry.Request Id Preserved On Retry 7508ms
Header Behavior On Retry.Different Requests Have Different Request Ids 3516ms
Header Behavior On Retry.Request Timestamp Changes On Retry 7515ms
Response Format Validation.Success Response Has Uuid Keyed Results 1004ms
Response Format Validation.Success Response Has Ok For Each Event 1507ms
Response Format Validation.Success No Retry After When All Ok 1507ms
Response Format Validation.Success Retry After Present When Retry Events 2511ms
Response Format Validation.Success No Retry After When Drop Only 1507ms
Response Format Validation.Response Echoes Request Id 1009ms
Retry Behavior.Retries On 408 7515ms
Retry Behavior.Retries On 500 7510ms
Retry Behavior.Retries On 503 9514ms
Retry Behavior.Retries On 504 7511ms
Retry Behavior.Retryable Errors Have Retry After 4508ms
Retry Behavior.Respects Retry After On Retryable Error 12516ms
Retry Behavior.Does Not Retry On 400 3503ms
Retry Behavior.Does Not Retry On 401 3506ms
Retry Behavior.Does Not Retry On 402 3508ms
Retry Behavior.Does Not Retry On 413 3505ms
Retry Behavior.Does Not Retry On 415 3507ms
Retry Behavior.Non Retryable Errors Have No Retry After 3506ms
Retry Behavior.Implements Backoff 23530ms
Retry Behavior.Max Retries Respected 23521ms
Partial Batch Handling.Handles 200 Full Success 3000ms
Partial Batch Handling.Handles 200 With All Ok 4508ms
Partial Batch Handling.Does Not Retry Dropped Events 4505ms
Partial Batch Handling.Does Not Retry Limited Events 4510ms
Partial Batch Handling.Prunes Ok Events On Partial Retry 7510ms
Partial Batch Handling.Prunes Dropped Events On Partial Retry 7516ms
Partial Batch Handling.Retries Only Retry Events From Partial 7512ms
Partial Batch Handling.Partial Retry Preserves Uuids 7508ms
Partial Batch Handling.Partial Retry Attempt Header Increments 7511ms
Partial Batch Handling.Partial Retry Request Id Preserved 7516ms
Partial Batch Handling.Respects Retry After On Partial 9511ms
Partial Batch Handling.Unknown Result Treated As Terminal 4507ms
Partial Batch Handling.Mixed Ok Drop Limited No Retry 4508ms
Compression.Sends Gzip Content Encoding 1008ms
Compression.No Content Encoding When Disabled 1009ms
Compression.Compressed Body Is Decompressible 1008ms
Error Handling.Does Not Retry On Unknown 4Xx 3508ms
Event Options.Cookieless Mode Override 1007ms
Event Options.Disable Skew Correction Override 1008ms
Event Options.Process Person Profile Override 1007ms
Event Options.Product Tour Id Override 1009ms
Event Options.Unset Options Omitted 1009ms
Event Options.Options Override In Batch 1012ms
Geoip And Historical Migration.Geoip Disable Injected Into Properties 1008ms
Geoip And Historical Migration.Historical Migration Set In Body 1008ms
Geoip And Historical Migration.Historical Migration Absent By Default 1008ms

Feature_Flags Tests

17/17 tests passed

View Details
Test Status Duration
Request Payload.Request With Person Properties Device Id 1006ms
Request Payload.Flags Request Uses V2 Query Param 1005ms
Request Payload.Flags Request Hits Flags Path Not Decide 1006ms
Request Payload.Flags Request Omits Authorization Header 1007ms
Request Payload.Token In Flags Body Matches Init 1006ms
Request Payload.Groups Round Trip 1006ms
Request Payload.Groups Default To Empty Object 1005ms
Request Payload.Disable Geoip False Propagates As Geoip Disable False 1005ms
Request Payload.Disable Geoip Omitted Defaults To False 1006ms
Request Payload.Flag Keys To Evaluate Contains Only Requested Key 1005ms
Request Lifecycle.No Flags Request On Init Alone 503ms
Request Lifecycle.No Flags Request On Normal Capture 1507ms
Request Lifecycle.Two Flag Calls Produce Two Remote Requests 1011ms
Request Lifecycle.Mock Response Value Is Returned To Caller 1002ms
Retry Behavior.Retries Flags On 502 1007ms
Retry Behavior.Retries Flags On 504 1006ms
Side Effect Events.Get Feature Flag Captures Feature Flag Called Event 1509ms

Comment thread posthog/test/test_client.py Outdated
The local feature flag / remote config credential now accepts either a
Personal API Key or a Project Secret API Key, so the field is renamed to
secret_key. personal_api_key is kept as a deprecated alias that resolves
into secret_key, with a DeprecationWarning, so existing code keeps working.
- Regenerate public API snapshot for the new secret_key field
- Update the unauthorized-error test to assert secret_key
- Collapse the three secret_key tests into one parameterized table
- ruff format
…ey-to-secret-key

# Conflicts:
#	references/public_api_snapshot.txt
Second assertion (in test_feature_flags) still pinned the old
personal_api_key wording after the message was renamed to secret_key.
@turnipdabeets turnipdabeets marked this pull request as ready for review July 2, 2026 17:19
@turnipdabeets turnipdabeets requested a review from a team as a code owner July 2, 2026 17:19
@greptile-apps

greptile-apps Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Reviews (2): Last reviewed commit: "test: assert secret_key in wrong-key err..." | Re-trigger Greptile

@turnipdabeets turnipdabeets marked this pull request as draft July 6, 2026 13:49
@turnipdabeets

turnipdabeets commented Jul 6, 2026

Copy link
Copy Markdown
Contributor Author

Marked ready for review.

Naming is settled — this is a generic secret_key config that accepts either a Personal API Key or a Project Secret API Key (both coexist; same Authorization: Bearer header). personal_api_key stays as a deprecated config-name alias that forwards into it — not a deprecation of personal keys as a credential. It's a name-level change and is crash-safe with respect to using the key (adds no new error path).

Merge timing still coordinates with the project-secret-key rollout (feature-flagged today) — ready-for-review ≠ merge-now.

@turnipdabeets turnipdabeets marked this pull request as ready for review July 6, 2026 15:37

@dustinbyrne dustinbyrne left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some lingering references

$  git -P grep -l 'personal_api_key' -- . ':(exclude)references/**'
.env.example
example.py
examples/async_redis_flag_cache.py
examples/celery_integration.py
examples/redis_flag_cache.py
examples/remote_config.py
openfeature-provider/openfeature/contrib/provider/posthog/provider.py
openfeature-provider/tests/conftest.py
openfeature-provider/tests/test_provider_unit.py
posthog/__init__.py
posthog/ai/prompts.py
posthog/client.py
posthog/flag_definition_cache.py
posthog/request.py
posthog/test/ai/test_prompts.py
posthog/test/test_client.py
posthog/test/test_client_fork.py
posthog/test/test_feature_flags.py
posthog/test/test_flag_definition_cache.py

Comment thread posthog/client.py Outdated
Comment on lines 237 to 238
secret_key=None,
personal_api_key=None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a breaking change if anyone is using positional arguments in the client constructor

given how many we have, it seems unlikely, but there's no downside to moving this addition to the end

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done — moved secret_key to the end of the constructor params (2b87f8a) so no existing positional argument shifts. Thanks!

Avoids shifting the positional order of existing constructor parameters
(non-breaking for any positional callers), per review feedback.
…ey-to-secret-key

# Conflicts:
#	posthog/client.py
#	references/public_api_snapshot.txt
@turnipdabeets turnipdabeets requested a review from dustinbyrne July 7, 2026 16:02
@turnipdabeets turnipdabeets merged commit 389e5aa into main Jul 7, 2026
38 checks passed
@turnipdabeets turnipdabeets deleted the rename-personal-api-key-to-secret-key branch July 7, 2026 16:04
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