<?php
/*
 * Owner-only guide: the Owner→client Push system (advisories + critical patches).
 * Served by modules/Help/HelpController (topic = "advisories").
 * No $baseUrl in scope here — use anchor (#id) or relative (sibling) links only.
 */
$c = static fn (string $s): string => '<pre><code>' . htmlspecialchars($s) . '</code></pre>';
?>

<h1><i class="bi bi-broadcast"></i> Pushing to your clients — advisories &amp; security patches</h1>
<p class="lead">From your licence server you can send every licensed installation a <strong>notice</strong> (it appears in
   their notification bell) or a <strong>critical security patch</strong> (it installs itself). It works like the way a
   phone quietly receives a security fix: the client picks it up on its next check&#8209;in, verifies it against your
   signing key, and acts on it — and nothing is ever sent to an unlicensed or tampered copy.</p>

<div class="alert alert-info">
    <strong>Who is this for?</strong> The Owner. Composing and sending pushes is <strong>owner&#8209;only</strong>
    (the <b>Push advisories</b> console on the Licence server). On the receiving side, the client's administrator sees
    the notice and controls whether critical patches auto&#8209;install.
</div>

<h2>Contents</h2>
<ul>
    <li><a href="#what">The one‑minute summary</a></li>
    <li><a href="#two">Two kinds of push: notice vs critical patch</a></li>
    <li><a href="#send">Sending a push — the console</a></li>
    <li><a href="#target">Everyone vs specific installs (targeting)</a></li>
    <li><a href="#travel">How a push reaches a client (and how fast)</a></li>
    <li><a href="#auto">Auto‑install of critical patches (opt‑out)</a></li>
    <li><a href="#notify">Automatic "an update is available" notices</a></li>
    <li><a href="#labels">Naming your servers (SEC‑SRV‑NP)</a></li>
    <li><a href="#safe">Why it is safe</a></li>
    <li><a href="#trouble">Troubleshooting</a></li>
</ul>

<h2 id="what">The one‑minute summary</h2>
<ul>
    <li>Open <b>Licence server → Push advisories to clients</b> (<code>/licensing/advisories</code>).</li>
    <li>Write a <b>notice</b> (a message) or mark it a <b>critical patch</b> (installs a released version).</li>
    <li>Choose <b>who</b> gets it — everyone, or specific installations.</li>
    <li><b>Publish.</b> Each licensed client verifies it against your signing key on its next check‑in and acts on it.</li>
    <li>You can <b>retire</b> a push at any time to stop sending it; clients keep anything they already received.</li>
</ul>

<h2 id="two">Two kinds of push</h2>
<table class="table table-sm">
    <thead><tr><th>Type</th><th>What the client does</th><th>Use it for</th></tr></thead>
    <tbody>
        <tr><td><b>Notice only</b></td>
            <td>Drops a message in the admin's <b>notification bell</b> (coloured by severity). Never changes a file.</td>
            <td>Announcements, maintenance windows, "rotate your keys", "a new feature is live".</td></tr>
        <tr><td><b>Critical patch</b> (auto‑install)</td>
            <td>Also tells the client to <b>install a specific released version</b> through the normal signed update
                pipeline — signature‑verified, with a restore point taken first — <em>even if</em> the client has
                general auto‑update switched off.</td>
            <td>An urgent security fix you need on the whole estate without waiting for each admin to click Install.</td></tr>
    </tbody>
</table>
<div class="alert alert-warning">
    A critical patch only ever installs a release you have already <b>published</b> through <b>App&nbsp;Bundle</b>
    (see the <a href="../updates/">Online Updates</a> guide). The advisory is the <em>instruction</em>; the signed
    bundle on your update host is the <em>payload</em>. Marking a push as a critical patch forces its severity to
    <b>Critical</b> — that is the only severity a client will auto‑install.
</div>

<h2 id="send">Sending a push — the console</h2>
<p>On the Licence server, click <b>Push advisories to clients</b>. Each field carries a <code>?</code> hint; in short:</p>
<table class="table table-sm">
    <tbody>
        <tr><td><b>Title / Message</b></td><td>What the admin reads in the bell.</td></tr>
        <tr><td><b>Severity</b></td><td>Notice / Good news / Warning / Critical — controls how prominent it looks.</td></tr>
        <tr><td><b>Type</b></td><td><em>Notice only</em>, or <em>Critical patch</em> (reveals an optional target version — blank = latest).</td></tr>
        <tr><td><b>Link</b></td><td>Where clicking the notice takes the admin (e.g. <code>/platform/updates</code>).</td></tr>
        <tr><td><b>Audience</b></td><td><em>Everyone</em>, or <em>Specific installs</em> you pick from the list.</td></tr>
        <tr><td><b>Expires</b></td><td>Optional — stop sending it after a date. Blank = until you retire it.</td></tr>
    </tbody>
