A lexicon-driven AppView for ATProto. happyview.dev
backfill firehose jetstream atproto appview oauth lexicon
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

docs: update 1 for v2.0

Trezy fd9352d2 cd87c9f4

+1518 -813
+5 -11
docs/README.md
··· 6 6 7 7 ## Features 8 8 9 - - 📜 **Lexicon-Driven**: Upload your lexicon schemas and HappyView generates fully functional XRPC query and procedure endpoints automatically, no code required 10 - - 🔄 **Real-Time Sync**: Records stream in from the AT Protocol network in real-time via [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap), with cryptographic verification and backfill via the admin API 11 - - 🔐 **OAuth Built In**: AT Protocol OAuth is handled natively via `atrium-oauth`, and writes are proxied back to the user's PDS with automatic DPoP and token refresh 12 - - 🌙 **Lua Scripting**: Add custom query and procedure logic with Lua scripts that have full access to the record database 13 - - 🗄️ **Automatic Indexing**: HappyView indexes relevant records into PostgreSQL as they arrive, ready to query 14 - - 🪝 **Index Hooks**: Attach Lua scripts to record collections that fire on every create, update, or delete — sync to search engines, trigger webhooks, or build materialized views in real time 15 - - 🌐 **Network Lexicons**: Fetch lexicon schemas directly from the AT Protocol network via DNS authority resolution 16 - - ⚡ **Hot Reloading**: Upload or update lexicons at runtime, and new endpoints are available immediately with no restart 17 - - 🏷️ **Label Support**: Subscribe to external [labelers](guides/labelers.md) and surface content labels on records, with self-label detection and color-coded badges in the dashboard 18 - - 🔌 **Plugin System**: Extend HappyView with WASM [plugins](guides/plugins.md) that integrate with external platforms like Steam, Xbox, and itch.io 19 - - 🛠️ **Admin Dashboard**: Manage lexicons, monitor record stats, and run backfill jobs through a built-in admin API 9 + - **Schema-driven endpoints.** Upload a [lexicon](guides/lexicons.md) and HappyView generates XRPC query and procedure routes, storage, and indexing from it — updatable at runtime with no restart. 10 + - **Network sync built in.** Real-time record streaming via [Jetstream](https://github.com/bluesky-social/jetstream), historical [backfill](guides/backfill.md) from each user's PDS, and AT Protocol OAuth with DPoP-bound proxy writes back to the PDS. 11 + - **Customize with Lua, hooks, and plugins.** [Lua scripts](guides/scripting.md) for query and procedure logic, [index hooks](guides/index-hooks.md) that fire on every record change, WASM [plugins](guides/plugins.md) for external platform integration, and [labeler](guides/labelers.md) subscriptions for content moderation. 12 + - **Protocol-native.** Works with any PDS, resolves DIDs through the directory, and fetches [network lexicons](guides/lexicons.md#network-lexicons) via DNS authority resolution. 13 + - **Full admin surface.** Built-in [dashboard](getting-started/dashboard.md) and [admin API](reference/admin-api.md) for managing lexicons, users, API keys, API clients, backfill jobs, and plugins. 20 14 21 15 ## Design Principles 22 16
+87 -27
docs/getting-started/authentication.md
··· 1 1 # Authentication 2 2 3 - HappyView uses [AT Protocol OAuth](https://atproto.com/specs/oauth) for authentication, handled natively via the `atrium-oauth` library. HappyView manages the full OAuth flow internally — no external auth service is required. 3 + HappyView has two distinct authentication surfaces: 4 + 5 + - **XRPC** (`/xrpc/*`) — client-level identification via an **API client key** on every request, plus optional user-level AT Protocol OAuth for endpoints that need a specific user's identity (e.g. procedures that write to a PDS). 6 + - **Admin API** (`/admin/*`) — user-level authentication via session cookies, admin API keys, or service auth JWTs, gated by [permissions](../guides/permissions.md). 7 + 8 + ## Which endpoints require what? 9 + 10 + | Endpoint type | Client identification | User authentication | 11 + | ----------------------------------- | ------------------------ | ------------------------------------------------------------------------------------ | 12 + | Queries (`GET /xrpc/{method}`) | `X-Client-Key` required | Optional — provide a session if the query needs to know who the user is | 13 + | Procedures (`POST /xrpc/{method}`) | `X-Client-Key` required | Required — a live OAuth session so HappyView can proxy writes to the user's PDS | 14 + | Admin API (`/admin/*`) | — | Required — must be a HappyView user with the right [permissions](../guides/permissions.md) | 15 + | Health check (`GET /health`) | — | — | 16 + 17 + ## XRPC: API client identification 4 18 5 - ## Which endpoints require auth? 19 + Every XRPC request — including unauthenticated `GET` queries — must identify itself with a registered API client. The client key is HappyView's rate-limit bucket key and its way of knowing who is calling. A request without one returns `401 Unauthorized` with `Missing client identification`. 6 20 7 - | Endpoint type | Auth required? | 8 - |---------------|---------------| 9 - | Queries (`GET /xrpc/{method}`) | No | 10 - | Procedures (`POST /xrpc/{method}`) | Yes | 11 - | Admin API (`/admin/*`) | Yes (must be a user with appropriate [permissions](../guides/permissions.md)) | 12 - | Health check (`GET /health`) | No | 21 + Register a client in the dashboard (**Settings > API Clients > New client**) or via `POST /admin/api-clients`. You'll get back an `hvc_…` client key and an `hvs_…` client secret — **the secret is only shown once**, so capture it immediately. 22 + 23 + HappyView resolves the client key from the first of: 24 + 25 + 1. The session cookie, if the user logged in through this client's OAuth flow (the cookie carries the `client_key` that minted it). 26 + 2. The `X-Client-Key` request header. 27 + 3. A `client_key` query-string parameter. 13 28 14 - Authentication uses signed session cookies set during the OAuth login flow. For programmatic access, API keys (prefixed `hv_`) are also supported via the `Authorization: Bearer` header. 29 + On top of the client key, HappyView does best-effort validation that the caller actually controls the client: 15 30 16 - ## Logging in via the dashboard 31 + - If an `Origin` header is present (typical for browser apps), it must match the client's registered `client_uri`. 32 + - Otherwise, an `X-Client-Secret` header may be supplied and must match the stored secret (typical for server-to-server callers). 17 33 18 - 1. Open the dashboard and click **Log in** 19 - 2. Enter your AT Protocol handle (e.g. `user.bsky.social`) 20 - 3. You'll be redirected to your identity provider's authorization page 21 - 4. After approving, you're redirected back to HappyView with a session cookie set 34 + Both checks currently log warnings on mismatch rather than rejecting the request, but the intent is clear: don't share client keys, and treat the secret like a password. 22 35 23 - The session cookie is HttpOnly and signed. It persists across browser sessions until you log out or the OAuth session expires. 36 + ### Calling a query 24 37 25 - ## Programmatic access 38 + ```sh 39 + curl 'https://happyview.example.com/xrpc/com.example.feed.getHot' \ 40 + -H 'X-Client-Key: hvc_a1b2c3...' 41 + ``` 26 42 27 - For scripts or CI/CD pipelines, use [API keys](../guides/api-keys.md) instead of OAuth: 43 + For a server-to-server integration, add the secret: 44 + 45 + ```sh 46 + curl 'https://happyview.example.com/xrpc/com.example.feed.getHot' \ 47 + -H 'X-Client-Key: hvc_a1b2c3...' \ 48 + -H 'X-Client-Secret: hvs_d4e5f6...' 49 + ``` 50 + 51 + ### Logging a user in so you can call procedures 52 + 53 + Queries that don't care who is calling need nothing more than the client key. Procedures — and queries whose Lua scripts read the caller's DID — need a real AT Protocol OAuth session. The shape of the flow: 54 + 55 + 1. Publish a client metadata document at your API client's `client_id_url`. 56 + 2. Redirect the user to HappyView's OAuth authorize endpoint with your `hvc_…` key as `client_id`. 57 + 3. Exchange the authorization code at the token endpoint using your client key + `hvs_…` secret. 58 + 4. HappyView sets a signed session cookie containing the user's DID and your client key. Subsequent XRPC requests made with that cookie are automatically attributed to your client — you don't need to also send `X-Client-Key`. 59 + 60 + For procedures, HappyView proxies the write to the user's PDS using the stored OAuth session (see [Proxying procedures](#proxying-procedures-to-the-users-pds) below). 61 + 62 + ## Admin API: user authentication 63 + 64 + Admin endpoints don't use API clients. They require a real HappyView user, identified by one of three methods: 65 + 66 + ### Session cookie (dashboard) 67 + 68 + When you log in to the dashboard via AT Protocol OAuth, HappyView sets a signed, HttpOnly session cookie containing your DID. That cookie is honored on admin endpoints as long as the DID is a HappyView user with the required permission for the call. 69 + 70 + ### Admin API key 71 + 72 + For automation — CI/CD, monitoring, cron jobs — create an [admin API key](../guides/api-keys.md) at **Settings > API Keys** or via `POST /admin/api-keys` and pass it as a bearer token: 28 73 29 74 ```sh 30 75 export TOKEN="hv_your-api-key-here" ··· 32 77 -H "Authorization: Bearer $TOKEN" 33 78 ``` 34 79 35 - API keys are created via the dashboard or `POST /admin/api-keys`. See the [API Keys guide](../guides/api-keys.md) for details. 80 + A key only carries the permissions selected at creation time and can never exceed the permissions of the user who created it. Admin API keys are not valid for XRPC endpoints — they exist solely for admin API access. 81 + 82 + ### Service auth JWT 83 + 84 + HappyView also accepts standard AT Protocol inter-service auth JWTs in the `Authorization` header. Another AppView, relay, or PDS can sign a short-lived ES256 or ES256K JWT with its DID's signing key; HappyView resolves the issuer's DID document, verifies the signature against the `#atproto` verification method, and treats the issuer DID as the caller identity. 85 + 86 + For a service auth JWT to validate: 36 87 37 - ## How authentication works 88 + - `alg` must be `ES256` or `ES256K`. 89 + - `typ` must not be `at+jwt`, `refresh+jwt`, or `dpop+jwt` (those are other token types, not inter-service JWTs). 90 + - `exp` must be in the future. 91 + - The signature must verify against the issuer DID's atproto signing key. 38 92 39 - HappyView supports three authentication methods: 93 + As with the other methods, the resolved DID still has to exist in the HappyView `users` table with the right permissions to hit admin endpoints — service auth gets you identified, not privileged. 40 94 41 - 1. **Session cookie** (web UI) — Set during the OAuth callback flow. The signed cookie contains the user's DID, which HappyView reads on each request. 42 - 2. **API key** (programmatic) — Bearer tokens starting with `hv_`. HappyView looks up the key hash in the database to resolve the caller's DID and permissions. 43 - 3. **Service auth JWT** (AT Protocol inter-service) — Standard AT Protocol service authentication via signed JWTs. HappyView validates the signature by resolving the issuer's DID document. 95 + ### Admin access and the first user 44 96 45 - For write operations (procedures), HappyView uses the stored OAuth session to proxy writes to the user's PDS. The `atrium-oauth` library handles DPoP proof generation and token refresh automatically. 97 + On a fresh deployment, the `users` table is empty. The first authenticated request to any admin endpoint auto-bootstraps that user as the **super user** with all permissions granted — so the first handle to log in owns the instance. 46 98 47 - ## Admin access 99 + To add more users after that, use `POST /admin/users` or the [dashboard](dashboard.md). You can assign permissions individually or use a template (`viewer`, `operator`, `manager`, `full_access`). See [Admin API](../reference/admin-api.md#user-management) for details. 100 + 101 + ## Proxying procedures to the user's PDS 48 102 49 - Admin endpoints require the authenticated user's DID to exist in the `users` table with the appropriate [permissions](../guides/permissions.md). If the table is empty (fresh deployment), the first authenticated request to any admin endpoint auto-bootstraps that user as the **super user** with all permissions granted. 103 + When a client calls an XRPC procedure that writes a record, HappyView proxies the write to the user's PDS using the user's stored OAuth session. `atrium-oauth` attaches a DPoP proof and a DPoP-bound access token to the outbound request automatically — HappyView doesn't do any manual DPoP handling. 50 104 51 - To add more users, use `POST /admin/users` or the [dashboard](dashboard.md). You can assign permissions individually or use a template (`viewer`, `operator`, `manager`, `full_access`). See [Admin API](../reference/admin-api.md#user-management) for details. 105 + This only works if HappyView has a live OAuth session for the caller, which in practice means the caller logged in through the dashboard or through an API client's OAuth flow. A request that only carries an `X-Client-Key` header (no session cookie) can hit queries but can't be used to proxy writes — there's no user to write as. Service auth JWTs and admin API keys similarly don't carry a user OAuth session. 106 + 107 + ## Next steps 108 + 109 + - [Permissions](../guides/permissions.md) — full list of permissions and what each one grants 110 + - [API Keys](../guides/api-keys.md) — create scoped admin API keys for automation 111 + - [Admin API — API Clients](../reference/admin-api.md#api-clients) — register API clients and configure rate limits
+16 -4
docs/getting-started/configuration.md
··· 12 12 | `SESSION_SECRET` | no | dev default | Secret key for signing session cookies. **Must be set in production** | 13 13 | `HOST` | no | `0.0.0.0` | Bind host | 14 14 | `PORT` | no | `3000` | Bind port | 15 - | `TAP_URL` | no | `http://localhost:2480` | [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) instance URL for real-time record streaming and backfill | 16 - | `TAP_ADMIN_PASSWORD` | no | --- | Shared secret for authenticating with Tap's admin endpoints | 15 + | `JETSTREAM_URL` | no | `wss://jetstream1.us-east.bsky.network` | Jetstream WebSocket URL for real-time record streaming | 17 16 | `RELAY_URL` | no | `https://bsky.network` | Relay URL for [backfill](../guides/backfill.md) repo discovery | 18 17 | `PLC_URL` | no | `https://plc.directory` | [PLC directory](https://github.com/did-method-plc/did-method-plc) URL for DID resolution | 18 + | `STATIC_DIR` | no | `./web/out` | Directory containing the built dashboard static assets | 19 19 | `EVENT_LOG_RETENTION_DAYS` | no | `30` | Number of days to keep event logs before automatic cleanup. Set to `0` to disable cleanup | 20 + | `TOKEN_ENCRYPTION_KEY` | no | --- | Base64-encoded 32-byte key for encrypting stored OAuth tokens. **Strongly recommended in production** | 21 + | `DEFAULT_RATE_LIMIT_CAPACITY` | no | `100` | Default token bucket capacity used when registering a new API client | 22 + | `DEFAULT_RATE_LIMIT_REFILL_RATE` | no | `2.0` | Default token bucket refill rate (tokens/second) for new API clients | 20 23 | `RUST_LOG` | no | `happyview=debug,tower_http=debug` | Log filter (uses `tracing_subscriber::EnvFilter`) | 21 24 | `APP_NAME` | no | --- | Application name shown on OAuth authorization screens. Overridden by database setting if set via admin API | 22 25 | `LOGO_URI` | no | --- | URL to application logo for OAuth screens. Overridden by database setting or logo upload | ··· 37 40 # Optional overrides 38 41 # HOST=0.0.0.0 39 42 # PORT=3000 40 - # TAP_URL=http://localhost:2480 41 - # TAP_ADMIN_PASSWORD=your-secret-here 43 + # JETSTREAM_URL=wss://jetstream1.us-east.bsky.network 42 44 # RELAY_URL=https://bsky.network 43 45 # PLC_URL=https://plc.directory 46 + # STATIC_DIR=./web/out 44 47 # EVENT_LOG_RETENTION_DAYS=30 48 + # TOKEN_ENCRYPTION_KEY=base64-encoded-32-byte-key 49 + # DEFAULT_RATE_LIMIT_CAPACITY=100 50 + # DEFAULT_RATE_LIMIT_REFILL_RATE=2.0 45 51 # RUST_LOG=happyview=debug,tower_http=debug 46 52 # APP_NAME=My App 47 53 # LOGO_URI=https://example.com/logo.png 48 54 # TOS_URI=https://example.com/tos 49 55 # POLICY_URI=https://example.com/privacy 50 56 ``` 57 + 58 + ## Next steps 59 + 60 + - [Authentication](authentication.md) — set up OAuth and admin users 61 + - [Dashboard](dashboard.md) — explore the admin dashboard 62 + - [Production deployment](../reference/production-deployment.md) — deploy HappyView to production
+9 -13
docs/getting-started/dashboard.md
··· 1 1 # Dashboard 2 2 3 - HappyView ships with a web dashboard that provides a visual interface for everything the [admin API](../reference/admin-api.md) offers: managing lexicons, viewing indexed records, and monitoring backfill jobs. It runs as a separate Next.js application alongside the Rust backend. 4 - 5 - ## Logging in for the first time 6 - 7 - The dashboard uses AT Protocol OAuth. Click **Log in** and enter your handle to authenticate. If no users exist in the database yet, the first authenticated request to any admin endpoint automatically bootstraps that user as the super user with all permissions. 3 + HappyView ships with a web dashboard that provides a visual interface for everything the [admin API](../reference/admin-api.md) offers: managing lexicons, viewing indexed records, and monitoring backfill jobs. It runs as a separate Next.js application alongside the Rust backend and authenticates via AT Protocol OAuth. 8 4 9 - ## Settings 10 - 11 - The **Settings** page is organized into sub-pages accessible from the collapsible sidebar: 12 - 13 - - **Users** — manage user accounts and permissions 14 - - **ENV Variables** — view and edit script variables 15 - - **API Keys** — create and revoke API keys 5 + On a fresh deployment with no users in the database, the first handle to log in is automatically bootstrapped as the super user with all permissions — so log in with the handle you want to own the instance first. 16 6 17 7 ## Adding a lexicon 18 8 ··· 29 19 30 20 Toggle **Enable backfill** to index historical records when uploading a record-type lexicon. 31 21 32 - **Network** lexicons are fetched from the AT Protocol network. Enter an NSID (e.g. `xyz.statusphere.status`) and HappyView resolves the schema automatically. If found, the lexicon JSON is displayed in a read-only editor. Click **Add** to track it. Network lexicons are kept up to date via Tap. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons) for how resolution works. 22 + **Network** lexicons are fetched from the AT Protocol network. Enter an NSID (e.g. `xyz.statusphere.status`) and HappyView resolves the schema automatically. If found, the lexicon JSON is displayed in a read-only editor. Click **Add** to track it. Network lexicons are kept up to date via the Jetstream subscription. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons) for how resolution works. 33 23 34 24 ### JSON editor 35 25 ··· 44 34 The Lua editor provides context-aware code completions, including suggestions for the `Record`, `db`, `input`, and `params` APIs as well as Lua keywords, builtins, and standard library functions. It also offers snippet templates for common constructs like `if`, `for`, and `function`. 45 35 46 36 See [Lua Scripting](../guides/scripting.md) for the full runtime reference and examples. 37 + 38 + ## Next steps 39 + 40 + - [Lexicons](../guides/lexicons.md) — how lexicons drive HappyView's indexing and routing 41 + - [Lua Scripting](../guides/scripting.md) — write custom query and procedure logic 42 + - [Permissions](../guides/permissions.md) — manage user access to admin features
+9 -14
docs/getting-started/deployment/docker.md
··· 1 1 # Local Development with Docker 2 2 3 - This guide runs the full HappyView stack locally using Docker Compose: [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap), HappyView, and the web dashboard. 3 + This guide runs HappyView and the dashboard locally using Docker Compose. 4 4 5 5 ## Prerequisites 6 6 ··· 14 14 cp .env.example .env 15 15 ``` 16 16 17 - Set `TAP_ADMIN_PASSWORD` in your `.env`. This shared secret is used by both Tap and HappyView: 18 - 19 - ```sh 20 - TAP_ADMIN_PASSWORD=your-secret-here 21 - ``` 22 - 23 - The `docker-compose.yml` configures everything else (service connections) automatically. See the [database setup guide](../../guides/database-setup.md) if you want to use Postgres instead. 17 + Edit `.env` and set at least `PUBLIC_URL` (e.g. `http://localhost:3000`) and `SESSION_SECRET`. The defaults work for everything else. See [Configuration](../configuration.md) for the full list of environment variables. 24 18 25 19 ## 2. Start the stack 26 20 ··· 30 24 31 25 This starts: 32 26 33 - | Service | Port | Description | 34 - | ------------- | ---- | ---------------------------------- | 35 - | **tap** | 2480 | Firehose consumer, backfill worker | 36 - | **happyview** | 3000 | HappyView API server | 37 - | **web** | 3001 | Next.js dashboard | 27 + | Service | Port | Description | 28 + | ------------- | ---- | --------------------- | 29 + | **happyview** | 3000 | HappyView API server | 30 + | **web** | 3001 | Next.js dashboard | 38 31 39 32 HappyView runs migrations automatically on startup. The first build will take a few minutes while Rust compiles. 33 + 34 + The `happyview` container serves its own bundled dashboard at `http://localhost:3000`, but that copy is baked in at container build time and only updates when you rebuild the image. For day-to-day development, use the dev dashboard at `http://localhost:3001` — it hot-reloads on changes to the `web/` source. 40 35 41 36 :::tip 42 - To use Postgres instead of SQLite, uncomment the `postgres` service in `docker-compose.yml` and update `DATABASE_URL` in `.env`. See the [database setup guide](../../guides/database-setup.md). 37 + SQLite is the default and requires no extra services. To use Postgres instead, uncomment the `postgres` service in `docker-compose.yml` and update `DATABASE_URL` in `.env`. See the [database setup guide](../../guides/database-setup.md). 43 38 ::: 44 39 45 40 ## Next steps
+1 -4
docs/getting-started/deployment/other.md
··· 1 1 # Local Development from Source 2 2 3 - This guide runs HappyView directly with `cargo run`, with you managing Tap separately. If you'd rather use Docker Compose to run everything together, see [Local Development with Docker](docker.md). 3 + This guide runs HappyView directly with `cargo run`. If you'd rather use Docker Compose, see [Local Development with Docker](docker.md). 4 4 5 5 ## Prerequisites 6 6 7 7 - Rust (stable) 8 - - A running [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) instance (delivers real-time records and handles backfill). See the [Tap documentation](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) for setup. 9 8 - (Optional) PostgreSQL 17+ if you prefer Postgres over the default SQLite 10 9 11 10 ## 1. Clone and configure ··· 23 22 DATABASE_URL=sqlite://data/happyview.db?mode=rwc 24 23 PUBLIC_URL=http://localhost:3000 25 24 SESSION_SECRET=change-me-in-production 26 - TAP_URL=http://localhost:2480 27 - TAP_ADMIN_PASSWORD=your-secret-here 28 25 ``` 29 26 30 27 Or if you prefer Postgres:
+7 -1
docs/getting-started/deployment/railway.md
··· 1 1 # Deploy on Railway 2 2 3 - The fastest way to get HappyView running is with Railway. This template deploys HappyView, [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) (real-time data and backfill), and Postgres with a single click: 3 + The fastest way to get HappyView running is with Railway. This template deploys HappyView and Postgres with a single click: 4 4 5 5 [![Deploy on Railway](https://railway.com/button.svg)](https://railway.com/deploy/happyview?referralCode=0QOgj_) 6 6 ··· 16 16 ::: 17 17 18 18 3. Access your HappyView dashboard at the instance's public URL. The first user to log in is automatically bootstrapped as the super user. 19 + 20 + ## Next steps 21 + 22 + - [Configuration](../configuration.md) — full list of environment variables 23 + - [Dashboard](../dashboard.md) — manage lexicons, users, and plugins via the web UI 24 + - [Production deployment](../../reference/production-deployment.md) — hardening checklist for production instances
+4 -8
docs/getting-started/quickstart.md
··· 8 8 9 9 | Option | Best for | 10 10 | ------------------------------------------ | ------------------------------------------------------------------------------------ | 11 - | [**Railway**](deployment/railway.md) | Fastest path — one-click deploy of the full stack (HappyView + Tap + Postgres) | 11 + | [**Railway**](deployment/railway.md) | Fastest path — one-click deploy of HappyView + Postgres | 12 12 | [**Docker Compose**](deployment/docker.md) | Local development with the full stack in containers | 13 13 | [**From source**](deployment/other.md) | Running HappyView with `cargo run` and managing dependencies yourself | 14 14 ··· 16 16 17 17 ## 2. Log in to the dashboard 18 18 19 - Open your HappyView instance in a browser. The built-in [dashboard](dashboard.md) is served at the root URL. 20 - 21 - Click **Log in** and authenticate with your AT Protocol identity. On a fresh deployment with no users configured, the first authenticated request to any admin endpoint automatically bootstraps that user as the **super user** with all permissions granted. 19 + The built-in [dashboard](dashboard.md) is served at your instance's root URL. Log in with your AT Protocol identity — on a fresh deployment, the first handle to authenticate is automatically bootstrapped as the **super user** with all permissions, so use the handle you want to own the instance. 22 20 23 21 ## 3. Add your first lexicon 24 22 ··· 29 27 3. HappyView resolves the schema from the AT Protocol network and shows a preview 30 28 4. Click **Add** 31 29 32 - HappyView immediately starts indexing records for that collection. A backfill job is created to fetch historical records, and new records stream in via Tap in real time. 30 + HappyView immediately starts indexing records for that collection. A backfill job is created to fetch historical records, and new records stream in via Jetstream in real time. 33 31 34 32 You can also upload lexicons manually via the dashboard or the [admin API](../reference/admin-api.md). See [Lexicons](../guides/lexicons.md) for the full details. 35 33 36 34 ## 4. Verify records are being indexed 37 35 38 - Go to the **Dashboard** home page. The stat cards show the total record count and a breakdown by collection. You can also browse indexed records on the **Records** page. 39 - 40 - To check backfill progress, go to the **Backfill** page. The Tap stats cards show how many repos and records Tap has processed. 36 + The dashboard home shows a live record count and a per-collection breakdown. For a deeper look, browse **Records** to inspect individual rows or **Backfill** to watch the historical fetch job drain. 41 37 42 38 ## 5. Query your data 43 39
+9 -9
docs/guides/backfill.md
··· 1 1 # Backfill 2 2 3 - When you add a new record-type lexicon, HappyView starts indexing new records from that moment via [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap). But what about records that already exist on the network? That's what backfill does: HappyView discovers repos via the relay and delegates the actual record fetching to Tap. 3 + When you add a new record-type lexicon, HappyView starts indexing new records from that moment via [Jetstream](https://github.com/bluesky-social/jetstream). But what about records that already exist on the network? That's what backfill does: HappyView discovers repos via the relay and fetches records directly from each user's PDS. 4 4 5 5 ## When backfill runs 6 6 ··· 12 12 ## How it works 13 13 14 14 1. **Determine target collections**: uses the specified collection, or all record lexicons with `backfill: true` 15 - 2. **Discover DIDs**: HappyView calls the relay's `com.atproto.sync.listReposByCollection` to find repos that contain records for each target collection (paginated, 1000 per page) 16 - 3. **Delegate to Tap**: HappyView sends discovered DIDs to Tap in batches of 1000 via its `/repos/add` endpoint 17 - 4. **Tap fetches records**: Tap handles the actual record fetching from each user's PDS and delivers them to HappyView via the WebSocket channel 15 + 2. **Discover DIDs**: HappyView calls the relay's `com.atproto.sync.listReposByCollection` to find repos that contain records for each target collection (paginated) 16 + 3. **Resolve each PDS**: for each discovered DID, HappyView resolves the DID document via PLC to find the user's PDS endpoint 17 + 4. **Fetch records**: HappyView calls `com.atproto.repo.listRecords` on each PDS for the target collection (paginated) and upserts each record into the local database 18 + 5. **Track progress**: counters for `processed_repos` and `total_records` are updated as the job runs 18 19 19 20 ## Job lifecycle 20 21 21 - HappyView marks a backfill job as "completed" once it finishes discovering repos and handing DIDs off to Tap (steps 1-3). This does **not** mean Tap has finished processing all the records. Tap works through them asynchronously after the handoff. 22 + A backfill job moves through `pending → running → completed` (or `failed`). Unlike earlier versions of HappyView, the job is only marked `completed` once every discovered repo has been processed end-to-end — there is no separate downstream queue. Progress is visible in real time on the dashboard's Backfill page. 22 23 23 - To see whether Tap is still working through the backlog, check the Tap stats on the dashboard's Backfill page or via `GET /admin/tap/stats`. The **outbox buffer** indicates how many events are still queued for delivery; a high number means Tap is actively processing. 24 + If a job fails midway, the `error` field contains the failure reason. Re-running the backfill resumes from scratch but is idempotent (records are upserted by URI). 24 25 25 26 ## Re-running backfills 26 27 27 - Re-running a backfill for a collection that's already been backfilled is safe. HappyView removes the discovered repos from Tap before re-adding them, which clears Tap's cached state and forces a full re-fetch of all records from each repo's PDS. This means re-running a backfill will restore any records that were previously deleted from HappyView, as well as pick up repos that were added to the network since the last run. 28 + Re-running a backfill for a collection that's already been backfilled is safe. Each record is upserted by its AT URI, so existing records are refreshed in place and any new records discovered since the last run are added. This also picks up new repos that have joined the network since the previous backfill. 28 29 29 30 ## Restoring deleted records 30 31 31 - Deleting records from HappyView (via the dashboard or API) only removes them from the local database — the records still exist on the AT Protocol network. To restore deleted records, create a backfill job for the affected collection. The backfill will clear Tap's cache for the discovered repos and re-fetch all records from the network, restoring any that were previously deleted. 32 + Deleting records from HappyView (via the dashboard or API) only removes them from the local database — the records still exist on the AT Protocol network. To restore deleted records, create a backfill job for the affected collection. The backfill will re-discover the repos and re-fetch all records from each PDS, restoring any that were previously deleted. 32 33 33 34 ## Next steps 34 35 35 36 - [Lexicons](lexicons.md#backfill-flag): Control whether lexicons trigger backfill on upload 36 37 - [Admin API](../reference/admin-api.md#backfill): Full reference for backfill endpoints 37 - - [Admin API - Tap Stats](../reference/admin-api.md#tap-stats): Monitor Tap's processing progress
+7 -1
docs/guides/database-setup.md
··· 52 52 The default `docker-compose.yml` ships with the Postgres service commented out. To use Postgres: 53 53 54 54 1. Uncomment the `postgres` service and `pgdata` volume in `docker-compose.yml` 55 - 2. Uncomment the `depends_on: postgres` blocks in the `tap` and `happyview` services 55 + 2. Uncomment the `depends_on: postgres` block in the `happyview` service 56 56 3. Update `DATABASE_URL` in `.env`: 57 57 ```sh 58 58 DATABASE_URL=postgres://happyview:happyview@postgres/happyview ··· 69 69 Both backends support the same Lua database API (`db.query`, `db.get`, `db.count`). Write SQL in **SQLite syntax** by default. If you are using Postgres, HappyView automatically translates common SQLite patterns to Postgres equivalents at runtime. 70 70 71 71 If you are migrating existing Lua scripts from Postgres SQL syntax to SQLite syntax, see the [Postgres to SQLite migration guide](postgres-to-sqlite-migration.md). 72 + 73 + ## Next steps 74 + 75 + - [Postgres → SQLite migration](postgres-to-sqlite-migration.md) — switch an existing instance from Postgres to SQLite 76 + - [Lua scripting](scripting.md) — write queries that target either backend 77 + - [Configuration](../getting-started/configuration.md) — `DATABASE_URL` and related variables
+12 -6
docs/guides/event-logs.md
··· 1 1 # Event Logs 2 2 3 - HappyView maintains an internal event log that records system activity — lexicon changes, record operations, Lua script executions and errors, user actions, API key events, backfill jobs, and Tap connectivity. Events are stored in a Postgres table and queryable via the [admin API](../reference/admin-api.md#event-logs). 3 + HappyView maintains an internal event log that records system activity — lexicon changes, record operations, Lua script executions and errors, user actions, API key events, backfill jobs, and Jetstream connectivity. Events are stored in the database and queryable via the [admin API](../reference/admin-api.md#event-logs). 4 4 5 5 ## Event types 6 6 ··· 23 23 | `record.created` | info | Record AT URI | `collection`, `did`, `rkey` | 24 24 | `record.deleted` | info | Record AT URI | `collection`, `did`, `rkey` | 25 25 26 - Logged when records are received from Tap and stored or removed from the local database. These are system-triggered events (`actor_did` is null). If a database error occurs during the operation, the same event type is logged with `error` severity and the error message is included in the detail. 26 + Logged when records are received from Jetstream and stored or removed from the local database. These are system-triggered events (`actor_did` is null). If a database error occurs during the operation, the same event type is logged with `error` severity and the error message is included in the detail. 27 27 28 28 ### Script events 29 29 ··· 91 91 92 92 See [Backfill](backfill.md) for background on backfill jobs. 93 93 94 - ### Tap events 94 + ### Jetstream events 95 95 96 96 | Event Type | Severity | Subject | Detail | 97 97 |---|---|---|---| 98 - | `tap.connected` | info | — | `url` | 99 - | `tap.disconnected` | warn | — | `reason` | 98 + | `jetstream.connected` | info | — | `url` | 99 + | `jetstream.disconnected` | warn | — | `reason` | 100 100 101 - Logged when the WebSocket connection to [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) is established or lost. 101 + Logged when the WebSocket connection to [Jetstream](https://github.com/bluesky-social/jetstream) is established or lost. 102 102 103 103 ## Querying events 104 104 ··· 127 127 Set `EVENT_LOG_RETENTION_DAYS=0` to disable automatic cleanup and keep logs indefinitely. 128 128 129 129 See [Configuration](../getting-started/configuration.md) for all environment variables. 130 + 131 + ## Next steps 132 + 133 + - [Admin API — Event Logs](../reference/admin-api.md#event-logs) — full query parameters and response format 134 + - [Permissions](permissions.md) — control which users can read event logs 135 + - [Troubleshooting](../reference/troubleshooting.md) — using event logs to diagnose issues
+26 -7
docs/guides/lexicons.md
··· 8 8 9 9 | Type | Effect | 10 10 | ------------- | ------------------------------------------------------------------------------ | 11 - | `record` | Syncs the collection filter to Tap and indexes records into Postgres. Supports [index hooks](index-hooks.md) | 11 + | `record` | Adds the collection to the Jetstream subscription filter and indexes records into the database. Supports [index hooks](index-hooks.md) | 12 12 | `query` | Registers a `GET /xrpc/{nsid}` endpoint that queries indexed records | 13 13 | `procedure` | Registers a `POST /xrpc/{nsid}` endpoint that proxies writes to the user's PDS | 14 14 | `definitions` | Stored but does not generate routes or subscriptions | ··· 31 31 32 32 When uploading a record-type lexicon, HappyView automatically creates a backfill job to discover existing records. If you only want to index new records going forward, you can set `backfill` to `false`. 33 33 34 - ## Tap collection filters 34 + ## Jetstream collection filters 35 35 36 - When record-type lexicons change (uploaded or deleted), HappyView automatically syncs the updated collection filter to Tap. HappyView always includes `com.atproto.lexicon.schema` in the filter to track network lexicon updates. 36 + When record-type lexicons change (uploaded or deleted), HappyView reconnects to Jetstream with an updated collection filter. HappyView always includes `com.atproto.lexicon.schema` in the filter to track network lexicon updates. 37 37 38 - Deleting a lexicon updates Tap's collection filters (stopping live indexing for that collection) but does **not** remove previously indexed repos or their cached state from Tap. To fully reset a collection's state, delete the lexicon, re-add it, and run a [backfill](backfill.md). 38 + Deleting a lexicon stops live indexing for that collection but does **not** remove previously indexed records from the database. To fully reset a collection's state, delete the lexicon and the associated records, re-add the lexicon, and run a [backfill](backfill.md). 39 39 40 40 ## Network lexicons 41 41 42 - If a lexicon has already been published, you don't need to upload the JSON manually. Point HappyView at the NSID and it fetches the lexicon directly from the network. Network lexicons are kept updated automatically via Tap. If the publisher updates their schema, your instance will pick up the change. 42 + If a lexicon has already been published, you don't need to upload the JSON manually. Point HappyView at the NSID and it fetches the lexicon directly from the network. Network lexicons are kept updated automatically via the Jetstream subscription. If the publisher updates their schema, your instance will pick up the change. 43 43 44 44 ### NSID authority resolution 45 45 ··· 65 65 66 66 The `value` field of the response is the raw lexicon JSON. 67 67 68 - ### Live updates via Tap 68 + ### Live updates via Jetstream 69 69 70 - Tap always subscribes to `com.atproto.lexicon.schema` alongside the dynamic record collections. When a record event arrives: 70 + The Jetstream subscription always includes `com.atproto.lexicon.schema` alongside the dynamic record collections. When a record event arrives: 71 71 72 72 - **create/update**: If the event's DID and rkey match a tracked network lexicon (`authority_did` and `nsid`), the lexicon is parsed, upserted into the `lexicons` table and in-memory registry, and collection filters are updated if it's a record type. 73 73 - **delete**: The lexicon is removed from the `lexicons` table and registry. ··· 75 75 ### Startup re-fetch 76 76 77 77 On every startup, HappyView re-fetches all network lexicons from their respective PDSes. This ensures consistency even if events were missed while offline. Failures are logged as warnings but don't block startup. 78 + 79 + ## XRPC routing for unknown methods 80 + 81 + When a client calls `/xrpc/{method}` and HappyView has a local lexicon (with a handler or Lua script) for that NSID, the request is served locally. Otherwise, HappyView proxies the request to the method's **home authority** using the same DNS-based authority resolution described above: 82 + 83 + 1. Extract the authority from the NSID (all segments except the last). `com.example.foo.getBar` → authority `com.example.foo`. 84 + 2. Reverse it to form a domain: `foo.example.com`. 85 + 3. Look up the `_lexicon.foo.example.com` TXT record for the authority's DID. 86 + 4. Resolve that DID to a PDS endpoint via the PLC directory. 87 + 5. Proxy the request to `{pds_endpoint}/xrpc/{method}`. 88 + 89 + A few things to note: 90 + 91 + - HappyView does **not** proxy to the reversed hostname directly. `foo.example.com` is only the DNS host for the TXT record — the actual XRPC request goes to whatever PDS endpoint the authority DID resolves to. 92 + - Proxying applies equally to queries and procedures. For procedures, HappyView uses the caller's OAuth session to attach a DPoP-bound access token (see [Authentication](../getting-started/authentication.md#proxying-procedures-to-the-users-pds)). 93 + - If authority resolution fails — no TXT record, unresolvable DID, or the target PDS 404s the method — the client gets an error back. HappyView does not fall back to any other routing strategy. 94 + - "Network lexicons" (lexicons you've explicitly tracked via the dashboard) are only about **indexing** record collections and keeping the schema up to date. They don't add handler logic. An unknown query against a tracked network lexicon still proxies out — it doesn't run against your local record table unless you also upload a local query lexicon with a matching `target_collection`. 95 + 96 + In short: if you want to serve an XRPC method on your instance, you need a local lexicon for it. Otherwise HappyView acts as a pass-through to the method's home PDS. 78 97 79 98 ## Next steps 80 99
+1 -1
docs/guides/permissions.md
··· 53 53 |---|---| 54 54 | `backfill:create` | Start backfill jobs | 55 55 | `backfill:read` | View backfill job status | 56 - | `stats:read` | View record and Tap statistics | 56 + | `stats:read` | View record statistics | 57 57 | `events:read` | Query the event log | 58 58 59 59 ## Permission templates
+4
docs/guides/plugins.md
··· 119 119 | `GET /admin/plugins` | List installed plugins | 120 120 | `POST /admin/plugins` | Install a plugin | 121 121 | `POST /admin/plugins/preview` | Preview plugin before installing | 122 + | `GET /admin/plugins/official` | Browse the official plugin registry catalog | 122 123 | `DELETE /admin/plugins/{id}` | Remove a plugin | 123 124 | `POST /admin/plugins/{id}/reload` | Reload plugin from source | 125 + | `POST /admin/plugins/{id}/check-update` | Check whether a newer version is available | 124 126 | `GET /admin/plugins/{id}/secrets` | Get configured secrets (masked) | 125 127 | `PUT /admin/plugins/{id}/secrets` | Update plugin secrets | 128 + 129 + The dashboard's **Settings > Plugins** page calls `GET /admin/plugins/official` to populate the install browser, and `POST /admin/plugins/{id}/check-update` to display update badges on installed plugins. 126 130 127 131 ## Security 128 132
+6
docs/guides/postgres-to-sqlite-migration.md
··· 84 84 ## Rollback 85 85 86 86 To switch back to Postgres, revert your `DATABASE_URL` to the Postgres connection string. Your Postgres database remains unchanged — HappyView does not modify it during the migration to SQLite. 87 + 88 + ## Next steps 89 + 90 + - [Database setup](database-setup.md) — choose between SQLite and Postgres for new instances 91 + - [Backfill](backfill.md) — re-index records from the network after switching backends 92 + - [Lua scripting](scripting.md) — write SQL that works against either backend
+549 -35
docs/reference/admin-api.md
··· 123 123 124 124 ## Network Lexicons 125 125 126 - Network lexicons are fetched from the AT Protocol network via DNS TXT resolution and kept updated via Tap. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons) for background. 126 + Network lexicons are fetched from the AT Protocol network via DNS TXT resolution and kept updated via the Jetstream subscription. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons) for background. 127 127 128 128 ### Add a network lexicon 129 129 ··· 218 218 } 219 219 ``` 220 220 221 - ## Tap Stats 222 - 223 - Aggregate stats from the [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) instance. Useful for monitoring backfill progress. See [Backfill - Job lifecycle](../guides/backfill.md#job-lifecycle) for context. 224 - 225 - ### Get Tap stats 226 - 227 - ``` 228 - GET /admin/tap/stats 229 - ``` 230 - 231 - ```sh 232 - curl http://localhost:3000/admin/tap/stats -H "$AUTH" 233 - ``` 234 - 235 - **Response**: `200 OK` 236 - 237 - ```json 238 - { 239 - "repo_count": 5234, 240 - "record_count": 1048576, 241 - "outbox_buffer": 42 242 - } 243 - ``` 244 - 245 - | Field | Type | Description | 246 - | --------------- | ------ | ----------------------------------------------------- | 247 - | `repo_count` | number | Total repos Tap is tracking | 248 - | `record_count` | number | Total records Tap has indexed | 249 - | `outbox_buffer` | number | Pending events awaiting delivery (high = Tap is busy) | 250 - 251 - Returns `502 Bad Gateway` if Tap is unreachable. 252 - 253 221 ## Backfill 254 222 255 223 ### Create a backfill job ··· 311 279 312 280 ## Event Logs 313 281 314 - HappyView records an audit trail of system events: lexicon changes, record operations, Lua script executions and errors, user actions, backfill jobs, and Tap connectivity. See the [Event Logs guide](../guides/event-logs.md) for details on event types and retention. 282 + HappyView records an audit trail of system events: lexicon changes, record operations, Lua script executions and errors, user actions, backfill jobs, and Jetstream connectivity. See the [Event Logs guide](../guides/event-logs.md) for details on event types and retention. 315 283 316 284 ### List event logs 317 285 ··· 683 651 684 652 **Response**: `204 No Content` 685 653 654 + ## Instance Settings 655 + 656 + Instance settings are key/value entries used to override environment-variable defaults at runtime (for example, the application name, terms-of-service URL, privacy policy URL, and uploaded logo). Settings stored here take precedence over the corresponding environment variables. All endpoints require the `settings:manage` permission. 657 + 658 + ### List settings 659 + 660 + ``` 661 + GET /admin/settings 662 + ``` 663 + 664 + ```sh 665 + curl http://localhost:3000/admin/settings -H "$AUTH" 666 + ``` 667 + 668 + Returns all key/value pairs stored in the `instance_settings` table. 669 + 670 + ### Upsert a setting 671 + 672 + ``` 673 + PUT /admin/settings/{key} 674 + ``` 675 + 676 + ```sh 677 + curl -X PUT http://localhost:3000/admin/settings/app_name \ 678 + -H "$AUTH" \ 679 + -H "Content-Type: application/json" \ 680 + -d '{ "value": "My HappyView" }' 681 + ``` 682 + 683 + ### Delete a setting 684 + 685 + ``` 686 + DELETE /admin/settings/{key} 687 + ``` 688 + 689 + Removes the override; the corresponding environment variable (if any) takes effect again. 690 + 691 + ### Upload / delete logo 692 + 693 + ``` 694 + PUT /admin/settings/logo 695 + DELETE /admin/settings/logo 696 + ``` 697 + 698 + `PUT` accepts a binary image body and stores it as the instance logo (served via the public dashboard). `DELETE` removes the stored logo. 699 + 700 + ## Domain Management 701 + 702 + Manage the domains a HappyView instance serves. Each domain gets its own AT Protocol OAuth client identity. The primary domain is auto-seeded from `PUBLIC_URL` on first boot. All endpoints require the `settings:manage` permission. 703 + 704 + ### List domains 705 + 706 + ``` 707 + GET /admin/domains 708 + ``` 709 + 710 + ```sh 711 + curl http://localhost:3000/admin/domains -H "$AUTH" 712 + ``` 713 + 714 + **Response**: `200 OK` 715 + 716 + ```json 717 + [ 718 + { 719 + "id": "550e8400-e29b-41d4-a716-446655440000", 720 + "url": "https://gamesgamesgamesgames.games", 721 + "is_primary": true, 722 + "created_at": "2026-04-16T00:00:00Z", 723 + "updated_at": "2026-04-16T00:00:00Z" 724 + } 725 + ] 726 + ``` 727 + 728 + ### Add a domain 729 + 730 + ``` 731 + POST /admin/domains 732 + ``` 733 + 734 + ```sh 735 + curl -X POST http://localhost:3000/admin/domains \ 736 + -H "$AUTH" \ 737 + -H "Content-Type: application/json" \ 738 + -d '{ "url": "https://api.cartridge.dev" }' 739 + ``` 740 + 741 + | Field | Type | Required | Description | 742 + | ----- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------ | 743 + | `url` | string | yes | Valid origin (scheme + host, no path or trailing slash). Must be `https` unless `PUBLIC_URL` is a loopback address. | 744 + 745 + Returns `400 Bad Request` if the URL is invalid or already registered. 746 + 747 + **Response**: `201 Created` 748 + 749 + ```json 750 + { 751 + "id": "550e8400-e29b-41d4-a716-446655440001", 752 + "url": "https://api.cartridge.dev", 753 + "is_primary": false, 754 + "created_at": "2026-04-16T00:00:00Z", 755 + "updated_at": "2026-04-16T00:00:00Z" 756 + } 757 + ``` 758 + 759 + Side effects: builds an OAuth client for the domain, updates the in-memory domain cache. 760 + 761 + ### Remove a domain 762 + 763 + ``` 764 + DELETE /admin/domains/{id} 765 + ``` 766 + 767 + ```sh 768 + curl -X DELETE http://localhost:3000/admin/domains/550e8400-e29b-41d4-a716-446655440001 \ 769 + -H "$AUTH" 770 + ``` 771 + 772 + Returns `400 Bad Request` if the domain is primary — set a different domain as primary first. Returns `404 Not Found` if the domain doesn't exist. 773 + 774 + **Response**: `204 No Content` 775 + 776 + Side effects: removes the domain's OAuth client and cache entry. 777 + 778 + ### Set primary domain 779 + 780 + ``` 781 + POST /admin/domains/{id}/primary 782 + ``` 783 + 784 + ```sh 785 + curl -X POST http://localhost:3000/admin/domains/550e8400-e29b-41d4-a716-446655440001/primary \ 786 + -H "$AUTH" 787 + ``` 788 + 789 + Sets the target domain as the primary. Unsets the current primary in a single operation. Returns `404 Not Found` if the domain doesn't exist. 790 + 791 + **Response**: `204 No Content` 792 + 793 + Side effects: updates the in-memory cache and the OAuth client registry's primary client reference. 794 + 795 + ## Script Variables 796 + 797 + Script variables are encrypted key/value pairs available to Lua scripts via the `vars` global. Use them for secrets like API tokens. 798 + 799 + ### List script variables 800 + 801 + ``` 802 + GET /admin/script-variables 803 + ``` 804 + 805 + Requires `script-variables:read`. Returns a list of variable keys (values are not returned). 806 + 807 + ### Upsert a script variable 808 + 809 + ``` 810 + POST /admin/script-variables 811 + ``` 812 + 813 + Requires `script-variables:create`. 814 + 815 + ```sh 816 + curl -X POST http://localhost:3000/admin/script-variables \ 817 + -H "$AUTH" \ 818 + -H "Content-Type: application/json" \ 819 + -d '{ "key": "ALGOLIA_API_KEY", "value": "..." }' 820 + ``` 821 + 822 + The value is encrypted at rest using `TOKEN_ENCRYPTION_KEY`. 823 + 824 + ### Delete a script variable 825 + 826 + ``` 827 + DELETE /admin/script-variables/{key} 828 + ``` 829 + 830 + Requires `script-variables:delete`. 831 + 832 + ## API Clients 833 + 834 + API clients represent third-party applications that call HappyView's XRPC endpoints. **Every XRPC request** — including unauthenticated queries — must identify itself with a registered client via the `X-Client-Key` header (or session cookie, or `client_key` query param). The client key is HappyView's rate-limit bucket and caller identity; a request without one gets `401 Unauthorized`. 835 + 836 + Each client has an `hvc_`-prefixed client key and an `hvs_`-prefixed client secret. The secret is only returned once (at creation) and is sha256-hashed in the database. Server-to-server callers pass the secret as `X-Client-Secret`; browser callers rely on the `Origin` header matching the client's registered `client_uri`. Both checks currently log warnings on mismatch rather than rejecting the request, but the rate-limit bucket is applied either way. See [Authentication — XRPC](../getting-started/authentication.md#xrpc-api-client-identification) for the client-side view, and the [API Keys guide](../guides/api-keys.md) for how admin API keys differ from API clients. 837 + 838 + ### List API clients 839 + 840 + ``` 841 + GET /admin/api-clients 842 + ``` 843 + 844 + Requires `api-clients:view`. Returns clients ordered by `created_at` descending. Secrets are never returned. 845 + 846 + ```sh 847 + curl http://localhost:3000/admin/api-clients -H "$AUTH" 848 + ``` 849 + 850 + **Response**: `200 OK` 851 + 852 + ```json 853 + [ 854 + { 855 + "id": "01J9...", 856 + "client_key": "hvc_a1b2c3...", 857 + "name": "My Game Client", 858 + "client_id_url": "https://example.com/client-metadata.json", 859 + "client_uri": "https://example.com", 860 + "redirect_uris": ["https://example.com/callback"], 861 + "scopes": "atproto", 862 + "rate_limit_capacity": 200, 863 + "rate_limit_refill_rate": 5.0, 864 + "is_active": true, 865 + "created_by": "did:plc:...", 866 + "created_at": "2026-04-13T12:00:00Z", 867 + "updated_at": "2026-04-13T12:00:00Z" 868 + } 869 + ] 870 + ``` 871 + 872 + ### Create an API client 873 + 874 + ``` 875 + POST /admin/api-clients 876 + ``` 877 + 878 + Requires `api-clients:create`. Generates a fresh `client_key` and `client_secret`. **The secret is only returned in this response** — store it immediately. 879 + 880 + ```sh 881 + curl -X POST http://localhost:3000/admin/api-clients \ 882 + -H "$AUTH" \ 883 + -H "Content-Type: application/json" \ 884 + -d '{ 885 + "name": "My Game Client", 886 + "client_id_url": "https://example.com/client-metadata.json", 887 + "client_uri": "https://example.com", 888 + "redirect_uris": ["https://example.com/callback"], 889 + "scopes": "atproto", 890 + "rate_limit_capacity": 200, 891 + "rate_limit_refill_rate": 5.0 892 + }' 893 + ``` 894 + 895 + | Field | Type | Required | Description | 896 + | ------------------------ | -------- | -------- | -------------------------------------------------------------------------------------- | 897 + | `name` | string | yes | Human-readable display name | 898 + | `client_id_url` | string | yes | URL to the client's published OAuth client metadata document | 899 + | `client_uri` | string | yes | The client's home/landing URL | 900 + | `redirect_uris` | string[] | yes | Allowed OAuth redirect URIs | 901 + | `scopes` | string | no | Space-separated OAuth scopes (default `"atproto"`) | 902 + | `rate_limit_capacity` | integer | no | Per-client token bucket capacity. Falls back to `DEFAULT_RATE_LIMIT_CAPACITY` if unset | 903 + | `rate_limit_refill_rate` | number | no | Tokens added per second. Falls back to `DEFAULT_RATE_LIMIT_REFILL_RATE` if unset | 904 + 905 + **Response**: `201 Created` 906 + 907 + ```json 908 + { 909 + "id": "01J9...", 910 + "client_key": "hvc_a1b2c3...", 911 + "client_secret": "hvs_d4e5f6...", 912 + "name": "My Game Client", 913 + "client_id_url": "https://example.com/client-metadata.json" 914 + } 915 + ``` 916 + 917 + The new client is immediately registered with the OAuth registry and rate limiter, so it can authenticate without restarting HappyView. 918 + 919 + ### Get an API client 920 + 921 + ``` 922 + GET /admin/api-clients/{id} 923 + ``` 924 + 925 + Requires `api-clients:view`. Returns the same `ApiClientSummary` shape as the list endpoint, or `404 Not Found`. 926 + 927 + ### Update an API client 928 + 929 + ``` 930 + PUT /admin/api-clients/{id} 931 + ``` 932 + 933 + Requires `api-clients:edit`. All fields are optional — only provided fields are changed. Updating either rate-limit field re-registers the client with the rate limiter using the new values. 934 + 935 + | Field | Type | Description | 936 + | ------------------------ | -------- | ------------------------------------------------------------------------ | 937 + | `name` | string | New display name | 938 + | `client_uri` | string | New home URL | 939 + | `redirect_uris` | string[] | Replace the allowed redirect URIs | 940 + | `scopes` | string | Replace the OAuth scopes | 941 + | `rate_limit_capacity` | integer | New bucket capacity. Pass `null` to clear the override | 942 + | `rate_limit_refill_rate` | number | New refill rate. Pass `null` to clear the override | 943 + | `is_active` | boolean | Disable (`false`) or re-enable (`true`) the client without deleting it | 944 + 945 + **Response**: `204 No Content` 946 + 947 + The OAuth registry is updated in place. The `client_id_url` is immutable — to change it, delete and recreate the client. 948 + 949 + ### Delete an API client 950 + 951 + ``` 952 + DELETE /admin/api-clients/{id} 953 + ``` 954 + 955 + Requires `api-clients:delete`. Removes the client from the OAuth registry, the rate limiter, and the client identity store. 956 + 957 + **Response**: `204 No Content` 958 + 959 + ## Plugins 960 + 961 + Plugins extend HappyView with WebAssembly modules sourced from the [official plugin registry](../guides/plugins.md) or any URL serving a `manifest.json`. Most endpoints take a plugin manifest URL and load (or reload) the plugin in place — no restart needed. Encrypted plugin secrets require `TOKEN_ENCRYPTION_KEY` to be configured. 962 + 963 + ### List installed plugins 964 + 965 + ``` 966 + GET /admin/plugins 967 + ``` 968 + 969 + Requires `plugins:read`. Returns every loaded plugin with its source, required secrets, configuration status, and any pending updates from the official registry cache. 970 + 971 + ```sh 972 + curl http://localhost:3000/admin/plugins -H "$AUTH" 973 + ``` 974 + 975 + **Response**: `200 OK` 976 + 977 + ```json 978 + { 979 + "encryption_configured": true, 980 + "plugins": [ 981 + { 982 + "id": "steam", 983 + "name": "Steam", 984 + "version": "1.2.0", 985 + "source": "url", 986 + "url": "https://example.com/plugins/steam/manifest.json", 987 + "sha256": null, 988 + "enabled": true, 989 + "auth_type": "openid", 990 + "required_secrets": [ 991 + { 992 + "key": "PLUGIN_STEAM_API_KEY", 993 + "name": "Steam Web API Key", 994 + "description": "Get your API key at steamcommunity.com/dev/apikey" 995 + } 996 + ], 997 + "secrets_configured": true, 998 + "loaded_at": null, 999 + "update_available": false, 1000 + "latest_version": "1.2.0", 1001 + "pending_releases": [] 1002 + } 1003 + ] 1004 + } 1005 + ``` 1006 + 1007 + `secrets_configured` is `true` if the plugin has no required secrets, or if a row exists for it in `plugin_configs`. `update_available` and `pending_releases` are populated from the cached official registry — call `POST /admin/plugins/{id}/check-update` to refresh them. 1008 + 1009 + ### Preview a plugin before installing 1010 + 1011 + ``` 1012 + POST /admin/plugins/preview 1013 + ``` 1014 + 1015 + Requires `plugins:create`. Fetches and parses a manifest without installing the plugin, so the dashboard can show what it would register. 1016 + 1017 + ```sh 1018 + curl -X POST http://localhost:3000/admin/plugins/preview \ 1019 + -H "$AUTH" \ 1020 + -H "Content-Type: application/json" \ 1021 + -d '{ "url": "https://example.com/plugins/steam/manifest.json" }' 1022 + ``` 1023 + 1024 + **Response**: `200 OK` 1025 + 1026 + ```json 1027 + { 1028 + "id": "steam", 1029 + "name": "Steam", 1030 + "version": "1.2.0", 1031 + "description": "Import your Steam game library and playtime data.", 1032 + "icon_url": "https://example.com/steam-icon.png", 1033 + "auth_type": "openid", 1034 + "required_secrets": [ 1035 + { "key": "PLUGIN_STEAM_API_KEY", "name": "Steam Web API Key", "description": "..." } 1036 + ], 1037 + "manifest_url": "https://example.com/plugins/steam/manifest.json", 1038 + "wasm_url": "https://example.com/plugins/steam/steam.wasm" 1039 + } 1040 + ``` 1041 + 1042 + Returns `400 Bad Request` if the manifest can't be fetched or parsed. 1043 + 1044 + ### Install a plugin 1045 + 1046 + ``` 1047 + POST /admin/plugins 1048 + ``` 1049 + 1050 + Requires `plugins:create`. Fetches the manifest, downloads the WASM, registers the plugin, and persists it. 1051 + 1052 + ```sh 1053 + curl -X POST http://localhost:3000/admin/plugins \ 1054 + -H "$AUTH" \ 1055 + -H "Content-Type: application/json" \ 1056 + -d '{ 1057 + "url": "https://example.com/plugins/steam/manifest.json", 1058 + "sha256": "abc123..." 1059 + }' 1060 + ``` 1061 + 1062 + | Field | Type | Required | Description | 1063 + | -------- | ------ | -------- | -------------------------------------------------------------------------------------------- | 1064 + | `url` | string | yes | URL to the plugin's `manifest.json` | 1065 + | `sha256` | string | no | Optional sha256 of the WASM binary. If provided, install fails when the downloaded hash mismatches | 1066 + 1067 + **Response**: `200 OK` returning the same `PluginSummary` shape as the list endpoint. `secrets_configured` will be `false` if the plugin requires any secrets — call `PUT /admin/plugins/{id}/secrets` to configure them before the plugin can run. 1068 + 1069 + ### List official plugins 1070 + 1071 + ``` 1072 + GET /admin/plugins/official 1073 + ``` 1074 + 1075 + Requires `plugins:read`. Returns the cached catalog of plugins from the official registry. The cache is refreshed periodically by the server; use `POST /admin/plugins/{id}/check-update` to force-refresh a single entry. 1076 + 1077 + **Response**: `200 OK` 1078 + 1079 + ```json 1080 + { 1081 + "last_refreshed_at": "2026-04-13T11:00:00Z", 1082 + "plugins": [ 1083 + { 1084 + "id": "steam", 1085 + "name": "Steam", 1086 + "description": "Import your Steam game library and playtime data.", 1087 + "icon_url": "https://example.com/steam-icon.png", 1088 + "latest_version": "1.2.0", 1089 + "manifest_url": "https://example.com/plugins/steam/manifest.json" 1090 + } 1091 + ] 1092 + } 1093 + ``` 1094 + 1095 + ### Remove a plugin 1096 + 1097 + ``` 1098 + DELETE /admin/plugins/{id} 1099 + ``` 1100 + 1101 + Requires `plugins:delete`. Unregisters the plugin from the runtime and deletes its row from the `plugins` table. Plugin secrets in `plugin_configs` are not removed automatically — they're available again if you reinstall the same plugin. 1102 + 1103 + **Response**: `204 No Content`. Returns `404 Not Found` if no plugin with that id is loaded. 1104 + 1105 + ### Reload a plugin 1106 + 1107 + ``` 1108 + POST /admin/plugins/{id}/reload 1109 + ``` 1110 + 1111 + Requires `plugins:create`. Re-fetches the plugin from its current source URL and re-registers it. Useful after publishing a new version of a plugin you host yourself. 1112 + 1113 + The body is optional. To point the plugin at a new URL, pass: 1114 + 1115 + ```json 1116 + { "url": "https://example.com/plugins/steam/manifest.json" } 1117 + ``` 1118 + 1119 + When a new URL is provided, the stored `sha256` is cleared (the new version has its own hash). File-based plugins cannot be reloaded via this endpoint and return `400 Bad Request`. 1120 + 1121 + **Response**: `200 OK` with the refreshed `PluginSummary`. 1122 + 1123 + ### Check for plugin updates 1124 + 1125 + ``` 1126 + POST /admin/plugins/{id}/check-update 1127 + ``` 1128 + 1129 + Requires `plugins:create`. Forces a cache refresh for one plugin from the official registry, then returns the updated `PluginSummary` with `update_available`, `latest_version`, and `pending_releases` reflecting the latest catalog state. 1130 + 1131 + **Response**: `200 OK` with a `PluginSummary`. 1132 + 1133 + ### Get plugin secrets 1134 + 1135 + ``` 1136 + GET /admin/plugins/{id}/secrets 1137 + ``` 1138 + 1139 + Requires `plugins:read`. Returns the plugin's configured secrets with values masked (last 4 characters shown for values longer than 8 characters, otherwise fully masked). Requires `TOKEN_ENCRYPTION_KEY` to be configured. 1140 + 1141 + **Response**: `200 OK` 1142 + 1143 + ```json 1144 + { 1145 + "plugin_id": "steam", 1146 + "secrets": { 1147 + "PLUGIN_STEAM_API_KEY": "********ABCD" 1148 + } 1149 + } 1150 + ``` 1151 + 1152 + ### Update plugin secrets 1153 + 1154 + ``` 1155 + PUT /admin/plugins/{id}/secrets 1156 + ``` 1157 + 1158 + Requires `plugins:create`. Encrypts the provided secret values with `TOKEN_ENCRYPTION_KEY` (AES-256-GCM) and upserts them into `plugin_configs`. 1159 + 1160 + ```sh 1161 + curl -X PUT http://localhost:3000/admin/plugins/steam/secrets \ 1162 + -H "$AUTH" \ 1163 + -H "Content-Type: application/json" \ 1164 + -d '{ 1165 + "secrets": { 1166 + "PLUGIN_STEAM_API_KEY": "your-new-api-key" 1167 + } 1168 + }' 1169 + ``` 1170 + 1171 + Special handling: 1172 + 1173 + - Values starting with `********` are treated as masked placeholders and the existing encrypted value is preserved (so you can `GET` then `PUT` without re-typing every secret). 1174 + - Empty string values are not stored — use them to clear a secret. 1175 + 1176 + **Response**: `204 No Content` 1177 + 686 1178 ## Permissions 687 1179 688 1180 Each admin API endpoint requires a specific permission. See the [Permissions guide](../guides/permissions.md) for the full list of permissions and templates. ··· 697 1189 | `GET /admin/network-lexicons` | `lexicons:read` | 698 1190 | `DELETE /admin/network-lexicons/{id}` | `lexicons:delete` | 699 1191 | `GET /admin/stats` | `stats:read` | 700 - | `GET /admin/tap/stats` | `stats:read` | 701 1192 | `POST /admin/backfill` | `backfill:create` | 702 1193 | `GET /admin/backfill/status` | `backfill:read` | 703 1194 | `GET /admin/events` | `events:read` | ··· 717 1208 | `GET /admin/labelers` | `labelers:read` | 718 1209 | `PATCH /admin/labelers/{did}` | `labelers:create` | 719 1210 | `DELETE /admin/labelers/{did}` | `labelers:delete` | 1211 + | `GET /admin/settings` | `settings:manage` | 1212 + | `PUT /admin/settings/{key}` | `settings:manage` | 1213 + | `DELETE /admin/settings/{key}` | `settings:manage` | 1214 + | `PUT /admin/settings/logo` | `settings:manage` | 1215 + | `DELETE /admin/settings/logo` | `settings:manage` | 1216 + | `GET /admin/plugins` | `plugins:read` | 1217 + | `POST /admin/plugins` | `plugins:create` | 1218 + | `POST /admin/plugins/preview` | `plugins:read` | 1219 + | `GET /admin/plugins/official` | `plugins:read` | 1220 + | `DELETE /admin/plugins/{id}` | `plugins:delete` | 1221 + | `POST /admin/plugins/{id}/reload` | `plugins:create` | 1222 + | `POST /admin/plugins/{id}/check-update` | `plugins:read` | 1223 + | `GET /admin/plugins/{id}/secrets` | `plugins:read` | 1224 + | `PUT /admin/plugins/{id}/secrets` | `plugins:create` | 1225 + | `GET /admin/domains` | `settings:manage` | 1226 + | `POST /admin/domains` | `settings:manage` | 1227 + | `DELETE /admin/domains/{id}` | `settings:manage` | 1228 + | `POST /admin/domains/{id}/primary` | `settings:manage` | 1229 + | `GET /admin/api-clients` | `api-clients:view` | 1230 + | `POST /admin/api-clients` | `api-clients:create` | 1231 + | `GET /admin/api-clients/{id}` | `api-clients:view` | 1232 + | `PUT /admin/api-clients/{id}` | `api-clients:edit` | 1233 + | `DELETE /admin/api-clients/{id}` | `api-clients:delete` |
+19 -15
docs/reference/architecture.md
··· 1 1 # Architecture 2 2 3 - Guide for contributors working on HappyView itself. For a user-facing overview, see the [Introduction](/README.md). 3 + Guide for contributors working on HappyView itself. For a user-facing overview, see the [Introduction](../README.md). 4 4 5 5 ## System overview 6 6 ··· 23 23 24 24 DB[("SQLite / PostgreSQL<br/><small>records · lexicons</small>")] 25 25 26 - Tap["Tap<br/><small>WebSocket</small>"] -->|record events| DB 27 - Relay["Relay<br/><small>Firehose</small>"] --> Tap 26 + Jetstream["Jetstream<br/><small>WebSocket</small>"] -->|record events| DB 27 + Relay["Relay<br/><small>listReposByCollection</small>"] -->|repo discovery| Backfill 28 + Backfill["Backfill Worker"] -->|listRecords| PDS 29 + Backfill --> DB 28 30 ``` 29 31 30 - Reads flow top-down through the query handler to the database (SQLite by default, or Postgres). Writes flow through the procedure handler to the user's PDS, then HappyView indexes the record locally. All record data enters the system through Tap, which handles both real-time firehose events and historical backfill. HappyView syncs collection filters to Tap and discovers repos via the relay for backfill, but Tap performs all record fetching. 32 + Reads flow top-down through the query handler to the database (SQLite by default, or Postgres). Writes flow through the procedure handler to the user's PDS, then HappyView indexes the record locally. Real-time record events stream in via [Jetstream](https://github.com/bluesky-social/jetstream); historical records are backfilled in-process by discovering repos via the relay's `listReposByCollection` and fetching records directly from each PDS. 31 33 32 34 ## Module overview 33 35 34 36 ``` 35 37 src/ 36 - main.rs Startup: config, DB, migrations, build OAuth client, spawn Tap worker, start server 38 + main.rs Startup: config, DB, migrations, build OAuth client, spawn Jetstream worker, start server 37 39 lib.rs AppState struct (incl. OAuth client + cookie key), module declarations 38 40 config.rs Environment variable loading 39 41 dns.rs DNS TXT resolver for atrium handle resolution ··· 41 43 server.rs Axum router: fixed routes + admin nest + auth routes + XRPC catch-all + static files 42 44 lexicon.rs ParsedLexicon, LexiconRegistry (Arc<RwLock<HashMap>>) 43 45 profile.rs DID document resolution, PDS discovery, profile fetching 44 - tap.rs Tap WebSocket listener, collection filter sync, backfill delegation 46 + jetstream.rs Jetstream WebSocket listener, collection filter sync, cursor persistence 45 47 resolve.rs NSID authority resolution (DNS TXT → DID → PDS) 46 48 auth/ 47 49 mod.rs Re-exports, COOKIE_NAME constant ··· 62 64 network_lexicons.rs Network lexicon tracking (add, list, remove) 63 65 records.rs Record listing handler 64 66 stats.rs Record count stats 65 - backfill.rs Backfill job creation (relay discovery + Tap delegation) 67 + backfill.rs Backfill job runner (relay discovery + per-PDS listRecords) 66 68 types.rs Request/response structs for admin endpoints 67 69 lua/ 68 70 mod.rs Re-exports ··· 129 131 ### Real-time indexing 130 132 131 133 ``` 132 - Tap WebSocket connection (tap::spawn) 133 - -> Collection filters synced to Tap on startup and lexicon changes 134 - -> Record events: 134 + Jetstream WebSocket connection (jetstream::spawn) 135 + -> Collection filters built from indexed lexicons and applied to subscription URL 136 + -> Reconnects on collection filter changes (lexicon add/remove) 137 + -> Record commit events: 135 138 create/update -> UPSERT into records table 136 139 delete -> DELETE from records table 137 140 -> Lexicon schema events (com.atproto.lexicon.schema): 138 141 -> Update tracked network lexicons in DB and registry 139 - -> Reconnects automatically on errors or collection filter changes 142 + -> Cursor persisted to instance_settings for resume on reconnect 140 143 ``` 141 144 142 145 ### Backfill ··· 144 147 ``` 145 148 POST /admin/backfill 146 149 -> Create backfill_jobs record (status = running) 147 - -> Relay listReposByCollection -> list of DIDs 148 - -> Send DIDs to Tap in batches of 1000 (POST /repos/add) 149 - -> Mark job as completed 150 - -> Tap fetches records asynchronously and delivers via WebSocket 150 + -> Relay listReposByCollection -> list of DIDs (paginated) 151 + -> For each DID: resolve PDS via PLC, listRecords from that PDS (paginated) 152 + -> UPSERT each record into records table 153 + -> Update processed_repos / total_records counters 154 + -> Mark job as completed (or failed with error message) 151 155 ``` 152 156 153 157 ## Database schema
+1 -1
docs/reference/changelog.md
··· 22 22 23 23 ## v1.9.0 — Event Logs 24 24 25 - - **Event logging** — system-wide audit trail for lexicon changes, record operations, Lua script executions/errors, admin actions, backfill jobs, and Tap connectivity 25 + - **Event logging** — system-wide audit trail for lexicon changes, record operations, Lua script executions/errors, admin actions, backfill jobs, and firehose connectivity 26 26 - **`GET /admin/events`** — query event logs with filtering by event type, category, severity, and subject, with cursor pagination 27 27 - **Lua error context** — script errors capture full debugging context: error message, script source, input payload, and caller DID 28 28 - **Automatic retention cleanup** — configurable via `EVENT_LOG_RETENTION_DAYS` (default 30 days)
+5 -5
docs/reference/glossary.md
··· 8 8 9 9 **DID** (Decentralized Identifier) — A persistent, globally unique identifier for an account (e.g. `did:plc:abc123`). 10 10 11 - **Firehose** — A real-time stream of all record events (creates, updates, deletes) across the AT Protocol network. HappyView consumes this via [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap). 11 + **Firehose** — A real-time stream of all record events (creates, updates, deletes) across the AT Protocol network. HappyView consumes a filtered slice of this via [Jetstream](https://github.com/bluesky-social/jetstream). 12 12 13 13 **Handle** — A human-readable name for an account (e.g. `user.bsky.social`). Handles resolve to a DID via DNS or the PLC directory. 14 14 ··· 22 22 23 23 **Record** — A single piece of data in an AT Protocol repository, identified by an AT URI (e.g. `at://did:plc:abc/xyz.statusphere.status/abc123`). 24 24 25 - **Relay** — A network service that aggregates repository data from many PDSes. HappyView queries the relay during [backfill](../guides/backfill.md) to discover which repos contain records for a given collection, then delegates the actual record fetching to Tap. 25 + **Relay** — A network service that aggregates repository data from many PDSes. HappyView queries the relay during [backfill](../guides/backfill.md) to discover which repos contain records for a given collection, then fetches each repo's records directly from its PDS. 26 26 27 27 **rkey** (Record Key) — The unique key for a record within a collection and repo. These are most commonly TIDs (timestamp-based) or NSIDs. 28 28 ··· 32 32 33 33 ## HappyView-specific terms 34 34 35 - **Backfill** — The process of bulk-indexing existing records from the network. HappyView discovers repos via the relay and delegates record fetching to Tap. Runs when a new record-type lexicon is uploaded or triggered manually. See [Backfill](../guides/backfill.md). 35 + **Backfill** — The process of bulk-indexing existing records from the network. HappyView discovers repos via the relay and fetches each repo's records directly from its PDS. Runs when a new record-type lexicon is uploaded or triggered manually. See [Backfill](../guides/backfill.md). 36 + 37 + **Jetstream** — A [filtered firehose](https://github.com/bluesky-social/jetstream) maintained by Bluesky that delivers AT Protocol record commit events as JSON over WebSocket. HappyView subscribes to Jetstream with a collection filter built from its indexed record lexicons, and persists a cursor for resume on reconnect. 36 38 37 39 **Network lexicon** — A lexicon fetched directly from the AT Protocol network via DNS authority resolution, rather than uploaded manually. See [Lexicons - Network lexicons](../guides/lexicons.md#network-lexicons). 38 - 39 - **Tap** — A [firehose consumer and backfill worker](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) that handles real-time record streaming, cryptographic verification, and historical record fetching. HappyView connects to Tap via WebSocket to receive record events, and delegates backfill work to Tap via its HTTP API. 40 40 41 41 **Permission** — A granular access control right that authorizes a specific action in the admin API. HappyView defines 20 permissions organized by category (e.g. `lexicons:create`, `users:read`). See [Permissions](../guides/permissions.md). 42 42
+53 -64
docs/reference/production-deployment.md
··· 1 - # Deployment 1 + # Production 2 2 3 - HappyView requires a database. SQLite is the default; Postgres is also supported, but requires additional setup. The [Quickstart](../getting-started/deployment/railway.md) covers the fastest path with Railway. This page covers other deployment options. 3 + This page covers what to change when taking a HappyView instance from local development to production. For setup instructions, see [Deployment](../getting-started/deployment/railway.md). This page assumes you already have a working deployment and focuses on hardening and operational concerns. 4 4 5 - ## Docker 5 + ## Session secret 6 6 7 - Build the image: 7 + Set `SESSION_SECRET` to a strong random value (at least 32 bytes). This signs the session cookies issued during OAuth login; rotating it invalidates every existing session. 8 8 9 9 ```sh 10 - docker build -t happyview . 10 + openssl rand -base64 48 11 11 ``` 12 12 13 - For local development, see [Docker deployment](../getting-started/deployment/docker.md). 13 + Never commit the secret to source control. Store it in your platform's secret manager (Railway variables, Docker secrets, Kubernetes secrets, etc.). 14 14 15 - ### Production Compose example 15 + ## Token encryption key 16 16 17 - :::note 18 - This example omits [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap), which is required for real-time record streaming and backfill. See the full `docker-compose.yml` in the repository for a complete configuration including Tap. 19 - ::: 17 + If you use [plugins](../guides/plugins.md) that require secrets (API keys, OAuth credentials), set `TOKEN_ENCRYPTION_KEY` to a base64-encoded 32-byte key. This encrypts plugin secrets at rest using AES-256-GCM: 18 + 19 + ```sh 20 + openssl rand -base64 32 21 + ``` 22 + 23 + Without this variable, the dashboard's plugin secret fields are disabled and plugins can only read secrets from environment variables. 20 24 21 - Using SQLite (default): 25 + ## TLS and `PUBLIC_URL` 22 26 23 - ```yaml 24 - services: 25 - happyview: 26 - image: happyview:latest 27 - ports: 28 - - "3000:3000" 29 - environment: 30 - DATABASE_URL: "sqlite://data/happyview.db?mode=rwc" 31 - PUBLIC_URL: "https://happyview.example.com" 32 - SESSION_SECRET: "${SESSION_SECRET}" 33 - volumes: 34 - - happyview-data:/app/data 27 + HappyView does not terminate TLS. Put it behind a reverse proxy (nginx, Caddy, Cloudflare Tunnel, a platform-managed load balancer) and set `PUBLIC_URL` to the public HTTPS URL: 35 28 36 - volumes: 37 - happyview-data: 29 + ```sh 30 + PUBLIC_URL=https://happyview.example.com 38 31 ``` 39 32 40 - Using Postgres: 33 + `PUBLIC_URL` is used to construct OAuth redirect URIs, so it must exactly match the URL users hit — including scheme. A mismatch breaks OAuth login. 34 + 35 + ## Database 36 + 37 + SQLite is fine for small to medium instances and is the default. Switch to Postgres if you need: 38 + 39 + - Multiple HappyView replicas sharing one database 40 + - Larger-than-memory working sets 41 + - External tools that need direct read access to the records table 42 + 43 + See the [database setup guide](../guides/database-setup.md) for configuration details and [Postgres → SQLite migration](../guides/postgres-to-sqlite-migration.md) if you're moving the other direction. Migrations run automatically on startup regardless of backend. 44 + 45 + ## Rate limits 46 + 47 + HappyView has a per-client token-bucket rate limiter for XRPC endpoints. The defaults (set via `DEFAULT_RATE_LIMIT_CAPACITY` and `DEFAULT_RATE_LIMIT_REFILL_RATE`) apply to any [API client](../guides/api-keys.md) that doesn't have per-client overrides. Raise the defaults cautiously — they exist so one misbehaving integrator can't saturate the server. 48 + 49 + Per-client overrides are set at client creation or via `PUT /admin/api-clients/{id}` (see [Admin API — API Clients](admin-api.md#api-clients)). 41 50 42 - ```yaml 43 - services: 44 - postgres: 45 - image: postgres:17 46 - environment: 47 - POSTGRES_USER: happyview 48 - POSTGRES_PASSWORD: "${POSTGRES_PASSWORD}" 49 - POSTGRES_DB: happyview 50 - volumes: 51 - - pgdata:/var/lib/postgresql/data 51 + ## Logging 52 52 53 - happyview: 54 - image: happyview:latest 55 - ports: 56 - - "3000:3000" 57 - environment: 58 - DATABASE_URL: "postgres://happyview:${POSTGRES_PASSWORD}@postgres/happyview" 59 - PUBLIC_URL: "https://happyview.example.com" 60 - SESSION_SECRET: "${SESSION_SECRET}" 61 - depends_on: 62 - postgres: 63 - condition: service_healthy 53 + The default `RUST_LOG` setting (`happyview=debug,tower_http=debug`) is noisy. For production, drop the verbosity: 64 54 65 - volumes: 66 - pgdata: 55 + ```sh 56 + RUST_LOG=happyview=info,tower_http=info 67 57 ``` 68 58 69 - ## Railway / Fly.io / other platforms 59 + Structured logs go to stdout, so any platform that captures container stdout (Railway, Fly, ECS, Kubernetes) will ingest them without further configuration. For retention and querying, ship stdout to your usual log aggregator. 70 60 71 - The general process for any hosting platform: 61 + ## Event log retention 72 62 73 - 1. Choose a database: SQLite (default, zero setup) or Postgres 17+ (provision separately) 74 - 2. Set `DATABASE_URL`, `PUBLIC_URL`, and `SESSION_SECRET` environment variables (see [Configuration](../getting-started/configuration.md) for all options) 75 - 3. Deploy the Docker image or build from source 76 - 4. HappyView listens on `PORT` (default `3000`) 77 - 5. Health check: `GET /health` returns `ok` 63 + The admin [event log](../guides/event-logs.md) is stored in the same database as records. `EVENT_LOG_RETENTION_DAYS` (default `30`) controls automatic cleanup. Set to `0` to keep events indefinitely — useful for compliance-sensitive deployments, but plan for database growth. 78 64 79 - See the [database setup guide](../guides/database-setup.md) for details on both backends. 65 + ## Health checks 80 66 81 - For Railway specifically, the [Quickstart](../getting-started/deployment/railway.md) template handles all of this with a single click. 67 + `GET /health` returns `200 ok` when HappyView can bind its HTTP listener. Use it as the readiness/liveness probe for your platform. 82 68 83 - ## Database 69 + For a deeper check, hit `GET /xrpc/com.atproto.server.describeServer` — this exercises the database and lexicon registry, and only returns `200` if HappyView can actually serve requests. 84 70 85 - HappyView supports SQLite (default) and Postgres. The backend is auto-detected from the `DATABASE_URL` scheme (`sqlite://` or `postgres://`). Migrations run automatically on startup. No manual migration step is needed. See the [database setup guide](../guides/database-setup.md) for details. 71 + ## Backups 86 72 87 - ## TLS 73 + - **SQLite**: back up the database file (e.g. `data/happyview.db`) plus its `-wal` and `-shm` sidecar files. Use `sqlite3 happyview.db ".backup '/path/backup.db'"` for a consistent snapshot while HappyView is running. 74 + - **Postgres**: standard `pg_dump` / managed-Postgres snapshots. 88 75 89 - HappyView does not terminate TLS. Put it behind a reverse proxy (nginx, Caddy, Cloudflare Tunnel, etc.) for HTTPS. Make sure `PUBLIC_URL` matches the public-facing URL (including `https://`). 76 + Most of what HappyView stores is derivable from the network — lost records can be re-indexed via [backfill](../guides/backfill.md). What you cannot recover from the network: user accounts and permissions, API keys, API clients, plugin secrets, and the Jetstream cursor. Prioritize those in your backup plan. 90 77 91 - ## Logging 78 + ## Next steps 92 79 93 - HappyView uses the `RUST_LOG` environment variable to control log output. The default (`happyview=debug,tower_http=debug`) logs all HappyView activity and HTTP requests. For production, consider `happyview=info,tower_http=info` to reduce noise. See [Configuration](../getting-started/configuration.md) for details. 80 + - [Configuration](../getting-started/configuration.md) — full environment variable reference 81 + - [Permissions](../guides/permissions.md) — lock down admin access before exposing the dashboard publicly 82 + - [Troubleshooting](troubleshooting.md) — diagnose issues with a running instance
+3 -3
docs/reference/troubleshooting.md
··· 20 20 21 21 - The query lexicon is missing a `target_collection`. Without it, the query doesn't know which records to read. See [Lexicons - target_collection](../guides/lexicons.md#target-collection). 22 22 - The record-type lexicon hasn't finished backfilling. Check backfill status with `GET /admin/backfill/status` or the dashboard. 23 - - Records exist on the network but HappyView hasn't indexed them yet. Tap only picks up new events from when the collection filter was added. Use [backfill](../guides/backfill.md) for historical records. 23 + - Records exist on the network but HappyView hasn't indexed them yet. Jetstream only delivers events from after the collection was added to the filter. Use [backfill](../guides/backfill.md) to import historical records. 24 24 25 25 ## Procedure returns 401 Unauthorized 26 26 ··· 82 82 83 83 **Causes**: 84 84 85 - - HappyView receives real-time events via [Tap](https://github.com/bluesky-social/indigo/tree/main/cmd/tap). Make sure Tap is running and connected to HappyView. See the [Tap documentation](https://github.com/bluesky-social/indigo/tree/main/cmd/tap) for configuration. 85 + - HappyView receives real-time events via [Jetstream](https://github.com/bluesky-social/jetstream). Verify the `JETSTREAM_URL` is reachable and check server logs for `jetstream.disconnected` events. 86 86 - No record-type lexicon exists for the collection. HappyView only indexes collections that have a corresponding record-type lexicon. 87 - - The Tap connection hasn't synced the new collection filter after a lexicon change. This should happen automatically. Check server logs for connection errors. 87 + - The Jetstream subscription hasn't reconnected with the new collection filter after a lexicon change. This should happen automatically. Check server logs for connection errors. 88 88 89 89 ## OAuth or login issues 90 90
+1 -1
docs/tutorials/statusphere.md
··· 52 52 }' 53 53 ``` 54 54 55 - HappyView now subscribes to `xyz.statusphere.status` via Tap. The `backfill` flag tells HappyView to also index existing status records from the network. You can monitor progress with `GET /admin/backfill/status` or the [dashboard](../getting-started/dashboard.md). 55 + HappyView now subscribes to `xyz.statusphere.status` via Jetstream. The `backfill` flag tells HappyView to also index existing status records from the network. You can monitor progress with `GET /admin/backfill/status` or the [dashboard](../getting-started/dashboard.md). 56 56 57 57 :::tip 58 58 Since the `xyz.statusphere.status` lexicon is [published on the AT Protocol network](../guides/lexicons.md#network-lexicons), you can also add it as a network lexicon instead of uploading the JSON manually:
+537 -492
package-lock.json
··· 8 8 "name": "happyview-docs", 9 9 "version": "0.0.0", 10 10 "dependencies": { 11 - "@docusaurus/core": "^3.7.0", 12 - "@docusaurus/preset-classic": "^3.7.0", 13 - "@docusaurus/theme-mermaid": "^3.9.2", 11 + "@docusaurus/core": "^3.10.0", 12 + "@docusaurus/preset-classic": "^3.10.0", 13 + "@docusaurus/theme-mermaid": "^3.10.0", 14 + "@mermaid-js/layout-elk": "^0.1.9", 14 15 "@tailwindcss/typography": "^0.5.19", 15 16 "prismjs": "^1.30.0", 16 17 "react": "^19.0.0", 17 18 "react-dom": "^19.0.0" 18 19 }, 19 20 "devDependencies": { 20 - "@docusaurus/tsconfig": "^3.7.0", 21 + "@docusaurus/tsconfig": "^3.10.0", 21 22 "typescript": "^5.7.0" 22 23 } 23 24 }, 24 25 "node_modules/@algolia/abtesting": { 25 - "version": "1.14.2", 26 - "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.14.2.tgz", 27 - "integrity": "sha512-aEP+MOV8UJ489ezmNO7ojCHCgcn8XpM5Mt+7oEazfhU5pop6P7zIXWh9hbKOdXkDM3+4D5AOy5m8iOB72B3w+w==", 26 + "version": "1.16.2", 27 + "resolved": "https://registry.npmjs.org/@algolia/abtesting/-/abtesting-1.16.2.tgz", 28 + "integrity": "sha512-n9s6bEV6imdtIEd+BGP7WkA4pEZ5YTdgQ05JQhHwWawHg3hyjpNwC0TShGz6zWhv+jfLDGA/6FFNbySFS0P9cw==", 28 29 "license": "MIT", 29 30 "dependencies": { 30 - "@algolia/client-common": "5.48.2", 31 - "@algolia/requester-browser-xhr": "5.48.2", 32 - "@algolia/requester-fetch": "5.48.2", 33 - "@algolia/requester-node-http": "5.48.2" 31 + "@algolia/client-common": "5.50.2", 32 + "@algolia/requester-browser-xhr": "5.50.2", 33 + "@algolia/requester-fetch": "5.50.2", 34 + "@algolia/requester-node-http": "5.50.2" 34 35 }, 35 36 "engines": { 36 37 "node": ">= 14.0.0" 37 38 } 38 39 }, 39 40 "node_modules/@algolia/autocomplete-core": { 40 - "version": "1.19.2", 41 - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", 42 - "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", 41 + "version": "1.19.8", 42 + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.8.tgz", 43 + "integrity": "sha512-3YEorYg44niXcm7gkft3nXYItHd44e8tmh4D33CTszPgP0QWkaLEaFywiNyJBo7UL/mqObA/G9RYuU7R8tN1IA==", 43 44 "license": "MIT", 44 45 "dependencies": { 45 - "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", 46 - "@algolia/autocomplete-shared": "1.19.2" 46 + "@algolia/autocomplete-plugin-algolia-insights": "1.19.8", 47 + "@algolia/autocomplete-shared": "1.19.8" 47 48 } 48 49 }, 49 50 "node_modules/@algolia/autocomplete-plugin-algolia-insights": { 50 - "version": "1.19.2", 51 - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", 52 - "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", 51 + "version": "1.19.8", 52 + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.8.tgz", 53 + "integrity": "sha512-ZvJWO8ZZJDpc1LNM2TTBdmQsZBLMR4rU5iNR2OYvEeFBiaf/0ESnRSSLQbryarJY4SVxtoz6A2ZtDMNM+iQEAA==", 53 54 "license": "MIT", 54 55 "dependencies": { 55 - "@algolia/autocomplete-shared": "1.19.2" 56 + "@algolia/autocomplete-shared": "1.19.8" 56 57 }, 57 58 "peerDependencies": { 58 59 "search-insights": ">= 1 < 3" 59 60 } 60 61 }, 61 62 "node_modules/@algolia/autocomplete-shared": { 62 - "version": "1.19.2", 63 - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", 64 - "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", 63 + "version": "1.19.8", 64 + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.8.tgz", 65 + "integrity": "sha512-h5hf2t8ejF6vlOgvLaZzQbWs5SyH2z4PAWygNAvvD/2RI29hdQ54ldUGwqVuj9Srs+n8XUKTPUqb7fvhBhQrnQ==", 65 66 "license": "MIT", 66 67 "peerDependencies": { 67 68 "@algolia/client-search": ">= 4.9.1 < 6", ··· 69 70 } 70 71 }, 71 72 "node_modules/@algolia/client-abtesting": { 72 - "version": "5.48.2", 73 - "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.48.2.tgz", 74 - "integrity": "sha512-J+WLy0T7Yic9iGmI/qqGD21O1wHo7mKoHEkZ+D5DZ4Yy12ZFCMbFHLjGFw3+gkMrYSOJs4UOconP8O5r+j7Uqg==", 73 + "version": "5.50.2", 74 + "resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.50.2.tgz", 75 + "integrity": "sha512-52iq0vHy1sphgnwoZyx5PmbEt8hsh+m7jD123LmBs6qy4GK7LbYZIeKd+nSnSipN2zvKRZ2zScS6h9PW3J7SXg==", 75 76 "license": "MIT", 76 77 "dependencies": { 77 - "@algolia/client-common": "5.48.2", 78 - "@algolia/requester-browser-xhr": "5.48.2", 79 - "@algolia/requester-fetch": "5.48.2", 80 - "@algolia/requester-node-http": "5.48.2" 78 + "@algolia/client-common": "5.50.2", 79 + "@algolia/requester-browser-xhr": "5.50.2", 80 + "@algolia/requester-fetch": "5.50.2", 81 + "@algolia/requester-node-http": "5.50.2" 81 82 }, 82 83 "engines": { 83 84 "node": ">= 14.0.0" 84 85 } 85 86 }, 86 87 "node_modules/@algolia/client-analytics": { 87 - "version": "5.48.2", 88 - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.48.2.tgz", 89 - "integrity": "sha512-bPcSBe6UXDnW9YtI4iCPQj5G/ENtS9tICgWVk9M1Vkgsp7YZKPEeHKn4vu8T62+uI4wH7JON7lnwQS7Hgg9+Kw==", 88 + "version": "5.50.2", 89 + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.50.2.tgz", 90 + "integrity": "sha512-WpPIUg+cSG2aPUG0gS8Ko9DwRgbRPUZxJkolhL2aCsmSlcEEZT65dILrfg5ovcxtx0Kvr+xtBVsTMtsQWRtPDQ==", 90 91 "license": "MIT", 91 92 "dependencies": { 92 - "@algolia/client-common": "5.48.2", 93 - "@algolia/requester-browser-xhr": "5.48.2", 94 - "@algolia/requester-fetch": "5.48.2", 95 - "@algolia/requester-node-http": "5.48.2" 93 + "@algolia/client-common": "5.50.2", 94 + "@algolia/requester-browser-xhr": "5.50.2", 95 + "@algolia/requester-fetch": "5.50.2", 96 + "@algolia/requester-node-http": "5.50.2" 96 97 }, 97 98 "engines": { 98 99 "node": ">= 14.0.0" 99 100 } 100 101 }, 101 102 "node_modules/@algolia/client-common": { 102 - "version": "5.48.2", 103 - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.48.2.tgz", 104 - "integrity": "sha512-X/t8zvUrzG4xBWVVqIwgNhvE3hZWa0h118gaEMRYXwc+QUnX+PoBnyoYaYYCwebX3dK/gafmjZ/hRy7NejgB0w==", 103 + "version": "5.50.2", 104 + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.50.2.tgz", 105 + "integrity": "sha512-Gj2MgtArGcsr82kIqRlo6/dCAFjrs2gLByEqyRENuT7ugrSMFuqg1vDzeBjRL1t3EJEJCFtT0PLX3gB8A6Hq4Q==", 105 106 "license": "MIT", 106 107 "engines": { 107 108 "node": ">= 14.0.0" 108 109 } 109 110 }, 110 111 "node_modules/@algolia/client-insights": { 111 - "version": "5.48.2", 112 - "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.48.2.tgz", 113 - "integrity": "sha512-VoTLdlfxpJYzWhEfZHCGtdJRbXgpopNScEow71S4hC8VS0DF4BU3aqq58yYYF4cN/63zhG62f2tol7UYFm0WNg==", 112 + "version": "5.50.2", 113 + "resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.50.2.tgz", 114 + "integrity": "sha512-CUqoid5jDpmrc0oK3/xuZXFt6kwT0P9Lw7/nsM14YTr6puvmi+OUKmURpmebQF22S2vCG8L1DAoXXujxQUi/ug==", 114 115 "license": "MIT", 115 116 "dependencies": { 116 - "@algolia/client-common": "5.48.2", 117 - "@algolia/requester-browser-xhr": "5.48.2", 118 - "@algolia/requester-fetch": "5.48.2", 119 - "@algolia/requester-node-http": "5.48.2" 117 + "@algolia/client-common": "5.50.2", 118 + "@algolia/requester-browser-xhr": "5.50.2", 119 + "@algolia/requester-fetch": "5.50.2", 120 + "@algolia/requester-node-http": "5.50.2" 120 121 }, 121 122 "engines": { 122 123 "node": ">= 14.0.0" 123 124 } 124 125 }, 125 126 "node_modules/@algolia/client-personalization": { 126 - "version": "5.48.2", 127 - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.48.2.tgz", 128 - "integrity": "sha512-lrmKAvaH6Rc+Aji+9MdgKb8vYfi7CMSgr3SZIVOxFgVKVM732dKQUPAAy54RsGKyt22Qk+IdYQsjOd01O3PUag==", 127 + "version": "5.50.2", 128 + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.50.2.tgz", 129 + "integrity": "sha512-AndZWFoc0gbP5901OeQJ73BazgGgSGiBEba4ohdoJuZwHTO2Gio8Q4L1VLmytMBYcviVigB0iICToMvEJxI4ug==", 129 130 "license": "MIT", 130 131 "dependencies": { 131 - "@algolia/client-common": "5.48.2", 132 - "@algolia/requester-browser-xhr": "5.48.2", 133 - "@algolia/requester-fetch": "5.48.2", 134 - "@algolia/requester-node-http": "5.48.2" 132 + "@algolia/client-common": "5.50.2", 133 + "@algolia/requester-browser-xhr": "5.50.2", 134 + "@algolia/requester-fetch": "5.50.2", 135 + "@algolia/requester-node-http": "5.50.2" 135 136 }, 136 137 "engines": { 137 138 "node": ">= 14.0.0" 138 139 } 139 140 }, 140 141 "node_modules/@algolia/client-query-suggestions": { 141 - "version": "5.48.2", 142 - "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.48.2.tgz", 143 - "integrity": "sha512-pEMkQq6jGxqELBxyFkZa9niK5eM+pQnIruoPQqCjfPgdrmAYYqLatrbWj4//AeQGoAe59xLwkExconu9OXWlNw==", 142 + "version": "5.50.2", 143 + "resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.50.2.tgz", 144 + "integrity": "sha512-NWoL+psEkz5dIzweaByVXuEB45wS8/rk0E0AhMMnaVJdVs7TcACPH2/OURm+N0xRDITkTHqCna823rd6Uqntdg==", 144 145 "license": "MIT", 145 146 "dependencies": { 146 - "@algolia/client-common": "5.48.2", 147 - "@algolia/requester-browser-xhr": "5.48.2", 148 - "@algolia/requester-fetch": "5.48.2", 149 - "@algolia/requester-node-http": "5.48.2" 147 + "@algolia/client-common": "5.50.2", 148 + "@algolia/requester-browser-xhr": "5.50.2", 149 + "@algolia/requester-fetch": "5.50.2", 150 + "@algolia/requester-node-http": "5.50.2" 150 151 }, 151 152 "engines": { 152 153 "node": ">= 14.0.0" 153 154 } 154 155 }, 155 156 "node_modules/@algolia/client-search": { 156 - "version": "5.48.2", 157 - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.48.2.tgz", 158 - "integrity": "sha512-PI+bOkutJnO7hsPZALHKWFj83K/45p4ABODUf0kKIoJS8tXJgDDhjYJGg6Eh/x177OokLfBPJUV9z3OspGt99g==", 157 + "version": "5.50.2", 158 + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.50.2.tgz", 159 + "integrity": "sha512-ypSboUJ3XJoQz5DeDo82hCnrRuwq3q9ZdFhVKAik9TnZh1DvLqoQsrbBjXg7C7zQOtV/Qbge/HmyoV6V5L7MhQ==", 159 160 "license": "MIT", 160 161 "peer": true, 161 162 "dependencies": { 162 - "@algolia/client-common": "5.48.2", 163 - "@algolia/requester-browser-xhr": "5.48.2", 164 - "@algolia/requester-fetch": "5.48.2", 165 - "@algolia/requester-node-http": "5.48.2" 163 + "@algolia/client-common": "5.50.2", 164 + "@algolia/requester-browser-xhr": "5.50.2", 165 + "@algolia/requester-fetch": "5.50.2", 166 + "@algolia/requester-node-http": "5.50.2" 166 167 }, 167 168 "engines": { 168 169 "node": ">= 14.0.0" ··· 175 176 "license": "MIT" 176 177 }, 177 178 "node_modules/@algolia/ingestion": { 178 - "version": "1.48.2", 179 - "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.48.2.tgz", 180 - "integrity": "sha512-bFQc93yvGvGJuDJv13NpK157yP5prYuo7mkWbdbIBMpRdBkDUTO9FuI9ScEaEWUiahW0ScKZyJNix0KWYGWfZg==", 179 + "version": "1.50.2", 180 + "resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.50.2.tgz", 181 + "integrity": "sha512-VlR2FRXLw2bCB94SQo6zxg/Qi+547aOji6Pb+dKE7h1DMCCY317St+OpjpmgzE+bT2O9ALIc0V4nVIBOd7Gy+Q==", 181 182 "license": "MIT", 182 183 "dependencies": { 183 - "@algolia/client-common": "5.48.2", 184 - "@algolia/requester-browser-xhr": "5.48.2", 185 - "@algolia/requester-fetch": "5.48.2", 186 - "@algolia/requester-node-http": "5.48.2" 184 + "@algolia/client-common": "5.50.2", 185 + "@algolia/requester-browser-xhr": "5.50.2", 186 + "@algolia/requester-fetch": "5.50.2", 187 + "@algolia/requester-node-http": "5.50.2" 187 188 }, 188 189 "engines": { 189 190 "node": ">= 14.0.0" 190 191 } 191 192 }, 192 193 "node_modules/@algolia/monitoring": { 193 - "version": "1.48.2", 194 - "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.48.2.tgz", 195 - "integrity": "sha512-D3Avase5S70wA8JMx9VFgbfoEpuyoPgJHa8sBycPndaeVzH4sst3HLm/u5c94+EkIkpGxdTC0EnxkGjFgtpUdQ==", 194 + "version": "1.50.2", 195 + "resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.50.2.tgz", 196 + "integrity": "sha512-Cmvfp2+qopzQt8OilU97rhLhosq7ZrB6uieok3EwFUqG/aalPg6DgfCmu0yJMrYe+KMC1qRVt1MTRAUwLknUMQ==", 196 197 "license": "MIT", 197 198 "dependencies": { 198 - "@algolia/client-common": "5.48.2", 199 - "@algolia/requester-browser-xhr": "5.48.2", 200 - "@algolia/requester-fetch": "5.48.2", 201 - "@algolia/requester-node-http": "5.48.2" 199 + "@algolia/client-common": "5.50.2", 200 + "@algolia/requester-browser-xhr": "5.50.2", 201 + "@algolia/requester-fetch": "5.50.2", 202 + "@algolia/requester-node-http": "5.50.2" 202 203 }, 203 204 "engines": { 204 205 "node": ">= 14.0.0" 205 206 } 206 207 }, 207 208 "node_modules/@algolia/recommend": { 208 - "version": "5.48.2", 209 - "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.48.2.tgz", 210 - "integrity": "sha512-W3ptpVzEtE++8Giuoy8oQO7fer58TIQfFWWem49yef/W3FTNjDmVskJg4SpEFBsX9vqK4REGC2ye//LeVWN5IA==", 209 + "version": "5.50.2", 210 + "resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.50.2.tgz", 211 + "integrity": "sha512-jrkuyKoOM7dFWQ/6Y4hQAse2SC3L/RldG6GnPjMvAj65h+7Ubb51S0pKk4ofSStF0xm4LCNe0C4T6XX4nOFDiQ==", 211 212 "license": "MIT", 212 213 "dependencies": { 213 - "@algolia/client-common": "5.48.2", 214 - "@algolia/requester-browser-xhr": "5.48.2", 215 - "@algolia/requester-fetch": "5.48.2", 216 - "@algolia/requester-node-http": "5.48.2" 214 + "@algolia/client-common": "5.50.2", 215 + "@algolia/requester-browser-xhr": "5.50.2", 216 + "@algolia/requester-fetch": "5.50.2", 217 + "@algolia/requester-node-http": "5.50.2" 217 218 }, 218 219 "engines": { 219 220 "node": ">= 14.0.0" 220 221 } 221 222 }, 222 223 "node_modules/@algolia/requester-browser-xhr": { 223 - "version": "5.48.2", 224 - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.48.2.tgz", 225 - "integrity": "sha512-XNElquK8FJi7AEDr7k42C5NZIGieMsGqpggFFBxtFxJs53zu8eOqs6zJ4Os7MdCQROMYMjZ/N+AlhRcxOWw7Bw==", 224 + "version": "5.50.2", 225 + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.50.2.tgz", 226 + "integrity": "sha512-4107YLJqCudPiBUlwnk6oTSUVwU7ab+qL1SfQGEDYI8DZH5gsf1ekPt9JykXRKYXf2IfouFL5GiCY/PHTFIjYw==", 226 227 "license": "MIT", 227 228 "dependencies": { 228 - "@algolia/client-common": "5.48.2" 229 + "@algolia/client-common": "5.50.2" 229 230 }, 230 231 "engines": { 231 232 "node": ">= 14.0.0" 232 233 } 233 234 }, 234 235 "node_modules/@algolia/requester-fetch": { 235 - "version": "5.48.2", 236 - "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.48.2.tgz", 237 - "integrity": "sha512-0Flw5rr9n5Yai5WFD7G8U0KN9oUaVTCHV6OxH48yaIpIcXfjjtBEZpsQYKecv2PN8qs9d5QBznOh+S9BKN6Tcw==", 236 + "version": "5.50.2", 237 + "resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.50.2.tgz", 238 + "integrity": "sha512-vOrd3MQpLgmf6wXAueTuZ/cA0W4uRwIHHaxNy3h+a6YcNn6bCV/gFdZuv3F13v593zRU2k5R75NmvRWLenvMrw==", 238 239 "license": "MIT", 239 240 "dependencies": { 240 - "@algolia/client-common": "5.48.2" 241 + "@algolia/client-common": "5.50.2" 241 242 }, 242 243 "engines": { 243 244 "node": ">= 14.0.0" 244 245 } 245 246 }, 246 247 "node_modules/@algolia/requester-node-http": { 247 - "version": "5.48.2", 248 - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.48.2.tgz", 249 - "integrity": "sha512-rprr8yA/tcoNoqoKFRm/6hBRsosMfcUSHVDGsi//hjo3g5BLwLtlzBxmhb47/7YjwfEQHtIDvu7L7qkY3kmC/g==", 248 + "version": "5.50.2", 249 + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.50.2.tgz", 250 + "integrity": "sha512-Mu9BFtgzGqDUy5Bcs2nMyoILIFSN13GKQaklKAFIsd0K3/9CpNyfeBc+/+Qs6mFZLlxG9qzullO7h+bjcTBuGQ==", 250 251 "license": "MIT", 251 252 "dependencies": { 252 - "@algolia/client-common": "5.48.2" 253 + "@algolia/client-common": "5.50.2" 253 254 }, 254 255 "engines": { 255 256 "node": ">= 14.0.0" ··· 441 442 } 442 443 }, 443 444 "node_modules/@babel/helper-define-polyfill-provider": { 444 - "version": "0.6.6", 445 - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.6.tgz", 446 - "integrity": "sha512-mOAsxeeKkUKayvZR3HeTYD/fICpCPLJrU5ZjelT/PA6WHtNDBOE436YiaEUvHN454bRM3CebhDsIpieCc4texA==", 445 + "version": "0.6.8", 446 + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", 447 + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", 447 448 "license": "MIT", 448 449 "dependencies": { 449 450 "@babel/helper-compilation-targets": "^7.28.6", ··· 618 619 } 619 620 }, 620 621 "node_modules/@babel/helpers": { 621 - "version": "7.28.6", 622 - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", 623 - "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", 622 + "version": "7.29.2", 623 + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz", 624 + "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==", 624 625 "license": "MIT", 625 626 "dependencies": { 626 627 "@babel/template": "^7.28.6", 627 - "@babel/types": "^7.28.6" 628 + "@babel/types": "^7.29.0" 628 629 }, 629 630 "engines": { 630 631 "node": ">=6.9.0" 631 632 } 632 633 }, 633 634 "node_modules/@babel/parser": { 634 - "version": "7.29.0", 635 - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", 636 - "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", 635 + "version": "7.29.2", 636 + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.2.tgz", 637 + "integrity": "sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==", 637 638 "license": "MIT", 638 639 "dependencies": { 639 640 "@babel/types": "^7.29.0" ··· 1758 1759 } 1759 1760 }, 1760 1761 "node_modules/@babel/preset-env": { 1761 - "version": "7.29.0", 1762 - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.0.tgz", 1763 - "integrity": "sha512-fNEdfc0yi16lt6IZo2Qxk3knHVdfMYX33czNb4v8yWhemoBhibCpQK/uYHtSKIiO+p/zd3+8fYVXhQdOVV608w==", 1762 + "version": "7.29.2", 1763 + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.2.tgz", 1764 + "integrity": "sha512-DYD23veRYGvBFhcTY1iUvJnDNpuqNd/BzBwCvzOTKUnJjKg5kpUBh3/u9585Agdkgj+QuygG7jLfOPWMa2KVNw==", 1764 1765 "license": "MIT", 1765 1766 "dependencies": { 1766 1767 "@babel/compat-data": "^7.29.0", ··· 1842 1843 } 1843 1844 }, 1844 1845 "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { 1845 - "version": "0.14.0", 1846 - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.0.tgz", 1847 - "integrity": "sha512-AvDcMxJ34W4Wgy4KBIIePQTAOP1Ie2WFwkQp3dB7FQ/f0lI5+nM96zUnYEOE1P9sEg0es5VCP0HxiWu5fUHZAQ==", 1846 + "version": "0.14.2", 1847 + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", 1848 + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", 1848 1849 "license": "MIT", 1849 1850 "dependencies": { 1850 - "@babel/helper-define-polyfill-provider": "^0.6.6", 1851 + "@babel/helper-define-polyfill-provider": "^0.6.8", 1851 1852 "core-js-compat": "^3.48.0" 1852 1853 }, 1853 1854 "peerDependencies": { ··· 1921 1922 "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz", 1922 1923 "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==", 1923 1924 "license": "MIT", 1924 - "engines": { 1925 - "node": ">=6.9.0" 1926 - } 1927 - }, 1928 - "node_modules/@babel/runtime-corejs3": { 1929 - "version": "7.29.0", 1930 - "resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.29.0.tgz", 1931 - "integrity": "sha512-TgUkdp71C9pIbBcHudc+gXZnihEDOjUAmXO1VO4HHGES7QLZcShR0stfKIxLSNIYx2fqhmJChOjm/wkF8wv4gA==", 1932 - "license": "MIT", 1933 - "dependencies": { 1934 - "core-js-pure": "^3.48.0" 1935 - }, 1936 1925 "engines": { 1937 1926 "node": ">=6.9.0" 1938 1927 } ··· 3367 3356 } 3368 3357 }, 3369 3358 "node_modules/@docsearch/core": { 3370 - "version": "4.6.0", 3371 - "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.0.tgz", 3372 - "integrity": "sha512-IqG3oSd529jVRQ4dWZQKwZwQLVd//bWJTz2HiL0LkiHrI4U/vLrBasKB7lwQB/69nBAcCgs3TmudxTZSLH/ZQg==", 3359 + "version": "4.6.2", 3360 + "resolved": "https://registry.npmjs.org/@docsearch/core/-/core-4.6.2.tgz", 3361 + "integrity": "sha512-/S0e6Dj7Zcm8m9Rru49YEX49dhU11be68c+S/BCyN8zQsTTgkKzXlhRbVL5mV6lOLC2+ZRRryaTdcm070Ug2oA==", 3373 3362 "license": "MIT", 3374 3363 "peerDependencies": { 3375 3364 "@types/react": ">= 16.8.0 < 20.0.0", ··· 3389 3378 } 3390 3379 }, 3391 3380 "node_modules/@docsearch/css": { 3392 - "version": "4.6.0", 3393 - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.0.tgz", 3394 - "integrity": "sha512-YlcAimkXclvqta47g47efzCM5CFxDwv2ClkDfEs/fC/Ak0OxPH2b3czwa4o8O1TRBf+ujFF2RiUwszz2fPVNJQ==", 3381 + "version": "4.6.2", 3382 + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-4.6.2.tgz", 3383 + "integrity": "sha512-fH/cn8BjEEdM2nJdjNMHIvOVYupG6AIDtFVDgIZrNzdCSj4KXr9kd+hsehqsNGYjpUjObeKYKvgy/IwCb1jZYQ==", 3395 3384 "license": "MIT" 3396 3385 }, 3397 3386 "node_modules/@docsearch/react": { 3398 - "version": "4.6.0", 3399 - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.0.tgz", 3400 - "integrity": "sha512-j8H5B4ArGxBPBWvw3X0J0Rm/Pjv2JDa2rV5OE0DLTp5oiBCptIJ/YlNOhZxuzbO2nwge+o3Z52nJRi3hryK9cA==", 3387 + "version": "4.6.2", 3388 + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-4.6.2.tgz", 3389 + "integrity": "sha512-/BbtGFtqVOGwZx0dw/UfhN/0/DmMQYnulY4iv0tPRhC2JCXv0ka/+izwt3Jzo1ZxXS/2eMvv9zHsBJOK1I9f/w==", 3401 3390 "license": "MIT", 3402 3391 "dependencies": { 3403 3392 "@algolia/autocomplete-core": "1.19.2", 3404 - "@docsearch/core": "4.6.0", 3405 - "@docsearch/css": "4.6.0" 3393 + "@docsearch/core": "4.6.2", 3394 + "@docsearch/css": "4.6.2" 3406 3395 }, 3407 3396 "peerDependencies": { 3408 3397 "@types/react": ">= 16.8.0 < 20.0.0", ··· 3425 3414 } 3426 3415 } 3427 3416 }, 3417 + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-core": { 3418 + "version": "1.19.2", 3419 + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.19.2.tgz", 3420 + "integrity": "sha512-mKv7RyuAzXvwmq+0XRK8HqZXt9iZ5Kkm2huLjgn5JoCPtDy+oh9yxUMfDDaVCw0oyzZ1isdJBc7l9nuCyyR7Nw==", 3421 + "license": "MIT", 3422 + "dependencies": { 3423 + "@algolia/autocomplete-plugin-algolia-insights": "1.19.2", 3424 + "@algolia/autocomplete-shared": "1.19.2" 3425 + } 3426 + }, 3427 + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-plugin-algolia-insights": { 3428 + "version": "1.19.2", 3429 + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-plugin-algolia-insights/-/autocomplete-plugin-algolia-insights-1.19.2.tgz", 3430 + "integrity": "sha512-TjxbcC/r4vwmnZaPwrHtkXNeqvlpdyR+oR9Wi2XyfORkiGkLTVhX2j+O9SaCCINbKoDfc+c2PB8NjfOnz7+oKg==", 3431 + "license": "MIT", 3432 + "dependencies": { 3433 + "@algolia/autocomplete-shared": "1.19.2" 3434 + }, 3435 + "peerDependencies": { 3436 + "search-insights": ">= 1 < 3" 3437 + } 3438 + }, 3439 + "node_modules/@docsearch/react/node_modules/@algolia/autocomplete-shared": { 3440 + "version": "1.19.2", 3441 + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.19.2.tgz", 3442 + "integrity": "sha512-jEazxZTVD2nLrC+wYlVHQgpBoBB5KPStrJxLzsIFl6Kqd1AlG9sIAGl39V5tECLpIQzB3Qa2T6ZPJ1ChkwMK/w==", 3443 + "license": "MIT", 3444 + "peerDependencies": { 3445 + "@algolia/client-search": ">= 4.9.1 < 6", 3446 + "algoliasearch": ">= 4.9.1 < 6" 3447 + } 3448 + }, 3428 3449 "node_modules/@docusaurus/babel": { 3429 - "version": "3.9.2", 3430 - "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.9.2.tgz", 3431 - "integrity": "sha512-GEANdi/SgER+L7Japs25YiGil/AUDnFFHaCGPBbundxoWtCkA2lmy7/tFmgED4y1htAy6Oi4wkJEQdGssnw9MA==", 3450 + "version": "3.10.0", 3451 + "resolved": "https://registry.npmjs.org/@docusaurus/babel/-/babel-3.10.0.tgz", 3452 + "integrity": "sha512-mqCJhCZNZUDg0zgDEaPTM4DnRsisa24HdqTy/qn/MQlbwhTb4WVaZg6ZyX6yIVKqTz8fS1hBMgM+98z+BeJJDg==", 3432 3453 "license": "MIT", 3433 3454 "dependencies": { 3434 3455 "@babel/core": "^7.25.9", ··· 3439 3460 "@babel/preset-react": "^7.25.9", 3440 3461 "@babel/preset-typescript": "^7.25.9", 3441 3462 "@babel/runtime": "^7.25.9", 3442 - "@babel/runtime-corejs3": "^7.25.9", 3443 3463 "@babel/traverse": "^7.25.9", 3444 - "@docusaurus/logger": "3.9.2", 3445 - "@docusaurus/utils": "3.9.2", 3464 + "@docusaurus/logger": "3.10.0", 3465 + "@docusaurus/utils": "3.10.0", 3446 3466 "babel-plugin-dynamic-import-node": "^2.3.3", 3447 3467 "fs-extra": "^11.1.1", 3448 3468 "tslib": "^2.6.0" ··· 3452 3472 } 3453 3473 }, 3454 3474 "node_modules/@docusaurus/bundler": { 3455 - "version": "3.9.2", 3456 - "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.9.2.tgz", 3457 - "integrity": "sha512-ZOVi6GYgTcsZcUzjblpzk3wH1Fya2VNpd5jtHoCCFcJlMQ1EYXZetfAnRHLcyiFeBABaI1ltTYbOBtH/gahGVA==", 3475 + "version": "3.10.0", 3476 + "resolved": "https://registry.npmjs.org/@docusaurus/bundler/-/bundler-3.10.0.tgz", 3477 + "integrity": "sha512-iONUGZGgp+lAkw/cJZH6irONcF4p8+278IsdRlq8lYhxGjkoNUs0w7F4gVXBYSNChq5KG5/JleTSsdJySShxow==", 3458 3478 "license": "MIT", 3459 3479 "dependencies": { 3460 3480 "@babel/core": "^7.25.9", 3461 - "@docusaurus/babel": "3.9.2", 3462 - "@docusaurus/cssnano-preset": "3.9.2", 3463 - "@docusaurus/logger": "3.9.2", 3464 - "@docusaurus/types": "3.9.2", 3465 - "@docusaurus/utils": "3.9.2", 3481 + "@docusaurus/babel": "3.10.0", 3482 + "@docusaurus/cssnano-preset": "3.10.0", 3483 + "@docusaurus/logger": "3.10.0", 3484 + "@docusaurus/types": "3.10.0", 3485 + "@docusaurus/utils": "3.10.0", 3466 3486 "babel-loader": "^9.2.1", 3467 3487 "clean-css": "^5.3.3", 3468 3488 "copy-webpack-plugin": "^11.0.0", ··· 3495 3515 } 3496 3516 }, 3497 3517 "node_modules/@docusaurus/core": { 3498 - "version": "3.9.2", 3499 - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.9.2.tgz", 3500 - "integrity": "sha512-HbjwKeC+pHUFBfLMNzuSjqFE/58+rLVKmOU3lxQrpsxLBOGosYco/Q0GduBb0/jEMRiyEqjNT/01rRdOMWq5pw==", 3518 + "version": "3.10.0", 3519 + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-3.10.0.tgz", 3520 + "integrity": "sha512-mgLdQsO8xppnQZc3LPi+Mf+PkPeyxJeIx11AXAq/14fsaMefInQiMEZUUmrc7J+956G/f7MwE7tn8KZgi3iRcA==", 3501 3521 "license": "MIT", 3502 3522 "dependencies": { 3503 - "@docusaurus/babel": "3.9.2", 3504 - "@docusaurus/bundler": "3.9.2", 3505 - "@docusaurus/logger": "3.9.2", 3506 - "@docusaurus/mdx-loader": "3.9.2", 3507 - "@docusaurus/utils": "3.9.2", 3508 - "@docusaurus/utils-common": "3.9.2", 3509 - "@docusaurus/utils-validation": "3.9.2", 3523 + "@docusaurus/babel": "3.10.0", 3524 + "@docusaurus/bundler": "3.10.0", 3525 + "@docusaurus/logger": "3.10.0", 3526 + "@docusaurus/mdx-loader": "3.10.0", 3527 + "@docusaurus/utils": "3.10.0", 3528 + "@docusaurus/utils-common": "3.10.0", 3529 + "@docusaurus/utils-validation": "3.10.0", 3510 3530 "boxen": "^6.2.1", 3511 3531 "chalk": "^4.1.2", 3512 3532 "chokidar": "^3.5.3", ··· 3518 3538 "escape-html": "^1.0.3", 3519 3539 "eta": "^2.2.0", 3520 3540 "eval": "^0.1.8", 3521 - "execa": "5.1.1", 3541 + "execa": "^5.1.1", 3522 3542 "fs-extra": "^11.1.1", 3523 3543 "html-tags": "^3.3.1", 3524 3544 "html-webpack-plugin": "^5.6.0", ··· 3529 3549 "prompts": "^2.4.2", 3530 3550 "react-helmet-async": "npm:@slorber/react-helmet-async@1.3.0", 3531 3551 "react-loadable": "npm:@docusaurus/react-loadable@6.0.0", 3532 - "react-loadable-ssr-addon-v5-slorber": "^1.0.1", 3552 + "react-loadable-ssr-addon-v5-slorber": "^1.0.3", 3533 3553 "react-router": "^5.3.4", 3534 3554 "react-router-config": "^5.1.1", 3535 3555 "react-router-dom": "^5.3.4", 3536 3556 "semver": "^7.5.4", 3537 - "serve-handler": "^6.1.6", 3557 + "serve-handler": "^6.1.7", 3538 3558 "tinypool": "^1.0.2", 3539 3559 "tslib": "^2.6.0", 3540 3560 "update-notifier": "^6.0.2", ··· 3550 3570 "node": ">=20.0" 3551 3571 }, 3552 3572 "peerDependencies": { 3573 + "@docusaurus/faster": "*", 3553 3574 "@mdx-js/react": "^3.0.0", 3554 3575 "react": "^18.0.0 || ^19.0.0", 3555 3576 "react-dom": "^18.0.0 || ^19.0.0" 3577 + }, 3578 + "peerDependenciesMeta": { 3579 + "@docusaurus/faster": { 3580 + "optional": true 3581 + } 3556 3582 } 3557 3583 }, 3558 3584 "node_modules/@docusaurus/cssnano-preset": { 3559 - "version": "3.9.2", 3560 - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.9.2.tgz", 3561 - "integrity": "sha512-8gBKup94aGttRduABsj7bpPFTX7kbwu+xh3K9NMCF5K4bWBqTFYW+REKHF6iBVDHRJ4grZdIPbvkiHd/XNKRMQ==", 3585 + "version": "3.10.0", 3586 + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-3.10.0.tgz", 3587 + "integrity": "sha512-qzSshTO1DB3TYW+dPUal5KHM7XPc5YQfzF3Kdb2NDACJUyGbNcFtw3tGkCJlYwhNCRKbZcmwraKUS1i5dcHdGg==", 3562 3588 "license": "MIT", 3563 3589 "dependencies": { 3564 3590 "cssnano-preset-advanced": "^6.1.2", ··· 3571 3597 } 3572 3598 }, 3573 3599 "node_modules/@docusaurus/logger": { 3574 - "version": "3.9.2", 3575 - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.9.2.tgz", 3576 - "integrity": "sha512-/SVCc57ByARzGSU60c50rMyQlBuMIJCjcsJlkphxY6B0GV4UH3tcA1994N8fFfbJ9kX3jIBe/xg3XP5qBtGDbA==", 3600 + "version": "3.10.0", 3601 + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-3.10.0.tgz", 3602 + "integrity": "sha512-9jrZzFuBH1LDRlZ7cznAhCLmAZ3HSDqgwdrSSZdGHq9SPUOQgXXu8mnxe2ZRB9NS1PCpMTIOVUqDtZPIhMafZg==", 3577 3603 "license": "MIT", 3578 3604 "dependencies": { 3579 3605 "chalk": "^4.1.2", ··· 3584 3610 } 3585 3611 }, 3586 3612 "node_modules/@docusaurus/mdx-loader": { 3587 - "version": "3.9.2", 3588 - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.9.2.tgz", 3589 - "integrity": "sha512-wiYoGwF9gdd6rev62xDU8AAM8JuLI/hlwOtCzMmYcspEkzecKrP8J8X+KpYnTlACBUUtXNJpSoCwFWJhLRevzQ==", 3613 + "version": "3.10.0", 3614 + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-3.10.0.tgz", 3615 + "integrity": "sha512-mQQV97080AH4PYNs087l202NMDqRopZA4mg5W76ZZyTFrmWhJ3mHg+8A+drJVENxw5/Q+wHMHLgsx+9z1nEs0A==", 3590 3616 "license": "MIT", 3591 3617 "dependencies": { 3592 - "@docusaurus/logger": "3.9.2", 3593 - "@docusaurus/utils": "3.9.2", 3594 - "@docusaurus/utils-validation": "3.9.2", 3618 + "@docusaurus/logger": "3.10.0", 3619 + "@docusaurus/utils": "3.10.0", 3620 + "@docusaurus/utils-validation": "3.10.0", 3595 3621 "@mdx-js/mdx": "^3.0.0", 3596 3622 "@slorber/remark-comment": "^1.0.0", 3597 3623 "escape-html": "^1.0.3", ··· 3623 3649 } 3624 3650 }, 3625 3651 "node_modules/@docusaurus/module-type-aliases": { 3626 - "version": "3.9.2", 3627 - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.9.2.tgz", 3628 - "integrity": "sha512-8qVe2QA9hVLzvnxP46ysuofJUIc/yYQ82tvA/rBTrnpXtCjNSFLxEZfd5U8cYZuJIVlkPxamsIgwd5tGZXfvew==", 3652 + "version": "3.10.0", 3653 + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-3.10.0.tgz", 3654 + "integrity": "sha512-/1O0Zg8w3DFrYX/I6Fbss7OJrtZw1QoyjDhegiFNHVi9A9Y0gQ3jUAytVxF6ywpAWpLyLxch8nN8H/V3XfzdJQ==", 3629 3655 "license": "MIT", 3630 3656 "dependencies": { 3631 - "@docusaurus/types": "3.9.2", 3657 + "@docusaurus/types": "3.10.0", 3632 3658 "@types/history": "^4.7.11", 3633 3659 "@types/react": "*", 3634 3660 "@types/react-router-config": "*", ··· 3642 3668 } 3643 3669 }, 3644 3670 "node_modules/@docusaurus/plugin-content-blog": { 3645 - "version": "3.9.2", 3646 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.9.2.tgz", 3647 - "integrity": "sha512-3I2HXy3L1QcjLJLGAoTvoBnpOwa6DPUa3Q0dMK19UTY9mhPkKQg/DYhAGTiBUKcTR0f08iw7kLPqOhIgdV3eVQ==", 3671 + "version": "3.10.0", 3672 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-3.10.0.tgz", 3673 + "integrity": "sha512-RuTz68DhB7CL96QO5UsFbciD7GPYq6QV+YMfF9V0+N4ZgLhJIBgpVAr8GobrKF6NRe5cyWWETU5z5T834piG9g==", 3648 3674 "license": "MIT", 3649 3675 "dependencies": { 3650 - "@docusaurus/core": "3.9.2", 3651 - "@docusaurus/logger": "3.9.2", 3652 - "@docusaurus/mdx-loader": "3.9.2", 3653 - "@docusaurus/theme-common": "3.9.2", 3654 - "@docusaurus/types": "3.9.2", 3655 - "@docusaurus/utils": "3.9.2", 3656 - "@docusaurus/utils-common": "3.9.2", 3657 - "@docusaurus/utils-validation": "3.9.2", 3676 + "@docusaurus/core": "3.10.0", 3677 + "@docusaurus/logger": "3.10.0", 3678 + "@docusaurus/mdx-loader": "3.10.0", 3679 + "@docusaurus/theme-common": "3.10.0", 3680 + "@docusaurus/types": "3.10.0", 3681 + "@docusaurus/utils": "3.10.0", 3682 + "@docusaurus/utils-common": "3.10.0", 3683 + "@docusaurus/utils-validation": "3.10.0", 3658 3684 "cheerio": "1.0.0-rc.12", 3685 + "combine-promises": "^1.1.0", 3659 3686 "feed": "^4.2.2", 3660 3687 "fs-extra": "^11.1.1", 3661 3688 "lodash": "^4.17.21", ··· 3676 3703 } 3677 3704 }, 3678 3705 "node_modules/@docusaurus/plugin-content-docs": { 3679 - "version": "3.9.2", 3680 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.9.2.tgz", 3681 - "integrity": "sha512-C5wZsGuKTY8jEYsqdxhhFOe1ZDjH0uIYJ9T/jebHwkyxqnr4wW0jTkB72OMqNjsoQRcb0JN3PcSeTwFlVgzCZg==", 3706 + "version": "3.10.0", 3707 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-3.10.0.tgz", 3708 + "integrity": "sha512-9BjHhf15ct8Z7TThTC0xRndKDVvMKmVsAGAN7W9FpNRzfMdScOGcXtLmcCWtJGvAezjOJIm6CxOYCy3Io5+RnQ==", 3682 3709 "license": "MIT", 3683 3710 "peer": true, 3684 3711 "dependencies": { 3685 - "@docusaurus/core": "3.9.2", 3686 - "@docusaurus/logger": "3.9.2", 3687 - "@docusaurus/mdx-loader": "3.9.2", 3688 - "@docusaurus/module-type-aliases": "3.9.2", 3689 - "@docusaurus/theme-common": "3.9.2", 3690 - "@docusaurus/types": "3.9.2", 3691 - "@docusaurus/utils": "3.9.2", 3692 - "@docusaurus/utils-common": "3.9.2", 3693 - "@docusaurus/utils-validation": "3.9.2", 3712 + "@docusaurus/core": "3.10.0", 3713 + "@docusaurus/logger": "3.10.0", 3714 + "@docusaurus/mdx-loader": "3.10.0", 3715 + "@docusaurus/module-type-aliases": "3.10.0", 3716 + "@docusaurus/theme-common": "3.10.0", 3717 + "@docusaurus/types": "3.10.0", 3718 + "@docusaurus/utils": "3.10.0", 3719 + "@docusaurus/utils-common": "3.10.0", 3720 + "@docusaurus/utils-validation": "3.10.0", 3694 3721 "@types/react-router-config": "^5.0.7", 3695 3722 "combine-promises": "^1.1.0", 3696 3723 "fs-extra": "^11.1.1", ··· 3710 3737 } 3711 3738 }, 3712 3739 "node_modules/@docusaurus/plugin-content-pages": { 3713 - "version": "3.9.2", 3714 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.9.2.tgz", 3715 - "integrity": "sha512-s4849w/p4noXUrGpPUF0BPqIAfdAe76BLaRGAGKZ1gTDNiGxGcpsLcwJ9OTi1/V8A+AzvsmI9pkjie2zjIQZKA==", 3740 + "version": "3.10.0", 3741 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-3.10.0.tgz", 3742 + "integrity": "sha512-5amX8kEJI+nIGtuLVjYk59Y5utEJ3CHETFOPEE4cooIRLA4xM4iBsA6zFgu4ljcopeYwvBzFEWf5g2I6Yb9SkA==", 3716 3743 "license": "MIT", 3717 3744 "dependencies": { 3718 - "@docusaurus/core": "3.9.2", 3719 - "@docusaurus/mdx-loader": "3.9.2", 3720 - "@docusaurus/types": "3.9.2", 3721 - "@docusaurus/utils": "3.9.2", 3722 - "@docusaurus/utils-validation": "3.9.2", 3745 + "@docusaurus/core": "3.10.0", 3746 + "@docusaurus/mdx-loader": "3.10.0", 3747 + "@docusaurus/types": "3.10.0", 3748 + "@docusaurus/utils": "3.10.0", 3749 + "@docusaurus/utils-validation": "3.10.0", 3723 3750 "fs-extra": "^11.1.1", 3724 3751 "tslib": "^2.6.0", 3725 3752 "webpack": "^5.88.1" ··· 3733 3760 } 3734 3761 }, 3735 3762 "node_modules/@docusaurus/plugin-css-cascade-layers": { 3736 - "version": "3.9.2", 3737 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.9.2.tgz", 3738 - "integrity": "sha512-w1s3+Ss+eOQbscGM4cfIFBlVg/QKxyYgj26k5AnakuHkKxH6004ZtuLe5awMBotIYF2bbGDoDhpgQ4r/kcj4rQ==", 3763 + "version": "3.10.0", 3764 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-css-cascade-layers/-/plugin-css-cascade-layers-3.10.0.tgz", 3765 + "integrity": "sha512-6q1vtt5FJcg5osgkHeM1euErECNqEZ5Z1j69yiNx2luEBIso+nxCkS9nqj8w+MK5X7rvKEToGhFfOFWncs51pQ==", 3739 3766 "license": "MIT", 3740 3767 "dependencies": { 3741 - "@docusaurus/core": "3.9.2", 3742 - "@docusaurus/types": "3.9.2", 3743 - "@docusaurus/utils": "3.9.2", 3744 - "@docusaurus/utils-validation": "3.9.2", 3768 + "@docusaurus/core": "3.10.0", 3769 + "@docusaurus/types": "3.10.0", 3770 + "@docusaurus/utils": "3.10.0", 3771 + "@docusaurus/utils-validation": "3.10.0", 3745 3772 "tslib": "^2.6.0" 3746 3773 }, 3747 3774 "engines": { ··· 3749 3776 } 3750 3777 }, 3751 3778 "node_modules/@docusaurus/plugin-debug": { 3752 - "version": "3.9.2", 3753 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.9.2.tgz", 3754 - "integrity": "sha512-j7a5hWuAFxyQAkilZwhsQ/b3T7FfHZ+0dub6j/GxKNFJp2h9qk/P1Bp7vrGASnvA9KNQBBL1ZXTe7jlh4VdPdA==", 3779 + "version": "3.10.0", 3780 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-3.10.0.tgz", 3781 + "integrity": "sha512-XcljKN+G+nmmK69uQA1d9BlYU3ZftG3T3zpK8/7Hf/wrOlV7TA4Ampdrdwkg0jElKdKAoSnPhCO0/U3bQGsVQQ==", 3755 3782 "license": "MIT", 3756 3783 "dependencies": { 3757 - "@docusaurus/core": "3.9.2", 3758 - "@docusaurus/types": "3.9.2", 3759 - "@docusaurus/utils": "3.9.2", 3784 + "@docusaurus/core": "3.10.0", 3785 + "@docusaurus/types": "3.10.0", 3786 + "@docusaurus/utils": "3.10.0", 3760 3787 "fs-extra": "^11.1.1", 3761 3788 "react-json-view-lite": "^2.3.0", 3762 3789 "tslib": "^2.6.0" ··· 3770 3797 } 3771 3798 }, 3772 3799 "node_modules/@docusaurus/plugin-google-analytics": { 3773 - "version": "3.9.2", 3774 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.9.2.tgz", 3775 - "integrity": "sha512-mAwwQJ1Us9jL/lVjXtErXto4p4/iaLlweC54yDUK1a97WfkC6Z2k5/769JsFgwOwOP+n5mUQGACXOEQ0XDuVUw==", 3800 + "version": "3.10.0", 3801 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-3.10.0.tgz", 3802 + "integrity": "sha512-hTEoodatpBZnUat5nFExbuTGA1lhWGy7vZGuTew5Q3QDtGKFpSJLYmZJhdTjvCFwv1+qQ67hgAVlKdJOB8TXow==", 3776 3803 "license": "MIT", 3777 3804 "dependencies": { 3778 - "@docusaurus/core": "3.9.2", 3779 - "@docusaurus/types": "3.9.2", 3780 - "@docusaurus/utils-validation": "3.9.2", 3805 + "@docusaurus/core": "3.10.0", 3806 + "@docusaurus/types": "3.10.0", 3807 + "@docusaurus/utils-validation": "3.10.0", 3781 3808 "tslib": "^2.6.0" 3782 3809 }, 3783 3810 "engines": { ··· 3789 3816 } 3790 3817 }, 3791 3818 "node_modules/@docusaurus/plugin-google-gtag": { 3792 - "version": "3.9.2", 3793 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.9.2.tgz", 3794 - "integrity": "sha512-YJ4lDCphabBtw19ooSlc1MnxtYGpjFV9rEdzjLsUnBCeis2djUyCozZaFhCg6NGEwOn7HDDyMh0yzcdRpnuIvA==", 3819 + "version": "3.10.0", 3820 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-3.10.0.tgz", 3821 + "integrity": "sha512-iB/Zzjv/eelJRbdULZqzWCbgMgJ7ht4ONVjXtN3+BI/muil6S87gQ1OJyPwlXD+ELdKkitC7bWv5eJdYOZLhrQ==", 3795 3822 "license": "MIT", 3796 3823 "dependencies": { 3797 - "@docusaurus/core": "3.9.2", 3798 - "@docusaurus/types": "3.9.2", 3799 - "@docusaurus/utils-validation": "3.9.2", 3800 - "@types/gtag.js": "^0.0.12", 3824 + "@docusaurus/core": "3.10.0", 3825 + "@docusaurus/types": "3.10.0", 3826 + "@docusaurus/utils-validation": "3.10.0", 3827 + "@types/gtag.js": "^0.0.20", 3801 3828 "tslib": "^2.6.0" 3802 3829 }, 3803 3830 "engines": { ··· 3809 3836 } 3810 3837 }, 3811 3838 "node_modules/@docusaurus/plugin-google-tag-manager": { 3812 - "version": "3.9.2", 3813 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.9.2.tgz", 3814 - "integrity": "sha512-LJtIrkZN/tuHD8NqDAW1Tnw0ekOwRTfobWPsdO15YxcicBo2ykKF0/D6n0vVBfd3srwr9Z6rzrIWYrMzBGrvNw==", 3839 + "version": "3.10.0", 3840 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-3.10.0.tgz", 3841 + "integrity": "sha512-FEjZxqKgLHa+Wez/EgKxRwvArNCWIScfyEQD95rot7jkxp6nonjI5XIbGfO/iYhM5Qinwe8aIEQHP2KZtpqVuA==", 3815 3842 "license": "MIT", 3816 3843 "dependencies": { 3817 - "@docusaurus/core": "3.9.2", 3818 - "@docusaurus/types": "3.9.2", 3819 - "@docusaurus/utils-validation": "3.9.2", 3844 + "@docusaurus/core": "3.10.0", 3845 + "@docusaurus/types": "3.10.0", 3846 + "@docusaurus/utils-validation": "3.10.0", 3820 3847 "tslib": "^2.6.0" 3821 3848 }, 3822 3849 "engines": { ··· 3828 3855 } 3829 3856 }, 3830 3857 "node_modules/@docusaurus/plugin-sitemap": { 3831 - "version": "3.9.2", 3832 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.9.2.tgz", 3833 - "integrity": "sha512-WLh7ymgDXjG8oPoM/T4/zUP7KcSuFYRZAUTl8vR6VzYkfc18GBM4xLhcT+AKOwun6kBivYKUJf+vlqYJkm+RHw==", 3858 + "version": "3.10.0", 3859 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-3.10.0.tgz", 3860 + "integrity": "sha512-DVTSLjB97hIjmayGnGcBfognCeI7ZuUKgEnU7Oz81JYqXtVg94mVTthDjq3QHTylYNeCUbkaW8VF0FDLcc8pPw==", 3834 3861 "license": "MIT", 3835 3862 "dependencies": { 3836 - "@docusaurus/core": "3.9.2", 3837 - "@docusaurus/logger": "3.9.2", 3838 - "@docusaurus/types": "3.9.2", 3839 - "@docusaurus/utils": "3.9.2", 3840 - "@docusaurus/utils-common": "3.9.2", 3841 - "@docusaurus/utils-validation": "3.9.2", 3863 + "@docusaurus/core": "3.10.0", 3864 + "@docusaurus/logger": "3.10.0", 3865 + "@docusaurus/types": "3.10.0", 3866 + "@docusaurus/utils": "3.10.0", 3867 + "@docusaurus/utils-common": "3.10.0", 3868 + "@docusaurus/utils-validation": "3.10.0", 3842 3869 "fs-extra": "^11.1.1", 3843 3870 "sitemap": "^7.1.1", 3844 3871 "tslib": "^2.6.0" ··· 3852 3879 } 3853 3880 }, 3854 3881 "node_modules/@docusaurus/plugin-svgr": { 3855 - "version": "3.9.2", 3856 - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.9.2.tgz", 3857 - "integrity": "sha512-n+1DE+5b3Lnf27TgVU5jM1d4x5tUh2oW5LTsBxJX4PsAPV0JGcmI6p3yLYtEY0LRVEIJh+8RsdQmRE66wSV8mw==", 3882 + "version": "3.10.0", 3883 + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-svgr/-/plugin-svgr-3.10.0.tgz", 3884 + "integrity": "sha512-lNljBESaETZqVBMPqkrGchr+UPT1eZzEPLmJhz8I76BxbjqgsUnRvrq6lQJ9sYjgmgX52KB7kkgczqd2yzoswQ==", 3858 3885 "license": "MIT", 3859 3886 "dependencies": { 3860 - "@docusaurus/core": "3.9.2", 3861 - "@docusaurus/types": "3.9.2", 3862 - "@docusaurus/utils": "3.9.2", 3863 - "@docusaurus/utils-validation": "3.9.2", 3887 + "@docusaurus/core": "3.10.0", 3888 + "@docusaurus/types": "3.10.0", 3889 + "@docusaurus/utils": "3.10.0", 3890 + "@docusaurus/utils-validation": "3.10.0", 3864 3891 "@svgr/core": "8.1.0", 3865 3892 "@svgr/webpack": "^8.1.0", 3866 3893 "tslib": "^2.6.0", ··· 3875 3902 } 3876 3903 }, 3877 3904 "node_modules/@docusaurus/preset-classic": { 3878 - "version": "3.9.2", 3879 - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.9.2.tgz", 3880 - "integrity": "sha512-IgyYO2Gvaigi21LuDIe+nvmN/dfGXAiMcV/murFqcpjnZc7jxFAxW+9LEjdPt61uZLxG4ByW/oUmX/DDK9t/8w==", 3905 + "version": "3.10.0", 3906 + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-3.10.0.tgz", 3907 + "integrity": "sha512-kw/Ye02Hc6xP1OdTswy8yxQEHg0fdPpyWAQRxr5b2x3h7LlG2Zgbb5BDFROnXDDMpUxB7YejlocJIE5HIEfpNA==", 3881 3908 "license": "MIT", 3882 3909 "dependencies": { 3883 - "@docusaurus/core": "3.9.2", 3884 - "@docusaurus/plugin-content-blog": "3.9.2", 3885 - "@docusaurus/plugin-content-docs": "3.9.2", 3886 - "@docusaurus/plugin-content-pages": "3.9.2", 3887 - "@docusaurus/plugin-css-cascade-layers": "3.9.2", 3888 - "@docusaurus/plugin-debug": "3.9.2", 3889 - "@docusaurus/plugin-google-analytics": "3.9.2", 3890 - "@docusaurus/plugin-google-gtag": "3.9.2", 3891 - "@docusaurus/plugin-google-tag-manager": "3.9.2", 3892 - "@docusaurus/plugin-sitemap": "3.9.2", 3893 - "@docusaurus/plugin-svgr": "3.9.2", 3894 - "@docusaurus/theme-classic": "3.9.2", 3895 - "@docusaurus/theme-common": "3.9.2", 3896 - "@docusaurus/theme-search-algolia": "3.9.2", 3897 - "@docusaurus/types": "3.9.2" 3910 + "@docusaurus/core": "3.10.0", 3911 + "@docusaurus/plugin-content-blog": "3.10.0", 3912 + "@docusaurus/plugin-content-docs": "3.10.0", 3913 + "@docusaurus/plugin-content-pages": "3.10.0", 3914 + "@docusaurus/plugin-css-cascade-layers": "3.10.0", 3915 + "@docusaurus/plugin-debug": "3.10.0", 3916 + "@docusaurus/plugin-google-analytics": "3.10.0", 3917 + "@docusaurus/plugin-google-gtag": "3.10.0", 3918 + "@docusaurus/plugin-google-tag-manager": "3.10.0", 3919 + "@docusaurus/plugin-sitemap": "3.10.0", 3920 + "@docusaurus/plugin-svgr": "3.10.0", 3921 + "@docusaurus/theme-classic": "3.10.0", 3922 + "@docusaurus/theme-common": "3.10.0", 3923 + "@docusaurus/theme-search-algolia": "3.10.0", 3924 + "@docusaurus/types": "3.10.0" 3898 3925 }, 3899 3926 "engines": { 3900 3927 "node": ">=20.0" ··· 3905 3932 } 3906 3933 }, 3907 3934 "node_modules/@docusaurus/theme-classic": { 3908 - "version": "3.9.2", 3909 - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.9.2.tgz", 3910 - "integrity": "sha512-IGUsArG5hhekXd7RDb11v94ycpJpFdJPkLnt10fFQWOVxAtq5/D7hT6lzc2fhyQKaaCE62qVajOMKL7OiAFAIA==", 3935 + "version": "3.10.0", 3936 + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-3.10.0.tgz", 3937 + "integrity": "sha512-9msCAsRdN+UG+RwPwCFb0uKy4tGoPh5YfBozXeGUtIeAgsMdn6f3G/oY861luZ3t8S2ET8S9Y/1GnpJAGWytww==", 3911 3938 "license": "MIT", 3912 3939 "dependencies": { 3913 - "@docusaurus/core": "3.9.2", 3914 - "@docusaurus/logger": "3.9.2", 3915 - "@docusaurus/mdx-loader": "3.9.2", 3916 - "@docusaurus/module-type-aliases": "3.9.2", 3917 - "@docusaurus/plugin-content-blog": "3.9.2", 3918 - "@docusaurus/plugin-content-docs": "3.9.2", 3919 - "@docusaurus/plugin-content-pages": "3.9.2", 3920 - "@docusaurus/theme-common": "3.9.2", 3921 - "@docusaurus/theme-translations": "3.9.2", 3922 - "@docusaurus/types": "3.9.2", 3923 - "@docusaurus/utils": "3.9.2", 3924 - "@docusaurus/utils-common": "3.9.2", 3925 - "@docusaurus/utils-validation": "3.9.2", 3940 + "@docusaurus/core": "3.10.0", 3941 + "@docusaurus/logger": "3.10.0", 3942 + "@docusaurus/mdx-loader": "3.10.0", 3943 + "@docusaurus/module-type-aliases": "3.10.0", 3944 + "@docusaurus/plugin-content-blog": "3.10.0", 3945 + "@docusaurus/plugin-content-docs": "3.10.0", 3946 + "@docusaurus/plugin-content-pages": "3.10.0", 3947 + "@docusaurus/theme-common": "3.10.0", 3948 + "@docusaurus/theme-translations": "3.10.0", 3949 + "@docusaurus/types": "3.10.0", 3950 + "@docusaurus/utils": "3.10.0", 3951 + "@docusaurus/utils-common": "3.10.0", 3952 + "@docusaurus/utils-validation": "3.10.0", 3926 3953 "@mdx-js/react": "^3.0.0", 3927 3954 "clsx": "^2.0.0", 3955 + "copy-text-to-clipboard": "^3.2.0", 3928 3956 "infima": "0.2.0-alpha.45", 3929 3957 "lodash": "^4.17.21", 3930 3958 "nprogress": "^0.2.0", ··· 3945 3973 } 3946 3974 }, 3947 3975 "node_modules/@docusaurus/theme-common": { 3948 - "version": "3.9.2", 3949 - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.9.2.tgz", 3950 - "integrity": "sha512-6c4DAbR6n6nPbnZhY2V3tzpnKnGL+6aOsLvFL26VRqhlczli9eWG0VDUNoCQEPnGwDMhPS42UhSAnz5pThm5Ag==", 3976 + "version": "3.10.0", 3977 + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-3.10.0.tgz", 3978 + "integrity": "sha512-Dkp1YXKn16ByCJAdIjbDIOpVb4Z66MsVD694/ilX1vAAHaVEMrVsf/NPd9VgreyFx08rJ9GqV1MtzsbTcU73Kg==", 3951 3979 "license": "MIT", 3952 3980 "dependencies": { 3953 - "@docusaurus/mdx-loader": "3.9.2", 3954 - "@docusaurus/module-type-aliases": "3.9.2", 3955 - "@docusaurus/utils": "3.9.2", 3956 - "@docusaurus/utils-common": "3.9.2", 3981 + "@docusaurus/mdx-loader": "3.10.0", 3982 + "@docusaurus/module-type-aliases": "3.10.0", 3983 + "@docusaurus/utils": "3.10.0", 3984 + "@docusaurus/utils-common": "3.10.0", 3957 3985 "@types/history": "^4.7.11", 3958 3986 "@types/react": "*", 3959 3987 "@types/react-router-config": "*", ··· 3973 4001 } 3974 4002 }, 3975 4003 "node_modules/@docusaurus/theme-mermaid": { 3976 - "version": "3.9.2", 3977 - "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.9.2.tgz", 3978 - "integrity": "sha512-5vhShRDq/ntLzdInsQkTdoKWSzw8d1jB17sNPYhA/KvYYFXfuVEGHLM6nrf8MFbV8TruAHDG21Fn3W4lO8GaDw==", 4004 + "version": "3.10.0", 4005 + "resolved": "https://registry.npmjs.org/@docusaurus/theme-mermaid/-/theme-mermaid-3.10.0.tgz", 4006 + "integrity": "sha512-Y2xrlwhIJ80oOZIO3PXL6A7J869splfcMI87E3NKpYsy3zJxOyV+BP1QMtGi59ajKgU868HPuyyn6J+6BZGOBg==", 3979 4007 "license": "MIT", 3980 4008 "dependencies": { 3981 - "@docusaurus/core": "3.9.2", 3982 - "@docusaurus/module-type-aliases": "3.9.2", 3983 - "@docusaurus/theme-common": "3.9.2", 3984 - "@docusaurus/types": "3.9.2", 3985 - "@docusaurus/utils-validation": "3.9.2", 4009 + "@docusaurus/core": "3.10.0", 4010 + "@docusaurus/module-type-aliases": "3.10.0", 4011 + "@docusaurus/theme-common": "3.10.0", 4012 + "@docusaurus/types": "3.10.0", 4013 + "@docusaurus/utils-validation": "3.10.0", 3986 4014 "mermaid": ">=11.6.0", 3987 4015 "tslib": "^2.6.0" 3988 4016 }, ··· 4001 4029 } 4002 4030 }, 4003 4031 "node_modules/@docusaurus/theme-search-algolia": { 4004 - "version": "3.9.2", 4005 - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.9.2.tgz", 4006 - "integrity": "sha512-GBDSFNwjnh5/LdkxCKQHkgO2pIMX1447BxYUBG2wBiajS21uj64a+gH/qlbQjDLxmGrbrllBrtJkUHxIsiwRnw==", 4032 + "version": "3.10.0", 4033 + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-3.10.0.tgz", 4034 + "integrity": "sha512-f5FPKI08e3JRG63vR/o4qeuUVHUHzFzM0nnF+AkB67soAZgNsKJRf2qmUZvlQkGwlV+QFkKe4D0ANMh1jToU3g==", 4007 4035 "license": "MIT", 4008 4036 "dependencies": { 4009 - "@docsearch/react": "^3.9.0 || ^4.1.0", 4010 - "@docusaurus/core": "3.9.2", 4011 - "@docusaurus/logger": "3.9.2", 4012 - "@docusaurus/plugin-content-docs": "3.9.2", 4013 - "@docusaurus/theme-common": "3.9.2", 4014 - "@docusaurus/theme-translations": "3.9.2", 4015 - "@docusaurus/utils": "3.9.2", 4016 - "@docusaurus/utils-validation": "3.9.2", 4037 + "@algolia/autocomplete-core": "^1.19.2", 4038 + "@docsearch/react": "^3.9.0 || ^4.3.2", 4039 + "@docusaurus/core": "3.10.0", 4040 + "@docusaurus/logger": "3.10.0", 4041 + "@docusaurus/plugin-content-docs": "3.10.0", 4042 + "@docusaurus/theme-common": "3.10.0", 4043 + "@docusaurus/theme-translations": "3.10.0", 4044 + "@docusaurus/utils": "3.10.0", 4045 + "@docusaurus/utils-validation": "3.10.0", 4017 4046 "algoliasearch": "^5.37.0", 4018 4047 "algoliasearch-helper": "^3.26.0", 4019 4048 "clsx": "^2.0.0", ··· 4032 4061 } 4033 4062 }, 4034 4063 "node_modules/@docusaurus/theme-translations": { 4035 - "version": "3.9.2", 4036 - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.9.2.tgz", 4037 - "integrity": "sha512-vIryvpP18ON9T9rjgMRFLr2xJVDpw1rtagEGf8Ccce4CkTrvM/fRB8N2nyWYOW5u3DdjkwKw5fBa+3tbn9P4PA==", 4064 + "version": "3.10.0", 4065 + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-3.10.0.tgz", 4066 + "integrity": "sha512-L9IbFLwTc5+XdgH45iQYufLn0SVZd6BUNelDbKIFlH+E4hhjuj/XHWAFMX/w2K59rfy8wak9McOaei7BSUfRPA==", 4038 4067 "license": "MIT", 4039 4068 "dependencies": { 4040 4069 "fs-extra": "^11.1.1", ··· 4045 4074 } 4046 4075 }, 4047 4076 "node_modules/@docusaurus/tsconfig": { 4048 - "version": "3.9.2", 4049 - "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.9.2.tgz", 4050 - "integrity": "sha512-j6/Fp4Rlpxsc632cnRnl5HpOWeb6ZKssDj6/XzzAzVGXXfm9Eptx3rxCC+fDzySn9fHTS+CWJjPineCR1bB5WQ==", 4077 + "version": "3.10.0", 4078 + "resolved": "https://registry.npmjs.org/@docusaurus/tsconfig/-/tsconfig-3.10.0.tgz", 4079 + "integrity": "sha512-TXdC3WXuPrdQAexLvjUJfnYf3YKEgEqAs5nK0Q88pRBCW7t7oN4ILvWYb3A5Z1wlSXyXGWW/mCUmLEhdWsjnDQ==", 4051 4080 "dev": true, 4052 4081 "license": "MIT" 4053 4082 }, 4054 4083 "node_modules/@docusaurus/types": { 4055 - "version": "3.9.2", 4056 - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.9.2.tgz", 4057 - "integrity": "sha512-Ux1JUNswg+EfUEmajJjyhIohKceitY/yzjRUpu04WXgvVz+fbhVC0p+R0JhvEu4ytw8zIAys2hrdpQPBHRIa8Q==", 4084 + "version": "3.10.0", 4085 + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-3.10.0.tgz", 4086 + "integrity": "sha512-F0dOt3FOoO20rRaFK7whGFQZ3ggyrWEdQc/c8/UiRuzhtg4y1w9FspXH5zpCT07uMnJKBPGh+qNazbNlCQqvSw==", 4058 4087 "license": "MIT", 4059 4088 "dependencies": { 4060 4089 "@mdx-js/mdx": "^3.0.0", ··· 4088 4117 } 4089 4118 }, 4090 4119 "node_modules/@docusaurus/utils": { 4091 - "version": "3.9.2", 4092 - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.9.2.tgz", 4093 - "integrity": "sha512-lBSBiRruFurFKXr5Hbsl2thmGweAPmddhF3jb99U4EMDA5L+e5Y1rAkOS07Nvrup7HUMBDrCV45meaxZnt28nQ==", 4120 + "version": "3.10.0", 4121 + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-3.10.0.tgz", 4122 + "integrity": "sha512-T3B0WTigsIthe0D4LQa2k+7bJY+c3WS+Wq2JhcznOSpn1lSN64yNtHQXboCj3QnUs1EuAZszQG1SHKu5w5ZrlA==", 4094 4123 "license": "MIT", 4095 4124 "dependencies": { 4096 - "@docusaurus/logger": "3.9.2", 4097 - "@docusaurus/types": "3.9.2", 4098 - "@docusaurus/utils-common": "3.9.2", 4125 + "@docusaurus/logger": "3.10.0", 4126 + "@docusaurus/types": "3.10.0", 4127 + "@docusaurus/utils-common": "3.10.0", 4099 4128 "escape-string-regexp": "^4.0.0", 4100 - "execa": "5.1.1", 4129 + "execa": "^5.1.1", 4101 4130 "file-loader": "^6.2.0", 4102 4131 "fs-extra": "^11.1.1", 4103 4132 "github-slugger": "^1.5.0", ··· 4120 4149 } 4121 4150 }, 4122 4151 "node_modules/@docusaurus/utils-common": { 4123 - "version": "3.9.2", 4124 - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.9.2.tgz", 4125 - "integrity": "sha512-I53UC1QctruA6SWLvbjbhCpAw7+X7PePoe5pYcwTOEXD/PxeP8LnECAhTHHwWCblyUX5bMi4QLRkxvyZ+IT8Aw==", 4152 + "version": "3.10.0", 4153 + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-3.10.0.tgz", 4154 + "integrity": "sha512-JyL7sb9QVDgYvudIS81Dv0lsWm7le0vGZSDwsztxWam1SPBqrnkvBy9UYL/amh6pbybkyYTd3CMTkO24oMlCSw==", 4126 4155 "license": "MIT", 4127 4156 "dependencies": { 4128 - "@docusaurus/types": "3.9.2", 4157 + "@docusaurus/types": "3.10.0", 4129 4158 "tslib": "^2.6.0" 4130 4159 }, 4131 4160 "engines": { ··· 4133 4162 } 4134 4163 }, 4135 4164 "node_modules/@docusaurus/utils-validation": { 4136 - "version": "3.9.2", 4137 - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.9.2.tgz", 4138 - "integrity": "sha512-l7yk3X5VnNmATbwijJkexdhulNsQaNDwoagiwujXoxFbWLcxHQqNQ+c/IAlzrfMMOfa/8xSBZ7KEKDesE/2J7A==", 4165 + "version": "3.10.0", 4166 + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-3.10.0.tgz", 4167 + "integrity": "sha512-c+6n2+ZPOJtWWc8Bb/EYdpSDfjYEScdCu9fB/SNjOmSCf1IdVnGf2T53o0tsz0gDRtCL90tifTL0JE/oMuP1Mw==", 4139 4168 "license": "MIT", 4140 4169 "dependencies": { 4141 - "@docusaurus/logger": "3.9.2", 4142 - "@docusaurus/utils": "3.9.2", 4143 - "@docusaurus/utils-common": "3.9.2", 4170 + "@docusaurus/logger": "3.10.0", 4171 + "@docusaurus/utils": "3.10.0", 4172 + "@docusaurus/utils-common": "3.10.0", 4144 4173 "fs-extra": "^11.2.0", 4145 4174 "joi": "^17.9.2", 4146 4175 "js-yaml": "^4.1.0", ··· 4737 4766 "react": ">=16" 4738 4767 } 4739 4768 }, 4769 + "node_modules/@mermaid-js/layout-elk": { 4770 + "version": "0.1.9", 4771 + "resolved": "https://registry.npmjs.org/@mermaid-js/layout-elk/-/layout-elk-0.1.9.tgz", 4772 + "integrity": "sha512-HuvaqFZBr6yT9PpWYockvKAZPJVd89yn/UjOYPxhzbZxlybL2v+2BjVCg7MVH6vRs1irUohb/s42HEdec1CCZw==", 4773 + "license": "MIT", 4774 + "peer": true, 4775 + "dependencies": { 4776 + "d3": "^7.9.0", 4777 + "elkjs": "^0.9.3" 4778 + }, 4779 + "peerDependencies": { 4780 + "mermaid": "^11.0.2" 4781 + } 4782 + }, 4740 4783 "node_modules/@mermaid-js/parser": { 4741 4784 "version": "1.0.0", 4742 4785 "resolved": "https://registry.npmjs.org/@mermaid-js/parser/-/parser-1.0.0.tgz", ··· 5333 5376 "node": ">=4" 5334 5377 } 5335 5378 }, 5336 - "node_modules/@trysound/sax": { 5337 - "version": "0.2.0", 5338 - "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", 5339 - "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", 5340 - "license": "ISC", 5341 - "engines": { 5342 - "node": ">=10.13.0" 5343 - } 5344 - }, 5345 5379 "node_modules/@types/body-parser": { 5346 5380 "version": "1.19.6", 5347 5381 "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz", ··· 5634 5668 } 5635 5669 }, 5636 5670 "node_modules/@types/debug": { 5637 - "version": "4.1.12", 5638 - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", 5639 - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", 5671 + "version": "4.1.13", 5672 + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", 5673 + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", 5640 5674 "license": "MIT", 5641 5675 "dependencies": { 5642 5676 "@types/ms": "*" ··· 5708 5742 "license": "MIT" 5709 5743 }, 5710 5744 "node_modules/@types/gtag.js": { 5711 - "version": "0.0.12", 5712 - "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.12.tgz", 5713 - "integrity": "sha512-YQV9bUsemkzG81Ea295/nF/5GijnD2Af7QhEofh7xu+kvCN6RdodgNwwGWXB5GMI3NoyvQo0odNctoH/qLMIpg==", 5745 + "version": "0.0.20", 5746 + "resolved": "https://registry.npmjs.org/@types/gtag.js/-/gtag.js-0.0.20.tgz", 5747 + "integrity": "sha512-wwAbk3SA2QeU67unN7zPxjEHmPmlXwZXZvQEpbEUQuMCRGgKyE1m6XDuTUA9b6pCGb/GqJmdfMOY5LuDjJSbbg==", 5714 5748 "license": "MIT" 5715 5749 }, 5716 5750 "node_modules/@types/hast": { ··· 6303 6337 } 6304 6338 }, 6305 6339 "node_modules/algoliasearch": { 6306 - "version": "5.48.2", 6307 - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.48.2.tgz", 6308 - "integrity": "sha512-U5U2dCy+ei/elHp7jMdYOPWBO0sjiUEyIW0PEblm4cL8GvDNiyiOlhZmKgwWbyPPj0w0s6HXeMZBAofTdVWgIQ==", 6340 + "version": "5.50.2", 6341 + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.50.2.tgz", 6342 + "integrity": "sha512-Tfp26yoNWurUjfgK4GOrVJQhSNXu9tJtHfFFNosgT2YClG+vPyUjX/gbC8rG39qLncnZg8Fj34iarQWpMkqefw==", 6309 6343 "license": "MIT", 6310 6344 "peer": true, 6311 6345 "dependencies": { 6312 - "@algolia/abtesting": "1.14.2", 6313 - "@algolia/client-abtesting": "5.48.2", 6314 - "@algolia/client-analytics": "5.48.2", 6315 - "@algolia/client-common": "5.48.2", 6316 - "@algolia/client-insights": "5.48.2", 6317 - "@algolia/client-personalization": "5.48.2", 6318 - "@algolia/client-query-suggestions": "5.48.2", 6319 - "@algolia/client-search": "5.48.2", 6320 - "@algolia/ingestion": "1.48.2", 6321 - "@algolia/monitoring": "1.48.2", 6322 - "@algolia/recommend": "5.48.2", 6323 - "@algolia/requester-browser-xhr": "5.48.2", 6324 - "@algolia/requester-fetch": "5.48.2", 6325 - "@algolia/requester-node-http": "5.48.2" 6346 + "@algolia/abtesting": "1.16.2", 6347 + "@algolia/client-abtesting": "5.50.2", 6348 + "@algolia/client-analytics": "5.50.2", 6349 + "@algolia/client-common": "5.50.2", 6350 + "@algolia/client-insights": "5.50.2", 6351 + "@algolia/client-personalization": "5.50.2", 6352 + "@algolia/client-query-suggestions": "5.50.2", 6353 + "@algolia/client-search": "5.50.2", 6354 + "@algolia/ingestion": "1.50.2", 6355 + "@algolia/monitoring": "1.50.2", 6356 + "@algolia/recommend": "5.50.2", 6357 + "@algolia/requester-browser-xhr": "5.50.2", 6358 + "@algolia/requester-fetch": "5.50.2", 6359 + "@algolia/requester-node-http": "5.50.2" 6326 6360 }, 6327 6361 "engines": { 6328 6362 "node": ">= 14.0.0" 6329 6363 } 6330 6364 }, 6331 6365 "node_modules/algoliasearch-helper": { 6332 - "version": "3.27.1", 6333 - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.27.1.tgz", 6334 - "integrity": "sha512-XXGr02Cz285vLbqM6vPfb39xqV1ptpFr1xn9mqaW+nUvYTvFTdKgYTC/Cg1VzgRTQqNkq9+LlUVv8cfCeOoKig==", 6366 + "version": "3.28.1", 6367 + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.28.1.tgz", 6368 + "integrity": "sha512-6iXpbkkrAI5HFpCWXlNmIDSBuoN/U1XnEvb2yJAoWfqrZ+DrybI7MQ5P5mthFaprmocq+zbi6HxnR28xnZAYBw==", 6335 6369 "license": "MIT", 6336 6370 "dependencies": { 6337 6371 "@algolia/events": "^4.0.1" ··· 6496 6530 } 6497 6531 }, 6498 6532 "node_modules/autoprefixer": { 6499 - "version": "10.4.24", 6500 - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.24.tgz", 6501 - "integrity": "sha512-uHZg7N9ULTVbutaIsDRoUkoS8/h3bdsmVJYZ5l3wv8Cp/6UIIoRDm90hZ+BwxUj/hGBEzLxdHNSKuFpn8WOyZw==", 6533 + "version": "10.5.0", 6534 + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", 6535 + "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", 6502 6536 "funding": [ 6503 6537 { 6504 6538 "type": "opencollective", ··· 6515 6549 ], 6516 6550 "license": "MIT", 6517 6551 "dependencies": { 6518 - "browserslist": "^4.28.1", 6519 - "caniuse-lite": "^1.0.30001766", 6552 + "browserslist": "^4.28.2", 6553 + "caniuse-lite": "^1.0.30001787", 6520 6554 "fraction.js": "^5.3.4", 6521 6555 "picocolors": "^1.1.1", 6522 6556 "postcss-value-parser": "^4.2.0" ··· 6558 6592 } 6559 6593 }, 6560 6594 "node_modules/babel-plugin-polyfill-corejs2": { 6561 - "version": "0.4.15", 6562 - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.15.tgz", 6563 - "integrity": "sha512-hR3GwrRwHUfYwGfrisXPIDP3JcYfBrW7wKE7+Au6wDYl7fm/ka1NEII6kORzxNU556JjfidZeBsO10kYvtV1aw==", 6595 + "version": "0.4.17", 6596 + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", 6597 + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", 6564 6598 "license": "MIT", 6565 6599 "dependencies": { 6566 6600 "@babel/compat-data": "^7.28.6", 6567 - "@babel/helper-define-polyfill-provider": "^0.6.6", 6601 + "@babel/helper-define-polyfill-provider": "^0.6.8", 6568 6602 "semver": "^6.3.1" 6569 6603 }, 6570 6604 "peerDependencies": { ··· 6594 6628 } 6595 6629 }, 6596 6630 "node_modules/babel-plugin-polyfill-regenerator": { 6597 - "version": "0.6.6", 6598 - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.6.tgz", 6599 - "integrity": "sha512-hYm+XLYRMvupxiQzrvXUj7YyvFFVfv5gI0R71AJzudg1g2AI2vyCPPIFEBjk162/wFzti3inBHo7isWFuEVS/A==", 6631 + "version": "0.6.8", 6632 + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", 6633 + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", 6600 6634 "license": "MIT", 6601 6635 "dependencies": { 6602 - "@babel/helper-define-polyfill-provider": "^0.6.6" 6636 + "@babel/helper-define-polyfill-provider": "^0.6.8" 6603 6637 }, 6604 6638 "peerDependencies": { 6605 6639 "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" ··· 6622 6656 "license": "MIT" 6623 6657 }, 6624 6658 "node_modules/baseline-browser-mapping": { 6625 - "version": "2.9.19", 6626 - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", 6627 - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", 6659 + "version": "2.10.19", 6660 + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.19.tgz", 6661 + "integrity": "sha512-qCkNLi2sfBOn8XhZQ0FXsT1Ki/Yo5P90hrkRamVFRS7/KV9hpfA4HkoWNU152+8w0zPjnxo5psx5NL3PSGgv5g==", 6628 6662 "license": "Apache-2.0", 6629 6663 "bin": { 6630 - "baseline-browser-mapping": "dist/cli.js" 6664 + "baseline-browser-mapping": "dist/cli.cjs" 6665 + }, 6666 + "engines": { 6667 + "node": ">=6.0.0" 6631 6668 } 6632 6669 }, 6633 6670 "node_modules/batch": { ··· 6744 6781 } 6745 6782 }, 6746 6783 "node_modules/brace-expansion": { 6747 - "version": "1.1.12", 6748 - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", 6749 - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", 6784 + "version": "1.1.14", 6785 + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", 6786 + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", 6750 6787 "license": "MIT", 6751 6788 "dependencies": { 6752 6789 "balanced-match": "^1.0.0", ··· 6766 6803 } 6767 6804 }, 6768 6805 "node_modules/browserslist": { 6769 - "version": "4.28.1", 6770 - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", 6771 - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", 6806 + "version": "4.28.2", 6807 + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", 6808 + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", 6772 6809 "funding": [ 6773 6810 { 6774 6811 "type": "opencollective", ··· 6786 6823 "license": "MIT", 6787 6824 "peer": true, 6788 6825 "dependencies": { 6789 - "baseline-browser-mapping": "^2.9.0", 6790 - "caniuse-lite": "^1.0.30001759", 6791 - "electron-to-chromium": "^1.5.263", 6792 - "node-releases": "^2.0.27", 6793 - "update-browserslist-db": "^1.2.0" 6826 + "baseline-browser-mapping": "^2.10.12", 6827 + "caniuse-lite": "^1.0.30001782", 6828 + "electron-to-chromium": "^1.5.328", 6829 + "node-releases": "^2.0.36", 6830 + "update-browserslist-db": "^1.2.3" 6794 6831 }, 6795 6832 "bin": { 6796 6833 "browserslist": "cli.js" ··· 6866 6903 } 6867 6904 }, 6868 6905 "node_modules/call-bind": { 6869 - "version": "1.0.8", 6870 - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", 6871 - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", 6906 + "version": "1.0.9", 6907 + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", 6908 + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", 6872 6909 "license": "MIT", 6873 6910 "dependencies": { 6874 - "call-bind-apply-helpers": "^1.0.0", 6875 - "es-define-property": "^1.0.0", 6876 - "get-intrinsic": "^1.2.4", 6911 + "call-bind-apply-helpers": "^1.0.2", 6912 + "es-define-property": "^1.0.1", 6913 + "get-intrinsic": "^1.3.0", 6877 6914 "set-function-length": "^1.2.2" 6878 6915 }, 6879 6916 "engines": { ··· 6956 6993 } 6957 6994 }, 6958 6995 "node_modules/caniuse-lite": { 6959 - "version": "1.0.30001770", 6960 - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", 6961 - "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", 6996 + "version": "1.0.30001788", 6997 + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001788.tgz", 6998 + "integrity": "sha512-6q8HFp+lOQtcf7wBK+uEenxymVWkGKkjFpCvw5W25cmMwEDU45p1xQFBQv8JDlMMry7eNxyBaR+qxgmTUZkIRQ==", 6962 6999 "funding": [ 6963 7000 { 6964 7001 "type": "opencollective", ··· 7504 7541 "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==", 7505 7542 "license": "MIT" 7506 7543 }, 7544 + "node_modules/copy-text-to-clipboard": { 7545 + "version": "3.2.2", 7546 + "resolved": "https://registry.npmjs.org/copy-text-to-clipboard/-/copy-text-to-clipboard-3.2.2.tgz", 7547 + "integrity": "sha512-T6SqyLd1iLuqPA90J5N4cTalrtovCySh58iiZDGJ6FGznbclKh4UI+FGacQSgFzwKG77W7XT5gwbVEbd9cIH1A==", 7548 + "license": "MIT", 7549 + "engines": { 7550 + "node": ">=12" 7551 + }, 7552 + "funding": { 7553 + "url": "https://github.com/sponsors/sindresorhus" 7554 + } 7555 + }, 7507 7556 "node_modules/copy-webpack-plugin": { 7508 7557 "version": "11.0.0", 7509 7558 "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz", ··· 7583 7632 } 7584 7633 }, 7585 7634 "node_modules/core-js-compat": { 7586 - "version": "3.48.0", 7587 - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.48.0.tgz", 7588 - "integrity": "sha512-OM4cAF3D6VtH/WkLtWvyNC56EZVXsZdU3iqaMG2B4WvYrlqU831pc4UtG5yp0sE9z8Y02wVN7PjW5Zf9Gt0f1Q==", 7635 + "version": "3.49.0", 7636 + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz", 7637 + "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==", 7589 7638 "license": "MIT", 7590 7639 "dependencies": { 7591 7640 "browserslist": "^4.28.1" ··· 7595 7644 "url": "https://opencollective.com/core-js" 7596 7645 } 7597 7646 }, 7598 - "node_modules/core-js-pure": { 7599 - "version": "3.48.0", 7600 - "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.48.0.tgz", 7601 - "integrity": "sha512-1slJgk89tWC51HQ1AEqG+s2VuwpTRr8ocu4n20QUcH1v9lAN0RXen0Q0AABa/DK1I7RrNWLucplOHMx8hfTGTw==", 7602 - "hasInstallScript": true, 7603 - "license": "MIT", 7604 - "funding": { 7605 - "type": "opencollective", 7606 - "url": "https://opencollective.com/core-js" 7607 - } 7608 - }, 7609 7647 "node_modules/core-util-is": { 7610 7648 "version": "1.0.3", 7611 7649 "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", ··· 7727 7765 } 7728 7766 }, 7729 7767 "node_modules/css-declaration-sorter": { 7730 - "version": "7.3.1", 7731 - "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.3.1.tgz", 7732 - "integrity": "sha512-gz6x+KkgNCjxq3Var03pRYLhyNfwhkKF1g/yoLgDNtFvVu0/fOLV9C8fFEZRjACp/XQLumjAYo7JVjzH3wLbxA==", 7768 + "version": "7.4.0", 7769 + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-7.4.0.tgz", 7770 + "integrity": "sha512-LTuzjPoyA2vMGKKcaOqKSp7Ub2eGrNfKiZH4LpezxpNrsICGCSFvsQOI29psISxNZtaXibkC2CXzrQ5enMeGGw==", 7733 7771 "license": "ISC", 7734 7772 "engines": { 7735 7773 "node": "^14 || ^16 || >=18" ··· 7944 7982 } 7945 7983 }, 7946 7984 "node_modules/cssdb": { 7947 - "version": "8.7.1", 7948 - "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.7.1.tgz", 7949 - "integrity": "sha512-+F6LKx48RrdGOtE4DT5jz7Uo+VeyKXpK797FAevIkzjV8bMHz6xTO5F7gNDcRCHmPgD5jj2g6QCsY9zmVrh38A==", 7985 + "version": "8.8.0", 7986 + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-8.8.0.tgz", 7987 + "integrity": "sha512-QbLeyz2Bgso1iRlh7IpWk6OKa3lLNGXsujVjDMPl9rOZpxKeiG69icLpbLCFxeURwmcdIfZqQyhlooKJYM4f8Q==", 7950 7988 "funding": [ 7951 7989 { 7952 7990 "type": "opencollective", ··· 9033 9071 "license": "MIT" 9034 9072 }, 9035 9073 "node_modules/electron-to-chromium": { 9036 - "version": "1.5.286", 9037 - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", 9038 - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", 9074 + "version": "1.5.336", 9075 + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.336.tgz", 9076 + "integrity": "sha512-AbH9q9J455r/nLmdNZes0G0ZKcRX73FicwowalLs6ijwOmCJSRRrLX63lcAlzy9ux3dWK1w1+1nsBJEWN11hcQ==", 9039 9077 "license": "ISC" 9078 + }, 9079 + "node_modules/elkjs": { 9080 + "version": "0.9.3", 9081 + "resolved": "https://registry.npmjs.org/elkjs/-/elkjs-0.9.3.tgz", 9082 + "integrity": "sha512-f/ZeWvW/BCXbhGEf1Ujp29EASo/lk1FDnETgNKwJrsVvGZhUWCZyg3xLJjAsxfOmt8KjswHmI5EwCQcPMpOYhQ==", 9083 + "license": "EPL-2.0" 9040 9084 }, 9041 9085 "node_modules/emoji-regex": { 9042 9086 "version": "9.2.2", ··· 9699 9743 } 9700 9744 }, 9701 9745 "node_modules/file-loader/node_modules/ajv": { 9702 - "version": "6.12.6", 9703 - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 9704 - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 9746 + "version": "6.14.0", 9747 + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", 9748 + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", 9705 9749 "license": "MIT", 9706 9750 "peer": true, 9707 9751 "dependencies": { ··· 11725 11769 } 11726 11770 }, 11727 11771 "node_modules/mdast-util-from-markdown": { 11728 - "version": "2.0.2", 11729 - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", 11730 - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", 11772 + "version": "2.0.3", 11773 + "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.3.tgz", 11774 + "integrity": "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q==", 11731 11775 "license": "MIT", 11732 11776 "dependencies": { 11733 11777 "@types/mdast": "^4.0.0", ··· 14047 14091 } 14048 14092 }, 14049 14093 "node_modules/mini-css-extract-plugin": { 14050 - "version": "2.10.0", 14051 - "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.0.tgz", 14052 - "integrity": "sha512-540P2c5dYnJlyJxTaSloliZexv8rji6rY8FhQN+WF/82iHQfA23j/xtJx97L+mXOML27EqksSek/g4eK7jaL3g==", 14094 + "version": "2.10.2", 14095 + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz", 14096 + "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==", 14053 14097 "license": "MIT", 14054 14098 "dependencies": { 14055 14099 "schema-utils": "^4.0.0", ··· 14073 14117 "license": "ISC" 14074 14118 }, 14075 14119 "node_modules/minimatch": { 14076 - "version": "3.1.2", 14077 - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 14078 - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 14120 + "version": "3.1.5", 14121 + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", 14122 + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", 14079 14123 "license": "ISC", 14080 14124 "dependencies": { 14081 14125 "brace-expansion": "^1.1.7" ··· 14192 14236 } 14193 14237 }, 14194 14238 "node_modules/node-releases": { 14195 - "version": "2.0.27", 14196 - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", 14197 - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", 14239 + "version": "2.0.37", 14240 + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.37.tgz", 14241 + "integrity": "sha512-1h5gKZCF+pO/o3Iqt5Jp7wc9rH3eJJ0+nh/CIoiRwjRxde/hAHyLPXYN4V3CqKAbiZPSeJFSWHmJsbkicta0Eg==", 14198 14242 "license": "MIT" 14199 14243 }, 14200 14244 "node_modules/normalize-path": { ··· 14269 14313 } 14270 14314 }, 14271 14315 "node_modules/null-loader/node_modules/ajv": { 14272 - "version": "6.12.6", 14273 - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 14274 - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 14316 + "version": "6.14.0", 14317 + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", 14318 + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", 14275 14319 "license": "MIT", 14276 14320 "peer": true, 14277 14321 "dependencies": { ··· 14833 14877 } 14834 14878 }, 14835 14879 "node_modules/postcss": { 14836 - "version": "8.5.6", 14837 - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", 14838 - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", 14880 + "version": "8.5.9", 14881 + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.9.tgz", 14882 + "integrity": "sha512-7a70Nsot+EMX9fFU3064K/kdHWZqGVY+BADLyXc8Dfv+mTLLVl6JzJpPaCZ2kQL9gIJvKXSLMHhqdRRjwQeFtw==", 14839 14883 "funding": [ 14840 14884 { 14841 14885 "type": "opencollective", ··· 16647 16691 } 16648 16692 }, 16649 16693 "node_modules/react-loadable-ssr-addon-v5-slorber": { 16650 - "version": "1.0.1", 16651 - "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.1.tgz", 16652 - "integrity": "sha512-lq3Lyw1lGku8zUEJPDxsNm1AfYHBrO9Y1+olAYwpUJ2IGFBskM0DMKok97A6LWUpHm+o7IvQBOWu9MLenp9Z+A==", 16694 + "version": "1.0.3", 16695 + "resolved": "https://registry.npmjs.org/react-loadable-ssr-addon-v5-slorber/-/react-loadable-ssr-addon-v5-slorber-1.0.3.tgz", 16696 + "integrity": "sha512-GXfh9VLwB5ERaCsU6RULh7tkemeX15aNh6wuMEBtfdyMa7fFG8TXrhXlx1SoEK2Ty/l6XIkzzYIQmyaWW3JgdQ==", 16653 16697 "license": "MIT", 16654 16698 "dependencies": { 16655 16699 "@babel/runtime": "^7.10.3" ··· 16882 16926 "license": "MIT" 16883 16927 }, 16884 16928 "node_modules/regjsparser": { 16885 - "version": "0.13.0", 16886 - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", 16887 - "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", 16929 + "version": "0.13.1", 16930 + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz", 16931 + "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==", 16888 16932 "license": "BSD-2-Clause", 16889 16933 "dependencies": { 16890 16934 "jsesc": "~3.1.0" ··· 17193 17237 "license": "MIT" 17194 17238 }, 17195 17239 "node_modules/resolve": { 17196 - "version": "1.22.11", 17197 - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", 17198 - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", 17240 + "version": "1.22.12", 17241 + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", 17242 + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", 17199 17243 "license": "MIT", 17200 17244 "dependencies": { 17245 + "es-errors": "^1.3.0", 17201 17246 "is-core-module": "^2.16.1", 17202 17247 "path-parse": "^1.0.7", 17203 17248 "supports-preserve-symlinks-flag": "^1.0.0" ··· 17371 17416 "license": "MIT" 17372 17417 }, 17373 17418 "node_modules/sax": { 17374 - "version": "1.4.4", 17375 - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.4.tgz", 17376 - "integrity": "sha512-1n3r/tGXO6b6VXMdFT54SHzT9ytu9yr7TaELowdYpMqY/Ao7EnlQGmAQ1+RatX7Tkkdm6hONI2owqNx2aZj5Sw==", 17419 + "version": "1.6.0", 17420 + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", 17421 + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", 17377 17422 "license": "BlueOak-1.0.0", 17378 17423 "engines": { 17379 17424 "node": ">=11.0.0" ··· 17534 17579 } 17535 17580 }, 17536 17581 "node_modules/serve-handler": { 17537 - "version": "6.1.6", 17538 - "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.6.tgz", 17539 - "integrity": "sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ==", 17582 + "version": "6.1.7", 17583 + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.7.tgz", 17584 + "integrity": "sha512-CinAq1xWb0vR3twAv9evEU8cNWkXCb9kd5ePAHUKJBkOsUpR1wt/CvGdeca7vqumL1U5cSaeVQ6zZMxiJ3yWsg==", 17540 17585 "license": "MIT", 17541 17586 "dependencies": { 17542 17587 "bytes": "3.0.0", 17543 17588 "content-disposition": "0.5.2", 17544 17589 "mime-types": "2.1.18", 17545 - "minimatch": "3.1.2", 17590 + "minimatch": "3.1.5", 17546 17591 "path-is-inside": "1.0.2", 17547 17592 "path-to-regexp": "3.3.0", 17548 17593 "range-parser": "1.2.0" ··· 17834 17879 "license": "MIT" 17835 17880 }, 17836 17881 "node_modules/sitemap": { 17837 - "version": "7.1.2", 17838 - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.2.tgz", 17839 - "integrity": "sha512-ARCqzHJ0p4gWt+j7NlU5eDlIO9+Rkr/JhPFZKKQ1l5GCus7rJH4UdrlVAh0xC/gDS/Qir2UMxqYNHtsKr2rpCw==", 17882 + "version": "7.1.3", 17883 + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-7.1.3.tgz", 17884 + "integrity": "sha512-tAjEd+wt/YwnEbfNB2ht51ybBJxbEWwe5ki/Z//Wh0rpBFTCUSj46GnxUKEWzhfuJTsee8x3lybHxFgUMig2hw==", 17840 17885 "license": "MIT", 17841 17886 "dependencies": { 17842 17887 "@types/node": "^17.0.5", ··· 18213 18258 "license": "MIT" 18214 18259 }, 18215 18260 "node_modules/svgo": { 18216 - "version": "3.3.2", 18217 - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", 18218 - "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", 18261 + "version": "3.3.3", 18262 + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.3.tgz", 18263 + "integrity": "sha512-+wn7I4p7YgJhHs38k2TNjy1vCfPIfLIJWR5MnCStsN8WuuTcBnRKcMHQLMM2ijxGZmDoZwNv8ipl5aTTen62ng==", 18219 18264 "license": "MIT", 18220 18265 "dependencies": { 18221 - "@trysound/sax": "0.2.0", 18222 18266 "commander": "^7.2.0", 18223 18267 "css-select": "^5.1.0", 18224 18268 "css-tree": "^2.3.1", 18225 18269 "css-what": "^6.1.0", 18226 18270 "csso": "^5.0.5", 18227 - "picocolors": "^1.0.0" 18271 + "picocolors": "^1.0.0", 18272 + "sax": "^1.5.0" 18228 18273 }, 18229 18274 "bin": { 18230 18275 "svgo": "bin/svgo" ··· 18910 18955 } 18911 18956 }, 18912 18957 "node_modules/url-loader/node_modules/ajv": { 18913 - "version": "6.12.6", 18914 - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", 18915 - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", 18958 + "version": "6.14.0", 18959 + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", 18960 + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", 18916 18961 "license": "MIT", 18917 18962 "peer": true, 18918 18963 "dependencies": {
+5 -4
package.json
··· 8 8 "clear": "docusaurus clear" 9 9 }, 10 10 "dependencies": { 11 - "@docusaurus/core": "^3.7.0", 12 - "@docusaurus/preset-classic": "^3.7.0", 13 - "@docusaurus/theme-mermaid": "^3.9.2", 11 + "@docusaurus/core": "^3.10.0", 12 + "@docusaurus/preset-classic": "^3.10.0", 13 + "@docusaurus/theme-mermaid": "^3.10.0", 14 + "@mermaid-js/layout-elk": "^0.1.9", 14 15 "@tailwindcss/typography": "^0.5.19", 15 16 "prismjs": "^1.30.0", 16 17 "react": "^19.0.0", 17 18 "react-dom": "^19.0.0" 18 19 }, 19 20 "devDependencies": { 20 - "@docusaurus/tsconfig": "^3.7.0", 21 + "@docusaurus/tsconfig": "^3.10.0", 21 22 "typescript": "^5.7.0" 22 23 } 23 24 }
+142 -87
sidebars.ts
··· 33 33 { 34 34 type: "doc", 35 35 id: "getting-started/deployment/other", 36 - label: "Other", 36 + label: "From Source", 37 + }, 38 + { 39 + type: "doc", 40 + id: "reference/production-deployment", 41 + label: "Production", 37 42 }, 38 43 ], 39 44 }, 40 45 { 41 46 type: "doc", 42 - id: "getting-started/authentication", 43 - label: "Authentication", 47 + id: "getting-started/configuration", 48 + label: "Configuration", 44 49 }, 45 50 { 46 51 type: "doc", 47 - id: "getting-started/configuration", 48 - label: "Configuration", 52 + id: "getting-started/authentication", 53 + label: "Authentication", 49 54 }, 50 55 { 51 56 type: "doc", ··· 70 75 label: "Guides", 71 76 items: [ 72 77 { 73 - type: "doc", 74 - id: "guides/lexicons", 75 - label: "Lexicons", 76 - }, 77 - { 78 - type: "doc", 79 - id: "guides/scripting", 80 - label: "Lua Scripting", 81 - }, 82 - { 83 - type: "doc", 84 - id: "guides/index-hooks", 85 - label: "Index Hooks", 86 - }, 87 - { 88 - type: "doc", 89 - id: "guides/backfill", 90 - label: "Backfill", 91 - }, 92 - { 93 - type: "doc", 94 - id: "guides/event-logs", 95 - label: "Event Logs", 96 - }, 97 - { 98 - type: "doc", 99 - id: "guides/plugins", 100 - label: "Plugins", 101 - }, 102 - ], 103 - }, 104 - { 105 - type: "category", 106 - label: "Reference", 107 - items: [ 108 - { 109 - type: "doc", 110 - id: "reference/xrpc-api", 111 - label: "XRPC API", 112 - }, 113 - { 114 - type: "doc", 115 - id: "reference/admin-api", 116 - label: "Admin API", 117 - }, 118 - { 119 78 type: "category", 120 - label: "Script Examples", 79 + label: "Indexing", 121 80 items: [ 122 81 { 123 82 type: "doc", 124 - id: "reference/scripts/get-record", 125 - label: "Get a Record", 83 + id: "guides/lexicons", 84 + label: "Lexicons", 126 85 }, 127 86 { 128 87 type: "doc", 129 - id: "reference/scripts/create-record", 130 - label: "Create Record", 88 + id: "guides/backfill", 89 + label: "Backfill", 131 90 }, 132 91 { 133 92 type: "doc", 134 - id: "reference/scripts/upsert-record", 135 - label: "Upsert Record", 93 + id: "guides/index-hooks", 94 + label: "Index Hooks", 136 95 }, 96 + ], 97 + }, 98 + { 99 + type: "category", 100 + label: "Scripting", 101 + items: [ 137 102 { 138 103 type: "doc", 139 - id: "reference/scripts/paginated-list", 140 - label: "Paginated List", 104 + id: "guides/scripting", 105 + label: "Lua Scripting", 141 106 }, 142 107 { 143 - type: "doc", 144 - id: "reference/scripts/list-or-fetch", 145 - label: "List or Fetch", 146 - }, 147 - { 148 - type: "doc", 149 - id: "reference/scripts/expanded-query", 150 - label: "Expanded Query", 108 + type: "category", 109 + label: "Script Examples", 110 + items: [ 111 + { 112 + type: "doc", 113 + id: "reference/scripts/get-record", 114 + label: "Get a Record", 115 + }, 116 + { 117 + type: "doc", 118 + id: "reference/scripts/create-record", 119 + label: "Create Record", 120 + }, 121 + { 122 + type: "doc", 123 + id: "reference/scripts/upsert-record", 124 + label: "Upsert Record", 125 + }, 126 + { 127 + type: "doc", 128 + id: "reference/scripts/paginated-list", 129 + label: "Paginated List", 130 + }, 131 + { 132 + type: "doc", 133 + id: "reference/scripts/list-or-fetch", 134 + label: "List or Fetch", 135 + }, 136 + { 137 + type: "doc", 138 + id: "reference/scripts/expanded-query", 139 + label: "Expanded Query", 140 + }, 141 + { 142 + type: "doc", 143 + id: "reference/scripts/update-or-delete", 144 + label: "Update or Delete", 145 + }, 146 + { 147 + type: "doc", 148 + id: "reference/scripts/batch-save", 149 + label: "Batch Save", 150 + }, 151 + { 152 + type: "doc", 153 + id: "reference/scripts/sidecar-records", 154 + label: "Sidecar Records", 155 + }, 156 + { 157 + type: "doc", 158 + id: "reference/scripts/cascading-delete", 159 + label: "Cascading Delete", 160 + }, 161 + { 162 + type: "doc", 163 + id: "reference/scripts/complex-mutations", 164 + label: "Complex Mutations", 165 + }, 166 + { 167 + type: "doc", 168 + id: "reference/scripts/algolia-sync", 169 + label: "Algolia Sync", 170 + }, 171 + { 172 + type: "doc", 173 + id: "reference/scripts/meilisearch-sync", 174 + label: "Meilisearch Sync", 175 + }, 176 + ], 151 177 }, 178 + ], 179 + }, 180 + { 181 + type: "category", 182 + label: "Features", 183 + items: [ 152 184 { 153 185 type: "doc", 154 - id: "reference/scripts/update-or-delete", 155 - label: "Update or Delete", 186 + id: "guides/labelers", 187 + label: "Labelers", 156 188 }, 157 189 { 158 190 type: "doc", 159 - id: "reference/scripts/batch-save", 160 - label: "Batch Save", 191 + id: "guides/plugins", 192 + label: "Plugins", 161 193 }, 194 + ], 195 + }, 196 + { 197 + type: "category", 198 + label: "Administration", 199 + items: [ 162 200 { 163 201 type: "doc", 164 - id: "reference/scripts/sidecar-records", 165 - label: "Sidecar Records", 202 + id: "guides/api-keys", 203 + label: "API Keys", 166 204 }, 167 205 { 168 206 type: "doc", 169 - id: "reference/scripts/cascading-delete", 170 - label: "Cascading Delete", 207 + id: "guides/permissions", 208 + label: "Permissions", 171 209 }, 172 210 { 173 211 type: "doc", 174 - id: "reference/scripts/complex-mutations", 175 - label: "Complex Mutations", 212 + id: "guides/event-logs", 213 + label: "Event Logs", 176 214 }, 215 + ], 216 + }, 217 + { 218 + type: "category", 219 + label: "Database", 220 + items: [ 177 221 { 178 222 type: "doc", 179 - id: "reference/scripts/algolia-sync", 180 - label: "Algolia Sync", 223 + id: "guides/database-setup", 224 + label: "Database Setup", 181 225 }, 182 226 { 183 227 type: "doc", 184 - id: "reference/scripts/meilisearch-sync", 185 - label: "Meilisearch Sync", 228 + id: "guides/postgres-to-sqlite-migration", 229 + label: "Postgres → SQLite Migration", 186 230 }, 187 231 ], 188 232 }, 233 + ], 234 + }, 235 + { 236 + type: "category", 237 + label: "Reference", 238 + items: [ 239 + { 240 + type: "doc", 241 + id: "reference/xrpc-api", 242 + label: "XRPC API", 243 + }, 244 + { 245 + type: "doc", 246 + id: "reference/admin-api", 247 + label: "Admin API", 248 + }, 189 249 { 190 250 type: "doc", 191 251 id: "reference/glossary", ··· 200 260 type: "doc", 201 261 id: "reference/troubleshooting", 202 262 label: "Troubleshooting", 203 - }, 204 - { 205 - type: "doc", 206 - id: "reference/production-deployment", 207 - label: "Production", 208 263 }, 209 264 ], 210 265 },