# 2026-09-12 --- Qingtian / FRO Detailed Development Report

## A. Phase 5D-1 --- Storage Guard Production Deployment

### A1. Sentinel Provisioning

确认 Host： - Mount target: `/mnt/qnap-survey` - Source:
`//192.168.1.9/NAS Survey Data` - Filesystem: CIFS - RW: confirmed

确认 Container： - Target: `/receive-file` - Source:
`//192.168.1.9/NAS Survey Data[/Receive File]` - CIFS RW: confirmed

建立 sentinel： - Host path:
`/mnt/qnap-survey/Receive File/.fro-receive-storage-id` - Container
path: `/receive-file/.fro-receive-storage-id` - Storage ID:
`fro-receive-qnap-survey-prod-20260912-d6f377dad93a9cf2fe41d3c2c0741bd5` -
Regular file: yes - Symlink: no - Size: 71 bytes - Host/container
content exact match

### A2. Docker Compose Configuration

加入： -
`REMOTE_OFFICE_RECEIVE_STORAGE_ID=fro-receive-qnap-survey-prod-20260912-d6f377dad93a9cf2fe41d3c2c0741bd5` -
`REMOTE_OFFICE_RECEIVE_STORAGE_SENTINEL=.fro-receive-storage-id` -
`REMOTE_OFFICE_RECEIVE_MIN_FREE_BYTES=10737418240`

Checkpoint： -
`docker-compose.yml.checkpoint_20260912_before_receive_phase5d1_deployment`

`docker compose config -q`：PASS。

### A3. Controlled Activation

执行： `docker compose up -d --no-deps --force-recreate remoteoffice`

Old container: - ID:
`180f235f4c8d81e62609be4f9f8b5abfe26c499006d2bd0b3b23344cee3b2d01` -
Started: `2026-09-11T23:58:47.495946377Z` - Restart count: 0

New container: - ID:
`9e17927c37ccf0a63dab20abcd00aff793be694b23f888dfd96549a79181508c` -
Started: `2026-09-12T14:21:03.104899718Z` - Restart count: 0

结果： - Uvicorn 正常启动。 - 无 traceback。 - 无
sentinel/storage/SQLite initialization failure。 - Storage Guard =
configured-and-healthy。 - Sentinel enforcement = ENABLED。 - Free space
当时约 2.007 TB，远高于 10 GiB reserve。 -
`/data/filedrop/receive.sqlite3` 正常。 - 原 metadata 可读：2 drops / 5
uploads。 - GET `/` = HTTP 200。 - GET `/filedrop` = HTTP 200。 -
Authenticated Receive list = HTTP 200。

------------------------------------------------------------------------

## B. Phase 5D-1 --- Real Production Upload Test

测试 source： - `/tmp/receive-phase5d1-production-test-20260912.txt` -
Size: 117 bytes - SHA-256:
`f6551962d5f026084dc60371ced1bdaeccf255c71eed310e00635b82fccdcc4b`

Test drop: - `0067d721-452e-467f-a91d-329c5939dd93`

Test upload: - `ca32a0af-5df3-416e-8eda-2a636ac5be10`

结果： - Create link: HTTP 201 - Public Receive page: HTTP 200 - Upload
initialization: HTTP 201 - Upload/finalization: HTTP 200 - Status:
Completed - Expected size: 117 - committed_offset: 117 - `.part`:
correctly removed - QNAP final file:
`/receive-file/Received/0067d721-452e-467f-a91d-329c5939dd93/receive-phase5d1-production-test-20260912.txt` -
Source/final SHA-256 exact match - Storage Guard after upload: healthy -
Container restart count: 0

测试 harness 曾因预期 response key `completed` 而产生 `KeyError`，但实际
HTTP upload 已成功；后续 database、QNAP file、checksum 与 admin detail
均确认 production operation 正常，因此不是 Receive production failure。

### B1. Controlled Test Cleanup

完成： - revoke exact test link - delete exact 117-byte QNAP test file -
remove empty Received test directory - delete exact upload row - delete
exact drop row - delete `/tmp` source

未影响： - sentinel - Storage Guard - unrelated QNAP files - existing
production metadata

Cleanup 后： - non-test metadata = 2 drops / 5 uploads - fingerprint:
`36b6ee3ce412a4daf059eec8688f8dbf17d772a10f0f35b4feac76ae8ec66ee4`

一个空的 `.fro-incoming/<test-drop-id>`
目录因不在授权删除目标内而保留；无 `.part` 文件。

**Phase 5D-1 FINAL STATUS: PASS / CLOSED.**

------------------------------------------------------------------------

## C. Phase 5E --- Receive Link Management UI

### C1. Backend API Confirmed

-   Create: `POST /filedrop/receive/links?expiry_hours={1..720}`
-   List: `GET /filedrop/receive/links`
-   Detail: `GET /filedrop/receive/links/{drop_id}`
-   Revoke: `POST /filedrop/receive/links/{drop_id}/revoke`
-   Management endpoints use `require_share_admin`.

### C2. UI Implementation

Changed: - `templates/filedrop.html` - new
`tests/test_receive_management_ui.py`

Checkpoint: -
`templates/filedrop.html.checkpoint_20260912_before_receive_phase5e`

Implemented: - Create Receive Link - expiry choices 1/6/12/24/72/168h -
one-time raw URL display - Copy Link - Done/Close -
Active/Expired/Revoked states - Revoke Active link - existing
detail/cleanup/history preserved

Security: - raw Receive URL only available from creation response - no
SQLite persistence of raw token - no localStorage - no IndexedDB - no
historical token recovery - token_hash not exposed

Tests: - Total 68 - PASS: 68 - Python syntax: PASS - HTML parse: PASS -
JS structural validation: PASS - Storage Guard regression: PASS

### C3. Browser Validation

Tailscale FileDrop address used: `http://100.117.100.85:8000/filedrop`

Browser verified: - Share Admin Unlock works - Receive Management
loads - Create 1-hour link works - one-time URL displayed - Copy Link
works - public Receive sender page opens successfully

Public sender page displayed: - Choose Files - Drop files here - Ready
state

No additional upload required because production upload path was already
fully validated during Phase 5D-1.

------------------------------------------------------------------------

## D. Phase 5E UI / UX Review

### D1. Obsolete Top Buttons Removed

Removed: - 上传文件 / Upload - 分享现有文件 / Share File - 接收文件 /
Receive

Inspection confirmed these were only `scrollIntoView` controls with no
application state/API responsibility.

After removal: - Receive tests: 68 PASS - Share targets API: HTTP 200 -
Receive list API: HTTP 200 - Storage Guard healthy - no restart

### D2. User-Approved Dashboard Direction

Desktop objective: approximately one 1920×1080 viewport.

Requested final structure:

#### Top Banner

-   File Transfer identity
-   Share File Admin Token + Unlock embedded in blue/gradient banner

#### Left

-   Browse Files
-   file checkboxes
-   Preview window
-   restore preview functionality
-   preserve old selection workflow:
    -   preview file
    -   tick one/multiple files
    -   choose selected files or whole folder

#### Center

-   Share File creation --- blue
-   Receive File creation --- purple
-   Share and Receive creation controls side-by-side
-   folder/target + expiry + create link arranged compactly

#### Unified Management

One view box: - Share Links tab/view --- blue - Receive Links tab/view
--- purple - vertical + horizontal internal scroll - sticky headers
where safe

Share Link Details should contain Client Download Activity rather than
adding another permanent dashboard box.

Desired Client Download fields where backend supports them: - client
name - phone - IP - filename - size - start time - last activity -
downloaded bytes - progress - completion/interruption status

No fabricated fields are allowed if backend does not currently collect
them.

#### Working Status

-   separate view box
-   bounded height
-   vertical + horizontal internal scrolling
-   global current activity only
-   avoid huge empty space

#### Cleanup

-   Abandoned Upload Cleanup
-   Cleanup History to be compacted into maintenance/tools area rather
    than large standalone cards.

------------------------------------------------------------------------

## E. Current Interrupted Work State

Codex began the unified dashboard redesign and modified
`templates/filedrop.html`.

Observed in interrupted diff: - `qingtianShareLinks = []` -
`qingtianDownloadActivity = []` -
`initializeQingtianUnifiedManagement()` - Receive records moved into
unified management structure - maintenance area being moved -
`showQingtianManagementView("share")` initialization

Codex then hit usage limit before completing implementation and
regression validation.

Therefore:

**Current dashboard redesign = UNVERIFIED / IN PROGRESS.**

Do not treat current template as final stable baseline.

No rollback was performed.

No Docker restart/recreate was performed.

------------------------------------------------------------------------

## F. Tomorrow Resume Procedure

Resume the same Codex session and instruct:

> Continue from the interrupted Phase 5E dashboard redesign exactly
> where you stopped. Do not restart from scratch. First inspect the
> current unverified diff, complete the implementation, then run the
> full regression validation.

Priority: 1. Restore Preview. 2. Restore/preserve file checkboxes. 3.
Preserve selected files vs whole-folder sharing. 4. Complete
Share/Receive unified management. 5. Complete Client Download Activity
using authoritative backend data only. 6. Complete dual-axis internal
scrolling. 7. Complete one-screen desktop layout. 8. Validate no
duplicate/orphan JS. 9. Run all 68+ Receive tests. 10. Real-browser
visual/E2E verification. 11. Only after acceptance: freeze Phase 5E.

## G. Do Not Do

-   Do not `git reset`.
-   Do not `git clean`.
-   Do not restart/recreate Docker merely for UI work.
-   Do not alter sentinel.
-   Do not weaken Storage Guard.
-   Do not begin Phase 5D-2 before Phase 5E dashboard is completed and
    accepted.
