Changelog

Content pinning and the GitHub App

Productv0.12.0

Reads can be pinned to a numbered release, so a build takes content as a version rather than as whatever the API returns. myna.lock records the pin, and connecting a repository makes publishing open a pull request that moves it.

Pinned reads

Pass a release to the client and every read answers with what that release served.

import { createMyna } from "@myna-sh/sdk";

const myna = createMyna({ project: "my-site", release: 42 });

await myna.entries.list("posts");                     // as release 42 served it
await myna.entries.list("posts", { release: 41 });    // an older one
await myna.entries.list("posts", { release: null });  // live

Over HTTP the parameter is at, and it takes a release number, release-42, or an ISO 8601 instant, which resolves to the newest release published at or before it. Filters, q, ordering, and keyset pagination apply to the pinned set and are still evaluated by the database. include resolves embedded entries at the same release.

An entry is addressed by the slug it carried at that release, so a URL built from a pinned read resolves at that release after a rename. Pinned responses carry Cache-Control: public, max-age=31536000, immutable.

Collection visibility and editorial order are read live: entries.rank carries no revision, and visibility is an access decision rather than content. See reading content.

myna.lock

myna pull                 # pin to the newest release
myna pull --release 42    # pin to a specific one
myna pull --check         # non-zero exit when the pin is behind

The file names a project, a release, and the date it published. Commit it, and the build reads at it:

import { readLock } from "@myna-sh/sdk/lock";

const lock = readLock();
const myna = createMyna({
  project: "my-site",
  ...(lock ? { release: lock.release } : {}),
});

@myna-sh/sdk/lock is a Node-only entry point. No lockfile means live reads, so a repository that has not adopted it is unaffected.

Pull requests

Install the Myna GitHub App, then open Settings → GitHub on a project and pick a repository. Publishing opens a pull request that moves myna.lock, with the field-level diff of every release in the span as its description. The repository's own checks run against the pinned content.

The app asks for Contents and Pull requests, read and write, on the repositories you select. Myna stores the installation id; the token that writes the pull request is requested per operation and expires within the hour.

One branch per project and release, so a redelivered event or a retry finds the branch and opens nothing.

myna pull --open-pr

myna pull --open-pr
myna pull --open-pr --run 'pnpm build:content'

Opens the same pull request from CI, using git and the GitHub CLI. Use it when the repository is not on GitHub, or when the build generates something from content — --run regenerates that artifact at the new pin and commits it alongside, which the app cannot do because it does not run your build.

Releases

myna releases diff 42

Field by field, for a release that already shipped.

Upgrading

Nothing to change. Pinning is opt-in and unpinned reads behave as before. GET /v1/meta advertises content.at and github.app.

Affects sdk · cli · api · dashboard

Give your agent something to work with.

Free to start, no card required. Sign in with GitHub, enable the products you want, and point your agent at them.