Skip to content

Dev - #270

Merged
vernu merged 12 commits into
mainfrom
dev
Aug 3, 2026
Merged

Dev#270
vernu merged 12 commits into
mainfrom
dev

Conversation

@vernu

@vernu vernu commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • Added automated workflows for Android, API, and web builds, tests, artifact generation, and end-to-end reporting.
    • Expanded API documentation to clearly identify API-key and bearer authentication requirements.
  • Bug Fixes

    • Webhook notification results now refresh correctly when date filters change, preventing stale data.
  • Tests

    • Improved end-to-end test stability by waiting for hydrated page content.
    • Added coverage for webhook filtering and cache behavior.

vernu and others added 8 commits August 3, 2026 09:11
textbee is public, so it qualifies for CodeRabbit's Open Source plan (the
Pro+ feature set at no cost). Reviews are comment-only on the chill
profile, so nothing gates a merge.

Two settings are load-bearing and easy to get wrong:

base_branches always includes the default branch and cannot exclude it,
so main is reviewed implicitly and dev has to be listed explicitly.
Without it, every feature PR would go unreviewed since they all target
dev. The skip-ai-review label is the only lever left for skipping the
dev to main roll-ups, which would otherwise re-review code already seen.

CodeRabbit auto-reads CLAUDE.md from the repo root as review guidelines,
but this repo's CLAUDE.md sits one directory above the git root and
.cursor/rules is not on its auto-read list. The no-em-dash and pnpm-only
rules are therefore encoded directly in tone_instructions and a global
path instruction.

Validated against schema.v2.json.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The workflow fired on push only, so pull requests carried no checks of
their own. CodeRabbit's github-checks tool waits on GitHub Checks and
comments on failures, which gave it nothing to read, and outside
contributors got no CI signal before merge.

It also ran everything in one workflow, with web and api sharing a single
job. On the last green run that job was 5m23s, of which the e2e suite was
2m52s while already carrying continue-on-error, so it dominated wall clock
while gating nothing. An api-only change paid for all of it plus both
android builds, because a workflow-level paths filter is all or nothing.

Now api, web and android each have their own workflow and their own paths
filter, which needs no third-party change-detection action, and web e2e is
its own job so the blocking signal lands in about 90 seconds.

Also folded in, since the files were being rewritten anyway:

- permissions: contents: read. Nothing was declared, so the token got
  default write scope on every run.
- concurrency with cancel-in-progress, and timeout-minutes. A hung job
  previously burned the six hour default.
- Action versions. actionlint rejected setup-node@v3, cache@v3 and
  setup-java@v3 as too old for current runners, and gradle-build-action
  is deprecated in favour of gradle/actions/setup-gradle.
- setup-node's built-in pnpm cache replaces the manual store-path and
  actions/cache block. pnpm is installed first so the cache has a package
  manager to query.
- The android job is skipped on fork pull requests. It writes
  google-services.json from repository secrets, and GitHub withholds
  secrets from forks, so it would fail every outside contribution.
- google-services.json is written through an env var instead of shell
  interpolation, so the secret never lands on a command line and JSON
  containing quotes cannot break the redirect.
- fail-fast: false on the android matrix, so a dev failure no longer
  cancels the prod build.
- Dropped the android_variant dispatch input. It was declared but never
  referenced; the matrix always built both variants.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…specs

Four specs had been failing on main for as long as the run history goes
back. The old workflow set continue-on-error on the e2e step rather than
the job, and a step with continue-on-error reports its conclusion as
success even when the command exits non-zero, so the failures never
surfaced. Splitting e2e into its own job made them visible.

None of them were stale. Every string they assert on still exists in the
source. Three are hydration races of the shape ab96e73 fixed for the
messaging specs: the sections stream behind a loading.tsx boundary, so the
HTML paints before React attaches handlers, and a click landing in that
gap is silently dropped. The test then waits out its timeout on a dialog
that was never going to open.

Both specs now navigate through a helper that waits on a value only the
client render can produce: the gateway stats figure on the dashboard, and
the fetched device id in the guide. Prism tokens are not usable as that
signal, because react-syntax-highlighter renders its spans server side
too, so they are already in the SSR payload.

The clipboard spec had a second, unrelated cause. It asserted on the
button's "Copied" label, and code-block.tsx clears that label two seconds
after the click, so the assertion raced a window narrow enough to miss on
a loaded runner. It now polls the clipboard, which is the behaviour under
test and does not expire.

Verified with --repeat-each=4 --retries=0 --workers=2: 56 passed. Single
worker runs are why local looked green while CI failed; the specs' own
comments note that parallel workers background the page, which one worker
never reproduces.

