<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Documentation**
* Updated installation and setup instructions across all documentation,
README files, and getting started guides to use the new Stack CLI
command format for project initialization. Users will now see the
updated command throughout documentation and framework-specific setup
guides.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
### Context
We didn't have an easy place for a user to see their domain statistics
and track their sent emails, either overall or by draft. Additionally,
there was scope creep with the sidebar, where we were supporting more
pages. Our emails landing page was also rather confusing, especially
toggling/ working with different email server types. So, we decide to
add a "sent" page, to track email logs and email statistics, as well as
let users temporarily override their sending limits if need be.
Additionally, a user may want to see a particular email in more detail:
what stage is it in? How did it proceed through time? How can I pause
the sending of this email or change the scheduled time or edit the code?
We allow for that to happen.
### Summary of Changes
#### New Pages
1. **Sent Page:** A Domain Reputation card lets you track how many of
your sent emails were bounced or marked as spam as well as how much
capacity you have left. We also provide a temporary override, where you
can use up to 4 times your capacity for a limited period of time.
Additionally, we provide an email log that lets you see the recently
sent emails. You can also toggle this view from a "list all emails" to
"group by template/draft" which shows stats for each template/draft id
(i.e a bar showing how many emails were sent, are pending, were marked
as spam, were bounced etc, and the total number of emails sent with that
template or draft). Clicking on an email in the list all view takes you
to the "email-viewer" endpoint for that email (see below). Clicking on a
template/draft in the group by view takes you to a page where you can
see the statistics for that template/draft in more detail (the "send"
stage view for that template/draft, as referenced below).
2. **Settings Page:** This is a new page we created because the old
"emails" landing page wasn't doing its job. This page is to track all
the email settings. Currently, we put in 2 sections. A "theme settings"
card where users can see their active theme and click on a button to be
navigated to the themes page. This is necessary as we remove themes from
the sidebar. The other section is a card for email server and domain
configuration - you can change your server type and adjust the settings
or send a test email. It's cleaner and less noisy.
3. **Drafts Page**: There are a lot of changes here. On the landing
page, we actually separate out the drafts into "active drafts" and
"draft history" because drafts are meant to be fire-and-forget, not
reusable. We also add the functionality to create a draft from a
template. This was tricky to manage because templates rely on template
variables which sent to the backend along with the code and injected
during render time. We deal with this by having AI rewrite the template
source code to remove any references to template variables and to make
the draft standalone. The drafts page has been separated into a
stepper-controlled multi stage process:
draft->recipients->schedule->sent. Sent is a read only view that shows
you the statistics of the emails sent using that draft, as mentioned
earlier. You can also see the sent view of a historical draft. You can
also bulk pause/cancel any unsent emails from the sent view of the
drafts.
4. **Sidebar Updates**: The email sidebar now doesn't show "themes" or
"emails" (the old landing page), but it does show "settings" and "sent",
and the default landing page for emails is "sent".
5. **Email Viewer**: When you click on an individual email, you get
navigated here. This has a timeline showing the progress of the email on
the right, and some optional info for the user that's toggleable on the
right bottom, while having either a preview of the email if it's sent or
a way to edit it. You can also change the scheduledAt date of an email
if it hasn't already been sent.
#### Bug Fixes
1. **Search in `TeamMemberSearchTable`**: This was broken. Every time
you tried to enter or remove a character, it would trigger skeleton
loading that overlapped the search bar too, preventing you from
adding/removing more. This was caused because the `useUser` hook
eventually ended up calling a `use` hook, which throws a promise that
triggers a suspense. This, coupled with the fact that the implementation
of `TeamMemberSearchTable` involved a prop-drilling/ dependency
inversion approach to passing down its toolbar to a base table
component, meant the suspense would cover the toolbar too and couldn't
be scoped to just the table. A refactor has gotten rid of the need for
those base components while fixing tables in `payments/customers`,
`teams/team_id`, and `payments/transactions` on top of the existing use
in email drafts recipients stage. We also dedupped some code.
2. **Stale draft fetches on draft landing page**: `useEmailDrafts` uses
an asyncCache to cache the fetched drafts. It is used on the drafts
landing page to render the drafts. When a draft is sent, its `sentAt` is
marked versus when it is still active, it is marked as null. The cache
was stale and so navigating to the landing page after firing off a draft
would errorneously represent that draft as still active and indeed, even
allow you to edit it and fire it again. This violated the principle of
drafts being fire and forget. This has been dealt with by adding
functionality to refresh the draft cache upon firing off a draft.
#### Other Changes
1. We bumped up the base time for the exponential send attempt retry
backoff in `email-queue-step` to 20 seconds. The previous base was two
seconds, and this effectively just made it wait until the next iteration
of the `email-queue-step` cron job or at most an iteration that wasn't
too far away. When an outage with our provider happens, it may take a
while for it to be resolved, so a longer backoff is justified
2. We transitioned the themes page and the templates page to using the
new components, though deeper UI refactors for them were out of scope
for this ticket.
3. We implement a "temporarily increase capacity" button, that bumps up
the throughput/ capacity limit fourfold for a user for a given period of
time. It works like this:
> Clicking the button sets a boost expiredat time.
> When this time is set and still valid, the capacity rate is multiplied
by 4.
> When the button is clicked, trigger a loading spinner until the route
finishes processing.
> When the timer runs out, we reset the button back to its original
state.
> We dont need to wrap the onclick with runAsyncWithAlert because the
component does that already.
4. We add a new default theme: a colorful theme with a lavender base.
This was mainly done so we could have three times in a theme showcase in
the settings page.
### UI Demos
**Sent Page Demo:**
https://github.com/user-attachments/assets/19294a90-bb65-4f00-9a97-111f6c08287f
**Drafts Page Demo**
https://github.com/user-attachments/assets/847609ef-d699-470c-a699-297bb9e17f04
**Settings Page Demo**
https://github.com/user-attachments/assets/190a3829-036a-4f57-89c0-a873bef5a7ce
**Email Viewer Page Demo**
https://github.com/user-attachments/assets/3bc50159-4acb-4865-a4dd-830c84ee4235
---------
Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com>
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Provision local-emulator projects from a local config file and return
emulator credentials via a new internal endpoint.
* Dashboard: "Open config file" flow to open local projects and refresh
owned projects.
* **Changes**
* Branch config can prefer/read/write local files for emulator projects.
* Environment config updates/resets are blocked for local-emulator
projects.
* Dashboard UI shows read-only notices and disables project creation in
emulator mode.
* Added DB mapping and a standard env flag to identify local-emulator
projects.
* **Tests**
* New E2E tests covering provisioning and config restrictions.
* **Chores**
* Removed legacy emulator docs and compose; added CI workflow for
local-emulator E2E runs.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com>
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Full Playground with multi-component live previews and generated TSX
snippets.
* New reusable Design data table and richer editable-grid interfaces.
* **Refactor**
* Replaced legacy UI primitives across many pages with unified Design
components (cards, buttons, alerts, badges, tabs).
* **Improvements**
* PageLayout supports optional content overflow.
* Enhanced inline editing, copy-to-clipboard, async toggles with
confirmation dialogs, dialog/form default value handling, and consistent
alerts/UX.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Konstantin Wohlwend <n2d4xc@gmail.com>
Co-authored-by: nams1570 <amanganapathy@gmail.com>
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Managed email domain onboarding: setup, DNS provisioning,
verification, status checks, and apply flow (Resend-backed).
* **UI**
* Project email settings: managed-provider setup dialog, managed sender
fields, status display, and test-send mapping.
* **Integrations**
* DNS provider automation and Resend webhook handling for domain status
updates; scoped keys for sending.
* **API**
* Admin endpoints / client APIs to setup, check, list, and apply managed
email domains.
* **Tests**
* End-to-end tests covering the full onboarding flow.
* **Chores**
* Added environment variables and config schema support for Resend and
DNS integrations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
DB migration compat / Back-compat — Current branch migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
DB migration compat / Forward-compat — Current branch code with ${{ needs.check-migrations-changed.outputs.base_branch }} branch migrations (push) Has been cancelled
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> **High Risk**
> Touches authentication and OAuth token/authorize flows and changes how
client requests are validated, so regressions could cause widespread
login/client-access failures. Also includes a data migration that alters
effective security posture for existing projects.
>
> **Overview**
> Adds a **project-level toggle**
(`project.requirePublishableClientKey`) to control whether client
requests/OAuth flows must include a publishable client key, including a
DB migration that backfills existing projects to require it.
>
> Backend auth now treats the publishable client key as *optional when
allowed*, introducing a public sentinel (`__stack_public_client__`) and
returning a new specific error
(`PUBLISHABLE_CLIENT_KEY_REQUIRED_FOR_PROJECT`) across smart request
auth + OAuth `authorize`/`callback`/`token` endpoints.
>
> Dashboard and SDKs update key generation/display and request
construction to handle missing publishable keys, expose an advanced
toggle on the Project Keys page, and extend internal config overrides to
support a new `project` level; E2E/tests and schema fuzzing are expanded
accordingly, and CI adds a forward-compat migration check job when
back-compat fails.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
5d06c08613. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Project-level config to require publishable client keys; migration
applied to existing projects.
* **Improvements**
* Auth flows now support optional publishable client keys with explicit
validation and a sentinel for keyless OAuth.
* Dashboard/UI and SDKs handle publishable keys as optional and
conditionally show/generate them.
* Admin/client APIs extended to manage project-level overrides.
* **Bug Fixes**
* Key validation behavior aligned with project config.
* **Tests**
* Expanded E2E and unit tests covering optional/required publishable-key
scenarios.
* **Documentation**
* Spec and knowledge docs updated to describe the sentinel and config
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
DB migrations are backwards-compatible / Test migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
https://www.loom.com/share/09a89533039d4bd4814332ec0728a30f
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added batch analytics event submission API endpoint
* Enhanced session replay timeline with visual markers for page views
and click events
* Display click event counts on replay list items
* Implemented client-side event tracking for page views and clicks
* **Bug Fixes**
* Session replay now properly errors when analytics feature is disabled
* **Tests**
* Added end-to-end tests for analytics events batch API with validation
and querying
* Updated session replay test expectations for analytics error handling
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Browser-side event tracker with batching, navigation & click capture
and background/keepalive delivery
* Server endpoint to accept batched analytics events and associate them
with session replay segments
* Client APIs to send analytics batches and integrate with session
replay
* **Bug Fixes / UX**
* Pausing replay now uses the UI-facing playback time for more accurate
pause positions
* Replay endpoint now returns a clear analytics-disabled error
(ANALYTICS_NOT_ENABLED) when analytics is off
* **Tests**
* End-to-end tests covering batch ingestion, validation, and replay
timing behavior
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added new session replay analytics columns to ClickHouse for enhanced
tracking and reporting
* **Refactor**
* Renamed session recording segment identifier across APIs and data
models from `tab_id` to `session_replay_segment_id`
* Updated internal data structures and type definitions to align with
new naming convention
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
https://www.loom.com/share/3b7c9288149e4f878693281778c9d7e0
## Todos (future PRs)
- Fix pre-login recording
- Better session search (filters, cmd-k, etc)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Analytics → Replays: session recording & multi-tab replay with
timeline, speed, seek, and playback settings; dashboard UI for listing
and viewing replays.
* **Admin APIs**
* Admin endpoints to list recordings, list chunks, fetch chunk events,
and retrieve all events (paginated).
* **Client**
* Client-side rrweb recording with batching, deduplication, upload API
and a send-batch client method.
* **Configuration**
* New STACK_S3_PRIVATE_BUCKET for private session storage.
* **Tests**
* Extensive unit and end-to-end tests for replay logic, streams,
playback, and APIs.
* **Chores**
* Removed an E2E API test GitHub Actions workflow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
DB migrations are backwards-compatible / Test migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Real-time AI search with project-scoped analytics and dynamic query
execution; streaming AI responses replace the placeholder flow.
* External DB sync adds ClickHouse support: users sync, sync metadata
tracking, tenancy-aware status, and per-mapping throttling.
* AI assistant UI shows expandable tool-invocation results and streams
via the real AI pipeline.
* **Chores**
* Dashboard dependencies and workspace exclusions updated; development
OpenAI env var added; editor config flag toggled.
* **Tests**
* E2E coverage extended to validate ClickHouse user sync and analytics
queries.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: aadesh18 <110230993+aadesh18@users.noreply.github.com>
Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
<!--
Make sure you've read the CONTRIBUTING.md guidelines:
https://github.com/stack-auth/stack-auth/blob/dev/CONTRIBUTING.md
-->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved pricing accuracy by implementing proper rounding in unit
price calculations during checkout. This ensures correct cent-level
precision in purchase computations, preventing potential rounding errors
in transaction totals.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
DB migrations are backwards-compatible / Test migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled
<img width="1920" height="969" alt="Screenshot 2026-02-04 at 9 47 16 AM"
src="https://github.com/user-attachments/assets/d7d0cd04-0051-4fc4-b857-e6f87ee97a59"
/>
**This PR revolves around the following components**
1. Sequencer - sequences the updates in the internal db
2. Poller - polls for the latest updates to sync with the external db
3. Outgoing Request Handler - essentially a trigger that can make http
requests based on a change in the internal db
4. Sync Engine - syncs with the latest changes from the internal db to
the external db
**What has been done**
- Added a global sequence id for ProjectUser, ContactChannel and
DeletedRow.
- Added the deletedRow table to keep track of the rows that were deleted
across ProjectUser and ContactChannel.
- Added the OutgoingRequest table to keep track of the outgoing requests
- Added function for the sequencer to call to sequence updates
- Added a sequencer that sequences all the changes in the internal db
every 50 ms
- Added a poller that polls for the latest changes in the internal db
every 50 ms, and adds to a queue
- Added a Vercel cron that calls sequencer and poller every minute
- Added a queue that fulfills the outgoing requests by making http calls
(for external db sync, it calls the sync engine endpoint)
- Added a sync engine that uses the defined sql mapping query in the
user's schema to pull in the changes for the user, and sync them with
the external db
- Added tests to test out each functionality
**How to review this PR:**
1. Review the migrations (sequence id, deletedRow, triggers, backlog
sync) (all files created under the migrations folder)
2. Review sequencer
3. Review poller
4. Review the changes in schema
5. Review sync-engine (the function, and it's helper file)
6. Review the schema changes, and query mappings
7. Review the tests (basic, advanced and race, along with the helper
file)
8. Review the changes made in Dockerfile to support local testing using
the postgres docker
<!-- CURSOR_SUMMARY -->
---
> [!NOTE]
> Introduces a cron-driven external DB sync pipeline with global
sequencing, internal poller and webhook sync engine, new DB
tables/functions, config schema/mappings, and comprehensive e2e tests.
>
> - **Database (Prisma/Migrations)**:
> - Add global sequence (`global_seq_id`) and
`sequenceId`/`shouldUpdateSequenceId` to `ProjectUser`,
`ContactChannel`, `DeletedRow` with partial indexes.
> - Create `DeletedRow` (capture deletes) and `OutgoingRequest` (queue)
tables; add unique/indexes.
> - Add triggers/functions: `log_deleted_row`,
`reset_sequence_id_on_update`, `backfill_null_sequence_ids`,
`enqueue_tenant_sync`.
> - **Backend/API**:
> - New internal routes: `GET
/api/latest/internal/external-db-sync/sequencer`, `GET /poller`, `POST
/sync-engine` (Upstash-verified) for sync orchestration.
> - Add cron wiring: `vercel.json` schedules and local
`scripts/run-cron-jobs.ts`; start in dev via `dev` script.
> - Tweak route handler (remove noisy logging) without behavior change.
> - **Sync Engine**:
> - Implement `src/lib/external-db-sync.ts` to read tenant mappings and
upsert to external Postgres (schema bootstrap, param checks,
sequencing).
> - Add default mappings `DEFAULT_DB_SYNC_MAPPINGS` and config schema
`dbSync.externalDatabases` in shared config.
> - **Testing/Infra**:
> - Add extensive e2e tests (basics, advanced, race conditions) for
sequencing, idempotency, deletes, pagination, multi-mapping, and
permissions.
> - Docker compose: add `external-db-test` Postgres for tests; e2e deps
for `pg` types.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3f2a8efcfb. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* External PostgreSQL sync: automatic, batched replication with
mappings, resume/idempotency, and on-demand enqueueing.
* **Admin UI**
* Real-time External DB Sync dashboard and status API showing
per-mapping backlog, sequencer/poller/sync-engine telemetry, and fusebox
controls.
* **Tests**
* Large e2e suite: basic, advanced, race, high-volume tests and test
utilities for external DB sync.
* **Chores**
* DB migrations, CI/workflow updates, background cron runner and
local/dev test support.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Konsti Wohlwend <n2d4xc@gmail.com>
Co-authored-by: Bilal Godil <bg2002@gmail.com>
<!-- CURSOR_SUMMARY -->
> [!NOTE]
> **High Risk**
> Touches core sign-up/auth flows and user restriction semantics
(including new DB constraints) and introduces dynamic rule
evaluation/logging; misconfiguration or CEL/parser bugs could block
sign-ups or incorrectly restrict users.
>
> **Overview**
> Introduces **CEL-based sign-up rules** (config-driven) that are
evaluated during password/OTP/OAuth sign-ups and anonymous upgrades;
matching rules can reject sign-ups or mark users as admin-restricted,
and triggers are logged for analytics.
>
> Extends `ProjectUser` with `restrictedByAdmin` plus public/private
restriction details, updates restriction computation/filtering, and
exposes these fields via user CRUD (including validation + DB constraint
enforcing consistency when unrestricted).
>
> Adds a new dashboard **Sign-up Rules** page with a visual condition
builder (CEL <-> visual tree), drag-reorder by priority, per-rule 48h
sparkline analytics via a new hidden internal endpoint, and adds
user-page UI to view/edit manual restrictions. Also refactors ClickHouse
client initialization to require env vars (removing
`isClickhouseConfigured` checks) and adjusts CI container startup wait
time.
>
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
2141e689e8c1b72303b805e9234f996010d0880. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Sign-up Rules: visual rule builder, in-project CRUD with drag-reorder,
per-rule analytics, backend evaluation, and admin UI.
* Admin user restrictions: dashboard controls, banners/status,
public/private admin details surfaced in user views.
* **APIs & Schema**
* Config and user schemas extended; new SignUpRejected error and sign-up
rule types added.
* **Tests**
* Extensive unit and E2E coverage for rules, parser, evaluator,
analytics, and restricted-user flows.
* **Docs**
* Editorial guidance added to AGENTS.md.
* **Chores**
* DB statement timeout, updated clean script, minor dependency
additions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
### Context
There are a smattering of bugs on the explore apps page. Clicking
"Enable App" may enable the app, but the button still shows, plus it
causes unnecessary redirects while the modal is still up. This behavior
can be seen in the linked clip
https://github.com/user-attachments/assets/09b12ccf-e174-4289-91f3-4f0e73cfe7e4
### Summary of Changes
We dynamically handle the modal open state, and track the path updates.
This lets us deal with the bugs above while avoiding unnecessary
renders, allowing reopening of previously opened modals, and preventing
unnecessary redirects.
Dealing with the enable apps button issues also now allows users to
navigate to the app page from the explore apps modal.
We also add a disable button to the modal. Previously, users had to
check the options for each app in order to disable it. Now they can do
it on the modal itself, which is in line with how the "Enable App"
functionality works.
### UI Demo
https://github.com/user-attachments/assets/5bfd35c6-5d28-4f99-958a-9300533e2351
<img width="509" height="858" alt="image"
src="https://github.com/user-attachments/assets/520a1a01-f13f-4e20-a3e7-9e47a777b507"
/>
Full image view support:
<img width="2345" height="924" alt="image"
src="https://github.com/user-attachments/assets/f22f7a83-fc47-4d37-a251-56f1fbb62c8f"
/>
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Added interactive fullscreen image preview for changelog entries with
keyboard and click-to-close controls.
* **Improvements**
* Unified changelog date format to US M/D/YY for consistent display.
* Broadened external image loading so changelog images from common hosts
display reliably.
* Inserted image badge placeholders to enhance changelog visuals.
<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
DB migrations are backwards-compatible / Test migrations with ${{ needs.check-migrations-changed.outputs.base_branch }} branch code (push) Has been cancelled