feat(hub): set an expiry on a share link from the UI (BEA-29) (#74)

The CLI has had --expires all along and the Public links table has always
said "no expiry" — naming an alternative the hub UI never offered. Every
link minted from the browser was permanent.

Expiry is offered AFTER minting, not before: the one-click share stays one
click, and PATCHing the token we just handed out keeps the URL already on
the clipboard valid. Minting with a TTL would instead create a second link,
since ShareDB.Create only reuses permanent ones.

- ShareDB.SetExpiry re-dates a live share in place; repo-write failure
  restores the previous row rather than deleting it (unlike Create's
  rollback, this row already existed — dropping it would revoke a live
  link over a disk hiccup).
- PATCH /api/shares/{token} mirrors handleShareRevoke: resolve the token,
  requirePerm(PermWrite), act. Duration parsing is copied from
  handleShareCreate so the two routes can't drift.
- Share dialog gets an Expires select (Never / 24h / 7d / 30d). A failed
  PATCH toasts and reverts the control. Copy link keeps the dialog's
  initial focus — the new control would otherwise have taken it.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Snow W. Lee (Sungwon)
2026-07-29 17:05:06 +09:00
committed by GitHub
co-authored by Claude Opus 5
parent 6ae941683e
commit acb99e85e3
17 changed files with 309 additions and 27 deletions
@@ -46,7 +46,7 @@ https://drive.example.com/s/eacc1df3ee6a6ebbdacc535c2796dc30
```
Links serve the file's **latest** synced content, which is the right behavior
for living reports and wiki pages, and live until revoked.
for living reports and wiki pages, and live until they expire or you revoke them.
```sh
bdrive share --list # every link you've minted
@@ -54,7 +54,10 @@ bdrive share --revoke <token-or-url> # kill one
bdrive share --expires 24h <file> # self-destructing link
```
The web UI has a Share button on every file.
The web UI has a Share button on every file. Its dialog also carries an
**Expires** selector — Never, 24 hours, 7 days, 30 days — which re-dates the
link it just minted. The token and URL don't change, so an expiry you add after
copying the link doesn't invalidate what you pasted.
This is what makes "write a report and share it" a single request: the agent
generates `wiki/report.html`, the hook pushes it, and the reply comes back with
+1 -1
View File
@@ -16,7 +16,7 @@ One binary, `bdrive` — the CLI, the sync daemon, and the web server.
| `bdrive scope [add\|rm <dirs...>]` | Show or change which subfolders sync — edits the managed block of `.bdriveignore` rules that `init --only` writes. Run from the mount root; the daemon picks changes up in seconds. `rm` stops syncing a folder but deletes nothing, locally or on the hub |
| `bdrive forget <path>...` | Stop syncing a path and remove it from the hub. Adds the rule to `.bdriveignore` (which syncs) and prunes in one step. Local files are never touched, here or on teammates' devices |
| `bdrive url [path]` | Internal hub link for a file or folder — sign-in and membership required. `--sync` pushes first; no argument gives the project home. Computed locally |
| `bdrive share <file>` | Public URL for a synced file. `--list`, `--revoke`, `--expires` |
| `bdrive share <file>` | Public URL for a synced file. `--list`, `--revoke`, `--expires` (the hub's Share dialog can also set an expiry on an existing link) |
| `bdrive sync [folder]` | Run one sync cycle now. Refuses folders this device never `init`ed and folders paused by `bdrive stop`. `--note <text>` stamps session context onto changes; `--note-ttl` (default 30m) bounds it. `--prune` also removes from the hub what `.bdriveignore` now excludes (files stay on disk everywhere). `--hook <label>` is agent-hook plumbing |
| `bdrive hooks [install\|uninstall]` | Register turn-boundary sync hooks in each detected agent platform's user config — once per machine, covering every folder. Run automatically by `bdrive init`; idempotent; `--agent` overrides detection. `uninstall` removes only BearDrive's own hook entries |
| `bdrive skill [install]` | Install the `beardrive` skill into detected agent platforms so the agent can do setup itself. Run automatically by `bdrive init`; idempotent; `--agent` overrides detection |