npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@defrex/autobuild-hosted-store-service

v0.8.0

Published

Readme

@defrex/autobuild-hosted-store-service

The optional hosted Autobuild service composes the remote BuildStore and the full TicketSource HTTP protocol with @defrex/autobuild-postgres-store. The root Next.js application mounts those machine protocols unchanged and serves the cookie-authenticated operator dashboard on the same origin. server.ts remains the named bare-Bun machine-service entrypoint for non-Next hosts.

Configure and run locally

The service and PostgreSQL adapter are published to npm (@defrex/autobuild-hosted-store-service, @defrex/autobuild-postgres-store) separately from the @defrex/autobuild CLI. The deployable web application runs from a release checkout: clone the compatible release tag and install it as shown in the complete environment reference, then migrate the database (the migration is idempotent):

DATABASE_URL=postgres://… bun run postgres:migrate

Set AB_STORE_SECRET, DATABASE_URL (or an explicit AB_POSTGRES_URL), one blob backend, and the web/auth variables below in that pinned checkout. Register a GitHub OAuth app with http://localhost:3000/api/auth/callback/github as its local callback, then run:

bun run dev

The GitHub app needs access to the user's primary email (user:email, or the GitHub App equivalent read-only email permission). Open http://localhost:3000. The browser receives only Better Auth's secure HTTP-only session cookie; it never receives a store/operator token or a signing/provider secret. To run only the legacy machine service use bun run hosted-store; AB_HOST defaults to 0.0.0.0 and PORT defaults to 3000. Check the public endpoint with curl http://localhost:3000/health; it reports the Autobuild and remote-protocol versions without opening the database. Clients use the deploy URL and an offline-minted token:

export AB_STORE=https://store.example.com
export AB_TOKEN="$(AB_STORE_SECRET='…' bun packages/hosted-store-service/src/bin.ts mint operator --ttl-seconds 3600)"
ab dispatch

Deployment operator tokens cover store and ticket operations, allowing one dispatcher credential. Legacy admin tokens still cover store administration but cannot access tickets.

The same deployment also serves the versioned operator API. External agents connect to the MCP server at /mcp — the same operator tool registry over Streamable HTTP with OAuth 2.1 through Better Auth — and every write is attributed to the person who authorized the client. Mint an attributed human-operator token with --user; unlike the deployment credential, it can use only the operator API and its signed identity is recorded on every control:

AB_STORE_SECRET='…' bun packages/hosted-store-service/src/bin.ts mint operator \
  --user 'Ada Lovelace' --ttl-seconds 3600

Mint a least-privilege build/session token with an explicit future expiry:

AB_STORE_SECRET='…' bun packages/hosted-store-service/src/bin.ts mint build \
  --build my-build --session implement --expires-at 2026-09-03T00:00:00Z

Minting is entirely local: the command reads only AB_STORE_SECRET, contacts no server, and prints only the token. Do not put the signing secret in a repository, browser, client host, command history, or logs; rotate it to revoke all tokens.

A deployment has one ticket backend. AB_TICKET_BACKEND defaults to database, which stores team-scoped tickets, comments, and blockers in PostgreSQL with the Triage, Ready, Doing, and Done lifecycle. Override those distinct names with AB_TICKET_TRIAGE_STATE, AB_TICKET_READY_STATE, AB_TICKET_DOING_STATE, and AB_TICKET_DONE_STATE. Set the backend to linear and provide LINEAR_API_KEY on the service to pass every request to the existing Linear adapter. That key never belongs on dispatcher or browser hosts. Team and claim/create policy arrive per request from repository config. The signed-in web Tickets surface uses the same durable effective config, discovers lifecycle names from this configured backend, and polls every two seconds. Its create/edit/move/block operations are delegated through short-lived attributed operator tokens; provider credentials and bearer tokens never reach the browser. Run the migration before serving (bun run deploy:build does so inside a hosted build); it adds separately versioned ticket and Better Auth schemas without changing an existing BuildStore v1 marker. Startup never creates or changes schema.

Each artifact is content-by-value and limited to 1,048,576 decoded bytes (1 MiB). Base64 and JSON make the HTTP body larger. A larger deposit receives a JSON 413 error naming that ceiling and does not mutate the store.

Each event read also accepts a bounded wait (?since=N&wait=S on the build and repository event routes): when nothing newer than since exists, the server holds the request until such an event is appended or S seconds elapse, then answers. wait is one or more ASCII digits (whole seconds); any other form is a 400 validation error, and a value above the hosted ceiling of 25 seconds is clamped to 25, never rejected. The ceiling must stay under the machine routes' maxDuration of 60 s (app/builds/[[...path]]/route.ts and app/repos/[[...path]]/route.ts), which exists to cover the hold; raise the two together if you change either.

Deploy to Vercel

  1. Import this repository and select its repository root as the project root.
  2. Select Bun. The checked-in vercel.json pins Bun 1.4.x and sets the build command to bun run deploy:build, which runs the idempotent migration against the deployment's own database URL and then builds the Next.js output. Pages and machine routes are one deployment.
  3. Create a GitHub OAuth app whose callback is https://YOUR_ORIGIN/api/auth/callback/github and grant read-only email.
  4. Add the store/database/blob variables and every web/auth variable below to each target environment. A Neon database and a Blob store connected through Vercel Storage inject DATABASE_URL and BLOB_READ_WRITE_TOKEN themselves. Generate an independent Better Auth secret with at least 32 high-entropy characters. AB_HOST and PORT are not needed.
  5. Deploy, then verify /health, browser sign-in, an operator control, a ticket, and an artifact round-trip. The build log names the database host the migration prepared; the build fails, and nothing goes live, when no database URL is configured or the existing schema is incompatible with the release being deployed.

