Skip to content
Open
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
17 changes: 14 additions & 3 deletions src/pages/docs/app-store.astro
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,21 @@ const bodyContent = `<h1>App Store</h1>
<pre><code><span class="comment"># 1. Discover what's installable</span>
<span class="cmd">pilotctl</span> appstore catalogue

<span class="comment"># 2. Install by id - fetch + verify sha + install; the daemon auto-spawns it</span>
<span class="comment"># 2. Inspect before committing - description, vendor, changelog, size, source, methods, permissions</span>
<span class="cmd">pilotctl</span> appstore view io.pilot.cosift [--all-changelog]

<span class="comment"># 3. Install by id - fetch + verify sha + install; the daemon auto-spawns it</span>
<span class="cmd">pilotctl</span> appstore install io.pilot.cosift

<span class="comment"># 3. Confirm it's ready (lists installed apps + the methods each exposes)</span>
<span class="comment"># 4. Confirm it's ready (lists installed apps + the methods each exposes)</span>
<span class="cmd">pilotctl</span> appstore list
<span class="cmd">pilotctl</span> appstore status io.pilot.cosift

<span class="comment"># 4. Call a method - JSON in, JSON out on stdout</span>
<span class="comment"># 5. Call a method - JSON in, JSON out on stdout</span>
<span class="cmd">pilotctl</span> appstore call io.pilot.cosift cosift.search '{"q":"raft consensus","k":"5"}'</code></pre>

<p><code>view &lt;id&gt;</code> is the app's detail page — it works whether or not the app is installed, so you can vet description, vendor, latest changelog (<code>--all-changelog</code> for full history), download/installed size, source URL, license, exposed methods, and the permissions it requests before installing.</p>

<div class="callout">
<p><strong>No config step.</strong> A well-built app ships with sane defaults, so <code>install</code> then <code>call</code> is all an agent needs. Apps may read an optional <code>config.json</code> next to their manifest for overrides (e.g. a self-hosted backend).</p>
</div>
Expand All @@ -74,10 +79,14 @@ const bodyContent = `<h1>App Store</h1>
<h2 id="lifecycle">Lifecycle</h2>

<pre><code><span class="cmd">pilotctl</span> appstore restart io.pilot.cosift <span class="comment"># respawn (e.g. after writing a config.json)</span>
<span class="cmd">pilotctl</span> appstore caps io.pilot.cosift <span class="comment"># spend caps + current rolling-window usage</span>
<span class="cmd">pilotctl</span> appstore audit io.pilot.cosift <span class="comment"># supervisor log: spawn / exit / verify-fail</span>
<span class="cmd">pilotctl</span> appstore actions <span class="comment"># pilotctl-side install/uninstall log (survives removal)</span>
<span class="cmd">pilotctl</span> appstore install io.pilot.cosift --force <span class="comment"># upgrade to a new version</span>
<span class="cmd">pilotctl</span> appstore uninstall io.pilot.cosift --yes</code></pre>

<p><code>caps</code> reports the manifest's spend caps and how much of each rolling window the app has consumed; <code>audit</code> tails the supervisor lifecycle log for one app; <code>actions</code> is the pilotctl-side install/uninstall log, which persists even after an app is removed. Both <code>audit</code> and <code>actions</code> accept <code>--tail &lt;n&gt;</code> and <code>--event &lt;name&gt;</code> (and <code>audit</code> takes <code>--since &lt;dur&gt;</code>).</p>

<div class="callout">
<p><strong>Upgrades key on the version.</strong> The supervisor respawns an app when its <code>app_version</code> changes. Bump the version for every new build, or a re-release of the same version won't roll running nodes onto the new binary.</p>
</div>
Expand Down Expand Up @@ -157,6 +166,8 @@ ipc.Serve(ctx, conn, d) <span class="comment">// on the --socket the daemon su
<p>To stage a release locally before publishing, point <code>$PILOT_APPSTORE_CATALOG_URL</code> at a <code>file://</code> catalogue and install by id - the same code path as production, with your own tarball.</p>
</div>

