/* StarForth — Steady-State Virtual Machine Runtime Copyright (c) 2023–2025 Robert A. James All rights reserved. This file is part of the StarForth project. Licensed under the StarForth License, Version 1.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at: https://github.com/star.4th@proton.me/StarForth/LICENSE.txt This software is provided "AS IS", WITHOUT WARRANTY OF ANY KIND, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. See the License for the specific language governing permissions and limitations under the License. */ /** * capsule.h - Init Capsule Architecture (M7.1) * * Content-addressed, immutable init capsules for VM birth. * See docs/lithosananke/M7.1.md for full specification. * * Key invariants: * - Exactly ONE production (p) INIT defines a baby VM * - capsule_id == content_hash (content-addressed) * - No shared/implicit base INITs * - DOMAIN is Mama-only, PERSONALITY is baby-only */ #ifndef STARKERNEL_CAPSULE_H #define STARKERNEL_CAPSULE_H #include #include #ifdef __cplusplus extern "C" { #endif /*=========================================================================== * Constants *===========================================================================*/ /** Magic signatures */ #define CAPSULE_DESC_MAGIC 0x53504143ULL /* 'CAPS' little-endian */ #define CAPSULE_DIR_MAGIC 0x44504143ULL /* 'CAPD' little-endian */ /** Version */ #define CAPSULE_VERSION_0 0 /** Limits */ #define CAPSULE_MAX_COUNT 256 /** Maximum capsule name length (colon-separated path, null-terminated) */ #define CAPSULE_NAME_MAX 512 /*=========================================================================== * Hash Algorithm Enum *===========================================================================*/ typedef enum { CAPSULE_HASH_XXHASH64 = 0, CAPSULE_HASH_SHA256 = 1, CAPSULE_HASH_BLAKE3 = 2, } CapsuleHashAlg; /*=========================================================================== * Flags *===========================================================================*/ /** State flags */ #define CAPSULE_FLAG_ACTIVE 0x00000001 /* Eligible for use */ #define CAPSULE_FLAG_REVOKED 0x00000002 /* Birth-blocked forever */ #define CAPSULE_FLAG_DEPRECATED 0x00000004 /* Eligible but discouraged */ #define CAPSULE_FLAG_PINNED 0x00000008 /* Immune to GC */ /** Mode flags (D2: babies carry both) */ #define CAPSULE_FLAG_PRODUCTION 0x00000010 /* (p) truth-bearing */ #define CAPSULE_FLAG_EXPERIMENT 0x00000020 /* (e) workload only */ /** Mama init flag (exactly one capsule must have this) */ #define CAPSULE_FLAG_MAMA_INIT 0x00000040 /* (m) Mama's init */ /** Validate mode flags. * Mama: neither (p) nor (e) may be set. * Babies: at least one of (p) or (e) must be set (both is fine — D2). */ #define CAPSULE_MODE_VALID(f) \ ((((f) & CAPSULE_FLAG_MAMA_INIT) != 0) ? \ (!((f) & (CAPSULE_FLAG_PRODUCTION | CAPSULE_FLAG_EXPERIMENT))) : \ (((f) & CAPSULE_FLAG_PRODUCTION) || ((f) & CAPSULE_FLAG_EXPERIMENT))) /** Check if capsule is Mama's init */ #define CAPSULE_IS_MAMA_INIT(f) \ (((f) & CAPSULE_FLAG_MAMA_INIT) && ((f) & CAPSULE_FLAG_ACTIVE)) /** Birth eligibility: active and not revoked (flag type irrelevant — D2) */ #define CAPSULE_BIRTH_ELIGIBLE(f) \ (((f) & CAPSULE_FLAG_ACTIVE) && \ !((f) & CAPSULE_FLAG_REVOKED)) /** DoE eligibility: experiment, active, not revoked */ #define CAPSULE_DOE_ELIGIBLE(f) \ (((f) & CAPSULE_FLAG_EXPERIMENT) && \ ((f) & CAPSULE_FLAG_ACTIVE) && \ !((f) & CAPSULE_FLAG_REVOKED)) /*=========================================================================== * Magic Field Packing * * bits 0..31 : 'CAPS' (0x53504143 little-endian) * bits 32..39 : version (0 for v0) * bits 40..47 : hashAlg (enum CapsuleHashAlg) * bits 48..63 : reserved (zero) *===========================================================================*/ #define CAPSULE_MAGIC_PACK(ver, alg) \ (CAPSULE_DESC_MAGIC | ((uint64_t)(ver) << 32) | ((uint64_t)(alg) << 40)) #define CAPSULE_MAGIC_GET_SIG(m) ((uint32_t)((m) & 0xFFFFFFFFULL)) #define CAPSULE_MAGIC_GET_VERSION(m) ((uint8_t)(((m) >> 32) & 0xFF)) #define CAPSULE_MAGIC_GET_HASHALG(m) ((uint8_t)(((m) >> 40) & 0xFF)) /*=========================================================================== * CapsuleDesc - Capsule Descriptor (64 bytes, cache-line aligned) *===========================================================================*/ typedef struct __attribute__((aligned(64))) { uint64_t magic; /* 0x00: 'CAPS' | ver | hashAlg | reserved */ uint64_t capsule_id; /* 0x08: == content_hash (content-addressed) */ uint64_t content_hash; /* 0x10: hash of payload bytes */ uint64_t offset; /* 0x18: byte offset into payload arena */ uint64_t length; /* 0x20: payload length in bytes */ uint32_t flags; /* 0x28: state + policy bits */ uint32_t owner_vm; /* 0x2C: 0 = mama, else child VM ID */ uint64_t birth_count; /* 0x30: how many VMs born from this */ uint64_t created_ns; /* 0x38: monotonic timestamp at registration */ } CapsuleDesc; /* 0x40 = 64 bytes */ /*=========================================================================== * CapsuleNameEntry - Capsule Name (parallel array to CapsuleDesc[]) * * Indexed 1:1 with capsule_descriptors[]. Name is the full relative path * from the capsule root with '/' replaced by ':', e.g.: * "core:init.4th" * "experiments:doe-l8:init-l8-diverse.4th" * "production:myvm.4th" *===========================================================================*/ typedef struct { char name[CAPSULE_NAME_MAX]; /* null-terminated, colon-separated path */ } CapsuleNameEntry; /*=========================================================================== * CapsuleDirHeader - Directory Header *===========================================================================*/ typedef struct { uint64_t magic; /* 'CAPD' | ver | reserved */ uint64_t arena_base; /* phys or virt base of payload arena */ uint64_t arena_size; /* bytes */ uint32_t desc_count; /* current number of descriptors */ uint32_t desc_capacity; /* max (fixed at compile time for Phase A) */ uint32_t name_count; /* == desc_count, kept separate for validation */ uint32_t reserved; /* padding */ uint64_t dir_hash; /* hash of descriptor table (for parity) */ } CapsuleDirHeader; /*=========================================================================== * Validation *===========================================================================*/ typedef enum { CAPSULE_VALID = 0, CAPSULE_ERR_BAD_MAGIC, CAPSULE_ERR_BAD_VERSION, CAPSULE_ERR_BAD_HASH_ALG, CAPSULE_ERR_BOUNDS, CAPSULE_ERR_MODE_INVALID, CAPSULE_ERR_REVOKED_ACTIVE, CAPSULE_ERR_HASH_MISMATCH, CAPSULE_ERR_NULL_PTR, } CapsuleValidateResult; /** * capsule_validate - Validate a capsule descriptor * * @param desc Capsule descriptor to validate * @param arena_base Base address of payload arena * @param arena_size Size of payload arena in bytes * @param verify_hash If true, recompute and compare content hash * @return CAPSULE_VALID on success, error code otherwise */ CapsuleValidateResult capsule_validate( const CapsuleDesc *desc, const uint8_t *arena_base, uint64_t arena_size, int verify_hash ); /** * capsule_validate_result_str - Get string for validation result */ const char *capsule_validate_result_str(CapsuleValidateResult result); /*=========================================================================== * Lookup *===========================================================================*/ /** * capsule_find_by_id - Find capsule by content hash ID * * @param dir Directory header * @param descs Descriptor array * @param id Capsule ID (content hash) to find * @return Pointer to descriptor, or NULL if not found */ const CapsuleDesc *capsule_find_by_id( const CapsuleDirHeader *dir, const CapsuleDesc *descs, uint64_t id ); /** * capsule_find_by_name - Find capsule by colon-separated name * * @param dir Directory header * @param descs Descriptor array * @param names Name entry array (parallel to descs) * @param name Colon-separated capsule name, e.g. "core:init.4th" * @return Pointer to descriptor, or NULL if not found */ const CapsuleDesc *capsule_find_by_name( const CapsuleDirHeader *dir, const CapsuleDesc *descs, const CapsuleNameEntry *names, const char *name ); /** * capsule_get_payload - Get pointer to capsule payload bytes * * @param desc Capsule descriptor * @param arena_base Base address of payload arena * @return Pointer to payload bytes, or NULL on error */ const uint8_t *capsule_get_payload( const CapsuleDesc *desc, const uint8_t *arena_base ); /** * capsule_find_mama_init - Find the Mama init capsule * * Searches the descriptor array for the capsule with CAPSULE_FLAG_MAMA_INIT. * There must be exactly one such capsule. * * @param dir Directory header * @param descs Descriptor array * @return Pointer to Mama's init descriptor, or NULL if not found */ const CapsuleDesc *capsule_find_mama_init( const CapsuleDirHeader *dir, const CapsuleDesc *descs ); #ifdef __cplusplus } #endif #endif /* STARKERNEL_CAPSULE_H */