Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
pulp::authoring_capsule Namespace Reference

Classes

struct  MemberInfo
class  CapsuleArchive
 A reader over an admitted archive. More...
struct  WriteMember
 One member to write. path must already be normalized. More...
struct  CanonicalPcm
struct  AdmissionOptions
struct  ExportItem
 One member of an export inventory. More...
struct  ExportRequest
class  Redistribution
 Permission to pass a component's bytes on. More...
struct  ComponentPolicy
struct  FileEntry
 One row of the archive closure. More...
struct  DependencyEntry
 A component whose bytes are not in the archive. More...
struct  ComponentRef
 A reference to one component row, for a result that must name components it does not own. More...
struct  CapsuleLimits
struct  Compatibility
 Version floors the consuming runtime must satisfy. More...
struct  Manifest
struct  CapabilityRequirement
struct  DependencySummary
struct  RightsSummary
 Rights facts, machine-derived. More...
struct  CapsulePreview
class  ProfileValidator
 Semantic validation of an extracted staging tree. More...
class  ProfileRegistry
struct  SignatureEnvelope
struct  VersionFloor
 Minimum version the signer will let this capsule be admitted at. More...
class  SignatureVerifier
class  StagingArea
 A private directory that is removed when it goes out of scope unless it was published. More...
struct  CapsuleError
 A rejection with the exact subject that caused it. More...

Typedefs

using ExtractionProgress = std::function<bool(std::size_t member_index, std::size_t member_count)>
 Progress and cancellation.

Enumerations

enum class  Canonicality : std::uint8_t { canonical_input , derived_output , preview , receipt }
enum class  SourceAvailability : std::uint8_t { included , external , local_only , omitted }
enum class  Editability : std::uint8_t { editable , opaque }
enum class  Disclosure : std::uint8_t {
  public_ , recipient_scoped , private_ , redacted ,
  not_recorded
}
enum class  RequiredFor : std::uint8_t { play , rebuild , remix , publish }
 Operations a component is required for. More...
enum class  Completeness : std::uint8_t { self_contained , resolvable , partial , play_only }
 Derived from the component rows. More...
enum class  Reproducibility : std::uint8_t { reproducible , best_effort , frozen_output_only }
enum class  CompatibilityVerdict : std::uint8_t { supported , other_product , runtime_too_old , unsupported }
 What the local runtime can offer for this capsule. More...
enum class  CapsuleStatus : std::uint8_t {
  ok , manifest_invalid , manifest_not_first , unsupported_format ,
  unsupported_format_version , unsupported_profile , unsupported_profile_version , unsupported_product ,
  unsupported_capability , missing_required_role , runtime_floor_too_old , schema_migration_refused ,
  closure_violation , digest_mismatch , unsafe_archive , archive_budget_exceeded ,
  path_rejected , path_collision , missing_dependency , dependency_digest_mismatch ,
  dependency_provider_denied , missing_licensed_sample , rights_insufficient , signature_invalid ,
  revoked_signer , downgrade_refused , creator_identity_required , decode_unsupported ,
  staging_failed , publication_conflict , cancelled
}

Functions

runtime::Result< CapsuleArchive, CapsuleError > open_archive (const std::filesystem::path &path, const CapsuleLimits &limits=kCapsuleLimitsV1)
runtime::Result< std::uint64_t, CapsuleError > write_archive_no_replace (const std::vector< WriteMember > &members, const std::filesystem::path &destination, const CapsuleLimits &limits=kCapsuleLimitsV1)
 Write deterministically to a path that must not already exist.
runtime::Result< CanonicalPcm, CapsuleError > decode_to_canonical (std::span< const std::uint8_t > source)
 Decode a source audio file into the canonical form.
std::vector< std::uint8_t > to_canonical_bytes (const CanonicalPcm &pcm)
 Serialize to the exact member bytes a capsule stores: the fixed header documented at the top of this file, then the interleaved little-endian binary32 samples.
runtime::Result< CanonicalPcm, CapsuleError > from_canonical_bytes (std::span< const std::uint8_t > bytes)
 Parse a canonical member from its bytes alone; no external metadata exists.
std::string canonical_pcm_digest (const CanonicalPcm &pcm)
 SHA-256, bare lowercase hex, over to_canonical_bytes(pcm).
runtime::Result< void, CapsuleError > validate_canonical (const CanonicalPcm &pcm)
 Reject NaN, infinity, and any frame count that disagrees with the buffer length.
