Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,21 @@ both profiles and refusing on the national security profile by mode or by build
pass on that profile shown by the decision's own tests, since no CI runtime carries the validated
provider.

### `slice/142`: signed statements follow the profile's v0.1 draft

The checks Trinity runs on its signed-statement format now follow the profile publisher's v0.1
draft in what they check and in which order, so Trinity names the same first defect as every other
implementation. Text in signed statements is judged by one pinned Unicode version (15.0.0), never
the runtime's, and refuses unassigned code points, invisible and bidirectional format controls, and
text that is not plainly in normal form. Bodies, headers and keys are checked in the draft's order,
with its names for each defect.

Verified by the test suite: agreement with every vector the publisher has cut, 593 across five
kinds, by a test that reads the publisher's set from a path and checks its digests first, and that
was shown to fail on a planted disagreement; the Unicode tables' counts against the draft's and
their regeneration byte for byte from the published data files; and a census that no normaliser is
called.

## 2026-10-08

### `slice/136`: the web pages ask who is there
Expand Down
39 changes: 39 additions & 0 deletions LICENSES/Unicode-3.0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
UNICODE LICENSE V3

COPYRIGHT AND PERMISSION NOTICE

Copyright © 1991-2026 Unicode, Inc.

NOTICE TO USER: Carefully read the following legal agreement. BY
DOWNLOADING, INSTALLING, COPYING OR OTHERWISE USING DATA FILES, AND/OR
SOFTWARE, YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO BE BOUND BY, ALL OF THE
TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT AGREE, DO NOT
DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR SOFTWARE.

Permission is hereby granted, free of charge, to any person obtaining a
copy of data files and any associated documentation (the "Data Files") or
software and any associated documentation (the "Software") to deal in the
Data Files or Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, and/or sell
copies of the Data Files or Software, and to permit persons to whom the
Data Files or Software are furnished to do so, provided that either (a)
this copyright and permission notice appear with all copies of the Data
Files or Software, or (b) this copyright and permission notice appear in
associated Documentation.

THE DATA FILES AND SOFTWARE ARE 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 OF
THIRD PARTY RIGHTS.

IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE
BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES,
OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE DATA
FILES OR SOFTWARE.

Except as contained in this notice, the name of a copyright holder shall
not be used in advertising or otherwise to promote the sale, use or other
dealings in these Data Files or Software without prior written
authorization of the copyright holder.
2 changes: 1 addition & 1 deletion bin/verify_receipt.exs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ defmodule VerifyReceipt do
@signed_kinds ~w(decision effect boot cap)

# The sources a v4 row needs, relative to Trinity's lib directory, in the order they are loaded.
@n6_sources ~w(n6/profile.ex n6/cbor.ex n6/digest.ex n6/body.ex n6/ec2.ex n6/cose.ex n6/carrier.ex receipts/v4.ex)
@n6_sources ~w(n6/profile.ex n6/unicode15.ex n6/cbor.ex n6/digest.ex n6/body.ex n6/ec2.ex n6/ed25519.ex n6/cose.ex n6/carrier.ex receipts/v4.ex)

# Named at run time, so compiling this file before the sources are loaded warns about nothing.
defp v4, do: Module.concat(["Trinity", "Receipts", "V4"])
Expand Down
36 changes: 36 additions & 0 deletions docs/07-security-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,42 @@ sign through the layer. New rows and checkpoints are written under `receipt_v4_<
`Trinity.Receipts.V4` from Trinity's `lib/` (`--n6` names it) and runs the same rules as the
in-app verifier, which a test holds it to; a chain with no v4 row still needs nothing but OTP.

### The profile's v0.1 draft, and the publisher's vectors (Slice 142, as built)

The profile's publisher posted draft v0.1-r7 on 2026-10-21. It fixes the order every check runs in
(steps D0 to D18 for the codec, B1 to B8 for a body, H1 to H4 for a protected header, K1 to K3 for
a key) and closes the list of codes a verifier may answer. Trinity's N6 layer now follows it, and
agrees with every vector the publisher has cut: 347 encoding, 124 body, 85 header, 18 thumbprint
and 19 digest vectors, measured against the publisher's set by a test anyone can point at it
(`TRINITY_N6_PUBLISHER_VECTORS`, `test/trinity/n6/publisher_vectors_test.exs`).

- **Text is judged by one pinned Unicode version, never the runtime's.** A text string is refused
if it holds a code point unassigned in Unicode 15.0.0, a format control (the bidirectional
controls, zero-width characters, the soft hyphen, the byte-order mark, the tag characters), a
combining mark out of canonical order, or a code point whose NFC quick check is No or Maybe.
Format controls are refused because they make what a reviewer sees differ from what was signed.
The four tables are generated from the Unicode 15.0.0 data files, each checked by SHA-256
(`scripts/unicode15_tables.exs`, `Trinity.N6.Unicode15`), and no Unicode normaliser runs anywhere
in the layer: runtimes ship different Unicode versions, and the one OTP 28 carries already calls
some 15.0.0-unassigned code points letters.
- **Every head is checked in the profile's order.** A map key whose head is malformed keeps that
defect's code before its type is looked at; an argument's missing bytes are found before a tag or
float is refused; a container's declared contents are counted against the item limit at its head,
before anything is read.
- **A body is one scan.** Required keys, undeclared keys and each value's type, range, grammar and
set order are checked in one pass over the keys in ascending order, so the first defect is the
same one in every implementation. Field types now carry ranges, enumerations, byte bounds and text
grammars.
- **A header is judged by its `typ` first,** because the `typ` selects which labels may appear; a
missing label is `header_missing`, a value of the wrong shape `header_value_invalid`. A strictly
decoded Ed25519 key (RFC 8032 section 5.1.3) is required where one is registered; OpenSSL accepts
some encodings that rule refuses.

Not covered here: what a verifier answers about a defect it finds after a signature has verified,
and the publisher's further Ed25519 rule on small-order points, which are the next increment. One
code Trinity answers, `alg_unavailable` (the runtime cannot run the header's algorithm), is not in
the draft's list; it is kept and has been put to the publisher.

## The effect population, published (Slice 027, as built)

The set of things that can cause an effect is small, derived from the tree, and published as
Expand Down
6 changes: 4 additions & 2 deletions lib/trinity/n6.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ defmodule Trinity.N6 do

* `Trinity.N6.CBOR`: the encoder and the strict decoder (rules E1 to E11);
* `Trinity.N6.Body`: a statement body against its declared schema;
* `Trinity.N6.Unicode15`: the Unicode 15.0.0 tables the text rule reads (generated);
* `Trinity.N6.Ed25519`: the strict decoding of an Ed25519 point;
* `Trinity.N6.Digest`: SHA-384 references to foreign bytes;
* `Trinity.N6.COSE`: the header rules, the key thumbprint, signing and verifying;
* `Trinity.N6.EC2`: ESP384's P-384 keys, thumbprint and `r || s` signatures (slice 140);
Expand All @@ -18,8 +20,8 @@ defmodule Trinity.N6 do

This is a top-level boundary with no dependency on the rest of Trinity, as `Trinity.Keys` is,
so it stays extractable: the compiler refuses a call from here into any other Trinity module.
The profile is provisional (v0, draft r3, and the publisher's answers of 2026-10-19 and
2026-10-20); see `Trinity.N6.Profile`. Nothing Trinity signed
The profile is provisional (v0.1, draft v0.1-r7, since slice 142); see `Trinity.N6.Profile`.
Nothing Trinity signed
before this boundary existed is changed by it.
"""

Expand Down
Loading
Loading