No production code changed. These were test bugs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Add CodeRabbit review, split CI into per-app workflows
Date filter changes for webhook history were ignored by react-query
because start and end were only sent as request params, not cache keys.

Fixes #256
…routes

The scheme was registered without a name, so it landed in the OpenAPI doc
as api_key and no operation referenced it. Swagger UI stored the key but
never sent the header. Name the scheme x-api-key and add ApiSecurity to
every AuthGuard route, mirroring the existing ApiBearerAuth placement.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Make Swagger UI actually send the x-api-key header
…lter-query-key

fix(web): include start/end in webhook notifications query key
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
textbee Building Building Aug 3, 2026 10:15am
textbee (staging) Ready Ready Preview Aug 3, 2026 10:15am

Request Review

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@vernu, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 17 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3bb9a8d5-cc3d-42fb-8689-44665b385da5

📥 Commits

Reviewing files that changed from the base of the PR and between 33f55bc and 3fa7265.

📒 Files selected for processing (3)
  • .github/workflows/android.yaml
  • .github/workflows/api.yaml
  • .github/workflows/web.yaml
📝 Walkthrough

Walkthrough

The pull request adds repository automation, documents API-key security in Swagger, centralizes webhook notification query keys, and synchronizes API guide and dashboard end-to-end tests with hydrated data.

Changes

Repository automation

Layer / File(s) Summary
Review configuration
.coderabbit.yaml
Adds CodeRabbit review settings, path instructions, GitHub checks, chat settings, and knowledge-base scopes.
CI workflow separation
.github/workflows/android.yaml, .github/workflows/api.yaml, .github/workflows/web.yaml
Adds separate Android, API, and web workflows with triggers, checks, artifacts, caching, permissions, and concurrency controls.

API security documentation

Layer / File(s) Summary
Swagger security metadata
api/src/main.ts, api/src/auth/auth.controller.ts, api/src/billing/billing.controller.ts, api/src/gateway/gateway.controller.ts, api/src/support/support.controller.ts, api/src/webhook/webhook.controller.ts
Registers the x-api-key Swagger scheme and applies API-key or bearer security metadata to authenticated endpoints.

Webhook notification queries

Layer / File(s) Summary
Query-key contract
web/lib/api/query-keys.ts, web/lib/api/query-keys.test.ts
Adds the webhookNotifications query-key factory and tests filter, pagination, and date-range values.
Query hook integration
web/lib/api/hooks.ts, web/lib/api/hooks.test.tsx
Uses the centralized query key in useWebhookNotifications and verifies that changing the start date sends a new request.

End-to-end test synchronization

Layer / File(s) Summary
Hydration-aware navigation
web/e2e/api-guide.spec.ts, web/e2e/dashboard.spec.ts
Adds navigation helpers that wait for hydrated guide or dashboard data. The clipboard test polls clipboard contents directly.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title "Dev" is too vague and does not identify the pull request's main changes. Replace "Dev" with a concise summary of the primary changes, such as separating CI workflows and updating API security and web test coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 6

🧹 Nitpick comments (3)
.github/workflows/android.yaml (2)

88-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Explain or remove the disabled test step.

The Run Android tests step is commented out with no rationale, unlike the e2e job in web.yaml, which documents its continue-on-error with a clear comment and TODO. As written, this silently drops unit test coverage from CI, and a future reader cannot tell whether it is temporary or intentional.

Add a short comment stating why the step is disabled and what would need to happen to re-enable it, or remove the dead block if the tests are permanently retired.
Do you want me to open an issue to track re-enabling ./gradlew test${{ matrix.variant }}DebugUnitTest?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/android.yaml around lines 88 - 91, Document the disabled
“Run Android tests” block with a concise comment explaining why `./gradlew
test${{ matrix.variant }}DebugUnitTest` is currently disabled and what must
happen before re-enabling it, or remove the commented-out step if Android unit
tests are permanently retired.

63-66: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Remove or align the Gradle version input.

The wrapper uses Gradle 7.5, while setup-gradle requests 7.2. The build invokes ./gradlew, so Gradle 7.2 is unused. Remove gradle-version, or set it to 7.5 to avoid the redundant download.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/android.yaml around lines 63 - 66, Update the Setup Gradle
step to remove the redundant gradle-version input, or align it with the
wrapper’s Gradle 7.5 version; preserve the existing ./gradlew-based build flow.
.github/workflows/api.yaml (1)

69-73: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a lint step to match the web workflow's quality gates.

