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
11 changes: 6 additions & 5 deletions js/watch/src/broadcast.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,12 @@ describe("cross-broadcast renditions", () => {
// A derived rendition produced only on demand by a service that claims a covering prefix (a
// wildcard) instead of announcing each path. Nothing announces the rendition until something
// subscribes to it, so the player must list it from the claim alone. The rendition is a sibling:
// one beneath its source is already covered by the source's own announcement.
// one beneath its source is already covered by the source's own announcement. The service prefix
// is hidden, as a deployment keeps it out of listings, so the claim is only seen by opting in.
describe("wildcard renditions", () => {
const name = Path.from("live/foo.hang");
const derived = Path.from("transcode/foo.hang");
const rel = Path.normalizeRelative("../transcode/foo.hang");
const derived = Path.from(".pro/transcode/foo.hang");
const rel = Path.normalizeRelative("../.pro/transcode/foo.hang");

const watch = (owner: Origin.Producer) =>
new Broadcast({
Expand Down Expand Up @@ -378,7 +379,7 @@ describe("wildcard renditions", () => {
await settle();
expect(videoRenditions(source)).toEqual(["source"]);

const worker = owner.dynamic(Path.from("transcode"));
const worker = owner.dynamic(Path.from(".pro/transcode"));
const requests = worker.requested();
await settle();
expect(videoRenditions(source)).toEqual(["source", "transcode"]);
Expand Down Expand Up @@ -426,7 +427,7 @@ describe("wildcard renditions", () => {
try {
// A catch-all (an archive) and a narrower pool both cover the derived path.
const archive = owner.dynamic(Path.empty());
const worker = owner.dynamic(Path.from("transcode"));
const worker = owner.dynamic(Path.from(".pro/transcode"));
await settle();
expect(videoRenditions(source)).toEqual(["source", "transcode"]);

Expand Down
4 changes: 3 additions & 1 deletion js/watch/src/broadcast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,9 @@ export class Broadcast {
const origin = effect.get(this.in.origin);
if (!origin) return;

const announced = origin.announced();
// Hidden routes count: a service claim under a `.`-named prefix is kept out of listings, but
// it still covers the renditions it would produce, and this set is never shown to anyone.
const announced = origin.announced(Path.Pattern.all(), { hidden: true });
effect.cleanup(() => announced.close());
this.#announced.set(new Set());

Expand Down
21 changes: 17 additions & 4 deletions quest/m0/wildcard/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,18 @@ on a generation field.

A prefix claim needs the variable part of a path trailing, so a fleet-wide
service claims its own prefix and mirrors the source path beneath it
(`.transcode/<pid>/foo.hang`) rather than publishing beneath the source. The
source's catalog reaches the contribution through a
cross-broadcast reference. The platform layout, grants, and metering are
the deployment's; moq.pro's is in its
(`.pro/transcode/<pid>/foo.hang`, moq.pro's convention) rather than publishing
beneath the source. The source's catalog reaches the contribution through a
cross-broadcast reference.

The leading `.` is deliberate. Existing customers on moq-lite-06 or older must
never see `.pro/` broadcasts, which could confuse their business logic. Those
versions cannot opt into hidden routes, so the relay never announces them
there. Hidden routes are a moq-lite-07 feature, so the player's covering check
opts into them and sees a claim only when lite-07 is negotiated; the token's
scope must still reach them. A customer who wants transcodes upgrades, or
subscribes to the explicit `.pro/<service>/...` path, which works on any
version. Grants and metering are the deployment's; moq.pro's are in its
[wildcard questline](https://github.com/moq-dev/moq.pro/blob/main/quest/m2/wildcard/README.md).

The archive serves the source path itself: a recording IS the broadcast,
Expand All @@ -179,6 +187,11 @@ announcement shadows it. A claim names no generation, so a client that must
distinguish recording generations reads the catalog's archive entry
([archive](/quest/m1/archive/README.md)) rather than announce state.

## Required

- moq-lite-07 is finalized and negotiated by default, no longer
`moq-lite-07-wip`, so the player's covering check sees hidden claims

## Related

- [path-patterns](/quest/m1/path-patterns.md) - owns the pattern dialect
Expand Down
2 changes: 1 addition & 1 deletion quest/m1/broadcast-epoch/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Decided:
bare-name viewer behind one needs a publisher that opts out with the raw
prefix route. Document this rather than promise it works.
- Derived output mirrors the epoch it came from
(`.transcode/pid/foo.hang/@e`, per the
(`.pro/transcode/pid/foo.hang/@e`, per the
[wildcard](/quest/m0/wildcard/README.md) line's derived-output layout), so
the service's prefix claim still covers it.

Expand Down
Loading