Version: 0.1
Status: Draft · Open RFC
Trust model — read this first
The forge block is a claim, not a proof. Anyone can write
"verified": true into their own manifest. A manifest is controlled by its
author; nothing in the block itself prevents forgery.
Consumers (CLIs, registries, AI clients) MUST treat the block as a cache hint and verify trust through one of two channels:
- Registry lookup — query
GET https://forgeregistry.com/api/v1/packages/:idand compare. The registry's verification records are the source of truth. - Signature verification — verify the publisher's Ed25519 signature over the canonical payload (see Signing below) against the public key served by the registry.
A consumer that renders a "verified" badge based solely on the block's contents is non-conformant with this spec.
Signing and key distribution
When a publisher runs forge publish, the CLI generates an Ed25519 keypair
(stored locally in ~/.forge/keys/) and signs the canonical payload:
forge:v1:{package_name}:{github_url}:{github_login}
The public key (SPKI PEM) and the base64 signature are stored in the
registry's verification record and served from
GET /api/v1/packages/:id as verified_publisher.publicKey and
verified_publisher.signature.
Key distribution: consumers fetch the public key from the registry at verification time. This is trust-on-first-use anchored at the registry — the registry binding key → GitHub identity is the root of trust. A transparency-log model (Sigstore) is under evaluation for v0.2 to remove the registry as a single point of trust; see the roadmap.
Key rotation: re-running forge publish with a new keypair replaces
the stored key and signature. Old signatures become invalid immediately.
Revocation
Verification can be withdrawn — e.g. a maintainer account is compromised or
a malicious update ships. Revoked entries keep their record (audit trail)
but gain a revoked block in the registry's API response:
"revoked": {
"revokedAt": "2026-06-11T09:00:00Z",
"reason": "maintainer account compromised"
}
Consumers MUST check for revoked on every verification and treat a
revoked package as untrusted regardless of any forge block contents,
signatures, or cached state. forge verify exits non-zero for revoked
packages.
Top-level structure
The forge block is added as a top-level key in your existing manifest file.
manifest root
└── forge object, optional
├── version string, required if forge block is present
├── publisher object, optional — identity & verification
├── security object, optional — scan results
├── evals object, optional — performance attestations [planned]
└── compose object, optional — composability hints [planned]
forge.version
| Field | Type | Required |
|---|---|---|
version |
string | yes (if forge block present) |
The version of this spec the block conforms to. Must be "0.1" for this
version of the spec.
"forge": {
"version": "0.1"
}
forge.publisher
Populated automatically by Forge when a listing is claimed. You can include it manually if you prefer — but remember it is a claim: consumers verify it against the registry's records or the publisher's signature (see Trust model above), never at face value.
| Field | Type | Description |
|---|---|---|
verified |
boolean | true if Forge has verified publisher identity |
verification_method |
string | How verification was performed (see values below) |
github_login |
string | GitHub username of the verified publisher |
verified_at |
string | ISO 8601 datetime when verification occurred |
verification_method values:
| Value | Description |
|---|---|
github-owner |
GitHub login matches the repo owner |
github-collaborator-api |
Forge confirmed repo access via GitHub collaborator API |
manual |
Manually reviewed and approved by the Forge team |
"forge": {
"version": "0.1",
"publisher": {
"verified": true,
"verification_method": "github-collaborator-api",
"github_login": "sam-rivera",
"verified_at": "2026-05-27T14:30:00Z"
}
}
forge.security
Populated automatically by Forge after a security scan runs. Read-only from the publisher's perspective — Forge writes these values; they are not self-reported.
| Field | Type | Description |
|---|---|---|
scanned |
boolean | true if a scan has been run |
scan_level |
string | "base" (default) or "verified" |
last_scan |
string | ISO 8601 datetime of most recent scan |
scanner_version |
string | Version of the Forge scanner that ran |
vulnerabilities |
integer | Total known CVEs for this version (from OSV database) |
critical |
integer | Critical severity vulnerabilities |
high |
integer | High severity vulnerabilities |
moderate |
integer | Moderate severity vulnerabilities |
low |
integer | Low severity vulnerabilities |
suspicious_scripts |
boolean | true if lifecycle scripts contain flagged patterns |
status |
string | "clean" | "warnings" | "critical" | "failed" |
"forge": {
"version": "0.1",
"security": {
"scanned": true,
"scan_level": "base",
"last_scan": "2026-05-27T14:30:00Z",
"scanner_version": "0.1.0",
"vulnerabilities": 0,
"critical": 0,
"high": 0,
"moderate": 0,
"low": 0,
"suspicious_scripts": false,
"status": "clean"
}
}
forge.evals — planned
Not yet implemented. Specified here for early adopter feedback.
| Field | Type | Description |
|---|---|---|
accuracy |
number | 0–1 accuracy score |
latency_p50_ms |
integer | Median latency in ms |
latency_p99_ms |
integer | p99 latency in ms |
eval_suite |
string | Eval suite ID (e.g. forge/standard-v1) |
total_runs |
integer | Number of test runs |
last_evaluated |
string | ISO 8601 datetime |
attestation |
string | "self-reported" | "forge-verified" | "reproducible" |
forge.compose — planned
Not yet implemented. Specified here for early adopter feedback.
| Field | Type | Description |
|---|---|---|
depends_on |
string[] | Package IDs this package calls at runtime |
can_be_called_by |
string[] | Package IDs that may invoke this package |
Complete example
{
"name": "web-researcher",
"description": "Deep web research agent",
"url": "https://example.dev/agents/web-researcher",
"version": "1.4.2",
"forge": {
"version": "0.1",
"publisher": {
"verified": true,
"verification_method": "github-collaborator-api",
"github_login": "ana",
"verified_at": "2026-05-27T14:30:00Z"
},
"security": {
"scanned": true,
"scan_level": "base",
"last_scan": "2026-05-27T14:30:00Z",
"scanner_version": "0.1.0",
"vulnerabilities": 0,
"critical": 0,
"high": 0,
"moderate": 0,
"low": 0,
"suspicious_scripts": false,
"status": "clean"
}
}
}
Usage by manifest format
MCP server (package.json)
Add the forge block as a top-level key in package.json:
{
"name": "my-mcp-server",
"version": "1.0.0",
"forge": { "version": "0.1", "publisher": { ... } }
}
A2A Agent Card (agent.json)
Add the forge block as an extension key in the Agent Card:
{
"name": "My Agent",
"url": "https://example.com/agent",
"version": "1.0",
"forge": { "version": "0.1", "publisher": { ... } }
}
SKILL.md frontmatter
Add a forge key in the YAML frontmatter:
---
name: code-reviewer
version: 1.0.0
forge:
version: "0.1"
publisher:
verified: true
github_login: sam-rivera
verified_at: "2026-05-27T14:30:00Z"
---
Changelog
v0.1 — 2026-05-27
Initial draft. Defines forge.version, forge.publisher, and forge.security.
Specifies forge.evals and forge.compose as planned fields.
2026-06-11 — clarifications (no schema change)
- Added the Trust model section: the block is a claim, not a proof; consumers must verify via registry lookup or signature.
- Documented signing, key distribution, and key rotation.
- Added the Revocation section and the
revokedAPI response block.