runtime::Result< CapsulePreview, CapsuleError > preview_capsule (const CapsuleArchive &archive, const ProfileRegistry &registry, const AdmissionOptions &options)
 Steps 1-4 of the import state machine: bounded manifest read, structural and closure validation, optional trust envelope, and a non-executing preview.
runtime::Result< void, CapsuleError > admit_to_staging (const CapsuleArchive &archive, const CapsulePreview &preview, const ProfileRegistry &registry, const StagingArea &staging, const ExtractionProgress &progress={})
 Steps 6-7: extract only declared members into staging, verifying digests, then run the profile's semantic validation.
runtime::Result< std::uint64_t, CapsuleError > export_capsule (ExportRequest request, const std::filesystem::path &destination, const CapsuleLimits &limits=kCapsuleLimitsV1)
 Fill in the closure — sorted files, digests, sizes, and revision_id — and write one deterministic archive to a destination that must not exist.
runtime::Result< std::string, CapsuleError > to_canonical_json (const Manifest &manifest)
 Serialize to canonical JSON: UTF-8 without BOM, LF, keys sorted by code point, no insignificant whitespace, shortest round-tripping numbers, no NaN or infinity, files sorted by path and dependencies by id in byte order.
runtime::Result< Manifest, CapsuleError > parse_manifest (std::string_view json)
 Parse and structurally validate.
runtime::Result< std::string, CapsuleError > revision_digest (const Manifest &manifest)
 sha256 over the canonical JSON of the whole manifest with exactly three fields removed: revision_id (self-referential), exported_at (the one value that changes when nothing else did), and attestations (signatures are computed over this digest).
Completeness derive_completeness (const Manifest &manifest)
 Recomputed from the component rows.
runtime::Result< std::string, CapsuleError > admit_member_path (std::string_view raw, const CapsuleLimits &limits=kCapsuleLimitsV1)
 Verify a member path and return it unchanged.
std::string collision_key (std::string_view normalized_path)
 Fold a normalized path to the key used for collision detection: ASCII case-folded, NFC, with confusable characters mapped to a representative.
runtime::Result< void, CapsuleError > check_collisions (const std::vector< std::string > &normalized)
 Detect a collision across a member set. Returns the first offending pair.
runtime::Result< void, CapsuleError > extract_declared (const CapsuleArchive &archive, const Manifest &manifest, const StagingArea &staging, const ExtractionProgress &progress={})
 Extract only the members the manifest declares, verifying each digest as it lands.
runtime::Result< std::vector< std::uint8_t >, CapsuleError > read_staged_member (const StagingArea &staging, const FileEntry &entry)
 Read one member back out of a staged tree.
runtime::Result< std::vector< std::uint8_t >, CapsuleError > read_staged_member (const std::filesystem::path &staging_root, const FileEntry &entry)
 Reads a declared member from a staging root the caller does not own.
std::string_view status_token (CapsuleStatus status) noexcept
 Stable machine-readable token, e.g.

Variables

constexpr std::uint32_t kMinCanonicalSampleRate = 8000
constexpr std::uint32_t kMaxCanonicalSampleRate = 192000
constexpr std::uint32_t kMaxCanonicalChannels = 2
constexpr std::uint32_t kCanonicalPcmDecoderVersion = 1
 The decoder's contract version, stored in every canonical member's header.
constexpr char kCanonicalPcmMagic [8] = {'p', 'u', 'l', 'p', '.', 'p', 'c', 'm'}
 First eight bytes of every canonical member.
constexpr std::size_t kCanonicalPcmHeaderBytes = 28
 Fixed header size; sample data begins here.
constexpr std::string_view kManifestPath = "capsule.json"
 Fixed path of the manifest, which must also be the archive's first member.
constexpr CapsuleLimits kCapsuleLimitsV1 {}
 The frozen v1 budgets.
constexpr std::string_view kFormatId = "org.pulp.audio-authoring-capsule"
 The vendor-neutral format identifier. Constant for format version 1.
constexpr std::uint32_t kFormatVersion = 1

Typedef Documentation

◆ ExtractionProgress

using pulp::authoring_capsule::ExtractionProgress = std::function<bool(std::size_t member_index, std::size_t member_count)>

Progress and cancellation.

Returning false cancels; the staging area is discarded and nothing outside it was ever touched.

Enumeration Type Documentation

◆ Canonicality

