Publish a local file with hackmd_create_note

Merged
JS
2d ago
+515-9

hackmd_create_note takes an absolute local_path to a .md file in place of content. The server reads the file, so a large note no longer passes through the conversation, creates the note, polls until it reads back with exactly that body, and then tracks the file the way hackmd_pull_note does. The reply carries tracking.status (tracked or not_tracked with a reason); a tracking failure is never an error once the POST has landed, because an error would invite a duplicate create.

Publishing puts local file content on HackMD, so it is stricter than a plain create. It needs a workspace root set in the server's own environment, like an image upload, and an explicit read_permission, since HackMD's default for an omitted one is unmeasured. The path is canonicalized and access-checked before the POST and compared again before the record is written, so a symlink swapped in during the network calls leaves the file untracked. A file that already has a sync record, a non-.md path, and local_path together with content are refused before any request. A file over the large-file warning size needs confirm_large_file: true.

The logic lives in src/sync/adopt.rs; src/note/crud.rs only gains the two input fields and a guard that create_note itself never sees a local_path. docs/tools.md and docs/configuration.md describe the new section and the root requirement.

Verified locally: cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test --all-targets --all-features (423 passed, 0 failed, 4 ignored), including six new tests in src/sync/adopt.rs for tracking, a differing read-back, a late read-back, the refusals, the root requirement, and create_note refusing a local_path. Not run against the live HackMD API.

Left out: the capture-and-persist pair is still written out in pull and adopt, and the sync lock is held across the POST and read-back on purpose, so two publishes of one file cannot both win.


Summary by cubic

hackmd_create_note now accepts an absolute local_path to a .md file in place of content. The server reads the file, creates the note, polls until it reads back with exactly that body, and then tracks the file the way hackmd_pull_note does.

  • The reply carries tracking.status (tracked, or not_tracked with a reason) and the summary says which; a tracking failure is never an error after the POST, since an error would invite a duplicate create.
  • Publishing requires a workspace root set in the server's own environment and an explicit read_permission; a file over the large-file warning size needs confirm_large_file: true.
  • Already-tracked files, non-.md paths, and local_path together with content are refused before any request.
  • The path is canonicalized and re-checked after the network calls, so a symlink swap leaves the file untracked; the sync lock is held across the POST and read-back so two publishes of one file cannot both win.
  • Tests cover every error kind, a missing file, and an unresolvable path; an already-tracked file maps to a conflict, and create_note itself refuses a local_path as an internal error.