···296 root.AddCommand(patchCmd)
297298 pushCmd := &cobra.Command{
299- Use: "push [note-ids...]",
300 Short: "Create or update multiple documents on leaflet",
301 Long: `Batch publish or update multiple local notes to leaflet.pub.
302···307This is useful for bulk operations and continuous publishing workflows.
308309Examples:
310- noteleaf pub push 1 2 3 # Publish/update notes 1, 2, and 3
311- noteleaf pub push 42 99 --draft # Create/update as drafts`,
312- Args: cobra.MinimumNArgs(1),
000313 RunE: func(cmd *cobra.Command, args []string) error {
00000000000000314 noteIDs := make([]int64, len(args))
315 for i, arg := range args {
316 id, err := parseNoteID(arg)
···320 noteIDs[i] = id
321 }
322323- isDraft, _ := cmd.Flags().GetBool("draft")
324-325- defer c.handler.Close()
326- return c.handler.Push(cmd.Context(), noteIDs, isDraft)
327 },
328 }
329 pushCmd.Flags().Bool("draft", false, "Create/update as drafts instead of publishing")
00330 root.AddCommand(pushCmd)
331-332 return root
333}
334
···296 root.AddCommand(patchCmd)
297298 pushCmd := &cobra.Command{
299+ Use: "push [note-ids...] [--file files...]",
300 Short: "Create or update multiple documents on leaflet",
301 Long: `Batch publish or update multiple local notes to leaflet.pub.
302···307This is useful for bulk operations and continuous publishing workflows.
308309Examples:
310+ noteleaf pub push 1 2 3 # Publish/update notes 1, 2, and 3
311+ noteleaf pub push 42 99 --draft # Create/update as drafts
312+ noteleaf pub push --file article.md # Create note from file and push
313+ noteleaf pub push --file a.md b.md --draft # Create notes from multiple files
314+ noteleaf pub push 1 2 --dry-run # Validate without pushing
315+ noteleaf pub push --file article.md --dry-run # Create note but don't push`,
316 RunE: func(cmd *cobra.Command, args []string) error {
317+ isDraft, _ := cmd.Flags().GetBool("draft")
318+ dryRun, _ := cmd.Flags().GetBool("dry-run")
319+ files, _ := cmd.Flags().GetStringSlice("file")
320+321+ defer c.handler.Close()
322+323+ if len(files) > 0 {
324+ return c.handler.PushFromFiles(cmd.Context(), files, isDraft, dryRun)
325+ }
326+327+ if len(args) == 0 {
328+ return fmt.Errorf("no note IDs or files provided")
329+ }
330+331 noteIDs := make([]int64, len(args))
332 for i, arg := range args {
333 id, err := parseNoteID(arg)
···337 noteIDs[i] = id
338 }
339340+ return c.handler.Push(cmd.Context(), noteIDs, isDraft, dryRun)
000341 },
342 }
343 pushCmd.Flags().Bool("draft", false, "Create/update as drafts instead of publishing")
344+ pushCmd.Flags().Bool("dry-run", false, "Create note records but skip leaflet push")
345+ pushCmd.Flags().StringSliceP("file", "f", []string{}, "Create notes from markdown files before pushing")
346 root.AddCommand(pushCmd)
0347 return root
348}
349
+33-2
internal/docs/ROADMAP.md
···45## Core Usability
67-The foundation across all domains is implemented. Tasks support CRUD operations, projects, tags, contexts, and time tracking. Notes have create, list, read, edit, and remove commands with interactive and static modes. Media queues exist for books, movies, and TV with progress and status management. SQLite persistence is in place with setup, seed, and reset commands. TUIs and colorized output are available.
089## RC
10···43#### Publication
4445- [x] Implement authentication with BlueSky/leaflet (AT Protocol).
46- - [ ] Add OAuth2
47- [x] Verify `pub pull` fetches and syncs documents from leaflet.
48- [x] Confirm `pub list` with status filtering (`all`, `published`, `draft`).
49- [ ] Test `pub post` creates new documents with draft/preview/validate modes.
···205- [ ] Enhanced parsing coverage
206- [ ] Export to multiple formats
207- [ ] Linking with tasks and notes
000000000000000000000000000000208209### User Experience
210
···45## Core Usability
67+The foundation across all domains is implemented. Tasks support CRUD operations, projects, tags, contexts, and time tracking.
8+Notes have create, list, read, edit, and remove commands with interactive and static modes. Media queues exist for books, movies, and TV with progress and status management. SQLite persistence is in place with setup, seed, and reset commands. TUIs and colorized output are available.
910## RC
11···44#### Publication
4546- [x] Implement authentication with BlueSky/leaflet (AT Protocol).
47+ - [ ] Add [OAuth2](#publications--authentication)
48- [x] Verify `pub pull` fetches and syncs documents from leaflet.
49- [x] Confirm `pub list` with status filtering (`all`, `published`, `draft`).
50- [ ] Test `pub post` creates new documents with draft/preview/validate modes.
···206- [ ] Enhanced parsing coverage
207- [ ] Export to multiple formats
208- [ ] Linking with tasks and notes
209+210+### Publications & Authentication
211+212+- [ ] OAuth2 authentication for AT Protocol
213+ - [ ] Client metadata server for publishing application details
214+ - [ ] DPoP (Demonstrating Proof of Possession) implementation
215+ - [ ] ES256 JWT generation with unique JTI nonces
216+ - [ ] Server-issued nonce management with 5-minute rotation
217+ - [ ] Separate nonce tracking for authorization and resource servers
218+ - [ ] PAR (Pushed Authorization Requests) flow
219+ - [ ] PKCE code challenge generation
220+ - [ ] State token management
221+ - [ ] Request URI handling
222+ - [ ] Identity resolution and verification
223+ - [ ] Bidirectional handle verification
224+ - [ ] DID resolution from handles
225+ - [ ] Authorization server discovery via .well-known endpoints
226+ - [ ] Token lifecycle management
227+ - [ ] Access token refresh (5-15 min lifetime recommended)
228+ - [ ] Refresh token rotation (180 day max for confidential clients)
229+ - [ ] Concurrent request handling to prevent duplicate refreshes
230+ - [ ] Secure token storage (encrypted at rest)
231+ - [ ] Local callback server for OAuth redirects
232+ - [ ] Ephemeral HTTP server on localhost
233+ - [ ] Browser launch integration
234+ - [ ] Timeout handling for abandoned flows
235+ - [ ] Migration path from app passwords to OAuth
236+ - [ ] Detect existing app password sessions
237+ - [ ] Prompt users to upgrade authentication
238+ - [ ] Maintain backward compatibility
239240### User Experience
241