<p>To check a bundle without installing it, <code>pilotctl appstore verify &lt;bundle-dir&gt;</code> sha256-checks every file in a pre-install bundle against its manifest and reports any mismatch — a tampered or wrongly-built bundle fails here before it ever reaches the install root.</p>

<h2 id="security">Security model &amp; hardening</h2>

<p>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.</p>
Expand Down
81 changes: 79 additions & 2 deletions src/pages/docs/cli-reference.astro
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@ const bodyContent = `<h1>CLI Reference</h1>
<li><a href="#identity">Identity &amp; Discovery</a></li>
<li><a href="#communication">Communication</a></li>
<li><a href="#trust">Trust management</a></li>
<li><a href="#verification">Verification &amp; Recovery</a></li>
<li><a href="#webhooks">Webhooks</a></li>
<li><a href="#tags">Tags</a></li>
<li><a href="#mailbox">Mailbox</a></li>
<li><a href="#networks">Networks</a></li>
<li><a href="#service-agents">Service Agents</a></li>
<li><a href="#appstore">App Store</a></li>
<li><a href="#diagnostics">Diagnostics</a></li>
<li><a href="#managed">Managed Networks</a></li>
<li><a href="#member-tags">Member Tags</a></li>
Expand Down Expand Up @@ -218,6 +220,22 @@ const bodyContent = `<h1>CLI Reference</h1>
<pre><code><span class="cmd">pilotctl</span> untrust &lt;node_id&gt;</code></pre>
<p>Returns: <code>node_id</code></p>

<h2 id="verification">Verification &amp; Recovery</h2>

<h3 id="verify">verify</h3>
<pre><code><span class="cmd">pilotctl</span> verify [status] [--node &lt;addr|id&gt;]
<span class="cmd">pilotctl</span> verify --provider &lt;name&gt;
<span class="cmd">pilotctl</span> verify --badge &lt;b&gt; --badge-sig &lt;s&gt; <span class="comment"># or --from &lt;file&gt;</span></code></pre>
<p>Verified-address badges prove a node controls a real, attested identity. Bare <code>verify</code> (or <code>verify status</code>) shows your current state; <code>--provider &lt;name&gt;</code> runs a device-flow to become verified; <code>--badge</code>/<code>--badge-sig</code> (or <code>--from &lt;file&gt;</code>) submits a badge you already hold. Badges are checked offline against the pinned issuer key — the registry's word is never trusted.</p>
<p>Returns: <code>verified</code> (bool), <code>node_id</code>, <code>address</code>, <code>issuer</code></p>

<h3 id="recovery">recovery</h3>
<pre><code><span class="cmd">pilotctl</span> recovery enroll &lt;...&gt;
<span class="cmd">pilotctl</span> recovery new-key &lt;...&gt;
<span class="cmd">pilotctl</span> recovery recover &lt;...&gt;</code></pre>
<p>Reclaim a node's address if its identity key is lost. <code>enroll</code> records an opaque recovery commitment for the address; <code>new-key</code> rotates to a fresh key; <code>recover</code> reclaims the address using recovery material. Enrollment and signatures come from the <code>pilot-verify</code> tool.</p>
<p>Returns: <code>status</code>, <code>node_id</code>, <code>address</code></p>

<h2 id="webhooks">Webhooks</h2>

