Skip to content

Bootstrap npm packages as a real xmd run: elicit the OTP #276

Description

@taras

Motivation

The npm bootstrap (scripts/bootstrap-npm-package.md, draft #154 — this supersedes it) is executable markdown that cannot run as one: npm's interactive auth outlives #153's 30-second block limit, so the document instructs the operator to extract its own exec block with awk and run it under bash, passing the OTP through an environment variable they must race against a 30-second code window.

<Elicit> inverts this. The document asks the operator for the OTP at the point of use — through the platform's own ask-a-person machinery — and the npm commands become non-interactive and fast. The workaround dance dissolves; the bootstrap becomes a real xmd run.

Contract

deno task xmd run scripts/bootstrap-npm-package.md --props-package packages/web
  • The target package arrives as a prop ({props.package} interpolated into the exec blocks), replacing the PACKAGE_DIR env var.
  • The OTP arrives through <Elicit> immediately before the publish/trust block: schema { type: "object", properties: { code: { type: "string", pattern: "^\\d{6}$" } }, required: ["code"], additionalProperties: false }, message telling the operator to enter a fresh code. The binding interpolates as npm_config_otp={otp.code} so both npm publish and npm trust ride one code; the script's existing idempotency covers an expired second step (re-run resumes past the publish).
  • The exec blocks' guards, preview/publish split, empty 0.0.0-bootstrap.0 artifact under the bootstrap dist-tag, npm trust github invocation, and verification output all carry over from the current script. npm whoami stays a prose precheck — a missing login is a browser flow <Elicit> cannot carry.
  • Run without a journal. A recorded OTP is stale by construction; the document must not be run with -j, and says so. (An unchanged question would replay the recorded code rather than re-ask — the fingerprint guard only refuses changed questions.)
  • Blocks must individually stay under Make executable code blocks use the CLI timeout #153's 30-second limit; with the OTP pre-supplied they run in seconds. If a slow registry makes that tight, split publish and trust into separate blocks rather than reintroducing the materialization workaround.

Spec maintenance (discovered during the 2026-08-02 web bootstrap)

specs/release-process-spec.md §6's premise — "npm exposes trusted-publisher settings only on a package that already exists" — is no longer true: npm 11.17's npm trust github succeeded against a nonexistent package (@executablemd/web, trust id a2479f35-…, while the registry still returned E404). §6 must be rewritten around the new procedure this document provides, and should state what pre-existence trust does and doesn't guarantee once verified against a real first publish.

Dependencies

Acceptance criteria

  • A full bootstrap of a fresh package runs end to end as one xmd run invocation: preview, elicited OTP in the browser form, publish under the bootstrap dist-tag, trust configuration, verification output.
  • A re-run against an already-bootstrapped package skips the publish and re-runs trust idempotently.
  • The document refuses to run usefully with a stale journal (documented, and the no--j instruction is in the Run section).
  • specs/release-process-spec.md §6 matches the new procedure in the same PR.
  • Draft Make npm bootstrap resumable #154 is closed as superseded.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions