Atproto AMA app
askimut scripts
1 folder · 27 files

README.md

Database Scripts #

Bluesky AMA Public Smoke Test #

Everything in the Bluesky AMA pipeline that runs in-process is covered by pnpm test. The smoke test below exists only for the transports that cannot be reproduced in-process: public Jetstream post discovery, OAuth against a real PDS, and the public AppView's real getPostThread shape. See ADR-0010 for why there is no local scenario command.

Prerequisites #

  • A dedicated public Recipient account, used for signing into the app.
  • A distinct public Asker account. Any public account works — Askimut never contacts an Asker's PDS, so a self-hosted one buys no extra coverage.

Setup #

cp .env.bsky-smoke.example .env.bsky-smoke.local
pnpm dev:bsky:smoke

The launcher will:

  • validate that Jetstream, AppView and the PDS point at public endpoints and that the database is an isolated local SQLite file;
  • migrate the isolated database;
  • clear TURSO_AUTH_TOKEN;
  • blank DEV_PDS_URL, DEV_PLC_URL, and PUBLIC_URL so OAuth cannot fall back to local development services;
  • normalize APP_URL to a loopback origin, which is what selects the loopback OAuth client; and
  • start the web app and Ingester with [web] and [ingester] output prefixes, then print the checklist.

Checklist #

  1. Sign in through the web app as the dedicated public Recipient.
  2. Enable Questions open and tag discovery in settings.
  3. Wait until the Ingester log shows the posts stream connected with the Recipient's DID in its wantedDids. Look for [jetstream:posts] connect wantedDids=[did:plc:…] (initial connect) or [jetstream:posts] options_update wantedDids=[did:plc:…] (after a toggle reload). The DID arrives either with the profile record over Jetstream or on the Ingester's periodic reload, so this can lag the toggle by up to a minute. A connected stream that predates the toggle does not carry the DID.
  4. Only then, from the Recipient's public account, post a top-level post containing an authentic #AMA rich-text facet. The stream has no replay: a Root posted too early is missed permanently.
  5. Verify the AMA Root was discovered with tag origin, in the settings list and/or the isolated database.
  6. From the public Asker account, post a first-level reply to that AMA Root.
  7. Open or refresh the Recipient's Inbox to trigger AppView revalidation.
  8. Verify the reply appears as a Pending question and that its Bluesky source URI matches the public reply.

Reading Failures #

Both halves of this workflow fail quietly, so check the Ingester log rather than trusting an empty screen.

  • AMA Root never appears: confirm the stream was connected and carrying the Recipient's DID before the post (step 3). If the log shows the posts stream repeatedly reconnecting, Jetstream is rejecting our subscription or our options update — the socket close is retried with backoff, so a malformed request looks like a flapping stream, not an error.
  • Inbox stays empty after the Root is found: a failed or drifted getPostThread is swallowed and yields no snapshot, so look for the [bsky] getPostThread failed log line. If the call succeeded but produced nothing, the real AppView response has drifted from the thread fixtures used by the suite — fix the fixtures, not the smoke test.
  • Reply is not visible: confirm the reply is public and first-level, and that it is visible from https://api.bsky.app. Allow time for indexing, then refresh the Inbox.
  • OAuth reaches the local network: stop the launcher and check .env.bsky-smoke.local. Sign in with the public Recipient, not a .test account.

Cleanup #

The public AMA post and reply are real posts and must be deleted by hand from the accounts that created them. Stop the launcher before removing the isolated local.db.bsky-smoke* files or the ignored .env.bsky-smoke.local.

Reset Dev Environment #

The dev network is ephemeral — PDS/PLC state is not persisted across restarts. DIDs change each boot; re-login after a restart. Fixtures auto-seed when pnpm dev:network starts.

Full reset (DB + restart network) #

Clears all fixture users from local.db and restarts dev-network (which re-seeds):

pnpm run reset:all

DB + network restart #

pnpm run db:reset

What reset clears from local.db #

  • Fixture users: alice.test, bob.test, carol.test, dave.test, askimut.test
  • All questions, answers, blocks, suspensions, OAuth sessions, and notifications for those users

Notes #

  • Destructive by default: Runs immediately without confirmation
  • Background start: Dev-network starts in background, logs go to .output/dev-network.log
  • Wait a moment: After reset, wait 2–3 seconds for dev-network to initialize and auto-seed

Seed Dev Fixtures #

Fixtures auto-seed when pnpm dev:network starts. Use pnpm seed to re-seed without restarting the network.

Workflow #

pnpm dev:network          # ephemeral PDS + auto-seed
pnpm dev:ingester         # confirms unsynced fixture + live writes
pnpm dev:standard-site    # only when testing Standard.site fetch UI
pnpm seed                 # re-seed only (network already running)

Scenarios covered #

Scenario Description
Bob answered Q&A bob → alice, native askimut answers
Bob shared answer bob → alice, multiple questions, one answer content
Bob Standard.site bob → alice, answered via site.standard.document
Bob pending normal pending question for alice
Carol blocked pending questions, blocked by alice
Dave suspended pending questions hidden from alice's inbox, suspended app-wide by askimut
Unsynced pending published on PDS, reindexed=false in DB until ingester runs

Prerequisites #

  • Dev-network running (pnpm dev:network) — fixtures seed automatically on startup
  • Ingester recommended (pnpm dev:ingester) to confirm the unsynced fixture

Local Standard.site fixture (alice.test) #

A fake Standard.site blog for linking Answer Content during local dev. Real internet Standard.site URLs fail for alice.test because the document owner DID must match the logged-in account.

Prerequisites #

  • Dev-network running (pnpm dev:network)
  • /etc/hosts entry (optional for Askimut linking — the dev fetch pins loopback; add if you want to open the article URL in a browser):
    127.0.0.1 standard-site.dev.test
    
  • STANDARD_SITE_DEV_ORIGIN=https://standard-site.dev.test:8443 in .env (see .env.example)
  • Signed in as alice.test in the web app
  • A pending question targeted to alice (from pnpm seed or ask as bob)

One-command setup #

pnpm dev:standard-site

This starts the HTTPS dev blog on port 8443. The PDS record is published by pnpm seed; re-run seed if the doc is missing.

pnpm dev:standard-site

Or publish the doc only (also done by pnpm seed):

pnpm tsx scripts/publish-alice-standard-site.ts
pnpm tsx scripts/dev-standard-site-server.ts

Inspect records:

pnpm tsx scripts/show-alice-records.ts site.standard.document

Troubleshooting #

Symptom Fix
Could not fetch external content Dev blog server not running; missing /etc/hosts; STANDARD_SITE_DEV_ORIGIN unset
Forbidden / ownership mismatch Signed in as wrong account, or pasted someone else's URL
unverifiable-url Re-run publish + server so backlink and canonical URL match
Publish fails Start dev-network first (pnpm dev:network; fixtures auto-seed)

State and TLS material live under .output/standard-site-dev/.