<h3 id="set-webhook">set-webhook</h3>
Expand All @@ -231,13 +249,15 @@ const bodyContent = `<h1>CLI Reference</h1>

<h2 id="tags">Tags</h2>

<p>Discovery tags are operator setup, so they live in the <code>extras</code> tier — <code>pilotctl set-tags</code> on its own is rejected.</p>

<h3 id="set-tags">set-tags</h3>
<pre><code><span class="cmd">pilotctl</span> set-tags &lt;tag1&gt; [tag2] [tag3]</code></pre>
<pre><code><span class="cmd">pilotctl</span> extras set-tags &lt;tag1&gt; [tag2] [tag3]</code></pre>
<p>Maximum 3 tags. Lowercase alphanumeric + hyphens, 1–32 characters each.</p>
<p>Returns: <code>node_id</code>, <code>tags</code></p>

<h3 id="clear-tags">clear-tags</h3>
<pre><code><span class="cmd">pilotctl</span> clear-tags</code></pre>
<pre><code><span class="cmd">pilotctl</span> extras clear-tags</code></pre>
<p>Returns: <code>tags</code> (empty array)</p>

<h2 id="mailbox">Mailbox</h2>
Expand Down Expand Up @@ -307,6 +327,50 @@ const bodyContent = `<h1>CLI Reference</h1>

<p>The <code>--wait [&lt;dur&gt;]</code> flag (default 30s) makes <code>send-message</code> block until the reply lands in <code>~/.pilot/inbox/</code>, which avoids racing with the file system poll. See <a href="/docs/service-agents">Service Agents</a> for the full pattern.</p>

<h2 id="appstore">App Store</h2>

<p>The app store installs local capability apps that run on your daemon as typed IPC services — JSON in, JSON out, auto-spawned on install. All subcommands are invoked as <code>pilotctl appstore &lt;subcommand&gt;</code>. The install root is <code>$PILOT_APPSTORE_ROOT</code> or <code>~/.pilot/apps</code>. See the full <a href="/docs/app-store">App Store</a> guide for the discover → install → call loop. Run <code>pilotctl appstore help</code> for the complete subcommand list.</p>

<h3 id="appstore-catalogue">catalogue</h3>
<pre><code><span class="cmd">pilotctl</span> appstore catalogue</code></pre>
<p>Lists apps available for one-command install (alias: <code>catalog</code>).</p>

<h3 id="appstore-view">view</h3>
<pre><code><span class="cmd">pilotctl</span> appstore view &lt;id&gt; [--all-changelog]</code></pre>
<p>App detail page — description, vendor, changelog, download/installed size, source URL, license, exposed methods, and granted permissions. Works whether or not the app is installed.</p>

<h3 id="appstore-install">install</h3>
<pre><code><span class="cmd">pilotctl</span> appstore install &lt;app-id&gt; [--force]
<span class="cmd">pilotctl</span> appstore install &lt;bundle-dir&gt; --local [--force]</code></pre>
<p>Install by catalogue ID (fetches, verifies, and extracts), or sideload a local bundle with <code>--local</code> (sandboxed: <code>fs.read</code>/<code>fs.write</code> under <code>$APP</code> + <code>audit.log</code>; no net, no <code>key.sign</code>, no hooks). The daemon auto-spawns the app on install.</p>

<h3 id="appstore-list">list</h3>
<pre><code><span class="cmd">pilotctl</span> appstore list</code></pre>
<p>Lists installed apps and the IPC methods each exposes.</p>

<h3 id="appstore-call">call</h3>
<pre><code><span class="cmd">pilotctl</span> appstore call &lt;id&gt; &lt;method&gt; [json-args] [--timeout &lt;dur&gt;]</code></pre>
<p>Dispatches an IPC call into an app and prints the JSON result on stdout. Every app exposes <code>&lt;app&gt;.help</code> listing its methods, params, and latency class. Default timeout 120s (also <code>$PILOT_APPSTORE_CALL_TIMEOUT</code>).</p>

<h3 id="appstore-status">status / caps / audit / actions</h3>
<pre><code><span class="cmd">pilotctl</span> appstore status &lt;id&gt;
<span class="cmd">pilotctl</span> appstore caps &lt;id&gt;
<span class="cmd">pilotctl</span> appstore audit &lt;id&gt; [--tail &lt;n&gt;] [--event &lt;name&gt;] [--since &lt;dur&gt;]
<span class="cmd">pilotctl</span> appstore actions [--tail &lt;n&gt;] [--event &lt;name&gt;]</code></pre>
<p><code>status</code> deep-dives one app's pinned state; <code>caps</code> shows the manifest's spend caps and current rolling-window usage; <code>audit</code> shows the supervisor lifecycle log (spawn/exit/suspend/verify-fail); <code>actions</code> shows the pilotctl-side install/uninstall log, which survives app removal.</p>

