FEP-0002: PSPF/2025 JSON Metadata Format Specification¶
Status: Standards Track
Type: Core Protocol
Created: 2025-01-08
Version: v0.1
Category: Standards Track
Abstract¶
This document specifies the JSON-based metadata format for PSPF/2025 packages. The metadata provides structured information about package contents, slot definitions, execution parameters, and build provenance. This specification defines the exact JSON schema, validation rules, encoding requirements, and parsing algorithms to ensure cross-language compatibility between Python, Go, and Rust implementations.
Table of Contents¶
- Introduction
- Conventions and Terminology
- JSON Metadata Structure
- Field Specifications
- Validation Rules
- Encoding and Serialization
- ABNF Grammar
- JSON Schema Definition
- Processing Algorithms
- Error Handling
- Security Considerations
- Implementation Requirements
- Test Vectors
- References
1. Introduction¶
1.1 Motivation¶
PSPF/2025 packages require structured metadata to describe their contents, execution requirements, and provenance. JSON provides an ideal balance between human readability, cross-language support, and parsing efficiency for v0 implementations. Future versions may introduce binary formats for performance-critical applications.
1.2 Scope¶
This specification defines: - Complete JSON schema for PSPF/2025 package metadata - Validation rules and semantic constraints - Encoding and normalization requirements - Cross-language parsing algorithms - Extension mechanisms for vendor-specific fields
This specification does NOT define: - Binary wire format (reserved for future versions) - Network transmission protocols - Metadata compression algorithms (handled at package level) - Runtime behavior of metadata fields
1.3 Requirements Language¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 RFC2119 RFC8174 when, and only when, they appear in all capitals, as shown here.
1.4 Related Documents¶
- FEP-0001: Core binary format and operation chains
- FEP-0003: Operation registry and allocation policy
- RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
- RFC 4627: JSON Media Type
2. Conventions and Terminology¶
2.1 Definitions¶
Metadata: Structured information describing package contents and requirements Slot Definition: JSON object describing a single data slot in the package Operation String: Human-readable representation of an operation chain Canonical Form: Normalized JSON representation for signature verification Extension Field: Vendor-specific field prefixed with "x-"
2.2 Notation Conventions¶
JSON examples use standard JSON notation with comments for clarity (comments are not valid in actual JSON):
{
"field": "value", // Comment for documentation
"number": 123, // Integer value
"array": [1, 2, 3] // Array of integers
}
ABNF grammar follows [RFC5234] notation.
Regular expressions use PCRE syntax.
2.3 Data Type Definitions¶
| JSON Type | PSPF Type | Range/Format |
|---|---|---|
| string | identifier | ^[a-z0-9][a-z0-9_-]*$ max 255 chars |
| string | version | Semantic versioning or custom format |
| string | checksum | Hex string, lowercase, no prefix |
| string | operations | Operation chain string (see Section 7) |
| number | uint32 | 0 to 4,294,967,295 |
| number | uint64 | 0 to 18,446,744,073,709,551,615 |
| number | timestamp | Unix timestamp (seconds since epoch) |
| string | path | Forward slashes, no ".." traversal |
3. JSON Metadata Structure¶
3.1 Root Object¶
The metadata MUST be a single JSON object with the following structure:
{
"format_version": "2025.0.0",
"package": {
"name": "package-name",
"version": "1.0.0",
"description": "Package description",
"author": "Author Name",
"license": "License-Identifier",
"homepage": "https://example.com"
},
"build": {
"timestamp": 1704067200,
"platform": "linux_x86_64",
"builder": "flavorpack-0.1.0",
"source_hash": "abc123...",
"reproducible": true
},
"slots": [
{
"id": 0,
"name": "slot-name",
"purpose": "code",
"lifecycle": "runtime",
"operations": "tar.gz",
"size": 1024,
"original_size": 2048,
"checksum": "deadbeef",
"permissions": "755"
}
],
"execution": {
"entry_point": "./bin/app",
"args": ["--config", "app.conf"],
"env": {
"KEY": "value"
},
"working_directory": "."
},
"dependencies": {
"runtime": ["libc.so.6"],
"optional": ["libfoo.so.1"]
},
"extensions": {
"x-vendor-field": "vendor-specific-value"
}
}
3.2 Object Hierarchy¶
root
├── format_version* (string)
├── package* (object)
│ ├── name* (string)
│ ├── version* (string)
│ ├── description (string)
│ ├── author (string)
│ ├── license (string)
│ └── homepage (string)
├── build (object)
│ ├── timestamp (number)
│ ├── platform (string)
│ ├── builder (string)
│ ├── source_hash (string)
│ └── reproducible (boolean)
├── slots* (array)
│ └── [slot] (object)
│ ├── id* (number)
│ ├── name* (string)
│ ├── purpose* (string)
│ ├── lifecycle* (string)
│ ├── operations* (string)
│ ├── size* (number)
│ ├── original_size (number)
│ ├── checksum* (string)
│ └── permissions (string)
├── execution (object)
│ ├── entry_point (string)
│ ├── args (array of strings)
│ ├── env (object)
│ └── working_directory (string)
├── dependencies (object)
│ ├── runtime (array of strings)
│ └── optional (array of strings)
└── extensions (object)
└── x-* (any)
* = required field
4. Field Specifications¶
4.1 Root Level Fields¶
4.1.1 format_version (REQUIRED)¶
Type: string
Pattern: ^\d{4}\.\d+\.\d+$
Example: "2025.0.0"
Identifies the metadata format version. For v0, this MUST be "2025.0.0".
4.1.2 package (REQUIRED)¶
Type: object
Contains basic package identification and information.
4.1.3 build (OPTIONAL)¶
Type: object
Contains build-time information for reproducibility and provenance.
4.1.4 slots (REQUIRED)¶
Type: array of objects
Min Items: 0
Max Items: 65535
Array of slot definitions. MAY be empty for launcher-only packages.
4.1.5 execution (OPTIONAL)¶
Type: object
Runtime execution parameters and environment configuration.
4.1.6 dependencies (OPTIONAL)¶
Type: object
External dependencies required or recommended for package execution.
4.1.7 extensions (OPTIONAL)¶
Type: object
Vendor-specific extensions. All keys MUST begin with "x-".
4.2 Package Object Fields¶
4.2.1 name (REQUIRED)¶
Type: string
Pattern: ^[a-z0-9][a-z0-9_-]*$
Min Length: 1
Max Length: 255
Example: "my-application"
Package identifier. MUST be lowercase alphanumeric with hyphens and underscores.
4.2.2 version (REQUIRED)¶
Type: string
Pattern: ^[0-9]+(\.[0-9]+)*([+-].+)?$
Max Length: 255
Example: "1.2.3-beta+build.456"
Package version. SHOULD follow semantic versioning but MAY use custom schemes.
4.2.3 description (OPTIONAL)¶
Type: string
Max Length: 4096
Example: "A high-performance web server"
Human-readable package description.
4.2.4 author (OPTIONAL)¶
Type: string
Max Length: 255
Example: "Jane Doe jane@example.com"
Package author or maintainer.
4.2.5 license (OPTIONAL)¶
Type: string
Max Length: 255
Example: "MIT" or "Apache-2.0"
SPDX license identifier or custom license name.
4.2.6 homepage (OPTIONAL)¶
Type: string
Format: URI
Max Length: 2048
Example: "https://example.com/project"
Project homepage or documentation URL.
4.3 Slot Object Fields¶
4.3.1 id (REQUIRED)¶
Type: number
Minimum: 0
Maximum: 4294967295
Example: 0
Unique slot identifier within the package. MUST be unique across all slots.
4.3.2 name (REQUIRED)¶
Type: string
Pattern: ^[a-zA-Z0-9][a-zA-Z0-9_.-]*$
Max Length: 255
Example: "python-runtime"
Human-readable slot name.
4.3.3 purpose (REQUIRED)¶
Type: string
Enum: ["code", "data", "config", "media"]
Example: "code"
Slot content classification:
- code: Executable binaries or scripts
- data: Application data files
- config: Configuration files
- media: Images, audio, video, or other media
4.3.4 lifecycle (REQUIRED)¶
Type: string
Enum: See table below
Example: "runtime"
| Value | Description | Extraction Behavior |
|---|---|---|
| init | First run only, then removed | Extract once, delete after |
| startup | Extract at every startup | Always extract fresh |
| runtime | Extract on first use (default) | Extract once, keep cached |
| shutdown | Extract during cleanup | Extract at termination |
| cache | Performance cache, can regenerate | Extract if missing |
| temporary | Remove after session ends | Extract, delete at exit |
| lazy | Load on-demand | Extract when accessed |
| eager | Load immediately on startup | Extract before execution |
| dev | Development mode only | Extract if DEV flag set |
| config | User-modifiable config files | Extract if not present |
| platform | Platform/OS specific content | Extract if platform matches |
4.3.5 operations (REQUIRED)¶
Type: string
Pattern: See Section 7
Example: "tar.gz" or "tar|gzip"
Operation chain string describing transformations applied to slot data.
4.3.6 size (REQUIRED)¶
Type: number
Minimum: 0
Maximum: 2^53-1 (JSON safe integer)
Example: 1048576
Size of slot data as stored in package (after operations applied).
4.3.7 original_size (OPTIONAL)¶
Type: number
Minimum: 0
Maximum: 2^53-1
Example: 4194304
Original size before operations applied. If omitted, assumed equal to size.
4.3.8 checksum (REQUIRED)¶
Type: string
Pattern: ^[a-f0-9]{16}$
Example: "deadbeef01234567"
SHA-256 hash of stored slot data (first 8 bytes) as 16-character hex string.
4.3.9 permissions (OPTIONAL)¶
Type: string
Pattern: ^[0-7]{3,4}$
Example: "755" or "0644"
Unix-style permissions as octal string.
4.4 Build Object Fields¶
4.4.1 timestamp (OPTIONAL)¶
Type: number
Example: 1704067200
Unix timestamp of package creation.
4.4.2 platform (OPTIONAL)¶
Type: string
Pattern: ^[a-z]+_[a-z0-9]+$
Example: "linux_x86_64", "darwin_arm64", "windows_amd64"
Target platform identifier.
4.4.3 builder (OPTIONAL)¶
Type: string
Max Length: 255
Example: "flavorpack-0.1.0"
Tool and version used to create package.
4.4.4 source_hash (OPTIONAL)¶
Type: string
Pattern: ^[a-f0-9]{64}$
Example: "abc123..."
SHA-256 hash of source code tree.
4.4.5 reproducible (OPTIONAL)¶
Type: boolean
Example: true
Whether package was built reproducibly.
4.5 Execution Object Fields¶
4.5.1 entry_point (OPTIONAL)¶
Type: string
Max Length: 4096
Example: "./bin/app"
Path to main executable within extracted package.
4.5.2 args (OPTIONAL)¶
Type: array of strings
Max Items: 1024
Example: ["--config", "app.conf"]
Default command-line arguments.
4.5.3 env (OPTIONAL)¶
Type: object
Max Properties: 1024
Example: {"PATH": "/app/bin:$PATH"}
Environment variables to set. Values MAY contain variable references.
4.5.4 working_directory (OPTIONAL)¶
Type: string
Default: "."
Example: "./data"
Working directory for execution relative to extraction root.
5. Validation Rules¶
5.1 Structural Validation¶
The JSON document MUST: 1. Be valid JSON according to [RFC7159] 2. Have a single root object 3. Include all required fields 4. Not exceed 10MB when uncompressed 5. Use UTF-8 encoding without BOM
5.2 Semantic Validation¶
5.2.1 Slot Validation¶
- Slot IDs MUST be unique within the package
- Slot names SHOULD be unique (warning if not)
- Slot checksums MUST be exactly 8 hex characters
- Operations strings MUST use only supported operations
5.2.2 Path Validation¶
All path strings MUST: - Use forward slashes as separators - Not contain ".." components - Not begin with "/" (relative paths only) - Not contain null bytes - Be valid UTF-8
5.2.3 Cross-Reference Validation¶
slot.sizeMUST match actual slot data size in packageslot.checksumMUST match computed Adler-32 of slot dataexecution.entry_pointSHOULD reference an extracted file
5.3 Extension Field Validation¶
Extension fields in the extensions object:
- MUST begin with "x-" prefix
- MAY contain any valid JSON value
- SHOULD use lowercase names with hyphens
- MUST NOT conflict with standard fields
6. Encoding and Serialization¶
6.1 JSON Encoding Rules¶
Metadata MUST be encoded as: - UTF-8 without byte order mark (BOM) - No trailing whitespace - No comments (not valid JSON) - Unix line endings (LF, not CRLF)
6.2 Canonical Form¶
For signature verification, metadata MUST be normalized to canonical form:
- Object Key Ordering: All object keys MUST be sorted lexicographically
- Whitespace: No unnecessary whitespace (compact form)
- Number Format: No leading zeros, no trailing decimal points
- String Escaping: Minimal escaping (only required characters)
- Unicode Normalization: NFC normalization for all strings
Canonical encoding:
6.3 Compression¶
When stored in packages, metadata SHOULD be compressed using GZIP with: - Compression level: 9 (best compression) - No embedded filename or timestamp - CRC32 verification enabled
7. ABNF Grammar¶
7.1 Operation String Grammar¶
operation-string = simple-op / compound-op / pipe-chain
simple-op = "raw" / "gzip" / "bzip2" / "xz" / "zstd" / "tar"
compound-op = "tar.gz" / "tar.bz2" / "tar.xz" / "tar.zst" /
"tgz" / "tbz2" / "txz"
pipe-chain = operation 1*( "|" operation )
operation = ALPHA 1*( ALPHA / DIGIT / "_" )
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
DIGIT = %x30-39 ; 0-9
7.2 Version String Grammar¶
version = major [ "." minor [ "." patch ] ] [ prerelease ] [ build ]
major = 1*DIGIT
minor = 1*DIGIT
patch = 1*DIGIT
prerelease = "-" 1*prerelease-char
build = "+" 1*build-char
prerelease-char = ALPHA / DIGIT / "-" / "."
build-char = ALPHA / DIGIT / "-" / "."
7.3 Identifier Grammar¶
identifier = identifier-start *identifier-char
identifier-start = LOWER / DIGIT
identifier-char = LOWER / DIGIT / "-" / "_"
LOWER = %x61-7A ; a-z
8. JSON Schema Definition¶
8.1 Complete JSON Schema¶
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "https://pspf.io/schemas/2025.0.0/metadata.json",
"title": "PSPF/2025 Package Metadata",
"type": "object",
"required": ["format_version", "package", "slots"],
"additionalProperties": false,
"properties": {
"format_version": {
"type": "string",
"const": "2025.0.0"
},
"package": {
"type": "object",
"required": ["name", "version"],
"additionalProperties": false,
"properties": {
"name": {
"type": "string",
"pattern": "^[a-z0-9][a-z0-9_-]*$",
"minLength": 1,
"maxLength": 255
},
"version": {
"type": "string",
"pattern": "^[0-9]+(\\.[0-9]+)*([+-].+)?$",
"maxLength": 255
},
"description": {
"type": "string",
"maxLength": 4096
},
"author": {
"type": "string",
"maxLength": 255
},
"license": {
"type": "string",
"maxLength": 255
},
"homepage": {
"type": "string",
"format": "uri",
"maxLength": 2048
}
}
},
"build": {
"type": "object",
"additionalProperties": false,
"properties": {
"timestamp": {
"type": "integer",
"minimum": 0
},
"platform": {
"type": "string",
"pattern": "^[a-z]+_[a-z0-9]+$"
},
"builder": {
"type": "string",
"maxLength": 255
},
"source_hash": {
"type": "string",
"pattern": "^[a-f0-9]{64}$"
},
"reproducible": {
"type": "boolean"
}
}
},
"slots": {
"type": "array",
"minItems": 0,
"maxItems": 65535,
"items": {
"type": "object",
"required": ["id", "name", "purpose", "lifecycle", "operations", "size", "checksum"],
"additionalProperties": false,
"properties": {
"id": {
"type": "integer",
"minimum": 0,
"maximum": 4294967295
},
"name": {
"type": "string",
"pattern": "^[a-zA-Z0-9][a-zA-Z0-9_.-]*$",
"maxLength": 255
},
"purpose": {
"type": "string",
"enum": ["code", "data", "config", "media"]
},
"lifecycle": {
"type": "string",
"enum": ["init", "startup", "runtime", "shutdown", "cache",
"temporary", "lazy", "eager", "dev", "config", "platform"]
},
"operations": {
"type": "string",
"pattern": "^(raw|gzip|bzip2|xz|zstd|tar|tar\\.gz|tar\\.bz2|tar\\.xz|tar\\.zst|tgz|tbz2|txz|([a-z]+)(\\|[a-z]+)*)$"
},
"size": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"original_size": {
"type": "integer",
"minimum": 0,
"maximum": 9007199254740991
},
"checksum": {
"type": "string",
"pattern": "^[a-f0-9]{16}$"
},
"permissions": {
"type": "string",
"pattern": "^[0-7]{3,4}$"
}
}
}
},
"execution": {
"type": "object",
"additionalProperties": false,
"properties": {
"entry_point": {
"type": "string",
"maxLength": 4096
},
"args": {
"type": "array",
"maxItems": 1024,
"items": {
"type": "string"
}
},
"env": {
"type": "object",
"maxProperties": 1024,
"additionalProperties": {
"type": "string"
}
},
"working_directory": {
"type": "string",
"maxLength": 4096
}
}
},
"dependencies": {
"type": "object",
"additionalProperties": false,
"properties": {
"runtime": {
"type": "array",
"items": {
"type": "string"
}
},
"optional": {
"type": "array",
"items": {
"type": "string"
}
}
}
},
"extensions": {
"type": "object",
"patternProperties": {
"^x-": {}
},
"additionalProperties": false
}
}
}
9. Processing Algorithms¶
9.1 Metadata Parsing Algorithm¶
function parseMetadata(jsonBytes):
// 1. Decode UTF-8
text = utf8Decode(jsonBytes)
if error:
return ERROR_INVALID_ENCODING
// 2. Parse JSON
try:
metadata = jsonParse(text)
catch:
return ERROR_INVALID_JSON
// 3. Validate against schema
if not validateSchema(metadata, PSPF_SCHEMA):
return ERROR_SCHEMA_VIOLATION
// 4. Check format version
if metadata.format_version != "2025.0.0":
return ERROR_UNSUPPORTED_VERSION
// 5. Validate semantic constraints
if not validateSemantics(metadata):
return ERROR_SEMANTIC_VIOLATION
return metadata
9.2 Canonical Form Algorithm¶
function canonicalize(metadata):
// 1. Deep copy to avoid mutation
canonical = deepCopy(metadata)
// 2. Sort all object keys recursively
canonical = sortKeysRecursive(canonical)
// 3. Normalize numbers
canonical = normalizeNumbers(canonical)
// 4. Normalize Unicode strings to NFC
canonical = normalizeUnicode(canonical)
// 5. Serialize with minimal whitespace
json = JSON.stringify(canonical, null, 0)
// 6. Ensure consistent separators
json = json.replace(/: /g, ':')
json = json.replace(/, /g, ',')
return json
9.3 Checksum Verification Algorithm¶
function verifyMetadataChecksum(metadata, expectedHash):
// 1. Canonicalize metadata
canonical = canonicalize(metadata)
// 2. Encode to UTF-8
bytes = utf8Encode(canonical)
// 3. Compute SHA-256
computedHash = sha256(bytes)
// 4. Compare hashes
return constantTimeEqual(computedHash, expectedHash)
10. Error Handling¶
10.1 Error Codes¶
// JSON Errors (1000-1099)
#define ERROR_INVALID_ENCODING 1000
#define ERROR_INVALID_JSON 1001
#define ERROR_SCHEMA_VIOLATION 1002
#define ERROR_UNSUPPORTED_VERSION 1003
#define ERROR_SEMANTIC_VIOLATION 1004
// Field Errors (1100-1199)
#define ERROR_MISSING_REQUIRED 1100
#define ERROR_INVALID_TYPE 1101
#define ERROR_INVALID_PATTERN 1102
#define ERROR_INVALID_ENUM 1103
#define ERROR_OUT_OF_RANGE 1104
// Slot Errors (1200-1299)
#define ERROR_DUPLICATE_SLOT_ID 1200
#define ERROR_INVALID_OPERATIONS 1201
#define ERROR_CHECKSUM_MISMATCH 1202
#define ERROR_SIZE_MISMATCH 1203
// Path Errors (1300-1399)
#define ERROR_PATH_TRAVERSAL 1300
#define ERROR_INVALID_PATH 1301
#define ERROR_ABSOLUTE_PATH 1302
10.2 Error Recovery¶
Implementations SHOULD attempt graceful degradation:
- Missing Optional Fields: Use defaults where sensible
- Unknown Extension Fields: Ignore "x-" prefixed fields
- Version Mismatch: Attempt compatibility if minor version
- Encoding Issues: Try alternative encodings (UTF-16, Latin-1)
10.3 Diagnostic Output¶
Error messages MUST include: - Error code - Field path (e.g., "slots[2].checksum") - Expected vs actual values - Line/column number if available
Example:
{
"error": 1102,
"field": "slots[2].checksum",
"message": "Invalid pattern",
"expected": "^[a-f0-9]{8}$",
"actual": "DEADBEEF",
"line": 45,
"column": 23
}
11. Security Considerations¶
11.1 Input Validation¶
Implementations MUST protect against:
JSON Bombs: Deeply nested structures or large expansions - Maximum nesting depth: 100 levels - Maximum string length: 10MB - Maximum array size: 65535 items - Maximum object properties: 10000
Resource Exhaustion: - Limit total metadata size to 10MB uncompressed - Timeout parsing after 5 seconds - Limit memory usage during parsing
Injection Attacks: - Sanitize all strings before use in commands - Validate paths to prevent directory traversal - Escape special characters in environment variables
11.2 Trust Boundaries¶
Metadata is untrusted input until verified:
- Parse and validate structure
- Verify metadata checksum from index block
- Verify package signature
- Only then trust content
11.3 Information Disclosure¶
Sensitive information in metadata: - Build paths may reveal system layout - Environment variables may contain secrets - Source hashes may reveal proprietary code structure
Implementations SHOULD: - Redact sensitive paths in logs - Not expose full metadata to untrusted code - Sanitize error messages
12. Implementation Requirements¶
12.1 Parser Requirements¶
All implementations MUST: 1. Accept any valid JSON according to schema 2. Reject invalid JSON with appropriate errors 3. Handle UTF-8, UTF-16, and UTF-32 encodings 4. Support full Unicode range including emoji 5. Parse numbers up to 2^53-1 accurately
12.2 Cross-Language Compatibility¶
Python Implementation¶
import json
import jsonschema
from typing import Dict, Any
def parse_metadata(data: bytes) -> Dict[str, Any]:
"""Parse and validate PSPF metadata."""
text = data.decode('utf-8')
metadata = json.loads(text)
jsonschema.validate(metadata, PSPF_SCHEMA)
return metadata
def canonicalize(metadata: Dict[str, Any]) -> bytes:
"""Convert to canonical form."""
return json.dumps(
metadata,
separators=(',', ':'),
sort_keys=True,
ensure_ascii=False
).encode('utf-8')
Go Implementation¶
package pspf
import (
"encoding/json"
"github.com/xeipuuv/gojsonschema"
)
type Metadata struct {
FormatVersion string `json:"format_version"`
Package Package `json:"package"`
Slots []Slot `json:"slots"`
// ... other fields
}
func ParseMetadata(data []byte) (*Metadata, error) {
var meta Metadata
if err := json.Unmarshal(data, &meta); err != nil {
return nil, err
}
// Validate against schema
result, err := ValidateSchema(meta)
if err != nil || !result.Valid() {
return nil, ErrSchemaViolation
}
return &meta, nil
}
Rust Implementation¶
use serde::{Deserialize, Serialize};
use serde_json;
use jsonschema;
#[derive(Debug, Deserialize, Serialize)]
struct Metadata {
format_version: String,
package: Package,
slots: Vec<Slot>,
// ... other fields
}
fn parse_metadata(data: &[u8]) -> Result<Metadata, Error> {
let text = std::str::from_utf8(data)?;
let metadata: Metadata = serde_json::from_str(text)?;
// Validate against schema
let schema = json!(PSPF_SCHEMA);
let compiled = jsonschema::JSONSchema::compile(&schema)?;
compiled.validate(&json!(metadata))?;
Ok(metadata)
}
12.3 Performance Requirements¶
Implementations SHOULD meet these targets:
- Parsing: < 10ms for 100KB metadata
- Validation: < 5ms for schema validation
- Canonicalization: < 2ms for typical metadata
- Memory Usage: < 10x metadata size
13. Test Vectors¶
13.1 Minimal Valid Metadata¶
Input:
Canonical Form (hex):
7b22666f726d61745f76657273696f6e223a22323032352e302e30222c227061636b616765223a7b226e616d65223a2274657374222c2276657273696f6e223a22312e302e30227d2c22736c6f7473223a5b5d7d
SHA-256: 5f95b7cf2f47fc5b7866ea021fe51cea6bc3bbceb9d3eb87a1244bd8db576eb0
13.2 Complete Metadata Example¶
Input:
{
"format_version": "2025.0.0",
"package": {
"name": "example-app",
"version": "2.1.0-beta+build.123",
"description": "Example application",
"author": "PSPF Team",
"license": "MIT",
"homepage": "https://pspf.io"
},
"build": {
"timestamp": 1704067200,
"platform": "linux_x86_64",
"builder": "flavorpack-0.1.0",
"source_hash": "abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789",
"reproducible": true
},
"slots": [
{
"id": 0,
"name": "runtime",
"purpose": "code",
"lifecycle": "startup",
"operations": "tar.gz",
"size": 1048576,
"original_size": 4194304,
"checksum": "deadbeef",
"permissions": "755"
},
{
"id": 1,
"name": "config",
"purpose": "config",
"lifecycle": "config",
"operations": "gzip",
"size": 1024,
"checksum": "cafebabe"
}
],
"execution": {
"entry_point": "./bin/app",
"args": ["--config", "/etc/app.conf"],
"env": {
"APP_HOME": "/opt/app",
"LOG_LEVEL": "info"
},
"working_directory": "."
},
"dependencies": {
"runtime": ["libc.so.6", "libssl.so.3"],
"optional": ["libcuda.so.12"]
},
"extensions": {
"x-vendor-signature": "xyz789",
"x-custom-field": {
"nested": "value"
}
}
}
13.3 Invalid Examples¶
Duplicate Slot ID:
{
"format_version": "2025.0.0",
"package": {"name": "test", "version": "1.0.0"},
"slots": [
{"id": 0, "name": "slot1", ...},
{"id": 0, "name": "slot2", ...} // ERROR: Duplicate ID
]
}
ERROR_DUPLICATE_SLOT_ID (1200)
Invalid Operation String:
{
"format_version": "2025.0.0",
"package": {"name": "test", "version": "1.0.0"},
"slots": [{
"id": 0,
"operations": "invalid|operation", // ERROR: Unknown operation
...
}]
}
ERROR_INVALID_OPERATIONS (1201)
Path Traversal Attempt:
Expected Error:ERROR_PATH_TRAVERSAL (1300)
14. References¶
14.1 Normative References¶
RFC2119 Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, March 1997.
RFC8174 Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, May 2017.
[RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data Interchange Format", RFC 7159, March 2014.
[RFC5234] Crocker, D., Ed., and P. Overell, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234, January 2008.
[RFC4627] Crockford, D., "The application/json Media Type for JavaScript Object Notation (JSON)", RFC 4627, July 2006.
14.2 Informative References¶
[FEP-0001] "PSPF/2025 Core Format & Operation Chains Specification", FEP-0001, January 2025.
[FEP-0003] "PSPF/2025 Operation Registry and Allocation Policy", FEP-0003, January 2025.
[JSON-SCHEMA] "JSON Schema: A Media Type for Describing JSON Documents", draft-handrews-json-schema-02, September 2019.
[SEMVER] Preston-Werner, T., "Semantic Versioning 2.0.0", https://semver.org/spec/v2.0.0.html
[SPDX] "Software Package Data Exchange (SPDX) Specification", https://spdx.org/specifications
Authors' Addresses
[Author contact information]
Copyright Notice
Copyright © 2025 IETF Trust and the persons identified as the document authors. All rights reserved.