RadicalPackages

Package Format Reference

RADpm Reference

RADpm is the RADPx-OS package model: signed .radpm archives described by machine-readable JSON indexes that RadBuild reads to resolve and stage packages into generated root filesystems. This page documents the on-disk schema and packaging model that the published indexes currently express only by example.

Tool: radpm Index schema: radpm-package-index schema_version: 1 Suites: stable, experimental

What RADpm Is

RADpm is the RADPx-OS package system. A package is a .radpm archive (a tar archive that unpacks into a rootfs/ tree and/or standard top-level directories such as bin, etc, lib, usr) plus a JSON metadata record. The metadata records are gathered into a package index and an optional packagegroup index per suite and component.

The radpm tool (source: RADLib/tools/radpm/radpm.cpp) reads these indexes and supports the commands list, resolve, verify, install, and cache-toolchain. In the current release line RadBuild is the installer: it resolves package metadata and stages package archives into generated RADPx root filesystems. In-OS package management is not enabled yet.

Indexes live under a fixed repository layout. For a repository root, suite, and component the tool derives the paths radpm/dists/<suite>/main/packages.json and radpm/dists/<suite>/main/packagegroups.json (see indexLocation() in radpm.cpp). The default suite is experimental; stable is also published. A repository may also be pointed directly at a single .json index file, or at an http(s):// base URL.

Package Index Schema (radpm-package-index)

The package index is a JSON object. Top-level fields observed in the published indexes (radpm/dists/<suite>/main/packages.json):

  • schema — string identifier, always "radpm-package-index". Present in every index; a format marker.
  • schema_version — integer, currently 1. Present in every index.
  • repository — human-readable repository name (e.g. "RadicalPackages RADPx Package Repository"). The radpm tool reads this into the repository provider field (default "unknown"), which then supplies each package's default provider.
  • suite — the suite the index belongs to ("stable" or "experimental"). Informational in the file; the tool takes the active suite from its --suite option rather than this field.
  • component — component name, currently always "main". Present in the file; not consumed by the tool.
  • packages — array of package records (see below). Empty arrays are valid; the stable index currently ships "packages": [].
  • signing_keyoptional/observed, index level. A GPG key fingerprint for the index as a whole. Present in the experimental index; the tool parses signing_key only on individual package records, not at index level, so at index level it is descriptive metadata.
  • signatureoptional/observed, index level. URL of a detached ASCII-armored signature over the index file (e.g. packages.json.asc). Present in the experimental index; not consumed by the tool.

Package Record Fields

Each entry of packages is an object. The following fields are parsed by parsePackage() in radpm.cpp:

  • name — package name (required; the tool errors on a record with no name).
  • version — package version string, e.g. "0.1.0-crimson", "0.2.0-radpx" (required).
  • suite — suite for this package; defaults to the repository suite when omitted.
  • architecture — target architecture slug. Observed values: radpx-any (architecture-independent) and radpx-x86_64.
  • summary — one-line human description.
  • dependencies — array of package names (or provided virtual names) this package requires. Used by resolve/verify to report unmet dependencies.
  • provides — array of virtual names this package satisfies. A dependency is considered met if some selected package's name or one of its provides entries matches. Example: radpx-ncurses provides libncurses, libtinfo, libradpxc, etc.
  • archive — location of the .radpm archive: an absolute http(s) URL or a path relative to the index. May be null/absent for pure metadata packages. On resolve the tool computes an absolute archive_location from this.
  • sha256 — hex SHA-256 of the archive. This is the integrity check the tool actually enforces: install runs sha256sum on the downloaded archive and fails on mismatch. May be null/absent when there is no archive.
  • bytes — integer archive size in bytes (default 0).
  • docs — documentation reference for the package. Observed values are relative doc paths ("docs/radpx-os/0.1.4/api/", "docs/radlib/0.2.0/api/") or a portal page ("radpx-os.html").
  • signatureoptional. URL of a detached ASCII-armored signature over the archive (the archive URL with a .asc suffix). May be null/absent. See GPG Signing below.
  • signing_keyoptional. GPG key fingerprint that signed the archive. May be null/absent. Every signed package in the experimental index uses fingerprint F3731ADBB37AFA120A7D5EBD20B2754CF3894789.
  • provideroptional. Provider name; defaults to the repository's repository value when omitted (the current records omit it and inherit the default).
  • repository_urloptional. Provider repository URL; defaults to the repository root when omitted.
  • supported_kernel_versionsoptional/observed. Array of version-range strings, e.g. [">=0.1.0 <0.3.0"]. Present on every current package record but not parsed by radpm.cpp; treat it as advisory metadata rather than an enforced constraint.

Packagegroups

A packagegroup is a named, versioned set of package names that are meant to be selected together. RADPx OS images should select packagegroups first and add explicit packages only when needed: packagegroups keep terminal, desktop, networking, and SDK selections reproducible while still letting the resolver report missing dependencies. Selecting a group adds all of its member package names to the resolve set.

Packagegroup Index (radpm-packagegroup-index)