enum class pulp::authoring_capsule::Canonicality : std::uint8_t
strong
Enumerator
canonical_input 
derived_output 
preview 
receipt 

◆ CapsuleStatus

enum class pulp::authoring_capsule::CapsuleStatus : std::uint8_t
strong
Enumerator
ok 
manifest_invalid 
manifest_not_first 
unsupported_format 
unsupported_format_version 
unsupported_profile 
unsupported_profile_version 
unsupported_product 
unsupported_capability 
missing_required_role 

The profile requires a semantic role this capsule does not carry, so the payload cannot satisfy the profile it claims.

runtime_floor_too_old 
schema_migration_refused 
closure_violation 
digest_mismatch 
unsafe_archive 
archive_budget_exceeded 
path_rejected 
path_collision 
missing_dependency 
dependency_digest_mismatch 
dependency_provider_denied 
missing_licensed_sample 
rights_insufficient 
signature_invalid 
revoked_signer 
downgrade_refused 
creator_identity_required 
decode_unsupported 
staging_failed 
publication_conflict 
cancelled 

◆ CompatibilityVerdict

enum class pulp::authoring_capsule::CompatibilityVerdict : std::uint8_t
strong

What the local runtime can offer for this capsule.

Enumerator
supported 

Profile registered, versions satisfied, capabilities available.

other_product 

Understood, but this product is not its product.

The caller can offer to hand it to the right one; it must never coerce the profile.

runtime_too_old 

Understood, but the local runtime is too old.

unsupported 

The profile or a required capability is not registered here.

◆ Completeness

enum class pulp::authoring_capsule::Completeness : std::uint8_t
strong

Derived from the component rows.

A capsule that declares its own completeness is ignored: the reader recomputes it.

Enumerator
self_contained 

Every required byte is present and may be redistributed.

resolvable 

Required components are absent but have stable identities and resolvers.

partial 

Inspectable or editable, but not fully rebuildable or playable.

play_only 

The admitted rendition plays; canonical editable inputs are incomplete.

◆ Disclosure

enum class pulp::authoring_capsule::Disclosure : std::uint8_t
strong
Enumerator
public_ 
recipient_scoped 
private_ 
redacted 
not_recorded 

◆ Editability

enum class pulp::authoring_capsule::Editability : std::uint8_t
strong
Enumerator
editable 
opaque 

◆ Reproducibility

enum class pulp::authoring_capsule::Reproducibility : std::uint8_t
strong
Enumerator
reproducible 

Declared inputs plus pinned dependencies regenerate the result, and receipts prove the claim.

best_effort 

Source and history are present, but a model, tool, or environment cannot be replayed exactly.

Preserving the accepted output is still worth doing; claiming determinism it does not have is not.

frozen_output_only 

Only playable derived artifacts are present.

◆ RequiredFor

enum class pulp::authoring_capsule::RequiredFor : std::uint8_t
strong

Operations a component is required for.

A component missing from the capsule downgrades exactly the operations that list it.

Enumerator
play 
rebuild 
remix 
publish 

◆ SourceAvailability

enum class pulp::authoring_capsule::SourceAvailability : std::uint8_t
strong
Enumerator
included 

Bytes travel in the capsule.

external 

Bytes are named by digest and fetched from a declared provider.

local_only 

Bytes exist only on the exporting machine and were deliberately omitted.

omitted 

Deliberately absent under the selected export policy.

Function Documentation

◆ admit_member_path()

runtime::Result< std::string, CapsuleError > pulp::authoring_capsule::admit_member_path ( std::string_view raw,
const CapsuleLimits & limits = kCapsuleLimitsV1 )

Verify a member path and return it unchanged.

It does not rewrite bytes toward NFC: with no Unicode character database linked, the only sound options are prove already-NFC or reject, and quietly returning a half-normalized path would be worse than either. A path this cannot prove is NFC is rejected.

Also rejects absolute paths, drive letters, UNC prefixes, any . or .. component, leading or trailing separators, empty components, backslashes, NUL and C0 controls, trailing dots or spaces, and anything past the depth or byte budget.

The accepted subset is narrow, which is affordable because a member path is generated by the exporter and is never the user's filename — a sample is content-addressed and the author's chosen name travels as metadata, where arbitrary text is fine.

◆ admit_to_staging()

runtime::Result< void, CapsuleError > pulp::authoring_capsule::admit_to_staging ( const CapsuleArchive & archive,
const CapsulePreview & preview,
const ProfileRegistry & registry,
const StagingArea & staging,
const ExtractionProgress & progress = {} )

