Skip to content
48 changes: 48 additions & 0 deletions docs-developers/architecture/cross-repo-contract.md
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,12 @@ tries the book's identifiers first, then its `book_matches` `work_id` and
`recording_id` when they find nothing. The envelope is the same, so the wire does
not change.

A book [added from LibriVox](#librivox-fetches) gets its row from the server's
fold of the done `librivox.fetch`, with the work and recording the server resolved
at queue time (`how` `accepted`). Where a LibriVox recording is on the server is
read from these rows alone, by their exact, non-empty `recording_id`, never from
`/meta`'s first-recording answer for a work.

The player's book page asks `/meta` for every loaded book that is not an episode
(`bookPageMetaEnabled`), so a book matched with neither identifier shows its
community content there. Most other surfaces keep the identifier gate
Expand Down Expand Up @@ -1373,6 +1379,7 @@ server's reader. See [The .audiosilo folder](../bridge/attachments.md).
| `audible.poll` | Polls one Audible account. |
| `audible.import` | Backs up one Audible title. |
| `audible.sync` | Syncs listening positions with one Audible account. |
| `librivox.fetch` | Downloads one LibriVox recording into a books library. |

Each kind's rules follow.

Expand Down Expand Up @@ -1594,6 +1601,34 @@ feed also answers `400 invalid_request`.

See [Position sync](../bridge/audible.md#position-sync-audiblesync-and-the-push-loop).

### LibriVox fetches

`librivox.fetch` (feature `librivox`) is internal and writing, for a books library,
not quiet, deduped per library and project, and in no module.

- Three admin routes queue and support it: `GET /admin/librivox/search`,
`GET /admin/librivox/work` and `POST /admin/librivox/fetch`. All are `404
metadata_off` while community metadata is off. There is no `/server` flag: a
client gates on the `librivox` feature.
- The server builds its params, `{librivox_id, work_id, recording_id, library_id}`,
with the work and recording from metaserve's `lookup?librivox_id=` at queue
time. The Bridge reads them leniently and ignores unknown fields.
- The Bridge reads the manifest from its own metadata service and downloads only
from `https` archive.org hosts, checking every redirect.
- It reports progress steps `manifest|download|cover|place|rescan`. The result is
`{library_id, path, librivox_id, files, bytes}`, where `path` is the book path
that `POST /bridge/rescan` answered.
- A failure is `{code, message}`, with `not_writable`, `exists`, `disk_full`,
`not_found`, `archive_unavailable` or `metadata_off`.
- It uses no new Bridge route.
- The Bridge writes `.audiosilo/librivox.json`
(`{version, librivox_id, work_id, recording_id, archive_id}`) into the book's
folder. The server does not read it yet, and its scanner skips the name.
- The server folds a done result into the book's `book_matches` row
([Matches by work id](#matches-by-work-id)).

See [Add from LibriVox](../bridge/librivox.md).

### The player's Bridge surface

The player's first admin-only UI is gated on all of these:
Expand All @@ -1609,6 +1644,10 @@ Its confirmation holds Generate back while the estimate's `open_job` is a
for a book with no ASIN or ISBN. Its `types.ts` mirrors the job, the estimate,
`BookMetaWork.generated` and `BookMetaWork.generated_description` by hand.

Find on LibriVox is gated the same way with `librivox` in place of `sidecars`, so
it shows only while the Bridge is online. Its `types.ts` and `client.ts` mirror the
three LibriVox routes by hand.

### Bridge seam and old clients

Everything is additive.
Expand Down Expand Up @@ -1643,6 +1682,15 @@ Audible backups:
it (`kind_unavailable`, and a poll's policy pass queues nothing).
- Its account PUT's `policy` still creates an account as before.

LibriVox fetches:

- An older server doesn't know `librivox.fetch`, so its `features` never list
`librivox`, and neither the console nor the player offers the feature.
- An older Bridge never advertises it, so the fetch route answers
`kind_unavailable`.
- A shipped player never sees Find on LibriVox. A book added this way is an
ordinary book with a recorded match.

Audible position sync:

- An older Bridge never advertises `audible.sync`, so the server queues none and the
Expand Down
4 changes: 4 additions & 0 deletions docs-developers/bridge/attachments.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ The prefix keeps the books of one folder apart, since a collection folder's book
share one `.audiosilo/`. These are the book attachment names; podcast-specific
files are described below. Audio is never stored in `.audiosilo/`.

A book [added from LibriVox](librivox.md#audiosilolibrivoxjson) also holds
`.audiosilo/librivox.json`, which names its LibriVox recording. It is no
attachment. The server skips the name and serves nothing from it.

### Podcast CHAP attachments

`podcast.fetch` writes `<show>/.audiosilo/<stem>.chapters.json`, stripping only
Expand Down
15 changes: 14 additions & 1 deletion docs-developers/bridge/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ the images (`AUDIOSILO_BRIDGE_DATA`), else `--data`, else `~/.audiosilo-bridge`.
the defaults and the environment apply;
- the SQLite database `bridge.db`;
- the sealed `secrets/` and their key `secret.key`;
- the tools the Bridge downloads.
- the tools the Bridge downloads;
- `librivox/`, one state file per LibriVox fetch
([Staging, resume and cleanup](librivox.md#staging-resume-and-cleanup)).

Settings are read from `<data>/config.yaml`, then overridden by `AUDIOSILO_BRIDGE_*`
variables. An **empty** variable counts as unset. A variable that doesn't parse
Expand Down Expand Up @@ -227,6 +229,17 @@ and tests. Release builds and images never carry the tag, so there they do nothi
| `AUDIOSILO_BRIDGE_AUDIBLE_FAKE_URL` | the base URL of an Audible fake (`go run -tags audiblefake ./cmd/audiblefake`): every Audible and Amazon endpoint goes there instead |
| `AUDIOSILO_BRIDGE_AUDIBLE_RECORD_DIR` | records every Audible exchange into a `0600` JSON-lines file in this folder, scrubbed of credentials as it is written. It is for recording fixtures from a real account |

## LibriVox

`librivox.fetch` has no settings of its own. It reads LibriVox manifests from the
engine's `metadata.base_url` (`AUDIOSILO_BRIDGE_METADATA_BASE_URL`, default
`https://meta.audiosilo.app`). With it empty, the job fails `metadata_off`. It
downloads only from archive.org, over https, through a guarded client that
reaches public addresses only (the podcasts' `allow_networks` does not apply).
The book's files go straight into the library's folder, staged in a hidden folder
beside the book, so the library needs the room, not the data folder. See
[Add from LibriVox](librivox.md).

## Secrets

The Bridge's secrets are **never in `config.yaml`**. They are:
Expand Down
5 changes: 4 additions & 1 deletion docs-developers/bridge/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,10 @@ Conventions that carry the design:
- the podcast jobs write a show's files in a podcast library
([Podcasts](podcasts.md));
- `audible.import` installs a backed-up title without replacing anything
([The hardened transfer](audible.md#the-hardened-transfer-internaltransfer)).
([The hardened transfer](audible.md#the-hardened-transfer-internaltransfer));
- `librivox.fetch` writes a whole new book folder, staged in a dot folder beside
it and moved into place by one no-replace rename, never into an existing book
([Add from LibriVox](librivox.md#staging-resume-and-cleanup)).

A delete moves the files into `.audiosilo-trash/` first, as podcast retention
does
Expand Down
7 changes: 7 additions & 0 deletions docs-developers/bridge/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ the job kinds in the Bridge's heartbeat include it (see
[`audible.sync`](audible.md#position-sync-audiblesync-and-the-push-loop) and a
push loop over `GET /bridge/progress` sync listening places both ways, furthest
only, for the accounts the console turns sync on for.
- **LibriVox.** [`librivox.fetch`](librivox.md) adds a LibriVox recording an admin
picked to a books library: the manifest from the community metadata service,
the sections from archive.org only, a no-replace move into place, a rescan. The
server then records the book as that recording.

Some job families belong to a [managed module](../server/modules.md) of the
server, which the console turns on and off.
Expand Down Expand Up @@ -258,6 +262,9 @@ one-command worker install needs them.
its matching, `audible.import` (backups: resume, the hardened transfer,
secrets), position sync (`audible.sync`, the push loop), the server's accounts,
titles and queueing, the `audible` module and the build-tagged fake.
- [Add from LibriVox](librivox.md) - `librivox.fetch` (its params, progress,
result and codes), the book's identity, the archive.org-only fetch, placement,
staging and resume, and `.audiosilo/librivox.json`.
- [Configuration](configuration.md) - the Bridge's settings and environment, the
images and the compose example.
- [Development](development.md) - the gate, the layout and the Bridge's own page.
Expand Down
Loading
Loading