file_facade.go: FileClient — единая точка входа. Держит stores map[string]FileStore и searchers map[string]Searcher; Read()/Write()/Search() выбирают бэкенд (PG → fast reads, REST/DAV → запись, ES → поиск) с fallback для чтений только на transient-ошибках. Client.Files() *FileClient, *FileClient реализует FileStore — старый код продолжает компилироваться.
Entry дополнен Updated (нативная строка бэкенда) и FilesCount/FoldersCount, чтобы oo dav ls --output json отдавал те же значения.
Миграция: cmd/oo/dav.go, cmd/oo/projects_files.go (download/rename/delete) — через FileStore; oo search — через фасад; cmd/office/fetch (preview/download/delete) — через интерфейс FileStore.
Депрекейт-пометки на transport-методы, которые теперь абстрагирует FileStore; публичный API не удалён.
Smoke live: oo dav ls 647 / -o json, oo projects files list 4, projects files download, dav download, oo search Rechnung (фасад→ES, без OO-кред) — ОК.
gitleaks — no leaks.
Известный чужой долг (не трогал): go vet -tags=integration падает на cmd/office/fetch/task_integration_test.go:60 (loader.TaskFields undefined) — есть на main.
Не мержу и не закрываю.
F4 эпика #34. Закрывает #38.
## Что
- `file_facade.go`: `FileClient` — единая точка входа. Держит `stores map[string]FileStore` и `searchers map[string]Searcher`; `Read()`/`Write()`/`Search()` выбирают бэкенд (PG → fast reads, REST/DAV → запись, ES → поиск) с fallback для чтений только на transient-ошибках. `Client.Files() *FileClient`, `*FileClient` реализует `FileStore` — старый код продолжает компилироваться.
- `Entry` дополнен `Updated` (нативная строка бэкенда) и `FilesCount`/`FoldersCount`, чтобы `oo dav ls --output json` отдавал те же значения.
- Миграция: `cmd/oo/dav.go`, `cmd/oo/projects_files.go` (download/rename/delete) — через `FileStore`; `oo search` — через фасад; `cmd/office/fetch` (preview/download/delete) — через интерфейс `FileStore`.
- Депрекейт-пометки на transport-методы, которые теперь абстрагирует `FileStore`; публичный API не удалён.
## Тесты
- Unit `file_facade_test.go`: `TestFileClientIsFileStore`, `TestClientFilesPrefersRESTForReadsAndWrites`, `TestFileClientPostgresTakesReadPriority`, `TestFileClientRegisterStoreNormalizesName`, `TestFileClientReadFallsBackOnlyOnTransient`, `TestFileClientReadStopsOnPermanentError`, `TestFileClientWriteUsesWriteBackend`, `TestFileClientWriteWithoutBackend`, `TestFileClientSearchSelection` — PASS.
- `go build ./... && go vet ./... && go test -race ./...` — зелёные.
- Integration live: `TestIntegrationFileStores` (REST+DAV) PASS.
- Smoke live: `oo dav ls 647` / `-o json`, `oo projects files list 4`, `projects files download`, `dav download`, `oo search Rechnung` (фасад→ES, без OO-кред) — ОК.
- gitleaks — no leaks.
Известный чужой долг (не трогал): `go vet -tags=integration` падает на `cmd/office/fetch/task_integration_test.go:60` (`loader.TaskFields undefined`) — есть на `main`.
Не мержу и не закрываю.
- FileClient composes FileStore/Searcher backends; Read()/Write()/Search()
select REST/DAV/PG/ES with transient read fallback. Client.Files() returns
it and *FileClient implements FileStore, so existing callers keep working.
- Entry gains backend-native Updated + folder FilesCount/FoldersCount so
dav ls output round-trips.
- cmd/oo dav/projects files and cmd/office/fetch download/preview/delete go
through FileStore; oo search goes through the facade.
- Mark transport methods that FileStore now abstracts as deprecated.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
F4 эпика #34. Закрывает #38.
Что
file_facade.go:FileClient— единая точка входа. Держитstores map[string]FileStoreиsearchers map[string]Searcher;Read()/Write()/Search()выбирают бэкенд (PG → fast reads, REST/DAV → запись, ES → поиск) с fallback для чтений только на transient-ошибках.Client.Files() *FileClient,*FileClientреализуетFileStore— старый код продолжает компилироваться.EntryдополненUpdated(нативная строка бэкенда) иFilesCount/FoldersCount, чтобыoo dav ls --output jsonотдавал те же значения.cmd/oo/dav.go,cmd/oo/projects_files.go(download/rename/delete) — черезFileStore;oo search— через фасад;cmd/office/fetch(preview/download/delete) — через интерфейсFileStore.FileStore; публичный API не удалён.Тесты
file_facade_test.go:TestFileClientIsFileStore,TestClientFilesPrefersRESTForReadsAndWrites,TestFileClientPostgresTakesReadPriority,TestFileClientRegisterStoreNormalizesName,TestFileClientReadFallsBackOnlyOnTransient,TestFileClientReadStopsOnPermanentError,TestFileClientWriteUsesWriteBackend,TestFileClientWriteWithoutBackend,TestFileClientSearchSelection— PASS.go build ./... && go vet ./... && go test -race ./...— зелёные.TestIntegrationFileStores(REST+DAV) PASS.oo dav ls 647/-o json,oo projects files list 4,projects files download,dav download,oo search Rechnung(фасад→ES, без OO-кред) — ОК.Известный чужой долг (не трогал):
go vet -tags=integrationпадает наcmd/office/fetch/task_integration_test.go:60(loader.TaskFields undefined) — есть наmain.Не мержу и не закрываю.