Skip to content

Consolidate low-signal tests from recent feature work - #801

Merged
kody-bot merged 4 commits into
mainfrom
cursor/test-quality-guidelines-6460
Jul 20, 2026
Merged

kody-bot merged 4 commits into
mainfrom
cursor/test-quality-guidelines-6460

Conversation

@cursor

@cursor cursor Bot commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor

Reduce maintenance weight from agent-authored micro-tests added with recent billing, feature-flag, community social, blog, passkey, and picker work.

Summary

  • Prefer fewer, longer workflow tests and drop redundant e2e/workerd smoke coverage already covered by faster units.
  • De-pin incidental copy (toasts, instructional descriptions, HTML labels) in favor of status/shape/testid behavior.
  • Net ~−690 lines across 24 test files; no production code changes.

Notable removals / merges

  • Delete e2e/account-pickers.spec.ts (client filter units cover search matching).
  • Delete profile-og-image.workers.test.ts and profile.frame.node.test.ts (folded/covered elsewhere).
  • Billing config/client/sync, feature-flag service/handler/MCP/e2e, social MCP + handlers, avatars, passkey labels, blog catalog/OG, username rewrite tests consolidated.
System recap — composes existing primitives (low risk)

Mode: recap · Base: main · Head: cursor/test-quality-guidelines-6460

Classification: composes — test-only cleanup; no primitives added or changed.

Primitives touched

Primitive Group Impact
billing auth composes — consolidate Stripe config/client/sync workflows
feature-flags auth composes — collapse service duplication
rbac auth composes — thinner admin HTTP/MCP wiring tests
community-listings assistant composes — merge social MCP/handler micro-tests
app-ui surfaces composes — fold profile/avatar/timeline/passkey tests
saved-packages assistant composes — merge username rewrite micro-cases

System map

Test-only consolidation across recently touched surfaces; production contracts unchanged.

Legend: green = composes (wiring only) · amber = extended by this PR · red = new primitive · gray = context (unchanged, included only when an edge crosses it).

flowchart LR
  billing["billing<br/>Stripe billing"]:::touched
  featureFlags["feature-flags<br/>Feature flags"]:::touched
  rbac["rbac<br/>Role-based access control"]:::touched
  community["community-listings<br/>Community package listings"]:::touched
  appUi["app-ui<br/>Browser app (Remix 3)"]:::touched
  savedPackages["saved-packages<br/>Saved packages"]:::touched
  billing -->|"fewer sync/client workflows"| billing
  featureFlags -->|"service owns evaluation"| rbac
  rbac -->|"thin HTTP/MCP wiring"| featureFlags
  community -->|"MCP + handler merge"| appUi
  appUi -->|"profile/avatar/timeline fold"| community
  savedPackages -->|"username rewrite merge"| savedPackages
  classDef touched fill:#1a7f37,color:#fff
  classDef extended fill:#9a6700,color:#fff
  classDef added fill:#cf222e,color:#fff
  classDef untouched fill:#57606a,color:#fff
Loading

Before / after

Area Before After
Billing tests 9+7+7 micro-cases ~3+2+4 workflows
Feature-flag layers 20 across 4 files 10
Social/profile/avatar/OG many micro-tests + picker e2e fewer workflows; picker e2e deleted
Lines — ~−690

Invariants

No userId isolation or auth contract changes.

