Policies
Dieser Inhalt ist noch nicht in deiner Sprache verfügbar.
The Limits & Policies page (/admin/limits) exposes runtime-tunable policy in seven sections — HTTP
Rate Limits, AI Provider Retry, AI Payload Caps, Identity & Lockout, Free tier,
Registration challenge and Invitation ceilings. Most
settings can be changed without restarting the server; a number require a restart and are flagged
RESTART in the UI.
How overrides work on this page
Section titled “How overrides work on this page”The page edits overrides, not raw values. Each field shows the compiled-in default beneath it
(default 10000), and the database holds a row only where you have actually changed something. Three
consequences, all of which the page’s lede states in one line:
- Saving a value that matches the baseline clears its override. Typing the default back in is the supported way to un-set a field — you do not need a reset for that.
- Reset section discards every override in one section, returning those fields to the baseline. It is
disabled when the section has none, and the count next to each section header (
3 OVERRIDES) tells you where they are. - Reset ALL overrides, at the bottom of the page, clears every override on the page at once. Use it to get back to a known-good configuration after experimenting.
“Baseline” means the value from appsettings.json and the environment — so an override you clear here
falls back to whatever your Compose file or .env sets, not necessarily to the number in this
documentation.
Rate limits
Section titled “Rate limits”Per-IP and per-user request budgets, enforced in front of the endpoint dispatcher. Each policy exposes three fields: Permit Limit, Window (sec) and Segments (how finely the sliding window is subdivided — more segments means the budget refills more smoothly).
| Policy on the page | Default | Scope |
|---|---|---|
| Global | 100 / 60s, 4 segments | per IP |
| Auth | 10 / 60s, 2 segments | per IP |
| Local auth | 5 / 60s, 2 segments | per IP |
| Sync | 30 / 60s, 3 segments | per authenticated user |
| AI (authenticated) | 30 / 60s, 3 segments | per user |
| AI (unauthenticated) | 5 / 60s, 2 segments | per IP |
| Pod uplink (connections) | 20 / 60s, 4 segments | per IP |
| Registration | 20 / 3600s, 6 segments | per IP |
Registration is its own bucket, not part of Auth: POST /auth/register is measured in accounts an
hour rather than attempts a minute, so raising Auth does nothing for a throttled sign-up flow and
tightening Auth does not slow an account farm. POST /auth/challenge sits on it too, so a client that
fetches a challenge and then registers spends two permits per account.
Every rate-limit field needs a restart. The limiter is built once at startup, so an edit here is saved and then waits — the page tells you how many settings are pending.
Local auth is the strict one, and it is the bucket most likely to surprise you: it covers
POST /admin/login, admin MFA, and POST /auth/login/local together, so five sign-in attempts a minute
from one address is the real ceiling. GET /admin/login sits on the looser Auth bucket. Separately,
ASP.NET Identity locks an account after its own run of failed attempts — see
Identity and lockout — so a 429 and a lockout are two different walls.
Pod uplink bounds connection attempts on the pod uplink hub, not API
calls. Budget one pod connect as at least two permits — SignalR negotiates and then upgrades, and both
count — so the default is roughly ten attempts a minute from one address. Raise it if a fleet of pods
shares one egress address and you see 429 on reconnect.
AI provider retry
Section titled “AI provider retry”How the AI proxy behaves when an upstream provider pushes back with 429 or a 5xx. All four hot-reload.
| Field | Default | Purpose |
|---|---|---|
| Max retries | 3 | Total retry attempts on 429/5xx |
| Max Retry-After (sec) | 30 | Cap on honouring a provider’s Retry-After header, so a hostile or clumsy value can’t stall a request for minutes |
| Min request interval (ms) | 500 | Client-side throttle between calls to the same provider |
| Cloudflare base backoff (sec) | 5 | Base delay for Cloudflare-fronted 429s, which don’t always carry a usable Retry-After |
AI payload caps
Section titled “AI payload caps”Caps on the size of AI proxy traffic, to keep one request from becoming an unbounded bill.
| Field | Default | Purpose | Restart |
|---|---|---|---|
| Max optimize text length (chars) | 10,000 | Ceiling on the text an Optimize request may submit | — |
| Max patterns per request | 10 | Ceiling on optimization patterns in one request | — |
| Chat max_tokens cap | 32,768 | Upper bound on max_tokens for a chat request; a larger client value is clamped |
— |
| Optimize max_tokens cap | 2,048 | The same bound for Optimize | — |
| Guardrail verdict max_tokens | 512 | Output budget for one guardrail classification. Raise it when decisions show ERROR with a classifier error — a reasoning classifier model can spend the whole budget thinking and never answer. Clamped to 64–8192 |
— |
| Server tool rounds | 3 | Rounds the server may spend calling its own tools before it forces a final answer. A wall-clock bound, not a spend bound — paid web searches stay capped by their own per-request budget. Raising it shrinks each Operator step’s per-call timeout so the step still fits its wall clock, so raise it for turns that need more grounding, not for turns that need more time. Clamped to 1–8 | — |
| Upstream timeout (sec) | 120 | How long to wait on the provider before giving up | RESTART |
| Kestrel max request body (MB) | 5 | Ceiling on any request body the server will accept | RESTART |
The same AiProxy configuration section carries the remaining guardrail tuning knobs — the verdict cache TTL, the classifier timeout and the short-circuit-on-hit switch. Those are not on this page; they are described with the feature, on Guardrails.
Identity and lockout
Section titled “Identity and lockout”The Identity & Lockout section holds password rules and account lockout for local (password) accounts. Provider-backed accounts are governed by their identity provider, not by these fields. Every field here needs a restart, because ASP.NET Identity binds its options once at startup.
| Field | Default |
|---|---|
| Minimum length | 10 |
| Required unique chars | 4 |
| Require digit | on |
| Require uppercase | on |
| Require lowercase | on |
| Require symbol | off |
| Max failed attempts | 5 |
| Lockout duration (min) | 15 |
| Enable for new users | on |
Lockout is per account and independent of the rate limits above: five wrong passwords lock
that account for fifteen minutes even from an address that is nowhere near its request budget. In the
audit log a lockout and a 429 look different — Login.Failed rows keep arriving
in the first case and stop in the second.
Password breach screening
Section titled “Password breach screening”The Password breach screening (HIBP) fields sit in the same section and, unlike the rest of it, take effect without a restart. With Enabled on (the default), setting or changing a local password sends the first five characters of its SHA-1 hash to api.pwnedpasswords.com and matches the returned suffix list locally — the password itself never leaves the server, and the reply is padded so its size does not identify the queried prefix. A hit rejects the password.
Reject when HIBP is unreachable is off by default: a lookup that times out accepts the password, which is what an air-gapped or egress-filtered instance needs. Turn it on to fail closed instead.
Whether password sign-up exists at all is not on this page: LocalAuth:Enabled,
LocalAuth:RequireEmailVerification and Admin:AllowPasswordLogin are startup configuration, described
in Configuration. Which OAuth providers are enabled is likewise
configuration — the Settings page shows their status read-only.
Free tier
Section titled “Free tier”One field: Suspend free tier (FreeTier:Suspended, off by default), and it hot-reloads like the
Identity password-breach pair above it — no restart, no RESTART badge.
Switching it on refuses all new account creation — local registration and every OAuth provisioning path, which covers both the desktop client and the Portal’s Microsoft sign-in — and refuses AI proxy spend for members of the default (free) group. Speech and embeddings are not covered. Existing sign-ins, including the admin console and admin password login, keep working: it freezes growth and spend, not access.
Per-user and per-group quotas
Section titled “Per-user and per-group quotas”Object caps are not on this page. They live on each group’s editor (Groups), so different groups can have different ceilings. Defaults for a new group:
| Object | Cap |
|---|---|
| Templates | 100 |
| Personas | 50 |
| AI providers | 20 |
| Sessions | 10,000 |
| Memories | 500 |
| Todos | 500 |
A sync push that would exceed a cap is rejected with 409 quota_exceeded, which the desktop client
surfaces in its Cloud Sync settings. Knowledge-base quotas sit in the same editor and are described on
Knowledge bases; the group’s hourly/daily/weekly token limits
are on Groups.
What needs a restart?
Section titled “What needs a restart?”Most fields are read through IOptionsMonitor<T> and re-bind the moment you save. The ones that cannot
are marked RESTART in the form:
- every HTTP rate-limit field — the limiter is constructed once at startup;
- every Identity & Lockout field — ASP.NET Identity binds its options once at startup;
- Upstream timeout (sec) and Kestrel max request body (MB).
Everything in AI Provider Retry and the remaining AI Payload Caps is live immediately.
Save a RESTART field and the page shows a notice counting how many settings are waiting, with a
Restart server button beneath it. If it reads Restart server (unavailable) and won’t click, the
container wasn’t told it may restart itself: set PIA_RESTART_SUPPORTED=true on the service (it needs a
Compose restart policy to come back up), or recreate the container by hand.
Settings that are not on this page at all — database provider, JWT signing key, encryption master key — are startup configuration and change only via the environment plus a restart. See Configuration.