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
File renamed without changes.
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ either way, but the hook catches it before a push, not after.

```
index.html the page (inline CSS/JS, system fonts, zero external assets)
bcn-removed/index.html pre-positioned migration page (see below) — NOT linked from nav
.drafts/bcn-removed/index.html pre-positioned migration page (see below) — UNPUBLISHED draft
_redirects /bcn-removed/* -> / until the draft publishes
_headers security headers incl. CSP
.githooks/pre-commit public-repo hygiene hook (see below)
bin/check-file-allowlist.sh the allowlist itself — shared by the hook and CI
Expand All @@ -32,10 +33,11 @@ the `ALLOW_PATTERNS` array in that script.

Addendum §2 (DECIDED): built ahead of any trigger so FosterStack is in front of
panic-searches within hours of Gradle actually removing `gradle/build-cache-node` from
Docker Hub, not days. It deploys automatically like any other file here (Cloudflare Pages
has no concept of "build but don't ship") but is deliberately **not linked from `index.html`**
and carries `<meta name="robots" content="noindex">`, so it sits at a real, working URL
that isn't discoverable until someone links to it.
Docker Hub, not days. REVISED Sep 11, 2026: it used to deploy at an unlisted URL behind
a `noindex` tag; the Sep 10 review pointed out that noindex is a request, not a gate —
the page claimed a removal that had not happened, at a live URL. It now lives in
`.drafts/` (dot-prefixed paths are excluded from the Pages upload, so it does not
deploy), and `/bcn-removed/*` 302s to the homepage in the meantime.

The trigger source is `fosterstack/ops`'s daily Docker Hub watcher
(`bin/docker-hub-watch.sh`, private repo) — it files a tracking issue when it detects the
Expand Down
6 changes: 6 additions & 0 deletions _redirects
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# /bcn-removed/ is pre-positioned for the day the incumbent's image is
# verifiably gone (the bcn-watch trigger), and unpublished until then — the
# draft lives in .drafts/, which Cloudflare Pages does not deploy
# (dot-prefixed paths are excluded from upload). Until publication, any
# stray inbound link lands on the homepage instead of a 404.
/bcn-removed/* / 302
4 changes: 4 additions & 0 deletions bin/check-file-allowlist.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ set -euo pipefail
ALLOW_PATTERNS=(
'^CONTRIBUTING\.md$'
'^\.github/PULL_REQUEST_TEMPLATE\.md$'
# Unpublished drafts: dot-prefixed, excluded from the Pages upload, so
# nothing under .drafts/ ever serves. The bcn-removed page waits here
# until the watcher verifies the removal.
'^\.drafts/([A-Za-z0-9._-]+/)*[A-Za-z0-9._-]+\.html$'
'^index\.html$'
'^README\.md$'
'^LICENSE$'
Expand Down
16 changes: 10 additions & 6 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -147,11 +147,12 @@ <h2>Built to be verified, not trusted</h2>

<h2>What we do not collect</h2>
<ul class="trust">
<li><strong>The product does not phone home.</strong> The server makes no outbound
network connections — no telemetry, no license check, no update ping. It is
self-hosted, and it works identically on a machine with no route to the internet.
Verified rather than asserted: the binary opens exactly one socket, its own listener,
at rest and under load.</li>
<li><strong>No telemetry, and no required FosterStack connection.</strong> The server
reports nothing to us — no usage data, no license check, no update ping — and today's
free core makes no outbound connections at all: it works identically on a machine with
no route to the internet. When the paid features ship, the only outbound traffic will
be what you configure (your identity provider for SSO, your peer replicas for HA) —
endpoints you choose, never FosterStack.</li>
<li><strong>This website collects no email addresses.</strong> There is no signup
form, no waitlist, and no newsletter. It sets no cookies, runs no analytics, and
loads nothing from a third party.</li>
Expand All @@ -174,7 +175,10 @@ <h2>Pricing</h2>
</table>
<p style="color:var(--muted); font-size:.9rem; margin-top:.6rem">
Self-serve, credit card, cancel anytime. Priced so an engineering manager can expense it
without a procurement cycle — the incumbent's median contract runs $57k/year.
without a procurement cycle. (For scale: the incumbent's median <em>platform</em>
contract — Develocity, the full product suite, of which the cache node is one
component — runs about $57k/year. That is not the price of a cache, and we are not
claiming it is; it is the procurement class this pricing deliberately avoids.)
</p>

<h2>Roadmap honesty</h2>
Expand Down
15 changes: 7 additions & 8 deletions robots.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# fosterstack.com
# Everything published here is meant to be found. The one unlisted page
# (/bcn-removed/) is deliberately NOT disallowed below: it carries a
# <meta name="robots" content="noindex"> tag, and a crawler has to be able
# to fetch the page to see that tag. Disallowing it here would block the
# crawl, leave the noindex unread, and make the page *more* likely to be
# indexed from a stray inbound link, not less.
# Everything published here is meant to be found. (Historical note: an
# unlisted /bcn-removed/ page used to live here behind a noindex tag; as of
# Sep 11, 2026 it is unpublished entirely — moved to an undeployed draft
# path until the incumbent image's removal is verified by the watcher —
# because noindex is a request to search engines, not a gate. The old URL
# 302s to the homepage meanwhile; see _redirects.)

User-agent: *
Allow: /
Expand All @@ -14,8 +14,7 @@ Allow: /
# function endpoint is excluded from crawling by default rather than by memory.
# Note Disallow stops the CRAWL and does not guarantee de-indexing: a disallowed
# URL can still be indexed from an inbound link, with no content. Same
# crawl-vs-index distinction as the /bcn-removed/ note above, pointing the other
# way. If a route ever needs to be provably absent from results, give it an
# crawl-vs-index distinction noted above, pointing the other way. If a route ever needs to be provably absent from results, give it an
# X-Robots-Tag: noindex header INSTEAD of a Disallow — a page that is never
# fetched never reveals its noindex.
Disallow: /api/
Expand Down
3 changes: 2 additions & 1 deletion sitemap.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Index page only, on purpose. /bcn-removed/ is pre-positioned and unlisted
Index page only, on purpose. The pre-positioned /bcn-removed/ page is unpublished
(an undeployed draft in .drafts/) until the watcher verifies the removal; it was unlisted
until its trigger fires (see ops/docs, addendum §2); it stays out of this
file and keeps its noindex tag until then.
-->
Expand Down