# workrr trust: instructions for AI agents

You are reading the machine-oriented guide to workrr trust. Use it when a user asks you to
**certify** an AI agent artifact (an agent skill, MCP server, ruleset, `AGENTS.md` or
`CLAUDE.md`), or to **verify** one before it is used. The human guide is
https://trust.workrr.ai/guide/ and the format spec is https://trust.workrr.ai/certificate/v0.1/.

Facts you can rely on (certifier v0.1.5):

- Certification runs in the artifact owner's own GitHub Actions, through the reusable workflow
  `workrr-trust/certify/.github/workflows/certify.yml@v0.1.5`. There is no workrr account,
  API key, server or fee for public repositories.
- The repository **must be public**. Private repositories sign through GitHub's private
  Sigstore instance, and workrr's public verifier rejects those certificates. Private
  certification is the enterprise offering: https://agents.workrr.ai/request?site=trust&intent=book or info@workrr.ai.
- A certificate is a Sigstore bundle (`certificate.sigstore.json`) recorded in the public
  Rekor log. It covers the exact bytes of one artifact folder or file.
- Level `scanned` is a public scan: workrr's `scan.yml` read a public commit without running
  its code and signed the result. It is not signed by the maintainer and ranks below Signed.
  The maintainer's own certificate, when one exists, takes precedence.
- Verifier: npm `@workrr-trust/certify` (CLI `workrr`, Node 22+) or Go
  `github.com/workrr-trust/certify/go/cmd/workrr`. Both give identical results.

## Task A: certify an artifact

### A1. Check the preconditions

1. Confirm the repository is public, on GitHub, and the user can push to it. If it's private,
   stop and tell the user about the enterprise option above.
