The person's record

Who the assistant is talking to, kept as claims, never orders.

What they are called, their timezone, who is in their household, what they are allergic to, what they are working on. An assistant loads the record at the start of a conversation and writes to it as it learns.

Python 3.12+ Serves on :8002 Tokens from keyring MIT licensed
GET    /v1/user                       -> counts, and every pinned entry your token may see
GET    /v1/user/schema                -> which field keys exist, and what each one means
PUT    /v1/user/fields/{key}          -> one named fact: preferred_name, timezone, ...
POST   /v1/user/notes                 -> something that happened, was noticed, or was learned
GET    /v1/user/entries?q=lisbon      -> full-text and filtered search across both
POST   /v1/user/entries/{id}/confirm  -> a human says this is still true
DELETE /v1/user/entries/{id}          -> forget one thing
DELETE /v1/user                       -> forget all of it, for good
No request names a personThe account comes from the token; it appears in no URL.
Provenance on everythingWho wrote it, where it came from, when a human last confirmed it.
Credentials are refusedAnything shaped like a key or a token is a 422 naming keyring.
Erasure reaches the bytesA purge is a delete plus a truncating checkpoint.

How it works

The subject is a person, and that drives the design.

It has no accounts of its own. The only identity it ever learns is the subject of a token keyring signed, verified locally against keyring's published keys.

01

Fields and notes

A field is one named fact with a meaning the schema states. A note is something that happened, was noticed, or was learned. Both are searchable, and both can be pinned.

02

Scope comes from the token

A token minted for user sees unscoped entries; one minted for user.<scope> sees those plus that compartment. A query parameter can narrow, never widen.

03

A record is data

An assistant that reads pages and email writes here from untrusted text, so every entry carries its provenance and is meant to be rendered as “your notes say”.

The API

No account id in any path, and no parameter that names a subject.

Every route except GET /healthy and GET /ready needs a bearer token minted by keyring. The reference is docs/api.md.

GET /v1/user

The record

Counts, and every pinned entry the token may see. GET /v1/user/schema says which field keys exist.

PUT /v1/user/fields/{key}

Fields

One named fact, typed and validated against the schema.

POST /v1/user/notes

Notes

Something that happened, was noticed, or was learned, with where it came from.

GET /v1/user/entries

Search

Full-text and filtered search across fields and notes.

POST …/entries/{id}/confirm

Confirming

A human says an entry is still true, which is recorded with it.

GET /v1/user/export

Export and events

Everything held about the person, and the change log, on request.

Run it

Three commands; every setting has a working default.

You need Python 3.12 or newer, uv, and a keyring to mint tokens (its own make run serves where the defaults expect it).

  1. Install.
    make install
  2. Take the defaults.
    cp .env.example .env
  3. Serve it; the interactive docs are at /docs.
    make run

A USER_API_-prefixed environment variable that matches no setting is a startup error, not a warning. Point it at a settings-api and each person can lower their own max_pinned and search_default_limit, and choose the compartment a write that names no scopes lands in. make check is the gate: format, lint, strict types, layering contracts, and the suite at 100% branch coverage.

What it will not do

The terms of the arrangement, stated rather than hidden.

Can one person's token read another person's record?

No. Every store method takes an account id that is not optional, so a cross-account read is not forbidden, it is inexpressible. Another account's entry reads back exactly like one that never existed.

Can a signed token be revoked?

No. Logging out of keyring ends a session there and nothing here; an already-minted token works until it expires, which is about fifteen minutes.

What happens to a secret pasted into a note?

It is refused with a 422 naming keyring as the right home. This store is plaintext on disk and indexed for search; a secret in it would be a secret in a search index.

What does “forget that” do?

What DELETE on one entry means is the person's own setting: grace (the default), immediate, or tombstone. DELETE /v1/user forgets all of it, for good.

Docs

Written for the person who has to run it.