cursoragent and others added 4 commits July 20, 2026 09:07
… workflow

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
- service.node.test.ts: de-pin description copy; fold note-preserve into global workflow
- admin-feature-flags.node.test.ts: merge HTTP lifecycle into one test; de-pin error prose
- admin-feature-flag-capabilities.node.test.ts: single MCP wiring workflow with audit
- e2e/admin-feature-flags.spec.ts: one journey for global toggle + per-user override

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Merge overlapping node and e2e tests into fewer workflow-oriented cases.
De-pin brittle UI copy and error prose; keep structural assertions (status,
data-testid, package ids, cache headers). Fold profile.frame tests into
profile.node.test.ts and delete the standalone frame file.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
Drop redundant account-pickers e2e and profile OG workerd smoke coverage
already exercised by client filter units and node renderer tests. Merge
billing-config/stripe-client micro-cases into workflow tests and fold
passkey label helpers into one contract test.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
@kody-bot kody-bot changed the title test(billing): consolidate subscription-sync rejection cases into one workflow Consolidate low-signal tests from recent feature work Jul 20, 2026
@kody-bot
kody-bot marked this pull request as ready for review July 20, 2026 09:12
@github-actions

Copy link
Copy Markdown
Contributor

🔎 Preview deployed: https://kody-pr-801.kody-a99.workers.dev

Worker: kody-pr-801
D1: kody-pr-801-db
KV: kody-pr-801-oauth-kv

Mocks:

@kody-bot
kody-bot merged commit b5ad13a into main Jul 20, 2026
6 checks passed
@kody-bot
kody-bot deleted the cursor/test-quality-guidelines-6460 branch July 20, 2026 09:19
cursor Bot pushed a commit that referenced this pull request Jul 27, 2026
The value-name builders, the legacy JSON parse helpers, and the second
config schema existed only to serve callers that no longer exist. The
value-name assertions in integration-save tests were the last references,
and a test whose only subject is dead code is not coverage.

One integration config schema remains, the one with an inline clientId, so
there is no longer a 'with client id' variant to disambiguate.

The migration test now builds its fixtures as literal historical JSON,
which is what a migration test should assert against anyway rather than
keeping a production schema alive to describe its own input.

Also drop the E2E integration seeder. It has had no callers since #801
removed its last one, so it was already dead; rewriting it against the new
tables would only create something to maintain.