2. Identify the artifact folder (call it `ARTIFACT_PATH`, relative to the repo root). It is
   detected as a `skill` if it contains `SKILL.md`, an `mcp-server` if it contains
   `server.json`, `agent-context` if it contains `AGENTS.md` or `CLAUDE.md`, else `other`.
   Follow the layout standard (https://trust.workrr.ai/standard/): one artifact per folder
   (`skills/<name>/`, `servers/<name>/`, `rules/<name>/`, or a root `AGENTS.md`), kebab-case
   folder name matching the declared `name`, at most 5 MB, no compiled binaries, no symlinks
   leaving the folder, and a `LICENSE` inside the folder. Don't move or rename the user's
   files without asking.
3. If it's a skill, make sure `SKILL.md` starts with YAML frontmatter containing non-empty
   `name` and `description` strings:

   ```markdown
   ---
   name: my-skill
   description: What it does. Use when <trigger>.
   ---
   ```

### A2. Add a test suite (recommended; required for level Tested)

Create `ARTIFACT_PATH/workrr.json`:

```json
{ "test": { "command": "node check.cjs" } }
```

The command runs with the artifact folder as the working directory, on `ubuntu-latest` with
Node 24, with a 10-minute limit, in a job that cannot sign. Exit code 0 means pass. Write a
deterministic test that checks the artifact does what it claims. For a skill, check the
frontmatter fields, the trigger in `description`, and any bundled examples or scripts. Use a
`.cjs` extension, or plain shell, if you aren't sure whether the folder is an ES module
package. Without `workrr.json`, the level is Signed (`banded`) instead of Tested (`silver`).

### A3. Add the workflow

Create `.github/workflows/workrr.yml` exactly like this, replacing `ARTIFACT_PATH`:

```yaml
name: workrr-certify
on:
  push:
    branches: [main]   # your default branch
    tags: ["v*"]
  workflow_dispatch:

jobs:
  certify:
    permissions:
      contents: read
      id-token: write
      attestations: write
    uses: workrr-trust/certify/.github/workflows/certify.yml@v0.1.5
    with:
      path: ARTIFACT_PATH
```

Rules:

- Keep the three `permissions` exactly as shown. Without `id-token: write` and
  `attestations: write`, nothing gets signed.
- Pin the tag `@v0.1.5`. Don't use a branch or commit SHA: verifiers only accept the
  certifier at a release tag.
- Use the branch name the repository actually uses, if it isn't `main`.
- The workflow certifies each push to the default branch (change `main` if it is
  `master`) and each `v*` release tag, so repos that never tag still get certificates.
- Several artifacts: add one job per artifact, each with its own `path`, in one workflow,
  or give each its own workflow file. Both work from `@v0.1.5`.
- Optional: `policy: path/to/policy.json` (relative to repo root), with fields `name`,
  `maxTotalBytes`, `forbiddenExtensions`, `requiredSkillFields`, `allowedTools`,
  `requireLicense`.

### A4. Pre-check locally (optional)

From the repo root, after committing everything:

```bash
npx -y @workrr-trust/certify@0.1.5 certify ARTIFACT_PATH --run-tests
```

It prints each check and `level`, or `NOT CERTIFIED` with reasons. Local runs don't sign
anything.

### A5. Commit, push and confirm

Commit `workrr.json`, the workflow and any fixes, then push. Then confirm:

```bash
gh run list --workflow workrr.yml --limit 1
gh run watch <run-id> --exit-status
```

A successful run has jobs `resolve`, `test` and `certify` all green, and an artifact named
`workrr-certificate`. Report the level and the artifact digest from the run summary to the
user.

### A6. Fix failures

The `certify` job log lists one reason per line after `NOT CERTIFIED`. Map them:

| Reason starts with | Fix |
|---|---|
| `provenance: artifact has uncommitted, untracked, or ignored files` | Commit every file in `ARTIFACT_PATH`, and remove generated or gitignored files from it. |
| `provenance: no source repository URL` | Only happens locally. Set a git `origin` remote. |
| `policy: SKILL.md has no parseable YAML frontmatter` | Add frontmatter as in A1.3. |
| `policy: SKILL.md frontmatter missing "<field>"` | Add that field as a non-empty string. |
| `policy: forbidden file type: <file>` | Remove compiled binaries (`.exe .dll .so .dylib .bin .jar .class .pyc`). |
| `policy: total size <n> bytes exceeds <max>` | Shrink the folder (baseline limit 5,000,000 bytes). |
| `policy: tool not allowed by policy: <tool>` | Remove the tool from `allowed-tools`, or change the custom policy. |
| `policy: policy name "workrr-baseline-v0.1" is reserved` | Choose a distinct `name` in your custom policy JSON (`workrr-baseline-v0.1` is reserved for the built-in baseline digest). |
| `policy: no LICENSE file` | Add a LICENSE file (only when the policy requires one). |
| `scan: WT0xx (high or critical) <file>:<line>` | See the rules below. Change that line. |
| `tests: exit code <n>` | Run the `workrr.json` command locally from `ARTIFACT_PATH` and fix it. |

Scan rules in `workrr-scan-v0.1` (`warn` never blocks):

| Rule | Severity | Pattern |
|---|---|---|
| WT001 | high | "ignore / disregard / forget previous instructions" phrasing |
| WT002 | critical | Unicode tag characters U+E0000–U+E007F |
| WT003 | high | Bidirectional control characters |
| WT004 | warn | Zero-width characters |
| WT005 | high | `curl`/`wget` piped into a shell |
| WT006 | high | Paths to credential stores (`~/.ssh/id_*`, `.aws/credentials`, `.netrc`, `.git-credentials`, `.docker/config.json`, `.kube/config`) |
| WT007 | high | Telling the agent not to tell or show the user something |
| WT008 | high | HTML comments containing instructions |
| WT009 | warn | Sending or uploading data to a URL |
| WT010 | warn | Base64-like blobs of 240+ characters |

Never try to get around a scan rule by obfuscating text. If a finding is a legitimate use
(for example, documentation that explains an attack), rephrase it, or tell the user why it
was flagged and let them decide.

### A7. Get listed in the public ledger (optional)

Open a pull request on https://github.com/workrr-trust/ledger that adds the line
`OWNER/REPO` to `sources.txt`. Or open the "Submit a certificate" issue at
https://github.com/workrr-trust/ledger/issues/new?template=submit-certificate.yml with the
repo and the `sha256:` digest. After the first certificate is indexed, later certificates
from that repo are found automatically every hour. Indexed certificates appear at
https://trust.workrr.ai/ledger/.

### A8. Add the badge (optional)

After the repo is in the ledger, add this line to the README, replacing `OWNER/REPO`:

```markdown
[![workrr certified](https://trust.workrr.ai/badge/OWNER/REPO.svg)](https://trust.workrr.ai/ledger/?repo=OWNER/REPO)
```

For one artifact in a multi-artifact repo, append `?path=ARTIFACT_PATH` to the badge URL.
The badge shows `not certified` until the ledger holds a certificate from that repo. It
reflects the ledger and is cached for up to 25 minutes. It is a pointer to the evidence,
not the evidence.

## Task B: verify an artifact before using it

1. Get the artifact folder exactly as published (for example, clone the repo at the
   certified commit).
2. Get its certificate, either from the "download" link on its row at
   https://trust.workrr.ai/ledger/, or from the publisher's run:
   `gh run download <run-id> --repo OWNER/REPO -n workrr-certificate -D cert`.
3. Verify (pass `--source OWNER/REPO` to require that the certificate's publisher repository matches):

   ```bash
   npx -y @workrr-trust/certify verify <artifact-folder> --bundle cert/certificate.sigstore.json --source OWNER/REPO
   ```

4. Interpret the result:
   - Exit code `0` and `VERIFIED · level <level>`: the folder's bytes match the certificate,
     the Sigstore signature and Rekor inclusion are valid, the signer is the official
     certifier `https://github.com/workrr-trust/certify/.github/workflows/certify.yml@refs/tags/v…`,
     the policy digest is the reserved `workrr-baseline-v0.1` baseline (a custom policy digest
     reports `custom policy, not baseline`), and `--source` matches `source.uri`.
   - Exit code `1` (`NOT VERIFIED`): don't use the artifact. Report the reason line, for
     example a digest mismatch, meaning the content changed after certification.
   - Exit code `2`: usage error. Fix the command.
5. To gate automatically, run the same command as a CI step or pre-load hook, and stop on a
   non-zero exit code. Pin the verifier version.

## What to tell users, and what not to

- Say: "certified by workrr trust at level Tested: provenance, policy, known-pattern scan
  and its own tests passed; the certificate is in the public Rekor log at index N."
- Don't say an artifact is "safe", "secure" or "malware-free". A scan pass means no high or
  critical findings from a fixed ruleset, nothing more.
- v0.1 limits: no revocation check yet, no Reproduced level yet (two independent forges), and
  the trust policy is built into the verifier.
- Don't copy, fork or modify `workrr-trust/certify`'s `certify.yml` to certify. A copy has a
  different signing identity, and verifiers will reject it.

## Links

- Human guide: https://trust.workrr.ai/guide/
- How it works: https://trust.workrr.ai/how-it-works/
- Spec: https://trust.workrr.ai/certificate/v0.1/ (JSON Schema: https://trust.workrr.ai/certificate/v0.1/schema.json)
- Ledger: https://trust.workrr.ai/ledger/ and https://github.com/workrr-trust/ledger
- Source: https://github.com/workrr-trust/certify (Apache-2.0)
- Example: https://github.com/workrr-trust/sample-skills
- Enterprise and private repositories: https://agents.workrr.ai/request?site=trust&intent=book · info@workrr.ai