The job runs Build and Unit test but never runs lint. api/package.json exposes "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix". web.yaml runs pnpm lint and pnpm typecheck before tests, but api.yaml has no equivalent step, so lint regressions in the API package will not be caught by CI.

♻️ Proposed addition
       - name: Install dependencies
         run: pnpm install
 
+      - name: Lint
+        run: pnpm lint
+
       - name: Build
         run: pnpm run build
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/api.yaml around lines 69 - 73, Add a dedicated lint step
to the API workflow job, invoking the package’s existing `pnpm lint` script
before `Build` and `Unit test`, so API lint regressions are caught by CI.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.coderabbit.yaml:
- Around line 92-96: Update the comment above the enabled github-checks
configuration to state that it waits for all GitHub Checks, then comments on
failures; leave the configuration unchanged.

In @.github/workflows/android.yaml:
- Around line 52-55: Update the Android workflow’s “Checkout repository” step to
set actions/checkout’s persist-credentials option to false, matching the
corresponding checkout steps in the other workflows; leave the existing ref
selection unchanged.

In @.github/workflows/api.yaml:
- Around line 45-49: Update the Checkout repository steps in the workflow
configurations to set persist-credentials to false alongside the existing
checkout options. Apply this consistently in the API, web, and Android
workflows, while preserving the current ref selection and checkout behavior.

In @.github/workflows/web.yaml:
- Around line 45-51: Update every actions/checkout step in the checks and e2e
jobs of web.yaml, and the corresponding checkout steps in api.yaml and
android.yaml, to set persist-credentials to false. Preserve the existing
checkout refs and other options.

In `@api/src/billing/billing.controller.ts`:
- Line 16: Adjust the Swagger security metadata in the billing controller so
unguarded GET /billing/plans and POST /billing/webhook/polar do not inherit
bearer or x-api-key requirements. Move `@ApiBearerAuth`() and
`@ApiSecurity`('x-api-key') from controller scope to the guarded billing methods,
or explicitly set operation-level security to empty for these public operations.

In `@web/e2e/api-guide.spec.ts`:
- Around line 110-116: Update the clipboard assertion in the polling block of
the API guide test to compare against the complete expected copied code block,
rather than merely checking for the api.textbee.dev substring. Normalize
whitespace as needed while preserving the existing polling behavior.

---

Nitpick comments:
In @.github/workflows/android.yaml:
- Around line 88-91: Document the disabled “Run Android tests” block with a
concise comment explaining why `./gradlew test${{ matrix.variant
}}DebugUnitTest` is currently disabled and what must happen before re-enabling
it, or remove the commented-out step if Android unit tests are permanently
retired.
- Around line 63-66: Update the Setup Gradle step to remove the redundant
gradle-version input, or align it with the wrapper’s Gradle 7.5 version;
preserve the existing ./gradlew-based build flow.

In @.github/workflows/api.yaml:
- Around line 69-73: Add a dedicated lint step to the API workflow job, invoking
the package’s existing `pnpm lint` script before `Build` and `Unit test`, so API
lint regressions are caught by CI.
🪄 Autofix (Beta)

✅ Autofix completed


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: ee0be272-af33-470e-bcfe-07f9e955b072

📥 Commits

Reviewing files that changed from the base of the PR and between f25b117 and 967ddd4.

📒 Files selected for processing (17)
  • .coderabbit.yaml
  • .github/workflows/android.yaml
  • .github/workflows/api.yaml
  • .github/workflows/build-and-test.yaml
  • .github/workflows/web.yaml
  • api/src/auth/auth.controller.ts
  • api/src/billing/billing.controller.ts
  • api/src/gateway/gateway.controller.ts
  • api/src/main.ts
  • api/src/support/support.controller.ts
  • api/src/webhook/webhook.controller.ts
  • web/e2e/api-guide.spec.ts
  • web/e2e/dashboard.spec.ts
  • web/lib/api/hooks.test.tsx
  • web/lib/api/hooks.ts
  • web/lib/api/query-keys.test.ts
  • web/lib/api/query-keys.ts
💤 Files with no reviewable changes (1)
  • .github/workflows/build-and-test.yaml

Comment thread .coderabbit.yaml
Comment thread .github/workflows/android.yaml
Comment thread .github/workflows/api.yaml
Comment on lines +45 to +51
- name: Checkout repository
uses: actions/checkout@v7
with:
ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref }}

# pnpm has to be on PATH before setup-node, or its pnpm cache resolution
# has no package manager to query.

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.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Consider disabling credential persistence on both checkout steps.

