feat: storage writes via storage-agent, accepts_uploads and write_template (M5.5)
ci / api / api (push) Successful in 33s
ci / contract / contract (сгенерированный код совпадает с openapi.yaml) (push) Successful in 43s
ci / mobile / mobile (Metro-бандл Android) (push) Successful in 1m11s
ci / ts / ts (packages + web) (push) Successful in 1m10s
ci / docker / docker (образы собираются — их сервер собирает сам при обновлении) (push) Successful in 51s

- storage-agent: POST /internal/files copies a staged file into a source
  (temp file, fsync, SHA-256 check, hard link so nothing is overwritten,
  " (2)" suffix on conflict, owner PIPU_FILE_UID/GID) and
  POST /internal/files/test. NFS sources that accept uploads are mounted
  rw in an agent-only /library-rw and bind-mounted read-only for others;
  local sources are written through /library-host-rw.
- meta: write templates ({track:02}, {disc:1-}, [optional]) with name
  sanitising and length limits, suggestion from the source's regexes
  and a reversibility check against 50 catalogue tracks.
- API and admin UI: accepts_uploads / write_template on sources,
  write-template suggest and check endpoints, write test result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Opus 5.5 committed 2026-10-20 13:46:56 +03:00
1 parent 9b50038bb4
commit f66be2ba0a
27 files changed
+2422 -213

No files matched your search

+24
View File
@@ -159,5 +159,29 @@
"wave_listen": "Played ≥ 50%",
"wave_early_skip": "Early skips",
"wave_likes": "Likes per 100"
},
"write_template": {
"title": "Uploads and path template",
"intro": "Approved tracks from the upload queue are placed here using a template that repeats this storage's folder layout.",
"accepts": "Accept uploads into this storage",
"nfs_rw_hint": "The storage will be reconnected: the agent also mounts it for writing (visible only to the agent). The NFS export must allow writes for PIPU_FILE_UID.",
"template": "Path template",
"hint": "For example {albumartist}/{year} - {album}/{disc:1-}{track:02} - {title}.{ext}; [ … ] is an optional part",
"suggest": "Suggest from layout",
"check": "Check",
"save": "Save",
"saved": "Saved",
"required": "Set a path template to accept uploads.",
"no_tracks": "The storage has no tracks yet, so there is nothing to check the template against.",
"check_ok": "The template is reversible: {{round_trip}} of {{total}} paths parse back unchanged, {{same_path}} match the real ones.",
"check_warn": "Mismatches found: {{round_trip}} of {{total}} parse back unchanged, {{same_path}} match the real paths (90% needed). New files may be laid out differently from existing ones.",
"col_real": "Real path",
"col_rendered": "From template",
"col_problem": "Mismatch",
"no_pattern": "no pattern matched",
"other_path": "different path",
"badge": "accepts uploads",
"write_ok": "Write: ok",
"write_fail": "Write failed: {{message}}"
}
}