# TRH Canonical Artifact Specification

**Identifier:** TRH-SPEC-001  
**Version:** 1.0.0  
**Status:** ACTIVE  
**Validator compatibility:** 0.1.x

## 1. Separation of concerns

A release consists of three independent files:

1. The artifact: exact canonical bytes.
2. The manifest: identity, lifecycle, hashes, provenance, and relationships.
3. The optional signature record: an Ed25519 signature over the lowercase
   hexadecimal `artifact_sha256` value encoded as UTF-8.

Filenames are descriptive and never establish authority by themselves.

## 2. Wrapped text artifacts

The `TRH-WRAPPED-1` profile contains exactly two blocks in this exact order:

```text
<!-- TRH:METADATA:BEGIN -->
{one JSON object}
<!-- TRH:METADATA:END -->
<!-- TRH:PAYLOAD:BEGIN -->
{payload bytes}
<!-- TRH:PAYLOAD:END -->
```

The four markers must each occur exactly once. No byte, text, comment,
whitespace, or newline may exist before the metadata begin marker or after the
payload end marker. Metadata must parse as one JSON object and must agree with
the manifest for canonical ID, artifact version, release, lifecycle status,
and collection ID.

## 3. Hashes

- `artifact_sha256` hashes every byte of the artifact exactly as stored.
- `payload_sha256` hashes the bytes between the payload markers after portable
  normalization: remove one leading UTF-8 BOM if present, convert CRLF and CR
  line endings to LF, and remove one final LF.

The exact canonical artifact may not start with a UTF-8 BOM. A BOM makes the
artifact structurally `INVALID`. BOM removal exists only for comparing a
portable payload copy and never repairs or canonicalizes the artifact.

## 4. Lifecycle

Allowed lifecycle states are `ACTIVE`, `DEPRECATED`, `SUPERSEDED`, `REVOKED`,
and `ARCHIVED`. Only one active canonical release may exist for a canonical ID.
Deprecated identifiers remain reserved and may not be reassigned.

## 5. Validation outcomes

- `VALID`: structure, schema, hashes, registry record, lifecycle, and any
  required signature all pass.
- `MODIFIED`: structure is valid but an artifact or payload hash differs.
- `UNREGISTERED`: the package is internally valid but no matching registry
  record exists.
- `INVALID`: wrapper, schema, metadata, encoding, or signature is invalid.
- `REVOKED`: the matching registry record or manifest is revoked.

`MODIFIED`, `UNREGISTERED`, `INVALID`, and `REVOKED` are non-zero validator
exit states in CI.

## 6. Signature standard

Signatures use Ed25519. Keys are raw 32-byte public keys encoded with standard
base64. Signatures are raw 64-byte values encoded with standard base64. The
trust policy is registry-controlled: a key ID is trusted only when it appears
in the published key registry and is valid for the release approval time.