radpm/dists/<suite>/main/packagegroups.json is optional (repositories without it still load). Top-level fields mirror the package index — schema ("radpm-packagegroup-index"), schema_version, repository, suite, component, and an index-level signing_key (observed) — plus:

  • packagegroups — array of group entries. Each entry either carries the full group inline, or points to a separate descriptor file via descriptor (a path relative to the index) or url. When a descriptor/url is present the tool loads that file and reads the full group from it; the inline name/version/provider/summary fields in the index entry act as a preview.

Packagegroup Descriptor (radpm-packagegroup)

Each descriptor file (e.g. packagegroups/radpx-terminal-base.json) is parsed by parseGroupDescriptor():

  • schema"radpm-packagegroup"; schema_version1 (present in file, not parsed).
  • name — group name (required), e.g. radpx-terminal-base.
  • version — group version (required), e.g. "0.2.0-beta.1".
  • provideroptional. Provider name; defaults to the repository provider.
  • repository_urloptional. Provider repository URL; defaults to the repository root.
  • summary — one-line human description.
  • packages — array of member package names.
  • docs — documentation reference (observed: "radpx-os.html#packagegroups").

Published experimental groups: radpx-terminal-base, radpx-desktop-base, radpx-networking, and radpx-dev-sdk.

GPG Signing

RADpm artifacts are signed with the RadicalPackages archive key, fingerprint F3731ADBB37AFA120A7D5EBD20B2754CF3894789. The public key is committed at keys/radical-packages-archive-key.asc (ASCII-armored) and keys/radical-packages-archive-key.gpg (dearmored); the private key is never committed.

Signatures are detached and ASCII-armored (.asc). Each signed package record carries a signature URL alongside its archive — the archive URL with a .asc suffix — and a signing_key fingerprint. The experimental package index also carries an index-level signature (over packages.json) and signing_key, and each packagegroup index carries an index-level signing_key.

Note on enforcement: the radpm tool records and passes through these signing fields but does not itself invoke GPG. The integrity check it enforces on install is the sha256 of each downloaded archive. Signature verification with the archive key is therefore a separate, operator-driven step against the published .asc files. (The same key also clear-signs and detach-signs the parallel Debian/APT channels — InRelease and Release.gpg — via scripts/stage_github_release_apt_repo.py.)

Resolve Output (radpm-lock)

radpm resolve/verify emit a lock object that radpm install consumes. It is generated output rather than index schema, but documents how the fields above are used. Fields: schema ("radpm-lock"), schema_version, repository, suite, index, selected_packages, selected_packagegroups, packages (each resolved package record plus a computed archive_location), diagnostics, and ok. On a missing package or unmet dependency the tool instead emits a radpm-error object and exits non-zero.

Example: A Real Package Record

Drawn verbatim from radpm/dists/experimental/main/packages.json (the radpx-ncurses record), showing an architecture-specific, signed package with virtual provides:

{
  "name": "radpx-ncurses",
  "version": "0.1.0-experimental",
  "suite": "experimental",
  "architecture": "radpx-x86_64",
  "summary": "RADPx ncurses/tinfo shared runtime and development headers for x86_64 terminal applications.",
  "dependencies": [
    "radpx-core"
  ],
  "provides": [
    "libncurses",
    "libncursesw",
    "libtinfo",
    "libradpxc",
    "radpx-terminal-ui-dev"
  ],
  "supported_kernel_versions": [
    ">=0.1.0 <0.3.0"
  ],
  "archive": "https://github.com/Radical-Computer-Technologies/RadicalPackages/releases/download/radpx-os-0.1.4-beta.1/radpx-ncurses_0.1.0-experimental_radpx-x86_64.radpm",
  "sha256": "853b76699f78622fbe7877e4685128e802a96cd7e371479addbe47ef013ed714",
  "bytes": 607457,
  "docs": "radpx-os.html",
  "signature": "https://github.com/Radical-Computer-Technologies/RadicalPackages/releases/download/radpx-os-0.1.4-beta.1/radpx-ncurses_0.1.0-experimental_radpx-x86_64.radpm.asc",
  "signing_key": "F3731ADBB37AFA120A7D5EBD20B2754CF3894789"
}

The enclosing index adds the object header and, in the experimental suite, index-level signing_key and signature fields:

{
  "schema": "radpm-package-index",
  "schema_version": 1,
  "repository": "RadicalPackages RADPx Package Repository",
  "suite": "experimental",
  "component": "main",
  "packages": [ /* ...records... */ ],
  "signing_key": "F3731ADBB37AFA120A7D5EBD20B2754CF3894789",
  "signature": "https://github.com/Radical-Computer-Technologies/RadicalPackages/releases/download/radpx-os-0.1.4-beta.1/packages.json.asc"
}

Example: A Packagegroup Descriptor

From radpm/dists/experimental/main/packagegroups/radpx-terminal-base.json:

{
  "schema": "radpm-packagegroup",
  "schema_version": 1,
  "name": "radpx-terminal-base",
  "version": "0.2.0-beta.1",
  "provider": "RadicalPackages",
  "repository_url": "https://github.com/Radical-Computer-Technologies/RadicalPackages",
  "summary": "Core RADPx terminal image package set with RADLib, ncurses, and vim-tiny.",
  "packages": [
    "radpx-core",
    "radlib",
    "radpx-ncurses",
    "radpx-vim-tiny"
  ],
  "docs": "radpx-os.html#packagegroups"
}

Related