<h3 id="appstore-restart">restart / uninstall / verify</h3>
<pre><code><span class="cmd">pilotctl</span> appstore restart &lt;id&gt;
<span class="cmd">pilotctl</span> appstore uninstall &lt;id&gt; --yes
<span class="cmd">pilotctl</span> appstore verify &lt;bundle-dir&gt;</code></pre>
<p><code>restart</code> clears crash-loop suspension and respawns the app; <code>uninstall</code> removes it from the install root; <code>verify</code> sha256-checks a pre-install bundle against its manifest.</p>

<h3 id="appstore-publisher">gen-key / sign / sign-catalogue</h3>
<pre><code><span class="cmd">pilotctl</span> appstore gen-key &lt;key-file&gt;
<span class="cmd">pilotctl</span> appstore sign --key &lt;key-file&gt; &lt;manifest&gt;
<span class="cmd">pilotctl</span> appstore sign-catalogue --key &lt;key-file&gt; &lt;catalogue.json&gt;</code></pre>
<p>Publisher tooling: generate an ed25519 publisher keypair, sign a manifest's <code>store.signature</code> so the supervisor accepts it, and sign a catalogue (writes a detached <code>.sig</code> pilotctl verifies on load). Alias: <code>sign-catalog</code>.</p>

<h2 id="diagnostics">Diagnostics</h2>

<h3 id="health">health</h3>
Expand Down Expand Up @@ -341,6 +405,11 @@ const bodyContent = `<h1>CLI Reference</h1>
<pre><code><span class="cmd">pilotctl</span> disconnect &lt;conn_id&gt;</code></pre>
<p>Returns: <code>conn_id</code></p>

<h3 id="prefer-direct">prefer-direct</h3>
<pre><code><span class="cmd">pilotctl</span> prefer-direct &lt;node_id|address|hostname&gt;</code></pre>
<p>Resets routing state for a peer so the next connection prefers a direct (hole-punched) tunnel over the relay — useful after a relay path got pinned. Requires daemon v1.12+.</p>
<p>Returns: <code>had_tunnel</code>, <code>was_relay_active</code>, <code>was_relay_pinned</code></p>

<h2 id="managed">Managed Networks</h2>
<p>Operator commands for networks that run an automated evaluation cycle (membership pruning + vacancy filling). Three subcommands: <code>status</code>, <code>cycle</code>, <code>reconcile</code>.</p>

Expand Down Expand Up @@ -469,6 +538,14 @@ const bodyContent = `<h1>CLI Reference</h1>
<pre><code><span class="cmd">pilotctl</span> version</code></pre>
<p>Prints the build version string.</p>

<h3 id="update">update</h3>
<pre><code><span class="cmd">pilotctl</span> update [status|enable|disable] [--pin &lt;tag&gt;]</code></pre>
<p>Self-update. With no subcommand, runs the updater once — checks for and installs the latest release. Automatic updates are <strong>off by default</strong>; <code>enable</code>/<code>disable</code> toggle the background updater and <code>status</code> shows the current setting and version. Distinct from <code>updates</code> (below), which just reads the changelog feed.</p>

<h3 id="review">review</h3>
<pre><code><span class="cmd">pilotctl</span> review &lt;pilot|app-id&gt; [--rating &lt;1-5&gt;] [--text "..."]</code></pre>
<p>Submit a rating and/or written review for Pilot itself (<code>pilot</code>) or for an installed app (e.g. <code>io.pilot.cosift</code>).</p>

