Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ build or blanks a number.
| File | What | From |
| ------------------------------ | ---------------------------------------------------------------- | ----------------------------------------------------------------- |
| `lib/community.json` | Stars, downloads, contributors, translators, the Verified values | GitHub, Homebrew, Discord, OpenSSF, SonarQube Cloud, `CREDITS.md` |
| `lib/floe-community.json` | The same for Floe, for `/floe/community` | The same sources, for `thaw-app/Floe` |
| `lib/floe-community.json` | The same for Floe, for `/floe` and `/floe/community` | The same sources, for `thaw-app/Floe` |
| `lib/community.json` (`world`) | Stars, issues and pull requests by country | Every stargazer's and author's GitHub profile location |
| `lib/roadmap-issues.json` | Whether each issue the roadmap links is open | GitHub |
| `lib/roadmap-requests.json` | The open feature requests, most thumbs-up first | GitHub |
Expand Down Expand Up @@ -183,7 +183,7 @@ On a touch device the home page's cube redraws twelve times a second.
bun run dev # syncs the docs, then serves http://localhost:3000

By default the sync fetches each repo's default branch from GitHub
(`development` for Thaw, `main` for Floe). To
(`development` for both). To
preview docs you have not pushed, point it at a local checkout in `.env.local`:

THAW_DOCS_DIR=/path/to/Thaw
Expand Down
16 changes: 16 additions & 0 deletions app/(floe)/floe/verified/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Metadata } from 'next';
import { VerifiedView } from '@/components/verified-page';
import { pageAlternates } from '@/lib/releases';

export const metadata: Metadata = {
// One address for the page, whichever domain it was reached on.
alternates: pageAlternates('/floe/verified', '/floe/verified.md'),
openGraph: { images: '/og/site/floeVerified/image.png' },
title: 'What Verified means for Floe',
description:
'What SLSA, the OpenSSF badges, the Scorecard and test coverage are, who vouches for each, and where Floe stands.',
};

export default function FloeVerifiedPage() {
return <VerifiedView product="floe" />;
}
78 changes: 2 additions & 76 deletions app/(home)/verified/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import type { Metadata } from 'next';
import Link from 'next/link';
import { verified } from '@/components/assurance';
import { Lead, PageHeader } from '@/components/page-header';
import { PageShell } from '@/components/page-shell';
import { ResolvingText } from '@/components/resolving-text';
import community from '@/lib/community.json';
import { VerifiedView } from '@/components/verified-page';
import { pageAlternates } from '@/lib/releases';
import { longDate } from '@/lib/shared';
import { sitePages } from '@/lib/site-pages';
import { meanings, readDays, standing } from '@/lib/verified';

