2026 / 03
NOEMA — a reflective life system
OutcomeShipped a private journaling system with its own identity model: records isolated per account, password recovery that needs no mail server, and a database dedicated to this app alone.
Overview
A private journaling and reflection system: daily entries, long-term milestones and life phases, each account's records fully isolated behind an identity model built for one person's most private data.
Context
A place to record what actually happened on a given day and look back across months — which only works if the person writing it never has to wonder who else can read it. That requirement drives the identity model: self-serve accounts, an echo-key recovery path that is deliberately not a second login factor, optional passkeys, and every record scoped to one account.
System
recovery: self-set secret · no mail server · no operator overrideOnly the person can recover the account.
Including me. That is the point.Problem
A multi-user journal running without a mail server has no password reset path. Leave it out and a forgotten password destroys the most private data on the system, permanently. Add the usual reset flow and the recovery route becomes the easiest way into exactly the data the system exists to protect.
Investigation
Initial hypothesis
The administrator could simply be added as a Maintainer.
Recovery rests on a second secret the person writes at signup: a prompt and answer of their own choosing, hashed independently of the login password. Alongside it they may store a hint, which is the only part ever shown back to them — the answer itself exists solely as a hash and is never displayed, mailed, or recoverable by an operator. Passkeys sit on top for anyone who would rather stop typing a password at all.
Evidence
merge_request.check_mergeability
# poll until merge_status permits mergeGitLab 18 refused cross-organization membership; only the CI bot could merge to protected main.
Decision
Script bot-owned merge requests and poll GitLab’s asynchronous mergeability result.
Result
Account recovery with no mail server and no support channel: the only party who can restore an account is the person who set the second secret. Records stay isolated per account, on a Postgres instance dedicated to this application rather than the shared cluster database.
What I would change
Current limitation: This solved the immediate migration constraint, but it was not treated as the desired long-term operating model. The scripted path runs through an in-cluster administrative console, is scoped to this one repository, and leaves the merge request itself as the audit record — a bot-authored MR is still a reviewable artifact, not a silent direct push.
Next step: Remove the special path entirely once organization membership semantics allow the administrator to hold a normal Maintainer role. The workaround should not outlive the constraint that created it.