Merge remote-tracking branch 'origin/master' into openniche-coupon-recipe

# Conflicts:
#	apps/logicsrc-web/src/app/llms.txt/route.ts
#	apps/logicsrc-web/src/app/sitemap.ts
#	apps/logicsrc-web/src/components/site-shell.tsx
#	apps/logicsrc-web/src/lib/docs.ts
This commit is contained in:
Anthony Ettinger 2026-09-13 02:11:57 +00:00
commit 271b00f137
18 changed files with 1682 additions and 0 deletions

View file

@ -24,6 +24,12 @@ export function GET(): Response {
- [OpenMCP](${SITE_URL}/openmcp): An open catalog of MCP relays: a relay serves /.well-known/openmcp.json, a catalog probes it and lists only what it found, and clients reach every relay through the catalog's REST, its own MCP endpoint, or signed webhooks.
- [OpenAccess](${SITE_URL}/openaccess): OAuth 2.1 with a grant you can carry: one hub account per person or agent, apps keep their own users and link them once, grants delegate narrower to agents, and a subscription bought in one app is honoured by every app that honours the product. Reference hub at openaccess.logicsrc.com.
- [OpenServer](${SITE_URL}/openserver): One file a hosting provider serves about what it sells, at /.well-known/openserver.json: every offer with kind (cloud, vps, dedicated, bare-metal, colocation, on-prem, shared, managed, paas, serverless, storage, gpu, edge, p2p, hybrid), the premises, management, tenancy and model axes, specs, one price, location and stock. Directories read the provider instead of scraping; first reader is nichedb.dev/c/hosting.
- [OpenCPU](${SITE_URL}/opencpu): The compute block of an OpenServer offer: threads against cores, the processor by its vendor name, dedicated, shared or burstable allocation, and a range that says what a buyer can add at checkout and for how much.
- [OpenMemory](${SITE_URL}/openmemory): The memory block of an OpenServer offer: RAM in mebibytes, DDR generation, ECC as three states, reserved or balloonable allocation, and a range priced per step.
- [OpenGPU](${SITE_URL}/opengpu): The gpu block of an OpenServer offer: the card by its vendor name, count and VRAM per device, interconnect, passthrough, MIG, vGPU or shared access, and a range over count.
- [OpenBandwidth](${SITE_URL}/openbandwidth): The network block of an OpenServer offer: port speed, transfer, unmetered, 95th percentile or flat metering, overage, IPv4 and IPv6 addresses as a priced resource, DDoS scrubbing, and a range.
- [OpenFile](${SITE_URL}/openfile): One file a publisher serves about the files it has published: content hash, swarm and HTTP fetch routes, verification, consent basis, price, and who holds it now, discovered at /.well-known/openfile.json. The web door onto an OpenSwarm ipfile swarm.
- [OpenDisk](${SITE_URL}/opendisk): One file a machine serves about the disk it will rent: free GiB, price per GiB-month, location, policy, proof cadence and hub standing, discovered at /.well-known/opendisk.json. What a peer-to-peer storage market is made of; reference marketplace d1sks.com.
- [OpenCoupon](${SITE_URL}/opencoupon): One file a merchant serves about what is on offer right now, at /.well-known/opencoupon.json: every code, sale and shipping threshold with kind, value, scope, dates, status and regions, expired codes kept so directories learn they died. A coupon site reads the merchant instead of a forum thread.
- [OpenRecipe.md](${SITE_URL}/openrecipe): One Markdown file that is a recipe: summary block (Serves, Prep, Cook, Cuisine, Diet, Author, Source), ingredients and steps as written, notes, nutrition; served next to the page or linked with rel="openrecipe"; schema.org/Recipe JSON-LD is derived from it, never the reverse.
- [AgentSwarm](${SITE_URL}/agent-swarm): Provider-neutral agent orchestration, model routing, and cost controls.

View file

@ -0,0 +1,63 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { ResourceSpecPage, type ResourceSpec } from "@/components/resource-spec-page";
export const metadata: Metadata = {
title: "OpenBandwidth · LogicSRC",
description:
"OpenBandwidth is the network block of an OpenServer offer: port speed, how traffic is metered (transfer, unmetered, 95th percentile, flat), what overage costs, IPv4 and IPv6 addresses as a priced resource, DDoS scrubbing, and a range that says what a buyer can add at checkout and for how much.",
alternates: { canonical: "/openbandwidth" }
};
const SPEC: ResourceSpec = {
name: "OpenBandwidth",
slug: "openbandwidth",
block: "network",
tagline:
"The network line of a server purchase, with the words fixed: the port, the meter, the overage, the addresses, and what more of any of them costs.",
problem:
"Unmetered 1 Gbps, 1 Gbps with 20 TB, and 1 Gbps at the 95th percentile with 100 Mbps committed are three products that every comparison site shows as 1 Gbps. The surprise on the invoice is always the network line: overage at a cent a gigabyte here and nine there, ingress free or billed, a second IPv4 address at two a month or unavailable at any price. IPv4 is now a market of its own, leased by the /24, and no catalog format has a place for it.",
sample: `{
"network": {
"bandwidth_mbps": 1000,
"metering": "transfer",
"transfer_gb": 20000,
"counts": "egress",
"overage": { "amount": 0.01, "currency": "USD", "per_gb": 1 },
"ipv4": 1,
"ipv4_price": { "amount": 2, "currency": "USD", "interval": "month", "per": 1 },
"ipv4_max": 8,
"ipv6": "/64",
"ddos": "always-on",
"range": {
"key": "bandwidth_mbps", "min": 1000, "max": 10000, "step": 1000,
"price": { "amount": 15, "currency": "USD", "interval": "month", "per": 1000 }
}
}
}`,
smallest: `{ "network": { "bandwidth_mbps": 1000 } }`,
fields: [
["bandwidth_mbps", "integer, required", "The port speed sold. A shaped link states the shaped rate."],
["metering", "transfer, unmetered, percentile, flat", "Gigabytes against transfer_gb, no cap, 95th percentile with commit_mbps, or a fixed price for the port."],
["transfer_gb, counts", "integer per interval; egress, ingress, both, max", "Included traffic and which direction counts. A reader never assumes egress."],
["overage, over_cap", "amount, currency, per_gb or per_mbps; bill, throttle, suspend", "What traffic past the cap costs, or what happens instead."],
["ipv4, ipv4_price, ipv4_max, ipv6", "integer; price per address; integer; boolean or prefix", "Addresses as a resource: included, the price of more, the ceiling, and the IPv6 assignment."],
["ddos, private_network, uplinks", "always-on, on-demand, none; boolean; integer", "That mitigation exists, a private LAN, physical links on a dedicated box."],
["range", "key bandwidth_mbps, transfer_gb or ipv4; min, max, step, price", "What the buyer can dial and what a step costs."]
],
directory: [
["Meter beside the port", "1 Gbps unmetered and 1 Gbps with 20 TB are two rows with two words."],
["Price a month of traffic", "Base plus overage at a stated volume, with the volume shown."],
["Addresses as a resource", "Included count, price of more, ceiling. Zero with no price is unstated, not free."],
["Never assume direction", "A cap with no counts is a cap with the direction unstated."]
],
absent: [
["No speed test", "bandwidth_mbps is the port sold. Achieved throughput is a measurement."],
["No carriers or peering", "Upstreams and exchanges are the provider's network page. An ASN goes under the provider's own key."],
["No SLA", "Uptime percentages and credits are the provider's terms, linked from the offer's url."]
]
};
export default function OpenBandwidthPage(): ReactNode {
return <ResourceSpecPage spec={SPEC} />;
}

View file

@ -0,0 +1,61 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { ResourceSpecPage, type ResourceSpec } from "@/components/resource-spec-page";
export const metadata: Metadata = {
title: "OpenCPU · LogicSRC",
description:
"OpenCPU is the compute block of an OpenServer offer: threads against cores, the processor by its vendor name, dedicated, shared or burstable allocation, and a range that says how many more a buyer can add at checkout and for how much.",
alternates: { canonical: "/opencpu" }
};
const SPEC: ResourceSpec = {
name: "OpenCPU",
slug: "opencpu",
block: "compute",
tagline:
"The processor line of a server purchase, with the words fixed: threads or cores, whose they are, and what one more costs.",
problem:
"Four vCPU on one pricing page is four hyperthreads of a shared socket, throttled at a fifth of sustained load. On the next it is four dedicated cores with the boost clock quoted. A comparison site sorts both on the number four, and the buyer who wanted the second pays for the first. A configurator that offers three processors at three prices keeps that choice in a form where no reader can see it.",
sample: `{
"compute": {
"vcpu": 4,
"cores": 2,
"threads_per_core": 2,
"arch": "x86_64",
"model": "AMD EPYC 9354",
"vendor": "AMD",
"base_ghz": 3.25,
"boost_ghz": 3.75,
"allocation": "dedicated",
"range": {
"key": "vcpu", "min": 2, "max": 32, "step": 2,
"price": { "amount": 4, "currency": "USD", "interval": "month", "per": 1 }
}
}
}`,
smallest: `{ "compute": { "vcpu": 4 } }`,
fields: [
["vcpu / cores", "integer, one required", "Threads sold to the guest, or physical cores. threads_per_core relates them; a reader never derives one from the other without it."],
["arch", "x86_64, arm64, riscv64, or the provider's word", "Absent means unstated, not x86."],
["model, vendor", "the vendor's own name", "AMD EPYC 9354, Ampere Altra Max. Kept verbatim so a buyer can look it up."],
["base_ghz, boost_ghz, sockets", "decimal GHz, integer", "The vendor's figures, not a measurement."],
["allocation", "dedicated, shared, burstable", "Reserved for the buyer, oversubscribed, or shared with a credit balance (credits_per_hour, baseline_pct)."],
["range", "key, min, max, step, price", "What the buyer can dial at checkout and what each step costs on top of the base price."]
],
directory: [
["Two columns", "vcpu and cores are sorted separately; a row with neither is listed and marked unstated."],
["Allocation beside the count", "Four dedicated threads and four shared ones are different products at the same number."],
["Price the range", "Base price plus the per-step price, so 8 vCPU reads as base plus four steps."],
["Keep the model string", "Normalise for search, display the vendor's spelling."]
],
absent: [
["No benchmarks", "Clock figures are the vendor's. A measured score is another document's business."],
["No instruction-set flags", "AVX-512, SVE and the rest: look up model. A provider that wants them states them under its own key."],
["No scheduling guarantees", "Pinning, NUMA and latency are the provider's terms, linked from the offer's url."]
]
};
export default function OpenCpuPage(): ReactNode {
return <ResourceSpecPage spec={SPEC} />;
}

View file

@ -0,0 +1,195 @@
import Link from "next/link";
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { SiteShell } from "@/components/site-shell";
import { mono, pre, table, td, th } from "../openontology/ui";
export const metadata: Metadata = {
title: "OpenDisk · LogicSRC",
description:
"OpenDisk is one file a machine serves about the disk it will rent: free GiB, price per GiB-month, location, policy, proof cadence and hub standing, at /.well-known/opendisk.json. What a peer-to-peer storage market is made of. Reference marketplace d1sks.com.",
alternates: { canonical: "/opendisk" }
};
const DESCRIPTOR = `{
"name": "seeder-a41e, Falkenstein",
"operator": "https://seeder-a41e.example/.well-known/openprofile.md",
"key": "ed25519:a41e…7b0a",
"hubs": ["https://bittorrented.com/api/openswarm", "https://d1sks.com/api/openswarm"],
"capacity": { "total_gib": 3726, "free_gib": 2210 },
"price": { "currency": "USD", "per_gib_month": 0.12, "per_gib_transfer": 0.004, "max_gib": 2000, "max_days": 365 },
"location": { "regions": ["fsn1"], "countries": ["DE"] },
"network": { "bandwidth_mbps": 1000, "transfer_gb": 20000 },
"accepts": { "visibility": ["private", "public"], "encrypted_only": false, "max_file_gib": 500 },
"proof": { "kinds": ["challenge", "probe"], "every_hours_min": 6 },
"record": { "source": "https://bittorrented.com/api/openswarm/pay2seed/seeders/ed25519:a41e…7b0a", "standing": 412 },
"payout": { "payee": "ed25519:a41e…7b0a", "network": "eip155:8453" }
}`;
const MINIMAL = `{ "name": "spare drive, Lisbon", "capacity": { "free_gib": 900 },
"price": { "currency": "USD", "per_gib_month": 0.08 } }`;
const RENT: Array<[string, string]> = [
["1. Read", "The descriptor for policy and price, and record.source at the hub for standing."],
["2. Attest", "The consent record pay2seed requires, with README.md at the root of the swarm."],
["3. Offer", "A pay2seed offer at one of the disk's hubs, at or above per_gib_month, with the budget escrowed."],
["4. Lease", "The disk's seeder client takes it on its next poll, or at once when the hub pushes to proof.webhook."],
["5. Prove", "Challenges and probes every period, receipts per proven period, payout to the payee. All paid2seed, unchanged."]
];
const MAPPING: Array<[string, string]> = [
["offers[].kind", "storage"],
["offers[].model", "p2p for a peer, centralized for a provider; the disk may say"],
["offers[].price", "{ amount: per_gib_month, currency, interval: month, unit: gib }"],
["offers[].stock", "in_stock while free_gib covers min_gib"],
["location, network, storage", "the same keys, the same units"]
];
const ABSENT: Array<[string, string]> = [
["No lease in this file", "The descriptor is the ask, the offer is the bid, the lease is the match, made at the hub as paid2seed says."],
["No escrow at the disk", "Money sits at a hub. A disk never holds a requester's funds."],
["No reputation of its own", "record is a copy of what a hub signed. A marketplace reads the hub, and lists the hub's number."],
["No plaintext", "By default a disk holds ipfile ciphertext it cannot read, and a personal swarm's existence is not in its public list."],
["No central registry", "Anyone may serve a descriptor and anyone may read it. Two marketplaces reading the same file list the same disk."]
];
export default function OpenDiskPage(): ReactNode {
return (
<SiteShell active="OpenDisk">
<div className="band">
<div className="section-head">
<p className="eyebrow">LogicSRC standards surface</p>
<h2>OpenDisk</h2>
<p>
One file a machine serves about the disk it will rent, so a disk can be found instead of
waited for, and a peer with a spare terabyte is on the market by putting a file at a URL.
</p>
</div>
<p style={{ color: "#41505d" }}>
<Link href="/openswarm">OpenSwarm</Link> already says how a seeder is paid to hold a swarm:
an offer with money escrowed, a lease, a storage proof every period, a payout per
GiB-month. What it does not say is how a requester finds a seeder before posting. The
market is one-sided: offers are listed and seeders poll them. OpenDisk is the other side.
A disk puts its free space, price, location, policy, proof cadence and hub standing at{" "}
<code style={mono}>/.well-known/opendisk.json</code>, and a requester reads the disk
before it posts.
</p>
<p style={{ color: "#5b6b7a" }}>
Status: 0.1. <a href="https://d1sks.com">d1sks.com</a> is the reference marketplace: every
descriptor it has read, standing pulled from the hubs each disk names, and an offer form that
posts to the disk&apos;s hub. Every disk is also a hosting offer in the{" "}
<Link href="/openserver">OpenServer</Link> sense, listed as one at nichedb.dev.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>The descriptor</h2>
<p>
Served at <code style={mono}>/.well-known/opendisk.json</code>. Only a name, the free
space and a price are required.
</p>
</div>
<pre style={pre}>{DESCRIPTOR}</pre>
<p style={{ color: "#41505d" }}>
<code style={mono}>key</code> is the seeder identity that signs proofs and is paid;{" "}
<code style={mono}>hubs</code> is where it takes leases. <code style={mono}>accepts</code>{" "}
is the operator&apos;s policy stated up front, so nobody posts an offer this disk would never
take. <code style={mono}>record.source</code> is the hub&apos;s own page for this seeder,
and a marketplace reads the hub, not the file, for anything it ranks on. The smallest valid
descriptor:
</p>
<pre style={pre}>{MINIMAL}</pre>
</div>
<div className="band">
<div className="section-head">
<h2>Renting a disk</h2>
<p>Nothing on the swarm side changes. The descriptor only moves the first step to a URL.</p>
</div>
<table style={table}>
<tbody>
{RENT.map(([step, what]) => (
<tr key={step}>
<td style={td}>
<strong>{step}</strong>
</td>
<td style={td}>{what}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>As an OpenServer offer</h2>
<p>A disk is a hosting offer, and a directory that reads OpenServer lists it without a second parser.</p>
</div>
<table style={table}>
<thead>
<tr>
<th style={th}>OpenServer</th>
<th style={th}>from OpenDisk</th>
</tr>
</thead>
<tbody>
{MAPPING.map(([key, from]) => (
<tr key={key}>
<td style={td}>
<code style={mono}>{key}</code>
</td>
<td style={td}>{from}</td>
</tr>
))}
</tbody>
</table>
<p style={{ color: "#41505d", marginTop: "1rem" }}>
A provider that sells storage plans and rents disk to swarms serves both files. A peer with
one drive serves only this one, and is listed in both places.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>What is deliberately absent</h2>
</div>
<table style={table}>
<tbody>
{ABSENT.map(([what, why]) => (
<tr key={what}>
<td style={td}>
<strong>{what}</strong>
</td>
<td style={td}>{why}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>Where everything lives</h2>
</div>
<ul style={{ color: "#41505d", lineHeight: 1.9, paddingLeft: "1.1rem" }}>
<li>
<Link href="/docs/opendisk">Specification</Link>: the descriptor, holding, renting a disk,
marketplaces, the OpenServer mapping
</li>
<li>
<a href="https://d1sks.com">d1sks.com</a>: the reference marketplace
</li>
<li>
<Link href="/openswarm">OpenSwarm</Link>: pay2seed for the offer, paid2seed for leases and
proofs, ippay for the payee, ipfile for what is held
</li>
<li>
<Link href="/openfile">OpenFile</Link>, the publisher&apos;s side and the holders list a disk
appears in; <Link href="/openserver">OpenServer</Link>, the hosting offer a disk maps onto
</li>
</ul>
</div>
</SiteShell>
);
}

View file

@ -0,0 +1,220 @@
import Link from "next/link";
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { SiteShell } from "@/components/site-shell";
import { mono, pre, table, td, th } from "../openontology/ui";
export const metadata: Metadata = {
title: "OpenFile · LogicSRC",
description:
"OpenFile is one file a publisher serves about the files it has published: content hash, swarm and HTTP fetch routes, verification, consent basis, price, and who holds it now, at /.well-known/openfile.json. The web door onto an OpenSwarm ipfile swarm.",
alternates: { canonical: "/openfile" }
};
const DESCRIPTOR = `{
"publisher": {
"name": "Dartmoor Field Recordings",
"operator": "https://dartmoor.example/.well-known/openprofile.md",
"key": "ed25519:5d29…d59e",
"hubs": ["https://bittorrented.com/api/openswarm"]
},
"files": [{
"id": "sha256:d6c3…93ff",
"name": "interview-2026-09-05.flac",
"size": 734003200,
"swarm": { "file": "ed25519:0d87…295d", "infohashV2": "sha256:4b74…a342" },
"encryption": "ipfile",
"fetch": [
{ "kind": "ipfile", "url": "magnet:?xs=urn:btpk:0d87…295d&s=ipfile" },
{ "kind": "http", "url": "https://gw.c0mpute.com/file/d6c3…93ff" },
{ "kind": "hls", "url": "https://gw.c0mpute.com/file/d6c3…93ff/index.m3u8" }
],
"attestation": { "basis": "own", "license": "CC-BY-4.0" },
"price": { "amount": 0.5, "currency": "USD", "per": "key", "offer": "https://keys.dartmoor.example/…" },
"holders": "https://bittorrented.com/api/openswarm/files/d6c3…93ff/holders"
}]
}`;
const MINIMAL = `{ "publisher": { "name": "Dartmoor Field Recordings" },
"files": [{ "id": "sha256:d6c3…93ff", "name": "interview-2026-09-05.flac" }] }`;
const FETCH: Array<[string, string, string]> = [
["ipfile", "a magnet for an OpenSwarm client", "encrypted pieces, paid per piece, the key on a pass"],
["magnet", "a vanilla magnet", "the ciphertext, for a client that cannot pay"],
["webseed", "BEP 19, ciphertext by range", "a gateway standing in for peers"],
["http", "the plaintext by range from a gateway", "a browser with nothing installed, behind a pass when there is a price"],
["hls", "a media file as a standard playlist", "any player, sealed when there is a price"]
];
const REUSED: Array<[string, string]> = [
["The swarm and the manifest", "ipfile: the file key, both infohashes, plainRoot as the content hash, the plaintext piece layer"],
["Consent and the README", "pay2seed: the attestation record, its basis and licence, the notice endpoint, README.md at the root"],
["Who holds it", "paid2seed: leases and the proofs behind provenAt"],
["Payment", "ippay: a pass bought over x402, presented as a bearer token on the gateway"],
["The feed", "ipdb: the same catalogue, replicated between peers, for a reader that speaks the swarm"]
];
const ABSENT: Array<[string, string]> = [
["No new swarm format", "The swarm is ipfile, the consent is pay2seed's, the payment is ippay's. This is a JSON door onto records that already exist."],
["No search", "A descriptor lists one publisher's files. Finding a file across publishers is a directory's job."],
["No trust score", "verified says where the file came from and who signed the manifest. basis is what the publisher claimed. The rest is the reader's judgement."],
["No DRM", "A pass holder gets the key and the bytes, as ipfile says."]
];
export default function OpenFilePage(): ReactNode {
return (
<SiteShell active="OpenFile">
<div className="band">
<div className="section-head">
<p className="eyebrow">LogicSRC standards surface</p>
<h2>OpenFile</h2>
<p>
One file a publisher serves about the files it has published, so a file can be found
instead of crawled, and fetched by a browser that has never heard of a swarm.
</p>
</div>
<p style={{ color: "#41505d" }}>
A file on a swarm is findable by its infohash and by nothing else. <Link href="/openswarm">OpenSwarm</Link>{" "}
fixed the inside of the swarm: a signed manifest, encrypted pieces, consent at upload, a
replicated catalogue. What none of that gives a person with a browser, a search engine or a
directory is a URL to start from. OpenFile puts a publisher&apos;s catalogue at{" "}
<code style={mono}>/.well-known/openfile.json</code>, with a content hash to verify
against, every way to fetch the bytes, the basis it was published on, the price, and who is
holding it right now.
</p>
<p style={{ color: "#5b6b7a" }}>
Status: 0.1. The reference reader is bittorrented.com, which lists consented swarms beside
the bare infohashes of its DHT crawl, with the README as the page. A product for it is
planned under a name not yet chosen.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>The descriptor</h2>
<p>
Served at <code style={mono}>/.well-known/openfile.json</code>. Only the publisher&apos;s
name and each file&apos;s content hash and name are required.
</p>
</div>
<pre style={pre}>{DESCRIPTOR}</pre>
<p style={{ color: "#41505d" }}>
<code style={mono}>id</code> is the SHA-256 of the plaintext, which for an ipfile swarm is
the manifest&apos;s <code style={mono}>plainRoot</code>: the same root the decrypted file
verifies against. Two publishers serving the same bytes list the same id, and a directory
has one file with two listings. <code style={mono}>encryption</code> is ipfile unless the
publisher says <code style={mono}>none</code> as an explicit act. The smallest valid
descriptor:
</p>
<pre style={pre}>{MINIMAL}</pre>
</div>
<div className="band">
<div className="section-head">
<h2>Five ways to fetch</h2>
<p>Listed in the publisher&apos;s order of preference. A reader picks the first kind it speaks.</p>
</div>
<table style={table}>
<thead>
<tr>
<th style={th}>kind</th>
<th style={th}>What it is</th>
<th style={th}>Who uses it</th>
</tr>
</thead>
<tbody>
{FETCH.map(([kind, what, who]) => (
<tr key={kind}>
<td style={td}>
<code style={mono}>{kind}</code>
</td>
<td style={td}>{what}</td>
<td style={td}>{who}</td>
</tr>
))}
</tbody>
</table>
<p style={{ color: "#41505d", marginTop: "1rem" }}>
Over any of them the bytes verify the same way: each piece against the plaintext piece
layer, or the whole against <code style={mono}>id</code>. A reader refuses bytes that fail
and says which holder served them.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>Holders</h2>
<p>A file is only as available as the machines holding it.</p>
</div>
<p style={{ color: "#41505d" }}>
<code style={mono}>holders</code> answers with who has the bytes now: a{" "}
<code style={mono}>seeder</code> with a lease and the time it last passed a proof, a{" "}
<code style={mono}>gateway</code> serving it over HTTP, a <code style={mono}>peer</code>{" "}
merely seen. Each carries its age, and a seeder&apos;s lease can be checked at the hub.
A holder that rents disk links its own <Link href="/opendisk">OpenDisk</Link> descriptor, so a
publisher that likes a holder can buy more of it.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>What is reused</h2>
<p>Every record OpenFile points at already has a name in the OpenSwarm family.</p>
</div>
<table style={table}>
<tbody>
{REUSED.map(([what, from]) => (
<tr key={what}>
<td style={td}>
<strong>{what}</strong>
</td>
<td style={td}>{from}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>What is deliberately absent</h2>
</div>
<table style={table}>
<tbody>
{ABSENT.map(([what, why]) => (
<tr key={what}>
<td style={td}>
<strong>{what}</strong>
</td>
<td style={td}>{why}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>Where everything lives</h2>
</div>
<ul style={{ color: "#41505d", lineHeight: 1.9, paddingLeft: "1.1rem" }}>
<li>
<Link href="/docs/openfile">Specification</Link>: the descriptor, the per-file descriptor,
holders, discovery, fetching and verifying, what a directory owes a publisher
</li>
<li>
<Link href="/openswarm">OpenSwarm</Link>: ipfile, pay2seed, paid2seed, ippay and ipdb,
the records this file is a door onto
</li>
<li>
<Link href="/opendisk">OpenDisk</Link>, what a holder serves about the disk it rents;{" "}
<Link href="/openserver">OpenServer</Link>, how a gateway or seeder is listed as hosting
</li>
<li>
<Link href="/openprofile">OpenProfile.md</Link>, the operator behind a publisher
</li>
</ul>
</div>
</SiteShell>
);
}

View file

@ -0,0 +1,61 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { ResourceSpecPage, type ResourceSpec } from "@/components/resource-spec-page";
export const metadata: Metadata = {
title: "OpenGPU · LogicSRC",
description:
"OpenGPU is the gpu block of an OpenServer offer: the card by its vendor name, count and VRAM per device, the interconnect between them, passthrough, MIG, vGPU or shared access, and a range that says how many more a buyer can add at checkout and for how much.",
alternates: { canonical: "/opengpu" }
};
const SPEC: ResourceSpec = {
name: "OpenGPU",
slug: "opengpu",
block: "gpu",
tagline:
"The accelerator line of a server purchase, with the words fixed: which card, how many, how much memory, how they are joined, whole or a slice, and what one more costs.",
problem:
"The same card is sold whole, as a MIG slice, as a time-shared vGPU and as a peer's idle desktop, at prices an order of magnitude apart, and a listing that says one A100 has said almost nothing: 40 or 80 GB, PCIe or SXM, NVLinked or not. The peer markets move by the minute and publish their own schemas. A buyer's agent asked for two 80 GB cards with NVLink under 4 an hour reads six catalogs six ways.",
sample: `{
"gpu": {
"model": "NVIDIA H100 SXM",
"vendor": "NVIDIA",
"count": 8,
"vram_mb": 81920,
"arch": "Hopper",
"interconnect": "nvlink",
"access": "passthrough",
"driver": "550",
"runtime": "CUDA 12.4",
"range": {
"key": "count", "min": 1, "max": 8, "step": 1,
"price": { "amount": 2.49, "currency": "USD", "interval": "hour", "per": 1 }
}
}
}`,
smallest: `{ "gpu": { "model": "NVIDIA RTX 4090" } }`,
fields: [
["model, vendor, arch", "the vendor's own name, required", "Including the form factor when the vendor distinguishes one: H100 SXM and H100 PCIe are two models."],
["count, vram_mb", "integer; mebibytes per device", "80 GB is 81920. A reader multiplies for the total and never assumes the provider did."],
["interconnect", "nvlink, nvswitch, infinity-fabric, pcie, none", "How the devices in one offer are joined. A single card states nothing."],
["access", "passthrough, mig, vgpu, shared", "The whole device, a hardware partition (profile or fraction), a virtualised share, or time-sliced with neighbours."],
["driver, runtime", "version strings", "What the provider installs by default; absent means the buyer installs their own."],
["range", "key count, min, max, step, price", "One offer per model; the range is over how many."]
],
directory: [
["Keep the model, match beside it", "NVIDIA H100 SXM and H100-SXM5-80GB are one card for search and two spellings on the page."],
["Access beside VRAM", "A MIG slice and a whole card share a model and differ in everything else."],
["Per-device price", "Computed from price and count so a row of eight and a row of one sort together, and labelled as computed."],
["Stock with its timestamp", "GPU stock goes stale first; every row says when it was read."]
],
absent: [
["No TFLOPS", "Vendor throughput depends on precision, sparsity and clock, and no two vendors quote it alike."],
["No reservation calendar", "Whether a card is free next Tuesday is the provider's scheduler. stock says now."],
["No spot flag", "A card at a spot price is a second offer; price.commitment and the url carry the terms."]
]
};
export default function OpenGpuPage(): ReactNode {
return <ResourceSpecPage spec={SPEC} />;
}

View file

@ -0,0 +1,59 @@
import type { ReactNode } from "react";
import type { Metadata } from "next";
import { ResourceSpecPage, type ResourceSpec } from "@/components/resource-spec-page";
export const metadata: Metadata = {
title: "OpenMemory · LogicSRC",
description:
"OpenMemory is the memory block of an OpenServer offer: RAM in mebibytes, DDR generation and speed, ECC as three states, reserved or balloonable allocation, and a range that says how much more a buyer can add at checkout and for how much.",
alternates: { canonical: "/openmemory" }
};
const SPEC: ResourceSpec = {
name: "OpenMemory",
slug: "openmemory",
block: "memory",
tagline:
"The memory line of a server purchase, with the words fixed: how much, what kind, whether it is corrected, whether it is yours, and what a step more costs.",
problem:
"Memory is the resource most often bought in increments and least often described. A configurator offers 64, 128 or 256 GB at three prices and a scraper records the default. Eight gigabytes on a VPS may be reserved or may be reclaimed by the host under pressure. Whether the DIMMs are error-corrected decides whether a database belongs on the machine, and almost no listing says.",
sample: `{
"memory": {
"ram_mb": 65536,
"type": "DDR5",
"ecc": true,
"speed_mts": 4800,
"channels": 8,
"allocation": "reserved",
"hugepages": true,
"range": {
"key": "ram_mb", "min": 32768, "max": 1048576, "step": 32768,
"price": { "amount": 12, "currency": "USD", "interval": "month", "per": 32768 }
}
}
}`,
smallest: `{ "memory": { "ram_mb": 8192 } }`,
fields: [
["ram_mb", "integer mebibytes, required", "What the guest sees. 8 GiB is 8192, the same unit OpenServer uses. Wins over compute.ram_mb when both are present."],
["type, speed_mts, channels", "DDR4, DDR5, LPDDR5, HBM3; MT/s; integer", "The vendor's rating, stated not measured."],
["ecc", "true, false, absent", "Three states. A directory never shows absent as false."],
["allocation", "reserved, balloonable, shared", "Backed and never reclaimed, reclaimable under host pressure, or oversubscribed."],
["swap_mb, hugepages", "integer, boolean", "Swap the provider configures by default; whether huge pages are allowed."],
["range", "key, min, max, step, price", "Memory sold in steps: the example is 32 GiB steps at 12 USD a month each."]
],
directory: [
["Mebibytes as the provider's unit", "Store ram_mb; display GiB or GB as the provider's page does, and say which."],
["ECC as three states", "Yes, no and unstated are three filters."],
["Price the range", "A configurator's three sizes are one offer with a range, shown as base plus step."],
["memory before compute.ram_mb", "Read the block first and never sum the two."]
],
absent: [
["No bandwidth or latency", "speed_mts is the DIMM rating. Measured memory bandwidth is a benchmark."],
["No persistent-memory tier", "Persistent and CXL-attached memory sit under the provider's own key until there is a second provider to agree with."],
["No per-process limits", "cgroup limits on a container platform are the platform's terms, linked from the offer's url."]
]
};
export default function OpenMemoryPage(): ReactNode {
return <ResourceSpecPage spec={SPEC} />;
}

View file

@ -26,6 +26,12 @@ const STATIC_ROUTES: Array<{
{ path: "/openmcp", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openaccess", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openserver", changeFrequency: "weekly", priority: 0.9 },
{ path: "/opencpu", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openmemory", changeFrequency: "weekly", priority: 0.9 },
{ path: "/opengpu", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openbandwidth", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openfile", changeFrequency: "weekly", priority: 0.9 },
{ path: "/opendisk", changeFrequency: "weekly", priority: 0.9 },
{ path: "/opencoupon", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openrecipe", changeFrequency: "weekly", priority: 0.9 },
{ path: "/openontology/explore", changeFrequency: "daily", priority: 0.7 },

View file

@ -0,0 +1,167 @@
import Link from "next/link";
import type { ReactNode } from "react";
import { SiteShell } from "@/components/site-shell";
import { mono, pre, table, td, th } from "../app/openontology/ui";
/**
* One landing page shape for the five OpenServer resource specifications
* (OpenCPU, OpenMemory, OpenDisk, OpenGPU, OpenBandwidth). Each page is
* the same five bands with different words, so the words live in the page
* and the bands live here.
*/
export type ResourceSpec = {
/** Display name, e.g. "OpenCPU". */
name: string;
/** URL slug under /docs and /, e.g. "opencpu". */
slug: string;
/** The block key on an OpenServer offer, e.g. "compute". */
block: string;
/** One line under the title. */
tagline: string;
/** Two or three sentences on why the resource needs its own words. */
problem: ReactNode;
/** The example block, pretty-printed JSON. */
sample: string;
/** The smallest valid block, one line of JSON. */
smallest: string;
/** Field name, values, meaning. */
fields: Array<[string, string, string]>;
/** What a directory does with the block. */
directory: Array<[string, string]>;
/** What is deliberately absent, and why. */
absent: Array<[string, string]>;
};
const SIBLINGS: Array<[string, string]> = [
["OpenCPU", "opencpu"],
["OpenMemory", "openmemory"],
["OpenDisk", "opendisk"],
["OpenGPU", "opengpu"],
["OpenBandwidth", "openbandwidth"]
];
export function ResourceSpecPage({ spec }: { spec: ResourceSpec }): ReactNode {
const wellKnown = `/.well-known/${spec.slug}.json`;
return (
<SiteShell active={spec.name}>
<div className="band">
<div className="section-head">
<p className="eyebrow">LogicSRC standards surface · OpenServer resource</p>
<h2>{spec.name}</h2>
<p>{spec.tagline}</p>
</div>
<p style={{ color: "#41505d" }}>{spec.problem}</p>
<p style={{ color: "#5b6b7a" }}>
Status: 0.1. The <code style={mono}>{spec.block}</code> block of an{" "}
<Link href="/docs/openserver">OpenServer</Link> offer, written down on its own. A provider
that sells only this resource lists it as an offer and may serve the same document at{" "}
<code style={mono}>{wellKnown}</code>. Every rule degrades: the smallest valid block is{" "}
<code style={mono}>{spec.smallest}</code>.
</p>
</div>
<div className="band">
<div className="section-head">
<h2>The {spec.block} block</h2>
<p>
Every key is the provider&apos;s claim, in fixed units. <code style={mono}>range</code>{" "}
is the part a buyer can dial at checkout: the field, its bounds, the step and what a
step costs.
</p>
</div>
<pre style={pre}>{spec.sample}</pre>
</div>
<div className="band">
<div className="section-head">
<h2>Fields</h2>
<p>Absent means unstated, never a default. A reader says so beside the number.</p>
</div>
<table style={table}>
<thead>
<tr>
<th style={th}>Key</th>
<th style={th}>Values</th>
<th style={th}>Meaning</th>
</tr>
</thead>
<tbody>
{spec.fields.map(([key, values, meaning]) => (
<tr key={key}>
<td style={td}>
<code style={mono}>{key}</code>
</td>
<td style={td}>{values}</td>
<td style={td}>{meaning}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>What a directory does with it</h2>
</div>
<table style={table}>
<tbody>
{spec.directory.map(([what, how]) => (
<tr key={what}>
<td style={td}>
<strong>{what}</strong>
</td>
<td style={td}>{how}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>What is deliberately absent</h2>
</div>
<table style={table}>
<tbody>
{spec.absent.map(([what, why]) => (
<tr key={what}>
<td style={td}>
<strong>{what}</strong>
</td>
<td style={td}>{why}</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="band">
<div className="section-head">
<h2>Where everything lives</h2>
</div>
<ul style={{ color: "#41505d", lineHeight: 1.9, paddingLeft: "1.1rem" }}>
<li>
<Link href={`/docs/${spec.slug}`}>Specification</Link>: the block, every rule and how
it degrades, the resource as its own offer, what a directory owes a provider
</li>
<li>
<Link href="/docs/openserver">OpenServer</Link>: the descriptor at{" "}
<code style={mono}>/.well-known/openserver.json</code> that this block sits in, and the
directory that reads it
</li>
<li>
The five resources of a purchase:{" "}
{SIBLINGS.map(([name, slug], i) => (
<span key={slug}>
{i > 0 ? ", " : ""}
{slug === spec.slug ? <strong>{name}</strong> : <Link href={`/${slug}`}>{name}</Link>}
</span>
))}
, each with the same <code style={mono}>range</code> shape
</li>
</ul>
</div>
</SiteShell>
);
}

View file

@ -18,6 +18,12 @@ const NAV: Array<{ href: string; label: string; external?: boolean }> = [
{ href: "/openmcp", label: "OpenMCP" },
{ href: "/openaccess", label: "OpenAccess" },
{ href: "/openserver", label: "OpenServer" },
{ href: "/opencpu", label: "OpenCPU" },
{ href: "/openmemory", label: "OpenMemory" },
{ href: "/opengpu", label: "OpenGPU" },
{ href: "/openbandwidth", label: "OpenBandwidth" },
{ href: "/openfile", label: "OpenFile" },
{ href: "/opendisk", label: "OpenDisk" },
{ href: "/opencoupon", label: "OpenCoupon" },
{ href: "/openrecipe", label: "OpenRecipe.md" },
{ href: "/#cli", label: "CLI" },

View file

@ -21,9 +21,15 @@ export const DOC_SLUGS = [
"openmcp",
"openaccess",
"openserver",
"openfile",
"opendisk",
"opencoupon",
"openrecipe",
"openstream",
"opencpu",
"openmemory",
"opengpu",
"openbandwidth",
"openspec-comparison",
"data-model",
"cli",