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
41 changes: 28 additions & 13 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,37 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

- **The structural floor is gated in CI** (macula-io/macula-codebase-checks#9): `phpcs`
refuses a function that nests past three blocks (`phpcs.xml`, `Generic.Metrics.NestingLevel`
absoluteNestingLevel 3) and `phpmd` refuses one past cyclomatic complexity 9 (`phpmd.xml`,
`CyclomaticComplexity` reportLevel 9). Both thresholds are spelled out rather than left at
a tool default, both run as steps of the `php-test` job, and `composer lint` runs the same
two locally. The tree was already inside the floor: 56 files, no findings.

## [0.9.0] - 2026-10-19
## [0.9.0] - 2026-10-29

The wire 1.0 release, for the fleet's flag day (19 Oct 2026, 18:03 UTC): from
then on every live station speaks wire 1.0 (macula 15) and nothing older, and
0.8.2 can no longer connect. libmacula is macula-go v0.27.0, whose code is
v0.27.0-rc.8's; this package's code is 0.9.0-rc.6's. The entries for rc.1 to
rc.6 below are what changed since 0.8.2.
0.8.2 can no longer connect. libmacula is macula-go v0.29.0, the release that
carries the A0 contract (v0.27.0 at the flag day); this package's code is
0.9.0-rc.6's. The entries for rc.1 to rc.6 below are what changed since 0.8.2.

### Changed since this entry was written

- **A call a keyed provider refuses `sealed_required` is resealed and answered**, instead of the
caller failing on a stale keyless candidate: the caller seals again to the key in the refusal's
signed tbs, which is the key the provider holds now (macula-go v0.29.0, macula-php#17).
- **The structural floor is gated in CI** (macula-io/macula-codebase-checks#9): `phpcs` refuses a
function that nests past three blocks (`phpcs.xml`, `Generic.Metrics.NestingLevel`
absoluteNestingLevel 3) and `phpmd` refuses one past cyclomatic complexity 9 (`phpmd.xml`,
`CyclomaticComplexity` reportLevel 9). Both thresholds are spelled out rather than left at a tool
default, both run as steps of the `php-test` job, and `composer lint` runs the same two locally.
The tree was already inside the floor: 56 files, no findings.

### What this release does not change

- Sealing is the default where the provider names a key, and only there. A provider names a KEM key
only when it opts in with `kemAdvertise: true`, which is off by default (`src/Pool.php:48`), so two
pools on default arguments talk in the clear. A call or stream is sealed whenever the advertisement
carries a key, and a provider that names none is called in the clear unless the caller asks for
`Confidentiality::Required`. Refusing a clear call unless the caller opts out is not in this
release.
- A procedure served with no policy is advertised open, unary and streaming alike: `serve` and
`serveStream` take the policy as a nullable parameter, and omitting it serves any caller
(macula-php#19 for streams, macula-php#21 for unary).

## [0.9.0-rc.6] - 2026-10-17

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ compatibility layer.
| Calls by direct dial (`call`, `providers`) | ✅ | ✅ | Errors arrive as `ProviderError` / `RelayError`; a station's refusal of a serve or subscribe is a `RefusedError` with its `reason`, `registration` and `station`; every other failure is a `MaculaException` whose `kind` is the library's error kind |
| UCANs (`NodeKey::ucan`, `Ucan::proofId`, `ucan:`/`proofs:`, `ServePolicy`) | ✅ | ✅ | A token minted for the node that presents it, delegated by `prf`; a procedure served under `ServePolicy::ucanRequired` or `realmMemberRequired` reaches its handler only with a chain the policy accepts, refused otherwise as `ProviderError` `unauthorized` |
| The seal report (`callReport`, `Stream::report`) | ✅ | — | Whether the exchange behind a result was sealed, to which provider and key |
| End-to-end sealing (`confidential:`, `kemAdvertise:`) | ✅ | ✅ | A call or stream is sealed whenever the provider's advertisement names a KEM key; `Confidentiality::Required` fails with `ConfidentialityError` rather than go in the clear; a served `Request` says whether it came `sealed` |
| End-to-end sealing (`confidential:`, `kemAdvertise:`) | ✅ | ✅ | A call or stream is sealed whenever the provider's advertisement names a KEM key; `Confidentiality::Required` fails with `ConfidentialityError` rather than go in the clear; a served `Request` says whether it came `sealed`. A keyed provider that refuses a call `sealed_required` has it resealed to the key in the refusal's signed tbs and answered, the key that provider holds now, rather than failing on a stale keyless candidate (macula-go v0.29.0) |
| A node's own namespace (`ownProcedure`) | ✅ | ✅ | `~<node_id>/<name>`: served and called with no org and no realm key; the node's signature authorizes it |
| Streams (`openStream`, `serveStream`) | ✅ | ✅ | Server, client and bidi; a QUIC stream per session, released on every path |
| Publish/subscribe | ✅ | ✅ | Signed publications, delivered once across links |
Expand Down
Loading