Skip to content

Publish a local file with hackmd_create_note - #40

Merged
jserv merged 1 commit into
mainfrom
dev
Nov 2, 2026
Merged

jserv merged 1 commit into
mainfrom
dev

Conversation

@jserv

@jserv jserv commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

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.

Written for commit c2ac251. Summary will update on new commits.

View guided diff Turn on auto-fix

cubic-dev-ai[bot]

This comment was marked as resolved.

hackmd_create_note now accepts 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. It creates the note, polls until the
note reads back with exactly that body, then tracks the file the way
hackmd_pull_note does. The reply summary says whether the file was
tracked, and tracking.status carries 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
checked before the POST and again before the record is written, so a
symlink swapped in during the network calls leaves the file untracked.

Refused before any request: a file that already has a sync record, a
non-.md path, and local_path together with content. A file over the
large-file warning size needs confirm_large_file: true. A
LocalPathNotHandled error is the server's own mistake and is reported
as an Internal error.

The sync lock is held across the POST and read-back on purpose, so two
publishes of one file cannot both win. Not run against the live API.
@jserv
jserv merged commit 9679aa2 into main Nov 2, 2026
12 checks passed
@jserv
jserv deleted the dev branch November 2, 2026 07:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant