8691074bf4bbb434cbebb0c61acf6a40cd01987f0a9035a07c4cc484886fb43c
# Blind Machine curated protocol bundle — carrier_count.## This manifest is the ONLY file the Rails platform parses. The author's pure# functions in server.py / local_project_owner.py / local_data_owner.py own the# computation; the numbered stage files are kit-owned shims that call them (see# docs/rfcs/0002). This file owns the governance + review surface (display# metadata + the gate values that let compute be authorized without unpacking the# tarball). See docs/protocol_structure.md for the schema and# docs/protocol_catalog.md §2 for this protocol's definition.## carrier_count proves REGISTRY COMPOSABILITY: it reuses the flagship's exact# published coordinate definition and the exact additive-BFV primitive, changing# ONLY the client-side encoding (dosage {0,1,2} thresholded to a carrier# indicator {0,1} before encryption). One coordinate definition can drive# multiple registered protocols without touching the trust loop.name: carrier_countversion: 1.0.0builder: type: uv project: envcrypto: tenseal-bfv # display hint; real deps live in env/uv.lockcomputation: additive_bfv # coordinate-wise homomorphic add of indicatorsmin_contributors: 20# The published coordinate definition — IDENTICAL to the flagship# `allele_frequency_count` (catalog §2: "same published variant coordinate# definition as protocol 1, folded into the digest"). What differs is the# encoded value domain: each contributor locally thresholds the alt-allele# dosage to a carrier indicator, so the protocol operates on a binary vector# `c in {0,1}^L`. The raw genotype the data owner starts from is still dosage# {0,1,2}/null; 10_encode.py maps dosage >= 1 -> 1, else 0 (missing -> 0).input: type: integer_vector length: 1000 value_domain: [0, 1] # carrier indicator per coordinate; missing -> 0 coordinates: kind: synthetic_variants seed: blind-v1-demo-coordinates fields: [chrom, pos, ref, alt]output: shape: aggregate_count_vector # sum_c in Z^L (+ append-1 sentinel -> N); carrier rate = n/N exactness: exact # BFV is exact in Z_t; carrier sums <= N never overflow tolerance: 0release_policy: aggregate_only: true # only the summed vector is ever decrypted allowed_runs_per_project: 1 # run cap (differencing mitigation, not a defense)resources: max_memory_mb: 8192 max_wall_seconds: 3600 max_ciphertext_mb: 512# Collaboration scenario (docs/rfcs/0002 §4.1): who runs which role's functions.# The author writes pure functions grouped BY ROLE into the files below; the# numbered stage shims that call them are kit-owned framework code, materialized# at run time (never signed into the bundle). `aggregate` = 1 project owner + N# data owners.scenario: name: aggregate roles: project_owner: { file: local_project_owner.py, functions: [ keygen, decrypt, decode ] } data_owner: { file: local_data_owner.py, functions: [ encode, encrypt ] } server: { file: server.py, functions: [ compute ] }# Content-addressing digests. Computed at registry ingest — `bundle` by# protocols/hash_bundle.py, `env_lock` over env/uv.lock + env/.python-version +# pinned runner metadata. Left null in the committed bundle ON PURPOSE: the# canonical bundle digest is computed over the raw bytes of every signed file# INCLUDING this manifest, so a computed `bundle` value here would be# self-referential (its own input). The authoritative digest instead NAMES the# bundle (protocol-<name>@<digest>) and is recorded out-of-band# (.blind-signature / DB), never inside the file it would have to hash. See# protocols/README.md § "Why the manifest ships null hash placeholders".hashes: bundle: null env_lock: null
Inside signed payload digest 8691074bf4bb…886fb43c. Change one byte here and the application becomes a different application.