export const metadata: Metadata = {
// One address for the page, whichever domain it was reached on.
Expand All @@ -19,72 +11,6 @@ export const metadata: Metadata = {
'What SLSA, the OpenSSF badges, the Scorecard and test coverage are, who vouches for each, and where Thaw stands.',
};

const read = readDays(community.readOn, {
bestPractices: 'The Best Practices badge',
baseline: 'The Baseline level',
scorecard: 'The Scorecard',
coverage: 'Test coverage',
field: 'The count of projects on OpenSSF’s list',
});

/**
* The page behind "What does this mean?" on the home page: each thing in the
* Verified row, what it is, where Thaw stands on it today, and who says so.
*/
export default function VerifiedPage() {
return (
<PageShell>
<PageHeader {...sitePages.verified} labelHref="/#verified">
<Lead>
Thaw asks for permissions that reach across your Mac. These are the outside checks on how
it is built and released: what each one is, and who vouches for it. A score a machine
gives is not the same as a checklist a project fills in, so each says which it is.{' '}
{standing(community.assurance)}
</Lead>
</PageHeader>

<dl className="border-t">
{meanings.map((entry) => {
// Matched by what it is: a value that could not be read is missing from the list.
const now = verified.find((value) => value.id === entry.id);
return (
<div
key={entry.term}
className="grid gap-x-10 gap-y-3 border-b py-8 sm:grid-cols-[14rem_minmax(0,1fr)]"
>
<dt className="flex flex-col gap-1">
<span className="text-sm text-fd-muted-foreground">{entry.term}</span>
{now && (
<span className="font-display text-3xl leading-tight font-semibold tracking-tight">
<ResolvingText>{now.value}</ResolvingText>
</span>
)}
</dt>
<dd className="flex max-w-2xl flex-col gap-3">
<p className="text-pretty">{entry.meaning}</p>
<p className="text-fd-muted-foreground text-pretty">
<span className="text-fd-foreground">Who says so.</span> {entry.checkedBy}
</p>
<p>
<a href={entry.href} className="tap link">
{new URL(entry.href).hostname.replace(/^www\./, '')}
</a>
</p>
</dd>
</div>
);
})}
</dl>

<p className="text-sm text-fd-muted-foreground">
{read.day && `Values read on ${longDate(read.day)}. `}
{read.older.map((entry) => `${entry.name} is from ${longDate(entry.day)}. `)}
The SLSA level is the one Thaw’s release pipeline is built to.{' '}
<Link href="/docs/thaw/verifying-releases" className="tap link">
How to verify a release yourself
</Link>
.
</p>
</PageShell>
);
return <VerifiedView product="thaw" />;
}
1 change: 1 addition & 0 deletions app/sitemap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
['/floe', newest.floe],
['/floe/roadmap', newest.floe],
['/floe/community', Object.values(floeCommunity.readOn).sort().at(-1)],
['/floe/verified', Object.values(floeCommunity.readOn).sort().at(-1)],
['/community', read],
['/verified', read],
['/faq', undefined],
Expand Down
60 changes: 41 additions & 19 deletions components/assurance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,39 @@ import Link from 'next/link';
import { ResolvingText } from '@/components/resolving-text';
import community from '@/lib/community.json';
import { compact } from '@/lib/shared';
import { verifiedFrom } from '@/lib/verified';

const { assurance } = community;
import { type Verified, verifiedFrom } from '@/lib/verified';

// What outside bodies have verified about how Thaw is built and released.
export const verified = verifiedFrom(assurance);

const stepped = verified.length === 5;
export const verified = verifiedFrom(community.assurance);

const numbers = [
{ value: community.stars, label: 'GitHub stars' },
{ value: community.downloads, label: 'downloads' },
{ value: community.contributors, label: 'contributors' },
{ value: community.releases, label: 'releases' },
].filter((entry) => typeof entry.value === 'number');
/** The counts from a product's community file that sit under its values. */
export const countsFrom = (
counts: Record<'stars' | 'downloads' | 'contributors' | 'releases', number>,
) =>
[
{ value: counts.stars, label: 'GitHub stars' },
{ value: counts.downloads, label: 'downloads' },
{ value: counts.contributors, label: 'contributors' },
{ value: counts.releases, label: 'releases' },
].filter((entry) => typeof entry.value === 'number');

/**
* How the project is run, small enough to read in passing: what has been independently
* verified about its releases, and how many people use and build it. /verified explains
* each one.
* How a project is run, small enough to read in passing: what has been independently
* verified about its releases, and how many people use and build it. Its Verified page
* explains each one.
*/
export function Assurance() {
export function VerifiedBlock({
values,
numbers,
communityHref,
meaningsHref,
}: {
values: Verified[];
numbers: ReturnType<typeof countsFrom>;
communityHref: string;
meaningsHref: string;
}) {
const stepped = values.length === 5;
return (
<>
<Heading as="h2" id="verified">
Expand All @@ -36,7 +47,7 @@ export function Assurance() {
<ul
className={`crossed ${stepped ? 'grid-cols-6 sm:grid-cols-5' : 'grid-cols-2 sm:grid-cols-4'}`}
>
{verified.map((entry, index) => (
{values.map((entry, index) => (
<li
key={entry.id}
className={stepped ? `${index < 2 ? 'col-span-3' : 'col-span-2'} sm:col-span-1` : ''}
Expand Down Expand Up @@ -83,14 +94,25 @@ export function Assurance() {
))}
</p>
<p className="mt-2 flex flex-wrap gap-x-6 gap-y-2 text-sm">
<Link href="/verified" className="tap link">
<Link href={meaningsHref} className="tap link">
What does this mean?
</Link>
<Link href="/community" className="tap link">
<Link href={communityHref} className="tap link">
Community
</Link>
</p>
</div>
</>
);
}

export function Assurance() {
return (
<VerifiedBlock
values={verified}
numbers={countsFrom(community)}
communityHref="/community"
meaningsHref="/verified"
/>
);
}
45 changes: 10 additions & 35 deletions components/floe-parts.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Heading } from 'fumadocs-ui/components/heading';
import { Download } from 'lucide-react';
import Link from 'next/link';
import { countsFrom, VerifiedBlock } from '@/components/assurance';
import { FeatureCells, MarkRow, NameGroups, WorksWith } from '@/components/feature-list';
import { InstallFacts } from '@/components/install-facts';
import { SectionLabel } from '@/components/section-label';
import community from '@/lib/floe-community.json';
import {
floeAlso,
floeAskAi,
Expand All @@ -14,6 +15,7 @@ import {
} from '@/lib/floe-features';
import { latestStable } from '@/lib/releases';
import { docsRoute } from '@/lib/shared';
import { verifiedFrom } from '@/lib/verified';

/** How to get Floe: one download, set out as Thaw's install box is (install-tabs.tsx). */
export function FloeInstall() {
Expand Down Expand Up @@ -71,41 +73,14 @@ export function FloeFeatures() {
);
}

/**
* Where Thaw's page has its Verified values, Floe's says they are on the way: Floe is early
* and has none of its own to show yet.
*/
/** Floe's own Verified values, read by the same sync as Thaw's. */
export function FloeAssurance() {
return (
<>
<Heading as="h2" id="verified">
Verified
</Heading>
<div className="not-prose my-6">
<p className="mb-3 font-display text-2xl leading-tight font-semibold tracking-tight text-balance sm:text-3xl">
Part of the way.
</p>
<p className="mb-6 text-fd-muted-foreground text-pretty">
Floe is signed and notarised, each release comes with a record of how it was built, and
the project has an{' '}
<a
href="https://scorecard.dev/viewer/?uri=github.com/thaw-app/Floe"
className="tap text-fd-foreground link"
>
OpenSSF Scorecard
</a>
. Thaw’s other checks, such as its OpenSSF Best Practices badge, are still to come.
</p>
<Link
href="/#verified"
className="tap press flex items-center justify-between gap-x-6 gap-y-1 border px-5 py-3 font-medium transition-colors hover:bg-fd-accent max-sm:flex-col max-sm:items-start"
>
See where Thaw stands
<span aria-hidden className="text-fd-muted-foreground">
SLSA, OpenSSF and test coverage
</span>
</Link>
</div>
</>
<VerifiedBlock
values={verifiedFrom(community.assurance, 'floe')}
numbers={countsFrom(community)}
communityHref="/floe/community"
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Resolved
meaningsHref="/floe/verified"
/>
);
}
2 changes: 2 additions & 0 deletions components/site-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ const feet: Record<ProductSlug, Foot> = {
{ text: 'What Floe does not do yet', href: `${floeDocs}/limitations` },
{ text: 'Developing Floe', href: `${floeDocs}/development` },
{ text: 'Security policy', href: `${floeDocs}/security` },
{ text: 'Verifying releases', href: `${floeDocs}/verifying-releases` },
{ text: 'What Verified means', href: '/floe/verified' },
],
},
{
Expand Down
Loading
Loading