From e8e555d8a412eec6c73a8275a655587fc30ad76d Mon Sep 17 00:00:00 2001 From: Ben Stull Date: Sat, 30 May 2026 04:04:11 -0700 Subject: [PATCH] docs(invites): correct stale last_seen_at NULL claim MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The provisioning docstring claimed the invitee row gets `last_seen_at = NULL` as the "not yet arrived" discriminator. It does not: the column is NOT NULL and the INSERT omits it, so it defaults to datetime('now') — the longer note below already explained this, but the bullet contradicted it. Rewrite the bullet to state the real behavior (both timestamps default to now; the pending-invite state lives in the unclaimed user_invite_tokens row) and note that consumers must treat a pending-invite row as never-seen. Comment-only; no runtime change. Co-Authored-By: Claude Opus 4.8 --- backend/app/invites.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/app/invites.py b/backend/app/invites.py index a5abcc5..565ef8e 100644 --- a/backend/app/invites.py +++ b/backend/app/invites.py @@ -144,10 +144,16 @@ def create_invite( The invitee `users` row is provisioned with: * `permission_state='granted'` — the admin's hand is the grant; the v0.8.0 self-serve `pending` queue is for the other path. - * `last_seen_at = NULL` — the discriminator for "invited but - not yet arrived" per the §16 / roadmap design. Every sign-in - path stamps `last_seen_at` to now, so a NULL value means the - invited user has not clicked through yet. + * `created_at` / `last_seen_at` — NOT set here, so both fall + through to the column default `datetime('now')` (the column is + `NOT NULL`; see `migrations/001_users_and_audit.sql` and the + longer note below). The "invited but not yet arrived" state is + therefore NOT carried on the user row — it is the existence of + an unclaimed `user_invite_tokens` row, surfaced as the listing's + `pending_invite` field. Consumers that want a truthful + last-seen MUST treat a pending-invite row as never-seen rather + than trusting `last_seen_at` (every real sign-in path stamps it + to now, but an unclaimed invite has never hit one). * `gitea_id = NULL`, `gitea_login = NULL` — same as a v0.7.0 OTC-provisioned user; the OAuth identity is grandfathered if the user ever lands through that path.