Steps 6-7: extract only declared members into staging, verifying digests, then run the profile's semantic validation.

Does not publish and does not compile. The caller has consent before calling this.

◆ canonical_pcm_digest()

std::string pulp::authoring_capsule::canonical_pcm_digest ( const CanonicalPcm & pcm)

SHA-256, bare lowercase hex, over to_canonical_bytes(pcm).

This is the identity a files[] row carries for an audio member — and because it is the digest of the member bytes themselves, it is the same digest the exporter's uniform member hashing and the importer's extraction check compute, with no audio-specific exception.

◆ check_collisions()

runtime::Result< void, CapsuleError > pulp::authoring_capsule::check_collisions ( const std::vector< std::string > & normalized)

Detect a collision across a member set. Returns the first offending pair.

◆ collision_key()

std::string pulp::authoring_capsule::collision_key ( std::string_view normalized_path)

Fold a normalized path to the key used for collision detection: ASCII case-folded, NFC, with confusable characters mapped to a representative.

Two members whose keys match are a collision even when their bytes differ — on a case-insensitive filesystem one would silently overwrite the other.

◆ decode_to_canonical()

runtime::Result< CanonicalPcm, CapsuleError > pulp::authoring_capsule::decode_to_canonical ( std::span< const std::uint8_t > source)

Decode a source audio file into the canonical form.

Admitted formats are exactly the ones that decode deterministically — identical bytes in, identical samples out, on every ISA:

  • WAV: RIFF/WAVE PCM16/PCM24/PCM32 and float32, including WAVE_FORMAT_EXTENSIBLE wrapping those;
  • AIFF and AIFF-C: big-endian PCM at 9..32 declared bits (decoded at the byte-container depth, since AIFF left-justifies), AIFF-C NONE/twos, 16-bit sowt, and fl32 float32;
  • FLAC: dr_flac's bit-exact integer decode, with this module's own power-of-two integer-to-float scaling.

Anything else — MP3, OGG, AAC, CAF, an unknown container, a codec inside a supported container — returns decode_unsupported naming what was found: an approximation the user did not ask for is worse than a refusal they can act on.

◆ derive_completeness()

Completeness pulp::authoring_capsule::derive_completeness ( const Manifest & manifest)

Recomputed from the component rows.

A declared value in the capsule is ignored.

◆ export_capsule()

runtime::Result< std::uint64_t, CapsuleError > pulp::authoring_capsule::export_capsule ( ExportRequest request,
const std::filesystem::path & destination,
const CapsuleLimits & limits = kCapsuleLimitsV1 )

Fill in the closure — sorted files, digests, sizes, and revision_id — and write one deterministic archive to a destination that must not exist.

Repeating this for unchanged content reproduces the file byte for byte.

What it validates, exactly. Each item's path is re-admitted and may not claim capsule.json; each digest and size is measured from the bytes that travel rather than taken from what the caller declared; the item set is checked for case and confusable collisions; and the finished manifest is read back through parse_manifest() before the archive is created. That last step is what applies the structural rules — a files[] row must declare source_availability: included, a dependency's provider must be https:// or capsule-library:, format/profile/product/ project_id must be present — to a Manifest that was assembled in memory and never parsed. to_canonical_json() alone applies none of them, so without the read-back a caller passing its own dependency rows straight through could mint a capsule this same code refuses to read. The refusal carries parse_manifest()'s status and JSON-pointer subject, and nothing is written.

dependencies[] is otherwise carried through as given: this layer resolves nothing, contacts no provider, and cannot confirm that a dependency's digest names the bytes a recipient will eventually fetch.

◆ extract_declared()

runtime::Result< void, CapsuleError > pulp::authoring_capsule::extract_declared ( const CapsuleArchive & archive,
const Manifest & manifest,
const StagingArea & staging,
const ExtractionProgress & progress = {} )

Extract only the members the manifest declares, verifying each digest as it lands.

An undeclared member is never written, so a capsule cannot smuggle a file past the closure it published.

◆ from_canonical_bytes()

runtime::Result< CanonicalPcm, CapsuleError > pulp::authoring_capsule::from_canonical_bytes ( std::span< const std::uint8_t > bytes)

Parse a canonical member from its bytes alone; no external metadata exists.

