Commit graph

5 commits

Author SHA1 Message Date
aa4a690d60 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>
2026-07-30 11:43:33 -07:00
898d5503b8
fix(pwa): unbreak sign-out, and stop echoing $PUBLIC_ORIGIN in the CLI hint (#108)
Two bugs on the dashboard, both fixed by handing appBar/CLI_HINT the request.

Sign-out was broken for everyone. csrfGuard rejects any POST whose _csrf does
not match the mc_csrf cookie, and /auth/logout is a POST that is not on the
exempt list, but the sign-out form carried no hidden field -- every click
answered 403 "bad csrf token". appBar now takes the request rather than the
user, because it needs the token as well as the identity. The field is written
out instead of reusing csrfInput(): html.mjs is the view layer and imports
nothing, and pulling in session.mjs would drag the database driver with it.

The "Connect the CLI" snippet still printed $PUBLIC_ORIGIN, so users on
app.logicsrc.com were told to point LOGICSRC_API at the generated Railway
hostname. #105 added requestOrigin() for exactly this and fixed the device-flow
URLs; the dashboard hint was missed. It now follows the request too, which is
not a hardcode swap -- the same deployment answering on its Railway hostname
still self-describes correctly.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 10:56:36 -07:00
60c0cbfbce
fix(pwa): return the caller's own host in the CLI device-flow URLs (#105)
Some checks are pending
CI / build (push) Waiting to run
test / test (push) Waiting to run
`logicsrc login --device` told users to open
https://logicsrc-credentials-production.up.railway.app/cli/device even when they
had reached the app on the real domain. /cli/device/code built verification_uri
from `config.origin`, which is a single fixed value read from $PUBLIC_ORIGIN, so
the response was wrong for every hostname except the one that variable happened
to name.

Derive the origin from the request instead: whatever host the CLI called is the
host it gets sent back to. Express honours X-Forwarded-Proto/Host here because
server.mjs sets `trust proxy` behind Railway's TLS terminator.

Deliberately scoped to the two device-flow URLs. The WebAuthn expectedOrigin in
passkey.mjs stays pinned to config.origin — validating a signature against a
host the caller supplied would defeat the check.

Note this fixes which URL is *printed*; the host still has to route to this
service for the link to load.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-30 09:19:37 -07:00
cf475f0f4c fix(cli): point logicsrc login at the real app + add device-code login
Some checks are pending
CI / build (push) Waiting to run
test / test (push) Waiting to run
`logicsrc login` defaulted to http://localhost:4010 — a dev origin that
doesn't exist on an installed machine, so the printed authorize URL went
nowhere. It now defaults to the hosted credentials app (apps/pwa), reads
the documented $LOGICSRC_API, and only reuses a stored apiUrl once that
identity has actually completed a login (which is how machines got stuck
pointing at localhost). Note logicsrc.com is the marketing site and has
no /cli routes.

The loopback flow is also unusable over SSH: redirect_uri is
http://127.0.0.1:<port>/callback, which resolves to the *browser's*
machine, not the CLI's. Added a device-authorization flow — the CLI
prints a short user_code, the human approves it from any browser:

  POST /cli/device/code   mint device_code + user_code (10 min TTL)
  GET  /cli/device        approve page (login required; typo-tolerant)
  POST /cli/device        approve/deny (CSRF-guarded browser form)
  POST /cli/device/token  CLI polls -> lsk_ API key

device_code is stored sha256-hashed, single-use, with authorization_pending
/ slow_down / access_denied / expired_token poll semantics. The CLI picks
the flow automatically (SSH/CI/no-DISPLAY -> device), with --device/--web
to force it and a fallback to loopback against servers without /cli/device.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 18:07:49 +00:00
9ba044577f feat(pwa): logicsrc credentials app — real auth + Turso, redesigned; retire commandboard-api credshare
Some checks failed
CI / build (push) Has been cancelled
test / test (push) Has been cancelled
Adds apps/pwa: an Express + libSQL/Turso app that is now the home of team
credential sharing, with the moshcode-style auth stack ported and reskinned to
match logicsrc.com (light theme, Inter, green accent).

apps/pwa
- auth: email/password (scrypt), passkeys (WebAuthn), CoinPay OAuth, cookie
  sessions, and lsk_ API keys for the CLI via a loopback OAuth-PKCE flow
  (/cli/authorize + /cli/token). Ported from the moshcode PWA.
- credshare API (/api/credshare/*): teams, members, invites, vaults, sealed
  grants, ciphertext secrets, audit — authed by session OR Bearer lsk_ key.
  Zero-knowledge: only ciphertext + sealed vault keys + public keys stored.
- teams dashboard, accept-invite, and settings (API keys) pages, server-rendered
  in the LogicSRC brand (lib/html.mjs).
- migrations (libSQL) 001_auth + 002_credshare, migrate-on-boot; Turso via
  TURSO_DATABASE_URL / TURSO_AUTH_TOKEN, or a local file db for dev.
- trimmed moshcode-specific approvals/credits/push/deliver.

CLI
- `logicsrc login` now does browser loopback OAuth-PKCE against the app and
  stores an lsk_ token (email-OTP removed); --token for CI. Client repointed.

Distribution
- install.sh (served at logicsrc.com/install.sh) installs the CLI from the
  GitHub repo: tarball -> npm install -> `npm run build:cli` -> logicsrc wrapper.
- root build:cli builds only the CLI's workspace chain (skips web/api/next).

Cleanup
- removed the commandboard-api credshare backend (superseded by the PWA) and its
  Supabase/Turso stores + libsql dep; commandboard-api tests green (40).
- removed the Next.js /teams page (the PWA is the web UI now).

Verified end-to-end: two accounts register on the PWA, mint lsk_ keys, CLI login
uploads identity keys, owner pushes an encrypted .env, teammate invited ->
accepted -> granted -> pulls the exact file. Server stores ciphertext only.
Full workspace build + tests green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-13 14:29:29 +00:00