The canonical envelope names its algorithm: schema_version 3, SHA-384/512 by option, SHA-256 the default - #42
Merged
Merged
Conversation
…ourth fixed member after the version, sha256 by default, sha384/sha512 by option, anything else refused at the option by name), schema_version 3 on the graph and on the diff record, the wire's hex keyed by the algorithm's name, and bytes at 2 verified the way the migration note will say (the version first, then SHA-256); the vocabulary census is the first red -- a @type over the three digests with no definition rows yet; the v2 goldens kept beside the new ones: 14 failures Signed-off-by: Ayla Croft <aylacroft@proton.me>
…ed member after the version -- sha256 by default and indefinitely, sha384/sha512 by option on encode/hash/hash_hex/hash_value, the diff's encode/hash/hash_hex and the wire surface's host options, anything else refused at the option by name before a byte is written; schema_version 3 on the graph and the diff record, 2 refused as 1 was; the digest computed at one site with the algorithm a variable, the key-holding census moved from two sites to one; the wire's hex keyed by the algorithm's name; the canonical page's rules 1 and 9, its worked example under all three digests with the sha384 bytes shown, and a Versions section that says what a verifier holding 1 or 2 does (SHA-256, unchanged bytes, forever); the diff page; the Algorithm family in the vocabulary; docs/crypto-posture.md and docs/fips.md; and a defect the FIPS page found on the way -- the .app did not require crypto, so a stdio-only release had no :crypto.hash/2 -- fixed and pinned by reading the built .app: 647 tests Signed-off-by: Ayla Croft <aylacroft@proton.me>
…e default over bytes naming sha384 survived while the bang had a body of its own and every pin went through it; the non-raising forms pinned; Mha2 re-cut at a caller of the digest site, since the census reads that line as text and a text kill proves nothing Signed-off-by: Ayla Croft <aylacroft@proton.me>
…, the default flipped, a fourth name admitted, bytes and hash encoded under different algorithms, the graph's version left at 2, the diff record without the member, the wire keyed sha256 whatever the choice, the diff hashing with the default -- nine, zero survivors; one survived a first cut (the diff's non-raising hash/2, which no pin reached while hash!/2 had its own body) and one was re-cut past a text kill Signed-off-by: Ayla Croft <aylacroft@proton.me>
…gorithms/0 -- every other spelling of the three names refused (a plant admitting the string sha384 survived a list that refused sha256 alone), given twice refused by that name, a non-keyword refused by name, a value naming a digest the option disagrees with refused; to_json/2 takes the option; the surface's diff path pinned under sha384 (a plant encoding the record under the default while keying the hex sha384 survived every test); the test's page-derived verifier reads the fixed-order prefix and refuses what the page calls malformed: 2 failures Signed-off-by: Ayla Croft <aylacroft@proton.me>
…the three atoms (every other spelling refused by name; given twice refused as such; a non-keyword refused by name, as Graph.new/1 does); hash_value/2 refuses a value naming a digest the option disagrees with -- the one public path where bytes could name a digest they were not hashed with; to_json/2 takes the option and the surface's byte-for-byte claim is stated under the same algorithm; the surface reads the algorithm once and threads it, so the key and the member cannot come from two reads; the page says the nodes and edges members do not depend on the algorithm, which is what lets the sha384/sha512 goldens be derived; rule 9 names all five functions; the graph's version comment says why 3; the test's page-derived verifier reads the fixed-order prefix and refuses what the page calls malformed Signed-off-by: Ayla Croft <aylacroft@proton.me>
…ring sha384 admitted; the surface's diff path under the default while the hex is keyed by the option) plus the value-names-another-digest guard removed; Mha8 re-anchored to the surface's one read; Mha11 re-cut past a compiler kill -- twelve, zero survivors Signed-off-by: Ayla Croft <aylacroft@proton.me>
… recipe named schema_version 2, which Graph.new/1 now refuses -- it names the version by the function and a pin holds it there; docs/fips.md restated in OTP 28's own words -- enable_fips_mode/1 is deprecated ('use config parameter fips_mode'), the parameter is read when the crypto NIF loads so it must be in the environment before the module is, crypto:start/0 does not work for FIPS mode, and :not_supported names the build rather than the provider; the how-to-tell names the member's position in all three artefacts (graph second, diff first, sidecar none) and the sidecar's version move, which it had called 'as before'; '0.6.0' replaced by 'the release after 0.5.0' where a number was not the agent's to write; the livebook's one SHA-256 sentence
Signed-off-by: Ayla Croft <aylacroft@proton.me>
…he mutated file) Signed-off-by: Ayla Croft <aylacroft@proton.me>
…s carry schema_version 2 or later, 3 today; docs/fips.md carries OTP's sentence the page had omitted -- a FIPS mode requested but not available fails to load the crypto module, so a release requiring crypto does not boot, the failure a FIPS host wants and one that comes before any check -- and marks its one inference from on_load as its own; the no-environment claim cites the reach census's pin on Application Signed-off-by: Ayla Croft <aylacroft@proton.me>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The canonical envelope names the digest it is hashed with, in its bytes — so a verifier reads the algorithm from what it holds, not from a page — and SHA-384 and SHA-512 become a host's option beside the SHA-256 default.
What the page claimed before.
docs/connectome-canonical.md's rule 9 said "the hash is SHA-256 over exactly these bytes" — the algorithm was prose beside the bytes, the bytes named aschema_versionand nothing about a digest, and the code spelled:sha256at two sites. Moving to SHA-384 would have been a format break announced in a release note.Now. A fourth fixed top-level member,
"algorithm", right after"schema_version":"sha256","sha384"or"sha512", and the hash is that digest over exactly those bytes — the member is under the hash like every other, so two envelopes of one graph naming different digests are different bytes with different hashes and neither is a rewrite of the other. The diff record gains the same member (its keys sort, so it comes first).schema_versionis3on the graph and on the diff record;Graph.new/1refuses2as it refused1— bytes are produced and hashed here, never re-imported.algorithm:onCanonical.encode/2,hash/2,hash_hex/2,hash_value/2, onDiff.encode/2,hash/2,hash_hex/2, and in the wire surface's host options; SHA-256 when absent, indefinitely; a fourth name refused byArgumentErrorbefore a byte is written. The digest is computed at one site underlib/, the algorithm a variable bound from the option — the key-holding census moves from "two sites, both:sha256" to "one site, no literal". The wire'stools/callresult keys the hex by the algorithm's name:sha256as before under the default.A verifier holding 0.4.0 or 0.5.0 bytes (
schema_version1 or 2) hashes them unchanged with SHA-256 and compares — those bytes name no algorithm and at those versions the digest is SHA-256 by the page's rule; published hashes stay verifiable forever. The page's Versions section says it in full — read the version; below 3, SHA-256; at 3, the named digest; anything else, refuse — and 0.5.0's goldens are kept in the tree and verified that way by a test. The worked example is given under all three digests, with the SHA-384 bytes shown, so a blind reader reproduces a SHA-384 hash from the page alone.Two pages:
docs/crypto-posture.md(one primitive at one site; three digests named in the bytes; no key, no signature, the seam for a signing package; why the algorithm is under the hash) anddocs/fips.md(what a FIPS-mode host needs, in OTP 28's own words — acryptobuilt with--enable-fipsagainst a validated OpenSSL FIPS provider; thefips_modeconfiguration parameter in the environment before thecryptomodule is first loaded, since OTP reads it when the NIF loads;enable_fips_mode/1deprecated in OTP 28; and OTP's own sentence that a FIPS mode requested but not available fails to load thecryptomodule, so a release requiringcryptodoes not boot — and that this package enables none of it and cannot, by the same census; measured on the development runtime, where:crypto.info_fips/0answers:not_supported, which OTP says names the build). A review lane reproduced every hash on both pages with coreutils alone, and the 0.5.0 goldens as the Versions section says.Found on the way, by writing the FIPS page's sentence about it: the
.appdid not requirecrypto. An HTTP host had it only throughplugandbandit, both optional; a stdio-only release built from the.appwould have had no:crypto.hash/2at all. Fixed (extra_applications), pinned by a test that reads the built.app.Red first — the vocabulary census went red on the
@typealone, before any test of the bytes. Twelve mutants over the envelope, zero survivors; three survived a first cut, each a pin that passed for the wrong reason: the diff's non-raisinghash/2hashed with the default over bytes naming SHA-384 while every pin went throughhash!/2(one body now, both forms pinned); the refusal pin proved the string"sha256"was refused, not that strings were (the domain is now generated fromalgorithms/0— every other spelling of the three names refused); and the wire surface's diff path had no pin under a non-default algorithm, so a hash under the keysha384beside bytes namingsha256— the thing the member exists to prevent — passed 647 tests (pinned; the surface now reads the option once and threads it, so the key and the member cannot come from two reads). A review lane wrote a verifier from the page alone, in Python, and reproduced every hash on the page and every golden. Gate on the head: thirteenpass.11 properties, 649 tests, 0 failures— 626 onmainplus twenty-three. Latency stays out of the signed envelope, by decision: a measurement of one machine on one day, not a property of the graph; the unsigned sidecar carries it as before.How to tell whether you are affected: a consumer that verifies by hashing the bytes it holds is not. A consumer that parses by position or by a fixed member list meets the member in three artefacts, each differently: the graph envelope at the second position, the diff record at the first (its keys sort), the sidecar not at all — but the sidecar's
schema_versionmoves to3with the graph's. A host that passes nothing getssha256everywhere it did.