The header is self-checking: a wrong magic, a decoder_version this build does not implement, a channel count outside [1, 2], or a payload whose length disagrees with the declared geometry is refused. There is no separate media struct: a successful parse returns the header's fields in the CanonicalPcm itself, and the decoder version is not surfaced because success proves it equals kCanonicalPcmDecoderVersion.

◆ open_archive()

runtime::Result< CapsuleArchive, CapsuleError > pulp::authoring_capsule::open_archive ( const std::filesystem::path & path,
const CapsuleLimits & limits = kCapsuleLimitsV1 )

◆ parse_manifest()

runtime::Result< Manifest, CapsuleError > pulp::authoring_capsule::parse_manifest ( std::string_view json)

Parse and structurally validate.

Does not check the archive closure — that needs the archive; see admit().

◆ preview_capsule()

runtime::Result< CapsulePreview, CapsuleError > pulp::authoring_capsule::preview_capsule ( const CapsuleArchive & archive,
const ProfileRegistry & registry,
const AdmissionOptions & options )

Steps 1-4 of the import state machine: bounded manifest read, structural and closure validation, optional trust envelope, and a non-executing preview.

Nothing is written outside the process.

This is also where the profile's required_roles() is applied — a missing role surfaces as missing_required_role in unmet with an unsupported verdict, which admit_to_staging() then refuses on. A consumer does not repeat that check.

◆ read_staged_member() [1/2]

runtime::Result< std::vector< std::uint8_t >, CapsuleError > pulp::authoring_capsule::read_staged_member ( const StagingArea & staging,
const FileEntry & entry )

Read one member back out of a staged tree.

This exists so a consumer never joins a manifest path to a staging root itself. The path rules and the join belong to the same layer: a consumer doing staging.root() / entry.path by hand is a path-admission decision made outside the module that owns path admission, and it silently loses the NFC, depth, byte-budget, reserved-name, and containment checks. So the row is re-admitted here — this is a public entry point taking an arbitrary FileEntry, and it cannot assume a caller ran preview or extraction first.

Every hop is opened relative to the staging area's pinned root refusing to follow links, and only a plain file is read: nothing in this module creates a symlink, a device, or a directory where a member belongs, so one standing there means the tree is not the one extraction wrote.

The size on disk must equal entry.bytes. That is checked before the bytes are copied out, so the read is bounded by what the owner-private tree actually holds rather than by a size the row asserted, and a truncated or replaced member is refused rather than returned as if it were whole. The content digest is not recomputed: extract_declared() verified it before the member was allowed to land, and the staging directory is readable only by its owner, so re-hashing on every read would charge a repeated cost for a property already established. A caller that wants the stronger check can hash the returned bytes against entry.sha256 itself.

Failures are exact. A path that fails admission reports whatever admit_member_path() decided — path_rejected for a path that could escape or that the grammar refuses. Everything else is staging_failed, with the declared and found sizes in required and found when the disagreement is a size.

◆ read_staged_member() [2/2]

runtime::Result< std::vector< std::uint8_t >, CapsuleError > pulp::authoring_capsule::read_staged_member ( const std::filesystem::path & staging_root,
const FileEntry & entry )

Reads a declared member from a staging root the caller does not own.

ProfileValidator::validate_staged() receives the staging root as a path rather than as a StagingArea, and a StagingArea cannot be adopted from an existing tree — create() makes a new one. Without this overload the entry point that exists so a consumer never joins an untrusted member path to a directory by hand is unreachable from the one place every consumer needs exactly that, and each profile hand-rolls the join instead.

Identical to the overload above in every respect: the same admission, the same directory-identity checks before and after the read, the same errors. The StagingArea is only ever read for its root.

◆ revision_digest()

runtime::Result< std::string, CapsuleError > pulp::authoring_capsule::revision_digest ( const Manifest & manifest)

sha256 over the canonical JSON of the whole manifest with exactly three fields removed: revision_id (self-referential), exported_at (the one value that changes when nothing else did), and attestations (signatures are computed over this digest).

Everything else is covered — title, created_at, provenance, distribution, each file row's executable_data, and any unknown optional key. Those fields are not inert: distribution is what makes a capsule Play-only and executable_data is what tells the user a payload contains code, so leaving either outside the digest would let outer metadata be edited on a validly signed capsule and still verify.

None of the covered fields depends on the machine or the moment, so the digest remains independent of compression level, archive member order, filesystem timestamps, export time, and the exporting machine's paths. Two exports of an unchanged project agree.