The _integration: prefix stays in the platform-reserved value guard so a
shadowing value cannot be created later.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>
kody-bot pushed a commit that referenced this pull request Jul 27, 2026
…ables (#979)

* feat(integrations): add user_oauth_apps and user_integrations tables

Integration config lived in the values store as _integration:<name> JSON
blobs, with the OAuth client id in a separate plain user value reached
through a clientIdValueName pointer.

Model an OAuth app (client credentials plus provider endpoints) separately
from a connection (one connected account). Production has one Google app
serving four connected accounts, so rotating client credentials was four
writes with four chances to half-finish; it is now one.

Composite (user_id, slug) keys and a composite foreign key keep per-user
isolation structural rather than conventional. No token, refresh token, or
client secret column exists in either table: those stay in secret_entries
and are referenced by name.

Backfill dedupes on the full app tuple rather than just the credential
pair, so connections merge into one app only when they agree on every
app-level field. Divergent rows split into separate apps instead of
silently inheriting one row's endpoints. Fail-closed CHECK(0) assertions
abort the transaction unless every migratable row produced exactly one
connection with a resolvable app.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* feat(integrations): read capabilities from D1 and add oauth app surface

integration_save/get/list/delete keep their names and flat output shape so
user package code and search are unaffected; clientIdValueName becomes
clientId now that the id is stored inline.

Add integration_oauth_app_list and integration_oauth_app_rotate_credentials
so credential rotation is a single write across every connection sharing
an app.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* refactor(search): build integration entities from D1 instead of value rows

The integration search entity derived candidates by scanning every user
value and JSON-parsing the ones with an _integration: prefix. It now
queries the integrations service directly.

Entity type, {name}:integration ref format, and the indexed document field
set are unchanged, so ranking and agent-facing behavior do not move.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* refactor(runtime): resolve integration client ids inline

createAuthenticatedFetch and the OpenAPI integration-auth path each read
the client id back out of the values store through clientIdValueName. The
id now arrives on the config, which removes a sandbox round-trip and the
'Client ID value not found' failure mode from the token refresh path.

Host allowlist enforcement, secret placeholder construction, and the
401-refresh-retry are unchanged.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* feat(account): group connections by oauth app and stop reading values in connect

The connect flow reached into the values store from the browser: it rebuilt
the _integration: value name client-side, read the config with value_get,
read the client id with a second value_get, and wrote it back with
value_set. It now goes through GET /account/integrations.json?name=.

The integrations page groups connections under the OAuth app they share, so
four Google accounts read as four accounts on one app rather than four
unrelated integrations. Tokens continue to land only in the secret store.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(values): hide platform-reserved value prefixes from agents

value_list only filtered isReservedValueName, an empty Set, so agents saw
platform plumbing mixed into the user's own config. The account UI already
hid these prefixes via its own duplicated list.

Move the guard into the values layer, filter it from value_list, reject
writes to those prefixes from value_set with a pointer to the right
capability, and stop leaking _openapi: rows into generic value search.
Internal saveValue is deliberately unguarded because platform code still
writes _openapi: rows through it.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* docs(integrations): document the oauth app model and cover deletion inventory

Both new tables join the account deletion and export inventory, connections
before apps to respect the ON DELETE RESTRICT direction. The guardrail tests
apply live migrations and fail on any uncovered user_id column.

Add the integrations primitive, which the taxonomy never had, and correct
docs/guides/oauth.md, which claimed integrations were stored as
_integration:<name> values.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* refactor(integrations): delete the values-era config helpers

The value-name builders, the legacy JSON parse helpers, and the second
config schema existed only to serve callers that no longer exist. The
value-name assertions in integration-save tests were the last references,
and a test whose only subject is dead code is not coverage.

One integration config schema remains, the one with an inline clientId, so
there is no longer a 'with client id' variant to disambiguate.

The migration test now builds its fixtures as literal historical JSON,
which is what a migration test should assert against anyway rather than
keeping a production schema alive to describe its own input.

Also drop the E2E integration seeder. It has had no callers since #801
removed its last one, so it was already dead; rewriting it against the new
tables would only create something to maintain.

The _integration: prefix stays in the platform-reserved value guard so a
shadowing value cannot be created later.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(integrations): preserve non-canonical integration value names in the backfill

A value named literally `_integration:` passed the migratable filter and
produced an empty app slug and connection name, then had its source row
deleted. The old parseIntegrationValueName rejected empty and non-canonical
names, so this was a regression against the previous validation.

Require a non-empty canonical suffix in every copy of the migratable
predicate, so those rows survive as values instead. Capture, delete, and
remain predicates stay identical, which is the property that guarantees the
delete can never outrun the insert.

Also make the staging tables restart-safe, and cover the cases that matter
if this ever goes wrong: an assertion firing must leave every _integration:*
row in place, and an integration whose client id value is missing must be
neither migrated nor deleted.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(integrations): store canonical use_pkce and canonicalize app slugs

The backfill wrote use_pkce = 0 for an explicit usePkce: false, but the
application layer can never produce that row: PKCE-off is already the
default for confidential flow, so normalizeIntegrationConfig omits the
field and writes NULL. findOauthAppByAppTuple compares with IS, so a
migrated 0 never matched a freshly normalized NULL and an app that should
have been reused was not, letting a reconnect create a duplicate app or
move a connection off the app its siblings share.

The backfill now applies the same omit-when-default rule, so there is one
canonical on-disk representation. The round-trip test could not catch this
because toIntegrationConfig normalizes on read, so the config compared
equal while the stored row did not; the new test asserts stored row values
directly.

Also canonicalize slugs on every oauth app path. They were only trimmed,
so an agent passing Google got 'not found' while integration_get('Google')
resolved, contradicting the rule that no lookup depends on caller casing.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(integrations): persist the setup client id and share one app-resolution path

The setup step held the entered client id only in session storage, so
abandoning the flow before token exchange lost it and a later reconnect
showed an empty field. Re-entering a client id means a trip back to the
provider's dashboard, so setup now persists the app row up front. A
connectionless app is a valid intermediate state: the FK points from
connection to app, not the reverse.

Reusing a matched app no longer rewrites its provider. That field is
derived from the incoming connection name, so saving an unrelated
connection with an identical app tuple relabeled the app its siblings
share. Reuse is now purely additive, and a connection moved off its old
app takes any orphaned app row with it.

Both write paths now go through one resolveOrCreateOauthApp, so the
usePkce, token-exchange-style, client-secret, and slug-allocation rules
cannot drift between setup and connect. The first draft of the setup fix
reimplemented all of them in the app layer, which is how two of the
reviewer findings on this branch happened in the first place.

Also correct docs that named requiredHosts instead of required_hosts_json,
implied every credential lives in secret_entries when client_id is inline,
and described app matching as credentials plus endpoints rather than the
full app tuple.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(integrations): resolve setup prefill by provider family, not slug guess

The connect prefill assumed an app's slug equals the connection name. App
resolution dedupes, so setting up a second account persists under the
shared app's slug: google-calendar lands on the google app. The fallback
looked for a slug named google-calendar, found nothing, and skipped the
prefill — leaving the original regression in place for exactly the
multi-account case this change exists to support.

Resolution is now connection, then exact slug, then provider family. A
family can legitimately hold different client ids (spotify and
spotify-family do), so prefill only happens when every candidate agrees.
Guessing would surface as an opaque provider error at token exchange
rather than as a visibly wrong field.

Lives in the service rather than the account loader, since the app layer
holding its own copy of app resolution is what produced the earlier
provider-rewrite and duplicate-app bugs.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(integrations): write canonical column values in the backfill

The backfill stored several columns exactly as they came out of the legacy
JSON, while the application layer normalizes before writing. Where those
columns sit in the app tuple, that mismatch means findOauthAppByAppTuple
cannot match a migrated row, so a reconnect allocates a fresh app and
strands its siblings on the old slug.

extra_authorize_params_json now sorts keys, and scope_separator drops the
default single space, both of which are compared in the tuple. Also aligned
token_exchange_style, client_secret_secret_name, authorize_url,
required_hosts_json, and scopes_json with their normalizers, and left a note
that SQL BINARY ordering matches localeCompare for the lowercase keys OAuth
providers actually use.

This is the third instance of the same class after use_pkce, so the tests
now assert stored column values rather than round-tripped config: reading
through toIntegrationConfig normalizes and hides exactly this defect.

Verified by dry-running the migration over the real production blobs: 19
connections collapse to 15 apps, every config matches what the application
layer produces from the same input, all client-id values survive, and
re-saving a shared-app sibling afterward reuses its app.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* fix(integrations): agree field by field on provider-family prefill

The family fallback treated candidates as interchangeable when they shared
a client id, then prefilled everything from whichever app won. Sharing a
client id does not imply sharing the rest: github and github-kent hold the
same client id but different client-secret names, so a new github-* setup
would have been handed the wrong secret name and one app's endpoints.

Each field is now prefilled only when every app in the family agrees on it.
That keeps the field users actually resent re-entering while never inventing
a client-secret name they did not choose. Refusing to prefill at all would
be safe but discards the shared client id in a real case, and picking a
winner is what produced the wrong default.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

* refactor(account): drop the unguarded value actions from secrets.json

The connect flow was the only caller of value_get and value_set on
/account/secrets.json, and it now reads integration config from D1 through
its own endpoint. What remained was an authenticated read/write path over
arbitrary user values with no reserved-name check, so it could still write
legacy _integration: blobs or corrupt a live _openapi: binding while the
MCP capability and the account values UI both refuse those prefixes.

Removing them is better than adding a third copy of the guard: /account/values
already owns value CRUD and applies it. No caller remains anywhere in the
client, handlers, or e2e.

Co-authored-by: Kent C. Dodds <me+github@kentcdodds.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
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