airi/server/AGENTS.md
RainbowBird 88625a8d84
Some checks are pending
CI / Lint (push) Waiting to run
CI / Build Test (stage-tamagotchi) (push) Waiting to run
CI / Build Test (stage-tamagotchi-godot) (push) Waiting to run
CI / Build Test (stage-web) (push) Waiting to run
CI / Build Test (ui-loading-screens) (push) Waiting to run
CI / Build Test (ui-transitions) (push) Waiting to run
CI / Unit Test (push) Waiting to run
CI / Type Check (push) Waiting to run
CI / Check Provenance (push) Waiting to run
Cloudflare Pages (Auth UI) / Deploy - ui-server-auth (push) Waiting to run
Cloudflare Workers / Deploy - stage-web (push) Waiting to run
Update Nix pnpmDeps Hash / update (push) Waiting to run
feat(api): hot-reload ConfigKV from Postgres (#2289)
## Summary

- Add the `config_kv` schema and Drizzle migration `0020`.
- Keep the ConfigKV schema, cache store, and invalidation contract in
the Resource API.
- Read ConfigKV through a five-minute Redis cache with PostgreSQL
fallback.
- Reload Router and TTS voice state through `configkv:invalidate`.
- Keep Auth rate limits fixed at 20 requests per 60 seconds.

## Stack

- Depends on #2294 for the Redis test implementation.
- This PR adds ConfigKV-specific cache-aside and Pub/Sub tests on top of
that implementation.

## Deployment

Run migration `0020` before this runtime reaches production traffic.

Then freeze ConfigKV writes. Audit and backfill the data with
[proj-airi/backend#2](https://github.com/proj-airi/backend/pull/2).
Merge
[proj-airi/backend#4](https://github.com/proj-airi/backend/pull/4)
first, so
the fixed Auth rate-limit keys are skipped.

Keep writes frozen until the hashes match and two API instances pass the
Pub/Sub reload check. This PR does not run production DDL or data
migration.

## Verification

- `pnpm exec vitest run <ConfigKV cache store, sync subscriber, and Auth
rate-limit tests>` (12 tests passed)
- `pnpm -F @proj-airi/api-server typecheck`
- `git diff --check`

See #2294 for its frozen-install, ESLint, and 73-test verification.

## Visual changes

None. This PR changes backend persistence and rate-limit wiring only.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Added centralized configuration storage with validation, caching,
refresh, and automatic synchronization across services.
- Configuration updates now refresh related language-model and
text-to-speech settings automatically.

- **Bug Fixes**
- Improved recovery after service reconnects by clearing stale
configuration and reloading current values.
- Invalid or unavailable configuration data now produces clearer
service-unavailable responses.

- **Changes**
- Authentication rate limiting now uses a consistent limit of 20
requests per minute per client.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Signed-off-by: RainbowBird <git@luoling.moe>
Signed-off-by: RainbowBird <rbxin2003@outlook.com>
2026-08-15 22:24:32 +08:00

585 B

Server Guide

Runtime contracts

  • Use Valibot for all server data that crosses a trust boundary.
  • This includes HTTP data, Pub/Sub messages, queue jobs, WebSocket events, database JSON, and provider responses.
  • Define each schema beside the contract owner.
  • Use parse if the caller converts invalid data into an error.
  • Use safeParse if the caller branches on valid and invalid data.
  • Do not use typeof, Record<string, unknown>, or type casts as runtime input validation.
  • Infer TypeScript types from Valibot schemas. Do not duplicate the contract in an interface.