Fallible for the same reason to_canonical_json() is: the digest is taken over canonical bytes, so it cannot exist when those bytes cannot.

◆ status_token()

std::string_view pulp::authoring_capsule::status_token ( CapsuleStatus status)
noexcept

Stable machine-readable token, e.g.

"digest_mismatch". Stable across releases: products key their explanatory copy off these.

◆ to_canonical_bytes()

std::vector< std::uint8_t > pulp::authoring_capsule::to_canonical_bytes ( const CanonicalPcm & pcm)

Serialize to the exact member bytes a capsule stores: the fixed header documented at the top of this file, then the interleaved little-endian binary32 samples.

canonical_pcm_digest() is the SHA-256 of exactly this buffer. The caller validates first; the header carries the fields as declared.

◆ to_canonical_json()

runtime::Result< std::string, CapsuleError > pulp::authoring_capsule::to_canonical_json ( const Manifest & manifest)

Serialize to canonical JSON: UTF-8 without BOM, LF, keys sorted by code point, no insignificant whitespace, shortest round-tripping numbers, no NaN or infinity, files sorted by path and dependencies by id in byte order.

Fallible because a hand-assembled Manifest can hold material no reader ever validated — a non-UTF-8 string, or a preserved subtree past the depth limit. Returning an empty string instead would hand the exporter a capsule that fails admission later, with nothing to tell the user why.

◆ validate_canonical()

runtime::Result< void, CapsuleError > pulp::authoring_capsule::validate_canonical ( const CanonicalPcm & pcm)

Reject NaN, infinity, and any frame count that disagrees with the buffer length.

A capsule that admitted a NaN would hand machine B silence or a blown output the author never heard.

◆ write_archive_no_replace()

runtime::Result< std::uint64_t, CapsuleError > pulp::authoring_capsule::write_archive_no_replace ( const std::vector< WriteMember > & members,
const std::filesystem::path & destination,
const CapsuleLimits & limits = kCapsuleLimitsV1 )

Write deterministically to a path that must not already exist.

Members are emitted in the given order with fixed metadata, so repeating an export of unchanged content reproduces the file byte for byte. The destination appears only once it is complete: a cancelled or failed write leaves no partial file for a person to mistake for a good one.

Variable Documentation

◆ kCanonicalPcmDecoderVersion

std::uint32_t pulp::authoring_capsule::kCanonicalPcmDecoderVersion = 1
inlineconstexpr

The decoder's contract version, stored in every canonical member's header.

A decode that is deterministic today must stay comparable tomorrow: a change to the decode arithmetic is a change to every digest it produced, so it must advance this number.

◆ kCanonicalPcmHeaderBytes

std::size_t pulp::authoring_capsule::kCanonicalPcmHeaderBytes = 28
inlineconstexpr

Fixed header size; sample data begins here.

◆ kCanonicalPcmMagic

char pulp::authoring_capsule::kCanonicalPcmMagic[8] = {'p', 'u', 'l', 'p', '.', 'p', 'c', 'm'}
inlineconstexpr

First eight bytes of every canonical member.

◆ kCapsuleLimitsV1

CapsuleLimits pulp::authoring_capsule::kCapsuleLimitsV1 {}
inlineconstexpr

The frozen v1 budgets.

A consumer may tighten a field; loosening one is a format change, not a configuration choice.

◆ kFormatId

std::string_view pulp::authoring_capsule::kFormatId = "org.pulp.audio-authoring-capsule"
inlineconstexpr

The vendor-neutral format identifier. Constant for format version 1.

◆ kFormatVersion

std::uint32_t pulp::authoring_capsule::kFormatVersion = 1
inlineconstexpr

◆ kManifestPath

std::string_view pulp::authoring_capsule::kManifestPath = "capsule.json"
inlineconstexpr

Fixed path of the manifest, which must also be the archive's first member.

It lives beside the budgets because it is a container fact: the reader requires it and the writer holds itself to the same rule, so neither may learn it from the envelope layer above.

◆ kMaxCanonicalChannels

std::uint32_t pulp::authoring_capsule::kMaxCanonicalChannels = 2
inlineconstexpr

◆ kMaxCanonicalSampleRate

std::uint32_t pulp::authoring_capsule::kMaxCanonicalSampleRate = 192000
inlineconstexpr

◆ kMinCanonicalSampleRate

std::uint32_t pulp::authoring_capsule::kMinCanonicalSampleRate = 8000
inlineconstexpr