fix(pwa): the CLI hint printed commands that no longer run

The "Connect the CLI" card handed out:

    LOGICSRC_API=https://app.logicsrc.com logicsrc login
    logicsrc teams push <team> prod --env .env
    logicsrc teams pull <team> prod --env .env

Two things are wrong with that, and both survived a release.

Since #109 addressed vaults as <team> <project> <env>, push and pull take
three positionals. The hint passes two, so pasting it exits with a missing-
argument error -- the card is not merely stale, it is broken.

The LOGICSRC_API prefix sets the variable to the value the CLI already
defaults to (DEFAULT_API_URL, #107), so on the hosted app it does nothing
while reading like a required step. It is now emitted only when the origin
is not the default, which is the case it exists for: self-hosting.

`--env .env` is dropped for the same reason -- it restates the option's own
default, and sitting next to the new <env> positional it made one flag and
one argument look like the same thing.

Same stale two-argument form fixed in the post-install hint (install.sh) and
the accept-invite message, and in the empty-vault-list prompt on the card.

CLI_HINT moves to src/lib/cli-hint.mjs so a test can assert on the rendered
commands without standing up express and the database, matching how the
other lib-level views are covered. The tests pin the argument count rather
than the prose: restyling the card stays free, dropping an argument does not.

apps/pwa: 13/13 pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Anthony Ettinger 2026-07-30 18:43:15 +00:00
parent ca182bc057
commit aa4a690d60
5 changed files with 86 additions and 11 deletions

View file

@ -8,6 +8,7 @@ import { page, footer, appBar, esc } from "../lib/html.mjs";
import { requireAuth, csrfInput } from "../lib/session.mjs";
import { createApiKey, listApiKeys, revokeApiKey } from "../lib/apikey.mjs";
import { requestOrigin } from "../lib/origin.mjs";
import { CLI_HINT } from "../lib/cli-hint.mjs";
import { config } from "../config.mjs";
export const pagesRouter = Router();
@ -15,14 +16,6 @@ export const pagesRouter = Router();
// placeholder replaced per-request (teamCard can't see req to render csrfInput)
const CSRF = "__CSRF__";
const CLI_HINT = (origin) => `<div class="card" style="margin-bottom:22px"><div class="card-head"><span class="h">Connect the CLI</span><span class="pill on">end-to-end encrypted</span></div>
<div class="card-body">
<p class="dim" style="margin-top:0;font-size:.9rem">Secrets are encrypted on your machine decrypt them with the <code>logicsrc</code> CLI, never here.</p>
<pre class="mono" style="background:var(--surface-2);border:1px solid var(--line);border-radius:8px;padding:12px;overflow:auto;font-size:.8rem;margin:0">LOGICSRC_API=${esc(origin)} logicsrc login
logicsrc teams push &lt;team&gt; prod --env .env # share
logicsrc teams pull &lt;team&gt; prod --env .env # receive</pre>
</div></div>`;
async function teamCard(team, uid) {
const members = await all(`SELECT * FROM credshare_members WHERE team_id = ? ORDER BY created_at`, [team.id]);
const me = members.find((m) => m.user_id === uid);
@ -50,7 +43,7 @@ async function teamCard(team, uid) {
<input type="email" name="email" placeholder="teammate@example.com" required style="flex:1"><button class="btn">Invite</button></form>` : ""}
<div class="label" style="margin:18px 0 6px">Vaults</div>
${vaults.length ? `<table><thead><tr><th>Vault</th><th>Secrets</th><th>Your access</th></tr></thead><tbody>${vaultRows.join("")}</tbody></table>`
: `<p class="faint mono" style="font-size:.82rem">No vaults yet — create one from the CLI: <code>logicsrc teams push ${esc(team.slug)} prod</code></p>`}
: `<p class="faint mono" style="font-size:.82rem">No vaults yet — create one from the CLI: <code>logicsrc teams push ${esc(team.slug)} &lt;project&gt; &lt;env&gt;</code></p>`}
</div></div>`;
}