</table>
<p>The right‑hand column lists everything you have published. Each has <b>Edit</b>, <b>Retire/Re‑activate</b> and
   <b>Delete</b>. Retiring stops the push going out; clients that already received it keep it.</p>

<h2 id="target">Everyone vs specific installs</h2>
<p>Set <b>Audience → Specific installs</b> to pick individual installations (they appear once they have checked in).
   Targeting is decided <b>on your server</b> from the authenticated licence of whoever is asking, so one customer can
   never receive another's targeted push — it is not something the client chooses.</p>

<h2 id="travel">How a push reaches a client</h2>
<p>Every licensed client checks in with your licence server — on each <b>daily renewal</b>, and again on a light
   background <b>check every few hours</b>. On each check‑in your server hands back a small, <b>signed advisory feed</b>
   for that specific licence (riding along with the licence lease). The client:</p>
<ol>
    <li><b>Verifies</b> the feed against your pinned signing key (a mirror or middle‑man can't forge or alter it).</li>
    <li><b>Confirms</b> the feed was built for <em>it</em> (not another install).</li>
    <li>For anything it hasn't seen before: shows the notice, and — if allowed — installs a critical patch.</li>
</ol>
<p>So a fresh push typically lands <b>within a few hours</b>, or immediately on the next renewal. It is idempotent:
   each item is shown once and installed once, tracked by a unique id, so a repeated feed changes nothing.</p>

<h2 id="auto">Auto‑install of critical patches (opt‑out)</h2>
<p>On the client, <b>Platform&nbsp;Updates</b> has a switch — <b>"Auto‑install critical security patches"</b> — that is
   <b>ON by default</b>. While it is on, a client applies your signed <em>critical</em> pushes automatically (restore
   point first). An admin can turn it off; then a critical patch still raises a prominent notice and banner, but a human
   must click <b>Install</b>. Ordinary (non‑critical) updates <em>always</em> wait for a human — this switch never
   changes that.</p>

<h2 id="notify">Automatic "an update is available" notices</h2>
<p>Separately from anything you push, a licensed client quietly notices when you publish a newer release and drops an
   <b>"update available"</b> item in the admin's bell, plus a banner on its Platform&nbsp;Updates page. This is
   notify‑only — it never installs anything by itself. It is why customers don't fall behind even when you send no
   advisory at all.</p>

<h2 id="labels">Naming your servers</h2>
<p>On <b>Licence server → Servers &amp; keys → Service addresses</b>, the <b>Server display names</b> editor lets you give
   each server a short, friendly label (e.g. <code>SEC-SRV-NP</code>). Clients show that label for their licence service
   instead of the raw address. The label rides inside the signed lease, so changing it reaches every install within a
   day, and it can't be spoofed. Leave it blank and the client shows an auto‑generated code.</p>

<h2 id="safe">Why it is safe</h2>
<ul>
    <li><b>Signed end‑to‑end.</b> Every push is signed by your Ed25519 key and verified offline by the client — the same
        trust anchor as licence leases and update bundles.</li>
    <li><b>Never to the wrong copy.</b> A copy whose licence is expired, revoked, unrecognised, or whose files have been
        tampered with is refused — it receives nothing and installs nothing.</li>
    <li><b>Reversible installs.</b> A critical patch goes through the normal update pipeline: signature‑checked, and a
        restore point is taken before anything changes, so it can be rolled back.</li>
    <li><b>Notice ≠ payload.</b> An advisory can only point at a version you have actually published; it cannot ship
        arbitrary code by itself.</li>
</ul>

<h2 id="trouble">Troubleshooting</h2>
<table class="table table-sm">
    <thead><tr><th>Symptom</th><th>Likely cause / fix</th></tr></thead>
    <tbody>
        <tr><td>A client never shows the notice</td>
            <td>It hasn't checked in yet (allow a few hours, or the next daily renewal), or its licence isn't currently
                valid. Confirm the install is <b>active</b> on the Licence server.</td></tr>
        <tr><td>A critical patch didn't auto‑install</td>
            <td>The client turned <b>Auto‑install critical security patches</b> off — it will have raised a notice + banner
                instead. Also check the release is actually <b>published</b> on your update host.</td></tr>
        <tr><td>Wrong installs received a targeted push</td>
            <td>They can't — targeting is server‑side by authenticated licence. Re‑check the <b>Audience</b> list on the push.</td></tr>
        <tr><td>You want to stop a push</td>
            <td><b>Retire</b> it in the console. Clients keep what they already have; delete removes it entirely.</td></tr>
    </tbody>
</table>

<p class="text-muted"><i class="bi bi-life-preserver"></i> Related: <a href="../licensing/">Licensing</a> (the check‑in
   channel this rides on) and <a href="../updates/">Online Updates</a> (publishing the bundles a critical patch installs).</p>
