The link after the table's [start, end) interval read, to the section
reference check, as one link text reaching back to energy-measurement
§2.7; and "keeps none signs" matched the public-text check's "none signs".
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The DVR store reads an object's Key ID to know a sealed room; the feature
was on only through the dev-dependency, so the relay built as another
crate's dependency (joule-moq-ingest, the e2e's release binary) did not
compile. tests/sealed_objects.rs now gets it from the normal dependency.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
confidentiality §9 (merged with L10) says a relay keeps nothing of an
end-to-end encrypted room's tracks beyond delivery; the DVR store kept
every track its prefix rules matched. The store now knows such a room by
its first object carrying a secure-objects Key ID (or properties that do
not read), never writes that group, deletes what it held of the room (its
events and receipts tracks are in the clear and can be whole first),
drops the room's decisions from decisions.wdl, writes nothing more of it,
and records it in sealed.wdl so a restart keeps refusing it. Moderation
still honours the room's decisions for what the cache serves.
live-recording §8.2 states the rule; confidentiality §9 points to it.
The joule-code changelog's stale "a file per group" now describes the
segments, and the cache's media/receipts pairing is documented.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A group's receipts are cached before its media, and under load the media's stream can be
taken after later groups, so the budget could evict receipts group g before media group g
had arrived: the pairing found no partner to evict, and media g was then cached and served
without receipts (the DVR by-age test, 8 of 64 runs under load). Evicting group g now moves
the partner track's evicted mark to g as well, so a partner group arriving later is never
served from the cache alone; a DVR-kept track still takes it for the store.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Taking group 3 can evict a media and receipts pair from the cache; the test's media and
receipts FETCHes are two requests, so an eviction between them left media without its
receipts ("the receipts of group 2 come with it", 16 of 64 runs under load with logging).
The test now waits until the relay's largest object of both tracks is group 3's.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The DVR store evicts the track whose lowest group arrived first; a group's arrival time
can be later than a higher group's (the cache recreates a group's state when it takes a
late group), so the store could evict groups 31 and 32 while group 30 stayed held below
the new mark: a gap in the window (1 of 16 concurrent runs of the window test). Moving a
track's evicted mark now removes every group at or below it, in the track and its
partner, so none is ever held below the mark.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
A second run in the same output directory failed its service scenario: the room service's
keygen refuses the key file the first run left.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The cache's byte budget evicted oldest first across tracks, and a group's receipts are
cached just before its media, so under pressure a media group could stay cached while its
receipts group was gone: a FETCH then served media no receipts covered (seen in the DVR
test a_window_by_age_empties_as_its_groups_pass_it under concurrent runs). The pair is now
evicted together, as the DVR store already evicts it, and kept together while either is
still arriving on a track the store keeps. Budget::take drops the partner's accounting.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Groups finish, and are sealed, out of order under load. The store evicted by arrival
across all groups, so a group sealed late could sit below groups already evicted, leaving
gaps in the window (seen as [29, 32, 34, ...] in the window test under concurrent runs).
Each track now evicts its lowest group first (across tracks, the one whose lowest group
arrived first), and the writer refuses a seal below the evicted mark when it writes it,
not only when it was queued.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
local_plan's run of groups the DVR store evicted searched the cache for the next whole
group from the run's first group itself, which the cache had already declined (it was at
or below the cache's own eviction mark), so the run ended at g - 1: an inverted range, and
at group 0 a subtraction overflow that panicked the session's task (seen in the DVR test
a_window_by_age_empties_as_its_groups_pass_it). The search now starts after g and skips
groups the cache evicted. local_plan takes the track's cache rather than the track, so the
two cases are unit tests.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Under load a group's stream can finish after the cache evicted a later group of its track;
the cache refused it, so the DVR store never got it. For a track the store keeps, the cache
now takes it and eviction drops the evicted group's state alone; coverage is unchanged. The
mux test of a stream that arrives after the close no longer fails when, on a loaded host, the
close arrives before its writes do.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Two sessions that ended together could interleave a line and its newline, leaving two
summaries on one line of summary.out_path.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
One durable sync per group file could not keep up with a room's audio groups (fifty a second
per publisher), so the writer fell behind and recent groups were neither cached nor stored.
Segments take ten seconds of a track each; a record a later one replaces is marked and
zeroed; a crash loses at most the last second, and what it leaves cut short is cut off and
counted at start.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The second implementation allows powers bit 4, states each accepted
grant's seek, and gives every request of seek its outcome by §10.6's
rule from the room's grants as §4.3 checks them; the README describes
the dvr room, the new refusals and the seek section.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Every existing record and stated outcome is unchanged; each accepted
grant's moqt entry gains its seek, false for every grant before the dvr
room.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
power::SEEK is bit 4, which the descriptor's and the grant's field rules
now allow; seek_check refuses seek_not_granted a request that starts in a
group below the live edge under a grant without it. The corpus gains the
accepted dvr room, three refused vectors (a grant with seek its role
lacks; a grant and a role with powers bit 5), each accepted grant's seek,
and the seek section.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
powers gains bit 4 seek; a role's and a grant's powers set none above
bit 4, and a grant's seek stays within its role's (§4.3 step 7). §10.6
fixes the live edge (MOQT §3.1.4) and when a FETCH or a SUBSCRIBE's fill
seeks back, which a relay serves only under a proved grant holding
seek, refusing any other with REQUEST_ERROR UNAUTHORIZED and the reason
phrase seek_not_granted (§11). §12 describes the new corpus content.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
The second implementation reads WMH1 version 1 or 2 by its own layout,
holds version 2's out and stored figures to the entries, chooses the
bound by the fifth byte (B2(M) for 2, B(M) otherwise), and states each
record's version and a version 2 record's DVR figures. New mutations
cover the stated version, figures and bound, the record's DVR bytes, and
the four new refusals. The README describes the new vectors.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Five vectors added (dvr_relay accepted; dvr_out_exceeds,
dvr_stored_exceeds, record_unknown_version, dvr_record_too_large
refused); every existing vector's records and receipt are unchanged and
its accepted records gain only their version, 1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
dvr_relay (accepted): the lesson's relay keeps a ten-second DVR window of
the composite and signs a version 2 record of it, a viewer joining at
20 s filled from the window. Refused: dvr_out_exceeds and
dvr_stored_exceeds (record_invalid), record_unknown_version (version 3),
dvr_record_too_large (past B2(M) by less than an entry). Each accepted
record's facts state its version, and a version 2 record's six DVR
figures; every existing record keeps its bytes.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
HopRecord gains dvr: Option<DvrFigures>; Some is version 2, None version 1,
whose bytes are unchanged. A record reads as version 1 or 2 by its own
layout, any other version unknown_version; version 2's out figures are
held to the out entries and its stored figures to the in entries
(record_invalid). The size bound is chosen by the fifth byte before
anything else is read: B2(M) = B(M) + 48 for version 2, B(M) otherwise.
DvrFigures::byte_seconds floors the sum once. energy_steering's corpus
builds its records as version 1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Version 2 of the per-hop session record adds one field, dvr, after ledger
and before sig: six u64 of what a hop that keeps a DVR window served from
it, stored in it, held in it (byte-seconds, rounded down) and dropped from
it for not verifying against their receipts. A reader reads version 1 or
2 by its own layout; version 2's out and stored figures are held to the
out and in entries (record_invalid); its bound is B2(M) = 600 + 180(M+2),
chosen by the fifth byte before anything else is read. The units do not
sum the DVR figures; the outcome states each record's version and, for
version 2, its figures. The receipt stays version 1.
Co-Authored-By: Claude Opus 5.5 <[email protected]>