diff --git a/src/pages/docs/app-store.astro b/src/pages/docs/app-store.astro index db337a6..4ff9b2d 100644 --- a/src/pages/docs/app-store.astro +++ b/src/pages/docs/app-store.astro @@ -14,6 +14,7 @@ const bodyContent = `
Two integrity layers protect every install, both re-checked at each spawn: the catalogue pins the tarball sha256 (a swapped CDN byte fails), and the manifest pins the binary sha256 under an ed25519 signature.
+The catalogue itself is signed. After editing catalogue.json, re-sign it so the daemon and pilotctl will trust it:
pilotctl appstore sign-catalogue --key catalog-signing.key catalogue/catalogue.json
+
+ This writes a detached catalogue.json.sig (commit both). pilotctl verifies it against the embedded catalogue key before trusting any entry - see Security model.
Three integrity layers protect every install: the catalogue carries a detached ed25519 signature (a substituted app list fails), the catalogue pins each tarball sha256 (a swapped CDN byte fails), and the manifest pins the binary sha256 under an ed25519 signature - the last two re-checked at every spawn.
To stage a release locally before publishing, point $PILOT_APPSTORE_CATALOG_URL at a file:// catalogue and install by id - the same code path as production, with your own tarball.
The app store is deny-by-default at every layer. Trust flows from a signed catalogue, through a signed manifest, to a sandboxed and continuously-verified child process.
+ +The catalogue is signed with a dedicated ed25519 key whose public half is compiled into pilotctl and the daemon. pilotctl fetches both catalogue.json and a detached catalogue.json.sig and verifies the signature before trusting any entry. An unsigned, missing-signature, or tampered catalogue is refused - a compromised host or CDN cannot point installs at hostile bundle URLs without forging the signature. The signing key can be rotated at build time:
go build -ldflags \
+ "-X .../internal/catalogtrust.publicKeyB64=<new-b64-pubkey>" \
+ ./cmd/pilotctl ./cmd/daemon
+
+ Apps never dial each other's sockets directly - every call goes through the daemon's broker, which enforces two gates before any dispatch:
+exposes set. That list is the app's entire callable surface; anything else is refused, even for the daemon itself.ipc.call grant targeting <app>.<method> (exact, <app>.*, or *). No grant, no call.The supervisor that spawns and watches each app applies defence-in-depth:
+exec, the binary is re-checked: rejected if it became a symlink, and its sha256 must still match the pinned hash. A binary swapped between install-scan and launch is caught before it runs.RLIMIT_NOFILE and an RLIMIT_AS address-space cap, bounding fd and memory abuse.Apps may register hooks on daemon primitives (declared in the manifest), but the hook surface is bounded: per-app rate limiting caps how often the daemon will dispatch into an app's hooks, and the number of dynamic hook registrations per app is capped - so a hostile hook can't become a DoS amplifier.
+The cosift app is a stateless adapter to a search / answer / research API over a multi-million-document web corpus. It exposes three utility methods and several status/discovery ones:
diff --git a/src/pages/sitemap.xml.ts b/src/pages/sitemap.xml.ts index df07328..c393bf2 100644 --- a/src/pages/sitemap.xml.ts +++ b/src/pages/sitemap.xml.ts @@ -1,8 +1,13 @@ import { blogPosts } from '../data/blogPosts'; -import { docsNav } from '../data/docsNav'; const site = 'https://pilotprotocol.network'; +// Enumerate every page module so the sitemap reflects the real route +// tree — no hand-maintained list to drift out of date. New pages appear +// automatically; only error pages, dynamic templates, and the /plain +// text-mirror are filtered out. +const pageGlob = import.meta.glob('./**/*.{astro,md,mdx}'); + function url(loc: string, lastmod: string, priority: number, changefreq = 'monthly') { return `