<h3 id="updates">updates</h3>
<pre><code><span class="cmd">pilotctl</span> updates [--count &lt;n&gt;] [--scope &lt;name&gt;]</code></pre>
<p>Reads the published Pilot Protocol changelog feed and prints recent entries (default: 5). <code>--scope</code> filters by tag (e.g. <code>protocol</code>, <code>cli</code>, <code>networks</code>).</p>
Expand Down
14 changes: 11 additions & 3 deletions src/pages/plain/docs/app-store.astro
Original file line number Diff line number Diff line change
Expand Up @@ -34,15 +34,19 @@ import PlainLayout from '../../../layouts/PlainLayout.astro';
<pre><code># 1. Discover what's installable
pilotctl appstore catalogue

# 2. Install by id - fetch + verify sha + install; the daemon auto-spawns it
# 2. Inspect before committing - description, vendor, changelog, size, source, methods, permissions
pilotctl appstore view io.pilot.cosift [--all-changelog]

# 3. Install by id - fetch + verify sha + install; the daemon auto-spawns it
pilotctl appstore install io.pilot.cosift

# 3. Confirm it's ready (lists installed apps + the methods each exposes)
# 4. Confirm it's ready (lists installed apps + the methods each exposes)
pilotctl appstore list
pilotctl appstore status io.pilot.cosift

# 4. Call a method - JSON in, JSON out on stdout
# 5. Call a method - JSON in, JSON out on stdout
pilotctl appstore call io.pilot.cosift cosift.search '&#123;"q":"raft consensus","k":"5"&#125;'</code></pre>
<p>`view &lt;id&gt;` is the app's detail page — it works whether or not the app is installed, so you can vet description, vendor, latest changelog (`--all-changelog` for full history), size, source URL, license, exposed methods, and requested permissions before installing.</p>
<p>No config step. A well-built app ships with sane defaults, so install then call is all an agent needs. Apps may read an optional config.json next to their manifest for overrides (e.g. a self-hosted backend).</p>

<h2>Discovery and the help convention</h2>
Expand All @@ -58,9 +62,12 @@ pilotctl appstore call io.pilot.cosift cosift.search '&#123;"q":"raft consensus"

<h2>Lifecycle</h2>
<pre><code>pilotctl appstore restart io.pilot.cosift # respawn (e.g. after writing a config.json)
pilotctl appstore caps io.pilot.cosift # spend caps + current rolling-window usage
pilotctl appstore audit io.pilot.cosift # supervisor log: spawn / exit / verify-fail
pilotctl appstore actions # pilotctl-side install/uninstall log (survives removal)
pilotctl appstore install io.pilot.cosift --force # upgrade to a new version
pilotctl appstore uninstall io.pilot.cosift --yes</code></pre>
<p>`caps` reports the manifest's spend caps and rolling-window usage; `audit` tails the supervisor lifecycle log for one app; `actions` is the pilotctl-side install/uninstall log, which persists even after an app is removed. Both `audit` and `actions` accept `--tail &lt;n&gt;` and `--event &lt;name&gt;` (and `audit` takes `--since &lt;dur&gt;`).</p>
<p>Upgrades key on the version: the supervisor respawns an app when its app_version changes. Bump the version for every new build, or a re-release of the same version won't roll running nodes onto the new binary.</p>

<h2>Building an app</h2>
Expand Down Expand Up @@ -119,6 +126,7 @@ gh release create cosift-v0.1.2 io.pilot.cosift-0.1.2.tar.gz</code></pre>
<li>Sideload (install &lt;dir&gt; --local): for local development. The manifest is clamped to a small sandbox: fs.read/fs.write under $APP and audit.log only. No net.dial, no inter-app calls, no hooks. A net-using app must go through the catalogue.</li>
</ul>
<p>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.</p>
<p>To check a bundle without installing it, `pilotctl appstore verify &lt;bundle-dir&gt;` sha256-checks every file in a pre-install bundle against its manifest and reports any mismatch — a tampered or wrongly-built bundle fails here before it ever reaches the install root.</p>

<h2>Security model and hardening</h2>
<p>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.</p>
Expand Down
Loading
Loading