Properties
category: spec
tags: [quota, disk-usage, plugin, plan]
last_updated: 2026-03-17
confidence: high

Per-Wiki Disk Usage Caps Plan

Quota enforcement code already exists in resolver.py (50MB limit, write rejection) but reads from robot.db where disk_usage_bytes is always 0. This plan wires up real measurements.

Architecture

  • Measurement: du -sb on entire wiki directory (repo + wiki.db + FAISS index)
  • Storage: New stats table in per-wiki wiki.db (not robot.db) — resolver already operates per-wiki-DB
  • Update timing: Page count on every save/delete (via otterwiki plugin hook). Disk usage via cron only (15-min interval, acceptable lag).
  • Enforcement: Existing resolver code — reads stats from wiki.db after DB swap, strips WRITE permission or returns 413 for API requests.

Components

1. stats table in wiki.db

CREATE TABLE IF NOT EXISTS stats (
    name VARCHAR(64) PRIMARY KEY,
    value TEXT,
    updated_at DATETIME
);

Keys: page_count, disk_usage_bytes. Seeded in _init_wiki_db().

2. New plugin: otterwiki-wikistats

Follows otterwiki-api pattern. Hooks: page_saved, page_deleted → update page_count via storage.list(). Disk usage left to cron. Must use _state["storage"] dict (not self.storage) for multi-tenant correctness — resolver patches this in _swap_storage().

3. Resolver changes

  • Add _get_wiki_stats(wiki_dir) — reads stats table from wiki.db
  • Move quota check to after _swap_database() — read real disk_usage from wiki.db with fallback to robot.db
  • Add otterwiki_wikistats._state["storage"] patch in _swap_storage()
  • Seed stats table in _init_wiki_db()

4. Cron backstop update

Update wiki-quota.sh.j2 to write to each wiki's wiki.db stats table (primary) AND keep updating robot.db for the dashboard API.

User Experience

  • API/MCP: HTTP 413 with "Wiki quota exceeded (50MB limit)"
  • Web UI: 403 on save (WRITE stripped). Generic permission denied — quota-specific message is a follow-up.
  • Dashboard: Reads disk_usage_bytes from robot.db via management API (15-min lag from cron).

Files to Modify

Repo File Change
robot.wtf app/resolver.py _get_wiki_stats(), quota check after swap, stats table in init, storage patch
robot.wtf ansible/roles/quota/templates/wiki-quota.sh.j2 Write to wiki.db + robot.db
robot.wtf ansible/roles/deploy/tasks/main.yml pip install otterwiki-wikistats
new repo otterwiki-wikistats Plugin: setup, page_saved, page_deleted hooks

Test Plan

  1. Quota read from wiki.db — over limit → WRITE stripped
  2. Under limit → pass-through
  3. API over-quota → 413
  4. Fallback to robot.db when stats table missing
  5. Plugin: page count updated on save/delete
  6. Plugin: uses _state["storage"] not stale reference

Open Questions

  1. Quota check must move to after _swap_database() — verify no regression on API 413 path
  2. Cron user permissions on wiki.db files
  3. Plugin _state dict convention — follow existing pattern from otterwiki-api