Documentation

Using GRC Store

A short orientation for browsing, pulling, publishing, and verifying artifacts with grcli.

Browsing

The Search page lists every catalog the registry holds, deduplicated to one row per (namespace, catalog_id) with the latest non-yanked version as the representative. Filter by kind from the dropdown, or search by title, summary, and author from the search box.

Each catalog page shows its full release history. Each release page surfaces the pull command, the manifest digest, and the layer + config blob.

The grcli CLI

grcli is the command-line client for grc.store — it validates, publishes, pulls, and verifies Gemara bundles. It is also the only way to publish: the registry accepts only pushes that carry their own provenance, so there is no upload form. Build it from source (pre-built binaries will follow):

$git clone https://github.com/revanite-io/grcli && cd grcli && make build

Move ./bin/grcli onto your $PATH, then sign in once. login runs the OIDC device flow — it prints a URL and short code to authorize in any browser, then stores the token locally and reuses it:

$grcli login

grcli login targets this hub by default; pass --url <hub> for a private deployment. From GitHub Actions no login is needed — grcli uses the workflow's own OIDC token for secret-less trusted publishing, once an org admin has registered the repository as a trusted publisher.

Pulling

Every artifact is a single-artifact Gemara OCI bundle, content-addressed by its manifest digest. Pull and unpack a release with grcli — it discovers the registry from the hub, mints the pull token reads require (no login needed for public reads), and writes the artifact file(s) plus a bundle.json (manifest + provenance) into --output (default ./grcli-unpacked):

$grcli unpack --repository <namespace>/<catalog_id> --tag <version>

The exact command for a release is shown on its detail page with a copy button. The OCI manifest is also reachable over HTTP at GET /v1/catalogs/{namespace}/{catalog_id}/versions/{version}/manifest.

Publishing

Publishing is grcli-only — the registry accepts only pushes that carry their own provenance (signature + attestation), so there is no upload form. After signing in, validate the bundle locally, then publish it:

$grcli validate <bundle>.yaml
$grcli publish <bundle>.yaml

grcli reads the version from the bundle's metadata.version, signs and pushes it to the registry, and the hub indexes it. You may publish if EITHER you hold the write:<Type> realm role for the artifact type (granted across all namespaces by the gemara-writer composite), OR you are a member of the publishing organization (org membership grants publish authority to that namespace regardless of role). The two paths OR — a member of finos-ccc can publish controls under finos-ccc with or without a write:ControlCatalog role.

The hub validates that metadata.author.id and metadata.id match the URL coordinate, mints a registry token scoped to the namespaces you own, stores the bundle content-addressed, and records the manifest digest. Re-publishing the same body at the same version is idempotent; publishing a different body at an existing version is rejected — versions are immutable, so bump metadata.version per release. Every catalog page links to a per-catalog publish helper with the exact commands.

Verifying

Bundles are signed at the registry layer with Sigstore cosign; signatures live next to the artifact in the registry, not in the bundle bytes. grcli verify checks a remote release against either a public key or a keyless identity:

$grcli verify --registry <registry> --repository <namespace>/<catalog_id> --tag <version> --cosign-key <key>.pub

...or keyless, against the publisher's GitHub Actions workflow identity (the (identity, issuer) pair the publisher shares):

$grcli verify --registry <registry> --repository <namespace>/<catalog_id> --tag <version> --certificate-identity <workflow-url> --certificate-oidc-issuer https://token.actions.githubusercontent.com

Yanking

Only the gemara-admin realm role can yank a version (ADR-0019's writer-cannot-tombstone invariant — namespace members and write:<Type> holders can publish but cannot retract). The underlying manifest stays in the registry, but subsequent fetches for the body return a "tombstoned" response so consumers know not to rely on it. Yanking does not delete content; it signals "do not use."