Neither the checks job's checkout (lines 45-51) nor the e2e job's checkout (lines 98-101) sets persist-credentials: false. Neither job pushes or commits, so the persisted GITHUB_TOKEN is unnecessary and stays readable for the whole job, including by pnpm install and Playwright browser install scripts.

This finding repeats in api.yaml and android.yaml. See the consolidated comment for a single fix across all three files.

Also applies to: 98-101

🧰 Tools
🪛 zizmor (1.28.0)

[warning] 45-51: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/web.yaml around lines 45 - 51, Update every
actions/checkout step in the checks and e2e jobs of web.yaml, and the
corresponding checkout steps in api.yaml and android.yaml, to set
persist-credentials to false. Preserve the existing checkout refs and other
options.

Source: Linters/SAST tools

Comment thread api/src/billing/billing.controller.ts Outdated
Comment thread web/e2e/api-guide.spec.ts Outdated
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Note

Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it.

Fixes Applied Successfully

Fixed 5 file(s) based on 6 unresolved review comments.

Files modified:

  • .coderabbit.yaml
  • api/pnpm-lock.yaml
  • api/src/billing/billing.controller.ts
  • web/e2e/api-guide.spec.ts
  • web/pnpm-lock.yaml

Commit: 5e49637a61bb24d8e10e1241f9bddd37b837785c

The changes have been pushed to the dev branch.

Time taken: 7m 15s


⚠️ 3 file(s) could not be committed — the agent does not have permission to push to .github/workflows/. Please apply these changes manually:

.github/workflows/android.yaml — 1 change:

Lines 53–58
         uses: actions/checkout@v7
         with:
           ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref }}
+          persist-credentials: false
 
       - name: Set up JDK 17
         uses: actions/setup-java@v5

.github/workflows/api.yaml — 1 change:

Lines 47–52
         uses: actions/checkout@v7
         with:
           ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref }}
+          persist-credentials: false
 
       # pnpm has to be on PATH before setup-node, or its pnpm cache resolution
       # has no package manager to query.

.github/workflows/web.yaml — 2 changes:

Lines 46–51
         uses: actions/checkout@v7
         with:
           ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref }}
+          persist-credentials: false
 
       # pnpm has to be on PATH before setup-node, or its pnpm cache resolution
       # has no package manager to query.
Lines 99–104
         uses: actions/checkout@v7
         with:
           ref: ${{ github.event_name == 'workflow_dispatch' && inputs.branch || github.ref }}
+          persist-credentials: false
 
       - name: Install pnpm
         uses: pnpm/action-setup@v6

Fixed 5 file(s) based on 6 unresolved review comments.

Co-authored-by: CodeRabbit <noreply@coderabbit.ai>
vernu and others added 2 commits August 3, 2026 13:12
The bot regenerated both pnpm lockfiles, floating every dependency to the
newest allowed version. That pulled zod 4.4.3 into @polar-sh/sdk, which
broke @polar-sh/sdk/webhooks type resolution and failed the API build on
CI. Restored from 967ddd4 and verified with a local pnpm install (no
diff, zod pinned back to 3.25.76).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The page's first Copy code button belongs to the Base URL chip, so the
exact-match assertion CodeRabbit added could never pass. Click the button
inside the #send-sms section instead, and build the expected snippet from
buildEndpoints() so the test cannot drift from the source template.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
actions/checkout writes the GITHUB_TOKEN into .git/config by default,
where any later step can read it. None of these jobs push or use git
auth after checkout, so persist-credentials: false removes the exposure.
Applies the CodeRabbit suggestion it could not commit itself.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@vernu
vernu merged commit f2b8563 into main Aug 3, 2026
17 checks passed
pull Bot pushed a commit to bryanwills/textbee that referenced this pull request Aug 3, 2026
CodeRabbit's auto-fix agent regenerated both lockfiles on PR vernu#270,
floating zod to v4 inside @polar-sh/sdk and breaking the API build.
Path filters already excluded lockfiles from review but do not stop the
fix agent from committing whatever its sandbox produces.

- lockfile-guard workflow fails any PR where a pnpm-lock.yaml changes
  without its sibling package.json
- packageManager pins pnpm@9.14.2 in api and web, and CI reads the pin
  via package_json_file instead of a loose version: 9
- CI installs use --frozen-lockfile so an out-of-sync lockfile fails at
  install time instead of being silently re-resolved
- .coderabbit.yaml instructs the fix agent to never run installs or
  commit lockfile changes

Closes vernu#271

Co-Authored-By: Claude Fable 5 <noreply@anthropic.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