6.9 Security model

6.9.1 Transport

Tomcat terminates HTTPS on :443 from a PKCS12 keystore (typically generated from a Let’s Encrypt certificate). No reverse proxy is required. PostgreSQL is bound to localhost:5432 and not exposed publicly.

6.9.2 Authentication

OAuth 2.1 (auth code + PKCE). The OwnSona server runs both halves of the OAuth machinery in a single WAR:

The two app-specific pieces register at startup via AsExtensions:

There is no static-token shortcut and no ?token= URL fallback — every request must go through the OAuth validation path. See Connecting Claude and Connecting OpenAI for the client-side end of the flow.

6.9.3 Secret rejection

SecretScanner runs on every write (remember, remember_batch, update_memory) and rejects text that matches the shape of:

Best-effort; the calling client shouldn’t be forwarding secrets in the first place. The check returns SECRET_REJECTED when it fires.

6.9.4 Database privileges

The ownsona PostgreSQL role has SELECT/INSERT/UPDATE/DELETE/TRUNCATE on memories, plus CREATE ON SCHEMA public and ownership of memories (and its sequence) so the auto-migrator can ALTER TABLE at runtime. It is not a superuser.

6.9.5 User isolation

Schema-level: every row carries user_id and every query filters on it. Operationally: single-user mode pins every write to the OWNSONA_USER_ID value (default "default"). Multi-user is deliberately out of scope.