# AllKard File Format Specification

```
Identifier:     allkard/1.0
Media type:     application/vnd.allkard+zip
Extension:      .kard
JSON Schema:    https://allkard.com/schema/v1.json
This document:  https://allkard.com/docs/spec-allkard-1.0.md
```

## Abstract

This document defines the on-disk layout of an AllKard archive, the contents of `kard.json`, the manifest and signature binding, witness key discovery, and the recommended verification procedure. A conforming archive is a ZIP file containing JSON metadata, optional binary assets, a SHA-256 manifest, and a detached Ed25519 signature.

## 1. Conventions

The key words MUST, MUST NOT, SHOULD, SHOULD NOT, MAY, and OPTIONAL in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119).

The JSON Schema at `https://allkard.com/schema/v1.json` is normative for the structure of `kard.json`. Where this document and the schema disagree on archive handling, canonicalization, or signing, this document takes precedence for those topics.

Implementations MUST NOT hardcode a witness hostname. Witness metadata MUST be read from each `kard.json` instance.

## 2. Archive

### 2.1 Members

A conforming archive MUST contain:

| Member | Required |
|--------|----------|
| `kard.json` | yes |
| `manifest.json` | yes |
| `signature` | yes |
| `assets/*` | as referenced by `kard.json` |

No other member names are permitted except optional ZIP directory markers (e.g. `assets/`) that verifiers MUST ignore.

### 2.2 Path syntax

Member names:

- MUST NOT start with `/` or `./`
- MUST NOT contain `\`, U+0000, empty path segments, `.`, or `..`
- MUST NOT exceed 240 octets in length
- MUST be either `kard.json`, `manifest.json`, `signature`, or match `^assets/[a-zA-Z0-9_./-]+$`

Asset paths listed in `kard.json` MUST satisfy the same `assets/` rules. Dot-segment rejection is required even when a pattern match would succeed.

### 2.3 Decompression limits

A verifier SHOULD enforce the following limits (reference implementation values):

| Limit | Value |
|-------|-------|
| Total uncompressed payload | 64 MiB |
| Single member | 24 MiB |
| Member count (including ignored directories) | 80 |

Exceeding a limit MUST cause verification to fail.

## 3. Document `kard.json`

### 3.1 Format field

`format` MUST be the string `allkard/1.0`.

### 3.2 Serialization

The stored file MUST be UTF-8. It MUST NOT begin with a BOM. The file bytes MUST equal the canonical JSON encoding of the parsed value (Section 6).

### 3.3 Class `memory`

When `class` is `memory`:

- `custody.transferable` MUST be `false`
- `custody.transfer_epoch` MUST be `0`
- `back.provenance_chain` MUST NOT be present

### 3.4 Class `provenance`

When `class` is `provenance`:

- `custody.transferable` MUST be `true`
- `back.provenance_chain` MUST be present and non-empty
- `custody.transfer_epoch` MUST equal the `epoch` of the last element of `provenance_chain`
- `custody.holder` MUST equal the `holder` of that last element

### 3.5 Chapters

`back.chapters[].sequence` MUST be contiguous starting at `1`. `id` values MUST be unique within the document.

### 3.6 Provenance chain

For `back.provenance_chain`, each element’s `epoch` MUST equal its zero-based array index. `acquired_at` MUST NOT decrease when read in array order.

### 3.7 Witness block

- `witness.authority` MUST be an `https` origin with empty path, query, userinfo, and fragment. Hierarchical hostnames (for example regional franchise witnesses) are permitted when they remain valid HTTPS origins sharing a single keys document at `/.well-known/witness-keys.json`.
- `witness.keys_discovery` MUST be `https`, share the origin of `witness.authority`, and have pathname `/.well-known/witness-keys.json`.
- `witness.signed_at` SHOULD be greater than or equal to `issued_at`.

### 3.8 Asset references

Each path in `front.hero_asset`, `front.logo_asset`, and any `back.chapters[].asset` MUST name a member present in the archive and listed in `manifest.json`. Packagers SHOULD NOT include assets that are not referenced.

## 4. Document `manifest.json`

The document MUST be a JSON object mapping member paths to lowercase hexadecimal SHA-256 digests of the raw member bytes. Keys MUST include at least `kard.json` and every `assets/*` member.

The on-disk bytes MUST be canonical JSON (Section 6). Key order in the serialization MUST be lexicographically sorted.

The signature (Section 5) is computed over the UTF-8 encoding of those bytes, not over a reformatted representation.

## 5. File `signature`

The file MUST contain one base64url-encoded Ed25519 signature and no other characters (no PEM, no JSON, no whitespace).

The signed message is the UTF-8 encoding of the canonical `manifest.json` octets.

`witness.key_id` in `kard.json` MUST identify the public key used for verification.

## 6. Canonical JSON

Canonical JSON is used for `kard.json`, `manifest.json`, and signing input.

Rules:

1. Object keys are serialized in lexicographic order.
2. No insignificant whitespace.
3. Strings use JSON escaping; U+0000–U+001F use `\uXXXX` unless named escapes apply.
4. Numbers MUST be safe integers or are not permitted in archive-bound values.
5. Object members with `undefined` values MUST NOT appear in output.

This definition is a restricted profile aligned with [RFC 8785](https://www.rfc-editor.org/rfc/rfc8785) for the value types allowed in AllKard.

## 7. Witness key document

Published at the URL named by `witness.keys_discovery`.

Object shape:

```
{
  "authority": string,   // MUST equal witness.authority
  "keys": [              // 1–32 entries
    {
      "key_id": string,
      "algorithm": "Ed25519",
      "public_key": string,  // base64url, 32 octets decoded
      "status": "active" | "retired" | "revoked"
    }
  ]
}
```

Verifiers MUST reject `revoked` keys. Verifiers MAY accept `retired` keys for older archives.

Fetch MUST use HTTPS. Credentials embedded in URLs MUST NOT be used. Automatic redirect following is NOT RECOMMENDED.

## 8. Verification procedure

Recommended order:

1. Extract members per Section 2.
2. Parse `kard.json`; check canonical form and schema.
3. Apply Section 3 semantic rules.
4. Parse `manifest.json`; check canonical form.
5. Hash members; compare to manifest.
6. Obtain Ed25519 public key for `witness.key_id`.
7. Verify signature over manifest bytes.
8. OPTIONAL: query `custody.status_endpoint` (Section 9).

Cryptographic success SHOULD be reported only if steps 2–7 pass. Step 8 does not change digest or signature results.

## 9. Optional custody endpoint

If `custody.status_endpoint` is set and the implementation performs an online check:

- Request HTTPS; parse JSON body.
- Body MUST include integer `current_epoch` ≥ 0.
- If `current_epoch` equals `custody.transfer_epoch`, an optional `holder` field SHOULD match `custody.holder` when present.
- If `current_epoch` is greater than `custody.transfer_epoch`, the file MAY be labeled a historical transfer at a later epoch.
- Network failure MUST NOT downgrade offline hash or signature results.

## 10. Media type

Files SHOULD be labeled `application/vnd.allkard+zip`. Registration with IANA is outside the scope of this revision.

## 11. Security considerations

- The signature binds `manifest.json` only. All manifest-listed bytes MUST be hashed.
- Malformed ZIP metadata and path traversal must be rejected (Section 2).
- A valid signature indicates that the witness signed the manifest at issuance time; it does not prove current ownership without Section 9 when applicable.
- Compromise of a witness private key affects all archives signed under that key id.

Vulnerability reports: see `SECURITY.md` in the reference repository.

## 12. Conformance

Reference vectors ship in the `conformance/` directory of the reference implementation. Independent implementations SHOULD produce equivalent pass/fail results for those vectors.

## 13. Revision history

| Revision | Changes |
|----------|---------|
| allkard/1.0 | Initial publication (this document) |

## 14. Normative references

- JSON Schema Draft 2020-12
- RFC 2119 (Key words for use in RFCs)
- RFC 8032 (Edwards-Curve Digital Signature Algorithm, EdDSA)
- RFC 8785 (JSON Canonicalization Scheme)

## 15. Informative references

- Reference implementation: `verifyKard`, `packKard` (`@allkard/core`)
- Optional verify parameter `trustedAuthorities` (reference SDK only): when provided, verification fails unless `witness.authority` matches a listed HTTPS origin or a wildcard host suffix such as `*.witness.example`. Omitting the parameter preserves neutral key discovery via `witness.keys_discovery`.