The shape follows Vercel's Bun runtime. The 1 MiB decoded ceiling leaves room for base64/JSON beneath Vercel Functions' 4.5 MB request and response payload limit.

Web/auth variables

  • BETTER_AUTH_SECRET: separate 32+ character high-entropy session secret.
  • BETTER_AUTH_URL: exact public origin (http://localhost:3000 locally).
  • GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET: server-only OAuth app values.
  • AB_WEB_AUTH_PROVIDERS=github: enabled provider set.
  • AB_WEB_ALLOWED_EMAILS: comma-separated, case-insensitive operator allowlist.
  • AB_WEB_REPOSITORIES: comma-separated repositories visible through the web gateway. Entries are repository identities — normalized https:// origins (e.g. https://github.com/defrex/autobuild); ssh-like spellings such as [email protected]:defrex/autobuild.git are accepted and normalized. They must match the Store's identity for the repository: since the checkoutless dispatch change, BuildRecord.repo and the dispatcher's repository key are the repository's normalized origin URL, not a checkout path. Records written before that change are keyed by checkout path, are not migrated, and remain visible only where their recorded repoOrigin matches the querying checkout's origin (decision 2026-09-10: dropping the old identity's history is acceptable).
  • AB_WEB_MCP_RESOURCE (optional): the protected resource the MCP server binds tokens to; defaults to <BETTER_AUTH_URL>/mcp. See the MCP server.

Removing an email blocks its next gateway request even if its database-backed session has not expired. Rotate BETTER_AUTH_SECRET to end every browser session. AB_STORE_SECRET, GitHub's client secret, PostgreSQL/blob credentials, machine tokens, and OAuth account tokens are server-only and must never use a NEXT_PUBLIC_ name.

On another Bun-capable host, bun run dev or bun run start serves the full application. bun run hosted-store serves machine routes only.

Hosted dispatcher

The deployment can own the dispatch kernel: a cron-authenticated endpoint — GET /api/dispatch — runs one bounded dispatcher tick per configured repository per invocation. See the operator procedure for the schedule, incident pauses, and behavior details. Dispatcher variables (server-only, like every secret above; none reach the browser):

  • AB_DISPATCHER_ORIGIN: the deployment's public origin, used as AB_STORE for the kernel, the hosted ticket source, and guests. Absolute http(s) origin; https required in production.
  • AB_DISPATCHER_REPOSITORIES: comma-separated repositories the dispatcher serves, normalized https:// identities exactly like AB_WEB_REPOSITORIES. When unset, the deployment's AB_WEB_REPOSITORIES set is used, so a deployment configures its repository set once.
  • AB_DISPATCHER_BUDGET_SECONDS: per-invocation work budget (default 240, clamped 10–780); pair it with the route's maxDuration as described in the operator procedure.
  • AB_DISPATCHER_TOKEN_TTL_SECONDS: the TTL of the per-tick deployment operator token minted for guests (default 604800 — 7 days; minimum 3600). It must outlive your largest guest timeoutSeconds (e.g. 14400).
  • CRON_SECRET: the cron authorization shared secret. Unset or blank disables the endpoint entirely. It is never a signing input and is unrelated to AB_STORE_SECRET.
  • GITHUB_TOKEN or GH_TOKEN: the shared forge credentials the kernel (and its publication settlement) use. They stay on the service; guests never receive one.
  • AB_DISPATCHER_GITHUB_TOKENS: optional per-repository forge credential overrides — a JSON object mapping repository identities to GitHub token material, e.g. {"https://github.com/acme/one":"github_pat_…","[email protected]:acme/two.git":"ghp_…"}. Keys accept the same spellings as the repository set and must name a served repository; a repository with an override authenticates its dispatcher tick with that token (both GITHUB_TOKEN and GH_TOKEN), every other repository keeps the shared GITHUB_TOKEN/GH_TOKEN. Unset means shared-only, and a repository with neither fails its tick — origin-mode dispatch never uses the gh CLI login of whoever runs the service, unlike a local checkout-mode dispatcher. Tokens never appear in logs, responses, or artifacts; server-only like every secret above.
  • Guest-forwarded variables such as AI_GATEWAY_API_KEY flow through from the service environment to the guest session untouched.
  • AB_DISTRIBUTION_ARCHIVE: optional explicit path to the guest distribution archive. Unset, the kernel uses the archive ab-hosted-store pack-distribution wrote to .autobuild-dist/ during the deployment build (required for a bundled deployment, which has no bun to pack with at runtime — see the operator procedure).

The Sandbox SDK authenticates with the deployment's own OIDC identity inside Vercel functions (the x-vercel-oidc-token request header, forwarded to the kernel as VERCEL_OIDC_TOKEN for the tick), so no VERCEL_TOKEN belongs on the service. Each invocation deposits a dispatcher-effective-config repository artifact and durable tick/run facts under the hosted-dispatcher-<uuid> run id — the web dashboard shows hosted activity exactly as it shows a local dispatcher. The repository journal's events keep growing by roughly one tick per minute per repository (intentional); the run/config artifacts themselves are retention-bounded — the store keeps the latest 200 revisions per dispatcher artifact kind and prunes older revisions at deposit time, overridable with AB_ARTIFACT_RETENTION_MAX_REVISIONS.