Properties
category: reference
tags:
  - robot.wtf
  - v1
  - sqlite
  - data-access
last_updated: 2026-03-15
confidence: high

V1-1/V1-2: SQLite Data Access Layer & TenantResolver Port

Summary

Ported the DynamoDB-backed data models, auth middleware, TenantResolver, and ManagementMiddleware from wikibot-io to robot.wtf using SQLite as the storage backend. Identity model changed from OAuth provider sub to ATProto DID.

Branch: feat/v1-sqlite-port in the robot.wtf repo Commit: 9861a0b Tests: 55/55 passing

Files Created (21 total)

Data Access Layer

File Description
app/db.py SQLite connection factory (WAL mode, foreign keys, configurable via ROBOT_DB_PATH)
app/models/user.py UserModel: CRUD by DID, get_by_username, set_username with validation
app/models/wiki.py WikiModel: CRUD by slug, list_by_owner, scan_by_token (bcrypt)
app/models/acl.py AclModel: CRUD by (wiki_slug, grantee_did), list_by_wiki, upsert semantics

Auth

File Description
app/auth/jwt.py PlatformJWT: RS256 sign/verify, issuer/audience = "robot.wtf"
app/auth/permissions.py Role-to-permission mapping (owner/editor/viewer)
app/auth/headers.py Proxy header construction for otterwiki
app/auth/acl.py AclEnforcer: check_access, check_public_access, check_bearer_token
app/auth/middleware.py AuthMiddleware: JWT from header or cookie, user resolution

WSGI Middleware

File Description
app/resolver.py TenantResolver: Host header → wiki slug, auth, ACL, storage swap (otterwiki stubbed)
app/management/routes.py ManagementMiddleware: /api/* routes for wiki CRUD, ACL, token management
app/management/token.py MCP bearer token generation (secrets + bcrypt)

Tests

File Tests
tests/conftest.py Shared fixtures: in-memory SQLite, model instances, sample data
tests/test_models.py 35 tests: all CRUD ops, constraints, FK enforcement, bcrypt token scan
tests/test_auth.py 20 tests: JWT round-trip, expiry, wrong key, permissions, ACL enforcer, auth middleware

Key Schema Differences from wikibot-io

Aspect wikibot-io robot.wtf
User PK UUID ATProto DID (text)
Wiki PK (owner_id, wiki_slug) composite slug only
ACL PK (wiki_id, grantee_id) where wiki_id = "owner:slug" (wiki_slug, grantee_did)
Identity OAuth provider + sub ATProto DID + handle
Storage DynamoDB + boto3 SQLite + sqlite3 stdlib
API prefix /admin/* /api/*
JWT issuer wikibot.io robot.wtf
Tier/billing Yes No

Architecture Notes

  • No boto3/DynamoDB references anywhere in the codebase
  • otterwiki imports are conditional in resolver.py — uses try/except ImportError with stubs
  • ManagementMiddleware auth callback returns 501 (ATProto OAuth not yet implemented)
  • TenantResolver extracts wiki slug from subdomain directly (not username+path like wikibot-io)
  • Foreign keys enforced — wiki requires valid owner_did, ACL requires valid wiki_slug and grantee_did