commits
Sweep crdt, delegation, dsp, ocamlfind, pid1, qemu, requests, scc,
sdls, sigstore, sle, spacedata, tls, vz, and prune: remove opam
dependencies that no dune stanza or source file references. Verified
each removal with a clean build and test run; the lint sweep is now
empty.
Sweep ocaml-scc, ocaml-scitt, ocaml-sdls, ocaml-sdnv, ocaml-sgp4,
ocaml-sle, ocaml-spake2, ocaml-sqlite, ocaml-srp to declare every
test-scope dependency that is actually used at test time.
Remove libraries declared in '(libraries ...)' clauses but unreferenced
by any module in the same source tree, as flagged by 'monopam lint'
after the new Dead_lib detection landed. Touches 131 dune files across
~80 packages.
A few stanzas needed a positive correction instead of a pure removal:
- ocaml-git/bin/diag: depended on eio_main + bytesrw-eio for an
Eio_posix.run call site; the umbrella was overkill, switch to the
precise eio_posix package.
- ocaml-scaleway/lib, ocaml-s3/lib: scaleway.mli / s3.mli reference
Eio_unix.Stdenv.base; eio.unix is required and was missing.
- merlint/lib: pulled bytesrw + nox-opam.bytesrw to surface
Opam_bytesrw, used by rule e915 and lint helpers.
Stanzas where Dead_lib was a false positive (transitive dep needed
for module visibility, virtual-library impls) are left untouched —
e.g. helix.jx.jsoo for ocaml-globe/demo retains its (libraries ...)
entry because it provides the impl of the helix.jx virtual lib.
Run mdx on eio/kek.mli so the {[ ... ]} odoc block now type-checks
the three KEK provisioning paths (auto, password-protected, explicit
file).
The example referenced a free `dir`, used unqualified `Kek.X`, and
discarded the return value with shadowing `let kek = ...` lines that
each ignore the previous binding. Restructured around a `report`
helper that prints the byte length on success and surfaces errors
via Fmt.epr + Sdls_eio.Kek.pp_error, then exercises all three calls
under one Eio_main.run so each branch's value is consumed.
Run mdx on eio/otar_eio.mli so the {[ ... ]} odoc block now
type-checks against the real Sdls.Otar / Sdls_eio.Otar_eio APIs.
The example referenced free `fs`, `kek`, `master_material`, `cmd`,
`send`, `log_error`, used unqualified `Otar_eio.of_path`, and
`let ... in` chains that do not parse at the toplevel. Wrapped in
`let run ~kek ~master_material ~cmd ~send = Eio_main.run @@ ...` so
the user supplies the credentials and command, the example shows
both the Ok reply and Error paths via Fmt.epr + Sdls.Otar.pp_error,
and the disk-touching of_path call doesn't execute at mdx test time.
Run mdx on eio/security_eio.mli so the {[ ... ]} odoc block now
type-checks against the real Sdls.Security and Sdls_eio.Security_eio
APIs.
The example used unqualified `Security_eio.of_path`, `Security.*`,
and the bare constructor `Bad_mac`; the real path resolution is
`Sdls.Security.Bad_mac` (the constructor lives on
`Sdls.Security.auth_failure_reason`, not `Sdls.Mc`). Added a wrapper
`let run () = ...` so the file-backed security store does not
materialise on disk at mdx test time, and replaced the trailing `...`
with a `Printf.printf` of the dump length so the example shows what
the store yields.
The example used 'fs', '...' and shorthand module references that don't
type-check. Wrap it in a 'run ()' function that takes env from
Eio_main.run, qualify Sdls_eio.Security_eio / Sdls.Security /
Sdls.Mc.Bad_mac fully, and replace the trailing '...' with a real
Printf.printf so the build catches drift.
Renaming packages to nox-* pushed several (libraries ...) lines past
dune fmt's wrap threshold, so dune fmt now spreads them one-per-line.
No semantic changes.
Renames 35 packages to make blacksun forks distinguishable from their
opam-repository upstreams. Module names (Git.x, Tls.x, ...) stay bare;
opam package names and dune (public_name) findlib references move to
nox-X. After this commit, zero local package names overlap with
opam-repository.
Renamed:
- nox-git, nox-irmin
- nox-crypto, nox-crypto-pk, nox-crypto-rng, nox-crypto-ec
- nox-tls, nox-tls-eio, nox-tar, nox-tar-eio, nox-tty, nox-tty-eio
- nox-arp, nox-ca-certs, nox-cbor, nox-cookie, nox-crc, nox-csv
- nox-gpt, nox-hkdf, nox-http, nox-jwt, nox-kdf, nox-loc
- nox-memtrace, nox-pds, nox-sexp, nox-slack, nox-toml
- nox-websocket, nox-x509, nox-xdge, nox-yaml
Also drops orphan tar-mirage and tar-unix opam templates that had no
matching package stanza.
Pure formatting changes from `dune fmt`: doc comment placement moves
from above the binding to below it for `type`s, multi-line `match`
expressions collapse onto one line where they fit, and infix operator
applications pick up spaces (`Soup.($?)` -> `Soup.( $? )`). No
semantic changes.
Follow up to the module rename: update the remaining callers that
still referenced [Err] (library [claude.ml{,i}], [client.ml], the test
driver [test.ml]), and fix one stray [^ e] string concatenation in
hermest's CLI that needed [Json.Error.to_string e] now that
[Json.of_string] yields a structured error.
Warning 69 (unused-field, mutable-never-assigned). Four independent
record fields were flagged as mutable but the code only mutates their
referents in place, never rebinds the record slot itself:
- ocaml-wal/lib/wal.ml: [t.file] (the Eio file resource; methods call
Eio.File.pwrite_all etc., the slot is set once at open time).
- ocaml-block/lib/block.ml: [Memory.state.data] (the backing bytes,
written via Bytes.blit_string; [Bytes.t] is already mutable).
- ocaml-sse/lib/sse.ml: [Parser.t.data_buf] (a Buffer.t, written via
Buffer.add_*; the slot never changes).
- ocaml-zephyr/lib/zephyr.ml: drop [mode : Read | Write] entirely —
set at open-time, read nowhere. The open_read / open_write
constructors already distinguish the two call shapes, so mode
tracking was redundant.
Previously the eight git-x subcommands sat flat at top level (split,
check, fix, verify, filter-paths, split-commit, drop-commit, reword),
with 'split' ambiguous between the subtree split and the per-directory
commit split.
Regrouped into two namespaces that mirror the object they act on:
git-x tree
split (was: git-x split)
add (new — inject a standalone history under a prefix)
drop (was: git-x filter-paths)
check (was: git-x check)
fix (was: git-x fix)
verify (was: git-x verify)
git-x commit
split (was: git-x split-commit)
drop (was: git-x drop-commit)
reword (was: git-x reword)
Each subcommand lives in cmd_<group>_<verb>.{ml,mli}; cmd_tree.ml and
cmd_commit.ml are the Cmd.group wrappers. git_x.ml registers just the
two groups.
'tree add' is a thin wrapper over Git.Subtree.add, which already
existed in the library but had no CLI exposure. It accepts a ref (e.g.
FETCH_HEAD after 'git fetch URL REF') and a --prefix, then builds a
subtree-merge commit with the current user's git config identity.
Log source names are updated to match (git-x.tree.split,
git-x.tree.fix). The cram test under test/cram/tree_split.t is
updated to use the new 'git-x tree split' invocation throughout.
Covers every package whose .opam was missing tags, misspelled a
singleton tag, or only carried a foreign org marker. The canonical
vocabulary now lives in .merlint as E915's topics: list; this pass
makes the monorepo pass E915 on the packages whose dune-project is
the source of truth.
Cleanups: drop singletons cop1/sle/sdls/uslp/s3/sdk; rename log to
logging (json-logs, vlog); add org:blacksun to formerly-Mirage-only
packages (ca-certs, tar, tls, x509, crypto-ec).
Additions to packages missing tags: cfdp-eio, cop1-eio, ltp-eio,
scc-eio, sdls-eio, sle-eio, yamlrw-eio, yamlrw-unix, ocaml-merlin,
scitt-atp, atp-lexicon-scitt, and 10 ocaml-atp subpackages.
Drops the redundant "t" suffix. Library name, opam package, module
(Csvt -> Csv), and directory all rename in lockstep. Every downstream
reference in interop tests, libraries, and docs updated.
Wire_3d now generates ExternalTypedefs.h, ExternalAPI.h, Wrapper, and
Fields files for schemas using WireCtx. Bitfield padding fixed so .3d
structs match OCaml codec wire_size. Test.c passes NULL for WIRECTX
and links per-schema Field stubs. File naming matches EverParse output.
Also: gitignore EverParse intermediates (.fst, .krml, .rsp, Makefile)
and remove the previously-tracked ones from ocaml-fsr.
Wire_3d now generates ExternalTypedefs.h, ExternalAPI.h, Wrapper,
and Fields files for schemas using WireCtx. Bitfield padding is
fixed so .3d structs match the OCaml codec wire_size. Test.c passes
NULL for the WIRECTX parameter and links per-schema Field stubs.
Affected: ax25, cfdp, fsr, ltp, mbr, pid1, pus, rpmsg, sdls,
spacefibre, squashfs, tcpcl, udpcl, spacewire, and others via @gen.
Same refactor pattern as xmlt (d786b041, 067b745c):
- Dropped the custom error ADT (Missing_header, Missing_column,
Bad_value, Truncated_row, Encode_error, Invalid_utf8), error_to_string,
pp_error.
- module Error = Textloc.Error (re-exports shared infrastructure).
- module Sort = Row | Field | Header with to_string, pp, kinded,
or_kind.
- Internal helpers raise Textloc.Error.msgf/msg; try/with at boundaries.
- decode/decode_string/decode_channel/decode_file/fold_channel/fold_file
now return (_, string) result.
- Added primed variants returning (_, Error.t) result.
- Path threading: push_array for row index, push_object for column
name -- errors carry structural context.
- Added ?max_rows / ?max_cols limits on decode.
- Kept Invalid_utf8_encode of int exception.
Tests tightened to STRUCTURAL assertions (exact frames list, exact
message) instead of substring checks.
Same tightening retrofitted to xmlt's context tests -- 12 tests
now assert exact Textloc.Error.t shape (full frame list including
outer-first ordering, exact message) rather than 'contains'.
Downstream fixes: ocaml-cdm collapses its typed error ADT to
[Parse_error of string]; 38 interop test files updated from
[Alcotest.failf "%a" Csvt.pp_error e] to ["%s" e].
csvt: 60 tests pass. xmlt: 177 tests pass.
Generate .opam.template files with x-quality-* fields based on
detected package features:
- x-quality-build: has lib/ with .ml files
- x-quality-test: has test/ with .ml files
- x-quality-fuzz: has fuzz/ with .ml files
- x-quality-interop: has test/interop/ directory
- x-quality-cram: has test/*.t/ directories
These fields are picked up by dune's opam generation and will be
checked by merlint E910 for consistency.
Also: add fmt dep to ocaml-sse/lib/dune (Fmt.pf used without dep).
monopam quality — scans packages for quality features, caches by
git commit hash. 166 packages: build=163, test=162, fuzz=94,
interop=39, doc=42.
Standard vocabulary based on crates.io categories, erratique/opam
conventions, and monorepo domain coverage:
Org: org:blacksun
Domain: aerospace, codec, crypto, network, storage, git, merkle
Purpose: cli, test, bench, format, log, system
Protocol: ccsds, uslp, cop1, sdls, sle, atproto, tls, http, json, binary
Cross-cutting: eio, simulation, math, compression
Tags placed in dune-project (package ...) stanzas via (tags ...).
Propagated to .opam files by dune's opam generation.
112 files across the monorepo. Printf.sprintf → Fmt.str,
Printf.printf → Fmt.pr for consistent formatting library usage.
Replace failwith (Fmt.str ...) with Fmt.failwith ... in spacedata,
squashfs, sdls, and sigstore.
Creates c/gen.ml + c/dune + generated .3d files for every package
that defines Wire codecs. Each gen.ml calls Wire_3d.main to project
the OCaml Wire codec definition to EverParse 3D format.
Packages: FSR, PUS, GPT, MBR, PID1, LTP, TCPCL (8 codecs), UDPCL,
AX.25, CFDP (3 fixed-size codecs), SDLS (EP header + MC status),
SpaceWire, RPMsg, SquashFS (5 codecs), SpaceFibre.
Codecs with Wire.Param.input (variable-size) are excluded from 3D
generation: CFDP header/eof/metadata/keep-alive, SDLS security
header/trailer, PUS tm_header/hk_param.
Proximity-1 and space-wire excluded: proximity-1 has only variable-
size codecs, space-wire has its own C generation approach.
Fixes E900 (17→2) and E905 (remaining MBR Partition.struct_).
End-to-end FSR test: Crypto_Init_TM_Unit_Test → build TM frame
(from CryptoLib's own ut_tm_apply.c test) → Crypto_TM_ApplySecurity
→ Crypto_Get_FSR(). The 32-bit FSR word is decoded by Fsr.decode
and verified: flags, SPI, ARSN, plus encode roundtrip.
The TM frame hex (1786 bytes) is stored in scripts/tm_frame.hex,
copied verbatim from CryptoLib's HAPPY_PATH_CLEAR_FECF test.
SDLS interop now has 21 tests: 8 protect, 12 security_header, 1 FSR.
FSR (Frame Security Report) interop requires:
1. Crypto_Init_TM_Unit_Test() for SA setup
2. A full 1786-byte TM frame matching CryptoLib's config
3. Crypto_TM_ApplySecurity() to produce secured frame
4. Crypto_Get_FSR() to read the 32-bit FSR word
The TM frame must be copied from CryptoLib's own ut_tm_apply.c
HAPPY_PATH_CLEAR_FECF test (3572-char hex literal). Tracked
separately from the TC interop which is already working.
Cross-validate SDLS frame protection against NASA CryptoLib — the
standard open-source CCSDS 355.0-B-2 implementation.
The generator (scripts/generate.c) calls CryptoLib's actual public
API: Crypto_Init_TC_Unit_Test() for SA setup, then
Crypto_TC_ApplySecurity() to produce secured frames. No SDLS
encoding is reimplemented — CryptoLib is the independent oracle.
12 reference vectors across three modes:
- Clear mode (SA 1, SPI=1, no encryption/auth)
- GCM encrypt-only (SA 2, SPI=2, header parsing only)
- GCM authenticated-encryption (SA 4, SPI=4, 16-byte MAC)
Two test suites:
- protect (8 tests): byte-for-byte match of Sdls.protect_frame
output against CryptoLib's secured frames
- security_header (12 tests): SPI and TC header consistency from
all CryptoLib-secured frames
12 vectors covering clear mode (SPI=1), GCM encryption (SPI=2), and GCM
authenticated encryption with 16-byte MAC (SPI=4). Generator calls
Crypto_TC_ApplySecurity from ~/git/cryptolib (NASA CryptoLib, C).
These tests used pure Python generators that reimplemented the spec
encoding — violating the interop testing principle that the oracle
must be an independent implementation, not a transcription.
A Python script that encodes the same spec our OCaml code does is
just a unit test with extra steps. It validates nothing about
cross-implementation compatibility.
Real interop tests require actual external tools:
- FSR/SDLS: NASA CryptoLib (Docker)
- Proximity-1: no known public oracle (skip until one exists)
Migrate all remaining binary protocol packages to use Wire codecs
for encode/decode, replacing manual Char.code / set_u8 / get_u16_be
/ put_u32_be byte-picking with Wire.Codec, Wire.map, Wire.Param,
and Wire.optional.
Packages migrated:
- cfdp: Wire codecs for 6 directive types (EOF, Finished, ACK,
Metadata, Prompt, Keep-Alive) with Param.input for large_file
flag and fss_size = 4 + 4*large_file. NAK uses be_bytes_to_int64
for the gap list (Wire.repeat blocked on byte budget from outer
PDU). 41 lines of byte helpers removed.
- sdls: Wire codecs for MC status reply, log/erase/self-test
replies, TLV event encoding. Security header/trailer use
Param.input for iv_len, sn_len, mac_len with byte_array ~size.
85 lines of byte helpers removed.
- ax25: FCS encode/decode via Wire.uint16 (LE). Extension tag
and cancel reason via Wire.map. 14 lines removed.
- proximity1: Staged Wire.Codec.get for frame-type bitfield
extraction, replacing manual bitmask. 4 lines removed.
- ltp: Wire.map for extension_tag and cancel_reason enum fields.
SDNV codec kept (variable-length encoding, not expressible as
Wire type). 3 lines removed.
- pus: Wire codecs for HK parameter, u16be field access. All
PUS secondary header encode/decode through Wire. 7 lines removed.
- mbr: Full 512-byte MBR Wire.Codec with embedded Wire.codec
for partition entries. 18 lines of byte helpers removed.
- pid1: Direct Bytes.of_string to Wire.Codec.decode, eliminating
intermediate buffer copy. 1 line removed.
- uslp: Wire.map helpers (be_uint) for variable-length integer
conversions; fecf_of_string/fecf_to_string cleaned up.
Total: ~170 lines of manual byte-picking eliminated across the
monorepo. Every binary protocol now uses Wire for format parsing.
The remaining Char.code usage is in: SDNV codec (LTP, inherently
variable-length), crypto operations (SDLS CMAC/hex), and value
conversions on Wire-decoded byte arrays.
All tests pass across all packages.
- CCSDS packages (aos, clcw, fsr, sdls, space-packet, tc, tm, uslp):
Wire.bool renamed to Wire.bit upstream; mechanical migration.
- ocaml-cfdp: adopt wire library for PDU header codec.
- ocaml-ltp: adopt wire library for segment header codec.
- ocaml-cop1: simplify interop test error formatting.
- dune fmt: reformat irmin, pus, scitt, crypto, tc/uslp 3D specs.
- monopam: add TODO.md tracking cram coverage gaps.
- Update .ocamlformat to 0.29.0 across all 591 files
- csvt: reuse single Buffer.t for field reads (no alloc per field)
- sexpt: Obj members decoded from stream into Dict, typed Variant GADT
- Reformat all source files for 0.29.0
- ocaml-rice: CCSDS 121.0-B lossless compression (Rice/Golomb)
- ocaml-udpcl: RFC 7122 UDP convergence layer for Bundle Protocol
- ocaml-erasure: CCSDS 131.5-B erasure correcting codes (GF(2^8))
- ocaml-short-ldpc: CCSDS 131.4-B short block-length LDPC
- ocaml-opm: CCSDS 502.0-B Orbit Parameter Message (KVN)
- ocaml-aem: CCSDS 504.0-B Attitude Ephemeris Message (KVN)
- ocaml-tdm: CCSDS 503.0-B Tracking Data Message (KVN)
- ocaml-rdm: CCSDS 508.1-B Re-entry Data Message (KVN)
141 new tests (192 total, was 51). Adapted from borealis test suite.
- test_crypto: 25 tests — AES-CCM/GCM roundtrips, NIST SP 800-38C/38D
known answer tests, nonce validation, AAD mismatch, tag truncation
- test_sa: 53 tests — SA constructors, IV management/wraparound,
anti-replay window (accept/reject/wraparound/disabled), SA lifecycle
(start/stop/rekey/expire), PDU wire format roundtrips, config validation
- test_keystore: 29 tests — CRUD, key lifecycle state machine, SDLS
integration (enc/auth/dec/verify access policies), serialization,
cipher-specific key length validation
- test_key: 21 tests — Key state machine, lifecycle transitions,
invalid transitions, Keyring operations
- test_security: 23 tests — Event encoding roundtrips, store operations,
alarm flags, event tags, pretty-printing
Also exports SA PDU command types in sa.mli that were previously hidden.
- Fix BCJR extrinsic LLR double-subtraction in turbo decoder;
all 7 turbo roundtrip tests now pass (39 total tm-sync tests)
- ocaml-sdls/fuzz: SA lifecycle, key state, EP PDU roundtrip (13 tests)
- ocaml-reed-solomon/fuzz: encode/decode with random errors (6 tests)
- ocaml-flexacm/fuzz: mode lookup, SNR monotonicity (6 tests)
- ocaml-sdls: Add Algorithm module for SA algorithm negotiation, re-export
- ocaml-sle: Add ROCF (Return Operational Control Field) service module
- ocaml-tm-sync: Add convolutional coding (rate 1/2 K=7), LDPC, turbo codes
with encode/decode and comprehensive unit tests
- ocaml-sgp4: Update GMAT interop station contacts test
- ocaml-hkdf: Regenerate opam with alcotest dep
- ocaml-flexacm: New package for flexible adaptive coding and modulation
ocaml-hkdf: Add 9 tests from RFC 5869 Appendix A (SHA-256 vectors A.1-A.3).
Each test case verifies extract (PRK), expand (OKM), and derive (combined).
This library previously had zero tests.
ocaml-sdls: Add NIST SP 800-38B test vectors for AES-CMAC (AES-128 and
AES-256, empty/16B/40B/64B messages) and RFC 4231 test vectors for HMAC
(SHA-256/384/512, test cases 1-4). Also adds verification and error tests.
New packages:
- ocaml-tm-sync (131.0-B): TM randomizer (LFSR) with CCSDS PN
sequence test vector; RS/convolutional/LDPC/turbo stubs
- ocaml-proximity1 (211.0-B): Proximity-1 frame header Wire codec
with encode/decode and roundtrip tests
Tests with spec vectors (96 tests total):
- tm-sync: PN sequence from CCSDS 131.0-B-4 Annex B
- cltu: BCH(63,56) parity, CLTU/ASM sync parsers
- cop1: FOP-1/FARM-1 state machine transitions
- fsr: 32-bit FSR Wire codec with known bit patterns
- proximity1: frame header roundtrip for all frame types
- ccsds-time: CUC/CDS encode/decode with epoch constants
- transport-eio: CLTU/ASM over Eio flows, COP-1 service layer
- sdls-eio: file-backed keystore, SA store, OTAR, security log,
KEK management, encrypted KV store, SDLS server
- cfdp: Eio filesystem-backed filestore for segmented transfers
- ltp-eio: length-prefixed segment send/recv over TCP
Ported from borealis eio/ wrappers with dependency updates
(crypto instead of mirage-crypto, bare int for Spi/Vcid/Scid).
New packages:
- ocaml-fsr: Frame Security Report (Wire codec for 32-bit FSR word)
- ocaml-hkdf: HMAC-based Key Derivation (RFC 5869)
- ocaml-ccsds-time: CCSDS time formats (CUC, CDS) with Wire codecs
- ocaml-transport: CLTU/ASM framing and COP-1 state machine
- ocaml-chunk: Zstd compression and application-layer chunking
- ocaml-sdls: Space Data Link Security (AES-GCM/CCM/CMAC frame
protection, SA management, key lifecycle, EP/MC protocols)
All binary protocol headers use Wire codecs. Dependencies on
borealis Binary module replaced with Bytesrw or Wire. Uses
ocaml-crypto instead of mirage-crypto.
Remove libraries declared in '(libraries ...)' clauses but unreferenced
by any module in the same source tree, as flagged by 'monopam lint'
after the new Dead_lib detection landed. Touches 131 dune files across
~80 packages.
A few stanzas needed a positive correction instead of a pure removal:
- ocaml-git/bin/diag: depended on eio_main + bytesrw-eio for an
Eio_posix.run call site; the umbrella was overkill, switch to the
precise eio_posix package.
- ocaml-scaleway/lib, ocaml-s3/lib: scaleway.mli / s3.mli reference
Eio_unix.Stdenv.base; eio.unix is required and was missing.
- merlint/lib: pulled bytesrw + nox-opam.bytesrw to surface
Opam_bytesrw, used by rule e915 and lint helpers.
Stanzas where Dead_lib was a false positive (transitive dep needed
for module visibility, virtual-library impls) are left untouched —
e.g. helix.jx.jsoo for ocaml-globe/demo retains its (libraries ...)
entry because it provides the impl of the helix.jx virtual lib.
Run mdx on eio/kek.mli so the {[ ... ]} odoc block now type-checks
the three KEK provisioning paths (auto, password-protected, explicit
file).
The example referenced a free `dir`, used unqualified `Kek.X`, and
discarded the return value with shadowing `let kek = ...` lines that
each ignore the previous binding. Restructured around a `report`
helper that prints the byte length on success and surfaces errors
via Fmt.epr + Sdls_eio.Kek.pp_error, then exercises all three calls
under one Eio_main.run so each branch's value is consumed.
Run mdx on eio/otar_eio.mli so the {[ ... ]} odoc block now
type-checks against the real Sdls.Otar / Sdls_eio.Otar_eio APIs.
The example referenced free `fs`, `kek`, `master_material`, `cmd`,
`send`, `log_error`, used unqualified `Otar_eio.of_path`, and
`let ... in` chains that do not parse at the toplevel. Wrapped in
`let run ~kek ~master_material ~cmd ~send = Eio_main.run @@ ...` so
the user supplies the credentials and command, the example shows
both the Ok reply and Error paths via Fmt.epr + Sdls.Otar.pp_error,
and the disk-touching of_path call doesn't execute at mdx test time.
Run mdx on eio/security_eio.mli so the {[ ... ]} odoc block now
type-checks against the real Sdls.Security and Sdls_eio.Security_eio
APIs.
The example used unqualified `Security_eio.of_path`, `Security.*`,
and the bare constructor `Bad_mac`; the real path resolution is
`Sdls.Security.Bad_mac` (the constructor lives on
`Sdls.Security.auth_failure_reason`, not `Sdls.Mc`). Added a wrapper
`let run () = ...` so the file-backed security store does not
materialise on disk at mdx test time, and replaced the trailing `...`
with a `Printf.printf` of the dump length so the example shows what
the store yields.
The example used 'fs', '...' and shorthand module references that don't
type-check. Wrap it in a 'run ()' function that takes env from
Eio_main.run, qualify Sdls_eio.Security_eio / Sdls.Security /
Sdls.Mc.Bad_mac fully, and replace the trailing '...' with a real
Printf.printf so the build catches drift.
Renames 35 packages to make blacksun forks distinguishable from their
opam-repository upstreams. Module names (Git.x, Tls.x, ...) stay bare;
opam package names and dune (public_name) findlib references move to
nox-X. After this commit, zero local package names overlap with
opam-repository.
Renamed:
- nox-git, nox-irmin
- nox-crypto, nox-crypto-pk, nox-crypto-rng, nox-crypto-ec
- nox-tls, nox-tls-eio, nox-tar, nox-tar-eio, nox-tty, nox-tty-eio
- nox-arp, nox-ca-certs, nox-cbor, nox-cookie, nox-crc, nox-csv
- nox-gpt, nox-hkdf, nox-http, nox-jwt, nox-kdf, nox-loc
- nox-memtrace, nox-pds, nox-sexp, nox-slack, nox-toml
- nox-websocket, nox-x509, nox-xdge, nox-yaml
Also drops orphan tar-mirage and tar-unix opam templates that had no
matching package stanza.
Follow up to the module rename: update the remaining callers that
still referenced [Err] (library [claude.ml{,i}], [client.ml], the test
driver [test.ml]), and fix one stray [^ e] string concatenation in
hermest's CLI that needed [Json.Error.to_string e] now that
[Json.of_string] yields a structured error.
Warning 69 (unused-field, mutable-never-assigned). Four independent
record fields were flagged as mutable but the code only mutates their
referents in place, never rebinds the record slot itself:
- ocaml-wal/lib/wal.ml: [t.file] (the Eio file resource; methods call
Eio.File.pwrite_all etc., the slot is set once at open time).
- ocaml-block/lib/block.ml: [Memory.state.data] (the backing bytes,
written via Bytes.blit_string; [Bytes.t] is already mutable).
- ocaml-sse/lib/sse.ml: [Parser.t.data_buf] (a Buffer.t, written via
Buffer.add_*; the slot never changes).
- ocaml-zephyr/lib/zephyr.ml: drop [mode : Read | Write] entirely —
set at open-time, read nowhere. The open_read / open_write
constructors already distinguish the two call shapes, so mode
tracking was redundant.
Previously the eight git-x subcommands sat flat at top level (split,
check, fix, verify, filter-paths, split-commit, drop-commit, reword),
with 'split' ambiguous between the subtree split and the per-directory
commit split.
Regrouped into two namespaces that mirror the object they act on:
git-x tree
split (was: git-x split)
add (new — inject a standalone history under a prefix)
drop (was: git-x filter-paths)
check (was: git-x check)
fix (was: git-x fix)
verify (was: git-x verify)
git-x commit
split (was: git-x split-commit)
drop (was: git-x drop-commit)
reword (was: git-x reword)
Each subcommand lives in cmd_<group>_<verb>.{ml,mli}; cmd_tree.ml and
cmd_commit.ml are the Cmd.group wrappers. git_x.ml registers just the
two groups.
'tree add' is a thin wrapper over Git.Subtree.add, which already
existed in the library but had no CLI exposure. It accepts a ref (e.g.
FETCH_HEAD after 'git fetch URL REF') and a --prefix, then builds a
subtree-merge commit with the current user's git config identity.
Log source names are updated to match (git-x.tree.split,
git-x.tree.fix). The cram test under test/cram/tree_split.t is
updated to use the new 'git-x tree split' invocation throughout.
Covers every package whose .opam was missing tags, misspelled a
singleton tag, or only carried a foreign org marker. The canonical
vocabulary now lives in .merlint as E915's topics: list; this pass
makes the monorepo pass E915 on the packages whose dune-project is
the source of truth.
Cleanups: drop singletons cop1/sle/sdls/uslp/s3/sdk; rename log to
logging (json-logs, vlog); add org:blacksun to formerly-Mirage-only
packages (ca-certs, tar, tls, x509, crypto-ec).
Additions to packages missing tags: cfdp-eio, cop1-eio, ltp-eio,
scc-eio, sdls-eio, sle-eio, yamlrw-eio, yamlrw-unix, ocaml-merlin,
scitt-atp, atp-lexicon-scitt, and 10 ocaml-atp subpackages.
Wire_3d now generates ExternalTypedefs.h, ExternalAPI.h, Wrapper, and
Fields files for schemas using WireCtx. Bitfield padding fixed so .3d
structs match OCaml codec wire_size. Test.c passes NULL for WIRECTX
and links per-schema Field stubs. File naming matches EverParse output.
Also: gitignore EverParse intermediates (.fst, .krml, .rsp, Makefile)
and remove the previously-tracked ones from ocaml-fsr.
Wire_3d now generates ExternalTypedefs.h, ExternalAPI.h, Wrapper,
and Fields files for schemas using WireCtx. Bitfield padding is
fixed so .3d structs match the OCaml codec wire_size. Test.c passes
NULL for the WIRECTX parameter and links per-schema Field stubs.
Affected: ax25, cfdp, fsr, ltp, mbr, pid1, pus, rpmsg, sdls,
spacefibre, squashfs, tcpcl, udpcl, spacewire, and others via @gen.
Same refactor pattern as xmlt (d786b041, 067b745c):
- Dropped the custom error ADT (Missing_header, Missing_column,
Bad_value, Truncated_row, Encode_error, Invalid_utf8), error_to_string,
pp_error.
- module Error = Textloc.Error (re-exports shared infrastructure).
- module Sort = Row | Field | Header with to_string, pp, kinded,
or_kind.
- Internal helpers raise Textloc.Error.msgf/msg; try/with at boundaries.
- decode/decode_string/decode_channel/decode_file/fold_channel/fold_file
now return (_, string) result.
- Added primed variants returning (_, Error.t) result.
- Path threading: push_array for row index, push_object for column
name -- errors carry structural context.
- Added ?max_rows / ?max_cols limits on decode.
- Kept Invalid_utf8_encode of int exception.
Tests tightened to STRUCTURAL assertions (exact frames list, exact
message) instead of substring checks.
Same tightening retrofitted to xmlt's context tests -- 12 tests
now assert exact Textloc.Error.t shape (full frame list including
outer-first ordering, exact message) rather than 'contains'.
Downstream fixes: ocaml-cdm collapses its typed error ADT to
[Parse_error of string]; 38 interop test files updated from
[Alcotest.failf "%a" Csvt.pp_error e] to ["%s" e].
csvt: 60 tests pass. xmlt: 177 tests pass.
Generate .opam.template files with x-quality-* fields based on
detected package features:
- x-quality-build: has lib/ with .ml files
- x-quality-test: has test/ with .ml files
- x-quality-fuzz: has fuzz/ with .ml files
- x-quality-interop: has test/interop/ directory
- x-quality-cram: has test/*.t/ directories
These fields are picked up by dune's opam generation and will be
checked by merlint E910 for consistency.
Also: add fmt dep to ocaml-sse/lib/dune (Fmt.pf used without dep).
Standard vocabulary based on crates.io categories, erratique/opam
conventions, and monorepo domain coverage:
Org: org:blacksun
Domain: aerospace, codec, crypto, network, storage, git, merkle
Purpose: cli, test, bench, format, log, system
Protocol: ccsds, uslp, cop1, sdls, sle, atproto, tls, http, json, binary
Cross-cutting: eio, simulation, math, compression
Tags placed in dune-project (package ...) stanzas via (tags ...).
Propagated to .opam files by dune's opam generation.
Creates c/gen.ml + c/dune + generated .3d files for every package
that defines Wire codecs. Each gen.ml calls Wire_3d.main to project
the OCaml Wire codec definition to EverParse 3D format.
Packages: FSR, PUS, GPT, MBR, PID1, LTP, TCPCL (8 codecs), UDPCL,
AX.25, CFDP (3 fixed-size codecs), SDLS (EP header + MC status),
SpaceWire, RPMsg, SquashFS (5 codecs), SpaceFibre.
Codecs with Wire.Param.input (variable-size) are excluded from 3D
generation: CFDP header/eof/metadata/keep-alive, SDLS security
header/trailer, PUS tm_header/hk_param.
Proximity-1 and space-wire excluded: proximity-1 has only variable-
size codecs, space-wire has its own C generation approach.
Fixes E900 (17→2) and E905 (remaining MBR Partition.struct_).
End-to-end FSR test: Crypto_Init_TM_Unit_Test → build TM frame
(from CryptoLib's own ut_tm_apply.c test) → Crypto_TM_ApplySecurity
→ Crypto_Get_FSR(). The 32-bit FSR word is decoded by Fsr.decode
and verified: flags, SPI, ARSN, plus encode roundtrip.
The TM frame hex (1786 bytes) is stored in scripts/tm_frame.hex,
copied verbatim from CryptoLib's HAPPY_PATH_CLEAR_FECF test.
SDLS interop now has 21 tests: 8 protect, 12 security_header, 1 FSR.
FSR (Frame Security Report) interop requires:
1. Crypto_Init_TM_Unit_Test() for SA setup
2. A full 1786-byte TM frame matching CryptoLib's config
3. Crypto_TM_ApplySecurity() to produce secured frame
4. Crypto_Get_FSR() to read the 32-bit FSR word
The TM frame must be copied from CryptoLib's own ut_tm_apply.c
HAPPY_PATH_CLEAR_FECF test (3572-char hex literal). Tracked
separately from the TC interop which is already working.
Cross-validate SDLS frame protection against NASA CryptoLib — the
standard open-source CCSDS 355.0-B-2 implementation.
The generator (scripts/generate.c) calls CryptoLib's actual public
API: Crypto_Init_TC_Unit_Test() for SA setup, then
Crypto_TC_ApplySecurity() to produce secured frames. No SDLS
encoding is reimplemented — CryptoLib is the independent oracle.
12 reference vectors across three modes:
- Clear mode (SA 1, SPI=1, no encryption/auth)
- GCM encrypt-only (SA 2, SPI=2, header parsing only)
- GCM authenticated-encryption (SA 4, SPI=4, 16-byte MAC)
Two test suites:
- protect (8 tests): byte-for-byte match of Sdls.protect_frame
output against CryptoLib's secured frames
- security_header (12 tests): SPI and TC header consistency from
all CryptoLib-secured frames
These tests used pure Python generators that reimplemented the spec
encoding — violating the interop testing principle that the oracle
must be an independent implementation, not a transcription.
A Python script that encodes the same spec our OCaml code does is
just a unit test with extra steps. It validates nothing about
cross-implementation compatibility.
Real interop tests require actual external tools:
- FSR/SDLS: NASA CryptoLib (Docker)
- Proximity-1: no known public oracle (skip until one exists)
Migrate all remaining binary protocol packages to use Wire codecs
for encode/decode, replacing manual Char.code / set_u8 / get_u16_be
/ put_u32_be byte-picking with Wire.Codec, Wire.map, Wire.Param,
and Wire.optional.
Packages migrated:
- cfdp: Wire codecs for 6 directive types (EOF, Finished, ACK,
Metadata, Prompt, Keep-Alive) with Param.input for large_file
flag and fss_size = 4 + 4*large_file. NAK uses be_bytes_to_int64
for the gap list (Wire.repeat blocked on byte budget from outer
PDU). 41 lines of byte helpers removed.
- sdls: Wire codecs for MC status reply, log/erase/self-test
replies, TLV event encoding. Security header/trailer use
Param.input for iv_len, sn_len, mac_len with byte_array ~size.
85 lines of byte helpers removed.
- ax25: FCS encode/decode via Wire.uint16 (LE). Extension tag
and cancel reason via Wire.map. 14 lines removed.
- proximity1: Staged Wire.Codec.get for frame-type bitfield
extraction, replacing manual bitmask. 4 lines removed.
- ltp: Wire.map for extension_tag and cancel_reason enum fields.
SDNV codec kept (variable-length encoding, not expressible as
Wire type). 3 lines removed.
- pus: Wire codecs for HK parameter, u16be field access. All
PUS secondary header encode/decode through Wire. 7 lines removed.
- mbr: Full 512-byte MBR Wire.Codec with embedded Wire.codec
for partition entries. 18 lines of byte helpers removed.
- pid1: Direct Bytes.of_string to Wire.Codec.decode, eliminating
intermediate buffer copy. 1 line removed.
- uslp: Wire.map helpers (be_uint) for variable-length integer
conversions; fecf_of_string/fecf_to_string cleaned up.
Total: ~170 lines of manual byte-picking eliminated across the
monorepo. Every binary protocol now uses Wire for format parsing.
The remaining Char.code usage is in: SDNV codec (LTP, inherently
variable-length), crypto operations (SDLS CMAC/hex), and value
conversions on Wire-decoded byte arrays.
All tests pass across all packages.
- CCSDS packages (aos, clcw, fsr, sdls, space-packet, tc, tm, uslp):
Wire.bool renamed to Wire.bit upstream; mechanical migration.
- ocaml-cfdp: adopt wire library for PDU header codec.
- ocaml-ltp: adopt wire library for segment header codec.
- ocaml-cop1: simplify interop test error formatting.
- dune fmt: reformat irmin, pus, scitt, crypto, tc/uslp 3D specs.
- monopam: add TODO.md tracking cram coverage gaps.
- ocaml-rice: CCSDS 121.0-B lossless compression (Rice/Golomb)
- ocaml-udpcl: RFC 7122 UDP convergence layer for Bundle Protocol
- ocaml-erasure: CCSDS 131.5-B erasure correcting codes (GF(2^8))
- ocaml-short-ldpc: CCSDS 131.4-B short block-length LDPC
- ocaml-opm: CCSDS 502.0-B Orbit Parameter Message (KVN)
- ocaml-aem: CCSDS 504.0-B Attitude Ephemeris Message (KVN)
- ocaml-tdm: CCSDS 503.0-B Tracking Data Message (KVN)
- ocaml-rdm: CCSDS 508.1-B Re-entry Data Message (KVN)
141 new tests (192 total, was 51). Adapted from borealis test suite.
- test_crypto: 25 tests — AES-CCM/GCM roundtrips, NIST SP 800-38C/38D
known answer tests, nonce validation, AAD mismatch, tag truncation
- test_sa: 53 tests — SA constructors, IV management/wraparound,
anti-replay window (accept/reject/wraparound/disabled), SA lifecycle
(start/stop/rekey/expire), PDU wire format roundtrips, config validation
- test_keystore: 29 tests — CRUD, key lifecycle state machine, SDLS
integration (enc/auth/dec/verify access policies), serialization,
cipher-specific key length validation
- test_key: 21 tests — Key state machine, lifecycle transitions,
invalid transitions, Keyring operations
- test_security: 23 tests — Event encoding roundtrips, store operations,
alarm flags, event tags, pretty-printing
Also exports SA PDU command types in sa.mli that were previously hidden.
- Fix BCJR extrinsic LLR double-subtraction in turbo decoder;
all 7 turbo roundtrip tests now pass (39 total tm-sync tests)
- ocaml-sdls/fuzz: SA lifecycle, key state, EP PDU roundtrip (13 tests)
- ocaml-reed-solomon/fuzz: encode/decode with random errors (6 tests)
- ocaml-flexacm/fuzz: mode lookup, SNR monotonicity (6 tests)
- ocaml-sdls: Add Algorithm module for SA algorithm negotiation, re-export
- ocaml-sle: Add ROCF (Return Operational Control Field) service module
- ocaml-tm-sync: Add convolutional coding (rate 1/2 K=7), LDPC, turbo codes
with encode/decode and comprehensive unit tests
- ocaml-sgp4: Update GMAT interop station contacts test
- ocaml-hkdf: Regenerate opam with alcotest dep
- ocaml-flexacm: New package for flexible adaptive coding and modulation
ocaml-hkdf: Add 9 tests from RFC 5869 Appendix A (SHA-256 vectors A.1-A.3).
Each test case verifies extract (PRK), expand (OKM), and derive (combined).
This library previously had zero tests.
ocaml-sdls: Add NIST SP 800-38B test vectors for AES-CMAC (AES-128 and
AES-256, empty/16B/40B/64B messages) and RFC 4231 test vectors for HMAC
(SHA-256/384/512, test cases 1-4). Also adds verification and error tests.
New packages:
- ocaml-tm-sync (131.0-B): TM randomizer (LFSR) with CCSDS PN
sequence test vector; RS/convolutional/LDPC/turbo stubs
- ocaml-proximity1 (211.0-B): Proximity-1 frame header Wire codec
with encode/decode and roundtrip tests
Tests with spec vectors (96 tests total):
- tm-sync: PN sequence from CCSDS 131.0-B-4 Annex B
- cltu: BCH(63,56) parity, CLTU/ASM sync parsers
- cop1: FOP-1/FARM-1 state machine transitions
- fsr: 32-bit FSR Wire codec with known bit patterns
- proximity1: frame header roundtrip for all frame types
- ccsds-time: CUC/CDS encode/decode with epoch constants
- transport-eio: CLTU/ASM over Eio flows, COP-1 service layer
- sdls-eio: file-backed keystore, SA store, OTAR, security log,
KEK management, encrypted KV store, SDLS server
- cfdp: Eio filesystem-backed filestore for segmented transfers
- ltp-eio: length-prefixed segment send/recv over TCP
Ported from borealis eio/ wrappers with dependency updates
(crypto instead of mirage-crypto, bare int for Spi/Vcid/Scid).
New packages:
- ocaml-fsr: Frame Security Report (Wire codec for 32-bit FSR word)
- ocaml-hkdf: HMAC-based Key Derivation (RFC 5869)
- ocaml-ccsds-time: CCSDS time formats (CUC, CDS) with Wire codecs
- ocaml-transport: CLTU/ASM framing and COP-1 state machine
- ocaml-chunk: Zstd compression and application-layer chunking
- ocaml-sdls: Space Data Link Security (AES-GCM/CCM/CMAC frame
protection, SA management, key lifecycle, EP/MC protocols)
All binary protocol headers use Wire codecs. Dependencies on
borealis Binary module replaced with Bytesrw or Wire. Uses
ocaml-crypto instead of mirage-crypto.