f8e797ab09
Replaces the Gitea OAuth gesture as the primary human-auth path (roadmap item #5, SPEC §6.2). Users sign in by entering their email, receiving a six-digit code via the existing SMTP layer, and entering the code on a two-step /login surface. The Gitea OAuth callback remains functional during migration — the new UI links to it as a fallback for users with active OAuth sessions or older invite paths — and is scheduled for removal in a future release once OTC adoption is universal. Existing users are linked by email on first OTC sign- in (gitea_id preserved); new users are provisioned with NULL gitea_id and rely on email as the identity key. The migration introduces backend/migrations/012_otc.sql (otc_codes table + users schema rebuild for nullable gitea_id and a partial unique index on email), two new endpoints (POST /auth/otc/request, POST /auth/otc/verify), bcrypt as a new backend dependency for code hashing, and 11 new tests in test_otc_vertical.py covering the happy path, expired and consumed and wrong codes, the per-email rate limit, the allowlist gate, the OAuth-era link path, fresh provisioning, and prior-code invalidation on re-request. No new secrets are required — the existing SECRET_KEY signs sessions and bcrypt's per-row salt covers the code hashes. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
61 lines
2.7 KiB
React
61 lines
2.7 KiB
React
// Landing.jsx — §14.1's pre-login surface.
|
|
//
|
|
// The page's three jobs per §14.1: name what this thing is, pitch why
|
|
// someone would care, and offer the sign-in affordance. The deployment
|
|
// supplies its display name via VITE_APP_NAME (see frontend/.env.example);
|
|
// the subtitle and pitch below currently carry the corpus this instance
|
|
// hosts and should be lifted into deployment config in a follow-up so
|
|
// the framework source stays brand-neutral.
|
|
|
|
import { Link } from 'react-router-dom'
|
|
|
|
export default function Landing() {
|
|
return (
|
|
<div className="landing">
|
|
<div className="landing-inner">
|
|
<h1>{import.meta.env.VITE_APP_NAME}</h1>
|
|
<p className="subtitle">
|
|
An open dictionary of the words humans and machines need to agree on.
|
|
</p>
|
|
|
|
<p className="pitch">
|
|
Large language models work brilliantly with programming languages because every
|
|
word in Python or C has a definitive meaning enforced by tooling. They struggle
|
|
with natural language because no such dictionary exists for words like
|
|
<em> consent</em>, <em> trait</em>, or <em> agency</em> — words that do enormous
|
|
work in any system that interacts with humans. The Open Human Model is the
|
|
corpus this framework produces — one word per RFC, argued in public, with the
|
|
first RFC defining <em>human</em>. Build the dictionary first.
|
|
</p>
|
|
|
|
<Link className="btn-signin" to="/login">Sign in</Link>
|
|
<Link className="secondary-link" to="/philosophy">Read the full philosophy →</Link>
|
|
|
|
<ul className="landing-deck">
|
|
<li>
|
|
<strong>One word per RFC.</strong> An RFC defines a single word — its meaning,
|
|
its relationships to other defined words, and the protocol by which humans and
|
|
machines interact with it.
|
|
</li>
|
|
<li>
|
|
<strong>Argued in public, with the model.</strong> Every definition is the
|
|
product of a transcript: a human and a model in careful argument until the
|
|
ambiguity is gone. The argument is the evidence the definition was earned.
|
|
</li>
|
|
<li>
|
|
<strong>Graduation is the load-bearing moment.</strong> A super-draft is the
|
|
start of the conversation. Graduation gives the definition a permanent home
|
|
and a stable identifier — and only then can other RFCs build on it.
|
|
</li>
|
|
</ul>
|
|
|
|
<p className="landing-attribution">
|
|
OHM is run by Ben on <strong>Wiggleverse RFC</strong> — the open-source
|
|
standardization-process software that powers it. Anyone can run their
|
|
own collaboration on the same substrate.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|