Milestones 0 and 1: foundation and money in (20261007.10)

Foundation: single arm64 container (Hono + SQLite via Drizzle, React + Vite),
local sign-in with long-lived sessions and passkeys, roles (read-only, full
access, admin), nightly and pre-upgrade backups, light and dark themes,
date-based version numbers, and the ideas lightbulb behind IDEAS_ENABLED.

Money in: accounts with balances, CSV import with bank detection, a column
mapping pop-up for unknown layouts, duplicate checks, transfer pairing and
undo; one-tap review with learned rules; activity with search, splits, tags,
notes and cash entries. Statement files are blocked from commits by a
pre-commit hook; tests use synthetic fixtures only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-07 19:52:07 -04:00
commit c3cf0f3eb8
147 changed files with 21713 additions and 0 deletions

View File

@@ -0,0 +1,33 @@
import type { ReactNode } from 'react';
import { useConfig } from '@/lib/session';
import { LogoMark, VersionTag } from './brand';
/** The calm, centered frame for setup, sign-in and the first password change. */
export function AuthLayout({ title, subtitle, children }: { title: string; subtitle?: ReactNode; children: ReactNode }) {
const { data } = useConfig();
return (
<div className="relative flex min-h-dvh flex-col items-center px-5 pt-safe">
<div className="spotlight pointer-events-none absolute inset-x-0 top-0 h-[460px]" aria-hidden />
<div className="relative flex w-full max-w-sm flex-1 flex-col justify-center py-12">
<div className="mb-8 flex flex-col items-center text-center">
<LogoMark className="mb-5 size-16 rounded-[22px] shadow-lift" />
<h1 className="text-[26px] font-semibold tracking-tight">{title}</h1>
{subtitle ? <p className="mt-2 text-[15px] leading-relaxed text-muted-foreground">{subtitle}</p> : null}
</div>
<div className="animate-fade-up rounded-3xl border bg-card p-6 shadow-lift sm:p-7">{children}</div>
</div>
<footer className="relative pb-6 pb-safe">
<VersionTag version={data?.version} />
</footer>
</div>
);
}
export function FormError({ message }: { message: string | null }) {
if (!message) return null;
return (
<p role="alert" className="rounded-xl bg-bad/10 px-3.5 py-2.5 text-[13.5px] leading-snug text-bad">
{message}
</p>
);
}