999c4b65ef
Implements the M3-frontend slice of the §22 multi-project track, per docs/superpowers/specs/2026-06-03-m3-frontend-design.md (design merged in #10). Completes the runtime-config cut 0.33.0 (M3-backend Plan A) began. Frontend: - DeploymentProvider boots GET /api/deployment → {name, tagline, defaultProjectId, projects}; brandTitle() neutral 'RFC' pre-fetch fallback. - /p/:projectId/* routing with generic /e/<slug> segment. ProjectLayout fetches /api/projects/:id, applies per-project theme (reset on switch), provides ProjectContext, guards the corpus (served only for the default; others get NotServedPlaceholder — decouples this slice from Plan B). - Directory at / (2+ projects) with N=1 redirect into the single project; ProjectSwitcher in deployment chrome; entry-noun by project type. - VITE_APP_NAME hard cut: removed from vite.config + index.html; the 6 brand reads now use deployment.name via context; static <title>RFC</title> + JS document.title. Internal /rfc·/proposals links → /p/<project>/e|proposals via lib/entryPaths. Backend: - GET /api/deployment returns default_project_id (the guard contract). - Server-side 308s: /rfc/<slug>, /rfc/<slug>/pr/<n>, /proposals/<n> → /p/<default>/… . nginx (testing + prod) routes /rfc/ and /proposals/ to the backend. Tests: 3 new backend redirect/deployment tests (438 pass); Vitest unit for DeploymentProvider, ProjectLayout (theme/guard/404), Directory (11 pass); clean build with no VITE_APP_NAME. Playwright e2e deferred until Tier-1 seeds a registry (see CHANGELOG 0.35.0 step 5). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
70 lines
2.8 KiB
React
70 lines
2.8 KiB
React
// BetaPending.jsx — the "your request is in review" page (§6.1 / §14.1).
|
|
//
|
|
// v0.3.0 introduced this surface as the post-OAuth-rejection page (a
|
|
// user whose email wasn't on the `allowed_emails` table bounced here).
|
|
// v0.8.0 (roadmap item #6) repurposes it as the post-OTC pending-grant
|
|
// page: any authenticated user whose `permission_state='pending'` lands
|
|
// here on root visits, after a fresh-OTC profile capture, or via the
|
|
// header "Your beta access is in review" affordance.
|
|
//
|
|
// The deployment supplies a contact channel via VITE_BETA_CONTACT (an
|
|
// email, URL, or short instruction). If unset, we render a generic
|
|
// ask-the-operator line.
|
|
|
|
import { Link } from 'react-router-dom'
|
|
import { useDeployment } from '../context/DeploymentProvider'
|
|
import { brandTitle } from '../lib/brand'
|
|
|
|
export default function BetaPending({ viewer }) {
|
|
const contact = import.meta.env.VITE_BETA_CONTACT || ''
|
|
const isPending = viewer?.permission_state === 'pending'
|
|
// §22.9: deployment name from runtime config (was VITE_APP_NAME).
|
|
const { name } = useDeployment()
|
|
return (
|
|
<div className="beta-pending">
|
|
<div className="beta-pending-inner">
|
|
<h1>
|
|
{isPending
|
|
? 'Your request is in review.'
|
|
: `${brandTitle(name)} is in private Beta.`}
|
|
</h1>
|
|
{isPending ? (
|
|
<>
|
|
<p>
|
|
Thanks for telling us a bit about yourself. The deployment's
|
|
admins are notified by email as soon as a request lands;
|
|
we don't commit to a fixed SLA — turnaround depends on
|
|
operator availability — and the deployment operator is
|
|
the right person to ask if a wait runs long.
|
|
</p>
|
|
<p>
|
|
While you wait, the catalog on the left lists every super-draft
|
|
and active RFC in the framework — reading is open. Discussion
|
|
and contribution unlock once your access is granted.
|
|
</p>
|
|
</>
|
|
) : (
|
|
<p>
|
|
Discussion and contribution are gated to invited contributors for
|
|
now. Reading is open — every super-draft, every active RFC, and
|
|
every public conversation is visible without signing in.
|
|
</p>
|
|
)}
|
|
{contact ? (
|
|
<p className="beta-pending-contact">
|
|
Questions? Contact <strong>{contact}</strong>.
|
|
</p>
|
|
) : (
|
|
<p className="beta-pending-contact">
|
|
Questions? Contact the deployment operator.
|
|
</p>
|
|
)}
|
|
<div className="beta-pending-actions">
|
|
<Link className="btn-primary" to="/">Browse the catalog</Link>
|
|
<Link className="btn-link-quiet" to="/philosophy">Read the philosophy →</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|