Media type: application/vnd.forgeproof.rpack+json (vendor tree). Registration status: not yet submitted.
The line above is the only place this repository states where the registration stands. Every other surface — the format specification, the README, the changelog — uses the bare type name and points here.
The name identifies the outer .rpack document described by the normative specification, skills/run/references/rpack-format.md. It is one name for every revision whose format member is forgeproof-rpack: no version token, no parameters. It is never written into a bundle — format and version are the in-band identity — so it travels outside the file, for example in a Content-Type header. It does not describe the .sigstore.json sidecar (a Sigstore bundle), the .pub.pem sidecar (an SPKI PEM), or the chain file.
- Trust: nothing. RFC 6838 §4.10: "the registration of a media type does not imply endorsement, approval, or recommendation by the IANA or the IETF or even certification that the specification is adequate." A media type is a name. What a bundle proves, and what it does not, is stated in the security considerations below and is the same in every ledger state.
- Verification: nothing.
verifyreads theformatandversionmembers and never the document's media type. No bundle byte changes when the ledger line does. - GitHub: nothing.
raw.githubusercontent.comserves.rpackfiles astext/plain; charset=utf-8whatever any registry says. - What it does give: a stable, collision-free name that tools can use for
Content-Type, MIME databases, and editor associations.
This is the RFC 6838 §5.6 template as it will be submitted through the IANA media types form. It is a draft until the ledger line says otherwise, and the ledger line — not this section — records what has happened to it.
Type name: application
Subtype name: vnd.forgeproof.rpack+json
Required parameters: N/A
Optional parameters: N/A
Encoding considerations: binary
JSON text (RFC 8259). RFC 8259 Section 8.1 requires UTF-8 for
interchange; the reference producer escapes all non-ASCII characters
and therefore emits pure ASCII. Lines may exceed 998 octets (the
embedded attestation carries a base64-encoded payload on one line),
so the content is not 7bit or 8bit text. Line-ending convention (LF
or CRLF), indentation, and member order are not significant; see
Interoperability considerations.
Security considerations:
This media type shares the security considerations of JSON (RFC
8259, Section 12): consumers MUST NOT evaluate the content as code
and MUST NOT rely on "eval()"-style parsing. Consumers SHOULD apply
the implementation limits RFC 8259 Section 9 permits (size, nesting
depth, number range) and SHOULD treat duplicate member names as an
error or ensure that the verified and the displayed views of a
document come from the same parse (RFC 8259 Section 4). The format
carries no active content, scripts, macros, external references, or
URLs that a conforming consumer must dereference, and employs no
compression; the embedded attestation payload is base64-encoded
text whose decoded size is bounded by the encoded size.
A ForgeProof bundle is a tamper-EVIDENT provenance record, not a
safety, security, review, or correctness attestation. It contains an
Ed25519 signature over a SHA-256 digest of the document's canonical
serialization; a valid signature proves only that the document was
not altered after signing by the holder of the corresponding private
key. It proves nothing about the correctness, safety, or quality of
the code the document describes. Consumers MUST NOT treat a verified
bundle as evidence that the described change was reviewed, tested to
any standard, or secure, and MUST NOT present it as compliance with
any regulation or framework.
The verifying public key travels inside the document ("public_key").
By default it is ephemeral, generated by the producing tool, deleted
after signing, and bound to no identity, certificate authority, or
transparency log: it is self-attested. A valid signature therefore
proves that the document was not altered since signing, not who
signed it. A future revision may carry identity material (for
example a certificate and transparency-log entry) inside
"attestation.verificationMaterial"; consumers MUST NOT assume it is
present and MUST treat its contents as untrusted until verified by
the rules of the Sigstore bundle format.
Privacy: the document discloses the issue title and URL, repository-
relative file paths, free-text design decisions, timestamps of the
recorded session, a public-key comment that by default embeds the
producing machine's "username@hostname", and (from format version
1.1.0) approval records that may contain the approver's e-mail
address. Producers publishing bundles SHOULD be aware they disclose
these; consumers that display bundles SHOULD treat them as personal
data. The producer's privacy policy is published with the format
specification.
Free-text members (issue title, requirement text, decisions, notes,
approver identifiers) are untrusted input: consumers that render
them as HTML or Markdown MUST escape them to prevent markup or
script injection.
The recorded artifact paths, and the issue number from which the
chain file's name is built, are untrusted input too: nothing in a
document prevents an artifact path that is absolute or that names a
network share, nor either value from climbing out of the project with
"..". Consumers that resolve them SHOULD confine resolution to the
intended project root. The reference producer has refused to record
such an artifact path, as the producing platform interprets it, since
plugin version 1.1.0; documents from earlier versions may carry one.
At the time of this registration the reference verifier does not
confine them: it resolves each as given (on Windows a recorded
network-share path is opened like any other path), so verifying a
document from an untrusted source can make it open a file outside the
project and disclose, through its verdict, whether a file exists
there, whether an artifact path names a regular file, whether the
file matches the digest recorded for it, and, for the chain file,
whether it parses as JSON and, when it parses as an array of objects,
its element count, the values of the members "index", "action" and
"timestamp" of those objects, and the "commit_sha" in the "data"
object of the last element whose "action" is "finalize", all of which
the verdict echoes.
The embedded attestation (format version 1.1.0 and later) is an
in-toto Statement inside a DSSE envelope inside a Sigstore-style
bundle object. It is data, not executable content. Its signature MUST
be verified under the key carried in the document's own "public_key"
member; a key or key hint carried inside the attestation itself is
never a substitute for it. Its decoded payload is attacker-controlled
JSON and MUST be parsed with the same limits as the outer document.
Interoperability considerations:
The document is a single JSON object. Producers write UTF-8 without
a byte-order mark (the reference producer writes ASCII). Member
order, indentation, and newline convention are NOT normative:
conforming verifiers re-serialize the parsed object in canonical
form (members sorted by code point, no whitespace, non-ASCII escaped)
before recomputing the digest, so consumers MUST NOT depend on byte
layout. All numbers are integers. The format is append-only and
versioned by the "version" member; consumers MUST ignore members
they do not recognize and MUST NOT infer the presence of any member
from the version value. The member "format" always has the value
"forgeproof-rpack".
Verifying the document's own signature requires OpenSSH "ssh-keygen"
(8.1 or later, "ssh-keygen -Y verify") in addition to a JSON parser
and SHA-256; the reference verifier is Python 3.11 standard library
plus ssh-keygen and has no other dependencies. Verifying the embedded
attestation requires only Ed25519 and JSON. Sigstore's cosign can
independently check the DSSE signature of the attestation, as
exported beside the document in the ".sigstore.json" sidecar file,
against the exported public key (the ".pub.pem" sidecar file) and,
for an artifact file supplied to it, that the file's digest is among
the signed subjects. That complements and never replaces the
verification the format specification defines, which additionally
binds the attestation to the document's own "public_key", to its
artifact list, and to its chain.
From format version 1.1.0 the document may embed an attestation
whose payload-type string "application/vnd.in-toto+json" (in-toto
Attestation Framework) and wrapper media-type string
"application/vnd.dev.sigstore.bundle.v0.3+json" (Sigstore bundle
format) are conventions defined by those projects. Neither appears
in the IANA media types registry at the time of this registration;
this registration neither defines nor claims them.
Published specification:
ForgeProof .rpack Bundle Format,
https://github.com/ryanjmichie-git/forgeproof-plugin/blob/v1.4.0/skills/run/references/rpack-format.md
(latest revision: the same path on the "main" branch).
Applications that use this media type:
ForgeProof, a Claude Code plugin (producer and verifier), and the
forgeproof-verify GitHub Action (verifier). Any JSON-aware tool can
read the document.
Fragment identifier considerations:
As specified for "+json" (RFC 6839, Section 3.1): no fragment
identifier syntax is defined for "application/json", and this type
defines none. JSON Pointer (RFC 6901) is not adopted.
Additional information:
Deprecated alias names for this type: N/A
Magic number(s): None at a fixed offset (JSON has none). The
document begins with "{" (0x7B) and the reference producer emits
the member "format" with the string value "forgeproof-rpack"
within the first 256 octets; detection rules search that window
for "\"format\": \"forgeproof-rpack\"" or
"\"format\":\"forgeproof-rpack\"".
File extension(s): .rpack
(Note: ".rpack" is also used by unrelated binary game-asset
archives whose first four octets are "RP5L" or "RP6L"; those files
never begin with "{" and are distinguishable by content.)
Macintosh file type code(s): N/A
Person & email address to contact for further information:
Ryan Michie <ryanjmichie@gmail.com>
Intended usage: COMMON
Interchanged publicly: committed to Git repositories and attached to
pull requests.
Restrictions on usage: None
Author: Ryan Michie
Change controller: Ryan Michie (ForgeProof project),
https://github.com/ryanjmichie-git/forgeproof-plugin
Provisional registration? (standards tree only): No
Two definitions ship under share/ so that desktop and command-line tools can recognize a bundle. ForgeProof never installs them. No skill, hook, or engine command copies them anywhere, runs update-mime-database or xdg-mime, or writes to your home directory. They are there for you to install by hand, in your own user account, or not at all. CI proves both against every frozen fixture and a fresh bundle on each push (stress/check_detection.py), with the limits below asserted rather than hidden.
For the desktop MIME database that file managers and GLib applications read. The definition is a sub-class of application/json, claims the *.rpack glob, and sniffs content: { at byte 0 and the format member within the first 256 bytes.
In the recipes below, <plugin-dir> is the directory the plugin was installed to (the marketplace cache or a checkout of this repository) and <your-project> is the repository whose bundle you are checking; neither share/ nor a bundle lives in the other. Install for your user only:
xdg-mime install --mode user <plugin-dir>/share/mime/packages/forgeproof-rpack.xmlwhich is equivalent to:
mkdir -p ~/.local/share/mime/packages
cp <plugin-dir>/share/mime/packages/forgeproof-rpack.xml ~/.local/share/mime/packages/
update-mime-database ~/.local/share/mimeUninstall:
xdg-mime uninstall --mode user <plugin-dir>/share/mime/packages/forgeproof-rpack.xmlor delete ~/.local/share/mime/packages/forgeproof-rpack.xml and run update-mime-database ~/.local/share/mime again. System scope is the same with /usr/share/mime and root.
To try it without installing anything:
T=$(mktemp -d); mkdir -p "$T/mime/packages"
cp <plugin-dir>/share/mime/packages/forgeproof-rpack.xml "$T/mime/packages/"
XDG_DATA_HOME="$T" update-mime-database "$T/mime"
XDG_DATA_HOME="$T" gio info -a standard::content-type <your-project>/.forgeproof/issue-42.rpackNever run update-mime-database on share/mime itself: it writes globs2, magic, mime.cache and more beside the XML. And query through gio info: on a session without a desktop environment, xdg-mime query filetype can fall through to file, which does not read this database.
What it reports (asserted in CI):
| File | Result |
|---|---|
named *.rpack, any layout (as written, CRLF, compact, key-sorted, BOM-prefixed) |
the type above |
| no extension; as written, CRLF, or compact in the producer's member order | the type above, by content |
| no extension; key-sorted or BOM-prefixed | text/plain — a limit, see Known limits |
an unrelated document named *.json |
application/json |
a game archive's RP6L… bytes, no extension |
application/octet-stream |
For file(1). There is nothing to install or uninstall: name the magic file on the command line.
file -e json -m <plugin-dir>/share/magic/forgeproof --mime-type <your-project>/.forgeproof/issue-42.rpack-e json is required. file runs its built-in JSON detector before it consults any magic file and stops at the first match, so plain file --mime-type prints application/json for a bundle, with or without -m — for a bundle no larger than the prefix file inspects (its bytes parameter, at least 1 MiB by default; a bundle is a few kilobytes), beyond which the built-in detector gives up and the answer is text/plain without -m, or ours with it. That answer is correct, only less specific; it is asserted in CI so that the precedence is documented, not hidden. -m names an alternate magic list rather than adding to the default one, so with the command above most files that are not a bundle are reported as text/plain or application/octet-stream (file's other built-in detectors still run, so a CSV or a tar archive keeps its own type).
file -C -m writes <name>.mgc into the current directory; compile only in a temporary directory, never inside a checkout.
What it reports with -e json -m share/magic/forgeproof (asserted in CI):
| File | Result |
|---|---|
| as written, CRLF, or compact in the producer's member order | the type above |
| key-sorted (indented or minified), or BOM-prefixed | text/plain — a limit |
unrelated JSON whose format is something else |
text/plain |
a bundle as written, without -e json |
application/json — the built-in detector's precedence |
The shared-mime-info test-list line, recorded here for the merge request the checklist describes:
issue-996.rpack application/vnd.forgeproof.rpack+json
GitHub renders a .rpack as JSON, in the file view and in diffs, if the repository's .gitattributes carries this line:
*.rpack linguist-language=JSON
Optional and cosmetic: it changes how GitHub highlights the file; verification is unaffected either way, and no -text is needed for bundles.
Optional and cosmetic: editors treat .rpack as plain text unless told otherwise. In VS Code, add to your user or workspace settings.json:
{
"files.associations": {
"*.rpack": "json"
},
"json.schemas": [
{
"fileMatch": ["*.rpack"],
"url": "https://raw.githubusercontent.com/ryanjmichie-git/forgeproof-plugin/v1.4.0/schemas/forgeproof-rpack-1.schema.json"
}
]
}ForgeProof never writes editor settings, .gitattributes, or MIME definitions into your repository or your home directory; this snippet is for you to apply by hand, or not at all.
.rpack is also used by unrelated binary game-asset archives whose first four bytes are RP5L or RP6L. Those files never begin with {, so one byte of content tells the two apart; no registry assigns the extension to either format.
- A key-sorted re-serialization escapes content sniffing. Detection by content keys on the specification's emission profile:
{at byte 0 and theformatmember within the first 256 bytes. A bundle re-serialized with sorted members (for example by a key-sorting JSON formatter) putsformatbehind the multi-kilobyteattestation; it remains valid and verifiable but is recognized by its file name only. - A byte-order mark escapes content sniffing too. The emission profile has producers write none, and a verifier ignores one; a BOM-prefixed copy is still valid but no longer has
{at byte 0, so it is recognized by its file name only. - Plain
filesaysapplication/json. Its built-in JSON detector runs before any magic file (on a bundle within the prefixfileinspects — any realistic one); the rule undershare/magic/is reached only with-e json(see Detection files). - A game archive named
.rpackis labelled by its name. On a desktop where a*.rpackglob has been installed, a file that fails the content test is still matched by the glob. The label is cosmetic:verifyrejects anything that is not a ForgeProof bundle.
Uniform Type Identifiers are declared in the Info.plist of an application bundle; there is no way to declare one without an app, and ForgeProof ships none. For any future macOS or iOS application the declaration would be com.forgeproof.rpack, conforming to public.json, with the .rpack extension and the media type above.
Submissions to upstream detection databases are maintainer actions, not release deliverables:
- Not before the ledger line above records a confirmed registration. shared-mime-info asks for "IANA registered mime-types when possible", and a definition submitted under a name that later changes needs an alias forever.
- shared-mime-info: a merge request carrying the XML definition and at least one test file ("Merge requests are required for new mime-types and should include one or more test files").
file/libmagic: an entry with a one-line summary, the file extension, a contact, and a reference to the specification.- Sign-off gate. The final text of every submission — and of every reply in its review — is presented to the project maintainer and sent only after his explicit sign-off.